@testspectra/matchers 1.0.69 → 1.1.0

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,23 +1,25 @@
1
- import { executeMultiMatcher } from "../matchers.js";
2
- import { SingleElementRunner } from "./single.js";
1
+ import { executeMultiMatcher } from '../matchers.js';
2
+ import { trackCommand } from '../reporter.js';
3
+ import { SingleElementRunner } from './single.js';
3
4
  /**
4
5
  * Fluent assertion, filtering, and iteration runner for multi-element collections.
5
6
  *
6
- * Implements `PromiseLike<void>`, allowing assertions across matching elements,
7
+ * Implements `PromiseLike<void>` and `CollectionReceiverAssertions<MultiElementRunner>`,
8
+ * allowing assertions across matching elements,
7
9
  * array index access (`.eq()`, `.first()`, `.last()`), and sequential iteration (`.each()`).
8
10
  *
9
11
  * @example
10
12
  * ```ts
11
13
  * // Assert collection size
12
- * await Spectra.getAll(".cart-item").should("have.length", 3);
14
+ * await Spectra.getAll(".cart-item").shouldHaveLength(3);
13
15
  *
14
16
  * // Target specific element from collection
15
17
  * await Spectra.getAll(".todo-item").first().click();
16
- * await Spectra.getAll(".todo-item").eq(2).should("have.text", "Buy Milk");
18
+ * await Spectra.getAll(".todo-item").eq(2).shouldHaveText("Buy Milk");
17
19
  *
18
20
  * // Iteration
19
21
  * await Spectra.getAll(".nav-link").each(async (link, i) => {
20
- * await link.should("be.visible");
22
+ * await link.shouldBeVisible();
21
23
  * });
22
24
  * ```
23
25
  */
