@camperaid/watest 2.5.9 → 2.6.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/README.md +41 -20
- package/core/base.js +24 -0
- package/core/deps.js +68 -39
- package/core/meta.js +30 -0
- package/core/series.js +19 -2
- package/package.json +1 -1
- package/tests/base/t-contains.js +31 -3
- package/tests/deps/samples/unified/tests/disabled/meta.js +3 -0
- package/tests/deps/samples/unified/tests/disabled-parent/child/meta.js +2 -0
- package/tests/deps/samples/unified/tests/disabled-parent/meta.js +2 -0
- package/tests/deps/samples/unified/tests/meta.js +12 -1
- package/tests/deps/t-watest-deps.js +13 -0
- package/tests/deps/t-watest-grid.js +11 -2
- package/tests/e2e/samples/folder/package-lock.json +1 -3
- package/tests/e2e/samples/loader/package-lock.json +1 -3
- package/tests/e2e/samples/loader-mixed/package-lock.json +1 -3
- package/tests/e2e/samples/loader-multiple/package-lock.json +1 -3
- package/tests/e2e/samples/single/package-lock.json +1 -3
- package/tests/e2e/samples/wd-mixed/package-lock.json +1 -3
- package/tests/e2e/samples/wd-single/package-lock.json +1 -3
- package/tests/series/logging/t-failures.js +5 -0
- package/tests/series/logging/t-success.js +5 -0
- package/tests/series/logging/t-verify.js +37 -18
- package/tests/series/run/t-debunk-failure.js +7 -8
- package/tests/series/run/t-debunk-success.js +7 -8
- package/tests/series/run/t-nested.js +7 -10
- package/tests/series/run/t-verify-webdriver.js +8 -19
- package/tests/series/run/t-verify.js +8 -13
- package/tests/series/servicer/t-enabled.js +38 -0
- package/tests/series/servicer/t-nested-servicer-lifecycle.js +2 -7
- package/tests/series/servicer/t-servicer-no-services.js +2 -6
- package/tests/series/servicer/t-servicer-type-switching.js +2 -9
- package/tests/series/servicer/t-servicer.js +2 -6
- package/tests/series/test.js +20 -0
package/README.md
CHANGED
|
@@ -44,14 +44,28 @@ Each test folder can have a `meta.js` file:
|
|
|
44
44
|
|
|
45
45
|
```javascript
|
|
46
46
|
// tests/e2e/meta.js
|
|
47
|
-
export const folders = ['login', 'checkout'];
|
|
48
|
-
export const services = ['db', 'ws'];
|
|
49
|
-
export const servicer = 'docker';
|
|
50
|
-
export const webdriver = true;
|
|
51
|
-
export const
|
|
52
|
-
export const
|
|
47
|
+
export const folders = ['login', 'checkout']; // Nested test folders
|
|
48
|
+
export const services = ['db', 'ws']; // Services to start
|
|
49
|
+
export const servicer = 'docker'; // Service manager: 'docker' | 'kubernetes'
|
|
50
|
+
export const webdriver = true; // Enable browser testing
|
|
51
|
+
export const enabled = process.env.FEATURE_ON; // Optional: true/false, 'true'/'false', or a function returning one
|
|
52
|
+
export const init = async () => {
|
|
53
|
+
/* setup */
|
|
54
|
+
};
|
|
55
|
+
export const uninit = async () => {
|
|
56
|
+
/* teardown */
|
|
57
|
+
};
|
|
53
58
|
```
|
|
54
59
|
|
|
60
|
+
`enabled` may be:
|
|
61
|
+
|
|
62
|
+
- a boolean
|
|
63
|
+
- the string `'true'` or `'false'`
|
|
64
|
+
- a synchronous function returning one of those values
|
|
65
|
+
|
|
66
|
+
Skipped suites are omitted from `--deps` and `--grid` metadata, and their
|
|
67
|
+
services are not started.
|
|
68
|
+
|
|
55
69
|
## Configuration
|
|
56
70
|
|
|
57
71
|
### Project Configuration File
|
|
@@ -80,8 +94,8 @@ export default {
|
|
|
80
94
|
webdriver_window_height: process.env.WATEST_WEBDRIVER_WINDOW_HEIGHT,
|
|
81
95
|
|
|
82
96
|
// Integration hooks (absolute paths to your project files)
|
|
83
|
-
servicer: './tests/servicer.js',
|
|
84
|
-
logger: './tests/logserver.js',
|
|
97
|
+
servicer: './tests/servicer.js', // Manages test services
|
|
98
|
+
logger: './tests/logserver.js', // Remote test logging
|
|
85
99
|
|
|
86
100
|
// Optional: ignore pattern
|
|
87
101
|
ignore_pattern: process.env.WATEST_IGNORE_PATTERN,
|
|
@@ -184,9 +198,9 @@ todo('implement logout');
|
|
|
184
198
|
```javascript
|
|
185
199
|
import { assert, not_reached, inspect } from '@camperaid/watest';
|
|
186
200
|
|
|
187
|
-
assert(condition, 'condition must be true');
|
|
188
|
-
not_reached('should not get here');
|
|
189
|
-
inspect(object);
|
|
201
|
+
assert(condition, 'condition must be true'); // Fails with stack trace
|
|
202
|
+
not_reached('should not get here'); // Always fails with stack trace
|
|
203
|
+
inspect(object); // Pretty-print object
|
|
190
204
|
```
|
|
191
205
|
|
|
192
206
|
### Test Helpers
|
|
@@ -195,8 +209,12 @@ inspect(object); // Pretty-print object
|
|
|
195
209
|
import { test_is, test_contains } from '@camperaid/watest';
|
|
196
210
|
|
|
197
211
|
// Silent checks (no success/fail logging)
|
|
198
|
-
if (test_is(got, expected)) {
|
|
199
|
-
|
|
212
|
+
if (test_is(got, expected)) {
|
|
213
|
+
/* ... */
|
|
214
|
+
}
|
|
215
|
+
if (test_contains(array, subset)) {
|
|
216
|
+
/* ... */
|
|
217
|
+
}
|
|
200
218
|
```
|
|
201
219
|
|
|
202
220
|
## Integration Testing
|
|
@@ -240,7 +258,7 @@ class LoginPage extends AppDriver {
|
|
|
240
258
|
this.action('Login')
|
|
241
259
|
.sendKeys(this.Email, email)
|
|
242
260
|
.sendKeys(this.Password, password)
|
|
243
|
-
.click(this.Submit)
|
|
261
|
+
.click(this.Submit),
|
|
244
262
|
);
|
|
245
263
|
}
|
|
246
264
|
|
|
@@ -266,10 +284,8 @@ Handle known intermittent or permanent failures in `meta.js`:
|
|
|
266
284
|
```javascript
|
|
267
285
|
export const expected_failures = [
|
|
268
286
|
[
|
|
269
|
-
'test_file.js',
|
|
270
|
-
[
|
|
271
|
-
[platform, type, group, failures, description],
|
|
272
|
-
],
|
|
287
|
+
'test_file.js', // or '*' for all files
|
|
288
|
+
[[platform, type, group, failures, description]],
|
|
273
289
|
],
|
|
274
290
|
];
|
|
275
291
|
```
|
|
@@ -316,7 +332,7 @@ Watest provides metadata helpers for external orchestrators to distribute tests
|
|
|
316
332
|
```javascript
|
|
317
333
|
// tests/meta.js
|
|
318
334
|
export const grid = {
|
|
319
|
-
'e2e+': ['tests/e2e'],
|
|
335
|
+
'e2e+': ['tests/e2e'], // '+' = split per browser
|
|
320
336
|
'www+': ['tests/www'],
|
|
321
337
|
'services': ['tests/services', 'tests/integration'],
|
|
322
338
|
'misc': ['tests/lib', 'tests/ops'],
|
|
@@ -340,7 +356,12 @@ watest --deps tests/e2e
|
|
|
340
356
|
## System Commands
|
|
341
357
|
|
|
342
358
|
```javascript
|
|
343
|
-
import {
|
|
359
|
+
import {
|
|
360
|
+
runCommand,
|
|
361
|
+
execCommand,
|
|
362
|
+
spawn,
|
|
363
|
+
runBashScript,
|
|
364
|
+
} from '@camperaid/watest';
|
|
344
365
|
|
|
345
366
|
// Run command, log output
|
|
346
367
|
await runCommand('npm', ['install']);
|
package/core/base.js
CHANGED
|
@@ -67,6 +67,30 @@ function contains(
|
|
|
67
67
|
msg,
|
|
68
68
|
{ ignore_unexpected, fail_ = fail, success_ = success } = {},
|
|
69
69
|
) {
|
|
70
|
+
// string contains array of strings: check each substring.
|
|
71
|
+
if (typeof got == 'string' && expected instanceof Array) {
|
|
72
|
+
let isok = true;
|
|
73
|
+
for (let e of expected) {
|
|
74
|
+
if (typeof e != 'string') {
|
|
75
|
+
fail_(`${msg}, expected string item, got ${typeof e}: ${stringify(e)}`);
|
|
76
|
+
isok = false;
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (!got.includes(e)) {
|
|
80
|
+
fail_(
|
|
81
|
+
`${msg}, got string doesn't contain expected string, got: ${stringify(
|
|
82
|
+
got,
|
|
83
|
+
)}, expected: ${stringify(e)}`,
|
|
84
|
+
);
|
|
85
|
+
isok = false;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (isok) {
|
|
89
|
+
success_(`${msg}, got: ${stringify(got)}`);
|
|
90
|
+
}
|
|
91
|
+
return isok;
|
|
92
|
+
}
|
|
93
|
+
|
|
70
94
|
if (typeof got == 'string' || typeof expected == 'string') {
|
|
71
95
|
if (typeof got != 'string') {
|
|
72
96
|
fail_(`${msg}, expected string, got object: []`);
|
package/core/deps.js
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
* Parses test folder metadata and generates grid configurations.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import fs from 'node:fs';
|
|
6
7
|
import { pathToFileURL } from 'node:url';
|
|
8
|
+
import { isMetaEnabled } from './meta.js';
|
|
7
9
|
import { join } from 'node:path';
|
|
8
10
|
import { settings } from './settings.js';
|
|
9
11
|
|
|
@@ -58,39 +60,41 @@ function matchesPath(folderPath, targetPaths) {
|
|
|
58
60
|
}
|
|
59
61
|
|
|
60
62
|
/**
|
|
61
|
-
* Collect metadata from a single directory's meta.js
|
|
62
|
-
* Helper for collectDeps
|
|
63
|
+
* Collect metadata from a single directory's meta.js.
|
|
63
64
|
*/
|
|
64
|
-
async function
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
65
|
+
async function scanMetaDir(dirPath, result) {
|
|
66
|
+
const metaPath = join(process.cwd(), dirPath, 'meta.js');
|
|
67
|
+
if (!fs.existsSync(metaPath)) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const metaUrl = pathToFileURL(metaPath).href;
|
|
72
|
+
const meta = await import(metaUrl);
|
|
73
|
+
|
|
74
|
+
if (!isMetaEnabled(meta)) {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (meta.servicer && !result.servicers.includes(meta.servicer)) {
|
|
79
|
+
result.servicers.push(meta.servicer);
|
|
80
|
+
}
|
|
81
|
+
if (meta.webdriver) {
|
|
82
|
+
result.webdriver = true;
|
|
83
|
+
}
|
|
84
|
+
if (meta.services) {
|
|
85
|
+
for (const service of meta.services) {
|
|
86
|
+
const serviceName = getServiceName(service);
|
|
87
|
+
if (!result.services.includes(serviceName)) {
|
|
88
|
+
result.services.push(serviceName);
|
|
82
89
|
}
|
|
83
90
|
}
|
|
84
|
-
|
|
85
|
-
return meta;
|
|
86
|
-
} catch {
|
|
87
|
-
// No meta.js or error loading it - that's ok
|
|
88
|
-
return null;
|
|
89
91
|
}
|
|
92
|
+
|
|
93
|
+
return meta;
|
|
90
94
|
}
|
|
91
95
|
|
|
92
96
|
/**
|
|
93
|
-
*
|
|
97
|
+
* Walk nested meta.js files from root toward the requested target paths.
|
|
94
98
|
* Starts from root folder, walks DOWN the tree, only following branches that match target paths.
|
|
95
99
|
* Similar to how series.js builds tests - uses bidirectional path matching.
|
|
96
100
|
*
|
|
@@ -98,9 +102,15 @@ async function collectMetaFromDir(dirPath, result) {
|
|
|
98
102
|
* @param {string[]} targetPaths - The specific test paths we're collecting deps for
|
|
99
103
|
* @param {Object} result - Accumulated result object
|
|
100
104
|
*/
|
|
101
|
-
async function
|
|
105
|
+
async function walkDepsTree(folder, targetPaths, result) {
|
|
102
106
|
// Collect metadata from current folder
|
|
103
|
-
const meta = await
|
|
107
|
+
const meta = await scanMetaDir(folder, result);
|
|
108
|
+
|
|
109
|
+
if (meta === undefined) {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
let hasEnabledTarget = targetPaths.some(target => target === folder);
|
|
104
114
|
|
|
105
115
|
// If this folder has subfolders, filter and recurse
|
|
106
116
|
if (meta?.folders) {
|
|
@@ -109,10 +119,16 @@ async function collectDepsRecursive(folder, targetPaths, result) {
|
|
|
109
119
|
|
|
110
120
|
// Only follow this branch if it matches any target path
|
|
111
121
|
if (matchesPath(subfolderPath, targetPaths)) {
|
|
112
|
-
await
|
|
122
|
+
if (await walkDepsTree(subfolderPath, targetPaths, result)) {
|
|
123
|
+
hasEnabledTarget = true;
|
|
124
|
+
}
|
|
113
125
|
}
|
|
114
126
|
}
|
|
127
|
+
} else if (targetPaths.some(target => target.startsWith(`${folder}/`))) {
|
|
128
|
+
hasEnabledTarget = true;
|
|
115
129
|
}
|
|
130
|
+
|
|
131
|
+
return hasEnabledTarget;
|
|
116
132
|
}
|
|
117
133
|
|
|
118
134
|
/**
|
|
@@ -122,7 +138,7 @@ async function collectDepsRecursive(folder, targetPaths, result) {
|
|
|
122
138
|
* @param {string[]} paths - Test paths to collect metadata for (defaults to entire tree)
|
|
123
139
|
* @param {Object} result - Initial result object
|
|
124
140
|
*/
|
|
125
|
-
|
|
141
|
+
async function buildDepsState(
|
|
126
142
|
paths = [settings.testsFolder],
|
|
127
143
|
result = { servicers: [], webdriver: false, services: [] },
|
|
128
144
|
) {
|
|
@@ -133,11 +149,20 @@ export async function collectDeps(
|
|
|
133
149
|
p => p === rootFolder || p.startsWith(rootFolder + '/'),
|
|
134
150
|
);
|
|
135
151
|
|
|
152
|
+
let hasEnabledTarget = false;
|
|
153
|
+
|
|
136
154
|
if (targetPaths.length > 0) {
|
|
137
|
-
await
|
|
155
|
+
hasEnabledTarget = await walkDepsTree(rootFolder, targetPaths, result);
|
|
138
156
|
}
|
|
139
157
|
|
|
140
|
-
return result;
|
|
158
|
+
return { deps: result, hasEnabledTarget };
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export async function collectDeps(
|
|
162
|
+
paths = [settings.testsFolder],
|
|
163
|
+
result = { servicers: [], webdriver: false, services: [] },
|
|
164
|
+
) {
|
|
165
|
+
return (await buildDepsState(paths, result)).deps;
|
|
141
166
|
}
|
|
142
167
|
|
|
143
168
|
/**
|
|
@@ -180,29 +205,33 @@ export async function generateGridTasks(gridConfig, args) {
|
|
|
180
205
|
const expandedGrid = {};
|
|
181
206
|
for (const [cellKey, cellPaths] of cellPathsMap) {
|
|
182
207
|
const { name, split } = parseCellSyntax(cellKey);
|
|
183
|
-
const
|
|
208
|
+
const { deps, hasEnabledTarget } = await buildDepsState(cellPaths);
|
|
209
|
+
|
|
210
|
+
if (!hasEnabledTarget) {
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
184
213
|
|
|
185
|
-
if (split &&
|
|
214
|
+
if (split && deps.webdriver && browsers.length > 1) {
|
|
186
215
|
// Split: one entry per browser
|
|
187
216
|
for (const wd of browsers) {
|
|
188
217
|
expandedGrid[`${name}-${wd}`] = {
|
|
189
218
|
paths: cellPaths,
|
|
190
219
|
webdrivers: wd,
|
|
191
|
-
servicers:
|
|
192
|
-
services:
|
|
220
|
+
servicers: deps.servicers,
|
|
221
|
+
services: deps.services,
|
|
193
222
|
};
|
|
194
223
|
}
|
|
195
224
|
} else {
|
|
196
225
|
// No split: single entry with all browsers as space-separated string
|
|
197
226
|
let webdriversValue = '';
|
|
198
|
-
if (
|
|
227
|
+
if (deps.webdriver && browsers.length > 0) {
|
|
199
228
|
webdriversValue = browsers.join(' ');
|
|
200
229
|
}
|
|
201
230
|
expandedGrid[name] = {
|
|
202
231
|
paths: cellPaths,
|
|
203
232
|
webdrivers: webdriversValue,
|
|
204
|
-
servicers:
|
|
205
|
-
services:
|
|
233
|
+
servicers: deps.servicers,
|
|
234
|
+
services: deps.services,
|
|
206
235
|
};
|
|
207
236
|
}
|
|
208
237
|
}
|
package/core/meta.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
function normalizeMetaEnabled(value) {
|
|
2
|
+
if (value && typeof value.then === 'function') {
|
|
3
|
+
throw new Error(
|
|
4
|
+
"Invalid meta.enabled value: async values are not supported; use a boolean, 'true', 'false', or a synchronous function returning one of those values",
|
|
5
|
+
);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
if (value === true || value === 'true') {
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (value === false || value === 'false') {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
throw new Error(
|
|
17
|
+
`Invalid meta.enabled value: expected boolean, 'true', 'false', or a function returning one of those values; got ${JSON.stringify(value)}`,
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function isMetaEnabled(meta) {
|
|
22
|
+
if (!meta || meta.enabled === undefined) {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const value =
|
|
27
|
+
typeof meta.enabled === 'function' ? meta.enabled() : meta.enabled;
|
|
28
|
+
|
|
29
|
+
return normalizeMetaEnabled(value);
|
|
30
|
+
}
|
package/core/series.js
CHANGED
|
@@ -2,12 +2,13 @@ import fs from 'fs';
|
|
|
2
2
|
import nodepath from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
4
|
|
|
5
|
-
import { assert, fail, testflow } from './core.js';
|
|
5
|
+
import { assert, fail, success, testflow } from './core.js';
|
|
6
6
|
import { parse, parse_failure } from './format.js';
|
|
7
7
|
import { ProcessArgs } from './process-args.js';
|
|
8
8
|
import { settings } from './settings.js';
|
|
9
9
|
import { spawn } from './spawn.js';
|
|
10
10
|
import { stringify } from './util.js';
|
|
11
|
+
import { isMetaEnabled } from './meta.js';
|
|
11
12
|
import { log, log_error } from '../logging/logging.js';
|
|
12
13
|
import { LogPipe } from '../logging/logpipe.js';
|
|
13
14
|
import { DriverBase } from '../webdriver/driver-base.js';
|
|
@@ -86,7 +87,7 @@ class Series {
|
|
|
86
87
|
core,
|
|
87
88
|
LogPipe,
|
|
88
89
|
webdriver,
|
|
89
|
-
webdrivers = settings.webdrivers,
|
|
90
|
+
webdrivers = settings.webdrivers || [],
|
|
90
91
|
},
|
|
91
92
|
) {
|
|
92
93
|
this.debunk = debunk;
|
|
@@ -212,12 +213,25 @@ class Series {
|
|
|
212
213
|
let tests = [];
|
|
213
214
|
try {
|
|
214
215
|
let test_module = await this.loadTestMeta(folder);
|
|
216
|
+
const enabled = isMetaEnabled(test_module);
|
|
215
217
|
let subfolders = test_module.folders;
|
|
216
218
|
let testfiles = test_module.list || (await this.getTestFileList(folder));
|
|
217
219
|
if (!subfolders && testfiles.length == 0) {
|
|
218
220
|
throw new Error(`No tests found in ${folder}`);
|
|
219
221
|
}
|
|
220
222
|
|
|
223
|
+
if (!enabled) {
|
|
224
|
+
return [
|
|
225
|
+
{
|
|
226
|
+
name: virtual_folder,
|
|
227
|
+
path: `${folder}/meta.js`,
|
|
228
|
+
func: () => success(`Skipped: meta.enabled=false`),
|
|
229
|
+
failures_info: [],
|
|
230
|
+
meta_disabled_folder: true,
|
|
231
|
+
},
|
|
232
|
+
];
|
|
233
|
+
}
|
|
234
|
+
|
|
221
235
|
if (test_module.expected_failures) {
|
|
222
236
|
inherited_expected_failures = inherited_expected_failures.concat(
|
|
223
237
|
test_module.expected_failures.filter(v => v[0] == '**'),
|
|
@@ -414,6 +428,9 @@ class Series {
|
|
|
414
428
|
|
|
415
429
|
return subtests_for_subfolders
|
|
416
430
|
.flatMap(({ subfolder, subtests }) => {
|
|
431
|
+
if (subtests.some(t => t.meta_disabled_folder)) {
|
|
432
|
+
return subtests;
|
|
433
|
+
}
|
|
417
434
|
// Case: no substests for a loader test running in a child process.
|
|
418
435
|
if (subtests.every(t => t.loader)) {
|
|
419
436
|
return subtests;
|
package/package.json
CHANGED
package/tests/base/t-contains.js
CHANGED
|
@@ -17,12 +17,12 @@ export async function test() {
|
|
|
17
17
|
`failure`,
|
|
18
18
|
);
|
|
19
19
|
|
|
20
|
-
// string
|
|
20
|
+
// string, empty array: success (contains all of nothing)
|
|
21
21
|
await is_output(
|
|
22
22
|
() => contains('cat', [], `String contains`),
|
|
23
|
+
[`Ok: String contains, got: 'cat'`],
|
|
23
24
|
[],
|
|
24
|
-
|
|
25
|
-
`failure`,
|
|
25
|
+
`string empty array`,
|
|
26
26
|
);
|
|
27
27
|
|
|
28
28
|
// string: failure: doesn't contains
|
|
@@ -35,6 +35,34 @@ export async function test() {
|
|
|
35
35
|
`failure`,
|
|
36
36
|
);
|
|
37
37
|
|
|
38
|
+
// string, string[]: success
|
|
39
|
+
await is_output(
|
|
40
|
+
() =>
|
|
41
|
+
contains(
|
|
42
|
+
'green cat on a mat',
|
|
43
|
+
['green', 'cat', 'mat'],
|
|
44
|
+
`String contains all`,
|
|
45
|
+
),
|
|
46
|
+
[`Ok: String contains all, got: 'green cat on a mat'`],
|
|
47
|
+
[],
|
|
48
|
+
`string array success`,
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
// string, string[]: partial failure
|
|
52
|
+
await is_output(
|
|
53
|
+
() =>
|
|
54
|
+
contains(
|
|
55
|
+
'green cat on a mat',
|
|
56
|
+
['green', 'dog', 'mat'],
|
|
57
|
+
`String contains all`,
|
|
58
|
+
),
|
|
59
|
+
[],
|
|
60
|
+
[
|
|
61
|
+
`Failed: String contains all, got string doesn't contain expected string, got: 'green cat on a mat', expected: 'dog'`,
|
|
62
|
+
],
|
|
63
|
+
`string array failure`,
|
|
64
|
+
);
|
|
65
|
+
|
|
38
66
|
// array: success
|
|
39
67
|
await is_output(
|
|
40
68
|
() => contains([0, 1], [1], `Array contains`),
|
|
@@ -1,6 +1,17 @@
|
|
|
1
|
-
export const folders = [
|
|
1
|
+
export const folders = [
|
|
2
|
+
'disabled',
|
|
3
|
+
'disabled-parent',
|
|
4
|
+
'e2e',
|
|
5
|
+
'integration',
|
|
6
|
+
'lib',
|
|
7
|
+
'services',
|
|
8
|
+
];
|
|
2
9
|
|
|
10
|
+
// Disabled cells stay listed here on purpose so deps/grid tests can verify
|
|
11
|
+
// that watest filters them out from generated metadata.
|
|
3
12
|
export const grid = {
|
|
13
|
+
'disabled': ['tests/disabled'],
|
|
14
|
+
'disabled-parent': ['tests/disabled-parent/child'],
|
|
4
15
|
'e2e+': ['tests/e2e'],
|
|
5
16
|
'integration': ['tests/integration'],
|
|
6
17
|
'lib': ['tests/lib'],
|
|
@@ -21,6 +21,19 @@ export async function test() {
|
|
|
21
21
|
services: ['db', 'nginx', 'request', 'inbucket'],
|
|
22
22
|
});
|
|
23
23
|
|
|
24
|
+
// Disabled suite should be omitted from deps metadata even when addressed directly
|
|
25
|
+
await testDeps(['tests/disabled'], unifiedSamplePath, {
|
|
26
|
+
servicers: [],
|
|
27
|
+
webdriver: false,
|
|
28
|
+
services: [],
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
await testDeps(['tests/disabled-parent/child'], unifiedSamplePath, {
|
|
32
|
+
servicers: [],
|
|
33
|
+
webdriver: false,
|
|
34
|
+
services: [],
|
|
35
|
+
});
|
|
36
|
+
|
|
24
37
|
// Test with deeply nested test file path
|
|
25
38
|
await testDeps(['tests/services/ws/webservice/t-ws.js'], nestedSamplePath, {
|
|
26
39
|
servicers: ['docker'],
|
|
@@ -42,7 +42,7 @@ export async function test() {
|
|
|
42
42
|
services: ['inbucket', 'request'],
|
|
43
43
|
},
|
|
44
44
|
},
|
|
45
|
-
'default browsers split + cells',
|
|
45
|
+
'default browsers split + cells and omit disabled suites',
|
|
46
46
|
);
|
|
47
47
|
|
|
48
48
|
// Single browser - no split even for + cells
|
|
@@ -75,7 +75,7 @@ export async function test() {
|
|
|
75
75
|
services: ['inbucket', 'request'],
|
|
76
76
|
},
|
|
77
77
|
},
|
|
78
|
-
'single browser no split',
|
|
78
|
+
'single browser no split and omit disabled suites',
|
|
79
79
|
);
|
|
80
80
|
|
|
81
81
|
// Multiple browsers without split (no + cells, explicit browsers)
|
|
@@ -119,4 +119,13 @@ export async function test() {
|
|
|
119
119
|
},
|
|
120
120
|
'filtered paths with split',
|
|
121
121
|
);
|
|
122
|
+
|
|
123
|
+
const result5 = await testGrid(['tests/disabled', 'chrome'], samplesPath);
|
|
124
|
+
is(result5, {}, 'disabled grid cell should be omitted');
|
|
125
|
+
|
|
126
|
+
const result6 = await testGrid(
|
|
127
|
+
['tests/disabled-parent/child', 'chrome'],
|
|
128
|
+
samplesPath,
|
|
129
|
+
);
|
|
130
|
+
is(result6, {}, 'grid cell should be omitted when a parent meta disables it');
|
|
122
131
|
}
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"../../../..": {
|
|
18
18
|
"name": "@camperaid/watest",
|
|
19
|
-
"version": "2.
|
|
19
|
+
"version": "2.6.0",
|
|
20
20
|
"dev": true,
|
|
21
21
|
"license": "MPL",
|
|
22
22
|
"dependencies": {
|
|
@@ -187,7 +187,6 @@
|
|
|
187
187
|
"version": "8.12.1",
|
|
188
188
|
"dev": true,
|
|
189
189
|
"license": "MIT",
|
|
190
|
-
"peer": true,
|
|
191
190
|
"bin": {
|
|
192
191
|
"acorn": "bin/acorn"
|
|
193
192
|
},
|
|
@@ -451,7 +450,6 @@
|
|
|
451
450
|
"version": "9.8.0",
|
|
452
451
|
"dev": true,
|
|
453
452
|
"license": "MIT",
|
|
454
|
-
"peer": true,
|
|
455
453
|
"dependencies": {
|
|
456
454
|
"@eslint-community/eslint-utils": "^4.2.0",
|
|
457
455
|
"@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.6.0",
|
|
20
20
|
"dev": true,
|
|
21
21
|
"license": "MPL",
|
|
22
22
|
"dependencies": {
|
|
@@ -187,7 +187,6 @@
|
|
|
187
187
|
"version": "8.12.1",
|
|
188
188
|
"dev": true,
|
|
189
189
|
"license": "MIT",
|
|
190
|
-
"peer": true,
|
|
191
190
|
"bin": {
|
|
192
191
|
"acorn": "bin/acorn"
|
|
193
192
|
},
|
|
@@ -451,7 +450,6 @@
|
|
|
451
450
|
"version": "9.8.0",
|
|
452
451
|
"dev": true,
|
|
453
452
|
"license": "MIT",
|
|
454
|
-
"peer": true,
|
|
455
453
|
"dependencies": {
|
|
456
454
|
"@eslint-community/eslint-utils": "^4.2.0",
|
|
457
455
|
"@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.6.0",
|
|
20
20
|
"dev": true,
|
|
21
21
|
"license": "MPL",
|
|
22
22
|
"dependencies": {
|
|
@@ -187,7 +187,6 @@
|
|
|
187
187
|
"version": "8.12.1",
|
|
188
188
|
"dev": true,
|
|
189
189
|
"license": "MIT",
|
|
190
|
-
"peer": true,
|
|
191
190
|
"bin": {
|
|
192
191
|
"acorn": "bin/acorn"
|
|
193
192
|
},
|
|
@@ -451,7 +450,6 @@
|
|
|
451
450
|
"version": "9.8.0",
|
|
452
451
|
"dev": true,
|
|
453
452
|
"license": "MIT",
|
|
454
|
-
"peer": true,
|
|
455
453
|
"dependencies": {
|
|
456
454
|
"@eslint-community/eslint-utils": "^4.2.0",
|
|
457
455
|
"@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.6.0",
|
|
20
20
|
"dev": true,
|
|
21
21
|
"license": "MPL",
|
|
22
22
|
"dependencies": {
|
|
@@ -187,7 +187,6 @@
|
|
|
187
187
|
"version": "8.12.1",
|
|
188
188
|
"dev": true,
|
|
189
189
|
"license": "MIT",
|
|
190
|
-
"peer": true,
|
|
191
190
|
"bin": {
|
|
192
191
|
"acorn": "bin/acorn"
|
|
193
192
|
},
|
|
@@ -451,7 +450,6 @@
|
|
|
451
450
|
"version": "9.8.0",
|
|
452
451
|
"dev": true,
|
|
453
452
|
"license": "MIT",
|
|
454
|
-
"peer": true,
|
|
455
453
|
"dependencies": {
|
|
456
454
|
"@eslint-community/eslint-utils": "^4.2.0",
|
|
457
455
|
"@eslint-community/regexpp": "^4.11.0",
|