testaro 8.4.7 → 8.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 (3) hide show
  1. package/package.json +1 -1
  2. package/run.js +60 -37
  3. package/watch.js +26 -30
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testaro",
3
- "version": "8.4.7",
3
+ "version": "8.5.2",
4
4
  "description": "Automation of accessibility testing",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/run.js CHANGED
@@ -9,6 +9,8 @@
9
9
  require('dotenv').config();
10
10
  // Requirements for commands.
11
11
  const {commands} = require('./commands');
12
+ // Playwright package.
13
+ const playwright = require('playwright');
12
14
 
13
15
  // ########## CONSTANTS
14
16
 
@@ -295,7 +297,7 @@ const browserClose = async () => {
295
297
  const errorStart = error => error.message.replace(/\n.+/s, '');
296
298
  // Launches a browser.
297
299
  const launch = async (report, typeName, lowMotion = false) => {
298
- const browserType = require('playwright')[typeName];
300
+ const browserType = playwright[typeName];
299
301
  // If the specified browser type exists:
300
302
  if (browserType) {
301
303
  // Close the current browser, if any.
@@ -604,6 +606,18 @@ const goTo = async (report, page, url, timeout, waitUntil, isStrict) => {
604
606
  };
605
607
  // Recursively performs the acts in a report.
606
608
  const doActs = async (report, actIndex, page) => {
609
+ // Quits and reports the performance being aborted.
610
+ const abortActs = async () => {
611
+ // Add data on the aborted command to the report.
612
+ report.jobData.abortTime = nowString();
613
+ report.jobData.abortedAct = actIndex;
614
+ // Prevent performance of additional commands.
615
+ actIndex = -2;
616
+ // Report this.
617
+ console.log('ERROR: Job aborted');
618
+ // Stop the action until the user resumes it.
619
+ await page.pause();
620
+ };
607
621
  process.on('message', message => {
608
622
  if (message === 'interrupt') {
609
623
  console.log('ERROR: Terminal interrupted doActs');
@@ -643,7 +657,7 @@ const doActs = async (report, actIndex, page) => {
643
657
  if (truth[1]) {
644
658
  // If the performance of commands is to stop:
645
659
  if (act.jump === 0) {
646
- // Stop.
660
+ // Quit.
647
661
  actIndex = -2;
648
662
  }
649
663
  // Otherwise, if there is a numerical jump:
@@ -712,23 +726,17 @@ const doActs = async (report, actIndex, page) => {
712
726
  }
713
727
  // If none of the visits succeeded:
714
728
  if (response.error) {
715
- // Report this.
716
- report.jobData.aborted = true;
717
- report.jobData.abortedAct = actIndex;
729
+ // Report this and quit.
718
730
  addError(act, 'failure', 'ERROR: Visits failed');
719
- // Quit.
720
- actIndex = -2;
731
+ await abortActs();
721
732
  }
722
733
  // Otherwise, i.e. if the last visit attempt succeeded:
723
734
  else {
724
735
  // If a prohibited redirection occurred:
725
736
  if (response.exception === 'badRedirection') {
726
- // Report this.
727
- report.jobData.aborted = true;
728
- report.jobData.abortedAct = actIndex;
737
+ // Report this and quit.
729
738
  addError(act, 'badRedirection', 'ERROR: Navigation illicitly redirected');
730
- // Quit.
731
- actIndex = -2;
739
+ await abortActs();
732
740
  }
733
741
  // Add the resulting URL to the act.
734
742
  if (! act.result) {
@@ -744,20 +752,22 @@ const doActs = async (report, actIndex, page) => {
744
752
  const result = act.result = {};
745
753
  // If the text is to be the URL:
746
754
  if (what === 'url') {
747
- // Wait for the URL to be the exact text and quit on failure.
755
+ // Wait for the URL to be the exact text.
748
756
  try {
749
757
  await page.waitForURL(which, {timeout: 15000});
750
758
  result.found = true;
751
759
  result.url = page.url();
752
760
  }
761
+ // If the wait times out:
753
762
  catch(error) {
754
- actIndex = -2;
763
+ // Quit.
764
+ await abortActs();
755
765
  waitError(page, act, error, 'text in the URL');
756
766
  }
757
767
  }
758
768
  // Otherwise, if the text is to be a substring of the page title:
759
769
  else if (what === 'title') {
760
- // Wait for the page title to include the text, case-insensitively, and quit on failure.
770
+ // Wait for the page title to include the text, case-insensitively.
761
771
  try {
762
772
  await page.waitForFunction(
763
773
  text => document
@@ -772,14 +782,16 @@ const doActs = async (report, actIndex, page) => {
772
782
  result.found = true;
773
783
  result.title = await page.title();
774
784
  }
785
+ // If the wait times out:
775
786
  catch(error) {
776
- actIndex = -2;
787
+ // Quit.
788
+ await abortActs();
777
789
  waitError(page, act, error, 'text in the title');
778
790
  }
779
791
  }
780
792
  // Otherwise, if the text is to be a substring of the text of the page body:
781
793
  else if (what === 'body') {
782
- // Wait for the body to include the text, case-insensitively, and quit on failure.
794
+ // Wait for the body to include the text, case-insensitively.
783
795
  try {
784
796
  await page.waitForFunction(
785
797
  text => document
@@ -793,25 +805,31 @@ const doActs = async (report, actIndex, page) => {
793
805
  );
794
806
  result.found = true;
795
807
  }
808
+ // If the wait times out:
796
809
  catch(error) {
797
- actIndex = -2;
810
+ // Quit.
811
+ await abortActs();
798
812
  waitError(page, act, error, 'text in the body');
799
813
  }
800
814
  }
801
815
  }
802
816
  // Otherwise, if the act is a wait for a state:
803
817
  else if (act.type === 'state') {
804
- // Wait for it and quit on failure.
818
+ // Wait for it.
805
819
  const stateIndex = ['loaded', 'idle'].indexOf(act.which);
806
820
  await page.waitForLoadState(
807
821
  ['domcontentloaded', 'networkidle'][stateIndex], {timeout: [10000, 15000][stateIndex]}
808
822
  )
809
- .catch(error => {
823
+ // If the wait times out:
824
+ .catch(async error => {
825
+ // Quit.
810
826
  console.log(`ERROR waiting for page to be ${act.which} (${error.message})`);
811
827
  addError(act, 'timeout', `ERROR waiting for page to be ${act.which}`);
812
- actIndex = -2;
828
+ await abortActs();
813
829
  });
830
+ // If the wait succeeded:
814
831
  if (actIndex > -2) {
832
+ // Add state data to the report.
815
833
  act.result = {
816
834
  success: true,
817
835
  state: act.which
@@ -1085,8 +1103,9 @@ const doActs = async (report, actIndex, page) => {
1085
1103
  // If a match was found:
1086
1104
  if (act.result.found) {
1087
1105
  // FUNCTION DEFINITION START
1088
- // Perform a click or Enter keypress and wait for the network to be idle.
1106
+ // Performs a click or Enter keypress and waits for the network to be idle.
1089
1107
  const doAndWait = async isClick => {
1108
+ // Perform and report the move.
1090
1109
  const move = isClick ? 'click' : 'Enter keypress';
1091
1110
  try {
1092
1111
  await isClick
@@ -1095,12 +1114,14 @@ const doActs = async (report, actIndex, page) => {
1095
1114
  act.result.success = true;
1096
1115
  act.result.move = move;
1097
1116
  }
1117
+ // If the move fails:
1098
1118
  catch(error) {
1119
+ // Quit and add failure data to the report.
1099
1120
  act.result.success = false;
1100
1121
  act.result.error = 'moveFailure';
1101
1122
  act.result.message = `ERROR: ${move} failed`;
1102
1123
  console.log(`ERROR: ${move} failed (${errorStart(error)})`);
1103
- actIndex = -2;
1124
+ await abortActs();
1104
1125
  }
1105
1126
  if (act.result.success) {
1106
1127
  try {
@@ -1186,15 +1207,16 @@ const doActs = async (report, actIndex, page) => {
1186
1207
  }
1187
1208
  // If the click or load failed:
1188
1209
  catch(error) {
1189
- // Quit and report the failure.
1210
+ // Quit and add failure data to the report.
1190
1211
  console.log(`ERROR clicking link (${errorStart(error)})`);
1191
1212
  act.result.success = false;
1192
1213
  act.result.error = 'unclickable';
1193
1214
  act.result.message = 'ERROR: click or load timed out';
1194
- actIndex = -2;
1215
+ await abortActs();
1195
1216
  }
1196
1217
  // If the link click succeeded:
1197
1218
  if (! act.result.error) {
1219
+ // Add success data to the report.
1198
1220
  act.result.success = true;
1199
1221
  act.result.move = 'clicked';
1200
1222
  }
@@ -1263,12 +1285,12 @@ const doActs = async (report, actIndex, page) => {
1263
1285
  }
1264
1286
  // Otherwise, i.e. if no match was found:
1265
1287
  else {
1266
- // Stop.
1288
+ // Quit and add failure data to the report.
1267
1289
  act.result.success = false;
1268
1290
  act.result.error = 'absent';
1269
1291
  act.result.message = 'ERROR: specified element not found';
1270
1292
  console.log('ERROR: Specified element not found');
1271
- actIndex = -2;
1293
+ await abortActs();
1272
1294
  }
1273
1295
  }
1274
1296
  // Otherwise, if the act is a keypress:
@@ -1460,18 +1482,18 @@ const doActs = async (report, actIndex, page) => {
1460
1482
  }
1461
1483
  // Otherwise, i.e. if the command is invalid:
1462
1484
  else {
1463
- // Add an error result to the act.
1485
+ // Quit and add error data to the report.
1464
1486
  const errorMsg = `ERROR: Invalid command of type ${act.type}`;
1465
1487
  console.log(errorMsg);
1466
1488
  addError(act, 'badCommand', errorMsg);
1467
- // Quit.
1468
- actIndex = -2;
1489
+ await abortActs();
1469
1490
  }
1470
- // Perform the remaining acts unless the performance of acts has been aborted.
1491
+ // Perform any remaining acts if not aborted.
1471
1492
  await doActs(report, actIndex + 1, page);
1472
1493
  }
1473
- else {
1474
- console.log('No more acts to perform; closing the browser');
1494
+ // Otherwise, if all commands have been performed and the job succeeded:
1495
+ else if (! report.jobData.abortTime) {
1496
+ console.log('Commands completed');
1475
1497
  await browserClose();
1476
1498
  console.log('Browser closed');
1477
1499
  }
@@ -1523,7 +1545,10 @@ const injectLaunches = acts => {
1523
1545
  }
1524
1546
  }
1525
1547
  };
1526
- // Runs a job and adds the results to the report of the job.
1548
+ /*
1549
+ Returns whether an initialized job report is valid and, if so, runs the job and adds the results
1550
+ to the report.
1551
+ */
1527
1552
  exports.doJob = async report => {
1528
1553
  // If the report is valid:
1529
1554
  if(isValidReport(report)) {
@@ -1554,16 +1579,14 @@ exports.doJob = async report => {
1554
1579
  report.jobData.presses = 0;
1555
1580
  report.jobData.amountRead = 0;
1556
1581
  report.jobData.testTimes = [];
1557
- // Recursively perform the specified acts.
1582
+ // Recursively perform the acts and get any page if debugging is on and a job was aborted.
1558
1583
  await doActs(report, 0, null);
1559
1584
  // Add the end time and duration to the report.
1560
1585
  const endTime = new Date();
1561
1586
  report.jobData.endTime = nowString();
1562
1587
  report.jobData.elapsedSeconds = Math.floor((endTime - startTime) / 1000);
1563
- return true;
1564
1588
  }
1565
1589
  else {
1566
1590
  console.log('ERROR: Initialized job report invalid');
1567
- return false;
1568
1591
  }
1569
1592
  };
package/watch.js CHANGED
@@ -96,19 +96,16 @@ const writeDirReport = async report => {
96
96
  const reportName = `${jobID}.json`;
97
97
  await fs.writeFile(`${reportDir}/${reportName}`, reportJSON);
98
98
  console.log(`Report ${reportName} saved`);
99
- return true;
100
99
  }
101
100
  catch(error) {
102
101
  console.log(`ERROR: Failed to write report (${error.message})`);
103
- return false;
104
102
  }
105
103
  }
106
104
  else {
107
105
  console.log('ERROR: Job has no ID');
108
- return false;
109
106
  }
110
107
  };
111
- // Submits a network report.
108
+ // Submits a network report to a server and returns the server response.
112
109
  const writeNetReport = async report => {
113
110
  const ack = await new Promise(resolve => {
114
111
  const wholeURL = `${process.env.PROTOCOL}://${reportURL}`;
@@ -135,12 +132,17 @@ const writeNetReport = async report => {
135
132
  report.agent = agent;
136
133
  request.on('error', error => {
137
134
  console.log(`ERROR submitting job report (${error.message})`);
138
- resolve({});
135
+ resolve({
136
+ error: 'ERROR: Job report submission failed',
137
+ message: error.message
138
+ });
139
139
  });
140
+ // Send the report to the server.
140
141
  request.write(JSON.stringify(report, null, 2));
141
142
  request.end();
142
143
  console.log(`Report ${report.job.id} submitted`);
143
144
  });
145
+ // Return the server response.
144
146
  return ack;
145
147
  };
146
148
  // Archives a job.
@@ -157,8 +159,9 @@ const wait = ms => {
157
159
  }, ms);
158
160
  });
159
161
  };
160
- // Runs a job and returns a report.
162
+ // Runs a job and returns the page.
161
163
  const runJob = async (job, isDirWatch) => {
164
+ // If the job has an ID:
162
165
  const {id} = job;
163
166
  if (id) {
164
167
  try {
@@ -173,7 +176,7 @@ const runJob = async (job, isDirWatch) => {
173
176
  // If a directory was watched:
174
177
  if (isDirWatch) {
175
178
  // Save the report.
176
- return await writeDirReport(report);
179
+ await writeDirReport(report);
177
180
  }
178
181
  // Otherwise, i.e. if the network was watched:
179
182
  else {
@@ -181,25 +184,19 @@ const runJob = async (job, isDirWatch) => {
181
184
  const ack = await writeNetReport(report);
182
185
  if (ack.error) {
183
186
  console.log(JSON.stringify(ack, null, 2));
184
- return false;
185
- }
186
- else {
187
- return true;
188
187
  }
189
188
  }
190
189
  }
190
+ // If the job failed:
191
191
  catch(error) {
192
+ // Report this.
192
193
  console.log(`ERROR: ${error.message}\n${error.stack}`);
193
- return {
194
- error: `ERROR: ${error.message}\n${error.stack}`
195
- };
196
194
  }
197
195
  }
196
+ // Otherwise, i.e. if the job has no ID:
198
197
  else {
198
+ // Report this.
199
199
  console.log('ERROR: Job has no id');
200
- return {
201
- error: 'ERROR: Job has no id'
202
- };
203
200
  }
204
201
  };
205
202
  // Checks for a job, performs it, and submits a report, once or repeatedly.
@@ -225,25 +222,24 @@ exports.cycle = async (isDirWatch, isForever, interval) => {
225
222
  if (job.id) {
226
223
  // Run it and save a report.
227
224
  console.log(`Running job ${job.id}`);
228
- statusOK = await runJob(job, isDirWatch);
225
+ await runJob(job, isDirWatch);
229
226
  console.log(`Job ${job.id} finished`);
230
- if (statusOK) {
231
- // If a directory was watched:
232
- if (isDirWatch) {
233
- // Archive the job.
234
- await archiveJob(job);
235
- console.log(`Job ${job.id} archived`);
236
- }
237
- // If watching was specified for only 1 job, stop.
238
- statusOK = isForever;
239
- // Prevent a wait before the next iteration.
240
- empty = false;
227
+ // If a directory was watched:
228
+ if (isDirWatch) {
229
+ // Archive the job.
230
+ await archiveJob(job);
231
+ console.log(`Job ${job.id} archived`);
241
232
  }
233
+ // If watching was specified for only 1 job, quit.
234
+ statusOK = isForever;
235
+ // Prevent a wait before the next iteration.
236
+ empty = false;
242
237
  }
238
+ // Otherwise, i.e. if no job was found:
243
239
  else {
240
+ // Cause a wait before the next check.
244
241
  empty = true;
245
242
  }
246
243
  }
247
244
  console.log('Watching ended');
248
- return '';
249
245
  };