UNPKG

23.7 kBJavaScriptView Raw
1'use strict';
2
3// Requires
4var path = require('path');
5var zlib = require('zlib');
6var nock = require('nock');
7var gruntMock = require('gruntmock');
8var checkPages = require('../tasks/checkPages.js');
9
10// Block all unexpected network calls...
11nock.disableNetConnect();
12// ... except deliberate connection errors
13nock.enableNetConnect('localhost');
14
15// Verify a task's output
16function testOutput(test, ok, error) {
17 return function(err, mock) {
18 test.equal(mock.logOk.length, ok.length, 'Wrong logOk count');
19 test.equal(mock.logError.length, error.length, 'Wrong logError count');
20 if (err) {
21 test.equal(err.message, error.slice(-1), 'Wrong exception text');
22 }
23 while (mock.logOk.length && ok.length) {
24 test.equal(mock.logOk.shift().replace(/\(\d+ms\)/, '(00ms)'), ok.shift(), 'Wrong logOk item');
25 }
26 while (mock.logError.length && error.length) {
27 test.equal(mock.logError.shift().replace(/\(\d+ms\)/, '(00ms)'), error.shift(), 'Wrong logError item');
28 }
29 test.done();
30 };
31}
32
33/* Helpers for mocking HTTP requests */
34
35function nockFiles(files, base, headers) {
36 var scope = nock(base || 'http://example.com');
37 files.forEach(function(file) {
38 scope
39 .get('/' + file)
40 .replyWithFile(200, path.join(__dirname, file), headers);
41 });
42}
43function nockLinks(links, base) {
44 var scope = nock(base || 'http://example.com');
45 links.forEach(function(link) {
46 scope
47 .head('/' + link)
48 .reply(200);
49 });
50}
51function nockRedirect(link, status) {
52 var slashLink = '/' + link;
53 nock('http://example.com')
54 .head(slashLink)
55 .reply(status || 301, '', { 'Location': slashLink + '_redirected' })
56 .get(slashLink)
57 .reply(status || 301, '', { 'Location': slashLink + '_redirected' });
58}
59
60exports.checkPages = {
61
62 // Task parameters
63
64 filesPresent: function(test) {
65 test.expect(4);
66 var mock = gruntMock.create({ files: [ { src: ['file'] } ] });
67 mock.invoke(checkPages, testOutput(test,
68 [],
69 ['checkPages task does not use files; remove the files parameter']));
70 },
71
72 pageUrlsMissing: function(test) {
73 test.expect(4);
74 var mock = gruntMock.create();
75 mock.invoke(checkPages, testOutput(test,
76 [],
77 ['pageUrls option is not present; it should be an array of URLs']));
78 },
79
80 pageUrlsWrongType: function(test) {
81 test.expect(4);
82 var mock = gruntMock.create({ options: { pageUrls: 'string' } });
83 mock.invoke(checkPages, testOutput(test,
84 [],
85 ['pageUrls option is invalid; it should be an array of URLs']));
86 },
87
88 linksToIgnoreWrongType: function(test) {
89 test.expect(4);
90 var mock = gruntMock.create({ options: { pageUrls: [], linksToIgnore: 'string' } });
91 mock.invoke(checkPages, testOutput(test,
92 [],
93 ['linksToIgnore option is invalid; it should be an array']));
94 },
95
96 maxResponseTimeWrongType: function(test) {
97 test.expect(4);
98 var mock = gruntMock.create({ options: { pageUrls: [], maxResponseTime: 'string' } });
99 mock.invoke(checkPages, testOutput(test,
100 [],
101 ['maxResponseTime option is invalid; it should be a positive number']));
102 },
103
104 userAgentWrongType: function(test) {
105 test.expect(4);
106 var mock = gruntMock.create({ options: { pageUrls: [], userAgent: 5 } });
107 mock.invoke(checkPages, testOutput(test,
108 [],
109 ['userAgent option is invalid; it should be a string or null']));
110 },
111
112 // Basic functionality
113
114 pageUrlsEmpty: function(test) {
115 test.expect(2);
116 var mock = gruntMock.create({ options: {
117 pageUrls: []
118 }});
119 mock.invoke(checkPages, testOutput(test,
120 [],
121 []));
122 },
123
124 pageUrlsValid: function(test) {
125 test.expect(4);
126 nockFiles(['validPage.html', 'externalLink.html']);
127 var mock = gruntMock.create({ options: {
128 pageUrls: ['http://example.com/validPage.html',
129 'http://example.com/externalLink.html']
130 }});
131 mock.invoke(checkPages, testOutput(test,
132 ['Page: http://example.com/validPage.html (00ms)',
133 'Page: http://example.com/externalLink.html (00ms)'],
134 []));
135 },
136
137 pageUrlsNotFound: function(test) {
138 test.expect(5);
139 nock('http://example.com').get('/notFound').reply(404);
140 var mock = gruntMock.create({ options: {
141 pageUrls: ['http://example.com/notFound']
142 }});
143 mock.invoke(checkPages, testOutput(test,
144 [],
145 ['Bad page (404): http://example.com/notFound (00ms)',
146 '1 issue, see above']));
147 },
148
149 pageUrlsMultiple: function(test) {
150 test.expect(9);
151 nockFiles(['validPage.html', 'externalLink.html', 'validPage.html']);
152 nock('http://example.com').get('/notFound').reply(404);
153 nock('http://example.com').get('/serverError').reply(500);
154 var mock = gruntMock.create({ options: {
155 pageUrls: ['http://example.com/validPage.html',
156 'http://example.com/notFound',
157 'http://example.com/externalLink.html',
158 'http://example.com/serverError',
159 'http://example.com/validPage.html']
160 }});
161 mock.invoke(checkPages, testOutput(test,
162 ['Page: http://example.com/validPage.html (00ms)',
163 'Page: http://example.com/externalLink.html (00ms)',
164 'Page: http://example.com/validPage.html (00ms)'],
165 ['Bad page (404): http://example.com/notFound (00ms)',
166 'Bad page (500): http://example.com/serverError (00ms)',
167 '2 issues, see above']));
168 },
169
170 // checkLinks functionality
171
172 checkLinksValid: function(test) {
173 test.expect(19);
174 nockFiles(['validPage.html']);
175 nockLinks([
176 'link0', 'link1', 'link3', 'link4', 'link5',
177 'link6', 'link7', 'link8', 'link9', 'link10',
178 'link11', 'link12', 'link13',
179 'movedTemporarily_redirected',
180 'movedPermanently_redirected']);
181 nockRedirect('movedPermanently', 301);
182 nockRedirect('movedTemporarily', 302);
183 nockLinks(['link2'], 'http://example.org');
184 var mock = gruntMock.create({ options: {
185 pageUrls: ['http://example.com/validPage.html'],
186 checkLinks: true
187 }});
188 mock.invoke(checkPages, testOutput(test,
189 ['Page: http://example.com/validPage.html (00ms)',
190 'Link: http://example.com/link13 (00ms)',
191 'Link: http://example.com/link12 (00ms)',
192 'Link: http://example.com/link11 (00ms)',
193 'Link: http://example.com/link10 (00ms)',
194 'Link: http://example.com/link9 (00ms)',
195 'Link: http://example.com/link0 (00ms)',
196 'Link: http://example.com/link8 (00ms)',
197 'Link: http://example.com/link7 (00ms)',
198 'Link: http://example.com/link6 (00ms)',
199 'Link: http://example.com/link5 (00ms)',
200 'Link: http://example.com/link4 (00ms)',
201 'Link: http://example.com/link3 (00ms)',
202 'Link: http://example.com/movedTemporarily (00ms)',
203 'Link: http://example.com/movedPermanently (00ms)',
204 'Link: http://example.org/link2 (00ms)',
205 'Link: http://example.com/link1 (00ms)'],
206 []));
207 },
208
209 checkLinksInvalid: function(test) {
210 test.expect(10);
211 nockFiles(['brokenLinks.html']);
212 nockLinks(['link0', 'link1', 'link2']);
213 nock('http://example.com')
214 .head('/broken0').reply(404)
215 .get('/broken0').reply(404)
216 .head('/broken1').reply(500)
217 .get('/broken1').reply(500);
218 var mock = gruntMock.create({ options: {
219 pageUrls: ['http://example.com/brokenLinks.html'],
220 checkLinks: true
221 }});
222 mock.invoke(checkPages, testOutput(test,
223 ['Page: http://example.com/brokenLinks.html (00ms)',
224 'Link: http://example.com/link2 (00ms)',
225 'Link: http://example.com/link1 (00ms)',
226 'Link: http://example.com/link0 (00ms)'],
227 ['Bad link (500): http://example.com/broken1 (00ms)',
228 'Bad link (404): http://example.com/broken0 (00ms)',
229 '2 issues, see above']));
230 },
231
232 checkLinksRetryWhenHeadFails: function(test) {
233 test.expect(4);
234 nockFiles(['retryWhenHeadFails.html']);
235 nock('http://example.com')
236 .head('/link').reply(500)
237 .get('/link').reply(200);
238 var mock = gruntMock.create({ options: {
239 pageUrls: ['http://example.com/retryWhenHeadFails.html'],
240 checkLinks: true
241 }});
242 mock.invoke(checkPages, testOutput(test,
243 ['Page: http://example.com/retryWhenHeadFails.html (00ms)',
244 'Link: http://example.com/link (00ms)'],
245 []));
246 },
247
248 checkLinksOnlySameDomainLinks: function(test) {
249 test.expect(4);
250 nockFiles(['externalLink.html']);
251 nockLinks(['link']);
252 var mock = gruntMock.create({ options: {
253 pageUrls: ['http://example.com/externalLink.html'],
254 checkLinks: true,
255 onlySameDomainLinks: true
256 }});
257 mock.invoke(checkPages, testOutput(test,
258 ['Page: http://example.com/externalLink.html (00ms)',
259 'Link: http://example.com/link (00ms)'],
260 []));
261 },
262
263 checkLinksDisallowRedirect: function(test) {
264 test.expect(6);
265 nockFiles(['redirectLink.html']);
266 nockRedirect('redirect');
267 var mock = gruntMock.create({ options: {
268 pageUrls: ['http://example.com/redirectLink.html'],
269 checkLinks: true,
270 disallowRedirect: true
271 }});
272 mock.invoke(checkPages, testOutput(test,
273 ['Page: http://example.com/redirectLink.html (00ms)'],
274 ['Bad link (301): http://example.com/redirect (00ms)',
275 '1 issue, see above']));
276 },
277
278 checkLinksLinksToIgnore: function(test) {
279 test.expect(6);
280 nockFiles(['ignoreLinks.html']);
281 nockLinks(['link0', 'link1', 'link2']);
282 var mock = gruntMock.create({ options: {
283 pageUrls: ['http://example.com/ignoreLinks.html'],
284 checkLinks: true,
285 linksToIgnore: ['http://example.com/ignore0', 'http://example.com/ignore1']
286 }});
287 mock.invoke(checkPages, testOutput(test,
288 ['Page: http://example.com/ignoreLinks.html (00ms)',
289 'Link: http://example.com/link2 (00ms)',
290 'Link: http://example.com/link1 (00ms)',
291 'Link: http://example.com/link0 (00ms)'],
292 []));
293 },
294
295 checkLinksMultiplePages: function(test) {
296 test.expect(10);
297 nockFiles(['externalLink.html', 'redirectLink.html', 'ignoreLinks.html']);
298 nockLinks(['link', 'link0', 'link1', 'link2', 'redirect_redirected']);
299 nockRedirect('redirect');
300 var mock = gruntMock.create({ options: {
301 pageUrls: ['http://example.com/externalLink.html',
302 'http://example.com/redirectLink.html',
303 'http://example.com/ignoreLinks.html'],
304 checkLinks: true,
305 onlySameDomainLinks: true,
306 linksToIgnore: ['http://example.com/ignore0', 'http://example.com/ignore1']
307 }});
308 mock.invoke(checkPages, testOutput(test,
309 ['Page: http://example.com/externalLink.html (00ms)',
310 'Link: http://example.com/link (00ms)',
311 'Page: http://example.com/redirectLink.html (00ms)',
312 'Link: http://example.com/redirect (00ms)',
313 'Page: http://example.com/ignoreLinks.html (00ms)',
314 'Link: http://example.com/link2 (00ms)',
315 'Link: http://example.com/link1 (00ms)',
316 'Link: http://example.com/link0 (00ms)'],
317 []));
318 },
319
320 // checkXhtml functionality
321
322 checkXhtmlValid: function(test) {
323 test.expect(3);
324 nockFiles(['validPage.html']);
325 var mock = gruntMock.create({ options: {
326 pageUrls: ['http://example.com/validPage.html'],
327 checkXhtml: true
328 }});
329 mock.invoke(checkPages, testOutput(test,
330 ['Page: http://example.com/validPage.html (00ms)'],
331 []));
332 },
333
334 checkXhtmlUnclosedElement: function(test) {
335 test.expect(6);
336 nockFiles(['unclosedElement.html']);
337 var mock = gruntMock.create({ options: {
338 pageUrls: ['http://example.com/unclosedElement.html'],
339 checkXhtml: true
340 }});
341 mock.invoke(checkPages, testOutput(test,
342 ['Page: http://example.com/unclosedElement.html (00ms)'],
343 ['Unexpected close tag, Line: 5, Column: 7, Char: >',
344 '1 issue, see above']));
345 },
346
347 checkXhtmlUnclosedImg: function(test) {
348 test.expect(6);
349 nockFiles(['unclosedImg.html']);
350 var mock = gruntMock.create({ options: {
351 pageUrls: ['http://example.com/unclosedImg.html'],
352 checkXhtml: true
353 }});
354 mock.invoke(checkPages, testOutput(test,
355 ['Page: http://example.com/unclosedImg.html (00ms)'],
356 ['Unexpected close tag, Line: 4, Column: 7, Char: >',
357 '1 issue, see above']));
358 },
359
360 checkXhtmlInvalidEntity : function(test) {
361 test.expect(6);
362 nockFiles(['invalidEntity.html']);
363 var mock = gruntMock.create({ options: {
364 pageUrls: ['http://example.com/invalidEntity.html'],
365 checkXhtml: true
366 }});
367 mock.invoke(checkPages, testOutput(test,
368 ['Page: http://example.com/invalidEntity.html (00ms)'],
369 ['Invalid character entity, Line: 3, Column: 21, Char: ;',
370 '1 issue, see above']));
371 },
372
373 checkXhtmlMultipleErrors : function(test) {
374 test.expect(7);
375 nockFiles(['multipleErrors.html']);
376 var mock = gruntMock.create({ options: {
377 pageUrls: ['http://example.com/multipleErrors.html'],
378 checkXhtml: true
379 }});
380 mock.invoke(checkPages, testOutput(test,
381 ['Page: http://example.com/multipleErrors.html (00ms)'],
382 ['Invalid character entity, Line: 4, Column: 23, Char: ;',
383 'Unexpected close tag, Line: 5, Column: 6, Char: >',
384 '2 issues, see above']));
385 },
386
387 // checkCaching functionality
388
389 checkCachingValid: function(test) {
390 test.expect(3);
391 nockFiles(['validPage.html'], null, {
392 'Cache-Control': 'public, max-age=1000',
393 'ETag': '"123abc"'
394 });
395 var mock = gruntMock.create({ options: {
396 pageUrls: ['http://example.com/validPage.html'],
397 checkCaching: true
398 }});
399 mock.invoke(checkPages, testOutput(test,
400 ['Page: http://example.com/validPage.html (00ms)'],
401 []));
402 },
403
404 checkCachingNoCache: function(test) {
405 test.expect(3);
406 nockFiles(['validPage.html'], null, {
407 'Cache-Control': 'no-cache'
408 });
409 var mock = gruntMock.create({ options: {
410 pageUrls: ['http://example.com/validPage.html'],
411 checkCaching: true
412 }});
413 mock.invoke(checkPages, testOutput(test,
414 ['Page: http://example.com/validPage.html (00ms)'],
415 []));
416 },
417
418 checkCachingWeakEtag: function(test) {
419 test.expect(3);
420 nockFiles(['validPage.html'], null, {
421 'Cache-Control': 'public, max-age=1000',
422 'ETag': 'W/"123abc"'
423 });
424 var mock = gruntMock.create({ options: {
425 pageUrls: ['http://example.com/validPage.html'],
426 checkCaching: true
427 }});
428 mock.invoke(checkPages, testOutput(test,
429 ['Page: http://example.com/validPage.html (00ms)'],
430 []));
431 },
432
433 checkCachingEmptyEtag: function(test) {
434 test.expect(3);
435 nockFiles(['validPage.html'], null, {
436 'Cache-Control': 'public, max-age=1000',
437 'ETag': '""'
438 });
439 var mock = gruntMock.create({ options: {
440 pageUrls: ['http://example.com/validPage.html'],
441 checkCaching: true
442 }});
443 mock.invoke(checkPages, testOutput(test,
444 ['Page: http://example.com/validPage.html (00ms)'],
445 []));
446 },
447
448 checkCachingMissingCacheControl: function(test) {
449 test.expect(6);
450 nockFiles(['validPage.html'], null, {
451 'ETag': '"123abc"'
452 });
453 var mock = gruntMock.create({ options: {
454 pageUrls: ['http://example.com/validPage.html'],
455 checkCaching: true
456 }});
457 mock.invoke(checkPages, testOutput(test,
458 ['Page: http://example.com/validPage.html (00ms)'],
459 ['Missing Cache-Control header in response',
460 '1 issue, see above']));
461 },
462
463 checkCachingInvalidCacheControl: function(test) {
464 test.expect(6);
465 nockFiles(['validPage.html'], null, {
466 'Cache-Control': 'invalid',
467 'ETag': '"123abc"'
468 });
469 var mock = gruntMock.create({ options: {
470 pageUrls: ['http://example.com/validPage.html'],
471 checkCaching: true
472 }});
473 mock.invoke(checkPages, testOutput(test,
474 ['Page: http://example.com/validPage.html (00ms)'],
475 ['Invalid Cache-Control header in response: invalid',
476 '1 issue, see above']));
477 },
478
479 checkCachingMissingEtag: function(test) {
480 test.expect(6);
481 nockFiles(['validPage.html'], null, {
482 'Cache-Control': 'public, max-age=1000'
483 });
484 var mock = gruntMock.create({ options: {
485 pageUrls: ['http://example.com/validPage.html'],
486 checkCaching: true
487 }});
488 mock.invoke(checkPages, testOutput(test,
489 ['Page: http://example.com/validPage.html (00ms)'],
490 ['Missing ETag header in response',
491 '1 issue, see above']));
492 },
493
494 checkCachingInvalidEtag: function(test) {
495 test.expect(6);
496 nockFiles(['validPage.html'], null, {
497 'Cache-Control': 'public, max-age=1000',
498 'ETag': 'invalid'
499 });
500 var mock = gruntMock.create({ options: {
501 pageUrls: ['http://example.com/validPage.html'],
502 checkCaching: true
503 }});
504 mock.invoke(checkPages, testOutput(test,
505 ['Page: http://example.com/validPage.html (00ms)'],
506 ['Invalid ETag header in response: invalid',
507 '1 issue, see above']));
508 },
509
510 // checkCompression functionality
511
512 checkCompressionValid: function(test) {
513 test.expect(4);
514 zlib.gzip('<html><body><a href="link">link</a></body></html>', function(err, buf) {
515 nock('http://example.com')
516 .get('/compressed')
517 .reply(200, [buf], {
518 'Content-Encoding': 'gzip'
519 });
520 nockLinks(['link']);
521 var mock = gruntMock.create({ options: {
522 pageUrls: ['http://example.com/compressed'],
523 checkCompression: true,
524 checkLinks: true
525 }});
526 mock.invoke(checkPages, testOutput(test,
527 ['Page: http://example.com/compressed (00ms)',
528 'Link: http://example.com/link (00ms)'],
529 []));
530 });
531 },
532
533 checkCompressionMissingContentEncoding: function(test) {
534 test.expect(6);
535 nockFiles(['validPage.html']);
536 var mock = gruntMock.create({ options: {
537 pageUrls: ['http://example.com/validPage.html'],
538 checkCompression: true
539 }});
540 mock.invoke(checkPages, testOutput(test,
541 ['Page: http://example.com/validPage.html (00ms)'],
542 ['Missing Content-Encoding header in response',
543 '1 issue, see above']));
544 },
545
546 checkCompressionInvalidContentEncoding: function(test) {
547 test.expect(6);
548 nockFiles(['validPage.html'], null, {
549 'Content-Encoding': 'invalid'
550 });
551 var mock = gruntMock.create({ options: {
552 pageUrls: ['http://example.com/validPage.html'],
553 checkCompression: true
554 }});
555 mock.invoke(checkPages, testOutput(test,
556 ['Page: http://example.com/validPage.html (00ms)'],
557 ['Invalid Content-Encoding header in response: invalid',
558 '1 issue, see above']));
559 },
560
561 // maxResponseTime functionality
562
563 maxResponseTimeValid: function(test) {
564 test.expect(3);
565 nock('http://example.com')
566 .get('/page')
567 .reply(200, '<html></html>');
568 var mock = gruntMock.create({ options: {
569 pageUrls: ['http://example.com/page'],
570 maxResponseTime: 100
571 }});
572 mock.invoke(checkPages, testOutput(test,
573 ['Page: http://example.com/page (00ms)'],
574 []));
575 },
576
577 maxResponseTimeSlow: function(test) {
578 test.expect(6);
579 nock('http://example.com')
580 .get('/page')
581 .delay(200)
582 .reply(200, '<html></html>');
583 var mock = gruntMock.create({ options: {
584 pageUrls: ['http://example.com/page'],
585 maxResponseTime: 100
586 }});
587 mock.invoke(checkPages, testOutput(test,
588 ['Page: http://example.com/page (00ms)'],
589 ['Page response took more than 100ms to complete',
590 '1 issue, see above']));
591 },
592
593 // userAgent functionality
594
595 userAgentValid: function(test) {
596 test.expect(4);
597 nock('http://example.com')
598 .matchHeader('User-Agent', 'custom-user-agent/1.2.3')
599 .get('/page')
600 .reply(200, '<html><body><a href="link">link</a></body></html>');
601 nock('http://example.com')
602 .matchHeader('User-Agent', 'custom-user-agent/1.2.3')
603 .head('/link')
604 .reply(200);
605 var mock = gruntMock.create({ options: {
606 pageUrls: ['http://example.com/page'],
607 checkLinks: true,
608 userAgent: 'custom-user-agent/1.2.3'
609 }});
610 mock.invoke(checkPages, testOutput(test,
611 ['Page: http://example.com/page (00ms)',
612 'Link: http://example.com/link (00ms)'],
613 []));
614 },
615
616 userAgentNull: function(test) {
617 test.expect(4);
618 nock('http://example.com')
619 .matchHeader('User-Agent', function(val) {
620 test.ok(undefined === val);
621 return true;
622 })
623 .get('/page')
624 .reply(200);
625 var mock = gruntMock.create({ options: {
626 pageUrls: ['http://example.com/page'],
627 userAgent: null
628 }});
629 mock.invoke(checkPages, testOutput(test,
630 ['Page: http://example.com/page (00ms)'],
631 []));
632 },
633
634 userAgentEmpty: function(test) {
635 test.expect(4);
636 nock('http://example.com')
637 .matchHeader('User-Agent', function(val) {
638 test.ok(undefined === val);
639 return true;
640 })
641 .get('/page')
642 .reply(200);
643 var mock = gruntMock.create({ options: {
644 pageUrls: ['http://example.com/page'],
645 userAgent: ''
646 }});
647 mock.invoke(checkPages, testOutput(test,
648 ['Page: http://example.com/page (00ms)'],
649 []));
650 },
651
652 // Nock configuration
653
654 requestHeaders: function(test) {
655 test.expect(4);
656 nock('http://example.com')
657 .matchHeader('User-Agent', 'grunt-check-pages/0.1.5')
658 .matchHeader('Cache-Control', 'no-cache')
659 .matchHeader('Pragma', 'no-cache')
660 .get('/page')
661 .reply(200, '<html><body><a href="link">link</a></body></html>');
662 nock('http://example.com')
663 .matchHeader('User-Agent', 'grunt-check-pages/0.1.5')
664 .matchHeader('Cache-Control', 'no-cache')
665 .matchHeader('Pragma', 'no-cache')
666 .head('/link')
667 .reply(200);
668 var mock = gruntMock.create({ options: {
669 pageUrls: ['http://example.com/page'],
670 checkLinks: true
671 }});
672 mock.invoke(checkPages, testOutput(test,
673 ['Page: http://example.com/page (00ms)',
674 'Link: http://example.com/link (00ms)'],
675 []));
676 },
677
678 // Connection errors
679
680 pageConnectionError: function(test) {
681 test.expect(5);
682 var mock = gruntMock.create({ options: {
683 pageUrls: ['http://localhost:9999/notListening']}});
684 mock.invoke(checkPages, testOutput(test,
685 [],
686 ['Page error (connect ECONNREFUSED): http://localhost:9999/notListening (00ms)',
687 '1 issue, see above']));
688 },
689
690 linkConnectionError: function(test) {
691 test.expect(6);
692 nock('http://example.com')
693 .get('/page')
694 .reply(200, '<html><body><a href="http://localhost:9999/notListening">notListening</a></body></html>');
695 var mock = gruntMock.create({ options: {
696 pageUrls: ['http://example.com/page'],
697 checkLinks: true
698 }});
699 mock.invoke(checkPages, testOutput(test,
700 ['Page: http://example.com/page (00ms)'],
701 ['Link error (connect ECONNREFUSED): http://localhost:9999/notListening (00ms)',
702 '1 issue, see above']));
703 },
704};