testaro 75.1.0 → 75.2.1
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/env.example +5 -4
- package/package.json +1 -1
- package/procs/catalog.js +2 -2
- package/procs/launch.js +35 -3
- package/procs/shoot.js +0 -1
package/env.example
CHANGED
|
@@ -14,19 +14,20 @@ WAITS=0
|
|
|
14
14
|
NODE_OPTIONS='--trace-uncaught --trace-warnings'
|
|
15
15
|
# Suppresses a routine warning from QualWeb.
|
|
16
16
|
PUPPETEER_DISABLE_HEADLESS_WARNING=true
|
|
17
|
+
# Replace the next 2 placeholders with http://localhost:3000 if Kilotest and Testaro are on the same host or the URL of the server (e.g., https://kilotest.com) if they are on different hosts.
|
|
17
18
|
# URL to poll for available jobs when watching the network.
|
|
18
|
-
|
|
19
|
+
NETWATCH_URL_JOB=__placeholder__/api/testaro-agent/job
|
|
19
20
|
# URL to report results to when watching the network.
|
|
20
|
-
|
|
21
|
+
NETWATCH_URL_REPORT=__placeholder__/api/testaro-agent/report
|
|
21
22
|
# Password of this Testaro agent
|
|
22
|
-
|
|
23
|
+
NETWATCH_URL_AUTH=__placeholder__
|
|
23
24
|
# Directory (relative to project root) to watch for jobs.
|
|
24
25
|
JOBDIR=__placeholder__
|
|
25
26
|
# Directory (relative to project root) to write reports to when watching a directory for jobs.
|
|
26
27
|
REPORTDIR=__placeholder__
|
|
27
28
|
# Multiplier for time limits (normally 1).
|
|
28
29
|
TIMEOUT_MULTIPLIER=1
|
|
29
|
-
# Whether to abort the job when
|
|
30
|
+
# Whether to abort the job when launch retries are exhausted or a test act crashes (default false).
|
|
30
31
|
ABORT_ASSERTIVELY=false
|
|
31
32
|
# URL of any non-default (e.g., self-hosted) Nu Html Checker API (see ghcr.io/validator/validator).
|
|
32
33
|
TESTARO_NU_URL=__placeholder__
|
package/package.json
CHANGED
package/procs/catalog.js
CHANGED
|
@@ -35,7 +35,7 @@ exports.getCatalog = async report => {
|
|
|
35
35
|
const targetURL = report.target?.url;
|
|
36
36
|
// If the report specifies a global browser ID and a global target URL:
|
|
37
37
|
if (browserID && targetURL) {
|
|
38
|
-
// Launch a browser
|
|
38
|
+
// Launch a browser and visit the target, or abort the job on failure.
|
|
39
39
|
const page = await launch({
|
|
40
40
|
report,
|
|
41
41
|
actIndex: null,
|
|
@@ -159,7 +159,7 @@ exports.getCatalog = async report => {
|
|
|
159
159
|
return catalog;
|
|
160
160
|
}
|
|
161
161
|
// Otherwise, i.e. if the launch or navigation failed, report and return this.
|
|
162
|
-
console.log('ERROR: Launch or navigation failure prevented
|
|
162
|
+
console.log('ERROR: Launch or navigation failure prevented cataloguing and aborted job');
|
|
163
163
|
return {};
|
|
164
164
|
}
|
|
165
165
|
// Otherwise, i.e. if the report specification is incomplete, report and return this.
|
package/procs/launch.js
CHANGED
|
@@ -132,6 +132,7 @@ const goTo = exports.goTo = async (report, page, url, timeout, waitUntil) => {
|
|
|
132
132
|
const actualURL = page.url();
|
|
133
133
|
const actualNorm = actualURL.startsWith('file:') ? normalizeURL(actualURL) : actualURL;
|
|
134
134
|
const urlNorm = url.startsWith('file:') ? normalizeURL(url) : url;
|
|
135
|
+
const title = await page.title();
|
|
135
136
|
// If the browser was redirected in violation of a strictness requirement:
|
|
136
137
|
if (report.strict && deSlash(actualNorm) !== deSlash(urlNorm)) {
|
|
137
138
|
// Return an error.
|
|
@@ -141,6 +142,15 @@ const goTo = exports.goTo = async (report, page, url, timeout, waitUntil) => {
|
|
|
141
142
|
error: 'badRedirection'
|
|
142
143
|
};
|
|
143
144
|
}
|
|
145
|
+
// Otherwise, if the browser was redirected to a CAPTCHA barrier:
|
|
146
|
+
else if ([urlNorm, title].some(identifier => identifier.includes('captcha'))) {
|
|
147
|
+
// Return this.
|
|
148
|
+
console.log(`ERROR: Visit to ${url} redirected to CAPTCHA barrier (${actualURL})`);
|
|
149
|
+
return {
|
|
150
|
+
success: false,
|
|
151
|
+
error: 'captchaBarrier'
|
|
152
|
+
};
|
|
153
|
+
}
|
|
144
154
|
// Otherwise, i.e. if no prohibited redirection occurred:
|
|
145
155
|
else {
|
|
146
156
|
// Press the Escape key to dismiss any modal dialog.
|
|
@@ -179,6 +189,15 @@ const goTo = exports.goTo = async (report, page, url, timeout, waitUntil) => {
|
|
|
179
189
|
error: `status429/retryAfterSeconds=${waitSeconds}`
|
|
180
190
|
};
|
|
181
191
|
}
|
|
192
|
+
// Otherwise, if the response status was a suspension:
|
|
193
|
+
else if (httpStatus === 202) {
|
|
194
|
+
// Return this.
|
|
195
|
+
console.log(`ERROR: Visit to ${url} suspended (status 202)`);
|
|
196
|
+
return {
|
|
197
|
+
success: false,
|
|
198
|
+
error: 'status202'
|
|
199
|
+
};
|
|
200
|
+
}
|
|
182
201
|
// Otherwise, i.e. if the response status was otherwise abnormal:
|
|
183
202
|
else {
|
|
184
203
|
// Return an error.
|
|
@@ -532,10 +551,10 @@ const launchOnce = async opts => {
|
|
|
532
551
|
};
|
|
533
552
|
// Manages browser launching and navigating and returns a page.
|
|
534
553
|
exports.launch = async (opts = {}) => {
|
|
554
|
+
let {tempBrowserID = ''} = opts;
|
|
535
555
|
const {
|
|
536
556
|
report = {},
|
|
537
557
|
actIndex = 0,
|
|
538
|
-
tempBrowserID = '',
|
|
539
558
|
tempURL = '',
|
|
540
559
|
headEmulation = 'high',
|
|
541
560
|
xPathNeed = 'script',
|
|
@@ -566,6 +585,7 @@ exports.launch = async (opts = {}) => {
|
|
|
566
585
|
}
|
|
567
586
|
// Otherwise, i.e. if the launch or navigation failed:
|
|
568
587
|
else {
|
|
588
|
+
let unusedBrowserIDs = ['chromium', 'webkit', 'firefox'].filter(id => id !== tempBrowserID);
|
|
569
589
|
let retriesLeft = retries;
|
|
570
590
|
let {error} = launchResult;
|
|
571
591
|
// As long as retries remain, decrement the allowed retry count and:
|
|
@@ -610,13 +630,25 @@ exports.launch = async (opts = {}) => {
|
|
|
610
630
|
error = launchResult.error;
|
|
611
631
|
// Report this.
|
|
612
632
|
console.log(`WARNING: Retry failed (${error})`);
|
|
633
|
+
// If a browser type was specified, retries are exhausted, and browser types are not:
|
|
634
|
+
if (tempBrowserID && unusedBrowserIDs.length && ! retriesLeft) {
|
|
635
|
+
// Change the browser type.
|
|
636
|
+
tempBrowserID = unusedBrowserIDs.shift();
|
|
637
|
+
console.log(`NOTICE: Changing browser type to ${tempBrowserID}`);
|
|
638
|
+
// Reset the retries.
|
|
639
|
+
retriesLeft = retries;
|
|
640
|
+
}
|
|
613
641
|
}
|
|
614
642
|
}
|
|
615
|
-
// If the retries were exhausted:
|
|
643
|
+
// If the retries were finally exhausted:
|
|
616
644
|
if (! retriesLeft) {
|
|
617
645
|
// Report this and, if so configured, that the job was aborted.
|
|
618
646
|
addError(
|
|
619
|
-
true,
|
|
647
|
+
true,
|
|
648
|
+
actIndex === null ? true : abortAssertively,
|
|
649
|
+
report,
|
|
650
|
+
actIndex,
|
|
651
|
+
`Launch or navigation failed; retries and browser types exhausted`
|
|
620
652
|
);
|
|
621
653
|
}
|
|
622
654
|
// Return a failure.
|
package/procs/shoot.js
CHANGED