@@ -27,22 +29,46 @@ export class MultiElementRunner {
27
29
  constructor(selector) {
28
30
  this._selector = selector;
29
31
  }
32
+ _pushAssertion(matcher, args = []) {
33
+ this._assertions.push({ matcher, args });
34
+ return this;
35
+ }
30
36
  // --- Collection Assertions ---
31
37
  /**
32
- * Queues an assertion matcher against the multi-element collection.
33
- *
34
- * @param matcher - Multi-element matcher string (e.g. `'have.length'`, `'be.empty'`).
35
- * @param args - Expected values or limits for the matcher.
36
- * @example
37
- * ```ts
38
- * await Spectra.getAll(".product-card").should("have.length.greaterThan", 0);
39
- * await Spectra.getAll(".error-badge").should("be.empty");
40
- * ```
41
- * @returns Current collection runner instance for chaining.
38
+ * Asserts that the collection contains exactly `count` elements.
42
39
  */
43
- should(matcher, ...args) {
44
- this._assertions.push({ matcher, args });
45
- return this;
40
+ shouldHaveLength(count) {
41
+ return this._pushAssertion('have.length', [count]);
42
+ }
43
+ /**
44
+ * Asserts that the collection does not contain `count` elements.
45
+ */
46
+ shouldNotHaveLength(count) {
47
+ return this._pushAssertion('not.have.length', [count]);
48
+ }
49
+ /**
50
+ * Asserts that the collection contains more than `min` elements.
51
+ */
52
+ shouldHaveLengthGreaterThan(min) {
53
+ return this._pushAssertion('have.length.greaterThan', [min]);
54
+ }
55
+ /**
56
+ * Asserts that the collection contains less than `max` elements.
57
+ */
58
+ shouldHaveLengthLessThan(max) {
59
+ return this._pushAssertion('have.length.lessThan', [max]);
60
+ }
61
+ /**
62
+ * Asserts that the collection is empty (contains 0 elements).
63
+ */
64
+ shouldBeEmpty() {
65
+ return this._pushAssertion('be.empty');
66
+ }
67
+ /**
68
+ * Asserts that the collection is not empty (contains at least 1 element).
69
+ */
70
+ shouldNotBeEmpty() {
71
+ return this._pushAssertion('not.be.empty');
46
72
  }
47
73
  // --- Item Navigation ---
48
74
  /**
@@ -56,8 +82,16 @@ export class MultiElementRunner {
56
82
  * @returns `SingleElementRunner` for the indexed element.
57
83
  */
58
84
  eq(index) {
59
- const indexedSelector = `(${this._selector})[${index + 1}]`;
60
- return new SingleElementRunner(indexedSelector);
85
+ const targetSelector = `${this._selector}[${index}]`;
86
+ const elPromise = (async () => {
87
+ if (typeof $$ !== 'undefined') {
88
+ const elements = await $$(this._selector);
89
+ return elements[index];
90
+ }
91
+ return { selector: targetSelector };
92
+ })();
93
+ elPromise.selector = targetSelector;
94
+ return new SingleElementRunner(elPromise);
61
95
  }
62
96
  /**
63
97
  * Returns a `SingleElementRunner` targeting the first element in the collection (`index = 0`).
@@ -76,13 +110,22 @@ export class MultiElementRunner {
76
110
  *
77
111
  * @example
78
112
  * ```ts
79
- * await Spectra.getAll(".step-indicator").last().should("have.class", "current");
113
+ * await Spectra.getAll(".step-indicator").last().shouldHaveClass("current");
80
114
  * ```
81
115
  * @returns `SingleElementRunner` for the last element.
82
116
  */
83
117
  last() {
84
- const indexedSelector = `(${this._selector})[last()]`;
85
- return new SingleElementRunner(indexedSelector);
118
+ const targetSelector = `${this._selector}[last()]`;
119
+ const elPromise = (async () => {
120
+ if (typeof $$ !== 'undefined') {
121
+ const elements = await $$(this._selector);
122
+ const arr = Array.isArray(elements) ? elements : await elements;
123
+ return arr[arr.length - 1];
124
+ }
125
+ return { selector: targetSelector };
126
+ })();
127
+ elPromise.selector = targetSelector;
128
+ return new SingleElementRunner(elPromise);
86
129
  }
87
130
  // --- Iteration Callback ---
88
131
  /**
@@ -92,7 +135,7 @@ export class MultiElementRunner {
92
135
  * @example
93
136
  * ```ts
94
137
  * await Spectra.getAll(".checkbox").each(async (item, index) => {
95
- * await item.should("be.visible");
138
+ * await item.shouldBeVisible();
96
139
  * });
97
140
  * ```
98
141
  */
@@ -112,7 +155,16 @@ export class MultiElementRunner {
112
155
  async then(onfulfilled, onrejected) {
113
156
  try {
114
157
  for (const assert of this._assertions) {
115
- await executeMultiMatcher(this._selector, assert.matcher, assert.args);
158
+ const payload = {
159
+ type: 'assertion',
160
+ key: assert.matcher,
161
+ target: this._selector,
162
+ args: assert.args,
163
+ isCollection: true,
164
+ };
165
+ await trackCommand('assertion', payload, async () => {
166
+ await executeMultiMatcher(this._selector, assert.matcher, assert.args);
167
+ });
116
168
  }
117
169
  const res = (onfulfilled ? await onfulfilled() : undefined);
118
170
  return res;
@@ -1,29 +1,30 @@
1
- import { SingleElementMatcher, ElementTarget, TypeOptions } from "../types.js";
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
  *
5
- * Implements `PromiseLike<void>`, allowing it to be awaited directly or chained with
6
- * multiple actions and `.should(...)` assertions.
5
+ * Implements `PromiseLike<void>` and `ElementReceiverAssertions<SingleElementRunner>`,
6
+ * allowing it to be awaited directly or chained with multiple actions and direct `.should...` assertions.
7
7
  *
8
8
  * @example
9
9
  * ```ts
10
10
  * // Direct action + chained assertion
11
11
  * await Spectra.get("#submit-btn")
12
12
  * .click()
13
- * .should("not.be.visible");
13
+ * .shouldNotBeVisible();
14
14
  *
15
15
  * // Query + multiple assertions
16
16
  * await Spectra.get(LoginPage.usernameInput)
17
- * .should("be.visible")
18
- * .should("be.enabled")
19
- * .should("have.value", "admin");
17
+ * .shouldBeVisible()
18
+ * .shouldBeEnabled()
19
+ * .shouldHaveValue("admin");
20
20
  * ```
21
21
  */
22
- export declare class SingleElementRunner implements PromiseLike<void> {
22
+ export declare class SingleElementRunner implements PromiseLike<void>, ElementReceiverAssertions<SingleElementRunner> {
23
23
  private _target;
24
24
  private _action;
25
+ private _actionPayload;
25
26
  private _assertions;
26
- constructor(target?: ElementTarget, action?: () => Promise<any>);
27
+ constructor(target?: ElementTarget, action?: () => Promise<any>, actionPayload?: any);
27
28
  /**
28
29
  * Clicks on the target element.
29
30
  *
@@ -110,32 +111,122 @@ export declare class SingleElementRunner implements PromiseLike<void> {
110
111
  */
111
112
  waitForElement(timeoutMs?: number): this;
112
113
  /**
113
- * Queues an assertion matcher against the current target element or page.
114
- *
115
- * @param matcher - Single element matcher string (e.g. `'be.visible'`, `'have.text'`).
116
- * @param args - Additional parameters for the matcher (e.g. expected text or value).
117
- * @example
118
- * ```ts
119
- * await Spectra.get("#status-badge").should("be.visible");
120
- * await Spectra.get("#username").should("have.value", "alice");
121
- * await Spectra.get("#banner").should("have.class", "alert-success");
122
- * ```
123
- * @returns Current runner instance for method chaining.
114
+ * Performs a right-click (context menu) interaction on the target element.
124
115
  */
125
- should(matcher: SingleElementMatcher, ...args: any[]): this;
116
+ rightClick(): this;
126
117
  /**
127
- * Queues an assertion matcher targeting a specific element.
128
- *
129
- * @param target - Custom element target for this specific assertion.
130
- * @param matcher - Single element matcher string.
131
- * @param args - Additional parameters for the matcher.
132
- * @example
133
- * ```ts
134
- * await Spectra.should(LoginPage.submitBtn, "be.enabled");
135
- * ```
136
- * @returns Current runner instance for method chaining.
118
+ * Drags the target element and drops it onto the specified destination element.
119
+ */
120
+ dragDrop(destination: ElementTarget): this;
121
+ /**
122
+ * Scrolls the target element into view.
123
+ */
124
+ scrollIntoView(): this;
125
+ private _pushAssertion;
126
+ /**
127
+ * Asserts that the target element is displayed and visible to the user.
128
+ */
129
+ shouldBeVisible(): this;
130
+ /**
131
+ * Asserts that the target element is not displayed or hidden from view.
132
+ */
133
+ shouldNotBeVisible(): this;
134
+ /**
135
+ * Asserts that the target element exists in the DOM.
136
+ */
137
+ shouldExist(): this;
138
+ /**
139
+ * Asserts that the target element does not exist in the DOM.
140
+ */
141
+ shouldNotExist(): this;
142
+ /**
143
+ * Asserts that the target element is clickable.
144
+ */
145
+ shouldBeClickable(): this;
146
+ /**
147
+ * Asserts that the target element is not clickable.
148
+ */
149
+ shouldNotBeClickable(): this;
150
+ /**
151
+ * Asserts that the target element is enabled (not disabled).
152
+ */
153
+ shouldBeEnabled(): this;
154
+ /**
155
+ * Asserts that the target element is disabled.
156
+ */
157
+ shouldBeDisabled(): this;
158
+ /**
159
+ * Asserts that the target checkbox or radio element is checked.
160
+ */
161
+ shouldBeChecked(): this;
162
+ /**
163
+ * Asserts that the target checkbox or radio element is not checked.
164
+ */
165
+ shouldNotBeChecked(): this;
166
+ /**
167
+ * Asserts that the target element currently has focus.
168
+ */
169
+ shouldBeFocused(): this;
170
+ /**
171
+ * Asserts that the target element does not have focus.
172
+ */
173
+ shouldNotBeFocused(): this;
174
+ /**
175
+ * Asserts that the target element has exact inner text matching the expected value.
176
+ */
177
+ shouldHaveText(expected: string | RegExp): this;
178
+ /**
179
+ * Asserts that the target element does not have inner text matching the expected value.
180
+ */
181
+ shouldNotHaveText(expected: string | RegExp): this;
182
+ /**
183
+ * Asserts that the target element's text contains the given substring.
184
+ */
185
+ shouldContainText(substring: string): this;
186
+ /**
187
+ * Asserts that the target element's text does not contain the given substring.
188
+ */
189
+ shouldNotContainText(substring: string): this;
190
+ /**
191
+ * Asserts that the target input element has the exact expected value.
192
+ */
193
+ shouldHaveValue(value: string): this;
194
+ /**
195
+ * Asserts that the target input element does not have the expected value.
196
+ */
197
+ shouldNotHaveValue(value: string): this;
198
+ /**
199
+ * Asserts that the target input element's value contains the given substring.
200
+ */
201
+ shouldContainValue(substring: string): this;
202
+ /**
203
+ * Asserts that the target input element's value does not contain the given substring.
204
+ */
205
+ shouldNotContainValue(substring: string): this;
206
+ /**
207
+ * Asserts that the target element has the specified HTML attribute and optional value.
208
+ */
209
+ shouldHaveAttribute(name: string, value?: string): this;
210
+ /**
211
+ * Asserts that the target element does not have the specified HTML attribute.
212
+ */
213
+ shouldNotHaveAttribute(name: string): this;
214
+ /**
215
+ * Asserts that the target element has the specified CSS class.
216
+ */
217
+ shouldHaveClass(className: string): this;
218
+ /**
219
+ * Asserts that the target element does not have the specified CSS class.
220
+ */
221
+ shouldNotHaveClass(className: string): this;
222
+ /**
223
+ * Asserts that the target element has the specified computed CSS property value.
224
+ */
225
+ shouldHaveCss(property: string, value: string): this;
226
+ /**
227
+ * Asserts that the target element does not have the specified computed CSS property value.
137
228
  */
138
- should(target: ElementTarget, matcher: SingleElementMatcher, ...args: any[]): this;
229
+ shouldNotHaveCss(property: string, value: string): this;
139
230
  /**
140
231
  * Standard Promise `then` implementation.
141
232
  * Executes queued action first (if any), followed sequentially by all queued assertions.