UNPKG

31.8 kBJavaScriptView Raw
1var chai = require('chai'),
2 expect = chai.expect,
3 sinon = require('sinon'),
4 sinonChai = require('sinon-chai'),
5 nock = require('nock'),
6 rewire = require('rewire'),
7 path = require('path'),
8 Amperize = rewire('../lib/amperize'),
9 amperize;
10
11chai.use(sinonChai);
12chai.config.includeStack = true;
13
14describe('Amperize', function () {
15 beforeEach(function () {
16 amperize = new Amperize();
17 });
18
19 afterEach(function () {
20 amperize = undefined;
21 nock.cleanAll();
22 sinon.restore();
23 });
24
25 describe('is a module', function () {
26 it('which has a constructor', function () {
27 expect(Amperize).to.be.a('function');
28 });
29
30 it('which has default options', function () {
31 expect(amperize).to.have.property('config');
32 expect(amperize.config).to.be.eql({
33 'amp-img': {
34 layout: 'responsive',
35 width: 600,
36 height: 400
37 },
38 'amp-anim': {
39 layout: 'responsive',
40 width: 600,
41 height: 400
42 },
43 'amp-iframe': {
44 layout: 'responsive',
45 width: 600,
46 height: 400,
47 sandbox: 'allow-scripts allow-same-origin'
48 },
49 'amp-youtube': {
50 layout: 'responsive',
51 width: 600,
52 height: 400
53 },
54 'request_timeout': 3000
55 });
56 });
57
58 it('which can be configured', function () {
59 var configurable = new Amperize({some: 'options'});
60 expect(configurable).to.have.property('config');
61 expect(configurable.config.some).to.be.equal('options');
62 });
63
64 it('which has htmlParser', function () {
65 expect(amperize).to.have.property('htmlParser');
66 expect(amperize.htmlParser).to.be.a('object');
67 });
68
69 it('which has #parse', function () {
70 expect(amperize).to.have.property('parse');
71 expect(amperize.parse).to.be.a('function');
72 });
73
74 it('which has #amperizer', function () {
75 expect(amperize).to.have.property('amperizer');
76 expect(amperize.amperizer).to.be.a('function');
77 });
78 });
79
80 describe('#parse', function () {
81 var resetProbeImageSize,
82 imageSizeMock,
83 probeImageSizeStub;
84
85 beforeEach(function () {
86 // reset rewire so tests are independent
87 if (resetProbeImageSize) {
88 resetProbeImageSize();
89 }
90 // stubbing the `probe-probe-image-size` lib, so we don't make a request everytime
91 probeImageSizeStub = sinon.stub();
92 });
93
94 it('throws an error if no callback provided', function () {
95 function err() {
96 amperize.parse('', null);
97 }
98
99 expect(err).throws('No callback provided');
100 });
101
102 it('transforms small <img> into <amp-img></amp-img> with full image dimensions and fixed layout', function (done) {
103 imageSizeMock = nock('http://static.wixstatic.com')
104 .get('/media/355241_d31358572a2542c5a44738ddcb59e7ea.jpg_256')
105 .reply(200, {
106 body: '<Buffer 2c be a4 40 f7 87 73 1e 57 2c c1 e4 0d 79 03 95 42 f0 42 2e 41 95 27 c9 5c 35 a7 71 2c 09 5a 57 d3 04 1e 83 03 28 07 96 b0 c8 88 65 07 7a d1 d6 63 50>'
107 });
108
109 probeImageSizeStub.returns(Promise.resolve({width: 50, height: 50, type: 'jpg'}));
110 resetProbeImageSize = Amperize.__set__('probeImageSize', probeImageSizeStub);
111
112 amperize.parse('<img src="http://static.wixstatic.com/media/355241_d31358572a2542c5a44738ddcb59e7ea.jpg_256">', function (error, result) {
113 expect(result).to.exist;
114 expect(result).to.contain('<amp-img');
115 expect(result).to.contain('src="http://static.wixstatic.com/media/355241_d31358572a2542c5a44738ddcb59e7ea.jpg_256"');
116 expect(result).to.contain('layout="fixed"');
117 expect(result).to.contain('width="50"');
118 expect(result).to.contain('height="50"');
119 expect(result).to.contain('</amp-img>');
120 done();
121 });
122 });
123
124 it('transforms big <img> into <amp-img></amp-img> with full image dimensions and responsive layout', function (done) {
125 imageSizeMock = nock('http://static.wixstatic.com')
126 .get('/media/355241_d31358572a2542c5a44738ddcb59e7ea.jpg_256')
127 .reply(200, {
128 body: '<Buffer 2c be a4 40 f7 87 73 1e 57 2c c1 e4 0d 79 03 95 42 f0 42 2e 41 95 27 c9 5c 35 a7 71 2c 09 5a 57 d3 04 1e 83 03 28 07 96 b0 c8 88 65 07 7a d1 d6 63 50>'
129 });
130
131 probeImageSizeStub.returns(Promise.resolve({width: 350, height: 200, type: 'jpg'}));
132 resetProbeImageSize = Amperize.__set__('probeImageSize', probeImageSizeStub);
133
134 amperize.parse('<img src="http://static.wixstatic.com/media/355241_d31358572a2542c5a44738ddcb59e7ea.jpg_256">', function (error, result) {
135 expect(result).to.exist;
136 expect(result).to.contain('<amp-img');
137 expect(result).to.contain('src="http://static.wixstatic.com/media/355241_d31358572a2542c5a44738ddcb59e7ea.jpg_256"');
138 expect(result).to.contain('layout="responsive"');
139 expect(result).to.contain('width="350"');
140 expect(result).to.contain('height="200"');
141 expect(result).to.contain('</amp-img>');
142 done();
143 });
144 });
145
146 it('transforms <img> into <amp-img></amp-img> when width and height is set and overwrites it', function (done) {
147 imageSizeMock = nock('http://somestockwebsite.com')
148 .get('/image.jpg')
149 .reply(200, {
150 body: '<Buffer 2c be a4 40 f7 87 73 1e 57 2c c1 e4 0d 79 03 95 42 f0 42 2e 41 95 27 c9 5c 35 a7 71 2c 09 5a 57 d3 04 1e 83 03 28 07 96 b0 c8 88 65 07 7a d1 d6 63 50>'
151 });
152
153 probeImageSizeStub.returns(Promise.resolve({width: 350, height: 200, type: 'jpg'}));
154 resetProbeImageSize = Amperize.__set__('probeImageSize', probeImageSizeStub);
155
156 amperize.parse('<img src="http://somestockwebsite.com/image.jpg" width="100" height="50">', function (error, result) {
157 expect(result).to.exist;
158 expect(result).to.contain('<amp-img');
159 expect(result).to.contain('src="http://somestockwebsite.com/image.jpg"');
160 expect(result).to.contain('layout="responsive"');
161 expect(result).to.contain('width="350"');
162 expect(result).to.contain('height="200"');
163 expect(result).to.contain('</amp-img>');
164 done();
165 });
166 });
167
168 it('transforms <img> into <amp-img></amp-img> does not overwrite layout attribute', function (done) {
169 imageSizeMock = nock('http://somestockwebsite.com')
170 .get('/image.jpg')
171 .reply(200, {
172 body: '<Buffer 2c be a4 40 f7 87 73 1e 57 2c c1 e4 0d 79 03 95 42 f0 42 2e 41 95 27 c9 5c 35 a7 71 2c 09 5a 57 d3 04 1e 83 03 28 07 96 b0 c8 88 65 07 7a d1 d6 63 50>'
173 });
174
175 probeImageSizeStub.returns(Promise.resolve({width: 350, height: 200, type: 'jpg'}));
176 resetProbeImageSize = Amperize.__set__('probeImageSize', probeImageSizeStub);
177
178 amperize.parse('<img src="http://somestockwebsite.com/image.jpg" layout="fixed">', function (error, result) {
179 expect(result).to.exist;
180 expect(result).to.contain('<amp-img');
181 expect(result).to.contain('src="http://somestockwebsite.com/image.jpg"');
182 expect(result).to.contain('layout="fixed"');
183 expect(result).to.contain('width="350"');
184 expect(result).to.contain('height="200"');
185 expect(result).to.contain('</amp-img>');
186 done();
187 });
188 });
189
190 it('transforms <img> into <amp-img> when no file extension is given', function (done) {
191 // This test is mocked, but works with this specific example.
192 // You can comment out the mocks and the test should still pass.
193 imageSizeMock = nock('https://www.zomato.com')
194 .matchHeader('User-Agent', /Mozilla\/.*Safari\/.*/)
195 .get('/logo/18163505/minilogo')
196 .reply(200, {
197 body: '<Buffer 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 00 68 00 00 00 0f 08 02 00 00 00 87 8f 1d 14 00 00 03 33 49 44 41 54 58 c3 ed 97 6b 48 93 51 18>'
198 });
199
200 probeImageSizeStub.returns(Promise.resolve({width: 104, height: 15, type: 'png'}));
201 resetProbeImageSize = Amperize.__set__('probeImageSize', probeImageSizeStub);
202
203 amperize.parse('<img src="https://www.zomato.com/logo/18163505/minilogo">', function (error, result) {
204 expect(result).to.exist;
205 expect(result).to.contain('<amp-img');
206 expect(result).to.contain('src="https://www.zomato.com/logo/18163505/minilogo"');
207 expect(result).to.contain('layout="fixed"');
208 expect(result).to.contain('width="104"');
209 expect(result).to.contain('height="15"');
210 expect(result).to.contain('</amp-img>');
211 done();
212 });
213 });
214
215 it('falls back to image-size for unprobable images', function (done) {
216 imageSizeMock = nock('https://somewebsite.com')
217 .get('/favicon.ico')
218 .replyWithFile(200, path.join(__dirname, 'fixtures/multi-size.ico'));
219
220 amperize.parse('<img src="https://somewebsite.com/favicon.ico">', function (error, result) {
221 expect(result).to.exist;
222 expect(result).to.contain('<amp-img');
223 expect(result).to.contain('src="https://somewebsite.com/favicon.ico"');
224 expect(result).to.contain('layout="fixed"');
225 expect(result).to.contain('width="256"');
226 expect(result).to.contain('height="256"');
227 expect(result).to.contain('</amp-img>');
228 done();
229 });
230 });
231
232 it('falls back to image-size for unprobable images (uppercase extension)', function (done) {
233 imageSizeMock = nock('https://somewebsite.com')
234 .get('/favicon.ICO')
235 .replyWithFile(200, path.join(__dirname, 'fixtures/multi-size.ico'));
236
237 amperize.parse('<img src="https://somewebsite.com/favicon.ICO">', function (error, result) {
238 expect(result).to.exist;
239 expect(result).to.contain('<amp-img');
240 expect(result).to.contain('src="https://somewebsite.com/favicon.ICO"');
241 expect(result).to.contain('layout="fixed"');
242 expect(result).to.contain('width="256"');
243 expect(result).to.contain('height="256"');
244 expect(result).to.contain('</amp-img>');
245 done();
246 });
247 });
248
249 it('falls back to image-size for unprobable images (query param)', function (done) {
250 imageSizeMock = nock('https://somewebsite.com')
251 .get('/favicon.ICO?v=1')
252 .replyWithFile(200, path.join(__dirname, 'fixtures/multi-size.ico'));
253
254 amperize.parse('<img src="https://somewebsite.com/favicon.ICO?v=1">', function (error, result) {
255 expect(result).to.exist;
256 expect(result).to.contain('<amp-img');
257 expect(result).to.contain('src="https://somewebsite.com/favicon.ICO?v=1"');
258 expect(result).to.contain('layout="fixed"');
259 expect(result).to.contain('width="256"');
260 expect(result).to.contain('height="256"');
261 expect(result).to.contain('</amp-img>');
262 done();
263 });
264 });
265
266 it('returns largest image value for .ico files', function (done) {
267 imageSizeMock = nock('https://somewebsite.com')
268 .get('/favicon.ico')
269 .replyWithFile(200, path.join(__dirname, 'fixtures/multi-size.ico'));
270
271 probeImageSizeStub.returns(Promise.resolve({
272 width: 32,
273 height: 32,
274 type: 'ico',
275 images: [
276 {width: 48, height: 48},
277 {width: 32, height: 32},
278 {width: 16, height: 16}
279 ]
280 }));
281 resetProbeImageSize = Amperize.__set__('sizeOf', probeImageSizeStub);
282
283 amperize.parse('<img src="https://somewebsite.com/favicon.ico">', function (error, result) {
284 expect(result).to.exist;
285 expect(result).to.contain('<amp-img');
286 expect(result).to.contain('src="https://somewebsite.com/favicon.ico"');
287 expect(result).to.contain('layout="fixed"');
288 expect(result).to.contain('width="48"');
289 expect(result).to.contain('height="48"');
290 expect(result).to.contain('</amp-img>');
291 done();
292 });
293 });
294
295 // TODO: adapt code to not trigger parallel requests for the same image
296 it.skip('uses cached size rather than extra requests for duplicated images in html', function (done) {
297 var GIF1x1 = Buffer.from('R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==', 'base64');
298 var secondImageSizeMock;
299
300 imageSizeMock = nock('http://example.com')
301 .get('/image.jpg')
302 .reply(200, GIF1x1);
303
304 secondImageSizeMock = nock('http://example.com')
305 .get('/image.jpg')
306 .reply(200, GIF1x1);
307
308 amperize.parse('<img src="http://example.com/image.jpg"><img src="http://example.com/image.jpg">', function (error, result) {
309 expect(imageSizeMock.isDone()).to.equal(true);
310 expect(secondImageSizeMock.isDone()).to.equal(false);
311 expect(result).to.exist;
312 expect(result).to.match(/<amp-img\s.*<amp-img/);
313 done();
314 });
315 });
316
317 it('transforms .gif <img> with only height property into <amp-anim></amp-anim> with full dimensions by overriding them', function (done) {
318 imageSizeMock = nock('https://media.giphy.com')
319 .get('/media/l46CtzgjhTm29Cbjq/giphy.gif')
320 .reply(200, {
321 body: '<Buffer 2c be a4 40 f7 87 73 1e 57 2c c1 e4 0d 79 03 95 42 f0 42 2e 41 95 27 c9 5c 35 a7 71 2c 09 5a 57 d3 04 1e 83 03 28 07 96 b0 c8 88 65 07 7a d1 d6 63 50>'
322 });
323
324 probeImageSizeStub.returns(Promise.resolve({width: 800, height: 600, type: 'gif'}));
325 resetProbeImageSize = Amperize.__set__('probeImageSize', probeImageSizeStub);
326
327 amperize.parse('<img src="https://media.giphy.com/media/l46CtzgjhTm29Cbjq/giphy.gif" height="500">', function (error, result) {
328 expect(result).to.exist;
329 expect(result).to.contain('<amp-anim');
330 expect(result).to.contain('src="https://media.giphy.com/media/l46CtzgjhTm29Cbjq/giphy.gif"');
331 expect(result).to.contain('layout="responsive"');
332 expect(result).to.contain('width="800"');
333 expect(result).to.contain('height="600"');
334 expect(result).to.contain('</amp-anim>');
335 done();
336 });
337 });
338
339 it('transforms <iframe> with only width property into <amp-iframe></amp-iframe> with full dimensions without overriding them', function (done) {
340 amperize.parse('<iframe src="https://giphy.com/embed/3oEduKP4VaUxJvLwuA" width="400"></iframe>', function (error, result) {
341 expect(result).to.exist;
342 expect(result).to.contain('<amp-iframe');
343 expect(result).to.contain('src="https://giphy.com/embed/3oEduKP4VaUxJvLwuA"');
344 expect(result).to.contain('layout="responsive"');
345 expect(result).to.contain('width="400"');
346 expect(result).to.contain('height="400"');
347 expect(result).to.contain('</amp-iframe>');
348 expect(result).to.contain('sandbox="allow-scripts allow-same-origin"');
349 done();
350 });
351 });
352
353 it('transforms <iframe> with only height property into <amp-iframe></amp-iframe> with full dimensions without overriding them', function (done) {
354 amperize.parse('<iframe src="https://giphy.com/embed/3oEduKP4VaUxJvLwuA" height="400"></iframe>', function (error, result) {
355 expect(result).to.exist;
356 expect(result).to.contain('<amp-iframe');
357 expect(result).to.contain('src="https://giphy.com/embed/3oEduKP4VaUxJvLwuA"');
358 expect(result).to.contain('layout="responsive"');
359 expect(result).to.contain('width="600"');
360 expect(result).to.contain('height="400"');
361 expect(result).to.contain('</amp-iframe>');
362 expect(result).to.contain('sandbox="allow-scripts allow-same-origin"');
363 done();
364 });
365 });
366
367 it('transforms <iframe> with youtube URL to <amp-youtube></amp-youtube>', function (done) {
368 amperize.parse('<iframe src="https://www.youtube.com/embed/HMQkV5cTuoY" height="400"></iframe>', function (error, result) {
369 expect(result).to.exist;
370 expect(result).to.contain('<amp-youtube');
371 expect(result).to.contain('data-videoid="HMQkV5cTuoY"');
372 expect(result).to.contain('layout="responsive"');
373 expect(result).to.contain('width="600"');
374 expect(result).to.contain('height="400"');
375 expect(result).to.contain('</amp-youtube>');
376 done();
377 });
378 });
379
380 it('transforms <iframe> with youtube URL to <amp-youtube></amp-youtube> removing disallowed attributes', function (done) {
381 amperize.parse('<iframe src="https://www.youtube.com/embed/HMQkV5cTuoY" allowfullscreen frameborder="0" allow="" height="400"></iframe>', function (error, result) {
382 expect(result).to.exist;
383 expect(result).to.contain('<amp-youtube');
384 expect(result).to.contain('data-videoid="HMQkV5cTuoY"');
385 expect(result).to.contain('layout="responsive"');
386 expect(result).to.contain('width="600"');
387 expect(result).to.contain('height="400"');
388 expect(result).to.contain('</amp-youtube>');
389 expect(result).to.not.contain('allowfullscreen');
390 expect(result).to.not.contain('frameborder');
391 expect(result).to.not.contain('allow');
392 done();
393 });
394 });
395
396 it('transforms <iframe> with sandbox property into <amp-iframe></amp-iframe> with full dimensions without overriding them', function (done) {
397 amperize.parse('<iframe src="https://giphy.com/embed/3oEduKP4VaUxJvLwuA" sandbox="allow-scripts"></iframe>', function (error, result) {
398 expect(result).to.exist;
399 expect(result).to.contain('<amp-iframe');
400 expect(result).to.contain('src="https://giphy.com/embed/3oEduKP4VaUxJvLwuA"');
401 expect(result).to.contain('layout="responsive"');
402 expect(result).to.contain('width="600"');
403 expect(result).to.contain('height="400"');
404 expect(result).to.contain('</amp-iframe>');
405 expect(result).to.contain('sandbox="allow-scripts"');
406 done();
407 });
408 });
409
410 it('adds \'https\' protocol to <iframe> if no protocol is supplied (e. e. giphy)', function (done) {
411 var url = '<iframe src="//giphy.com/embed/3oEduKP4VaUxJvLwuA" width="480" height="372" frameBorder="0" class="giphy-embed" allowFullScreen></iframe>';
412 amperize.parse(url, function (error, result) {
413 expect(result).to.exist;
414 expect(result).to.contain('<amp-iframe');
415 expect(result).to.contain('src="https://giphy.com/embed/3oEduKP4VaUxJvLwuA"');
416 expect(result).to.contain('layout="responsive"');
417 expect(result).to.contain('width="480"');
418 expect(result).to.contain('height="372"');
419 expect(result).to.contain('</amp-iframe>');
420 expect(result).to.contain('sandbox="allow-scripts allow-same-origin"');
421 done();
422 });
423 });
424
425 it('adds \'https\' protocol to <iframe> if only \'http\' protocol is supplied', function (done) {
426 var url = '<iframe src="http://giphy.com/embed/3oEduKP4VaUxJvLwuA" width="480" height="372" frameBorder="0" class="giphy-embed" allowFullScreen></iframe><p><a href="http://giphy.com/gifs/afv-funny-fail-lol-3oEduKP4VaUxJvLwuA">via GIPHY</a></p>';
427 amperize.parse(url, function (error, result) {
428 expect(result).to.exist;
429 expect(result).to.contain('<amp-iframe');
430 expect(result).to.contain('src="https://giphy.com/embed/3oEduKP4VaUxJvLwuA"');
431 expect(result).to.contain('layout="responsive"');
432 expect(result).to.contain('width="480"');
433 expect(result).to.contain('height="372"');
434 expect(result).to.contain('</amp-iframe>');
435 expect(result).to.contain('sandbox="allow-scripts allow-same-origin"');
436 done();
437 });
438 });
439
440 it('transforms local <img> into <amp-img></amp-img> with default image dimensions', function (done) {
441 amperize.parse('<img src="/content/images/IMG_xyz.jpg">', function (error, result) {
442 expect(result).to.exist;
443 expect(result).to.contain('<amp-img');
444 expect(result).to.contain('src="/content/images/IMG_xyz.jpg"');
445 expect(result).to.contain('layout="responsive"');
446 expect(result).to.contain('width="600"');
447 expect(result).to.contain('height="400"');
448 expect(result).to.contain('</amp-img>');
449 done();
450 });
451 });
452
453 it('can handle <img> tag without src and does not transform it', function (done) {
454 amperize.parse('<img><//img><p>some text here</p>', function (error, result) {
455 expect(result).to.exist;
456 expect(result).to.be.equal('<img><p>some text here</p>');
457 done();
458 });
459 });
460
461 it('can handle invalid URLs', function (done) {
462 amperize.parse('<img src="http:not-a-website">', function (error, result) {
463 expect(result).to.exist;
464 expect(result).to.be.equal('<img src="http:not-a-website">');
465 done();
466 });
467 });
468
469 it('can handle <iframe> tag without src and does not transform it', function (done) {
470 amperize.parse('<iframe>', function (error, result) {
471 expect(result).to.exist;
472 expect(result).to.be.equal('<iframe></iframe>');
473 done();
474 });
475 });
476
477 it('transforms <audio> with a fallback to <amp-audio>', function (done) {
478 amperize.parse('<audio src="http://foo.mp3" autoplay>Your browser does not support the <code>audio</code> element.</audio>', function (error, result) {
479 expect(result).to.exist;
480 expect(result).to.contain('<amp-audio src="https://foo.mp3" autoplay="">');
481 expect(result).to.contain('Your browser does not support the <code>audio</code> element.');
482 expect(result).to.contain('</amp-audio>');
483 done();
484 });
485 });
486
487 it('transforms <audio> with a <source> tag to <amp-audio> and maintains the attributes', function (done) {
488 amperize.parse('<audio controls="controls" width="auto" height="50" autoplay="mobile">Your browser does not support the <code>audio</code> element.<source src="//foo.wav" type="audio/wav"></audio>', function (error, result) {
489 expect(result).to.exist;
490 expect(result).to.contain('<amp-audio');
491 expect(result).to.contain('controls="controls" width="auto" height="50" autoplay="mobile"');
492 expect(result).to.contain('<source src="https://foo.wav" type="audio/wav">');
493 expect(result).to.contain('</amp-audio>');
494 done();
495 });
496 });
497
498 it('transforms <audio> with a <track> tag to <amp-audio>', function (done) {
499 amperize.parse('<audio src="foo.ogg"><track kind="captions" src="https://foo.en.vtt" srclang="en" label="English"><track kind="captions" src="https://foo.sv.vtt" srclang="sv" label="Svenska"></audio>', function (error, result) {
500 expect(result).to.exist;
501 expect(result).to.contain('<amp-audio src="foo.ogg">');
502 expect(result).to.contain('<track kind="captions" src="https://foo.en.vtt" srclang="en" label="English">');
503 expect(result).to.contain('<track kind="captions" src="https://foo.sv.vtt" srclang="sv" label="Svenska">');
504 expect(result).to.contain('</amp-audio>');
505 done();
506 });
507 });
508
509 it('transforms all src urls in <amp-audio> to https', function (done) {
510 amperize.parse('<audio src="//foo.ogg"><source type="audio/mpeg" src="http://foo.mp3"><track kind="captions" src="http://foo.en.vtt" srclang="en" label="English"><track kind="captions" src="http://foo.sv.vtt" srclang="sv" label="Svenska"></audio>', function (error, result) {
511 expect(result).to.exist;
512 expect(result).to.contain('<amp-audio src="https://foo.ogg">');
513 expect(result).to.contain('<source type="audio/mpeg" src="https://foo.mp3">');
514 expect(result).to.contain('<track kind="captions" src="https://foo.en.vtt" srclang="en" label="English">');
515 expect(result).to.contain('<track kind="captions" src="https://foo.sv.vtt" srclang="sv" label="Svenska">');
516 expect(result).to.contain('</amp-audio>');
517 done();
518 });
519 })
520
521 it('can handle redirects', function (done) {
522 var secondImageSizeMock;
523 var GIF1x1 = Buffer.from('R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==', 'base64');
524
525 imageSizeMock = nock('http://noimagehere.com')
526 .get('/files/f/feedough/x/11/1540353_20925115.jpg')
527 .reply(301, {
528 body: ''
529 },
530 {
531 location: 'http://someredirectedurl.com/files/f/feedough/x/11/1540353_20925115.jpg'
532 });
533
534 secondImageSizeMock = nock('http://someredirectedurl.com')
535 .get('/files/f/feedough/x/11/1540353_20925115.jpg')
536 .reply(200, GIF1x1);
537
538 amperize.parse('<img src="http://noimagehere.com/files/f/feedough/x/11/1540353_20925115.jpg">', function (error, result) {
539 expect(imageSizeMock.isDone()).to.be.equal(true, 'imageSizeMock isn\'t done');
540 expect(secondImageSizeMock.isDone()).to.be.equal(true, 'secondImageSizeMock isn\'t done');
541 expect(error).to.be.null;
542 expect(result).to.contain('<amp-img src="http://noimagehere.com/files/f/feedough/x/11/1540353_20925115.jpg" width="1" height="1" layout="fixed"></amp-img>');
543 done();
544 });
545 });
546
547 it('can handle request errors', function (done) {
548 imageSizeMock = nock('http://example.com')
549 .get('/images/IMG_xyz.jpg')
550 .reply(404, {message: 'something awful happened', code: 'AWFUL_ERROR'});
551
552 amperize.parse('<img src="http://example.com/images/IMG_xyz.jpg">', function (error, result) {
553 expect(error).to.be.null;
554 expect(result).to.contain('<img src="http://example.com/images/IMG_xyz.jpg">');
555 done();
556 });
557 });
558
559 it('can handle errors of probe-image-size module', function (done) {
560 // will throw ProbeError: unrecognized file format
561 imageSizeMock = nock('http://example.com')
562 .get('/images/IMG_xyz.jpg')
563 .reply(200, 'not an image');
564
565 amperize.parse('<img src="http://example.com/images/IMG_xyz.jpg">', function (error, result) {
566 expect(error).to.be.null;
567 expect(result).to.contain('<img src="http://example.com/images/IMG_xyz.jpg">');
568 done();
569 });
570 });
571
572 it('can handle timeout errors', function (done) {
573 var GIF1x1 = Buffer.from('R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==', 'base64');
574
575 this.timeout(300);
576 amperize = new Amperize({request_timeout: 100});
577
578 // NOTE: nock will compare the delay value with the timeout value used in the underlying `request`
579 // call and immediately fire an ETIMEDOUT event so don't expect test times to match the delay
580 //
581 // Unfortunately nock.cleanAll() does not stop delayed requests so there can be a delay once all tests
582 // finish running whilst waiting for timeouts to finish so it's best to keep delays as short as possible
583 // https://github.com/nock/nock/issues/1118
584 imageSizeMock = nock('http://example.com')
585 .get('/images/IMG_xyz.jpg')
586 .delay(200)
587 .reply(200, GIF1x1);
588
589 amperize.parse('<img src="http://example.com/images/IMG_xyz.jpg">', function (error, result) {
590 expect(error).to.be.null;
591 expect(result).to.contain('<img src="http://example.com/images/IMG_xyz.jpg">');
592 done();
593 });
594 });
595 });
596
597 describe('#amperizer', function () {
598 it('throws an error if HTML parsing failed', function () {
599 function err() {
600 amperize.amperizer('some error', []);
601 }
602
603 expect(err).throws('Amperizer failed to parse DOM');
604 });
605
606 it('should start traversing the DOM as soon as HTML parser is ready', function (done) {
607 var emit = sinon.spy(amperize, 'emit');
608
609 amperize.parse('<html><body></body></html>', function () {
610 var first, second;
611
612 expect(emit).to.be.calledTwice;
613
614 first = emit.getCall(0).args;
615 expect(first).to.be.an('array');
616 expect(first[0]).to.be.equal('read');
617 expect(first[1]).to.be.equal(null);
618 expect(first[2]).to.be.an('array');
619
620 second = emit.getCall(1).args;
621 expect(second).to.be.an('array');
622 expect(second[0]).to.be.include('parsed');
623 expect(second[1]).to.be.equal(null);
624 expect(second[2]).to.be.equal('<html><body></body></html>');
625
626 done();
627 });
628 });
629 });
630});