@camperaid/watest 2.5.0 → 2.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 +274 -129
- package/bin/watest.js +36 -2
- package/core/base.js +10 -3
- package/core/core.js +43 -15
- package/core/deps.js +211 -0
- package/core/{process_args.js → process-args.js} +8 -0
- package/core/series.js +70 -28
- package/core/settings.js +28 -10
- package/core/system.js +68 -0
- package/core/util.js +1 -1
- package/eslint.config.js +1 -1
- package/index.js +15 -3
- package/interfaces/servicer.js +13 -3
- package/logging/logging.js +1 -1
- package/logging/logpipe.js +38 -21
- package/package.json +1 -1
- package/tests/base/{t_core.js → t-core.js} +10 -3
- package/tests/base/t-system.js +59 -0
- package/tests/base/{t_throws.js → t-throws.js} +67 -0
- package/tests/base/test.js +1 -2
- package/tests/deps/samples/nested/.watestrc.js +3 -0
- package/tests/deps/samples/nested/tests/meta.js +1 -0
- package/tests/deps/samples/nested/tests/services/meta.js +1 -0
- package/tests/deps/samples/nested/tests/services/ws/meta.js +1 -0
- package/tests/deps/samples/nested/tests/services/ws/webservice/meta.js +2 -0
- package/tests/deps/samples/nested/tests/services/ws/webservice/t-ws.js +3 -0
- package/tests/deps/samples/unified/.watestrc.js +3 -0
- package/tests/deps/samples/unified/tests/e2e/meta.js +4 -0
- package/tests/deps/samples/unified/tests/e2e/pages/meta.js +1 -0
- package/tests/deps/samples/unified/tests/e2e/pages/t-example.js +3 -0
- package/tests/deps/samples/unified/tests/e2e/t-example.js +3 -0
- package/tests/deps/samples/unified/tests/integration/meta.js +3 -0
- package/tests/deps/samples/unified/tests/lib/meta.js +0 -0
- package/tests/deps/samples/unified/tests/lib/t-example.js +3 -0
- package/tests/deps/samples/unified/tests/meta.js +8 -0
- package/tests/deps/samples/unified/tests/services/meta.js +3 -0
- package/tests/deps/samples/unified/tests/services/request/meta.js +1 -0
- package/tests/deps/samples/unified/tests/services/t-example.js +3 -0
- package/tests/deps/t-parse-cell-syntax.js +6 -0
- package/tests/deps/t-parse-grid-args.js +11 -0
- package/tests/deps/t-watest-deps.js +37 -0
- package/tests/deps/t-watest-grid.js +122 -0
- package/tests/deps/test.js +63 -0
- package/tests/e2e/samples/folder/package-lock.json +3 -1
- package/tests/e2e/samples/loader/package-lock.json +3 -1
- package/tests/e2e/samples/loader/tests/meta.js +1 -1
- package/tests/e2e/samples/{loader_mixed → loader-mixed}/package-lock.json +3 -1
- package/tests/e2e/samples/{loader_multiple/tests/core → loader-mixed/tests/ui}/meta.js +1 -1
- package/tests/e2e/samples/{loader_multiple → loader-multiple}/package-lock.json +3 -1
- package/tests/e2e/samples/{loader_multiple → loader-multiple}/tests/base/meta.js +1 -1
- package/tests/e2e/samples/{loader_mixed/tests/ui → loader-multiple/tests/core}/meta.js +1 -1
- package/tests/e2e/samples/single/package-lock.json +3 -1
- package/tests/e2e/samples/{wd_mixed → wd-mixed}/package-lock.json +3 -1
- package/tests/e2e/samples/{wd_single → wd-single}/package-lock.json +3 -1
- package/tests/e2e/{t_folder.js → t-folder.js} +3 -3
- package/tests/e2e/{t_loader_mixed.js → t-loader-mixed.js} +7 -7
- package/tests/e2e/{t_loader_multiple_patterns.js → t-loader-multiple-patterns.js} +9 -9
- package/tests/e2e/{t_loader_multiple.js → t-loader-multiple.js} +8 -8
- package/tests/e2e/{t_loader.js → t-loader.js} +4 -4
- package/tests/e2e/{t_single.js → t-single.js} +3 -3
- package/tests/e2e/{t_wd_firefox_chrome_pattern.js → t-wd-firefox-chrome-pattern.js} +8 -8
- package/tests/e2e/{t_wd_firefox_chrome.js → t-wd-firefox-chrome.js} +7 -7
- package/tests/e2e/{t_wd_firefox.js → t-wd-firefox.js} +5 -5
- package/tests/e2e/{t_wd_mixed_firefox_chrome.js → t-wd-mixed-firefox-chrome.js} +9 -9
- package/tests/e2e/{t_wd_mixed_firefox.js → t-wd-mixed-firefox.js} +7 -7
- package/tests/meta.js +1 -1
- package/tests/series/build/t-pattern-filtering.js +175 -0
- package/tests/series/build/{t_webdriver_services.js → t-webdriver-services.js} +1 -0
- package/tests/series/logging/{t_failures.js → t-failures.js} +1 -1
- package/tests/series/logging/{t_success.js → t-success.js} +1 -1
- package/tests/series/logging/{t_verify.js → t-verify.js} +2 -2
- package/tests/series/meta.js +1 -0
- package/tests/series/perform/{t_failure_notest.js → t-failure-notest.js} +1 -0
- package/tests/series/perform/{t_failure.js → t-failure.js} +1 -0
- package/tests/series/perform/{t_intermittent_global.js → t-intermittent-global.js} +1 -0
- package/tests/series/perform/{t_intermittent.js → t-intermittent.js} +2 -0
- package/tests/series/perform/{t_missing_perma.js → t-missing-perma.js} +2 -0
- package/tests/series/perform/{t_nested.js → t-nested.js} +1 -0
- package/tests/series/perform/{t_perma.js → t-perma.js} +1 -0
- package/tests/series/perform/{t_success.js → t-success.js} +2 -0
- package/tests/series/servicer/mock-servicer.js +68 -0
- package/tests/series/servicer/t-nested-servicer-lifecycle.js +99 -0
- package/tests/series/servicer/t-servicer-no-services.js +53 -0
- package/tests/series/servicer/t-servicer-type-switching.js +139 -0
- package/tests/series/servicer/t-servicer.js +51 -0
- package/tests/series/test.js +1 -1
- package/tests/test.js +2 -0
- package/tests/webdriver/test.js +3 -3
- package/webdriver/{control_driver.js → control-driver.js} +1 -1
- package/webdriver/{driver_base.js → driver-base.js} +3 -1
- package/webdriver/driver.js +1 -1
- package/webdriver/session.js +57 -30
- package/tests/base/{t_api.js → t-api.js} +0 -0
- package/tests/base/{t_contains.js → t-contains.js} +0 -0
- package/tests/base/{t_format.js → t-format.js} +0 -0
- package/tests/base/{t_is_object.js → t-is-object.js} +0 -0
- package/tests/base/{t_is_primitive.js → t-is-primitive.js} +0 -0
- package/tests/base/{t_is_string.js → t-is-string.js} +0 -0
- package/tests/base/{t_is.js → t-is.js} +0 -0
- package/tests/base/{t_ok.js → t-ok.js} +0 -0
- package/tests/base/{t_stringify.js → t-stringify.js} +0 -0
- package/tests/base/{t_test_.js → t-test-.js} +0 -0
- package/tests/e2e/samples/folder/tests/unit/{t_test.js → t-test.js} +0 -0
- package/tests/e2e/samples/{loader_multiple/tests/module_mock.js → loader/tests/module-mock.js} +0 -0
- package/tests/e2e/samples/loader/tests/{t_test.js → t-test.js} +0 -0
- package/tests/e2e/samples/{loader_mixed → loader-mixed}/.watestrc.js +0 -0
- package/tests/e2e/samples/{loader_mixed → loader-mixed}/package.json +0 -0
- package/tests/e2e/samples/{loader_mixed → loader-mixed}/tests/meta.js +0 -0
- package/tests/e2e/samples/{loader/tests/module_mock.js → loader-mixed/tests/module-mock.js} +0 -0
- package/tests/e2e/samples/{loader_mixed → loader-mixed}/tests/module.js +0 -0
- package/tests/e2e/samples/{loader_mixed/tests/ui/t_test.js → loader-mixed/tests/ui/t-test.js} +0 -0
- package/tests/e2e/samples/{loader_mixed/tests/unit/t_test.js → loader-mixed/tests/unit/t-test.js} +0 -0
- package/tests/e2e/samples/{loader_multiple → loader-multiple}/.watestrc.js +0 -0
- package/tests/e2e/samples/{loader_multiple → loader-multiple}/package.json +0 -0
- package/tests/e2e/samples/{loader_multiple/tests/base/t_btest.js → loader-multiple/tests/base/t-btest.js} +0 -0
- package/tests/e2e/samples/{loader_multiple/tests/core/t_ctest.js → loader-multiple/tests/core/t-ctest.js} +0 -0
- package/tests/e2e/samples/{loader_multiple → loader-multiple}/tests/meta.js +0 -0
- package/tests/e2e/samples/{loader_mixed/tests/module_mock.js → loader-multiple/tests/module-mock.js} +0 -0
- package/tests/e2e/samples/{loader_multiple → loader-multiple}/tests/module.js +0 -0
- package/tests/e2e/samples/single/tests/{t_test.js → t-test.js} +0 -0
- package/tests/e2e/samples/{wd_mixed → wd-mixed}/.watestrc.js +0 -0
- package/tests/e2e/samples/{wd_mixed → wd-mixed}/package.json +0 -0
- package/tests/e2e/samples/{wd_mixed → wd-mixed}/tests/meta.js +0 -0
- package/tests/e2e/samples/{wd_mixed → wd-mixed}/tests/ui/meta.js +0 -0
- package/tests/e2e/samples/{wd_mixed/tests/ui/t_test.js → wd-mixed/tests/ui/t-test.js} +0 -0
- package/tests/e2e/samples/{wd_mixed/tests/unit/t_test.js → wd-mixed/tests/unit/t-test.js} +0 -0
- package/tests/e2e/samples/{wd_single → wd-single}/.watestrc.js +0 -0
- package/tests/e2e/samples/{wd_single → wd-single}/package.json +0 -0
- package/tests/e2e/samples/{wd_single → wd-single}/tests/meta.js +0 -0
- package/tests/e2e/samples/{wd_single/tests/t_test.js → wd-single/tests/t-test.js} +0 -0
- package/tests/series/build/{t_adjust_names_webdriver.js → t-adjust-names-webdriver.js} +0 -0
- package/tests/series/build/{t_adjust_names.js → t-adjust-names.js} +0 -0
- package/tests/series/build/{t_expected_failures.js → t-expected-failures.js} +0 -0
- package/tests/series/build/{t_loader_mixed.js → t-loader-mixed.js} +0 -0
- package/tests/series/build/{t_loader.js → t-loader.js} +0 -0
- package/tests/series/build/{t_mixed.js → t-mixed.js} +0 -0
- package/tests/series/build/{t_nested.js → t-nested.js} +0 -0
- package/tests/series/build/{t_patterns_loader.js → t-patterns-loader.js} +0 -0
- package/tests/series/build/{t_patterns_webdriver.js → t-patterns-webdriver.js} +0 -0
- package/tests/series/build/{t_webdriver_firefox_mixed.js → t-webdriver-firefox-mixed.js} +0 -0
- package/tests/series/build/{t_webdriver_nested.js → t-webdriver-nested.js} +0 -0
- package/tests/series/build/{t_webdriver.js → t-webdriver.js} +0 -0
- package/tests/series/generic/{t_failures_info.js → t-failures-info.js} +0 -0
- package/tests/series/{mock_series.js → mock-series.js} +0 -0
- package/tests/series/run/{t_debunk_failure.js → t-debunk-failure.js} +1 -1
- package/tests/series/run/{t_debunk_success.js → t-debunk-success.js} +1 -1
- package/tests/series/run/{t_nested.js → t-nested.js} +1 -1
- package/tests/series/run/{t_verify_webdriver.js → t-verify-webdriver.js} +1 -1
- package/tests/series/run/{t_verify.js → t-verify.js} +1 -1
- /package/tests/webdriver/{t_app_driver_selectors.js → t-app-driver-selectors.js} +0 -0
- /package/tests/webdriver/{t_app_driver.js → t-app-driver.js} +0 -0
- /package/tests/webdriver/{t_attribute_all.js → t-attribute-all.js} +0 -0
- /package/tests/webdriver/{t_attribute.js → t-attribute.js} +0 -0
- /package/tests/webdriver/{t_doubleclick.js → t-doubleclick.js} +0 -0
- /package/tests/webdriver/{t_doubleclickat.js → t-doubleclickat.js} +0 -0
- /package/tests/webdriver/{t_execute.js → t-execute.js} +0 -0
- /package/tests/webdriver/{t_if_has_elements.js → t-if-has-elements.js} +0 -0
- /package/tests/webdriver/{t_if_no_elements.js → t-if-no-elements.js} +0 -0
- /package/tests/webdriver/{t_no_elements_or_not_visible.js → t-no-elements-or-not-visible.js} +0 -0
- /package/tests/webdriver/{t_properties.js → t-properties.js} +0 -0
- /package/tests/webdriver/{t_script.js → t-script.js} +0 -0
- /package/tests/webdriver/{t_select_all.js → t-select-all.js} +0 -0
- /package/tests/webdriver/{t_selection.js → t-selection.js} +0 -0
- /package/tests/webdriver/{t_text_all.js → t-text-all.js} +0 -0
- /package/tests/webdriver/{t_text.js → t-text.js} +0 -0
- /package/webdriver/{app_driver.js → app-driver.js} +0 -0
package/logging/logpipe.js
CHANGED
|
@@ -2,7 +2,7 @@ import path from 'path';
|
|
|
2
2
|
|
|
3
3
|
import { FileStream as DefaultFileStream } from './filestream.js';
|
|
4
4
|
import { log, log_error } from './logging.js';
|
|
5
|
-
import settings from '../core/settings.js';
|
|
5
|
+
import { settings } from '../core/settings.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* A single instance of a logpipe writing to std and file streams.
|
|
@@ -15,6 +15,7 @@ class LogPipeInstance {
|
|
|
15
15
|
|
|
16
16
|
attach(invocation) {
|
|
17
17
|
this.invocation = invocation;
|
|
18
|
+
this.run = settings.run;
|
|
18
19
|
this.log_dir = path.join(settings.log_dir, this.invocation);
|
|
19
20
|
if (this.suppress_logging) {
|
|
20
21
|
return;
|
|
@@ -28,7 +29,7 @@ class LogPipeInstance {
|
|
|
28
29
|
log_error(e);
|
|
29
30
|
});
|
|
30
31
|
|
|
31
|
-
return settings.logger.testRunStarted({ run:
|
|
32
|
+
return settings.logger.testRunStarted({ run: this.run, invocation });
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
async logScreenshot(pic) {
|
|
@@ -41,7 +42,7 @@ class LogPipeInstance {
|
|
|
41
42
|
log(`Screenshot is captured and written to ${stream.filepath}`);
|
|
42
43
|
|
|
43
44
|
await settings.logger.writeLogFile({
|
|
44
|
-
run:
|
|
45
|
+
run: this.run,
|
|
45
46
|
invocation: this.invocation,
|
|
46
47
|
name,
|
|
47
48
|
content,
|
|
@@ -50,30 +51,42 @@ class LogPipeInstance {
|
|
|
50
51
|
|
|
51
52
|
logSourceMap() {
|
|
52
53
|
return settings.logger.writeSourceMap({
|
|
53
|
-
run:
|
|
54
|
+
run: this.run,
|
|
54
55
|
invocation: this.invocation,
|
|
55
56
|
});
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
release() {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
if (this.suppress_logging || !this.fstream) {
|
|
61
|
+
return Promise.resolve();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const filepath = this.fstream.filepath;
|
|
65
|
+
|
|
66
|
+
return this.fstream
|
|
67
|
+
.end()
|
|
68
|
+
.then(() => this.fstream.readFile())
|
|
69
|
+
.then(content =>
|
|
70
|
+
settings.logger.writeLogFile({
|
|
71
|
+
run: this.run,
|
|
72
|
+
invocation: this.invocation,
|
|
73
|
+
name: this.fname,
|
|
74
|
+
content,
|
|
75
|
+
zip: true,
|
|
76
|
+
}),
|
|
77
|
+
)
|
|
78
|
+
.catch(e => {
|
|
79
|
+
log_error(
|
|
80
|
+
`[logpipe:error] ✗ Logging shutdown failed for ${filepath}:`,
|
|
81
|
+
{
|
|
82
|
+
filepath,
|
|
67
83
|
invocation: this.invocation,
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
)
|
|
73
|
-
|
|
74
|
-
log_error(`Logging shutdown rejected: ${e}`);
|
|
75
|
-
})
|
|
76
|
-
);
|
|
84
|
+
error: e.message,
|
|
85
|
+
code: e.code,
|
|
86
|
+
stack: e.stack,
|
|
87
|
+
},
|
|
88
|
+
);
|
|
89
|
+
});
|
|
77
90
|
}
|
|
78
91
|
}
|
|
79
92
|
|
|
@@ -127,6 +140,10 @@ class LogPipe {
|
|
|
127
140
|
// Remove the pipe from the stack to prevent anyone writing into it after
|
|
128
141
|
// its release.
|
|
129
142
|
let pipeToRelease = this.stack.pop();
|
|
143
|
+
if (!pipeToRelease) {
|
|
144
|
+
return Promise.resolve();
|
|
145
|
+
}
|
|
146
|
+
|
|
130
147
|
await pipeToRelease.release(...args);
|
|
131
148
|
|
|
132
149
|
if (this.suppress_logging) {
|
package/package.json
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
import { colorify, group, fail, success, is_output } from './test.js';
|
|
2
2
|
|
|
3
3
|
export async function test() {
|
|
4
|
-
// console.log
|
|
5
|
-
|
|
4
|
+
// console.log - Node adds yellow color codes to numbers in TTY
|
|
5
|
+
const colored3 = `\x1b[33m3\x1b[39m\n`;
|
|
6
|
+
|
|
7
|
+
await is_output(
|
|
8
|
+
() => console.log(3),
|
|
9
|
+
[colored3],
|
|
10
|
+
[],
|
|
11
|
+
`console.log(3)`,
|
|
12
|
+
);
|
|
6
13
|
|
|
7
14
|
// console.error
|
|
8
15
|
await is_output(
|
|
9
16
|
() => console.error(3),
|
|
10
17
|
[],
|
|
11
|
-
[
|
|
18
|
+
[colored3],
|
|
12
19
|
`console.error(3)`,
|
|
13
20
|
);
|
|
14
21
|
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { ok, contains } from '../../index.js';
|
|
2
|
+
import { runCommand, runBashScript, execCommand } from '../../core/system.js';
|
|
3
|
+
|
|
4
|
+
export async function test() {
|
|
5
|
+
// Test 1: runCommand with echo
|
|
6
|
+
{
|
|
7
|
+
const result = await runCommand('echo', ['hello', 'world']);
|
|
8
|
+
ok(result.exitCode === 0, 'echo command should succeed');
|
|
9
|
+
ok(result.stdout === 'hello world', 'stdout should contain echo output');
|
|
10
|
+
ok(result.stderr === '', 'stderr should be empty');
|
|
11
|
+
ok(result.stdoutLines.length === 1, 'should have one stdout line');
|
|
12
|
+
ok(result.stdoutLines[0] === 'hello world', 'stdout line should match');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Test 2: runBashScript with simple script
|
|
16
|
+
{
|
|
17
|
+
const script = 'echo "test script"; echo "line 2"';
|
|
18
|
+
const result = await runBashScript(script);
|
|
19
|
+
ok(result.exitCode === 0, 'bash script should succeed');
|
|
20
|
+
contains(result.stdout, 'test script', 'should contain first echo');
|
|
21
|
+
contains(result.stdout, 'line 2', 'should contain second echo');
|
|
22
|
+
ok(result.stdoutLines.length === 2, 'should have two stdout lines');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Test 3: execCommand for simple cases
|
|
26
|
+
{
|
|
27
|
+
const output = await execCommand('echo', ['simple test']);
|
|
28
|
+
ok(output === 'simple test', 'execCommand should return stdout directly');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Test 4: runCommand with failing command
|
|
32
|
+
{
|
|
33
|
+
const result = await runCommand('bash', ['-c', 'echo "error" >&2; exit 1']);
|
|
34
|
+
ok(result.exitCode === 1, 'failing command should return exit code 1');
|
|
35
|
+
ok(result.stdout === '', 'stdout should be empty');
|
|
36
|
+
ok(result.stderr === 'error', 'stderr should contain error message');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Test 5: execCommand should throw on failure
|
|
40
|
+
{
|
|
41
|
+
let threw = false;
|
|
42
|
+
try {
|
|
43
|
+
await execCommand('bash', ['-c', 'exit 1']);
|
|
44
|
+
} catch (error) {
|
|
45
|
+
threw = true;
|
|
46
|
+
contains(error.message, 'exit code 1', 'error should mention exit code');
|
|
47
|
+
}
|
|
48
|
+
ok(threw, 'execCommand should throw on non-zero exit code');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Test 6: runBashScript with arguments
|
|
52
|
+
{
|
|
53
|
+
const script = 'echo "arg1: $1, arg2: $2"';
|
|
54
|
+
const result = await runBashScript(script, ['first', 'second']);
|
|
55
|
+
ok(result.exitCode === 0, 'bash script with args should succeed');
|
|
56
|
+
contains(result.stdout, 'arg1: first', 'should pass first argument');
|
|
57
|
+
contains(result.stdout, 'arg2: second', 'should pass second argument');
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -136,4 +136,71 @@ unexpected character: '2' at 6 pos, expected: '1' at '' line
|
|
|
136
136
|
],
|
|
137
137
|
`no_throws fail (async)`,
|
|
138
138
|
);
|
|
139
|
+
|
|
140
|
+
// throws: accept object descriptor (statusCode + JSON body)
|
|
141
|
+
await is_output(
|
|
142
|
+
() =>
|
|
143
|
+
throws(
|
|
144
|
+
() => {
|
|
145
|
+
const err = new Error(
|
|
146
|
+
'HTTP error code 422 for https://api.digitalocean.com/v2/droplets',
|
|
147
|
+
);
|
|
148
|
+
err.statusCode = 422;
|
|
149
|
+
err.responseBody = JSON.stringify({
|
|
150
|
+
id: 'unprocessable_entity',
|
|
151
|
+
message: 'You specified an invalid image for Droplet creation.',
|
|
152
|
+
});
|
|
153
|
+
throw err;
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
statusCode: 422,
|
|
157
|
+
responseBody: JSON.stringify({
|
|
158
|
+
id: 'unprocessable_entity',
|
|
159
|
+
message: 'You specified an invalid image for Droplet creation.',
|
|
160
|
+
}),
|
|
161
|
+
},
|
|
162
|
+
`Throws error descriptor`,
|
|
163
|
+
),
|
|
164
|
+
[
|
|
165
|
+
`Ok: Throws error descriptor, got: {statusCode: 422, responseBody: '{"id":"unprocessable_entity","message":"You specified an invalid image for Droplet creation."}'}`,
|
|
166
|
+
],
|
|
167
|
+
[],
|
|
168
|
+
`throws accept object descriptor`,
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
// throws: accept RegExp for message matching
|
|
172
|
+
await is_output(
|
|
173
|
+
() =>
|
|
174
|
+
throws(
|
|
175
|
+
() => {
|
|
176
|
+
throw new Error(
|
|
177
|
+
'Unexpected 404 response code for https://example.com/test from droplet 1',
|
|
178
|
+
);
|
|
179
|
+
},
|
|
180
|
+
/404|Unexpected/,
|
|
181
|
+
`Throws with RegExp`,
|
|
182
|
+
),
|
|
183
|
+
[
|
|
184
|
+
`Ok: Throws with RegExp 'Unexpected 404 response code for https://example.com/test from droplet 1' matches /404|Unexpected/ regexp`,
|
|
185
|
+
],
|
|
186
|
+
[],
|
|
187
|
+
`throws accept RegExp pattern`,
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
// throws: fail RegExp that doesn't match
|
|
191
|
+
await is_output(
|
|
192
|
+
() =>
|
|
193
|
+
throws(
|
|
194
|
+
() => {
|
|
195
|
+
throw new Error('Some other error message');
|
|
196
|
+
},
|
|
197
|
+
/404|Unexpected/,
|
|
198
|
+
`RegExp should match`,
|
|
199
|
+
),
|
|
200
|
+
[],
|
|
201
|
+
[
|
|
202
|
+
`Failed: RegExp should match 'Some other error message' doesn't match /404|Unexpected/ regexp`,
|
|
203
|
+
],
|
|
204
|
+
`throws fail RegExp no match`,
|
|
205
|
+
);
|
|
139
206
|
}
|
package/tests/base/test.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { testflow } from '../../core/core.js';
|
|
2
2
|
import { is_output as is_output_base } from '../../core/base.js';
|
|
3
3
|
|
|
4
|
-
export * from '
|
|
5
|
-
export * from '../../core/core.js';
|
|
4
|
+
export * from '../test.js';
|
|
6
5
|
export * from '../../core/format.js';
|
|
7
6
|
|
|
8
7
|
function is_output(func, out, err, msg) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const folders = ['services'];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const folders = ['ws'];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const folders = ['webservice'];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const services = ['request'];
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const services = ['request'];
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { is, parseGridArgs } from './test.js';
|
|
2
|
+
|
|
3
|
+
export async function test() {
|
|
4
|
+
const args1 = parseGridArgs(['tests/e2e', 'tests/www', 'chrome', 'firefox']);
|
|
5
|
+
is(args1.paths, ['tests/e2e', 'tests/www'], 'paths');
|
|
6
|
+
is(args1.webdrivers, ['chrome', 'firefox'], 'webdrivers');
|
|
7
|
+
|
|
8
|
+
const args2 = parseGridArgs([]);
|
|
9
|
+
is(args2.paths, [], 'empty paths');
|
|
10
|
+
is(args2.webdrivers, [], 'empty webdrivers');
|
|
11
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { testDeps } from './test.js';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
|
|
5
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
const unifiedSamplePath = path.join(__dirname, 'samples/unified');
|
|
7
|
+
const nestedSamplePath = path.join(__dirname, 'samples/nested');
|
|
8
|
+
|
|
9
|
+
export async function test() {
|
|
10
|
+
// Test specific path: tests/e2e
|
|
11
|
+
await testDeps(['tests/e2e'], unifiedSamplePath, {
|
|
12
|
+
servicers: ['kubernetes'],
|
|
13
|
+
webdriver: true,
|
|
14
|
+
services: ['db', 'nginx', 'request'],
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
// Test no arguments (should default to tests/)
|
|
18
|
+
await testDeps([], unifiedSamplePath, {
|
|
19
|
+
servicers: ['kubernetes', 'docker'],
|
|
20
|
+
webdriver: true,
|
|
21
|
+
services: ['db', 'nginx', 'request', 'inbucket'],
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// Test with deeply nested test file path
|
|
25
|
+
await testDeps(['tests/services/ws/webservice/t-ws.js'], nestedSamplePath, {
|
|
26
|
+
servicers: ['docker'],
|
|
27
|
+
webdriver: false,
|
|
28
|
+
services: ['ws'],
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// Test with nested directory path
|
|
32
|
+
await testDeps(['tests/services/ws/webservice'], nestedSamplePath, {
|
|
33
|
+
servicers: ['docker'],
|
|
34
|
+
webdriver: false,
|
|
35
|
+
services: ['ws'],
|
|
36
|
+
});
|
|
37
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { is, testGrid } from './test.js';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
|
|
5
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
const samplesPath = path.join(__dirname, 'samples/unified');
|
|
7
|
+
|
|
8
|
+
export async function test() {
|
|
9
|
+
// Default browsers from .watestrc.js (chrome, firefox) - splits + cells
|
|
10
|
+
const result1 = await testGrid([], samplesPath);
|
|
11
|
+
is(
|
|
12
|
+
result1,
|
|
13
|
+
{
|
|
14
|
+
'e2e-chrome': {
|
|
15
|
+
paths: ['tests/e2e'],
|
|
16
|
+
webdrivers: 'chrome',
|
|
17
|
+
servicers: ['kubernetes'],
|
|
18
|
+
services: ['db', 'nginx', 'request'],
|
|
19
|
+
},
|
|
20
|
+
'e2e-firefox': {
|
|
21
|
+
paths: ['tests/e2e'],
|
|
22
|
+
webdrivers: 'firefox',
|
|
23
|
+
servicers: ['kubernetes'],
|
|
24
|
+
services: ['db', 'nginx', 'request'],
|
|
25
|
+
},
|
|
26
|
+
'integration': {
|
|
27
|
+
paths: ['tests/integration'],
|
|
28
|
+
webdrivers: 'chrome firefox',
|
|
29
|
+
servicers: ['docker'],
|
|
30
|
+
services: ['db'],
|
|
31
|
+
},
|
|
32
|
+
'lib': {
|
|
33
|
+
paths: ['tests/lib'],
|
|
34
|
+
webdrivers: '',
|
|
35
|
+
servicers: [],
|
|
36
|
+
services: [],
|
|
37
|
+
},
|
|
38
|
+
'services': {
|
|
39
|
+
paths: ['tests/services'],
|
|
40
|
+
webdrivers: '',
|
|
41
|
+
servicers: ['docker'],
|
|
42
|
+
services: ['inbucket', 'request'],
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
'default browsers split + cells',
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
// Single browser - no split even for + cells
|
|
49
|
+
const result2 = await testGrid(['chrome'], samplesPath);
|
|
50
|
+
is(
|
|
51
|
+
result2,
|
|
52
|
+
{
|
|
53
|
+
e2e: {
|
|
54
|
+
paths: ['tests/e2e'],
|
|
55
|
+
webdrivers: 'chrome',
|
|
56
|
+
servicers: ['kubernetes'],
|
|
57
|
+
services: ['db', 'nginx', 'request'],
|
|
58
|
+
},
|
|
59
|
+
integration: {
|
|
60
|
+
paths: ['tests/integration'],
|
|
61
|
+
webdrivers: 'chrome',
|
|
62
|
+
servicers: ['docker'],
|
|
63
|
+
services: ['db'],
|
|
64
|
+
},
|
|
65
|
+
lib: {
|
|
66
|
+
paths: ['tests/lib'],
|
|
67
|
+
webdrivers: '',
|
|
68
|
+
servicers: [],
|
|
69
|
+
services: [],
|
|
70
|
+
},
|
|
71
|
+
services: {
|
|
72
|
+
paths: ['tests/services'],
|
|
73
|
+
webdrivers: '',
|
|
74
|
+
servicers: ['docker'],
|
|
75
|
+
services: ['inbucket', 'request'],
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
'single browser no split',
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
// Multiple browsers without split (no + cells, explicit browsers)
|
|
82
|
+
const result3 = await testGrid(
|
|
83
|
+
['tests/lib', 'chrome', 'firefox'],
|
|
84
|
+
samplesPath,
|
|
85
|
+
);
|
|
86
|
+
is(
|
|
87
|
+
result3,
|
|
88
|
+
{
|
|
89
|
+
lib: {
|
|
90
|
+
paths: ['tests/lib'],
|
|
91
|
+
webdrivers: '',
|
|
92
|
+
servicers: [],
|
|
93
|
+
services: [],
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
'no webdriver cell with multiple browsers',
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
// Filter by paths with multiple browsers (+ cell splits)
|
|
100
|
+
const result4 = await testGrid(
|
|
101
|
+
['tests/e2e', 'chrome', 'firefox'],
|
|
102
|
+
samplesPath,
|
|
103
|
+
);
|
|
104
|
+
is(
|
|
105
|
+
result4,
|
|
106
|
+
{
|
|
107
|
+
'e2e-chrome': {
|
|
108
|
+
paths: ['tests/e2e'],
|
|
109
|
+
webdrivers: 'chrome',
|
|
110
|
+
servicers: ['kubernetes'],
|
|
111
|
+
services: ['db', 'nginx', 'request'],
|
|
112
|
+
},
|
|
113
|
+
'e2e-firefox': {
|
|
114
|
+
paths: ['tests/e2e'],
|
|
115
|
+
webdrivers: 'firefox',
|
|
116
|
+
servicers: ['kubernetes'],
|
|
117
|
+
services: ['db', 'nginx', 'request'],
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
'filtered paths with split',
|
|
121
|
+
);
|
|
122
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export * from '../test.js';
|
|
2
|
+
export * from '../../core/deps.js';
|
|
3
|
+
|
|
4
|
+
import { is } from '../test.js';
|
|
5
|
+
import { spawn } from '../../core/spawn.js';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
|
+
|
|
9
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Helper to test watest --deps command
|
|
13
|
+
* @param {string[]} paths - Paths to pass to --deps (empty array for no args)
|
|
14
|
+
* @param {string} samplesPath - Path to samples directory
|
|
15
|
+
* @param {Object} expected - Expected metadata result
|
|
16
|
+
*/
|
|
17
|
+
export async function testDeps(paths, samplesPath, expected) {
|
|
18
|
+
let stdout = '';
|
|
19
|
+
let stderr = '';
|
|
20
|
+
|
|
21
|
+
const args = ['../../../../bin/watest.js', '--deps', ...paths];
|
|
22
|
+
|
|
23
|
+
await spawn('node', args, { cwd: samplesPath }, buffer => {
|
|
24
|
+
for (let { str_data, is_stdout } of buffer) {
|
|
25
|
+
if (is_stdout) stdout += str_data;
|
|
26
|
+
else stderr += str_data;
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
is(stderr, '', 'no errors');
|
|
31
|
+
|
|
32
|
+
// Filter out Settings lines before JSON
|
|
33
|
+
const jsonStart = stdout.indexOf('{');
|
|
34
|
+
const jsonStr = jsonStart >= 0 ? stdout.slice(jsonStart) : stdout;
|
|
35
|
+
|
|
36
|
+
const meta = JSON.parse(jsonStr);
|
|
37
|
+
const pathsDesc =
|
|
38
|
+
paths.length === 0 ? 'no args (defaults to tests/)' : paths.join(', ');
|
|
39
|
+
is(meta, expected, `deps for ${pathsDesc}`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Helper to test watest --grid command
|
|
44
|
+
* @param {string[]} args - Arguments to pass to --grid
|
|
45
|
+
* @param {string} cwd - Working directory for the command
|
|
46
|
+
* @returns {Promise<Object>} Parsed grid JSON output
|
|
47
|
+
*/
|
|
48
|
+
export async function testGrid(args, cwd) {
|
|
49
|
+
let stdout = '';
|
|
50
|
+
const watestBin = path.join(__dirname, '../../bin/watest.js');
|
|
51
|
+
|
|
52
|
+
await spawn('node', [watestBin, '--grid', ...args], { cwd }, buffer => {
|
|
53
|
+
for (let { str_data, is_stdout } of buffer) {
|
|
54
|
+
if (is_stdout) stdout += str_data;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const jsonStart = stdout.indexOf('{');
|
|
59
|
+
if (jsonStart < 0) {
|
|
60
|
+
throw new Error(`No JSON in output: ${stdout}`);
|
|
61
|
+
}
|
|
62
|
+
return JSON.parse(stdout.slice(jsonStart));
|
|
63
|
+
}
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"../../../..": {
|
|
18
18
|
"name": "@camperaid/watest",
|
|
19
|
-
"version": "2.
|
|
19
|
+
"version": "2.5.1",
|
|
20
20
|
"dev": true,
|
|
21
21
|
"license": "MPL",
|
|
22
22
|
"dependencies": {
|
|
@@ -187,6 +187,7 @@
|
|
|
187
187
|
"version": "8.12.1",
|
|
188
188
|
"dev": true,
|
|
189
189
|
"license": "MIT",
|
|
190
|
+
"peer": true,
|
|
190
191
|
"bin": {
|
|
191
192
|
"acorn": "bin/acorn"
|
|
192
193
|
},
|
|
@@ -450,6 +451,7 @@
|
|
|
450
451
|
"version": "9.8.0",
|
|
451
452
|
"dev": true,
|
|
452
453
|
"license": "MIT",
|
|
454
|
+
"peer": true,
|
|
453
455
|
"dependencies": {
|
|
454
456
|
"@eslint-community/eslint-utils": "^4.2.0",
|
|
455
457
|
"@eslint-community/regexpp": "^4.11.0",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"../../../..": {
|
|
18
18
|
"name": "@camperaid/watest",
|
|
19
|
-
"version": "2.
|
|
19
|
+
"version": "2.5.1",
|
|
20
20
|
"dev": true,
|
|
21
21
|
"license": "MPL",
|
|
22
22
|
"dependencies": {
|
|
@@ -187,6 +187,7 @@
|
|
|
187
187
|
"version": "8.12.1",
|
|
188
188
|
"dev": true,
|
|
189
189
|
"license": "MIT",
|
|
190
|
+
"peer": true,
|
|
190
191
|
"bin": {
|
|
191
192
|
"acorn": "bin/acorn"
|
|
192
193
|
},
|
|
@@ -450,6 +451,7 @@
|
|
|
450
451
|
"version": "9.8.0",
|
|
451
452
|
"dev": true,
|
|
452
453
|
"license": "MIT",
|
|
454
|
+
"peer": true,
|
|
453
455
|
"dependencies": {
|
|
454
456
|
"@eslint-community/eslint-utils": "^4.2.0",
|
|
455
457
|
"@eslint-community/regexpp": "^4.11.0",
|