testaro 4.4.0 → 4.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/commands.js +4 -3
  2. package/package.json +1 -1
  3. package/run.js +158 -146
  4. package/tests/aatt.js +66 -29
package/commands.js CHANGED
@@ -100,8 +100,8 @@ exports.commands = {
100
100
  state: [
101
101
  'Wait until the page reaches a load state',
102
102
  {
103
- which: [true, 'string', 'hasLength', '“loaded” or “idle”'],
104
- what: [false, 'string', 'isState', 'comment']
103
+ which: [true, 'string', 'isState', '“loaded” or “idle”'],
104
+ what: [false, 'string', 'hasLength', 'comment']
105
105
  }
106
106
  ],
107
107
  tenonRequest: [
@@ -146,7 +146,8 @@ exports.commands = {
146
146
  aatt: [
147
147
  'Perform an AATT test with HTML CodeSniffer',
148
148
  {
149
- waitLong: [false, 'boolean', '', 'whether to wait 20 instead of 10 seconds for the result']
149
+ waitLong: [false, 'boolean', '', 'whether to wait 12 instead of 6 seconds for a result'],
150
+ tryLimit: [false, 'number', '', 'times to try the test before giving up; default 4']
150
151
  }
151
152
  ],
152
153
  axe: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testaro",
3
- "version": "4.4.0",
3
+ "version": "4.5.2",
4
4
  "description": "Automation of accessibility testing",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/run.js CHANGED
@@ -256,7 +256,7 @@ const launch = async typeName => {
256
256
  // Make its console messages appear in the Playwright console.
257
257
  page.on('console', msg => {
258
258
  const msgText = msg.text();
259
- console.log(msgText);
259
+ console.log(`[${msgText}]`);
260
260
  logCount++;
261
261
  logSize += msgText.length;
262
262
  const msgLC = msgText.toLowerCase();
@@ -291,7 +291,7 @@ const textOf = async (page, element) => {
291
291
  if (['A', 'BUTTON', 'INPUT', 'SELECT'].includes(tagName)) {
292
292
  // Return its visible labels, descriptions, and legend if the first input in a fieldset.
293
293
  totalText = await page.evaluate(element => {
294
- const {tagName} = element;
294
+ const {tagName, ariaLabel} = element;
295
295
  let ownText = '';
296
296
  if (['A', 'BUTTON'].includes(tagName)) {
297
297
  ownText = element.textContent;
@@ -302,6 +302,9 @@ const textOf = async (page, element) => {
302
302
  // HTML link elements have no labels property.
303
303
  const labels = tagName !== 'A' ? Array.from(element.labels) : [];
304
304
  const labelTexts = labels.map(label => label.textContent);
305
+ if (ariaLabel) {
306
+ labelTexts.push(ariaLabel);
307
+ }
305
308
  const refIDs = new Set([
306
309
  element.getAttribute('aria-labelledby') || '',
307
310
  element.getAttribute('aria-describedby') || ''
@@ -369,69 +372,79 @@ const textOf = async (page, element) => {
369
372
  return null;
370
373
  }
371
374
  };
372
- // Returns an element case-insensitively matching a text.
375
+ // Returns an element of a type case-insensitively matching a text.
373
376
  const matchElement = async (page, selector, matchText, index = 0) => {
374
- // If the page still exists:
375
- if (page) {
376
- // Wait 2 seconds until the body contains any text to be matched.
377
- const slimText = debloat(matchText);
378
- const bodyText = await page.textContent('body');
379
- const slimBody = debloat(bodyText);
380
- const textInBodyJSHandle = await page.waitForFunction(
381
- args => {
382
- const matchText = args[0];
383
- const bodyText = args[1];
384
- return ! matchText || bodyText.includes(matchText);
385
- },
386
- [slimText, slimBody],
387
- {timeout: 4000}
388
- )
389
- .catch(async error => {
390
- console.log(`ERROR: text “${matchText}” not in body (${error.message})`);
391
- });
392
- // If there is no text to be matched or the body contained it:
393
- if (textInBodyJSHandle) {
394
- const lcText = matchText ? matchText.toLowerCase() : '';
395
- // Identify the selected elements.
396
- const selections = await page.$$(`body ${selector}`);
377
+ if (matchText) {
378
+ // If the page still exists:
379
+ if (page) {
380
+ const slimText = debloat(matchText);
381
+ // Identify the elements of the specified type.
382
+ const selections = await page.$$(selector);
397
383
  // If there are any:
398
384
  if (selections.length) {
399
385
  // If there are enough to make a match possible:
400
386
  if (index < selections.length) {
401
- // Return the nth one including any specified text, or the count of candidates if none.
402
- const elementTexts = [];
403
- let nth = 0;
404
- for (const element of selections) {
405
- const elementText = await textOf(page, element);
406
- elementTexts.push(elementText);
407
- if ((! lcText || elementText.includes(lcText)) && nth++ === index) {
408
- return element;
387
+ // Return the specified one, if any.
388
+ let matchCount = 0;
389
+ const selectionTexts = [];
390
+ for (const selection of selections) {
391
+ const selectionText = await textOf(page, selection);
392
+ selectionTexts.push(selectionText);
393
+ if (selectionText.includes(slimText)) {
394
+ if (matchCount++ === index) {
395
+ return {
396
+ success: true,
397
+ matchingElement: selection
398
+ };
399
+ }
409
400
  }
410
401
  }
411
- return elementTexts;
402
+ // None satisfied the specifications, so return a failure.
403
+ return {
404
+ success: false,
405
+ error: 'exhausted',
406
+ message: `Text found in only ${matchCount} (not ${index + 1}) of ${selections.length}`,
407
+ candidateTexts: selectionTexts
408
+ };
412
409
  }
413
- // Otherwise, i.e. if there are too few to make a match possible:
410
+ // Otherwise, i.e. if there are too few such elements to make a match possible:
414
411
  else {
415
- // Return the count of candidates.
416
- return selections.length;
412
+ // Return a failure.
413
+ return {
414
+ success: false,
415
+ error: 'fewer',
416
+ message: `Count of '${selector}' elements only ${selections.length}`
417
+ };
417
418
  }
418
419
  }
419
- // Otherwise, i.e. if there are no selected elements, return 0.
420
+ // Otherwise, i.e. if there are no elements of the specified type:
420
421
  else {
421
- return 0;
422
+ // Return a failure.
423
+ return {
424
+ success: false,
425
+ error: 'none',
426
+ message: `No '${selector}' elements found`
427
+ };
422
428
  }
423
429
  }
424
- // Otherwise, i.e. if the body did not contain it:
430
+ // Otherwise, i.e. if the page no longer exists:
425
431
  else {
426
- // Return the failure.
427
- return -1;
432
+ // Return a failure.
433
+ return {
434
+ success: false,
435
+ error: 'gone',
436
+ message: 'Page gone'
437
+ };
428
438
  }
429
439
  }
430
- // Otherwise, i.e. if the page no longer exists:
440
+ // Otherwise, i.e. if no text was specified:
431
441
  else {
432
- // Return null.
433
- console.log('ERROR: Page gone');
434
- return null;
442
+ // Return a failure.
443
+ return {
444
+ success: false,
445
+ error: 'text',
446
+ message: 'No text specified'
447
+ };
435
448
  }
436
449
  };
437
450
  // Returns a string with any final slash removed.
@@ -502,8 +515,9 @@ const visit = async (act, page, isStrict) => {
502
515
  // If the visit fails:
503
516
  if (response === 'error') {
504
517
  // Give up.
505
- console.log(`ERROR: Visits to ${requestedURL} failed`);
506
- act.result = `ERROR: Visit to ${requestedURL} failed`;
518
+ const errorMsg = `ERROR: Attemts to visit ${requestedURL} failed`;
519
+ console.log(errorMsg);
520
+ act.result = errorMsg;
507
521
  await page.goto('about:blank')
508
522
  .catch(error => {
509
523
  console.log(`ERROR: Navigation to blank page failed (${error.message})`);
@@ -563,6 +577,14 @@ const waitError = (page, act, error, what) => {
563
577
  act.result.error = `ERROR waiting for ${what}`;
564
578
  return false;
565
579
  };
580
+ // Waits.
581
+ const wait = ms => {
582
+ return new Promise(resolve => {
583
+ setTimeout(() => {
584
+ resolve('');
585
+ }, ms);
586
+ });
587
+ };
566
588
  // Recursively performs the acts in a report.
567
589
  const doActs = async (report, actIndex, page) => {
568
590
  const {acts} = report;
@@ -597,12 +619,12 @@ const doActs = async (report, actIndex, page) => {
597
619
  if (truth[1]) {
598
620
  // If the performance of commands is to stop:
599
621
  if (act.jump === 0) {
600
- // Set the command index to cause a stop.
622
+ // Stop.
601
623
  actIndex = -2;
602
624
  }
603
625
  // Otherwise, if there is a numerical jump:
604
626
  else if (act.jump) {
605
- // Set the command index accordingly.
627
+ // Set the act index accordingly.
606
628
  actIndex += act.jump - 1;
607
629
  }
608
630
  // Otherwise, if there is a named next command:
@@ -630,76 +652,65 @@ const doActs = async (report, actIndex, page) => {
630
652
  else if (act.type === 'wait') {
631
653
  const {what, which} = act;
632
654
  console.log(`>> for ${what} to include “${which}”`);
633
- // Wait 5 or 10 seconds for the specified text, and quit if it does not.
634
- let successJSHandle;
655
+ // Wait 5 or 10 seconds for the specified text, and quit if it does not appear.
635
656
  if (act.what === 'url') {
636
- successJSHandle = await page.waitForFunction(
637
- text => document.URL.includes(text), act.which, {timeout: 5000}
638
- )
657
+ await page.waitForURL(act.which, {timeout: 15000})
639
658
  .catch(error => {
640
- actIndex = acts.length;
641
- return waitError(page, act, error, 'URL');
659
+ actIndex = -2;
660
+ waitError(page, act, error, 'URL');
642
661
  });
643
662
  }
644
663
  else if (act.what === 'title') {
645
- successJSHandle = await page.waitForFunction(
646
- text => document.title.includes(text), act.which, {timeout: 5000}
664
+ await page.waitForFunction(
665
+ text => document && document.title && document.title.includes(text),
666
+ act.which,
667
+ {
668
+ polling: 1000,
669
+ timeout: 5000
670
+ }
647
671
  )
648
672
  .catch(error => {
649
- actIndex = acts.length;
650
- return waitError(page, act, error, 'title');
673
+ actIndex = -2;
674
+ waitError(page, act, error, 'title');
651
675
  });
652
676
  }
653
677
  else if (act.what === 'body') {
654
- successJSHandle = await page.waitForFunction(
655
- matchText => {
656
- const innerText = document && document.body && document.body.innerText;
657
- if (innerText) {
658
- return innerText.includes(matchText);
659
- }
660
- else {
661
- actIndex = acts.length;
662
- console.log('ERROR finding document body');
663
- return false;
664
- }
665
- }, which, {timeout: 20000}
678
+ await page.waitForFunction(
679
+ text => document && document.body && document.body.innerText.includes(text),
680
+ act.which,
681
+ {
682
+ polling: 2000,
683
+ timeout: 10000
684
+ }
666
685
  )
667
- .catch(error => {
668
- actIndex = acts.length;
669
- return waitError(page, act, error, 'body');
686
+ .catch(async error => {
687
+ actIndex = -2;
688
+ waitError(page, act, error, 'body');
670
689
  });
671
690
  }
672
- if (successJSHandle) {
691
+ // If the text was found:
692
+ if (actIndex > -2) {
693
+ // Add this to the report.
673
694
  act.result = {url: page.url()};
674
695
  if (act.what === 'title') {
675
696
  act.result.title = await page.title();
676
697
  }
677
- await page.waitForLoadState('networkidle', {timeout: 10000})
678
- .catch(error => {
679
- console.log(`ERROR waiting for stability after ${act.what} (${error.message})`);
680
- act.result.error = `ERROR waiting for stability after ${act.what}`;
681
- });
682
698
  }
683
699
  }
684
700
  // Otherwise, if the act is a wait for a state:
685
701
  else if (act.type === 'state') {
686
- // If the state is valid:
702
+ // Wait for it, and quit if it does not appear.
687
703
  const stateIndex = ['loaded', 'idle'].indexOf(act.which);
688
- if (stateIndex !== -1) {
689
- // Wait for it, and quit if it does not appear.
690
- await page.waitForLoadState(
691
- ['domcontentloaded', 'networkidle'][stateIndex], {timeout: [10000, 5000][stateIndex]}
692
- )
693
- .catch(error => {
694
- console.log(`ERROR waiting for page to be ${act.which} (${error.message})`);
695
- act.result = `ERROR waiting for page to be ${act.which}`;
696
- actIndex = acts.length;
697
- });
698
- }
699
- else {
700
- console.log('ERROR: invalid state');
701
- act.result = 'ERROR: invalid state';
702
- actIndex = acts.length;
704
+ await page.waitForLoadState(
705
+ ['domcontentloaded', 'networkidle'][stateIndex], {timeout: [10000, 5000][stateIndex]}
706
+ )
707
+ .catch(error => {
708
+ console.log(`ERROR waiting for page to be ${act.which} (${error.message})`);
709
+ act.result = `ERROR waiting for page to be ${act.which}`;
710
+ actIndex = -2;
711
+ });
712
+ if (actIndex > -2) {
713
+ act.result = `Page became ${act.which}`;
703
714
  }
704
715
  }
705
716
  // Otherwise, if the act is a page switch:
@@ -889,48 +900,34 @@ const doActs = async (report, actIndex, page) => {
889
900
  // Otherwise, if the act is a move:
890
901
  else if (moves[act.type]) {
891
902
  const selector = typeof moves[act.type] === 'string' ? moves[act.type] : act.what;
892
- // Identify the element to perform the move on.
893
- const whichElement = await matchElement(page, selector, act.which || '', act.index);
894
- // If there were enough candidates but no text match:
895
- if (Array.isArray(whichElement)) {
896
- // Add the result to the act.
897
- act.result = {
898
- candidateCount: whichElement.length,
899
- error: 'ERROR: no element with matching text found',
900
- candidateTexts: whichElement
901
- };
902
- }
903
- // Otherwise, if the body did not contain the text:
904
- else if (whichElement === -1) {
905
- // Add the failure to the act.
906
- act.result = 'ERROR: body did not contain text to match';
907
- }
908
- // Otherwise, if there were not enough candidates:
909
- else if (typeof whichElement === 'number') {
910
- // Add the failure to the act.
911
- act.result = {
912
- candidateCount: whichElement,
913
- error: 'ERROR: too few such elements to allow a match'
914
- };
903
+ // Try up to 5 times, every 2 seconds, to identify the element to perform the move on.
904
+ let matchResult = {success: false};
905
+ let tries = 0;
906
+ while (tries++ < 5 && ! matchResult.success) {
907
+ matchResult = await matchElement(page, selector, act.which || '', act.index);
908
+ if (! matchResult.success) {
909
+ await wait(2000);
910
+ }
915
911
  }
916
- // Otherwise, if a match was found:
917
- else if (whichElement !== null) {
912
+ // If a match was found:
913
+ if (matchResult.success) {
914
+ const {matchingElement} = matchResult;
918
915
  // If the move is a button click, perform it.
919
916
  if (act.type === 'button') {
920
- await whichElement.click({timeout: 3000});
917
+ await matchingElement.click({timeout: 3000});
921
918
  act.result = 'clicked';
922
919
  }
923
920
  // Otherwise, if it is checking a radio button or checkbox, perform it.
924
921
  else if (['checkbox', 'radio'].includes(act.type)) {
925
- await whichElement.waitForElementState('stable', {timeout: 2000})
922
+ await matchingElement.waitForElementState('stable', {timeout: 2000})
926
923
  .catch(error => {
927
924
  console.log(`ERROR waiting for stable ${act.type} (${error.message})`);
928
925
  act.result = `ERROR waiting for stable ${act.type}`;
929
926
  });
930
927
  if (! act.result) {
931
- const isEnabled = await whichElement.isEnabled();
928
+ const isEnabled = await matchingElement.isEnabled();
932
929
  if (isEnabled) {
933
- await whichElement.check({
930
+ await matchingElement.check({
934
931
  force: true,
935
932
  timeout: 2000
936
933
  })
@@ -951,29 +948,37 @@ const doActs = async (report, actIndex, page) => {
951
948
  }
952
949
  // Otherwise, if it is focusing the element, perform it.
953
950
  else if (act.type === 'focus') {
954
- await whichElement.focus({timeout: 2000});
951
+ await matchingElement.focus({timeout: 2000});
955
952
  act.result = 'focused';
956
953
  }
957
954
  // Otherwise, if it is clicking a link, perform it.
958
955
  else if (act.type === 'link') {
959
- const href = await whichElement.getAttribute('href');
960
- const target = await whichElement.getAttribute('target');
961
- await whichElement.click({timeout: 2000})
956
+ const href = await matchingElement.getAttribute('href');
957
+ const target = await matchingElement.getAttribute('target');
958
+ await matchingElement.click({timeout: 2000})
962
959
  .catch(async () => {
963
- await whichElement.click({
960
+ console.log('ERROR: First attempt to click link timed out');
961
+ await matchingElement.click({
964
962
  force: true,
965
963
  timeout: 10000
964
+ })
965
+ .catch(() => {
966
+ actIndex = -2;
967
+ console.log('ERROR: Second (forced) attempt to click link timed out');
968
+ act.result = 'ERROR: Normal and forced click attempts timed out';
966
969
  });
967
970
  });
968
- act.result = {
969
- href: href || 'NONE',
970
- target: target || 'NONE',
971
- move: 'clicked'
972
- };
971
+ if (actIndex > -2) {
972
+ act.result = {
973
+ href: href || 'NONE',
974
+ target: target || 'NONE',
975
+ move: 'clicked'
976
+ };
977
+ }
973
978
  }
974
979
  // Otherwise, if it is selecting an option in a select list, perform it.
975
980
  else if (act.type === 'select') {
976
- const options = await whichElement.$$('option');
981
+ const options = await matchingElement.$$('option');
977
982
  let optionText = '';
978
983
  if (options && Array.isArray(options) && options.length) {
979
984
  const optionTexts = [];
@@ -984,12 +989,12 @@ const doActs = async (report, actIndex, page) => {
984
989
  const matchTexts = optionTexts.map((text, index) => text.includes(act.what) ? index : -1);
985
990
  const index = matchTexts.filter(text => text > -1)[act.index || 0];
986
991
  if (index !== undefined) {
987
- await whichElement.selectOption({index});
992
+ await matchingElement.selectOption({index});
988
993
  optionText = optionTexts[index];
989
994
  }
990
995
  }
991
996
  act.result = optionText
992
- ? `&ldquo;${optionText}}&rdquo; selected`
997
+ ? `“${optionText} selected`
993
998
  : 'ERROR: option not found';
994
999
  }
995
1000
  // Otherwise, if it is entering text on the element:
@@ -1003,19 +1008,24 @@ const doActs = async (report, actIndex, page) => {
1003
1008
  what = what.replace(/__[A-Z]+__/, envValue);
1004
1009
  }
1005
1010
  // Enter the text.
1006
- await whichElement.type(act.what);
1011
+ await matchingElement.type(act.what);
1007
1012
  report.presses += act.what.length;
1008
1013
  act.result = 'entered';
1009
1014
  }
1010
1015
  // Otherwise, i.e. if the move is unknown, add the failure to the act.
1011
1016
  else {
1012
1017
  // Report the error.
1013
- act.result = 'ERROR: move unknown';
1018
+ const report = 'ERROR: move unknown';
1019
+ act.result = report;
1020
+ console.log(report);
1014
1021
  }
1015
1022
  }
1016
- // Otherwise, i.e. if the page was gone:
1023
+ // Otherwise, i.e. if no match was found:
1017
1024
  else {
1018
- act.result = 'ERROR: page gone, so matching element not found';
1025
+ // Stop.
1026
+ act.result = matchResult;
1027
+ console.log('ERROR: Specified element not found');
1028
+ actIndex = -2;
1019
1029
  }
1020
1030
  }
1021
1031
  // Otherwise, if the act is a keypress:
@@ -1203,7 +1213,9 @@ const doActs = async (report, actIndex, page) => {
1203
1213
  // Otherwise, i.e. if the command is invalid:
1204
1214
  else {
1205
1215
  // Add an error result to the act.
1206
- act.result = `ERROR: Invalid command of type ${act.type}`;
1216
+ const errorMsg = `ERROR: Invalid command of type ${act.type}`;
1217
+ act.result = errorMsg;
1218
+ console.log(errorMsg);
1207
1219
  }
1208
1220
  // Perform the remaining acts.
1209
1221
  await doActs(report, actIndex + 1, page);
package/tests/aatt.js CHANGED
@@ -7,31 +7,59 @@
7
7
  const {evaluate} = require('aatt');
8
8
 
9
9
  // FUNCTIONS
10
- exports.reporter = async (page, waitLong) => {
11
- // Set the limit in seconds on the wait for the result.
12
- const timeLimit = waitLong ? 20 : 10;
13
- // Get the HTML of the document body.
14
- const source = await page.content();
15
- // Return the result of a test with the HTML CodeSniffer WCAG 2.1 AA ruleset as a string.
16
- const report = evaluate({
17
- source,
18
- output: 'json',
19
- engine: 'htmlcs',
20
- level: 'WCAG2AA'
21
- });
22
- // Wait for it until the time limit expires.
23
- let timeoutID;
24
- const wait = new Promise(resolve => {
25
- timeoutID = setTimeout(() => {
26
- resolve('');
27
- }, 1000 * timeLimit);
28
- });
29
- const resultIfFast = await Promise.race([report, wait]);
30
- // If it arrived within the time limit:
31
- if (resultIfFast) {
32
- clearTimeout(timeoutID);
33
- // Remove the non-JSON prefix and (if any) suffix from the string.
34
- const reportJSON = resultIfFast.replace(/^.+?Object]\s+|\s+done\s*$/sg, '');
10
+ // Recursively test a page with HTML CodeSniffer for WCAC 2.1 AAA.
11
+ const retest = async (page, waitLong, triesLeft) => {
12
+ // If the limit on tries has not been exhausted:
13
+ if (triesLeft) {
14
+ // Set the limit in seconds on the wait for the result.
15
+ const timeLimit = waitLong ? 12 : 6;
16
+ // Get the HTML of the document body.
17
+ const source = await page.content();
18
+ // Return the result of a test with the HTML CodeSniffer WCAG 2.1 AA ruleset as a string.
19
+ const report = evaluate({
20
+ source,
21
+ output: 'json',
22
+ engine: 'htmlcs',
23
+ level: 'WCAG2AAA'
24
+ });
25
+ // Wait for it until the time limit expires.
26
+ let timeoutID;
27
+ const wait = new Promise(resolve => {
28
+ timeoutID = setTimeout(() => {
29
+ resolve('');
30
+ }, 1000 * timeLimit);
31
+ });
32
+ const result = await Promise.race([report, wait]);
33
+ // If it arrived within the time limit:
34
+ if (result) {
35
+ clearTimeout(timeoutID);
36
+ // Return the result as JSON.
37
+ const reportJSON = result.replace(/^.+?Object.?\s+|\s+done\s*$/sg, '');
38
+ return {
39
+ triesLeft,
40
+ reportJSON
41
+ };
42
+ }
43
+ else {
44
+ console.log(`ERROR: Test aatt timed out at ${timeLimit} seconds; tries left: ${triesLeft - 1}`);
45
+ return retest(page, waitLong, --triesLeft);
46
+ }
47
+ }
48
+ // Otherwise, i.e. if the limit on tries has been exhausted:
49
+ else {
50
+ // Return this.
51
+ return {
52
+ triesLeft,
53
+ reportJSON: ''
54
+ };
55
+ }
56
+ };
57
+ exports.reporter = async (page, waitLong, tryLimit = 4) => {
58
+ // Try the test up to the limit on tries.
59
+ const result = await retest(page, waitLong, tryLimit);
60
+ const {triesLeft, reportJSON} = result;
61
+ // If any try succeeded:
62
+ if (reportJSON) {
35
63
  try {
36
64
  // Convert the JSON string to an array.
37
65
  const issueArray = JSON.parse(reportJSON);
@@ -49,10 +77,18 @@ exports.reporter = async (page, waitLong) => {
49
77
  .join('+');
50
78
  }
51
79
  });
52
- return {result: nonNotices};
80
+ return {
81
+ result: {
82
+ report: nonNotices,
83
+ triesLeft
84
+ }
85
+ };
53
86
  }
54
87
  catch (error) {
55
88
  console.log(`ERROR processing AATT report (${error.message})`);
89
+ console.log(
90
+ `JSON report starts with ${reportJSON.slice(0, 50)} and ends with ${reportJSON.slice(-50)}`
91
+ );
56
92
  return {
57
93
  result: {
58
94
  prevented: true,
@@ -61,14 +97,15 @@ exports.reporter = async (page, waitLong) => {
61
97
  };
62
98
  }
63
99
  }
64
- // Otherwise, i.e. if the result did not arrive within the time limit:
100
+ // Otherwise, i.e. if the limit on tries was exhausted:
65
101
  else {
66
102
  // Report the failure.
67
- console.log('ERROR: getting report took too long');
103
+ const error = 'ERROR: Getting AATT report took too long';
104
+ console.log(error);
68
105
  return {
69
106
  result: {
70
107
  prevented: true,
71
- error: 'ERROR: getting AATT report took too long'
108
+ error
72
109
  }
73
110
  };
74
111
  }