@testspectra/matchers 1.1.8-rc.2 → 1.1.8-rc.21

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.
@@ -1,453 +1,454 @@
1
- /**
2
- * Fluent assertion matchers for `SingleElementProxy`.
3
- *
4
- * Each matcher polls the bound `PlatformDriverBridge` (or the delegated state getters) with
5
- * `trackStep('assertion')` instrumentation. There is zero `activePlatform` branching here —
6
- * platform-specific behavior lives entirely in the driver's `isClickable` / `hasClass` /
7
- * state-inspection methods.
8
- */
9
-
10
- import type { AssertionOptions, ScopedSelector } from '../types';
11
-
12
- export function createElementAssertions(
13
- selector: string | ScopedSelector,
14
- index: number | null,
15
- state: Record<string, any>,
16
- ): Record<string, any> {
17
- const driver = () => globalThis.__TS_RUNTIME__.activeDriver!;
18
- const selectorText = typeof selector === 'string' ? selector : selector.selector;
19
-
20
- async function shouldBeVisible(options?: AssertionOptions): Promise<void> {
21
- return globalThis.__TS_RUNTIME__.trackStep(
22
- 'assertion',
23
- { type: 'assertion', key: 'be.visible', target: selector, args: [] },
24
- async () => {
25
- const ok = await globalThis.__TS_RUNTIME__.pollCondition(
26
- () => state.isVisible(),
27
- options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs(),
28
- );
29
- if (!ok) throw new Error(`Expected element "${selectorText}" to be visible`);
30
- },
31
- );
32
- }
33
-
34
- async function shouldNotBeVisible(options?: AssertionOptions): Promise<void> {
35
- return globalThis.__TS_RUNTIME__.trackStep(
36
- 'assertion',
37
- { type: 'assertion', key: 'not.be.visible', target: selector, args: [] },
38
- async () => {
39
- const ok = await globalThis.__TS_RUNTIME__.pollCondition(
40
- async () => !(await state.isVisible()),
41
- options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs(),
42
- );
43
- if (!ok) throw new Error(`Expected element "${selectorText}" not to be visible`);
44
- },
45
- );
46
- }
47
-
48
- async function shouldExist(options?: AssertionOptions): Promise<void> {
49
- return globalThis.__TS_RUNTIME__.trackStep(
50
- 'assertion',
51
- { type: 'assertion', key: 'exist', target: selector, args: [] },
52
- async () => {
53
- const ok = await globalThis.__TS_RUNTIME__.pollCondition(
54
- () => state.isExisting(),
55
- options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs(),
56
- );
57
- if (!ok) throw new Error(`Expected element "${selectorText}" to exist in DOM`);
58
- },
59
- );
60
- }
61
-
62
- async function shouldNotExist(options?: AssertionOptions): Promise<void> {
63
- return globalThis.__TS_RUNTIME__.trackStep(
64
- 'assertion',
65
- { type: 'assertion', key: 'not.exist', target: selector, args: [] },
66
- async () => {
67
- const ok = await globalThis.__TS_RUNTIME__.pollCondition(
68
- async () => !(await state.isExisting()),
69
- options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs(),
70
- );
71
- if (!ok) throw new Error(`Expected element "${selectorText}" not to exist in DOM`);
72
- },
73
- );
74
- }
75
-
76
- async function shouldBeEnabled(options?: AssertionOptions): Promise<void> {
77
- return globalThis.__TS_RUNTIME__.trackStep(
78
- 'assertion',
79
- { type: 'assertion', key: 'be.enabled', target: selector, args: [] },
80
- async () => {
81
- const ok = await globalThis.__TS_RUNTIME__.pollCondition(
82
- () => state.isEnabled(),
83
- options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs(),
84
- );
85
- if (!ok) throw new Error(`Expected element "${selectorText}" to be enabled`);
86
- },
87
- );
88
- }
89
-
90
- async function shouldBeDisabled(options?: AssertionOptions): Promise<void> {
91
- return globalThis.__TS_RUNTIME__.trackStep(
92
- 'assertion',
93
- { type: 'assertion', key: 'be.disabled', target: selector, args: [] },
94
- async () => {
95
- const ok = await globalThis.__TS_RUNTIME__.pollCondition(
96
- async () => !(await state.isEnabled()),
97
- options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs(),
98
- );
99
- if (!ok) throw new Error(`Expected element "${selectorText}" to be disabled`);
100
- },
101
- );
102
- }
103
-
104
- async function shouldBeClickable(options?: AssertionOptions): Promise<void> {
105
- return globalThis.__TS_RUNTIME__.trackStep(
106
- 'assertion',
107
- { type: 'assertion', key: 'be.clickable', target: selector, args: [] },
108
- async () => {
109
- const ok = await globalThis.__TS_RUNTIME__.pollCondition(
110
- () => driver().isClickable(selector, index),
111
- options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs(),
112
- );
113
- if (!ok) throw new Error(`Expected element "${selectorText}" to be clickable`);
114
- },
115
- );
116
- }
117
-
118
- async function shouldNotBeClickable(options?: AssertionOptions): Promise<void> {
119
- return globalThis.__TS_RUNTIME__.trackStep(
120
- 'assertion',
121
- { type: 'assertion', key: 'not.be.clickable', target: selector, args: [] },
122
- async () => {
123
- const ok = await globalThis.__TS_RUNTIME__.pollCondition(
124
- async () => !(await driver().isClickable(selector, index)),
125
- options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs(),
126
- );
127
- if (!ok) throw new Error(`Expected element "${selectorText}" not to be clickable`);
128
- },
129
- );
130
- }
131
-
132
- async function shouldBeChecked(options?: AssertionOptions): Promise<void> {
133
- return globalThis.__TS_RUNTIME__.trackStep(
134
- 'assertion',
135
- { type: 'assertion', key: 'be.checked', target: selector, args: [] },
136
- async () => {
137
- const ok = await globalThis.__TS_RUNTIME__.pollCondition(
138
- () => state.isChecked(),
139
- options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs(),
140
- );
141
- if (!ok) throw new Error(`Expected element "${selectorText}" to be checked`);
142
- },
143
- );
144
- }
145
-
146
- async function shouldNotBeChecked(options?: AssertionOptions): Promise<void> {
147
- return globalThis.__TS_RUNTIME__.trackStep(
148
- 'assertion',
149
- { type: 'assertion', key: 'not.be.checked', target: selector, args: [] },
150
- async () => {
151
- const ok = await globalThis.__TS_RUNTIME__.pollCondition(
152
- async () => !(await state.isChecked()),
153
- options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs(),
154
- );
155
- if (!ok) throw new Error(`Expected element "${selectorText}" not to be checked`);
156
- },
157
- );
158
- }
159
-
160
- async function shouldBeFocused(options?: AssertionOptions): Promise<void> {
161
- return globalThis.__TS_RUNTIME__.trackStep(
162
- 'assertion',
163
- { type: 'assertion', key: 'be.focused', target: selector, args: [] },
164
- async () => {
165
- const ok = await globalThis.__TS_RUNTIME__.pollCondition(
166
- () => state.isFocused(),
167
- options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs(),
168
- );
169
- if (!ok) throw new Error(`Expected element "${selectorText}" to be focused`);
170
- },
171
- );
172
- }
173
-
174
- async function shouldNotBeFocused(options?: AssertionOptions): Promise<void> {
175
- return globalThis.__TS_RUNTIME__.trackStep(
176
- 'assertion',
177
- { type: 'assertion', key: 'not.be.focused', target: selector, args: [] },
178
- async () => {
179
- const ok = await globalThis.__TS_RUNTIME__.pollCondition(
180
- async () => !(await state.isFocused()),
181
- options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs(),
182
- );
183
- if (!ok) throw new Error(`Expected element "${selectorText}" not to be focused`);
184
- },
185
- );
186
- }
187
-
188
- async function shouldHaveValue(value: unknown, options?: AssertionOptions): Promise<void> {
189
- return globalThis.__TS_RUNTIME__.trackStep(
190
- 'assertion',
191
- { type: 'assertion', key: 'have.value', target: selector, args: [value] },
192
- async () => {
193
- let actual = '';
194
- const ok = await globalThis.__TS_RUNTIME__.pollCondition(async () => {
195
- actual = await state.getValue();
196
- return actual === String(value);
197
- }, options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs());
198
- if (!ok) throw new Error(`Expected element "${selectorText}" to have value "${value}", but got "${actual}"`);
199
- },
200
- );
201
- }
202
-
203
- async function shouldNotHaveValue(value: unknown, options?: AssertionOptions): Promise<void> {
204
- return globalThis.__TS_RUNTIME__.trackStep(
205
- 'assertion',
206
- { type: 'assertion', key: 'not.have.value', target: selector, args: [value] },
207
- async () => {
208
- const ok = await globalThis.__TS_RUNTIME__.pollCondition(async () => {
209
- const actual = await state.getValue();
210
- return actual !== String(value);
211
- }, options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs());
212
- if (!ok) throw new Error(`Expected element "${selectorText}" not to have value "${value}"`);
213
- },
214
- );
215
- }
216
-
217
- async function shouldContainValue(value: unknown, options?: AssertionOptions): Promise<void> {
218
- return globalThis.__TS_RUNTIME__.trackStep(
219
- 'assertion',
220
- { type: 'assertion', key: 'contain.value', target: selector, args: [value] },
221
- async () => {
222
- let actual = '';
223
- const ok = await globalThis.__TS_RUNTIME__.pollCondition(async () => {
224
- actual = await state.getValue();
225
- return actual.includes(String(value));
226
- }, options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs());
227
- if (!ok) throw new Error(`Expected element "${selectorText}" to contain value "${value}", but got "${actual}"`);
228
- },
229
- );
230
- }
231
-
232
- async function shouldNotContainValue(value: unknown, options?: AssertionOptions): Promise<void> {
233
- return globalThis.__TS_RUNTIME__.trackStep(
234
- 'assertion',
235
- { type: 'assertion', key: 'not.contain.value', target: selector, args: [value] },
236
- async () => {
237
- const ok = await globalThis.__TS_RUNTIME__.pollCondition(async () => {
238
- const actual = await state.getValue();
239
- return !actual.includes(String(value));
240
- }, options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs());
241
- if (!ok) throw new Error(`Expected element "${selectorText}" not to contain value "${value}"`);
242
- },
243
- );
244
- }
245
-
246
- async function shouldHaveText(expected: string | RegExp, options?: AssertionOptions): Promise<void> {
247
- return globalThis.__TS_RUNTIME__.trackStep(
248
- 'assertion',
249
- { type: 'assertion', key: 'have.text', target: selector, args: [expected] },
250
- async () => {
251
- let actual = '';
252
- const ok = await globalThis.__TS_RUNTIME__.pollCondition(async () => {
253
- actual = await state.getText();
254
- if (expected instanceof RegExp) return expected.test(actual);
255
- return actual === String(expected) || actual.trim() === String(expected).trim();
256
- }, options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs());
257
- if (!ok) {
258
- if (expected instanceof RegExp)
259
- throw new Error(`Expected element "${selectorText}" text to match ${expected}, but got "${actual}"`);
260
- throw new Error(`Expected element "${selectorText}" to have text "${expected}", but got "${actual}"`);
261
- }
262
- },
263
- );
264
- }
265
-
266
- async function shouldNotHaveText(expected: string | RegExp, options?: AssertionOptions): Promise<void> {
267
- return globalThis.__TS_RUNTIME__.trackStep(
268
- 'assertion',
269
- { type: 'assertion', key: 'not.have.text', target: selector, args: [expected] },
270
- async () => {
271
- let actual = '';
272
- const ok = await globalThis.__TS_RUNTIME__.pollCondition(async () => {
273
- if (!(await state.isExisting())) return false;
274
- actual = await state.getText();
275
- if (expected instanceof RegExp) return !expected.test(actual);
276
- return actual !== String(expected) && actual.trim() !== String(expected).trim();
277
- }, options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs());
278
- if (!ok) {
279
- if (expected instanceof RegExp)
280
- throw new Error(`Expected element "${selectorText}" text not to match ${expected}`);
281
- throw new Error(`Expected element "${selectorText}" not to have text "${expected}"`);
282
- }
283
- },
284
- );
285
- }
286
-
287
- async function shouldContainText(substring: string, options?: AssertionOptions): Promise<void> {
288
- return globalThis.__TS_RUNTIME__.trackStep(
289
- 'assertion',
290
- { type: 'assertion', key: 'contain.text', target: selector, args: [substring] },
291
- async () => {
292
- let actual = '';
293
- const ok = await globalThis.__TS_RUNTIME__.pollCondition(async () => {
294
- actual = await state.getText();
295
- return actual.includes(String(substring));
296
- }, options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs());
297
- if (!ok) throw new Error(`Expected element "${selectorText}" to contain text "${substring}", but got "${actual}"`);
298
- },
299
- );
300
- }
301
-
302
- async function shouldNotContainText(substring: string, options?: AssertionOptions): Promise<void> {
303
- return globalThis.__TS_RUNTIME__.trackStep(
304
- 'assertion',
305
- { type: 'assertion', key: 'not.contain.text', target: selector, args: [substring] },
306
- async () => {
307
- const ok = await globalThis.__TS_RUNTIME__.pollCondition(async () => {
308
- const actual = await state.getText();
309
- return !actual.includes(String(substring));
310
- }, options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs());
311
- if (!ok) throw new Error(`Expected element "${selectorText}" not to contain text "${substring}"`);
312
- },
313
- );
314
- }
315
-
316
- async function shouldHaveClass(className: string, options?: AssertionOptions): Promise<void> {
317
- return globalThis.__TS_RUNTIME__.trackStep(
318
- 'assertion',
319
- { type: 'assertion', key: 'have.class', target: selector, args: [className] },
320
- async () => {
321
- const ok = await globalThis.__TS_RUNTIME__.pollCondition(
322
- () => driver().hasClass(selector, className, index),
323
- options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs(),
324
- );
325
- if (!ok) throw new Error(`Expected element "${selectorText}" to have class "${className}"`);
326
- },
327
- );
328
- }
329
-
330
- async function shouldNotHaveClass(className: string, options?: AssertionOptions): Promise<void> {
331
- return globalThis.__TS_RUNTIME__.trackStep(
332
- 'assertion',
333
- { type: 'assertion', key: 'not.have.class', target: selector, args: [className] },
334
- async () => {
335
- const ok = await globalThis.__TS_RUNTIME__.pollCondition(
336
- async () => !(await driver().hasClass(selector, className, index)),
337
- options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs(),
338
- );
339
- if (!ok) throw new Error(`Expected element "${selectorText}" not to have class "${className}"`);
340
- },
341
- );
342
- }
343
-
344
- async function shouldHaveAttribute(name: string, value?: string, options?: AssertionOptions): Promise<void> {
345
- return globalThis.__TS_RUNTIME__.trackStep(
346
- 'assertion',
347
- { type: 'assertion', key: 'have.attr', target: selector, args: value !== undefined ? [name, value] : [name] },
348
- async () => {
349
- let actual: string | null = null;
350
- const ok = await globalThis.__TS_RUNTIME__.pollCondition(async () => {
351
- actual = await state.getAttribute(name);
352
- if (value !== undefined) return actual === String(value);
353
- return actual !== null;
354
- }, options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs());
355
- if (!ok) {
356
- if (value !== undefined)
357
- throw new Error(
358
- `Expected element "${selectorText}" to have attribute "${name}" = "${value}", but got "${actual}"`,
359
- );
360
- throw new Error(`Expected element "${selectorText}" to have attribute "${name}"`);
361
- }
362
- },
363
- );
364
- }
365
-
366
- async function shouldNotHaveAttribute(name: string, options?: AssertionOptions): Promise<void> {
367
- return globalThis.__TS_RUNTIME__.trackStep(
368
- 'assertion',
369
- { type: 'assertion', key: 'not.have.attr', target: selector, args: [name] },
370
- async () => {
371
- const ok = await globalThis.__TS_RUNTIME__.pollCondition(async () => {
372
- const actual = await state.getAttribute(name);
373
- return actual === null;
374
- }, options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs());
375
- if (!ok) throw new Error(`Expected element "${selectorText}" not to have attribute "${name}"`);
376
- },
377
- );
378
- }
379
-
380
- async function shouldHaveCss(property: string, value: string, options?: AssertionOptions): Promise<void> {
381
- return globalThis.__TS_RUNTIME__.trackStep(
382
- 'assertion',
383
- { type: 'assertion', key: 'have.css', target: selector, args: [property, value] },
384
- async () => {
385
- const norm = (v: any) =>
386
- String(v ?? '')
387
- .replace(/\s+/g, '')
388
- .replace(/rgba\((.+?),1\)/, 'rgb($1)')
389
- .toLowerCase();
390
- let actualCss = '';
391
- const ok = await globalThis.__TS_RUNTIME__.pollCondition(async () => {
392
- const css = await state.getCSSProperty(property);
393
- actualCss = css.value;
394
- return norm(actualCss) === norm(value);
395
- }, options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs());
396
- if (!ok)
397
- throw new Error(
398
- `Expected element "${selectorText}" to have CSS "${property}" = "${value}", but got "${actualCss}"`,
399
- );
400
- },
401
- );
402
- }
403
-
404
- async function shouldNotHaveCss(property: string, value: string, options?: AssertionOptions): Promise<void> {
405
- return globalThis.__TS_RUNTIME__.trackStep(
406
- 'assertion',
407
- { type: 'assertion', key: 'not.have.css', target: selector, args: [property, value] },
408
- async () => {
409
- const norm = (v: any) =>
410
- String(v ?? '')
411
- .replace(/\s+/g, '')
412
- .replace(/rgba\((.+?),1\)/, 'rgb($1)')
413
- .toLowerCase();
414
- const ok = await globalThis.__TS_RUNTIME__.pollCondition(async () => {
415
- const css = await state.getCSSProperty(property);
416
- return norm(css.value) !== norm(value);
417
- }, options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs());
418
- if (!ok) throw new Error(`Expected element "${selectorText}" not to have CSS "${property}" = "${value}"`);
419
- },
420
- );
421
- }
422
-
423
- return {
424
- shouldBeVisible,
425
- shouldNotBeVisible,
426
- shouldExist,
427
- shouldNotExist,
428
- shouldBeEnabled,
429
- shouldBeDisabled,
430
- shouldBeClickable,
431
- shouldNotBeClickable,
432
- shouldBeChecked,
433
- shouldNotBeChecked,
434
- shouldBeFocused,
435
- shouldNotBeFocused,
436
- shouldHaveValue,
437
- shouldNotHaveValue,
438
- shouldContainValue,
439
- shouldNotContainValue,
440
- shouldHaveText,
441
- shouldNotHaveText,
442
- shouldContainText,
443
- shouldNotContainText,
444
- shouldHaveClass,
445
- shouldNotHaveClass,
446
- shouldHaveAttribute,
447
- shouldNotHaveAttribute,
448
- shouldHaveCss,
449
- shouldNotHaveCss,
450
- };
451
- }
452
-
453
- globalThis.__TS_RUNTIME__.createElementAssertions = createElementAssertions;
1
+ /**
2
+ * Fluent assertion matchers for `SingleElementProxy`.
3
+ *
4
+ * Each matcher polls the bound `PlatformDriverBridge` (or the delegated state getters) with
5
+ * `trackStep('assertion')` instrumentation. There is zero `activePlatform` branching here —
6
+ * platform-specific behavior lives entirely in the driver's `isClickable` / `hasClass` /
7
+ * state-inspection methods.
8
+ */
9
+
10
+ import type { AssertionOptions, ScopedSelector } from '../types.js';
11
+
12
+ export function createElementAssertions(
13
+ selector: string | ScopedSelector,
14
+ index: number | null,
15
+ state: Record<string, any>,
16
+ ): Record<string, any> {
17
+ const driver = () => globalThis.__TS_RUNTIME__.activeDriver!;
18
+ const selectorText = typeof selector === 'string' ? selector : selector.selector;
19
+
20
+ async function shouldBeVisible(options?: AssertionOptions): Promise<void> {
21
+ return globalThis.__TS_RUNTIME__.trackStep(
22
+ 'assertion',
23
+ { type: 'assertion', key: 'be.visible', target: selector, args: [] },
24
+ async () => {
25
+ const ok = await globalThis.__TS_RUNTIME__.pollCondition(
26
+ () => state.isVisible(),
27
+ options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs(),
28
+ );
29
+ if (!ok) throw new Error(`Expected element "${selectorText}" to be visible`);
30
+ },
31
+ );
32
+ }
33
+
34
+ async function shouldNotBeVisible(options?: AssertionOptions): Promise<void> {
35
+ return globalThis.__TS_RUNTIME__.trackStep(
36
+ 'assertion',
37
+ { type: 'assertion', key: 'not.be.visible', target: selector, args: [] },
38
+ async () => {
39
+ const ok = await globalThis.__TS_RUNTIME__.pollCondition(
40
+ async () => !(await state.isVisible()),
41
+ options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs(),
42
+ );
43
+ if (!ok) throw new Error(`Expected element "${selectorText}" not to be visible`);
44
+ },
45
+ );
46
+ }
47
+
48
+ async function shouldExist(options?: AssertionOptions): Promise<void> {
49
+ return globalThis.__TS_RUNTIME__.trackStep(
50
+ 'assertion',
51
+ { type: 'assertion', key: 'exist', target: selector, args: [] },
52
+ async () => {
53
+ const ok = await globalThis.__TS_RUNTIME__.pollCondition(
54
+ () => state.isExisting(),
55
+ options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs(),
56
+ );
57
+ if (!ok) throw new Error(`Expected element "${selectorText}" to exist in DOM`);
58
+ },
59
+ );
60
+ }
61
+
62
+ async function shouldNotExist(options?: AssertionOptions): Promise<void> {
63
+ return globalThis.__TS_RUNTIME__.trackStep(
64
+ 'assertion',
65
+ { type: 'assertion', key: 'not.exist', target: selector, args: [] },
66
+ async () => {
67
+ const ok = await globalThis.__TS_RUNTIME__.pollCondition(
68
+ async () => !(await state.isExisting()),
69
+ options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs(),
70
+ );
71
+ if (!ok) throw new Error(`Expected element "${selectorText}" not to exist in DOM`);
72
+ },
73
+ );
74
+ }
75
+
76
+ async function shouldBeEnabled(options?: AssertionOptions): Promise<void> {
77
+ return globalThis.__TS_RUNTIME__.trackStep(
78
+ 'assertion',
79
+ { type: 'assertion', key: 'be.enabled', target: selector, args: [] },
80
+ async () => {
81
+ const ok = await globalThis.__TS_RUNTIME__.pollCondition(
82
+ () => state.isEnabled(),
83
+ options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs(),
84
+ );
85
+ if (!ok) throw new Error(`Expected element "${selectorText}" to be enabled`);
86
+ },
87
+ );
88
+ }
89
+
90
+ async function shouldBeDisabled(options?: AssertionOptions): Promise<void> {
91
+ return globalThis.__TS_RUNTIME__.trackStep(
92
+ 'assertion',
93
+ { type: 'assertion', key: 'be.disabled', target: selector, args: [] },
94
+ async () => {
95
+ const ok = await globalThis.__TS_RUNTIME__.pollCondition(
96
+ async () => !(await state.isEnabled()),
97
+ options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs(),
98
+ );
99
+ if (!ok) throw new Error(`Expected element "${selectorText}" to be disabled`);
100
+ },
101
+ );
102
+ }
103
+
104
+ async function shouldBeClickable(options?: AssertionOptions): Promise<void> {
105
+ return globalThis.__TS_RUNTIME__.trackStep(
106
+ 'assertion',
107
+ { type: 'assertion', key: 'be.clickable', target: selector, args: [] },
108
+ async () => {
109
+ const ok = await globalThis.__TS_RUNTIME__.pollCondition(
110
+ () => driver().isClickable(selector, index),
111
+ options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs(),
112
+ );
113
+ if (!ok) throw new Error(`Expected element "${selectorText}" to be clickable`);
114
+ },
115
+ );
116
+ }
117
+
118
+ async function shouldNotBeClickable(options?: AssertionOptions): Promise<void> {
119
+ return globalThis.__TS_RUNTIME__.trackStep(
120
+ 'assertion',
121
+ { type: 'assertion', key: 'not.be.clickable', target: selector, args: [] },
122
+ async () => {
123
+ const ok = await globalThis.__TS_RUNTIME__.pollCondition(
124
+ async () => !(await driver().isClickable(selector, index)),
125
+ options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs(),
126
+ );
127
+ if (!ok) throw new Error(`Expected element "${selectorText}" not to be clickable`);
128
+ },
129
+ );
130
+ }
131
+
132
+ async function shouldBeChecked(options?: AssertionOptions): Promise<void> {
133
+ return globalThis.__TS_RUNTIME__.trackStep(
134
+ 'assertion',
135
+ { type: 'assertion', key: 'be.checked', target: selector, args: [] },
136
+ async () => {
137
+ const ok = await globalThis.__TS_RUNTIME__.pollCondition(
138
+ () => state.isChecked(),
139
+ options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs(),
140
+ );
141
+ if (!ok) throw new Error(`Expected element "${selectorText}" to be checked`);
142
+ },
143
+ );
144
+ }
145
+
146
+ async function shouldNotBeChecked(options?: AssertionOptions): Promise<void> {
147
+ return globalThis.__TS_RUNTIME__.trackStep(
148
+ 'assertion',
149
+ { type: 'assertion', key: 'not.be.checked', target: selector, args: [] },
150
+ async () => {
151
+ const ok = await globalThis.__TS_RUNTIME__.pollCondition(
152
+ async () => !(await state.isChecked()),
153
+ options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs(),
154
+ );
155
+ if (!ok) throw new Error(`Expected element "${selectorText}" not to be checked`);
156
+ },
157
+ );
158
+ }
159
+
160
+ async function shouldBeFocused(options?: AssertionOptions): Promise<void> {
161
+ return globalThis.__TS_RUNTIME__.trackStep(
162
+ 'assertion',
163
+ { type: 'assertion', key: 'be.focused', target: selector, args: [] },
164
+ async () => {
165
+ const ok = await globalThis.__TS_RUNTIME__.pollCondition(
166
+ () => state.isFocused(),
167
+ options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs(),
168
+ );
169
+ if (!ok) throw new Error(`Expected element "${selectorText}" to be focused`);
170
+ },
171
+ );
172
+ }
173
+
174
+ async function shouldNotBeFocused(options?: AssertionOptions): Promise<void> {
175
+ return globalThis.__TS_RUNTIME__.trackStep(
176
+ 'assertion',
177
+ { type: 'assertion', key: 'not.be.focused', target: selector, args: [] },
178
+ async () => {
179
+ const ok = await globalThis.__TS_RUNTIME__.pollCondition(
180
+ async () => !(await state.isFocused()),
181
+ options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs(),
182
+ );
183
+ if (!ok) throw new Error(`Expected element "${selectorText}" not to be focused`);
184
+ },
185
+ );
186
+ }
187
+
188
+ async function shouldHaveValue(value: unknown, options?: AssertionOptions): Promise<void> {
189
+ return globalThis.__TS_RUNTIME__.trackStep(
190
+ 'assertion',
191
+ { type: 'assertion', key: 'have.value', target: selector, args: [value] },
192
+ async () => {
193
+ let actual = '';
194
+ const ok = await globalThis.__TS_RUNTIME__.pollCondition(async () => {
195
+ actual = await state.getValue();
196
+ return actual === String(value);
197
+ }, options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs());
198
+ if (!ok) throw new Error(`Expected element "${selectorText}" to have value "${value}", but got "${actual}"`);
199
+ },
200
+ );
201
+ }
202
+
203
+ async function shouldNotHaveValue(value: unknown, options?: AssertionOptions): Promise<void> {
204
+ return globalThis.__TS_RUNTIME__.trackStep(
205
+ 'assertion',
206
+ { type: 'assertion', key: 'not.have.value', target: selector, args: [value] },
207
+ async () => {
208
+ const ok = await globalThis.__TS_RUNTIME__.pollCondition(async () => {
209
+ const actual = await state.getValue();
210
+ return actual !== String(value);
211
+ }, options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs());
212
+ if (!ok) throw new Error(`Expected element "${selectorText}" not to have value "${value}"`);
213
+ },
214
+ );
215
+ }
216
+
217
+ async function shouldContainValue(value: unknown, options?: AssertionOptions): Promise<void> {
218
+ return globalThis.__TS_RUNTIME__.trackStep(
219
+ 'assertion',
220
+ { type: 'assertion', key: 'contain.value', target: selector, args: [value] },
221
+ async () => {
222
+ let actual = '';
223
+ const ok = await globalThis.__TS_RUNTIME__.pollCondition(async () => {
224
+ actual = await state.getValue();
225
+ return actual.includes(String(value));
226
+ }, options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs());
227
+ if (!ok) throw new Error(`Expected element "${selectorText}" to contain value "${value}", but got "${actual}"`);
228
+ },
229
+ );
230
+ }
231
+
232
+ async function shouldNotContainValue(value: unknown, options?: AssertionOptions): Promise<void> {
233
+ return globalThis.__TS_RUNTIME__.trackStep(
234
+ 'assertion',
235
+ { type: 'assertion', key: 'not.contain.value', target: selector, args: [value] },
236
+ async () => {
237
+ const ok = await globalThis.__TS_RUNTIME__.pollCondition(async () => {
238
+ const actual = await state.getValue();
239
+ return !actual.includes(String(value));
240
+ }, options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs());
241
+ if (!ok) throw new Error(`Expected element "${selectorText}" not to contain value "${value}"`);
242
+ },
243
+ );
244
+ }
245
+
246
+ async function shouldHaveText(expected: string | RegExp, options?: AssertionOptions): Promise<void> {
247
+ return globalThis.__TS_RUNTIME__.trackStep(
248
+ 'assertion',
249
+ { type: 'assertion', key: 'have.text', target: selector, args: [expected] },
250
+ async () => {
251
+ let actual = '';
252
+ const ok = await globalThis.__TS_RUNTIME__.pollCondition(async () => {
253
+ actual = await state.getText();
254
+ if (expected instanceof RegExp) return expected.test(actual);
255
+ return actual === String(expected) || actual.trim() === String(expected).trim();
256
+ }, options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs());
257
+ if (!ok) {
258
+ if (expected instanceof RegExp)
259
+ throw new Error(`Expected element "${selectorText}" text to match ${expected}, but got "${actual}"`);
260
+ throw new Error(`Expected element "${selectorText}" to have text "${expected}", but got "${actual}"`);
261
+ }
262
+ },
263
+ );
264
+ }
265
+
266
+ async function shouldNotHaveText(expected: string | RegExp, options?: AssertionOptions): Promise<void> {
267
+ return globalThis.__TS_RUNTIME__.trackStep(
268
+ 'assertion',
269
+ { type: 'assertion', key: 'not.have.text', target: selector, args: [expected] },
270
+ async () => {
271
+ let actual = '';
272
+ const ok = await globalThis.__TS_RUNTIME__.pollCondition(async () => {
273
+ if (!(await state.isExisting())) return false;
274
+ actual = await state.getText();
275
+ if (expected instanceof RegExp) return !expected.test(actual);
276
+ return actual !== String(expected) && actual.trim() !== String(expected).trim();
277
+ }, options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs());
278
+ if (!ok) {
279
+ if (expected instanceof RegExp)
280
+ throw new Error(`Expected element "${selectorText}" text not to match ${expected}`);
281
+ throw new Error(`Expected element "${selectorText}" not to have text "${expected}"`);
282
+ }
283
+ },
284
+ );
285
+ }
286
+
287
+ async function shouldContainText(substring: string, options?: AssertionOptions): Promise<void> {
288
+ return globalThis.__TS_RUNTIME__.trackStep(
289
+ 'assertion',
290
+ { type: 'assertion', key: 'contain.text', target: selector, args: [substring] },
291
+ async () => {
292
+ let actual = '';
293
+ const ok = await globalThis.__TS_RUNTIME__.pollCondition(async () => {
294
+ actual = await state.getText();
295
+ return actual.includes(String(substring));
296
+ }, options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs());
297
+ if (!ok)
298
+ throw new Error(`Expected element "${selectorText}" to contain text "${substring}", but got "${actual}"`);
299
+ },
300
+ );
301
+ }
302
+
303
+ async function shouldNotContainText(substring: string, options?: AssertionOptions): Promise<void> {
304
+ return globalThis.__TS_RUNTIME__.trackStep(
305
+ 'assertion',
306
+ { type: 'assertion', key: 'not.contain.text', target: selector, args: [substring] },
307
+ async () => {
308
+ const ok = await globalThis.__TS_RUNTIME__.pollCondition(async () => {
309
+ const actual = await state.getText();
310
+ return !actual.includes(String(substring));
311
+ }, options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs());
312
+ if (!ok) throw new Error(`Expected element "${selectorText}" not to contain text "${substring}"`);
313
+ },
314
+ );
315
+ }
316
+
317
+ async function shouldHaveClass(className: string, options?: AssertionOptions): Promise<void> {
318
+ return globalThis.__TS_RUNTIME__.trackStep(
319
+ 'assertion',
320
+ { type: 'assertion', key: 'have.class', target: selector, args: [className] },
321
+ async () => {
322
+ const ok = await globalThis.__TS_RUNTIME__.pollCondition(
323
+ () => driver().hasClass(selector, className, index),
324
+ options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs(),
325
+ );
326
+ if (!ok) throw new Error(`Expected element "${selectorText}" to have class "${className}"`);
327
+ },
328
+ );
329
+ }
330
+
331
+ async function shouldNotHaveClass(className: string, options?: AssertionOptions): Promise<void> {
332
+ return globalThis.__TS_RUNTIME__.trackStep(
333
+ 'assertion',
334
+ { type: 'assertion', key: 'not.have.class', target: selector, args: [className] },
335
+ async () => {
336
+ const ok = await globalThis.__TS_RUNTIME__.pollCondition(
337
+ async () => !(await driver().hasClass(selector, className, index)),
338
+ options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs(),
339
+ );
340
+ if (!ok) throw new Error(`Expected element "${selectorText}" not to have class "${className}"`);
341
+ },
342
+ );
343
+ }
344
+
345
+ async function shouldHaveAttribute(name: string, value?: string, options?: AssertionOptions): Promise<void> {
346
+ return globalThis.__TS_RUNTIME__.trackStep(
347
+ 'assertion',
348
+ { type: 'assertion', key: 'have.attr', target: selector, args: value !== undefined ? [name, value] : [name] },
349
+ async () => {
350
+ let actual: string | null = null;
351
+ const ok = await globalThis.__TS_RUNTIME__.pollCondition(async () => {
352
+ actual = await state.getAttribute(name);
353
+ if (value !== undefined) return actual === String(value);
354
+ return actual !== null;
355
+ }, options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs());
356
+ if (!ok) {
357
+ if (value !== undefined)
358
+ throw new Error(
359
+ `Expected element "${selectorText}" to have attribute "${name}" = "${value}", but got "${actual}"`,
360
+ );
361
+ throw new Error(`Expected element "${selectorText}" to have attribute "${name}"`);
362
+ }
363
+ },
364
+ );
365
+ }
366
+
367
+ async function shouldNotHaveAttribute(name: string, options?: AssertionOptions): Promise<void> {
368
+ return globalThis.__TS_RUNTIME__.trackStep(
369
+ 'assertion',
370
+ { type: 'assertion', key: 'not.have.attr', target: selector, args: [name] },
371
+ async () => {
372
+ const ok = await globalThis.__TS_RUNTIME__.pollCondition(async () => {
373
+ const actual = await state.getAttribute(name);
374
+ return actual === null;
375
+ }, options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs());
376
+ if (!ok) throw new Error(`Expected element "${selectorText}" not to have attribute "${name}"`);
377
+ },
378
+ );
379
+ }
380
+
381
+ async function shouldHaveCss(property: string, value: string, options?: AssertionOptions): Promise<void> {
382
+ return globalThis.__TS_RUNTIME__.trackStep(
383
+ 'assertion',
384
+ { type: 'assertion', key: 'have.css', target: selector, args: [property, value] },
385
+ async () => {
386
+ const norm = (v: any) =>
387
+ String(v ?? '')
388
+ .replace(/\s+/g, '')
389
+ .replace(/rgba\((.+?),1\)/, 'rgb($1)')
390
+ .toLowerCase();
391
+ let actualCss = '';
392
+ const ok = await globalThis.__TS_RUNTIME__.pollCondition(async () => {
393
+ const css = await state.getCSSProperty(property);
394
+ actualCss = css.value;
395
+ return norm(actualCss) === norm(value);
396
+ }, options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs());
397
+ if (!ok)
398
+ throw new Error(
399
+ `Expected element "${selectorText}" to have CSS "${property}" = "${value}", but got "${actualCss}"`,
400
+ );
401
+ },
402
+ );
403
+ }
404
+
405
+ async function shouldNotHaveCss(property: string, value: string, options?: AssertionOptions): Promise<void> {
406
+ return globalThis.__TS_RUNTIME__.trackStep(
407
+ 'assertion',
408
+ { type: 'assertion', key: 'not.have.css', target: selector, args: [property, value] },
409
+ async () => {
410
+ const norm = (v: any) =>
411
+ String(v ?? '')
412
+ .replace(/\s+/g, '')
413
+ .replace(/rgba\((.+?),1\)/, 'rgb($1)')
414
+ .toLowerCase();
415
+ const ok = await globalThis.__TS_RUNTIME__.pollCondition(async () => {
416
+ const css = await state.getCSSProperty(property);
417
+ return norm(css.value) !== norm(value);
418
+ }, options?.timeoutMs ?? globalThis.__TS_RUNTIME__.getAssertionTimeoutMs());
419
+ if (!ok) throw new Error(`Expected element "${selectorText}" not to have CSS "${property}" = "${value}"`);
420
+ },
421
+ );
422
+ }
423
+
424
+ return {
425
+ shouldBeVisible,
426
+ shouldNotBeVisible,
427
+ shouldExist,
428
+ shouldNotExist,
429
+ shouldBeEnabled,
430
+ shouldBeDisabled,
431
+ shouldBeClickable,
432
+ shouldNotBeClickable,
433
+ shouldBeChecked,
434
+ shouldNotBeChecked,
435
+ shouldBeFocused,
436
+ shouldNotBeFocused,
437
+ shouldHaveValue,
438
+ shouldNotHaveValue,
439
+ shouldContainValue,
440
+ shouldNotContainValue,
441
+ shouldHaveText,
442
+ shouldNotHaveText,
443
+ shouldContainText,
444
+ shouldNotContainText,
445
+ shouldHaveClass,
446
+ shouldNotHaveClass,
447
+ shouldHaveAttribute,
448
+ shouldNotHaveAttribute,
449
+ shouldHaveCss,
450
+ shouldNotHaveCss,
451
+ };
452
+ }
453
+
454
+ globalThis.__TS_RUNTIME__.createElementAssertions = createElementAssertions;