output_spec.js 7.4 KB

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