@camperaid/watest 2.3.4 → 2.3.8
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 +5 -0
- package/core/base.js +12 -3
- package/core/core.js +7 -7
- package/core/series.js +17 -1
- package/core/settings.js +4 -0
- package/core/util.js +4 -3
- package/package.json +1 -1
- package/tests/base/t_is_object.js +19 -0
- package/tests/base/t_stringify.js +1 -0
- package/tests/e2e/samples/folder/node_modules/.package-lock.json +1 -1
- package/tests/e2e/samples/folder/package-lock.json +1 -1
- package/tests/e2e/samples/loader/node_modules/.package-lock.json +1 -1
- package/tests/e2e/samples/loader/package-lock.json +1 -1
- package/tests/e2e/samples/loader_mixed/node_modules/.package-lock.json +1 -1
- package/tests/e2e/samples/loader_mixed/package-lock.json +1 -1
- package/tests/e2e/samples/loader_multiple/node_modules/.package-lock.json +1 -1
- package/tests/e2e/samples/loader_multiple/package-lock.json +1 -1
- package/tests/e2e/samples/single/node_modules/.package-lock.json +1 -1
- package/tests/e2e/samples/single/package-lock.json +1 -1
- package/tests/e2e/samples/wd_mixed/node_modules/.package-lock.json +1 -1
- package/tests/e2e/samples/wd_mixed/package-lock.json +1 -1
- package/tests/e2e/samples/wd_single/node_modules/.package-lock.json +1 -1
- package/tests/e2e/samples/wd_single/package-lock.json +1 -1
- package/tests/webdriver/t_app_driver.js +2 -2
- package/webdriver/app_driver.js +20 -3
- package/webdriver/driver.js +66 -5
package/.watestrc.js
CHANGED
|
@@ -18,6 +18,11 @@ const cfg = {
|
|
|
18
18
|
*/
|
|
19
19
|
log_dir: process.env.WATEST_LOG_DIR,
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* If a test takes longer than the given number, the test will fail.
|
|
23
|
+
*/
|
|
24
|
+
timeout: process.env.WATEST_TIMEOUT,
|
|
25
|
+
|
|
21
26
|
/**
|
|
22
27
|
* Temporary storage dir. Recreated each test run. Shall be used to store
|
|
23
28
|
* files generated by tests if any.
|
package/core/base.js
CHANGED
|
@@ -324,6 +324,17 @@ function is_object_impl(
|
|
|
324
324
|
return false;
|
|
325
325
|
}
|
|
326
326
|
|
|
327
|
+
// Date
|
|
328
|
+
if (got instanceof Date) {
|
|
329
|
+
if (got.valueOf() == expected.valueOf()) {
|
|
330
|
+
return true;
|
|
331
|
+
}
|
|
332
|
+
let got_str = stringify(got);
|
|
333
|
+
let expected_str = `expected: ${stringify(expected)}`;
|
|
334
|
+
fail_(`${contextmsg} unexpected value: ${got_str}, ${expected_str}`);
|
|
335
|
+
return false;
|
|
336
|
+
}
|
|
337
|
+
|
|
327
338
|
// Convert Set and Map to Arrays.
|
|
328
339
|
if (got instanceof Set) {
|
|
329
340
|
got = Array.from(got.values());
|
|
@@ -537,9 +548,7 @@ function is_out(got, expected, msg) {
|
|
|
537
548
|
|
|
538
549
|
let min = Math.min(got_i.length, exp_i.length);
|
|
539
550
|
for (let j = 0; j < min; j++) {
|
|
540
|
-
log_error(
|
|
541
|
-
`${j}\t'${got_i[j]}'\t'${exp_i[j]}'\t${exp_i[j] == got_i[j]}`
|
|
542
|
-
);
|
|
551
|
+
log_error(`${j}\t'${got_i[j]}'\t'${exp_i[j]}'\t${exp_i[j] == got_i[j]}`);
|
|
543
552
|
}
|
|
544
553
|
|
|
545
554
|
for (let j = min; j < got_i.length; j++) {
|
package/core/core.js
CHANGED
|
@@ -57,11 +57,16 @@ class Core {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
fail(msg) {
|
|
60
|
-
|
|
60
|
+
if (typeof msg == 'object') {
|
|
61
|
+
inspect(msg);
|
|
62
|
+
this.unconditional_fail('Unexpected exception');
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
61
66
|
for (let v of this.expectedFailures) {
|
|
62
67
|
if (v.group == '*' || v.group == this.currgroup) {
|
|
63
68
|
let f = v.list.find(f => f[1] == 0 || f[0] == '*');
|
|
64
|
-
if (f && (f[0] == '*' ||
|
|
69
|
+
if (f && (f[0] == '*' || msg.includes(f[0]))) {
|
|
65
70
|
f[1]++;
|
|
66
71
|
this.warn(msg);
|
|
67
72
|
|
|
@@ -78,11 +83,6 @@ class Core {
|
|
|
78
83
|
}
|
|
79
84
|
}
|
|
80
85
|
|
|
81
|
-
if (typeof msg == 'object') {
|
|
82
|
-
inspect(msg);
|
|
83
|
-
msg = 'Unexpected exception';
|
|
84
|
-
}
|
|
85
|
-
|
|
86
86
|
this.unconditional_fail(msg);
|
|
87
87
|
}
|
|
88
88
|
|
package/core/series.js
CHANGED
|
@@ -637,7 +637,23 @@ class Series {
|
|
|
637
637
|
let start_time = new Date();
|
|
638
638
|
try {
|
|
639
639
|
this.core.setExpectedFailures(failures_info);
|
|
640
|
-
|
|
640
|
+
|
|
641
|
+
// If timeout is given then race it against the test.
|
|
642
|
+
if (settings.timeout) {
|
|
643
|
+
let kungFuDeathGripTimer = 0;
|
|
644
|
+
let kungFuDeathGrip = new Promise(r => {
|
|
645
|
+
kungFuDeathGripTimer = setTimeout(r, settings.timeout);
|
|
646
|
+
}).then(() =>
|
|
647
|
+
fail(
|
|
648
|
+
`Test ${name} takes longer than ${settings.timeout}ms. It's either slow or never ends.`
|
|
649
|
+
)
|
|
650
|
+
);
|
|
651
|
+
|
|
652
|
+
await Promise.race([func(), kungFuDeathGrip]);
|
|
653
|
+
clearTimeout(kungFuDeathGripTimer);
|
|
654
|
+
} else {
|
|
655
|
+
await func(); // execute the test
|
|
656
|
+
}
|
|
641
657
|
} catch (e) {
|
|
642
658
|
let failmsg = e;
|
|
643
659
|
if (e instanceof Error) {
|
package/core/settings.js
CHANGED
package/core/util.js
CHANGED
|
@@ -8,9 +8,7 @@ const cfg = require('./settings.js');
|
|
|
8
8
|
* Logs object in console colored.
|
|
9
9
|
*/
|
|
10
10
|
function inspect(obj) {
|
|
11
|
-
log(
|
|
12
|
-
require('util').inspect(obj, false, null, true /* enable colors */)
|
|
13
|
-
);
|
|
11
|
+
log(require('util').inspect(obj, false, null, true /* enable colors */));
|
|
14
12
|
}
|
|
15
13
|
|
|
16
14
|
/**
|
|
@@ -31,6 +29,9 @@ function stringify(obj, traces = new Set()) {
|
|
|
31
29
|
if (obj instanceof Array) {
|
|
32
30
|
return `[${obj.map(i => stringify(i, traces)).join(', ')}]`;
|
|
33
31
|
}
|
|
32
|
+
if (obj instanceof Date) {
|
|
33
|
+
return obj.toISOString();
|
|
34
|
+
}
|
|
34
35
|
if (obj instanceof Set) {
|
|
35
36
|
let values = Array.from(obj.values());
|
|
36
37
|
return `Set[${values.map(i => stringify(i, traces)).join(', ')}]`;
|
package/package.json
CHANGED
|
@@ -27,6 +27,25 @@ module.exports.test = async () => {
|
|
|
27
27
|
`types: Map`
|
|
28
28
|
);
|
|
29
29
|
|
|
30
|
+
// types: Date success
|
|
31
|
+
await is_output(
|
|
32
|
+
() => is_object(new Date('2022-01-01'), new Date('2022-01-01'), 'TstMsg'),
|
|
33
|
+
[`Ok: TstMsg, got: 2022-01-01T00:00:00.000Z`],
|
|
34
|
+
[],
|
|
35
|
+
`types: Date sucess`
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
// types: Date failure
|
|
39
|
+
await is_output(
|
|
40
|
+
() => is_object(new Date('2022-01-01'), new Date('2023-02-02'), 'TstMsg'),
|
|
41
|
+
[],
|
|
42
|
+
[
|
|
43
|
+
`Failed: TstMsg: unexpected value: 2022-01-01T00:00:00.000Z, expected: 2023-02-02T00:00:00.000Z`,
|
|
44
|
+
`Failed: TstMsg`,
|
|
45
|
+
],
|
|
46
|
+
`types: Date failure`
|
|
47
|
+
);
|
|
48
|
+
|
|
30
49
|
// function sucess
|
|
31
50
|
await is_output(
|
|
32
51
|
() => is_object({ field: 'hey' }, () => true, 'TstMsg'),
|
|
@@ -21,6 +21,7 @@ module.exports.test = () => {
|
|
|
21
21
|
is(stringify(new Set(['v1', 'v2'])), `Set['v1', 'v2']`, 'set');
|
|
22
22
|
is(stringify(new Map([['key', 'value']])), `Map{key: 'value'}`, 'map');
|
|
23
23
|
is(stringify(/\d+/), `/\\d+/`, 'regexp');
|
|
24
|
+
is(stringify(new Date('2022-01-01')), '2022-01-01T00:00:00.000Z', `Date`);
|
|
24
25
|
|
|
25
26
|
// functions
|
|
26
27
|
is(
|
|
@@ -25,7 +25,7 @@ module.exports.test = do_self_tests(snippet, async session => {
|
|
|
25
25
|
`Test: Input is shown. Selector: '#input'`,
|
|
26
26
|
`Ok: '#input' has to be unique, got: 1`,
|
|
27
27
|
`Ok: Input is shown`,
|
|
28
|
-
`Action: Input.type into Type hello`,
|
|
28
|
+
`Action: Input.type 'hello' into Type hello`,
|
|
29
29
|
`Test: Focus. Selector: '#input'`,
|
|
30
30
|
`Ok: '#input' has to be unique, got: 1`,
|
|
31
31
|
`Ok: Focus`,
|
|
@@ -47,7 +47,7 @@ module.exports.test = do_self_tests(snippet, async session => {
|
|
|
47
47
|
`Test: Input is shown. Selector: '#input'`,
|
|
48
48
|
`Ok: '#input' has to be unique, got: 1`,
|
|
49
49
|
`Ok: Input is shown`,
|
|
50
|
-
`Action: Input.type into Type hello`,
|
|
50
|
+
`Action: Input.type 'hello' into Type hello`,
|
|
51
51
|
`Test: Focus. Selector: '#input'`,
|
|
52
52
|
`Ok: '#input' has to be unique, got: 1`,
|
|
53
53
|
`Ok: Focus`,
|
package/webdriver/app_driver.js
CHANGED
|
@@ -73,7 +73,7 @@ class AppDriver {
|
|
|
73
73
|
|
|
74
74
|
type(selector, value, field) {
|
|
75
75
|
return this.chain(() =>
|
|
76
|
-
this.action(`${this.uiname}.type into ${field}`)
|
|
76
|
+
this.action(`${this.uiname}.type '${value}' into ${field}`)
|
|
77
77
|
.sendKeys(selector, '', `Focus`)
|
|
78
78
|
.elementFocused(selector, 'Focused')
|
|
79
79
|
.selectAll(selector, `Select all text`)
|
|
@@ -82,6 +82,14 @@ class AppDriver {
|
|
|
82
82
|
);
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
clear(selector, field) {
|
|
86
|
+
return this.chain(() =>
|
|
87
|
+
this.action(`${this.uiname}.clear ${field}`)
|
|
88
|
+
.clear(selector, `Clear text`)
|
|
89
|
+
.textIs(selector, '', `Check ${field} text`)
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
85
93
|
setValue(selector, value, field) {
|
|
86
94
|
return this.chain(() =>
|
|
87
95
|
this.action(`${this.uiname}.setValue for ${field}`)
|
|
@@ -100,7 +108,7 @@ class AppDriver {
|
|
|
100
108
|
|
|
101
109
|
uncheck(selector, field) {
|
|
102
110
|
return this.chain(() =>
|
|
103
|
-
this.action(`${this.
|
|
111
|
+
this.action(`${this.uiname}.uncheck ${field}`)
|
|
104
112
|
.click(selector, `Click at ${field}`)
|
|
105
113
|
.hasElements(
|
|
106
114
|
`${selector}:not(:checked)`,
|
|
@@ -109,10 +117,19 @@ class AppDriver {
|
|
|
109
117
|
);
|
|
110
118
|
}
|
|
111
119
|
|
|
120
|
+
execute(script, descr) {
|
|
121
|
+
return this.chain(() =>
|
|
122
|
+
this.action(`${this.uiname}.execute ${descr}`)
|
|
123
|
+
.executeScript(script, `Execute script`)
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
112
127
|
// Returns a name for the tested class. Typically the name convension for
|
|
113
128
|
// UI drivers is a test class name postixed by Driver.
|
|
114
129
|
get uiname() {
|
|
115
|
-
|
|
130
|
+
let o = this;
|
|
131
|
+
while ((o = Object.getPrototypeOf(o)) && o.constructor.name == '');
|
|
132
|
+
return o.constructor.name.replace(/Driver$/, '');
|
|
116
133
|
}
|
|
117
134
|
|
|
118
135
|
defineSelectors(context, selectors) {
|
package/webdriver/driver.js
CHANGED
|
@@ -169,13 +169,47 @@ class Driver extends DriverBase {
|
|
|
169
169
|
);
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
+
/**
|
|
173
|
+
* Waits untils an element defined by a selector has attribute.
|
|
174
|
+
*/
|
|
175
|
+
hasAttribute(selector, attr, msg) {
|
|
176
|
+
assert(selector, `hasAttribute: no selector`);
|
|
177
|
+
assert(attr, `hasAttribute: no attr`);
|
|
178
|
+
assert(msg, `hasAttribute: no msg`);
|
|
179
|
+
|
|
180
|
+
return this.matchAttribute({
|
|
181
|
+
selector,
|
|
182
|
+
attr,
|
|
183
|
+
msg,
|
|
184
|
+
test: got => got !== null,
|
|
185
|
+
expected_stringified: stringify(null),
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Waits untils an element defined by a selector has no attribute.
|
|
191
|
+
*/
|
|
192
|
+
noAttribute(selector, attr, msg) {
|
|
193
|
+
assert(selector, `noAttribute: no selector`);
|
|
194
|
+
assert(attr, `noAttribute: no attr`);
|
|
195
|
+
assert(msg, `noAttribute: no msg`);
|
|
196
|
+
|
|
197
|
+
return this.matchAttribute({
|
|
198
|
+
selector,
|
|
199
|
+
attr,
|
|
200
|
+
msg,
|
|
201
|
+
test: got => got === null,
|
|
202
|
+
expected_stringified: stringify(null),
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
172
206
|
/**
|
|
173
207
|
* Waits untils an element defined by a selector has attribute of a given value.
|
|
174
208
|
*/
|
|
175
209
|
attributeIs(selector, attr, value, msg) {
|
|
176
210
|
assert(selector, `attributeIs: no selector`);
|
|
177
211
|
assert(attr, `attributeIs: no attr`);
|
|
178
|
-
assert(value
|
|
212
|
+
assert(value !== undefined, `attributeIs: no value`);
|
|
179
213
|
assert(msg, `attributeIs: no msg`);
|
|
180
214
|
|
|
181
215
|
return this.matchAttribute({
|
|
@@ -187,6 +221,29 @@ class Driver extends DriverBase {
|
|
|
187
221
|
});
|
|
188
222
|
}
|
|
189
223
|
|
|
224
|
+
/**
|
|
225
|
+
* Waits untils an element defined by a selector has attribute of a given value.
|
|
226
|
+
*/
|
|
227
|
+
attributeIsAll(selector, attr, values, msg) {
|
|
228
|
+
assert(selector, `attributeIsAll: no selector`);
|
|
229
|
+
assert(attr, `attributeIsAll: no attr`);
|
|
230
|
+
assert(values, `attributeIsAll: no values`);
|
|
231
|
+
assert(msg, `attributeIsAll: no msg`);
|
|
232
|
+
|
|
233
|
+
return this.matchAttributeAll({
|
|
234
|
+
selector,
|
|
235
|
+
attr,
|
|
236
|
+
values,
|
|
237
|
+
msg,
|
|
238
|
+
test: got =>
|
|
239
|
+
test_is(
|
|
240
|
+
got,
|
|
241
|
+
values.map(value => got => got == value)
|
|
242
|
+
),
|
|
243
|
+
expected_stringified: stringify(values),
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
|
|
190
247
|
/**
|
|
191
248
|
* Waits untils an element defined by a selector has attribute of a given value.
|
|
192
249
|
*/
|
|
@@ -800,10 +857,14 @@ else {
|
|
|
800
857
|
window.getSelection().addRange(r);
|
|
801
858
|
}
|
|
802
859
|
`;
|
|
803
|
-
return this.run(
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
860
|
+
return this.run(
|
|
861
|
+
() =>
|
|
862
|
+
this.dvr.executeScript(script).catch(e => {
|
|
863
|
+
fail(`Failed to execute selectAll script: ${script}`);
|
|
864
|
+
throw e;
|
|
865
|
+
}),
|
|
866
|
+
msg
|
|
867
|
+
);
|
|
807
868
|
}
|
|
808
869
|
|
|
809
870
|
/**
|