@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.
Files changed (34) hide show
  1. package/README.md +41 -20
  2. package/core/base.js +24 -0
  3. package/core/deps.js +68 -39
  4. package/core/meta.js +30 -0
  5. package/core/series.js +19 -2
  6. package/package.json +1 -1
  7. package/tests/base/t-contains.js +31 -3
  8. package/tests/deps/samples/unified/tests/disabled/meta.js +3 -0
  9. package/tests/deps/samples/unified/tests/disabled-parent/child/meta.js +2 -0
  10. package/tests/deps/samples/unified/tests/disabled-parent/meta.js +2 -0
  11. package/tests/deps/samples/unified/tests/meta.js +12 -1
  12. package/tests/deps/t-watest-deps.js +13 -0
  13. package/tests/deps/t-watest-grid.js +11 -2
  14. package/tests/e2e/samples/folder/package-lock.json +1 -3
  15. package/tests/e2e/samples/loader/package-lock.json +1 -3
  16. package/tests/e2e/samples/loader-mixed/package-lock.json +1 -3
  17. package/tests/e2e/samples/loader-multiple/package-lock.json +1 -3
  18. package/tests/e2e/samples/single/package-lock.json +1 -3
  19. package/tests/e2e/samples/wd-mixed/package-lock.json +1 -3
  20. package/tests/e2e/samples/wd-single/package-lock.json +1 -3
  21. package/tests/series/logging/t-failures.js +5 -0
  22. package/tests/series/logging/t-success.js +5 -0
  23. package/tests/series/logging/t-verify.js +37 -18
  24. package/tests/series/run/t-debunk-failure.js +7 -8
  25. package/tests/series/run/t-debunk-success.js +7 -8
  26. package/tests/series/run/t-nested.js +7 -10
  27. package/tests/series/run/t-verify-webdriver.js +8 -19
  28. package/tests/series/run/t-verify.js +8 -13
  29. package/tests/series/servicer/t-enabled.js +38 -0
  30. package/tests/series/servicer/t-nested-servicer-lifecycle.js +2 -7
  31. package/tests/series/servicer/t-servicer-no-services.js +2 -6
  32. package/tests/series/servicer/t-servicer-type-switching.js +2 -9
  33. package/tests/series/servicer/t-servicer.js +2 -6
  34. 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']; // 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 init = async () => { /* setup */ };
52
- export const uninit = async () => { /* teardown */ };
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', // Manages test services
84
- logger: './tests/logserver.js', // Remote test logging
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'); // Fails with stack trace
188
- not_reached('should not get here'); // Always fails with stack trace
189
- inspect(object); // Pretty-print 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
- if (test_contains(array, subset)) { /* ... */ }
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', // or '*' for all files
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'], // '+' = split per browser
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 { runCommand, execCommand, spawn, runBashScript } from '@camperaid/watest';
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 collectMetaFromDir(dirPath, result) {
65
- try {
66
- const metaPath = join(process.cwd(), dirPath, 'meta.js');
67
- const metaUrl = pathToFileURL(metaPath).href;
68
- const meta = await import(metaUrl);
69
-
70
- if (meta.servicer && !result.servicers.includes(meta.servicer)) {
71
- result.servicers.push(meta.servicer);
72
- }
73
- if (meta.webdriver) {
74
- result.webdriver = true;
75
- }
76
- if (meta.services) {
77
- for (const service of meta.services) {
78
- const serviceName = getServiceName(service);
79
- if (!result.services.includes(serviceName)) {
80
- result.services.push(serviceName);
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
- * Recursively collect metadata from nested meta.js files.
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 collectDepsRecursive(folder, targetPaths, result) {
105
+ async function walkDepsTree(folder, targetPaths, result) {
102
106
  // Collect metadata from current folder
103
- const meta = await collectMetaFromDir(folder, result);
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 collectDepsRecursive(subfolderPath, targetPaths, result);
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
- export async function collectDeps(
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 collectDepsRecursive(rootFolder, targetPaths, result);
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 meta = await collectDeps(cellPaths);
208
+ const { deps, hasEnabledTarget } = await buildDepsState(cellPaths);
209
+
210
+ if (!hasEnabledTarget) {
211
+ continue;
212
+ }
184
213
 
185
- if (split && meta.webdriver && browsers.length > 1) {
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: meta.servicers,
192
- services: meta.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 (meta.webdriver && browsers.length > 0) {
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: meta.servicers,
205
- services: meta.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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camperaid/watest",
3
- "version": "2.5.9",
3
+ "version": "2.6.1",
4
4
  "description": "Web Application Testsuite",
5
5
  "type": "module",
6
6
  "engines": {
@@ -17,12 +17,12 @@ export async function test() {
17
17
  `failure`,
18
18
  );
19
19
 
20
- // string: failure: got string, expected array
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
- [`Failed: String contains, got string, expected object: []`],
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`),
@@ -0,0 +1,3 @@
1
+ export const enabled = 'false';
2
+ export const servicer = 'docker';
3
+ export const services = ['ws'];
@@ -0,0 +1,2 @@
1
+ export const servicer = 'docker';
2
+ export const services = ['ws'];
@@ -0,0 +1,2 @@
1
+ export const enabled = 'false';
2
+ export const folders = ['child'];
@@ -1,6 +1,17 @@
1
- export const folders = ['e2e', 'integration', 'lib', 'services'];
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.5.1",
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.5.1",
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.5.1",
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.5.1",
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",