@camperaid/watest 2.5.4 → 2.5.6

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/.watestrc.js CHANGED
@@ -43,6 +43,12 @@ const cfg = {
43
43
  */
44
44
  webdriver_loglevel: process.env.WATEST_WEBDRIVER_LOGLEVEL,
45
45
 
46
+ /**
47
+ * Additional Chrome arguments.
48
+ * JSON array, e.g.: ["enable-unsafe-swiftshader", "use-gl=swiftshader"]
49
+ */
50
+ webdriver_chrome_args: process.env.WATEST_WEBDRIVER_CHROME_ARGS,
51
+
46
52
  /**
47
53
  * Web drivers to run tests for.
48
54
  */
package/core/series.js CHANGED
@@ -481,6 +481,7 @@ class Series {
481
481
  failures_info: [],
482
482
  skip_on_fail: 'skip-on-fail',
483
483
  init_or_uninit: true,
484
+ ...(test_module.timeout && { timeout: test_module.timeout }),
484
485
  });
485
486
  }
486
487
 
@@ -500,13 +501,17 @@ class Series {
500
501
  testname: path,
501
502
  });
502
503
 
503
- tests.push({
504
+ const testObj = {
504
505
  name,
505
506
  path,
506
507
  func: test_wrap,
507
508
  webdriver,
508
509
  failures_info,
509
- });
510
+ };
511
+ if (test_module.timeout) {
512
+ testObj.timeout = test_module.timeout;
513
+ }
514
+ tests.push(testObj);
510
515
  }
511
516
 
512
517
  // Add tests from subfolders.
@@ -531,6 +536,7 @@ class Series {
531
536
  failures_info: [],
532
537
  skip_on_fail: 'skip-on-fail',
533
538
  init_or_uninit: true,
539
+ ...(test_module.timeout && { timeout: test_module.timeout }),
534
540
  });
535
541
  }
536
542
 
@@ -653,6 +659,7 @@ class Series {
653
659
  skip_on_fail,
654
660
  run_in_child_process,
655
661
  init_or_uninit,
662
+ timeout,
656
663
  } = test;
657
664
 
