testaro 8.4.6 → 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.
- package/README.md +45 -39
- package/package.json +1 -1
- package/run.js +60 -37
- package/watch.js +26 -30
package/README.md
CHANGED
|
@@ -362,9 +362,53 @@ An example of a **Testaro-defined** test is:
|
|
|
362
362
|
|
|
363
363
|
In this case, Testaro runs the `motion` test with the specified parameters.
|
|
364
364
|
|
|
365
|
+
###### Continuum
|
|
366
|
+
|
|
367
|
+
The `continuum` packaged test makes use of the files in the `continuum` directory. The test inserts the contents of all three files into the page as scripts and then uses them to perform the tests of the Continuum package.
|
|
368
|
+
|
|
369
|
+
Level Access on 22 August 2022 granted authorization for the copying of the `AccessEngine.community.js` file insofar as necessary for allowing Continuum community edition tests to be included in Testaro.
|
|
370
|
+
|
|
371
|
+
###### IBM Equal Access
|
|
372
|
+
|
|
373
|
+
The `ibm` packaged test requires the `aceconfig.js` file.
|
|
374
|
+
|
|
375
|
+
If you choose to invoke this packaged test with the `withNewContent` property specified, you will choose whether the tested content is the content of the existing page or is retrieved anew with the document URL. Typically, both methods succeed and deliver similar results. However, sometimes one method succeeds and the other fails, or one method reports more violations than the other does. In those cases, most often the success, or the larger violation count, arises from the existing page (`withNewContent: false`).
|
|
376
|
+
|
|
377
|
+
###### HTML CodeSniffer
|
|
378
|
+
|
|
379
|
+
The `htmlcs` packaged test makes use of the`htmlcs/HTMLCS.js` file. That file was created, and can be recreated if necessary, as follows:
|
|
380
|
+
|
|
381
|
+
1. Clone the (HTML CodeSniffer package)[https://github.com/squizlabs/HTML_CodeSniffer].
|
|
382
|
+
1. Make that package’s directory the active directory.
|
|
383
|
+
1. Install the HTML CodeSniffer dependencies by executing `npm install`.
|
|
384
|
+
1. Build the HTML CodeSniffer auditor by executing `grunt build`.
|
|
385
|
+
1. Copy the `build/HTMLCS.js` and `build/licence.txt` files into the `htmlcs` directory of Testaro.
|
|
386
|
+
1. Edit the Testaro copy of `htmlcs/HTMLCS.js` to produce the changes shown below.
|
|
387
|
+
|
|
388
|
+
The changes in `htmlcs/HTMLCS.js` are:
|
|
389
|
+
|
|
390
|
+
```diff
|
|
391
|
+
479a480
|
|
392
|
+
> '4_1_2_attribute': 'attribute',
|
|
393
|
+
6482a6484
|
|
394
|
+
> var messageStrings = new Set();
|
|
395
|
+
6496d6497
|
|
396
|
+
< console.log('done');
|
|
397
|
+
6499d6499
|
|
398
|
+
< console.log('done');
|
|
399
|
+
6500a6501
|
|
400
|
+
> return Array.from(messageStrings);
|
|
401
|
+
6531c6532,6534
|
|
402
|
+
< console.log('[HTMLCS] ' + typeName + '|' + msg.code + '|' + nodeName + '|' + elementId + '|' + msg.msg + '|' + html);
|
|
403
|
+
---
|
|
404
|
+
> messageStrings.add(
|
|
405
|
+
> typeName + '|' + msg.code + '|' + nodeName + '|' + elementId + '|' + msg.msg + '|' + html
|
|
406
|
+
> );
|
|
407
|
+
```
|
|
408
|
+
|
|
365
409
|
###### Tenon
|
|
366
410
|
|
|
367
|
-
Most packaged tests require only one command, but the `tenon` test requires two commands:
|
|
411
|
+
Most packaged tests require only one command, but the `tenon` packaged test requires two commands:
|
|
368
412
|
- A command of type `tenonRequest`.
|
|
369
413
|
- A command of type `test` with `tenon` as the value of `which`.
|
|
370
414
|
|
|
@@ -404,44 +448,6 @@ Tenon recommends giving it a public URL rather than giving it the content of a p
|
|
|
404
448
|
|
|
405
449
|
If a `tenon` test is included in a job, environment variables named `TENON_USER` and `TENON_PASSWORD` must exist, with your Tenon username and password, respectively, as their values. You can obtain those from [Tenon](https://tenon.io/documentation/overview).
|
|
406
450
|
|
|
407
|
-
###### Continuum
|
|
408
|
-
|
|
409
|
-
The `continuum` test makes use of the files in the `continuum` directory. The test inserts the contents of all three files into the page as scripts and then uses them to perform the tests of the Continuum package.
|
|
410
|
-
|
|
411
|
-
Level Access on 22 August 2022 granted authorization for the copying of the `AccessEngine.community.js` file insofar as necessary for allowing Continuum community edition tests to be included in Testaro.
|
|
412
|
-
|
|
413
|
-
###### HTML CodeSniffer
|
|
414
|
-
|
|
415
|
-
The `htmlcs` test makes use of the`htmlcs/HTMLCS.js` file. That file was created, and can be recreated if necessary, as follows:
|
|
416
|
-
|
|
417
|
-
1. Clone the (HTML CodeSniffer package)[https://github.com/squizlabs/HTML_CodeSniffer].
|
|
418
|
-
1. Make that package’s directory the active directory.
|
|
419
|
-
1. Install the HTML CodeSniffer dependencies by executing `npm install`.
|
|
420
|
-
1. Build the HTML CodeSniffer auditor by executing `grunt build`.
|
|
421
|
-
1. Copy the `build/HTMLCS.js` and `build/licence.txt` files into the `htmlcs` directory of Testaro.
|
|
422
|
-
1. Edit the Testaro copy of `htmlcs/HTMLCS.js` to produce the changes shown below.
|
|
423
|
-
|
|
424
|
-
The changes in `htmlcs/HTMLCS.js` are:
|
|
425
|
-
|
|
426
|
-
```diff
|
|
427
|
-
479a480
|
|
428
|
-
> '4_1_2_attribute': 'attribute',
|
|
429
|
-
6482a6484
|
|
430
|
-
> var messageStrings = new Set();
|
|
431
|
-
6496d6497
|
|
432
|
-
< console.log('done');
|
|
433
|
-
6499d6499
|
|
434
|
-
< console.log('done');
|
|
435
|
-
6500a6501
|
|
436
|
-
> return Array.from(messageStrings);
|
|
437
|
-
6531c6532,6534
|
|
438
|
-
< console.log('[HTMLCS] ' + typeName + '|' + msg.code + '|' + nodeName + '|' + elementId + '|' + msg.msg + '|' + html);
|
|
439
|
-
---
|
|
440
|
-
> messageStrings.add(
|
|
441
|
-
> typeName + '|' + msg.code + '|' + nodeName + '|' + elementId + '|' + msg.msg + '|' + html
|
|
442
|
-
> );
|
|
443
|
-
```
|
|
444
|
-
|
|
445
451
|
###### WAVE
|
|
446
452
|
|
|
447
453
|
If a `wave` test is included in the job, an environment variable named `WAVE_KEY` must exist, with your WAVE API key as its value. You can get it from [WebAIM](https://wave.webaim.org/api/).
|
package/package.json
CHANGED
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 =
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
1468
|
-
actIndex = -2;
|
|
1489
|
+
await abortActs();
|
|
1469
1490
|
}
|
|
1470
|
-
// Perform
|
|
1491
|
+
// Perform any remaining acts if not aborted.
|
|
1471
1492
|
await doActs(report, actIndex + 1, page);
|
|
1472
1493
|
}
|
|
1473
|
-
|
|
1474
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
225
|
+
await runJob(job, isDirWatch);
|
|
229
226
|
console.log(`Job ${job.id} finished`);
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
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
|
};
|