output_spec.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. var should = require('should'),
  2. needle = require('./../'),
  3. http = require('http'),
  4. sinon = require('sinon'),
  5. stream = require('stream'),
  6. fs = require('fs'),
  7. port = 11111,
  8. server;
  9. describe('with output option', function() {
  10. var server, handler, file = '/tmp/foobar.out';
  11. function send_request_cb(where, cb) {
  12. var url = 'http://localhost:' + port + '/whatever.file';
  13. return needle.get(url, { output: where }, cb);
  14. }
  15. function send_request_stream(where, cb) {
  16. var url = 'http://localhost:' + port + '/whatever.file';
  17. var stream = needle.get(url, { output: where });
  18. stream.on('end', cb);
  19. }
  20. // this will only work in UNICES
  21. function get_open_file_descriptors() {
  22. var list = fs.readdirSync('/proc/self/fd');
  23. return list.length;
  24. }
  25. var send_request = send_request_cb;
  26. before(function(){
  27. server = http.createServer(function(req, res) {
  28. handler(req, res);
  29. }).listen(port);
  30. });
  31. after(function() {
  32. server.close();
  33. })
  34. beforeEach(function() {
  35. try { fs.unlinkSync(file) } catch(e) { };
  36. })
  37. describe('and a 404 response', function() {
  38. before(function() {
  39. handler = function(req, res) {
  40. res.writeHead(404, {'Content-Type': 'text/plain' });
  41. res.end();
  42. }
  43. })
  44. it('doesnt attempt to write a file', function(done) {
  45. var spy = sinon.spy(fs, 'createWriteStream');
  46. send_request(file, function(err, resp) {
  47. resp.statusCode.should.eql(404);
  48. spy.called.should.eql(false);
  49. spy.restore();
  50. done();
  51. })
  52. })
  53. it('doesnt actually write a file', function(done) {
  54. send_request(file, function(err, resp) {
  55. resp.statusCode.should.eql(404);
  56. fs.existsSync(file).should.eql(false);
  57. done();
  58. })
  59. })
  60. })
  61. describe('and a 200 response', function() {
  62. describe('for an empty response', function() {
  63. before(function() {
  64. handler = function(req, res) {
  65. res.writeHead(200, { 'Content-Type': 'text/plain' });
  66. res.end();
  67. }
  68. })
  69. it('uses a writableStream', function(done) {
  70. var spy = sinon.spy(fs, 'createWriteStream');
  71. send_request(file, function(err, resp) {
  72. resp.statusCode.should.eql(200);
  73. spy.called.should.eql(true);
  74. spy.restore();
  75. done();
  76. })
  77. })
  78. it('writes a file', function(done) {
  79. fs.existsSync(file).should.eql(false);
  80. send_request(file, function(err, resp) {
  81. fs.existsSync(file).should.eql(true);
  82. done();
  83. })
  84. })
  85. it('file is zero bytes in length', function(done) {
  86. send_request(file, function(err, resp) {
  87. fs.statSync(file).size.should.equal(0);
  88. done();
  89. })
  90. })
  91. if (process.platform != 'win32') {
  92. it('closes the file descriptor', function(done) {
  93. var open_descriptors = get_open_file_descriptors();
  94. send_request(file + Math.random(), function(err, resp) {
  95. var current_descriptors = get_open_file_descriptors();
  96. open_descriptors.should.eql(current_descriptors);
  97. done()
  98. })
  99. })
  100. }
  101. })
  102. describe('for a JSON response', function() {
  103. before(function() {
  104. handler = function(req, res) {
  105. res.writeHead(200, { 'Content-Type': 'application/javascript' });
  106. res.end(JSON.stringify({foo: 'bar'}));
  107. }
  108. })
  109. it('uses a writableStream', function(done) {
  110. var spy = sinon.spy(fs, 'createWriteStream');
  111. send_request(file, function(err, resp) {
  112. resp.statusCode.should.eql(200);
  113. spy.called.should.eql(true);
  114. spy.restore();
  115. done();
  116. })
  117. })
  118. it('writes a file', function(done) {
  119. fs.existsSync(file).should.eql(false);
  120. send_request(file, function(err, resp) {
  121. fs.existsSync(file).should.eql(true);
  122. done();
  123. })
  124. })
  125. it('file size equals response length', function(done) {
  126. send_request(file, function(err, resp) {
  127. fs.statSync(file).size.should.equal(resp.bytes);
  128. done();
  129. })
  130. })
  131. it('response pipeline is honoured (JSON is decoded by default)', function(done) {
  132. send_request_stream(file, function(err, resp) {
  133. // we need to wait a bit since writing to config.output
  134. // happens independently of needle's callback logic.
  135. setTimeout(function() {
  136. fs.readFileSync(file).toString().should.eql('{\"foo\":\"bar\"}');
  137. done();
  138. }, 20);
  139. })
  140. })
  141. it('closes the file descriptor', function(done) {
  142. var open_descriptors = get_open_file_descriptors();
  143. send_request(file + Math.random(), function(err, resp) {
  144. var current_descriptors = get_open_file_descriptors();
  145. open_descriptors.should.eql(current_descriptors);
  146. done()
  147. })
  148. })
  149. })
  150. describe('for a binary file', function() {
  151. var pixel = Buffer.from("base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs", "base64");
  152. before(function() {
  153. handler = function(req, res) {
  154. res.writeHead(200, { 'Content-Type': 'application/octet-stream', 'Transfer-Encoding': 'chunked' });
  155. res.write(pixel.slice(0, 10));
  156. res.write(pixel.slice(10, 20));
  157. res.write(pixel.slice(20, 30));
  158. res.write(pixel.slice(30));
  159. res.end();
  160. }
  161. })
  162. it('uses a writableStream', function(done) {
  163. var spy = sinon.spy(fs, 'createWriteStream');
  164. send_request(file, function(err, resp) {
  165. resp.statusCode.should.eql(200);
  166. spy.called.should.eql(true);
  167. spy.restore();
  168. done();
  169. })
  170. })
  171. it('writes a file', function(done) {
  172. fs.existsSync(file).should.eql(false);
  173. send_request(file, function(err, resp) {
  174. fs.existsSync(file).should.eql(true);
  175. done();
  176. })
  177. })
  178. it('file size equals response length', function(done) {
  179. send_request(file, function(err, resp) {
  180. fs.statSync(file).size.should.equal(resp.bytes);
  181. done();
  182. })
  183. })
  184. it('file is equal to original buffer', function(done) {
  185. send_request(file, function(err, resp) {
  186. // we need to wait a bit since writing to config.output
  187. // happens independently of needle's callback logic.
  188. setTimeout(function() {
  189. fs.readFileSync(file).should.eql(pixel);
  190. done();
  191. }, 20);
  192. })
  193. })
  194. it('returns the data in resp.body too', function(done) {
  195. send_request(file, function(err, resp) {
  196. resp.body.should.eql(pixel);
  197. done();
  198. })
  199. })
  200. if (process.platform != 'win32') {
  201. it('closes the file descriptor', function(done) {
  202. var open_descriptors = get_open_file_descriptors();
  203. send_request(file + Math.random(), function(err, resp) {
  204. var current_descriptors = get_open_file_descriptors();
  205. open_descriptors.should.eql(current_descriptors);
  206. done()
  207. })
  208. })
  209. }
  210. })
  211. })
  212. })