@testspectra/matchers 1.1.8-rc.2 → 1.1.8-rc.4
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/dist/__tests__/matcher-contracts.test.d.ts +1 -0
- package/dist/__tests__/matcher-contracts.test.js +498 -0
- package/dist/__tests__/matchers.test.js +8 -0
- package/dist/matchers.d.ts +10 -3
- package/dist/matchers.js +576 -135
- package/dist/reporter.js +13 -1
- package/dist/runner/collection.d.ts +4 -16
- package/dist/runner/collection.js +44 -30
- package/dist/runner/single.d.ts +4 -30
- package/dist/runner/single.js +60 -62
- package/dist/spectra.d.ts +3 -3
- package/dist/spectra.js +3 -3
- package/package.json +1 -1
- package/src/contract.ts +223 -223
- package/src/proto.ts +35 -35
- package/src/runtime/assertions.ts +453 -453
- package/src/runtime/element_actions.ts +178 -178
- package/src/runtime/element_proxy.ts +200 -200
- package/src/runtime/element_state.ts +94 -94
- package/src/runtime/spectra.ts +110 -110
- package/src/types.ts +1648 -1648
- package/tsconfig.json +17 -17
package/dist/reporter.js
CHANGED
|
@@ -67,7 +67,19 @@ export function formatArgs(args) {
|
|
|
67
67
|
*/
|
|
68
68
|
export async function trackCommand(category, commandText, fn) {
|
|
69
69
|
const start = Date.now();
|
|
70
|
-
const
|
|
70
|
+
const payloadObj = typeof commandText === 'object' ? { ...commandText } : { text: commandText };
|
|
71
|
+
if (typeof globalThis !== 'undefined') {
|
|
72
|
+
const g = globalThis;
|
|
73
|
+
const currentTest = g.__CURRENT_TEST_TITLE__ || g.__CURRENT_TEST_ID__;
|
|
74
|
+
if (currentTest && !payloadObj.test) {
|
|
75
|
+
payloadObj.test = currentTest;
|
|
76
|
+
}
|
|
77
|
+
const workerId = g.__TESTSPECTRA_WORKER_ID__;
|
|
78
|
+
if (workerId !== undefined && payloadObj.workerId === undefined) {
|
|
79
|
+
payloadObj.workerId = workerId;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const payload = JSON.stringify(payloadObj);
|
|
71
83
|
console.log(`[TESTSPECTRA_STEP_START] ${payload}`);
|
|
72
84
|
try {
|
|
73
85
|
const result = await fn();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CollectionReceiverAssertions
|
|
1
|
+
import { CollectionReceiverAssertions } from '../types.js';
|
|
2
2
|
import { SingleElementRunner } from './single.js';
|
|
3
3
|
/**
|
|
4
4
|
* Fluent assertion, filtering, and iteration runner for multi-element collections.
|
|
@@ -26,6 +26,7 @@ export declare class MultiElementRunner implements PromiseLike<void>, Collection
|
|
|
26
26
|
private _selector;
|
|
27
27
|
private _assertions;
|
|
28
28
|
constructor(selector: string);
|
|
29
|
+
private _pushAssertion;
|
|
29
30
|
/**
|
|
30
31
|
* Asserts that the collection contains exactly `count` elements.
|
|
31
32
|
*/
|
|
@@ -50,19 +51,6 @@ export declare class MultiElementRunner implements PromiseLike<void>, Collection
|
|
|
50
51
|
* Asserts that the collection is not empty (contains at least 1 element).
|
|
51
52
|
*/
|
|
52
53
|
shouldNotBeEmpty(): this;
|
|
53
|
-
/**
|
|
54
|
-
* Queues an assertion matcher against the multi-element collection.
|
|
55
|
-
*
|
|
56
|
-
* @param matcher - Multi-element matcher string (e.g. `'have.length'`, `'be.empty'`).
|
|
57
|
-
* @param args - Expected values or limits for the matcher.
|
|
58
|
-
* @example
|
|
59
|
-
* ```ts
|
|
60
|
-
* await Spectra.getAll(".product-card").should("have.length.greaterThan", 0);
|
|
61
|
-
* await Spectra.getAll(".error-badge").should("be.empty");
|
|
62
|
-
* ```
|
|
63
|
-
* @returns Current collection runner instance for chaining.
|
|
64
|
-
*/
|
|
65
|
-
should(matcher: MultiElementMatcher, ...args: any[]): this;
|
|
66
54
|
/**
|
|
67
55
|
* Returns a `SingleElementRunner` targeting the element at the specified 0-based index.
|
|
68
56
|
*
|
|
@@ -89,7 +77,7 @@ export declare class MultiElementRunner implements PromiseLike<void>, Collection
|
|
|
89
77
|
*
|
|
90
78
|
* @example
|
|
91
79
|
* ```ts
|
|
92
|
-
* await Spectra.getAll(".step-indicator").last().
|
|
80
|
+
* await Spectra.getAll(".step-indicator").last().shouldHaveClass("current");
|
|
93
81
|
* ```
|
|
94
82
|
* @returns `SingleElementRunner` for the last element.
|
|
95
83
|
*/
|
|
@@ -101,7 +89,7 @@ export declare class MultiElementRunner implements PromiseLike<void>, Collection
|
|
|
101
89
|
* @example
|
|
102
90
|
* ```ts
|
|
103
91
|
* await Spectra.getAll(".checkbox").each(async (item, index) => {
|
|
104
|
-
* await item.
|
|
92
|
+
* await item.shouldBeVisible();
|
|
105
93
|
* });
|
|
106
94
|
* ```
|
|
107
95
|
*/
|
|
@@ -29,58 +29,46 @@ export class MultiElementRunner {
|
|
|
29
29
|
constructor(selector) {
|
|
30
30
|
this._selector = selector;
|
|
31
31
|
}
|
|
32
|
+
_pushAssertion(matcher, args = []) {
|
|
33
|
+
this._assertions.push({ matcher, args });
|
|
34
|
+
return this;
|
|
35
|
+
}
|
|
32
36
|
// --- Collection Assertions ---
|
|
33
37
|
/**
|
|
34
38
|
* Asserts that the collection contains exactly `count` elements.
|
|
35
39
|
*/
|
|
36
40
|
shouldHaveLength(count) {
|
|
37
|
-
return this.
|
|
41
|
+
return this._pushAssertion('have.length', [count]);
|
|
38
42
|
}
|
|
39
43
|
/**
|
|
40
44
|
* Asserts that the collection does not contain `count` elements.
|
|
41
45
|
*/
|
|
42
46
|
shouldNotHaveLength(count) {
|
|
43
|
-
return this.
|
|
47
|
+
return this._pushAssertion('not.have.length', [count]);
|
|
44
48
|
}
|
|
45
49
|
/**
|
|
46
50
|
* Asserts that the collection contains more than `min` elements.
|
|
47
51
|
*/
|
|
48
52
|
shouldHaveLengthGreaterThan(min) {
|
|
49
|
-
return this.
|
|
53
|
+
return this._pushAssertion('have.length.greaterThan', [min]);
|
|
50
54
|
}
|
|
51
55
|
/**
|
|
52
56
|
* Asserts that the collection contains less than `max` elements.
|
|
53
57
|
*/
|
|
54
58
|
shouldHaveLengthLessThan(max) {
|
|
55
|
-
return this.
|
|
59
|
+
return this._pushAssertion('have.length.lessThan', [max]);
|
|
56
60
|
}
|
|
57
61
|
/**
|
|
58
62
|
* Asserts that the collection is empty (contains 0 elements).
|
|
59
63
|
*/
|
|
60
64
|
shouldBeEmpty() {
|
|
61
|
-
return this.
|
|
65
|
+
return this._pushAssertion('be.empty');
|
|
62
66
|
}
|
|
63
67
|
/**
|
|
64
68
|
* Asserts that the collection is not empty (contains at least 1 element).
|
|
65
69
|
*/
|
|
66
70
|
shouldNotBeEmpty() {
|
|
67
|
-
return this.
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Queues an assertion matcher against the multi-element collection.
|
|
71
|
-
*
|
|
72
|
-
* @param matcher - Multi-element matcher string (e.g. `'have.length'`, `'be.empty'`).
|
|
73
|
-
* @param args - Expected values or limits for the matcher.
|
|
74
|
-
* @example
|
|
75
|
-
* ```ts
|
|
76
|
-
* await Spectra.getAll(".product-card").should("have.length.greaterThan", 0);
|
|
77
|
-
* await Spectra.getAll(".error-badge").should("be.empty");
|
|
78
|
-
* ```
|
|
79
|
-
* @returns Current collection runner instance for chaining.
|
|
80
|
-
*/
|
|
81
|
-
should(matcher, ...args) {
|
|
82
|
-
this._assertions.push({ matcher, args });
|
|
83
|
-
return this;
|
|
71
|
+
return this._pushAssertion('not.be.empty');
|
|
84
72
|
}
|
|
85
73
|
// --- Item Navigation ---
|
|
86
74
|
/**
|
|
@@ -96,9 +84,22 @@ export class MultiElementRunner {
|
|
|
96
84
|
eq(index) {
|
|
97
85
|
const targetSelector = `${this._selector}[${index}]`;
|
|
98
86
|
const elPromise = (async () => {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
87
|
+
const getElements = typeof $$ !== 'undefined' ? $$ : globalThis.$$;
|
|
88
|
+
if (typeof getElements === 'function') {
|
|
89
|
+
const elements = await getElements(this._selector);
|
|
90
|
+
if (typeof elements?.nth === 'function') {
|
|
91
|
+
return elements.nth(index);
|
|
92
|
+
}
|
|
93
|
+
if (index === 0 && typeof elements?.first === 'function') {
|
|
94
|
+
return elements.first();
|
|
95
|
+
}
|
|
96
|
+
if (elements && elements[index] !== undefined) {
|
|
97
|
+
return elements[index];
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const getDollar = typeof $ !== 'undefined' ? $ : globalThis.$;
|
|
101
|
+
if (typeof getDollar === 'function') {
|
|
102
|
+
return getDollar(targetSelector);
|
|
102
103
|
}
|
|
103
104
|
return { selector: targetSelector };
|
|
104
105
|
})();
|
|
@@ -122,17 +123,30 @@ export class MultiElementRunner {
|
|
|
122
123
|
*
|
|
123
124
|
* @example
|
|
124
125
|
* ```ts
|
|
125
|
-
* await Spectra.getAll(".step-indicator").last().
|
|
126
|
+
* await Spectra.getAll(".step-indicator").last().shouldHaveClass("current");
|
|
126
127
|
* ```
|
|
127
128
|
* @returns `SingleElementRunner` for the last element.
|
|
128
129
|
*/
|
|
129
130
|
last() {
|
|
130
131
|
const targetSelector = `${this._selector}[last()]`;
|
|
131
132
|
const elPromise = (async () => {
|
|
132
|
-
|
|
133
|
-
|
|
133
|
+
const getElements = typeof $$ !== 'undefined' ? $$ : globalThis.$$;
|
|
134
|
+
if (typeof getElements === 'function') {
|
|
135
|
+
const elements = await getElements(this._selector);
|
|
136
|
+
if (typeof elements?.last === 'function') {
|
|
137
|
+
return elements.last();
|
|
138
|
+
}
|
|
139
|
+
if (typeof elements?.nth === 'function') {
|
|
140
|
+
return elements.nth(-1);
|
|
141
|
+
}
|
|
134
142
|
const arr = Array.isArray(elements) ? elements : await elements;
|
|
135
|
-
|
|
143
|
+
if (arr && arr.length > 0) {
|
|
144
|
+
return arr[arr.length - 1];
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
const getDollar = typeof $ !== 'undefined' ? $ : globalThis.$;
|
|
148
|
+
if (typeof getDollar === 'function') {
|
|
149
|
+
return getDollar(targetSelector);
|
|
136
150
|
}
|
|
137
151
|
return { selector: targetSelector };
|
|
138
152
|
})();
|
|
@@ -147,7 +161,7 @@ export class MultiElementRunner {
|
|
|
147
161
|
* @example
|
|
148
162
|
* ```ts
|
|
149
163
|
* await Spectra.getAll(".checkbox").each(async (item, index) => {
|
|
150
|
-
* await item.
|
|
164
|
+
* await item.shouldBeVisible();
|
|
151
165
|
* });
|
|
152
166
|
* ```
|
|
153
167
|
*/
|
package/dist/runner/single.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ElementReceiverAssertions, ElementTarget,
|
|
1
|
+
import { ElementReceiverAssertions, ElementTarget, TypeOptions } from '../types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Fluent interaction and assertion runner for a single element or browser context.
|
|
4
4
|
*
|
|
@@ -90,11 +90,11 @@ export declare class SingleElementRunner implements PromiseLike<void>, ElementRe
|
|
|
90
90
|
*/
|
|
91
91
|
select(value: string): this;
|
|
92
92
|
/**
|
|
93
|
-
*
|
|
93
|
+
* Hovers over the target element.
|
|
94
94
|
*
|
|
95
95
|
* @example
|
|
96
96
|
* ```ts
|
|
97
|
-
* await Spectra.get("#dropdown-
|
|
97
|
+
* await Spectra.get("#dropdown-trigger").hover();
|
|
98
98
|
* ```
|
|
99
99
|
* @returns Current runner instance for method chaining.
|
|
100
100
|
*/
|
|
@@ -122,6 +122,7 @@ export declare class SingleElementRunner implements PromiseLike<void>, ElementRe
|
|
|
122
122
|
* Scrolls the target element into view.
|
|
123
123
|
*/
|
|
124
124
|
scrollIntoView(): this;
|
|
125
|
+
private _pushAssertion;
|
|
125
126
|
/**
|
|
126
127
|
* Asserts that the target element is displayed and visible to the user.
|
|
127
128
|
*/
|
|
@@ -226,33 +227,6 @@ export declare class SingleElementRunner implements PromiseLike<void>, ElementRe
|
|
|
226
227
|
* Asserts that the target element does not have the specified computed CSS property value.
|
|
227
228
|
*/
|
|
228
229
|
shouldNotHaveCss(property: string, value: string): this;
|
|
229
|
-
/**
|
|
230
|
-
* Queues an assertion matcher against the current target element or page.
|
|
231
|
-
*
|
|
232
|
-
* @param matcher - Single element matcher string (e.g. `'be.visible'`, `'have.text'`).
|
|
233
|
-
* @param args - Additional parameters for the matcher (e.g. expected text or value).
|
|
234
|
-
* @example
|
|
235
|
-
* ```ts
|
|
236
|
-
* await Spectra.get("#status-badge").should("be.visible");
|
|
237
|
-
* await Spectra.get("#username").should("have.value", "alice");
|
|
238
|
-
* await Spectra.get("#banner").should("have.class", "alert-success");
|
|
239
|
-
* ```
|
|
240
|
-
* @returns Current runner instance for method chaining.
|
|
241
|
-
*/
|
|
242
|
-
should(matcher: SingleElementMatcher, ...args: any[]): this;
|
|
243
|
-
/**
|
|
244
|
-
* Queues an assertion matcher targeting a specific element.
|
|
245
|
-
*
|
|
246
|
-
* @param target - Custom element target for this specific assertion.
|
|
247
|
-
* @param matcher - Single element matcher string.
|
|
248
|
-
* @param args - Additional parameters for the matcher.
|
|
249
|
-
* @example
|
|
250
|
-
* ```ts
|
|
251
|
-
* await Spectra.should(LoginPage.submitBtn, "be.enabled");
|
|
252
|
-
* ```
|
|
253
|
-
* @returns Current runner instance for method chaining.
|
|
254
|
-
*/
|
|
255
|
-
should(target: ElementTarget, matcher: SingleElementMatcher, ...args: any[]): this;
|
|
256
230
|
/**
|
|
257
231
|
* Standard Promise `then` implementation.
|
|
258
232
|
* Executes queued action first (if any), followed sequentially by all queued assertions.
|
package/dist/runner/single.js
CHANGED
|
@@ -120,9 +120,17 @@ export class SingleElementRunner {
|
|
|
120
120
|
this._action = async () => {
|
|
121
121
|
const el = await resolveElement(target);
|
|
122
122
|
if (options?.clearFirst) {
|
|
123
|
-
|
|
123
|
+
if (typeof el.clearValue === 'function')
|
|
124
|
+
await el.clearValue();
|
|
125
|
+
else if (typeof el.clear === 'function')
|
|
126
|
+
await el.clear();
|
|
124
127
|
}
|
|
125
|
-
|
|
128
|
+
if (typeof el.setValue === 'function')
|
|
129
|
+
await el.setValue(value);
|
|
130
|
+
else if (typeof el.fill === 'function')
|
|
131
|
+
await el.fill(value);
|
|
132
|
+
else if (typeof el.type === 'function')
|
|
133
|
+
await el.type(value);
|
|
126
134
|
};
|
|
127
135
|
return this;
|
|
128
136
|
}
|
|
@@ -140,7 +148,10 @@ export class SingleElementRunner {
|
|
|
140
148
|
this._actionPayload = { type: 'action', key: 'clear', target: getRawTarget(target), args: [] };
|
|
141
149
|
this._action = async () => {
|
|
142
150
|
const el = await resolveElement(target);
|
|
143
|
-
|
|
151
|
+
if (typeof el.clearValue === 'function')
|
|
152
|
+
await el.clearValue();
|
|
153
|
+
else if (typeof el.clear === 'function')
|
|
154
|
+
await el.clear();
|
|
144
155
|
};
|
|
145
156
|
return this;
|
|
146
157
|
}
|
|
@@ -159,16 +170,19 @@ export class SingleElementRunner {
|
|
|
159
170
|
this._actionPayload = { type: 'action', key: 'selectOption', target: getRawTarget(target), args: [value] };
|
|
160
171
|
this._action = async () => {
|
|
161
172
|
const el = await resolveElement(target);
|
|
162
|
-
|
|
173
|
+
if (typeof el.selectByVisibleText === 'function')
|
|
174
|
+
await el.selectByVisibleText(value);
|
|
175
|
+
else if (typeof el.selectOption === 'function')
|
|
176
|
+
await el.selectOption({ label: value });
|
|
163
177
|
};
|
|
164
178
|
return this;
|
|
165
179
|
}
|
|
166
180
|
/**
|
|
167
|
-
*
|
|
181
|
+
* Hovers over the target element.
|
|
168
182
|
*
|
|
169
183
|
* @example
|
|
170
184
|
* ```ts
|
|
171
|
-
* await Spectra.get("#dropdown-
|
|
185
|
+
* await Spectra.get("#dropdown-trigger").hover();
|
|
172
186
|
* ```
|
|
173
187
|
* @returns Current runner instance for method chaining.
|
|
174
188
|
*/
|
|
@@ -177,7 +191,10 @@ export class SingleElementRunner {
|
|
|
177
191
|
this._actionPayload = { type: 'action', key: 'hover', target: getRawTarget(target), args: [] };
|
|
178
192
|
this._action = async () => {
|
|
179
193
|
const el = await resolveElement(target);
|
|
180
|
-
|
|
194
|
+
if (typeof el.moveTo === 'function')
|
|
195
|
+
await el.moveTo();
|
|
196
|
+
else if (typeof el.hover === 'function')
|
|
197
|
+
await el.hover();
|
|
181
198
|
};
|
|
182
199
|
return this;
|
|
183
200
|
}
|
|
@@ -242,191 +259,172 @@ export class SingleElementRunner {
|
|
|
242
259
|
};
|
|
243
260
|
return this;
|
|
244
261
|
}
|
|
262
|
+
_pushAssertion(matcher, args = []) {
|
|
263
|
+
this._assertions.push({
|
|
264
|
+
target: this._target,
|
|
265
|
+
matcher,
|
|
266
|
+
args,
|
|
267
|
+
});
|
|
268
|
+
return this;
|
|
269
|
+
}
|
|
245
270
|
// --- Fluent Assertion Matchers ---
|
|
246
271
|
/**
|
|
247
272
|
* Asserts that the target element is displayed and visible to the user.
|
|
248
273
|
*/
|
|
249
274
|
shouldBeVisible() {
|
|
250
|
-
return this.
|
|
275
|
+
return this._pushAssertion('be.visible');
|
|
251
276
|
}
|
|
252
277
|
/**
|
|
253
278
|
* Asserts that the target element is not displayed or hidden from view.
|
|
254
279
|
*/
|
|
255
280
|
shouldNotBeVisible() {
|
|
256
|
-
return this.
|
|
281
|
+
return this._pushAssertion('not.be.visible');
|
|
257
282
|
}
|
|
258
283
|
/**
|
|
259
284
|
* Asserts that the target element exists in the DOM.
|
|
260
285
|
*/
|
|
261
286
|
shouldExist() {
|
|
262
|
-
return this.
|
|
287
|
+
return this._pushAssertion('exist');
|
|
263
288
|
}
|
|
264
289
|
/**
|
|
265
290
|
* Asserts that the target element does not exist in the DOM.
|
|
266
291
|
*/
|
|
267
292
|
shouldNotExist() {
|
|
268
|
-
return this.
|
|
293
|
+
return this._pushAssertion('not.exist');
|
|
269
294
|
}
|
|
270
295
|
/**
|
|
271
296
|
* Asserts that the target element is clickable.
|
|
272
297
|
*/
|
|
273
298
|
shouldBeClickable() {
|
|
274
|
-
return this.
|
|
299
|
+
return this._pushAssertion('be.clickable');
|
|
275
300
|
}
|
|
276
301
|
/**
|
|
277
302
|
* Asserts that the target element is not clickable.
|
|
278
303
|
*/
|
|
279
304
|
shouldNotBeClickable() {
|
|
280
|
-
return this.
|
|
305
|
+
return this._pushAssertion('not.be.clickable');
|
|
281
306
|
}
|
|
282
307
|
/**
|
|
283
308
|
* Asserts that the target element is enabled (not disabled).
|
|
284
309
|
*/
|
|
285
310
|
shouldBeEnabled() {
|
|
286
|
-
return this.
|
|
311
|
+
return this._pushAssertion('be.enabled');
|
|
287
312
|
}
|
|
288
313
|
/**
|
|
289
314
|
* Asserts that the target element is disabled.
|
|
290
315
|
*/
|
|
291
316
|
shouldBeDisabled() {
|
|
292
|
-
return this.
|
|
317
|
+
return this._pushAssertion('be.disabled');
|
|
293
318
|
}
|
|
294
319
|
/**
|
|
295
320
|
* Asserts that the target checkbox or radio element is checked.
|
|
296
321
|
*/
|
|
297
322
|
shouldBeChecked() {
|
|
298
|
-
return this.
|
|
323
|
+
return this._pushAssertion('be.checked');
|
|
299
324
|
}
|
|
300
325
|
/**
|
|
301
326
|
* Asserts that the target checkbox or radio element is not checked.
|
|
302
327
|
*/
|
|
303
328
|
shouldNotBeChecked() {
|
|
304
|
-
return this.
|
|
329
|
+
return this._pushAssertion('not.be.checked');
|
|
305
330
|
}
|
|
306
331
|
/**
|
|
307
332
|
* Asserts that the target element currently has focus.
|
|
308
333
|
*/
|
|
309
334
|
shouldBeFocused() {
|
|
310
|
-
return this.
|
|
335
|
+
return this._pushAssertion('be.focused');
|
|
311
336
|
}
|
|
312
337
|
/**
|
|
313
338
|
* Asserts that the target element does not have focus.
|
|
314
339
|
*/
|
|
315
340
|
shouldNotBeFocused() {
|
|
316
|
-
return this.
|
|
341
|
+
return this._pushAssertion('not.be.focused');
|
|
317
342
|
}
|
|
318
343
|
/**
|
|
319
344
|
* Asserts that the target element has exact inner text matching the expected value.
|
|
320
345
|
*/
|
|
321
346
|
shouldHaveText(expected) {
|
|
322
|
-
return this.
|
|
347
|
+
return this._pushAssertion('have.text', [expected]);
|
|
323
348
|
}
|
|
324
349
|
/**
|
|
325
350
|
* Asserts that the target element does not have inner text matching the expected value.
|
|
326
351
|
*/
|
|
327
352
|
shouldNotHaveText(expected) {
|
|
328
|
-
return this.
|
|
353
|
+
return this._pushAssertion('not.have.text', [expected]);
|
|
329
354
|
}
|
|
330
355
|
/**
|
|
331
356
|
* Asserts that the target element's text contains the given substring.
|
|
332
357
|
*/
|
|
333
358
|
shouldContainText(substring) {
|
|
334
|
-
return this.
|
|
359
|
+
return this._pushAssertion('contain.text', [substring]);
|
|
335
360
|
}
|
|
336
361
|
/**
|
|
337
362
|
* Asserts that the target element's text does not contain the given substring.
|
|
338
363
|
*/
|
|
339
364
|
shouldNotContainText(substring) {
|
|
340
|
-
return this.
|
|
365
|
+
return this._pushAssertion('not.contain.text', [substring]);
|
|
341
366
|
}
|
|
342
367
|
/**
|
|
343
368
|
* Asserts that the target input element has the exact expected value.
|
|
344
369
|
*/
|
|
345
370
|
shouldHaveValue(value) {
|
|
346
|
-
return this.
|
|
371
|
+
return this._pushAssertion('have.value', [value]);
|
|
347
372
|
}
|
|
348
373
|
/**
|
|
349
374
|
* Asserts that the target input element does not have the expected value.
|
|
350
375
|
*/
|
|
351
376
|
shouldNotHaveValue(value) {
|
|
352
|
-
return this.
|
|
377
|
+
return this._pushAssertion('not.have.value', [value]);
|
|
353
378
|
}
|
|
354
379
|
/**
|
|
355
380
|
* Asserts that the target input element's value contains the given substring.
|
|
356
381
|
*/
|
|
357
382
|
shouldContainValue(substring) {
|
|
358
|
-
return this.
|
|
383
|
+
return this._pushAssertion('contain.value', [substring]);
|
|
359
384
|
}
|
|
360
385
|
/**
|
|
361
386
|
* Asserts that the target input element's value does not contain the given substring.
|
|
362
387
|
*/
|
|
363
388
|
shouldNotContainValue(substring) {
|
|
364
|
-
return this.
|
|
389
|
+
return this._pushAssertion('not.contain.value', [substring]);
|
|
365
390
|
}
|
|
366
391
|
/**
|
|
367
392
|
* Asserts that the target element has the specified HTML attribute and optional value.
|
|
368
393
|
*/
|
|
369
394
|
shouldHaveAttribute(name, value) {
|
|
370
|
-
return value !== undefined
|
|
395
|
+
return value !== undefined
|
|
396
|
+
? this._pushAssertion('have.attr', [name, value])
|
|
397
|
+
: this._pushAssertion('have.attr', [name]);
|
|
371
398
|
}
|
|
372
399
|
/**
|
|
373
400
|
* Asserts that the target element does not have the specified HTML attribute.
|
|
374
401
|
*/
|
|
375
402
|
shouldNotHaveAttribute(name) {
|
|
376
|
-
return this.
|
|
403
|
+
return this._pushAssertion('not.have.attr', [name]);
|
|
377
404
|
}
|
|
378
405
|
/**
|
|
379
406
|
* Asserts that the target element has the specified CSS class.
|
|
380
407
|
*/
|
|
381
408
|
shouldHaveClass(className) {
|
|
382
|
-
return this.
|
|
409
|
+
return this._pushAssertion('have.class', [className]);
|
|
383
410
|
}
|
|
384
411
|
/**
|
|
385
412
|
* Asserts that the target element does not have the specified CSS class.
|
|
386
413
|
*/
|
|
387
414
|
shouldNotHaveClass(className) {
|
|
388
|
-
return this.
|
|
415
|
+
return this._pushAssertion('not.have.class', [className]);
|
|
389
416
|
}
|
|
390
417
|
/**
|
|
391
418
|
* Asserts that the target element has the specified computed CSS property value.
|
|
392
419
|
*/
|
|
393
420
|
shouldHaveCss(property, value) {
|
|
394
|
-
return this.
|
|
421
|
+
return this._pushAssertion('have.css', [property, value]);
|
|
395
422
|
}
|
|
396
423
|
/**
|
|
397
424
|
* Asserts that the target element does not have the specified computed CSS property value.
|
|
398
425
|
*/
|
|
399
426
|
shouldNotHaveCss(property, value) {
|
|
400
|
-
return this.
|
|
401
|
-
}
|
|
402
|
-
should(a, b, ...rest) {
|
|
403
|
-
const isFirstArgMatcher = typeof a === 'string' &&
|
|
404
|
-
(a.includes('.') ||
|
|
405
|
-
a.includes('exist') ||
|
|
406
|
-
a.includes('visible') ||
|
|
407
|
-
a.includes('clickable') ||
|
|
408
|
-
a.includes('focused') ||
|
|
409
|
-
a.includes('enabled') ||
|
|
410
|
-
a.includes('disabled') ||
|
|
411
|
-
a.includes('selected') ||
|
|
412
|
-
a.includes('checked'));
|
|
413
|
-
if (b !== undefined && !isFirstArgMatcher) {
|
|
414
|
-
// Form: should(target, matcher, ...args)
|
|
415
|
-
this._assertions.push({
|
|
416
|
-
target: a,
|
|
417
|
-
matcher: b,
|
|
418
|
-
args: rest,
|
|
419
|
-
});
|
|
420
|
-
}
|
|
421
|
-
else {
|
|
422
|
-
// Form: should(matcher, ...args) -> on current target
|
|
423
|
-
this._assertions.push({
|
|
424
|
-
target: this._target,
|
|
425
|
-
matcher: a,
|
|
426
|
-
args: b !== undefined ? [b, ...rest] : rest,
|
|
427
|
-
});
|
|
428
|
-
}
|
|
429
|
-
return this;
|
|
427
|
+
return this._pushAssertion('not.have.css', [property, value]);
|
|
430
428
|
}
|
|
431
429
|
// --- Execution when awaited ---
|
|
432
430
|
/**
|
package/dist/spectra.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ import { MockHandle, InterceptRule } from './intercept/index.js';
|
|
|
15
15
|
* await Spectra.get("#username").type("admin");
|
|
16
16
|
*
|
|
17
17
|
* // Collection assertion
|
|
18
|
-
* await Spectra.getAll(".item").
|
|
18
|
+
* await Spectra.getAll(".item").shouldHaveLength(5);
|
|
19
19
|
*
|
|
20
20
|
* // Mobile touch swipe
|
|
21
21
|
* await Spectra.swipe({ direction: "left", distance: 350 });
|
|
@@ -29,7 +29,7 @@ export declare class SpectraStatic {
|
|
|
29
29
|
* @example
|
|
30
30
|
* ```ts
|
|
31
31
|
* await Spectra.get("#login-btn").click();
|
|
32
|
-
* await Spectra.get(LoginPage.submitButton).
|
|
32
|
+
* await Spectra.get(LoginPage.submitButton).shouldBeVisible();
|
|
33
33
|
* ```
|
|
34
34
|
* @returns `SingleElementRunner` for chaining actions and assertions.
|
|
35
35
|
*/
|
|
@@ -40,7 +40,7 @@ export declare class SpectraStatic {
|
|
|
40
40
|
* @param selector - Selector string matching multiple elements.
|
|
41
41
|
* @example
|
|
42
42
|
* ```ts
|
|
43
|
-
* await Spectra.getAll(".product-card").
|
|
43
|
+
* await Spectra.getAll(".product-card").shouldHaveLengthGreaterThan(0);
|
|
44
44
|
* await Spectra.getAll("li.tab").first().click();
|
|
45
45
|
* ```
|
|
46
46
|
* @returns `MultiElementRunner` for collection assertions and indexing.
|
package/dist/spectra.js
CHANGED
|
@@ -16,7 +16,7 @@ import { trackCommand } from './reporter.js';
|
|
|
16
16
|
* await Spectra.get("#username").type("admin");
|
|
17
17
|
*
|
|
18
18
|
* // Collection assertion
|
|
19
|
-
* await Spectra.getAll(".item").
|
|
19
|
+
* await Spectra.getAll(".item").shouldHaveLength(5);
|
|
20
20
|
*
|
|
21
21
|
* // Mobile touch swipe
|
|
22
22
|
* await Spectra.swipe({ direction: "left", distance: 350 });
|
|
@@ -30,7 +30,7 @@ export class SpectraStatic {
|
|
|
30
30
|
* @example
|
|
31
31
|
* ```ts
|
|
32
32
|
* await Spectra.get("#login-btn").click();
|
|
33
|
-
* await Spectra.get(LoginPage.submitButton).
|
|
33
|
+
* await Spectra.get(LoginPage.submitButton).shouldBeVisible();
|
|
34
34
|
* ```
|
|
35
35
|
* @returns `SingleElementRunner` for chaining actions and assertions.
|
|
36
36
|
*/
|
|
@@ -43,7 +43,7 @@ export class SpectraStatic {
|
|
|
43
43
|
* @param selector - Selector string matching multiple elements.
|
|
44
44
|
* @example
|
|
45
45
|
* ```ts
|
|
46
|
-
* await Spectra.getAll(".product-card").
|
|
46
|
+
* await Spectra.getAll(".product-card").shouldHaveLengthGreaterThan(0);
|
|
47
47
|
* await Spectra.getAll("li.tab").first().click();
|
|
48
48
|
* ```
|
|
49
49
|
* @returns `MultiElementRunner` for collection assertions and indexing.
|
package/package.json
CHANGED