test.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. 'use strict';
  2. var expect = require('expect.js');
  3. var EventEmitter = require('events').EventEmitter;
  4. var progress = require('../');
  5. function normalizeStates(states) {
  6. states.forEach(function (state) {
  7. state.time.elapsed = Math.round(state.time.elapsed),
  8. state.time.remaining = state.time.remaining != null ? Math.round(state.time.remaining) : null;
  9. state.speed = state.speed != null ? Math.round(state.speed) : null;
  10. });
  11. }
  12. describe('request-progress', function () {
  13. var request;
  14. var states;
  15. var response;
  16. beforeEach(function () {
  17. states = [];
  18. request = new EventEmitter();
  19. response = new EventEmitter();
  20. request.on('progress', function (state) {
  21. states.push(JSON.parse(JSON.stringify(state)));
  22. });
  23. });
  24. it('should emit the progress event with the correct state information', function (done) {
  25. progress(request, { throttle: 0 })
  26. .on('end', function () {
  27. normalizeStates(states);
  28. expect(states).to.eql([{
  29. percent: 0.5,
  30. speed: null,
  31. size: { total: 10, transferred: 5, },
  32. time: { elapsed: 0, remaining: null }
  33. }, {
  34. percent: 0.8,
  35. speed: 7,
  36. size: { total: 10, transferred: 8 },
  37. time: { elapsed: 1, remaining: 0 }
  38. }, {
  39. percent: 1,
  40. speed: 8,
  41. size: { total: 10, transferred: 10 },
  42. time: { elapsed: 1, remaining: 0 }
  43. }]);
  44. done();
  45. });
  46. request.emit('request');
  47. request.emit('response', Object.assign(response, { headers: { 'content-length': 10 } }));
  48. setTimeout(function () {
  49. response.emit('data', new Buffer('aaaaa'));
  50. }, 25);
  51. setTimeout(function () {
  52. response.emit('data', new Buffer('bbb'));
  53. }, 1150);
  54. setTimeout(function () {
  55. response.emit('data', new Buffer('cc'));
  56. request.emit('end');
  57. }, 1250);
  58. });
  59. it('should provide request.progressState (and request.progressContext)', function (done) {
  60. progress(request, { throttle: 0 })
  61. .on('end', function () {
  62. expect(request.progressState).to.be(null);
  63. expect(request.progressContext).to.be(null);
  64. done();
  65. });
  66. expect(request.progressContext).to.be.an('object');
  67. expect(request.progressState).to.be(undefined);
  68. request.emit('request');
  69. request.emit('response', Object.assign(response, { headers: { 'content-length': 2 } }));
  70. expect(request.progressContext).to.be.an('object');
  71. expect(request.progressState).to.be.an('object');
  72. setTimeout(function () {
  73. response.emit('data', new Buffer('a'));
  74. expect(request.progressContext).to.be.an('object');
  75. expect(request.progressState).to.be.an('object');
  76. expect(request.progressState.percent).to.be(0.5);
  77. }, 25);
  78. setTimeout(function () {
  79. response.emit('data', new Buffer('b'));
  80. expect(request.progressContext).to.be.an('object');
  81. expect(request.progressState).to.be.an('object');
  82. expect(request.progressState.percent).to.be(1);
  83. request.emit('end');
  84. }, 100);
  85. });
  86. it('should have a option.delay default of 0', function () {
  87. progress(request);
  88. expect(request.progressContext.options.delay).to.be(0);
  89. });
  90. it('should respect the passed option.delay', function (done) {
  91. progress(request, { throttle: 0, delay: 250 })
  92. .on('end', function () {
  93. expect(states).to.have.length(2);
  94. expect(states[0].percent).to.be(0.6);
  95. expect(states[1].percent).to.be(1);
  96. done();
  97. });
  98. request.emit('request');
  99. request.emit('response', Object.assign(response, { headers: { 'content-length': 10 } }));
  100. setTimeout(function () {
  101. response.emit('data', new Buffer('aa'));
  102. }, 25);
  103. setTimeout(function () {
  104. response.emit('data', new Buffer('bb'));
  105. }, 200);
  106. setTimeout(function () {
  107. response.emit('data', new Buffer('cc'));
  108. }, 300);
  109. setTimeout(function () {
  110. response.emit('data', new Buffer('dddd'));
  111. request.emit('end');
  112. }, 400);
  113. });
  114. it('should have a option.throttle default of 1000', function () {
  115. progress(request);
  116. expect(request.progressContext.options.throttle).to.be(1000);
  117. });
  118. it('should respect the passed option.throttle', function (done) {
  119. progress(request, { throttle: 300, delay: 0 })
  120. .on('end', function () {
  121. expect(states).to.have.length(3);
  122. expect(states[0].percent).to.be(0.2);
  123. expect(states[1].percent).to.be(0.6);
  124. expect(states[2].percent).to.be(0.9);
  125. done();
  126. });
  127. request.emit('request');
  128. request.emit('response', Object.assign(response, { headers: { 'content-length': 10 } }));
  129. setTimeout(function () {
  130. response.emit('data', new Buffer('aa'));
  131. }, 25);
  132. setTimeout(function () {
  133. response.emit('data', new Buffer('bb'));
  134. }, 100);
  135. setTimeout(function () {
  136. response.emit('data', new Buffer('cc'));
  137. }, 300);
  138. setTimeout(function () {
  139. response.emit('data', new Buffer('dd'));
  140. }, 400);
  141. setTimeout(function () {
  142. response.emit('data', new Buffer('e'));
  143. }, 500);
  144. setTimeout(function () {
  145. response.emit('data', new Buffer('bf'));
  146. request.emit('end');
  147. }, 700);
  148. });
  149. it('should have a option.lengthHeader default of "content-length"', function () {
  150. progress(request);
  151. expect(request.progressContext.options.lengthHeader).to.be('content-length');
  152. });
  153. it('should use option.lengthHeader', function (done) {
  154. progress(request, {
  155. throttle: 0,
  156. lengthHeader: 'x-transfer-length'
  157. })
  158. .on('end', function () {
  159. expect(states).to.have.length(2);
  160. expect(states[0].percent).to.be(0.5);
  161. expect(states[0].size.total).to.be(10);
  162. expect(states[1].percent).to.be(1);
  163. expect(states[1].size.total).to.be(10);
  164. done();
  165. });
  166. request.emit('request');
  167. request.emit('response', Object.assign(response, {
  168. headers: { 'x-transfer-length': 10, 'content-length': 5 }
  169. }));
  170. setTimeout(function () {
  171. response.emit('data', new Buffer('aaaaa'));
  172. }, 25);
  173. setTimeout(function () {
  174. response.emit('data', new Buffer('bbbbb'));
  175. request.emit('end');
  176. }, 200);
  177. });
  178. it('should fail if response is already set', function () {
  179. request.response = { headers: { 'content-length': 10 } };
  180. expect(function () {
  181. progress(request);
  182. }).to.throwException(/too late/);
  183. });
  184. it('should deal with unknown content length', function (done) {
  185. progress(request, { throttle: 0 })
  186. .on('end', function () {
  187. normalizeStates(states);
  188. expect(states).to.eql([{
  189. percent: null,
  190. speed: null,
  191. size: { total: null, transferred: 5, },
  192. time: { elapsed: 0, remaining: null }
  193. }, {
  194. percent: null,
  195. speed: 10,
  196. size: { total: null, transferred: 12, },
  197. time: { elapsed: 1, remaining: null }
  198. }]);
  199. done();
  200. });
  201. request.emit('request');
  202. request.emit('response', Object.assign(response, { headers: {} }));
  203. setTimeout(function () {
  204. response.emit('data', new Buffer('aaaaa'));
  205. }, 25);
  206. setTimeout(function () {
  207. response.emit('data', new Buffer('bbbbbbb'));
  208. request.emit('end');
  209. }, 1150);
  210. });
  211. it('should deal with payloads higher than the content length', function (done) {
  212. progress(request, { throttle: 0 })
  213. .on('end', function () {
  214. normalizeStates(states);
  215. expect(states).to.eql([{
  216. percent: 0.5,
  217. speed: null,
  218. size: { total: 10, transferred: 5, },
  219. time: { elapsed: 0, remaining: null }
  220. }, {
  221. percent: 1,
  222. speed: 10,
  223. size: { total: 10, transferred: 12 },
  224. time: { elapsed: 1, remaining: 0 }
  225. }]);
  226. done();
  227. });
  228. request.emit('request');
  229. request.emit('response', Object.assign(response, { headers: { 'content-length': 10 } }));
  230. setTimeout(function () {
  231. response.emit('data', new Buffer('aaaaa'));
  232. }, 25);
  233. setTimeout(function () {
  234. response.emit('data', new Buffer('bbbbbbb'));
  235. request.emit('end');
  236. }, 1150);
  237. });
  238. it('should not report after the request ends', function (done) {
  239. progress(request, { throttle: 100 });
  240. request.emit('request');
  241. request.emit('response', Object.assign(response, { headers: { 'content-length': 10 } }));
  242. setTimeout(function () {
  243. response.emit('data', new Buffer('aa'));
  244. }, 25);
  245. setTimeout(function () {
  246. response.emit('data', new Buffer('bbbbbbbb'));
  247. request.emit('end');
  248. }, 50);
  249. setTimeout(function () {
  250. normalizeStates(states);
  251. expect(states).to.have.length(1);
  252. expect(states[0].percent).to.be(0.2);
  253. done();
  254. }, 500);
  255. });
  256. it('should not generate duplicate progress events if called twice', function (done) {
  257. progress(request, { throttle: 0 });
  258. progress(request, { throttle: 0 })
  259. .on('end', function () {
  260. expect(states).to.have.length(1);
  261. expect(states[0].percent).to.be(1);
  262. done();
  263. });
  264. request.emit('request');
  265. request.emit('response', Object.assign(response, { headers: { 'content-length': 2 } }));
  266. setTimeout(function () {
  267. response.emit('data', new Buffer('aa'));
  268. request.emit('end');
  269. }, 25);
  270. });
  271. it('should reset stuff on "request" event', function () {
  272. progress(request, { throttle: 0 });
  273. expect(request.progressContext).to.be.an('object');
  274. expect(request.progressState).to.be(undefined);
  275. request.emit('request');
  276. request.emit('response', Object.assign(response, { headers: { 'content-length': 2 } }));
  277. expect(request.progressContext).to.be.an('object');
  278. expect(request.progressState).to.be.an('object');
  279. request.emit('request');
  280. expect(request.progressContext).to.be.an('object');
  281. expect(request.progressState).to.be(null);
  282. });
  283. it('should hook into "data" event from the response and not the request', function (done) {
  284. // See: https://github.com/IndigoUnited/node-request-progress/issues/20
  285. progress(request, { throttle: 0 })
  286. .on('end', function () {
  287. expect(states).to.have.length(2);
  288. expect(states[0].percent).to.be(0.5);
  289. expect(states[1].percent).to.be(1);
  290. done();
  291. });
  292. request.emit('request');
  293. request.emit('response', Object.assign(response, { headers: { 'content-length': 4 } }));
  294. setTimeout(function () {
  295. response.emit('data', new Buffer('aa'));
  296. }, 25);
  297. setTimeout(function () {
  298. request.emit('data', new Buffer('aa'));
  299. }, 50);
  300. setTimeout(function () {
  301. response.emit('data', new Buffer('aa'));
  302. request.emit('end');
  303. }, 100);
  304. });
  305. });