testaro 8.5.2 → 9.0.0
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 +94 -155
- package/{commands.js → actSpecs.js} +1 -1
- package/call.js +35 -13
- package/package.json +2 -3
- package/run.js +99 -148
- package/samples/00000-ts18-example.json +3 -3
- package/validation/executors/run.js +40 -0
- package/validation/executors/watchDir.js +7 -6
- package/validation/executors/watchNet.js +5 -6
- package/validation/jobs/done/README.md +3 -0
- package/validation/jobs/{00000-simple-example.json → todo/00000-simple-example.json} +6 -7
- package/validation/jobs/{README.md → todo/README.md} +0 -0
- package/validation/tests/jobs/allHidden.json +3 -2
- package/validation/tests/jobs/bulk.json +3 -2
- package/validation/tests/jobs/docType.json +3 -2
- package/validation/tests/jobs/elements.json +3 -2
- package/validation/tests/jobs/embAc.json +3 -2
- package/validation/tests/jobs/filter.json +3 -2
- package/validation/tests/jobs/focAll.json +3 -2
- package/validation/tests/jobs/focInd.json +3 -2
- package/validation/tests/jobs/focOp.json +3 -2
- package/validation/tests/jobs/focVis.json +3 -2
- package/validation/tests/jobs/hover.json +3 -2
- package/validation/tests/jobs/labClash.json +3 -2
- package/validation/tests/jobs/linkTo.json +3 -2
- package/validation/tests/jobs/linkUl.json +3 -2
- package/validation/tests/jobs/menuNav.json +3 -2
- package/validation/tests/jobs/miniText.json +3 -2
- package/validation/tests/jobs/motion.json +3 -2
- package/validation/tests/jobs/nonTable.json +3 -2
- package/validation/tests/jobs/radioSet.json +3 -2
- package/validation/tests/jobs/role.json +3 -2
- package/validation/tests/jobs/styleDiff.json +3 -2
- package/validation/tests/jobs/tabNav.json +3 -2
- package/validation/tests/jobs/textNodes.json +3 -2
- package/validation/tests/jobs/title.json +3 -2
- package/validation/tests/jobs/titledEl.json +3 -2
- package/validation/tests/jobs/zIndex.json +3 -2
- package/validation/validateTest.js +3 -8
- package/validation/watch/{README.md → done/README.md} +0 -0
- package/validation/watch/todo/README.md +3 -0
- package/watch.js +16 -22
- package/high.js +0 -60
- package/validation/executors/high.js +0 -52
- package/validation/executors/low.js +0 -53
package/run.js
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
|
|
8
8
|
// Module to keep secrets.
|
|
9
9
|
require('dotenv').config();
|
|
10
|
-
// Requirements for
|
|
11
|
-
const {
|
|
10
|
+
// Requirements for acts.
|
|
11
|
+
const {actSpecs} = require('./actSpecs');
|
|
12
12
|
// Playwright package.
|
|
13
13
|
const playwright = require('playwright');
|
|
14
14
|
|
|
@@ -18,7 +18,6 @@ const playwright = require('playwright');
|
|
|
18
18
|
const debug = process.env.DEBUG === 'true';
|
|
19
19
|
// Set WAITS environment variable to a positive number to insert delays (in ms).
|
|
20
20
|
const waits = Number.parseInt(process.env.WAITS) || 0;
|
|
21
|
-
const urlInject = process.env.URL_INJECT || 'yes';
|
|
22
21
|
// CSS selectors for targets of moves.
|
|
23
22
|
const moves = {
|
|
24
23
|
button: 'button, [role=button], input[type=submit]',
|
|
@@ -68,20 +67,6 @@ const tests = {
|
|
|
68
67
|
wave: 'WAVE',
|
|
69
68
|
zIndex: 'z indexes'
|
|
70
69
|
};
|
|
71
|
-
// Tests that may change the DOM.
|
|
72
|
-
const domChangers = new Set([
|
|
73
|
-
'axe',
|
|
74
|
-
'continuum',
|
|
75
|
-
'focAll',
|
|
76
|
-
'focInd',
|
|
77
|
-
'focOp',
|
|
78
|
-
'hover',
|
|
79
|
-
'htmlcs',
|
|
80
|
-
'ibm',
|
|
81
|
-
'menuNav',
|
|
82
|
-
'textNodes',
|
|
83
|
-
'wave'
|
|
84
|
-
]);
|
|
85
70
|
// Browser types available in PlayWright.
|
|
86
71
|
const browserTypeNames = {
|
|
87
72
|
'chromium': 'Chrome',
|
|
@@ -189,24 +174,24 @@ const hasSubtype = (variable, subtype) => {
|
|
|
189
174
|
return true;
|
|
190
175
|
}
|
|
191
176
|
};
|
|
192
|
-
// Validates
|
|
193
|
-
const
|
|
194
|
-
// Identify the type of the
|
|
195
|
-
const type =
|
|
177
|
+
// Validates an act.
|
|
178
|
+
const isValidAct = act => {
|
|
179
|
+
// Identify the type of the act.
|
|
180
|
+
const type = act.type;
|
|
196
181
|
// If the type exists and is known:
|
|
197
|
-
if (type &&
|
|
182
|
+
if (type && actSpecs.etc[type]) {
|
|
198
183
|
// Copy the validator of the type for possible expansion.
|
|
199
|
-
const validator = Object.assign({},
|
|
184
|
+
const validator = Object.assign({}, actSpecs.etc[type][1]);
|
|
200
185
|
// If the type is test:
|
|
201
186
|
if (type === 'test') {
|
|
202
187
|
// Identify the test.
|
|
203
|
-
const testName =
|
|
188
|
+
const testName = act.which;
|
|
204
189
|
// If one was specified and is known:
|
|
205
190
|
if (testName && tests[testName]) {
|
|
206
191
|
// If it has special properties:
|
|
207
|
-
if (
|
|
192
|
+
if (actSpecs.tests[testName]) {
|
|
208
193
|
// Expand the validator by adding them.
|
|
209
|
-
Object.assign(validator,
|
|
194
|
+
Object.assign(validator, actSpecs.tests[testName][1]);
|
|
210
195
|
}
|
|
211
196
|
}
|
|
212
197
|
// Otherwise, i.e. if no or an unknown test was specified:
|
|
@@ -215,22 +200,22 @@ const isValidCommand = command => {
|
|
|
215
200
|
return false;
|
|
216
201
|
}
|
|
217
202
|
}
|
|
218
|
-
// Return whether the
|
|
203
|
+
// Return whether the act is valid.
|
|
219
204
|
return Object.keys(validator).every(property => {
|
|
220
205
|
if (property === 'name') {
|
|
221
206
|
return true;
|
|
222
207
|
}
|
|
223
208
|
else {
|
|
224
209
|
const vP = validator[property];
|
|
225
|
-
const
|
|
226
|
-
// If it is optional and omitted or present and valid:
|
|
227
|
-
const optAndNone = ! vP[0] && !
|
|
228
|
-
const
|
|
229
|
-
return optAndNone ||
|
|
210
|
+
const aP = act[property];
|
|
211
|
+
// If it is optional and omitted or is present and valid:
|
|
212
|
+
const optAndNone = ! vP[0] && ! aP;
|
|
213
|
+
const isValidAct = aP !== undefined && hasType(aP, vP[1]) && hasSubtype(aP, vP[2]);
|
|
214
|
+
return optAndNone || isValidAct;
|
|
230
215
|
}
|
|
231
216
|
});
|
|
232
217
|
}
|
|
233
|
-
// Otherwise, i.e. if the
|
|
218
|
+
// Otherwise, i.e. if the act has an unknown or no type:
|
|
234
219
|
else {
|
|
235
220
|
// Return invalidity.
|
|
236
221
|
return false;
|
|
@@ -240,42 +225,60 @@ const isValidCommand = command => {
|
|
|
240
225
|
const isValidReport = report => {
|
|
241
226
|
if (report) {
|
|
242
227
|
// Return whether the report is valid.
|
|
243
|
-
const {
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
[job, 'report has job property'],
|
|
247
|
-
[acts, 'report has acts property'],
|
|
248
|
-
[jobData, 'report has jobData property'],
|
|
249
|
-
[id, 'job has id property'],
|
|
250
|
-
[what, 'job has what property'],
|
|
251
|
-
[typeof strict === 'boolean', 'job has true or false strict property'],
|
|
252
|
-
[commands, 'job has commands property'],
|
|
253
|
-
[sources, 'job has sources property'],
|
|
254
|
-
[jobCreationTime, 'job has jobCreationTime property'],
|
|
255
|
-
[timeStamp, 'job has timeStamp property'],
|
|
256
|
-
[Array.isArray(acts), 'acts has array value'],
|
|
257
|
-
[typeof id === 'string', 'id has string value'],
|
|
258
|
-
[typeof what === 'string', 'what has string value'],
|
|
259
|
-
[Array.isArray(commands), 'commands has array value'],
|
|
260
|
-
[commands[0].type, 'first command has type property'],
|
|
261
|
-
[commands[0].type === 'launch', 'first command has launch type'],
|
|
262
|
-
[commands.length > 1, 'command count greater than 1'],
|
|
263
|
-
[commands[1].type, 'second command has type property'],
|
|
264
|
-
[commands[1].type === 'url', 'second command has url type'],
|
|
265
|
-
[commands[1].which, 'second command has which property'],
|
|
266
|
-
[isURL(commands[1].which), 'second command which property has URL value'],
|
|
267
|
-
[commands.every(command => isValidCommand(command)), 'every command is valid'],
|
|
268
|
-
[sources && typeof sources.script === 'string', 'sources has script property with string value'],
|
|
269
|
-
[sources && sources.host, 'sources has host property']
|
|
270
|
-
];
|
|
271
|
-
const invalidityIndex = criteria.findIndex(criterion => ! criterion[0]);
|
|
272
|
-
if (invalidityIndex > -1) {
|
|
273
|
-
console.log(`ERROR: report fails “${criteria[invalidityIndex][1]}” requirement`);
|
|
228
|
+
const {id, what, strict, timeLimit, acts, sources, creationTime, timeStamp} = report;
|
|
229
|
+
if (! id || typeof id !== 'string') {
|
|
230
|
+
return 'Bad report ID';
|
|
274
231
|
}
|
|
275
|
-
|
|
232
|
+
if (! what || typeof what !== 'string') {
|
|
233
|
+
return 'Bad report what';
|
|
234
|
+
}
|
|
235
|
+
if (! strict || typeof strict !== 'boolean') {
|
|
236
|
+
return 'Bad report strict';
|
|
237
|
+
}
|
|
238
|
+
if (! timeLimit || typeof timeLimit !== 'number' || timeLimit < 1) {
|
|
239
|
+
return 'Bad report time limit';
|
|
240
|
+
}
|
|
241
|
+
if (! acts || ! Array.isArray(acts) || acts.length < 2) {
|
|
242
|
+
return 'Bad report acts';
|
|
243
|
+
}
|
|
244
|
+
if (! acts.every(act => act.type && typeof act.type === 'string')) {
|
|
245
|
+
return 'Act with no type';
|
|
246
|
+
}
|
|
247
|
+
if (acts[0].type !== 'launch') {
|
|
248
|
+
return 'First act type not launch';
|
|
249
|
+
}
|
|
250
|
+
if (acts[1].type !== 'url') {
|
|
251
|
+
return 'Second act type not url';
|
|
252
|
+
}
|
|
253
|
+
if (! ['chromium', 'webkit', 'firefox'].includes(acts[0].which)) {
|
|
254
|
+
return 'Bad first act which';
|
|
255
|
+
}
|
|
256
|
+
if (! acts[1].which || typeof acts[1].which !== 'string' || ! isURL(acts[1].which)) {
|
|
257
|
+
return 'Second act which not a URL';
|
|
258
|
+
}
|
|
259
|
+
if (acts.some(act => ! isValidAct(act))) {
|
|
260
|
+
return 'Not all acts valid';
|
|
261
|
+
}
|
|
262
|
+
if (! sources || typeof sources !== 'object') {
|
|
263
|
+
return 'Bad report sources';
|
|
264
|
+
}
|
|
265
|
+
if (typeof sources.script !== 'string') {
|
|
266
|
+
return 'Bad sources script';
|
|
267
|
+
}
|
|
268
|
+
if (
|
|
269
|
+
! creationTime
|
|
270
|
+
|| typeof creationTime !== 'string'
|
|
271
|
+
|| ! /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$/.test(creationTime)
|
|
272
|
+
) {
|
|
273
|
+
return 'bad job creation time';
|
|
274
|
+
}
|
|
275
|
+
if (! timeStamp || typeof timeStamp !== 'string') {
|
|
276
|
+
return 'bad report timestamp';
|
|
277
|
+
}
|
|
278
|
+
return '';
|
|
276
279
|
}
|
|
277
280
|
else {
|
|
278
|
-
return
|
|
281
|
+
return 'no report';
|
|
279
282
|
}
|
|
280
283
|
};
|
|
281
284
|
|
|
@@ -608,10 +611,10 @@ const goTo = async (report, page, url, timeout, waitUntil, isStrict) => {
|
|
|
608
611
|
const doActs = async (report, actIndex, page) => {
|
|
609
612
|
// Quits and reports the performance being aborted.
|
|
610
613
|
const abortActs = async () => {
|
|
611
|
-
// Add data on the aborted
|
|
614
|
+
// Add data on the aborted act to the report.
|
|
612
615
|
report.jobData.abortTime = nowString();
|
|
613
616
|
report.jobData.abortedAct = actIndex;
|
|
614
|
-
// Prevent performance of additional
|
|
617
|
+
// Prevent performance of additional acts.
|
|
615
618
|
actIndex = -2;
|
|
616
619
|
// Report this.
|
|
617
620
|
console.log('ERROR: Job aborted');
|
|
@@ -625,18 +628,18 @@ const doActs = async (report, actIndex, page) => {
|
|
|
625
628
|
}
|
|
626
629
|
});
|
|
627
630
|
const {acts} = report;
|
|
628
|
-
// If any more
|
|
631
|
+
// If any more acts are to be performed:
|
|
629
632
|
if (actIndex > -1 && actIndex < acts.length) {
|
|
630
|
-
// Identify the
|
|
633
|
+
// Identify the act to be performed.
|
|
631
634
|
const act = acts[actIndex];
|
|
632
635
|
// If it is valid:
|
|
633
|
-
if (
|
|
636
|
+
if (isValidAct(act)) {
|
|
634
637
|
const whichSuffix = act.which ? ` (${act.which})` : '';
|
|
635
638
|
console.log(`>>>> ${act.type}${whichSuffix}`);
|
|
636
|
-
// Increment the count of
|
|
639
|
+
// Increment the count of acts performed.
|
|
637
640
|
actCount++;
|
|
638
641
|
act.startTime = Date.now();
|
|
639
|
-
// If the
|
|
642
|
+
// If the act is an index changer:
|
|
640
643
|
if (act.type === 'next') {
|
|
641
644
|
const condition = act.if;
|
|
642
645
|
const logSuffix = condition.length === 3 ? ` ${condition[1]} ${condition[2]}` : '';
|
|
@@ -655,7 +658,7 @@ const doActs = async (report, actIndex, page) => {
|
|
|
655
658
|
};
|
|
656
659
|
// If the condition is true:
|
|
657
660
|
if (truth[1]) {
|
|
658
|
-
// If the performance of
|
|
661
|
+
// If the performance of acts is to stop:
|
|
659
662
|
if (act.jump === 0) {
|
|
660
663
|
// Quit.
|
|
661
664
|
actIndex = -2;
|
|
@@ -665,14 +668,14 @@ const doActs = async (report, actIndex, page) => {
|
|
|
665
668
|
// Set the act index accordingly.
|
|
666
669
|
actIndex += act.jump - 1;
|
|
667
670
|
}
|
|
668
|
-
// Otherwise, if there is a named next
|
|
671
|
+
// Otherwise, if there is a named next act:
|
|
669
672
|
else if (act.next) {
|
|
670
673
|
// Set the new index accordingly, or stop if it does not exist.
|
|
671
674
|
actIndex = acts.map(act => act.name).indexOf(act.next) - 1;
|
|
672
675
|
}
|
|
673
676
|
}
|
|
674
677
|
}
|
|
675
|
-
// Otherwise, if the
|
|
678
|
+
// Otherwise, if the act is a launch:
|
|
676
679
|
else if (act.type === 'launch') {
|
|
677
680
|
// Launch the specified browser, creating a browser context and a page in it.
|
|
678
681
|
await launch(report, act.which, act.lowMotion ? 'reduce' : 'no-preference');
|
|
@@ -681,13 +684,13 @@ const doActs = async (report, actIndex, page) => {
|
|
|
681
684
|
}
|
|
682
685
|
// Otherwise, if a current page exists:
|
|
683
686
|
else if (page) {
|
|
684
|
-
// If the
|
|
687
|
+
// If the act is a url:
|
|
685
688
|
if (act.type === 'url') {
|
|
686
689
|
// Identify the URL.
|
|
687
690
|
const resolved = act.which.replace('__dirname', __dirname);
|
|
688
691
|
requestedURL = resolved;
|
|
689
692
|
// Visit it and wait until the network is idle.
|
|
690
|
-
const {strict} = report
|
|
693
|
+
const {strict} = report;
|
|
691
694
|
let response = await goTo(report, page, requestedURL, 15000, 'networkidle', strict);
|
|
692
695
|
// If the visit fails:
|
|
693
696
|
if (response.error) {
|
|
@@ -851,8 +854,10 @@ const doActs = async (report, actIndex, page) => {
|
|
|
851
854
|
// Otherwise, if the page has a URL:
|
|
852
855
|
else if (page.url() && page.url() !== 'about:blank') {
|
|
853
856
|
const url = page.url();
|
|
854
|
-
// If redirection is permitted or did not occur:
|
|
855
|
-
if (
|
|
857
|
+
// If redirection is inapplicable, is permitted, or did not occur:
|
|
858
|
+
if (
|
|
859
|
+
url.startsWith('file:') || ! report.strict || deSlash(url) === deSlash(requestedURL)
|
|
860
|
+
) {
|
|
856
861
|
// Add the URL to the act.
|
|
857
862
|
act.url = url;
|
|
858
863
|
// If the act is a revelation:
|
|
@@ -983,7 +988,7 @@ const doActs = async (report, actIndex, page) => {
|
|
|
983
988
|
// Initialize the arguments.
|
|
984
989
|
const args = [act.which === 'tenon' ? tenonData : page];
|
|
985
990
|
// Identify the additional validator of the test.
|
|
986
|
-
const testValidator =
|
|
991
|
+
const testValidator = actSpecs.tests[act.which];
|
|
987
992
|
// If it exists:
|
|
988
993
|
if (testValidator) {
|
|
989
994
|
// Identify its argument properties.
|
|
@@ -1245,7 +1250,7 @@ const doActs = async (report, actIndex, page) => {
|
|
|
1245
1250
|
act.result.move = 'selected';
|
|
1246
1251
|
act.result.option = optionText;
|
|
1247
1252
|
}
|
|
1248
|
-
// Otherwise, if it is entering text
|
|
1253
|
+
// Otherwise, if it is entering text in an input element:
|
|
1249
1254
|
else if (['text', 'search'].includes(act.type)) {
|
|
1250
1255
|
act.result.attributes = {};
|
|
1251
1256
|
const {attributes} = act.result;
|
|
@@ -1458,7 +1463,7 @@ const doActs = async (report, actIndex, page) => {
|
|
|
1458
1463
|
// Otherwise, i.e. if the act type is unknown:
|
|
1459
1464
|
else {
|
|
1460
1465
|
// Add the error result to the act.
|
|
1461
|
-
addError(act, 'badType', 'ERROR: Invalid
|
|
1466
|
+
addError(act, 'badType', 'ERROR: Invalid act type');
|
|
1462
1467
|
}
|
|
1463
1468
|
}
|
|
1464
1469
|
// Otherwise, i.e. if redirection is prohibited but occurred:
|
|
@@ -1480,88 +1485,37 @@ const doActs = async (report, actIndex, page) => {
|
|
|
1480
1485
|
}
|
|
1481
1486
|
act.endTime = Date.now();
|
|
1482
1487
|
}
|
|
1483
|
-
// Otherwise, i.e. if the
|
|
1488
|
+
// Otherwise, i.e. if the act is invalid:
|
|
1484
1489
|
else {
|
|
1485
1490
|
// Quit and add error data to the report.
|
|
1486
|
-
const errorMsg = `ERROR: Invalid
|
|
1491
|
+
const errorMsg = `ERROR: Invalid act of type ${act.type}`;
|
|
1487
1492
|
console.log(errorMsg);
|
|
1488
|
-
addError(act, '
|
|
1493
|
+
addError(act, 'badAct', errorMsg);
|
|
1489
1494
|
await abortActs();
|
|
1490
1495
|
}
|
|
1491
1496
|
// Perform any remaining acts if not aborted.
|
|
1492
1497
|
await doActs(report, actIndex + 1, page);
|
|
1493
1498
|
}
|
|
1494
|
-
// Otherwise, if all
|
|
1499
|
+
// Otherwise, if all acts have been performed and the job succeeded:
|
|
1495
1500
|
else if (! report.jobData.abortTime) {
|
|
1496
|
-
console.log('
|
|
1501
|
+
console.log('Acts completed');
|
|
1497
1502
|
await browserClose();
|
|
1498
1503
|
console.log('Browser closed');
|
|
1499
1504
|
}
|
|
1500
1505
|
};
|
|
1501
|
-
// Injects launch and url acts into a report where necessary to undo DOM changes.
|
|
1502
|
-
const injectLaunches = acts => {
|
|
1503
|
-
let injectMore = true;
|
|
1504
|
-
while (injectMore) {
|
|
1505
|
-
const injectIndex = acts.findIndex((act, index) =>
|
|
1506
|
-
index < acts.length - 1
|
|
1507
|
-
&& act.type === 'test'
|
|
1508
|
-
&& acts[index + 1].type === 'test'
|
|
1509
|
-
&& domChangers.has(act.which)
|
|
1510
|
-
);
|
|
1511
|
-
if (injectIndex === -1) {
|
|
1512
|
-
injectMore = false;
|
|
1513
|
-
}
|
|
1514
|
-
else {
|
|
1515
|
-
const lastBrowserType = acts.reduce((browserType, act, index) => {
|
|
1516
|
-
if (act.type === 'launch' && index < injectIndex) {
|
|
1517
|
-
return act.which;
|
|
1518
|
-
}
|
|
1519
|
-
else {
|
|
1520
|
-
return browserType;
|
|
1521
|
-
}
|
|
1522
|
-
}, '');
|
|
1523
|
-
const lastURL = acts.reduce((url, act, index) => {
|
|
1524
|
-
if (act.type === 'url' && index < injectIndex) {
|
|
1525
|
-
return act.which;
|
|
1526
|
-
}
|
|
1527
|
-
else {
|
|
1528
|
-
return url;
|
|
1529
|
-
}
|
|
1530
|
-
}, '');
|
|
1531
|
-
acts.splice(
|
|
1532
|
-
injectIndex + 1,
|
|
1533
|
-
0,
|
|
1534
|
-
{
|
|
1535
|
-
type: 'launch',
|
|
1536
|
-
which: lastBrowserType,
|
|
1537
|
-
what: `${lastBrowserType} browser`
|
|
1538
|
-
},
|
|
1539
|
-
{
|
|
1540
|
-
type: 'url',
|
|
1541
|
-
which: lastURL,
|
|
1542
|
-
what: 'URL'
|
|
1543
|
-
}
|
|
1544
|
-
);
|
|
1545
|
-
}
|
|
1546
|
-
}
|
|
1547
|
-
};
|
|
1548
1506
|
/*
|
|
1549
1507
|
Returns whether an initialized job report is valid and, if so, runs the job and adds the results
|
|
1550
1508
|
to the report.
|
|
1551
1509
|
*/
|
|
1552
1510
|
exports.doJob = async report => {
|
|
1553
1511
|
// If the report is valid:
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
Injection of url acts alone does not guarantee test independence.
|
|
1560
|
-
*/
|
|
1561
|
-
if (urlInject === 'yes') {
|
|
1562
|
-
injectLaunches(report.acts);
|
|
1563
|
-
}
|
|
1512
|
+
const reportInvalidity = isValidReport(report);
|
|
1513
|
+
if (reportInvalidity) {
|
|
1514
|
+
console.log(reportInvalidity);
|
|
1515
|
+
}
|
|
1516
|
+
else {
|
|
1564
1517
|
// Add initialized job data to the report.
|
|
1518
|
+
report.jobData = {};
|
|
1565
1519
|
const startTime = new Date();
|
|
1566
1520
|
report.jobData.startTime = nowString();
|
|
1567
1521
|
report.jobData.endTime = '';
|
|
@@ -1586,7 +1540,4 @@ exports.doJob = async report => {
|
|
|
1586
1540
|
report.jobData.endTime = nowString();
|
|
1587
1541
|
report.jobData.elapsedSeconds = Math.floor((endTime - startTime) / 1000);
|
|
1588
1542
|
}
|
|
1589
|
-
else {
|
|
1590
|
-
console.log('ERROR: Initialized job report invalid');
|
|
1591
|
-
}
|
|
1592
1543
|
};
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
},
|
|
12
12
|
{
|
|
13
13
|
"type": "url",
|
|
14
|
-
"which": "https://example.
|
|
14
|
+
"which": "https://example.edu",
|
|
15
15
|
"what": "Example.com",
|
|
16
16
|
"id": "example"
|
|
17
17
|
},
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
},
|
|
37
37
|
{
|
|
38
38
|
"type": "url",
|
|
39
|
-
"which": "https://example.
|
|
39
|
+
"which": "https://example.edu",
|
|
40
40
|
"what": "Example.com",
|
|
41
41
|
"id": "example"
|
|
42
42
|
},
|
|
@@ -221,7 +221,7 @@
|
|
|
221
221
|
"batch": "",
|
|
222
222
|
"host": {
|
|
223
223
|
"id": "example",
|
|
224
|
-
"which": "https://example.
|
|
224
|
+
"which": "https://example.edu",
|
|
225
225
|
"what": "Example.com"
|
|
226
226
|
},
|
|
227
227
|
"requester": "user@domain.tld"
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// run.js
|
|
2
|
+
// Validator for immediate job execution.
|
|
3
|
+
|
|
4
|
+
// ########## IMPORTS
|
|
5
|
+
|
|
6
|
+
const fs = require('fs/promises');
|
|
7
|
+
|
|
8
|
+
// ########## CONSTANTS
|
|
9
|
+
|
|
10
|
+
const {doJob} = require('../../run');
|
|
11
|
+
const jobID = '00000-simple-example';
|
|
12
|
+
|
|
13
|
+
// ########## OPERATION
|
|
14
|
+
|
|
15
|
+
// Get the simple job.
|
|
16
|
+
fs.readFile(`${__dirname}/../jobs/todo/${jobID}.json`, 'utf8')
|
|
17
|
+
.then(async jobJSON => {
|
|
18
|
+
const report = JSON.parse(jobJSON);
|
|
19
|
+
// Run it.
|
|
20
|
+
await doJob(report);
|
|
21
|
+
try {
|
|
22
|
+
// Check the report against expectations.
|
|
23
|
+
const {acts, jobData} = report;
|
|
24
|
+
if (acts.length !== 3) {
|
|
25
|
+
console.log('Failure: Counts of acts is not 3');
|
|
26
|
+
}
|
|
27
|
+
else if (! jobData) {
|
|
28
|
+
console.log('Failure: Report omits jobData');
|
|
29
|
+
}
|
|
30
|
+
else if (jobData.endTime < jobData.startTime) {
|
|
31
|
+
console.log('Failure: End time precedes start time');
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
console.log('Success');
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
catch(error) {
|
|
38
|
+
console.log(`ERROR: ${error.message}`);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
@@ -10,18 +10,19 @@ const fs = require('fs/promises');
|
|
|
10
10
|
// Override cycle environment variables with validation-specific ones.
|
|
11
11
|
process.env.PROTOCOL = 'http';
|
|
12
12
|
process.env.JOBDIR = `${__dirname}/../watch`;
|
|
13
|
-
process.env.DONEDIR = `${__dirname}/../done`;
|
|
14
13
|
process.env.REPORTDIR = `${__dirname}/../../temp`;
|
|
15
14
|
const jobID = '00000-simple-example';
|
|
16
|
-
const {cycle} = require(
|
|
15
|
+
const {cycle} = require('../../watch');
|
|
17
16
|
|
|
18
17
|
// Start checking for jobs every 5 seconds.
|
|
19
18
|
cycle(true, false, 5)
|
|
20
19
|
.then(() => {
|
|
21
|
-
console.log('Watch validation ended');
|
|
20
|
+
console.log('Success: Watch validation ended');
|
|
22
21
|
});
|
|
23
|
-
//
|
|
22
|
+
// Make a job available after 7 seconds.
|
|
24
23
|
setTimeout(() => {
|
|
25
|
-
fs.copyFile(
|
|
26
|
-
|
|
24
|
+
fs.copyFile(
|
|
25
|
+
`${__dirname}/../jobs/todo/${jobID}.json`, `${process.env.JOBDIR}/todo/${jobID}.json`
|
|
26
|
+
);
|
|
27
|
+
console.log('Job made available after 7 seconds');
|
|
27
28
|
}, 7000);
|
|
@@ -9,11 +9,11 @@ const fs = require('fs/promises');
|
|
|
9
9
|
|
|
10
10
|
// Override cycle environment variables with validation-specific ones.
|
|
11
11
|
process.env.PROTOCOL = 'http';
|
|
12
|
-
const jobDir = `${__dirname}/../jobs`;
|
|
12
|
+
const jobDir = `${__dirname}/../jobs/todo`;
|
|
13
13
|
process.env.JOB_URL = 'localhost:3007/api/job';
|
|
14
14
|
process.env.REPORT_URL = 'localhost:3007/api';
|
|
15
15
|
process.env.AGENT = 'testarauth';
|
|
16
|
-
const {cycle} = require(
|
|
16
|
+
const {cycle} = require('../../watch');
|
|
17
17
|
const client = require(process.env.PROTOCOL);
|
|
18
18
|
const jobID = '00000-simple-example';
|
|
19
19
|
|
|
@@ -81,11 +81,10 @@ const requestHandler = (request, response) => {
|
|
|
81
81
|
const bodyJSON = bodyParts.join('');
|
|
82
82
|
const body = JSON.parse(bodyJSON);
|
|
83
83
|
if (
|
|
84
|
-
body.
|
|
85
|
-
&& body.acts
|
|
84
|
+
body.acts
|
|
86
85
|
&& body.jobData
|
|
87
|
-
&& body.agent
|
|
88
|
-
&& body.agent === process.env.AGENT
|
|
86
|
+
&& body.jobData.agent
|
|
87
|
+
&& body.jobData.agent === process.env.AGENT
|
|
89
88
|
) {
|
|
90
89
|
ack.result = 'Success: Valid report submitted';
|
|
91
90
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "00000-simple-example",
|
|
3
|
-
"what": "Test example.
|
|
3
|
+
"what": "Test example.edu with bulk",
|
|
4
4
|
"strict": true,
|
|
5
5
|
"timeLimit": 10,
|
|
6
|
-
"
|
|
6
|
+
"acts": [
|
|
7
7
|
{
|
|
8
8
|
"type": "launch",
|
|
9
9
|
"which": "chromium",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
},
|
|
12
12
|
{
|
|
13
13
|
"type": "url",
|
|
14
|
-
"which": "https://example.
|
|
14
|
+
"which": "https://example.edu/",
|
|
15
15
|
"what": "Example.com",
|
|
16
16
|
"id": "example"
|
|
17
17
|
},
|
|
@@ -24,13 +24,12 @@
|
|
|
24
24
|
"sources": {
|
|
25
25
|
"script": "simple",
|
|
26
26
|
"batch": "",
|
|
27
|
-
"
|
|
27
|
+
"target": {
|
|
28
28
|
"id": "example",
|
|
29
|
-
"
|
|
30
|
-
"what": "Example.com"
|
|
29
|
+
"what": "Example"
|
|
31
30
|
},
|
|
32
31
|
"requester": "user@domain.tld"
|
|
33
32
|
},
|
|
34
|
-
"
|
|
33
|
+
"creationTime": "2022-11-12T22:51:45",
|
|
35
34
|
"timeStamp": "00000"
|
|
36
35
|
}
|
|
File without changes
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
"id": "allHiddenVal",
|
|
3
3
|
"what": "validation of allHidden test",
|
|
4
4
|
"strict": true,
|
|
5
|
-
"
|
|
5
|
+
"timeLimit": 20,
|
|
6
|
+
"acts": [
|
|
6
7
|
{
|
|
7
8
|
"type": "launch",
|
|
8
9
|
"which": "chromium",
|
|
@@ -308,6 +309,6 @@
|
|
|
308
309
|
"host": {},
|
|
309
310
|
"requester": ""
|
|
310
311
|
},
|
|
311
|
-
"
|
|
312
|
+
"creationTime": "2002-11-12T09:31:00",
|
|
312
313
|
"timeStamp": "00000"
|
|
313
314
|
}
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
"id": "bulkVal",
|
|
3
3
|
"what": "validation of bulk test",
|
|
4
4
|
"strict": true,
|
|
5
|
-
"
|
|
5
|
+
"timeLimit": 20,
|
|
6
|
+
"acts": [
|
|
6
7
|
{
|
|
7
8
|
"type": "launch",
|
|
8
9
|
"which": "chromium",
|
|
@@ -42,6 +43,6 @@
|
|
|
42
43
|
"host": {},
|
|
43
44
|
"requester": ""
|
|
44
45
|
},
|
|
45
|
-
"
|
|
46
|
+
"creationTime": "2002-11-12T09:31:00",
|
|
46
47
|
"timeStamp": "00000"
|
|
47
48
|
}
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
"id": "docTypeVal",
|
|
3
3
|
"what": "validation of docType test",
|
|
4
4
|
"strict": true,
|
|
5
|
-
"
|
|
5
|
+
"timeLimit": 20,
|
|
6
|
+
"acts": [
|
|
6
7
|
{
|
|
7
8
|
"type": "launch",
|
|
8
9
|
"which": "chromium",
|
|
@@ -40,6 +41,6 @@
|
|
|
40
41
|
"host": {},
|
|
41
42
|
"requester": ""
|
|
42
43
|
},
|
|
43
|
-
"
|
|
44
|
+
"creationTime": "2002-11-12T09:31:00",
|
|
44
45
|
"timeStamp": "00000"
|
|
45
46
|
}
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
"id": "elementsVal",
|
|
3
3
|
"what": "validation of elements test",
|
|
4
4
|
"strict": true,
|
|
5
|
-
"
|
|
5
|
+
"timeLimit": 20,
|
|
6
|
+
"acts": [
|
|
6
7
|
{
|
|
7
8
|
"type": "launch",
|
|
8
9
|
"which": "chromium",
|
|
@@ -134,6 +135,6 @@
|
|
|
134
135
|
"host": {},
|
|
135
136
|
"requester": ""
|
|
136
137
|
},
|
|
137
|
-
"
|
|
138
|
+
"creationTime": "2002-11-12T09:31:00",
|
|
138
139
|
"timeStamp": "00000"
|
|
139
140
|
}
|