658
665
  if (stop && !name.endsWith('uninit')) {
@@ -678,6 +685,7 @@ class Series {
678
685
 
679
686
  // Invoke a test.
680
687
  log(`\n!Running: ${name}, path: ${path}\n`);
688
+
681
689
  let start_time = new Date();
682
690
  let kungFuDeathGrip = null;
683
691
  let kungFuDeathGripResolve = null;
@@ -695,22 +703,21 @@ class Series {
695
703
  try {
696
704
  this.core.setExpectedFailures(failures_info);
697
705
 
698
- // If timeout is given then race it against the test.
699
- if (settings.timeout) {
706
+ // If timeout is given (from meta.js or settings) then race it against the test.
707
+ const effectiveTimeout = timeout ?? settings.timeout;
708
+ if (effectiveTimeout) {
709
+ const timeoutMs = effectiveTimeout * 1000;
700
710
  kungFuDeathGrip = new Promise(
701
711
  resolve => (kungFuDeathGripResolve = resolve),
702
712
  ).then(value => {
703
713
  if (value != kKungFuDeathGripCancelled) {
704
714
  fail(
705
- `Test ${name} takes longer than ${settings.timeout}ms. It's either slow or never ends.`,
715
+ `Test ${name} takes longer than ${effectiveTimeout}s. It's either slow or never ends.`,
706
716
  );
707
717
  return kKungFuDeathGripTimeout;
708
718
  }
709
719
  });
710
- kungFuDeathGripTimer = setTimeout(
711
- kungFuDeathGripResolve,
712
- settings.timeout,
713
- );
720
+ kungFuDeathGripTimer = setTimeout(kungFuDeathGripResolve, timeoutMs);
714
721
  let retval = await Promise.race([func(), kungFuDeathGrip]);
715
722
  if (retval != kKungFuDeathGripTimeout) {
716
723
  clearTimeout(kungFuDeathGripTimer);
package/core/settings.js CHANGED
@@ -54,11 +54,11 @@ class Settings {
54
54
  }
55
55
 
56
56
  get testFilePattern() {
57
- return this.rc.test_file_pattern || /^t[-_]/;
57
+ return this.rc?.test_file_pattern || /^t[-_]/;
58
58
  }
59
59
 
60
60
  get timeout() {
61
- return parseInt(this.rc.timeout) || 0;
61
+ return parseInt(this.rc?.timeout) || 0;
62
62
  }
63
63
 
64
64
  setupTmpStorageDir() {
@@ -112,12 +112,33 @@ class Settings {
112
112
  this.rc.webdriver_headless == true ||
113
113
  this.rc.webdriver_headless == 'true';
114
114
  this.webdriver_loglevel = this.rc.webdriver_loglevel;
115
+ this.webdriver_chrome_args = [];
116
+
117
+ if (typeof this.rc.webdriver_chrome_args == 'string') {
118
+ try {
119
+ const parsed = JSON.parse(this.rc.webdriver_chrome_args);
120
+ if (Array.isArray(parsed)) {
121
+ this.webdriver_chrome_args = parsed;
122
+ }
123
+ } catch (e) {
124
+ console.error(
125
+ `Settings: failed to parse webdriver_chrome_args '${this.rc.webdriver_chrome_args}'`,
126
+ e,
127
+ );
128
+ }
129
+ }
115
130
 
116
131
  this.webdriver_window_width =
117
132
  parseInt(this.rc.webdriver_window_width) || 1366;
118
133
  this.webdriver_window_height =
119
134
  parseInt(this.rc.webdriver_window_height) || 768;
120
135
 
136
+ if (!this.silent) {
137
+ console.log(
138
+ `Settings: webdriver_chrome_args=${JSON.stringify(this.webdriver_chrome_args)}`,
139
+ );
140
+ }
141
+
121
142
  if (this.webdrivers && !this.silent) {
122
143
  console.log(`Settings: ${this.webdrivers.join(', ')} webdrivers`);
123
144
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camperaid/watest",
3
- "version": "2.5.4",
3
+ "version": "2.5.6",
4
4
  "description": "Web Application Testsuite",
5
5
  "type": "module",
6
6
  "engines": {
@@ -0,0 +1,107 @@
1
+ import { is_test_output } from '../test.js';
2
+ import { success } from '../../../core/core.js';
3
+ import { Core } from '../../../core/core.js';
4
+ import { Series } from '../../../core/series.js';
5
+
6
+ class MockLogPipe {
7
+ attach() {
8
+ return Promise.resolve();
9
+ }
10
+ release() {
11
+ return Promise.resolve();
12
+ }
13
+ logToFile() {}
14
+ }
15
+
16
+ function make_perform_with_timeout(tests) {
17
+ return async () => {
18
+ const series = new Series('tests/', {
19
+ core: new Core(),
20
+ LogPipe: new MockLogPipe(),
21
+ });
22
+ try {
23
+ await series.perform({ folder: 'tests/', tests });
24
+ } finally {
25
+ series.shutdown();
26
+ }
27
+ };
28
+ }
29
+
30
+ export async function test() {
31
+ // Test that timeout from meta.js causes test to fail after specified time
32
+ await is_test_output(
33
+ make_perform_with_timeout([
34
+ {
35
+ name: 't-slow.js',
36
+ path: 'tests/t-slow.js',
37
+ func: () => new Promise(resolve => setTimeout(resolve, 500)),
38
+ failures_info: [],
39
+ timeout: 0.05, // 50ms timeout in seconds
40
+ },
41
+ ]),
42
+ [
43
+ '\x1B[38;5;99mStarted\x1B[0m tests/',
44
+ '!Running: t-slow.js, path: tests/t-slow.js',
45
+ '>t-slow.js completed in',
46
+ '\x1B[38;5;243mCompleted\x1B[0m tests/',
47
+ 'Testsuite: shutdown',
48
+ ],
49
+ [
50
+ "\x1B[31mFailed:\x1B[0m Test t-slow.js takes longer than 0.05s. It's either slow or never ends.",
51
+ '\x1B[31m>t-slow.js\x1B[0m has 1 failure(s)',
52
+ ],
53
+ 'meta timeout causes test to fail',
54
+ );
55
+
56
+ // Test that test completes normally when timeout is not exceeded
57
+ await is_test_output(
58
+ make_perform_with_timeout([
59
+ {
60
+ name: 't-fast.js',
61
+ path: 'tests/t-fast.js',
62
+ func: () => {
63
+ success('fast test passes');
64
+ return Promise.resolve();
65
+ },
66
+ failures_info: [],
67
+ timeout: 1, // 1 second timeout
68
+ },
69
+ ]),
70
+ [
71
+ '\x1B[38;5;99mStarted\x1B[0m tests/',
72
+ '!Running: t-fast.js, path: tests/t-fast.js',
73
+ '\x1B[32mOk:\x1B[0m fast test passes',
74
+ '>t-fast.js completed in',
75
+ '\x1B[38;5;243mCompleted\x1B[0m tests/',
76
+ 'Testsuite: shutdown',
77
+ ],
78
+ [],
79
+ 'test completes within timeout',
80
+ );
81
+
82
+ // Test that no timeout applies when timeout is undefined
83
+ await is_test_output(
84
+ make_perform_with_timeout([
85
+ {
86
+ name: 't-no-timeout.js',
87
+ path: 'tests/t-no-timeout.js',
88
+ func: () => {
89
+ success('no timeout test passes');
90
+ return new Promise(resolve => setTimeout(resolve, 10));
91
+ },
92
+ failures_info: [],
93
+ // timeout: undefined - no timeout set
94
+ },
95
+ ]),
96
+ [
97
+ '\x1B[38;5;99mStarted\x1B[0m tests/',
98
+ '!Running: t-no-timeout.js, path: tests/t-no-timeout.js',
99
+ '\x1B[32mOk:\x1B[0m no timeout test passes',
100
+ '>t-no-timeout.js completed in',
101
+ '\x1B[38;5;243mCompleted\x1B[0m tests/',
102
+ 'Testsuite: shutdown',
103
+ ],
104
+ [],
105
+ 'test runs without timeout when not specified',
106
+ );
107
+ }
@@ -20,6 +20,7 @@ export async function test() {
20
20
  const expected_stdout = [
21
21
  'Settings: no temporary storage dir',
22
22
  'Settings: logging into /tmp',
23
+ 'Settings: webdriver_chrome_args=[]',
23
24
  'Settings: chrome webdrivers',
24
25
  '\x1B[38;5;99mStarted\x1B[0m mac/',
25
26
  '\x1B[38;5;99mStarted\x1B[0m mac/unit',
@@ -33,6 +33,7 @@ export async function test() {
33
33
  const expected_stdout = [
34
34
  'Settings: no temporary storage dir',
35
35
  'Settings: logging into /tmp',
36
+ 'Settings: webdriver_chrome_args=[]',
36
37
  'Settings: chrome webdrivers',
37
38
  ...expected_out_for_success,
38
39
  ...expected_out_for_success,
@@ -35,6 +35,7 @@ export async function test() {
35
35
  [
36
36
  'Settings: no temporary storage dir',
37
37
  'Settings: logging into /tmp',
38
+ 'Settings: webdriver_chrome_args=[]',
38
39
  'Settings: chrome webdrivers',
39
40
  '\x1B[38;5;99mStarted\x1B[0m mac/',
40
41
  '\x1B[38;5;99mStarted\x1B[0m mac/unit',
@@ -33,6 +33,7 @@ export async function test() {
33
33
  const expected_stdout = [
34
34
  'Settings: no temporary storage dir',
35
35
  'Settings: logging into /tmp',
36
+ 'Settings: webdriver_chrome_args=[]',
36
37
  'Settings: chrome webdrivers',
37
38
  '\x1B[38;5;99mStarted\x1B[0m mac/',
38
39
  '\x1B[38;5;99mStarted\x1B[0m mac/webdriver',
@@ -33,6 +33,7 @@ export async function test() {
33
33
  const expected_stdout = [
34
34
  'Settings: no temporary storage dir',
35
35
  'Settings: logging into /tmp',
36
+ 'Settings: webdriver_chrome_args=[]',
36
37
  'Settings: chrome webdrivers',
37
38
  '\x1B[38;5;99mStarted\x1B[0m mac/',
38
39
  '\x1B[38;5;99mStarted\x1B[0m mac/unit',
@@ -35,6 +35,7 @@ export async function test() {
35
35
  [
36
36
  'Settings: no temporary storage dir',
37
37
  'Settings: logging into /tmp',
38
+ 'Settings: webdriver_chrome_args=[]',
38
39
  'Settings: chrome webdrivers',
39
40
  '\x1B[38;5;99mStarted\x1B[0m mac/',
40
41
 
@@ -26,6 +26,7 @@ export async function test() {
26
26
  [
27
27
  'Settings: no temporary storage dir',
28
28
  'Settings: logging into /tmp',
29
+ 'Settings: webdriver_chrome_args=[]',
29
30
  'Settings: chrome webdrivers',
30
31
  '\x1B[38;5;99mStarted\x1B[0m mac/',
31
32
  '!Running: mac/init, path: tests/meta.js',
@@ -66,6 +66,7 @@ export async function test() {
66
66
  [
67
67
  'Settings: no temporary storage dir',
68
68
  'Settings: logging into /tmp',
69
+ 'Settings: webdriver_chrome_args=[]',
69
70
  'Settings: chrome webdrivers',
70
71
  '\x1B[38;5;99mStarted\x1B[0m mac/',
71
72
  '\x1B[38;5;99mStarted\x1B[0m mac/folder1',
@@ -22,6 +22,7 @@ export async function test() {
22
22
  [
23
23
  'Settings: no temporary storage dir',
24
24
  'Settings: logging into /tmp',
25
+ 'Settings: webdriver_chrome_args=[]',
25
26
  'Settings: chrome webdrivers',
26
27
  '\x1B[38;5;99mStarted\x1B[0m mac/',
27
28
  '!Running: mac/init, path: tests/meta.js',
@@ -30,7 +30,7 @@ function getChromeOptions() {
30
30
  height: settings.webdriver_window_height,
31
31
  });
32
32
  if (settings.webdriver_headless) {
33
- chromeOptions.addArguments('headless');
33
+ chromeOptions.addArguments('headless=new');
34
34
  }
35
35
  if (settings.webdriver == 'chrome-mobile') {
36
36
  chromeOptions.setMobileEmulation({
@@ -44,6 +44,9 @@ function getChromeOptions() {
44
44
  chromeOptions.addArguments('no-sandbox');
45
45
  chromeOptions.addArguments('disable-dev-shm-usage');
46
46
 
47
+ for (const arg of settings.webdriver_chrome_args || []) {
48
+ chromeOptions.addArguments(arg);
49
+ }
47
50
  return chromeOptions;
48
51
  }
49
52