@testspectra/matchers 1.0.41 → 1.0.43

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/src/proto.ts CHANGED
@@ -4,48 +4,323 @@ import { resolveElement } from "./matchers.js";
4
4
  declare global {
5
5
  namespace WebdriverIO {
6
6
  interface Element {
7
+ /**
8
+ * Asserts that the element is displayed on the screen and visible to the user.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * await LoginPage.submitButton.shouldBeVisible();
13
+ * ```
14
+ * @returns The element instance for chaining.
15
+ */
7
16
  shouldBeVisible(): Promise<Element>;
17
+
18
+ /**
19
+ * Asserts that the element is NOT displayed or is hidden from view.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * await LoginPage.errorMessage.shouldNotBeVisible();
24
+ * ```
25
+ * @returns The element instance for chaining.
26
+ */
8
27
  shouldNotBeVisible(): Promise<Element>;
28
+
29
+ /**
30
+ * Asserts that the element exists in the DOM/UI hierarchy.
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * await LoginPage.rememberMeCheckbox.shouldExist();
35
+ * ```
36
+ * @returns The element instance for chaining.
37
+ */
9
38
  shouldExist(): Promise<Element>;
39
+
40
+ /**
41
+ * Asserts that the element does NOT exist in the DOM/UI hierarchy.
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * await LoginPage.loadingSpinner.shouldNotExist();
46
+ * ```
47
+ * @returns The element instance for chaining.
48
+ */
10
49
  shouldNotExist(): Promise<Element>;
50
+
51
+ /**
52
+ * Asserts that the element is enabled for interaction.
53
+ *
54
+ * @example
55
+ * ```ts
56
+ * await LoginPage.loginButton.shouldBeEnabled();
57
+ * ```
58
+ * @returns The element instance for chaining.
59
+ */
11
60
  shouldBeEnabled(): Promise<Element>;
61
+
62
+ /**
63
+ * Asserts that the element is disabled (cannot be interacted with).
64
+ *
65
+ * @example
66
+ * ```ts
67
+ * await LoginPage.disabledSubmit.shouldBeDisabled();
68
+ * ```
69
+ * @returns The element instance for chaining.
70
+ */
12
71
  shouldBeDisabled(): Promise<Element>;
72
+
73
+ /**
74
+ * Asserts that the form element (radio button, checkbox, option) is selected.
75
+ *
76
+ * @example
77
+ * ```ts
78
+ * await SettingsPage.darkModeRadio.shouldBeSelected();
79
+ * ```
80
+ * @returns The element instance for chaining.
81
+ */
13
82
  shouldBeSelected(): Promise<Element>;
83
+
84
+ /**
85
+ * Asserts that the checkbox or radio element is checked.
86
+ *
87
+ * @example
88
+ * ```ts
89
+ * await SettingsPage.termsCheckbox.shouldBeChecked();
90
+ * ```
91
+ * @returns The element instance for chaining.
92
+ */
14
93
  shouldBeChecked(): Promise<Element>;
94
+
95
+ /**
96
+ * Asserts that the input element has the exact given value.
97
+ *
98
+ * @param expectedValue - The exact expected value.
99
+ * @example
100
+ * ```ts
101
+ * await LoginPage.usernameInput.shouldHaveValue("admin@test.com");
102
+ * ```
103
+ * @returns The element instance for chaining.
104
+ */
15
105
  shouldHaveValue(expectedValue: string): Promise<Element>;
106
+
107
+ /**
108
+ * Asserts that the input element's value contains the given substring.
109
+ *
110
+ * @param expectedValue - Substring expected to be present in the value.
111
+ * @example
112
+ * ```ts
113
+ * await LoginPage.tokenInput.shouldContainValue("JWT_");
114
+ * ```
115
+ * @returns The element instance for chaining.
116
+ */
16
117
  shouldContainValue(expectedValue: string): Promise<Element>;
118
+
119
+ /**
120
+ * Asserts that the element's text content matches the exact expected text.
121
+ *
122
+ * @param expectedText - The exact expected text content.
123
+ * @example
124
+ * ```ts
125
+ * await LoginPage.headerTitle.shouldHaveText("Welcome to TestSpectra");
126
+ * ```
127
+ * @returns The element instance for chaining.
128
+ */
17
129
  shouldHaveText(expectedText: string): Promise<Element>;
130
+
131
+ /**
132
+ * Asserts that the element's text content contains the expected substring.
133
+ *
134
+ * @param expectedText - Substring expected to be within the element text.
135
+ * @example
136
+ * ```ts
137
+ * await LoginPage.welcomeBanner.shouldContainText("Welcome");
138
+ * ```
139
+ * @returns The element instance for chaining.
140
+ */
18
141
  shouldContainText(expectedText: string): Promise<Element>;
142
+
143
+ /**
144
+ * Asserts that the element has the specified CSS class.
145
+ *
146
+ * @param className - Expected CSS class name.
147
+ * @example
148
+ * ```ts
149
+ * await NavigationBar.homeTab.shouldHaveClass("is-active");
150
+ * ```
151
+ * @returns The element instance for chaining.
152
+ */
19
153
  shouldHaveClass(className: string): Promise<Element>;
154
+
155
+ /**
156
+ * Asserts that the element has the specified attribute, optionally checking its exact value.
157
+ *
158
+ * @param attributeName - Name of the attribute (e.g. `aria-label`, `disabled`, `href`).
159
+ * @param expectedValue - Optional expected value of the attribute.
160
+ * @example
161
+ * ```ts
162
+ * await NavigationBar.logoLink.shouldHaveAttribute("href", "/dashboard");
163
+ * await NavigationBar.cartButton.shouldHaveAttribute("aria-expanded");
164
+ * ```
165
+ * @returns The element instance for chaining.
166
+ */
20
167
  shouldHaveAttribute(attributeName: string, expectedValue?: string): Promise<Element>;
21
168
  }
22
169
 
170
+ /**
171
+ * Optional settings for HTTP network interception responses.
172
+ */
173
+ export interface InterceptFixtureOptions {
174
+ /** HTTP status code to return in the mocked response (default: 200) */
175
+ statusCode?: number;
176
+ /** Custom HTTP response headers */
177
+ headers?: Record<string, string>;
178
+ }
179
+
180
+ /**
181
+ * Structured mock payload object with optional status code and headers.
182
+ */
183
+ export interface InterceptFixtureObject<TData = unknown> {
184
+ /** HTTP status code */
185
+ statusCode?: number;
186
+ /** Response body payload */
187
+ body: TData;
188
+ /** Custom HTTP response headers */
189
+ headers?: Record<string, string>;
190
+ }
191
+
192
+ /**
193
+ * Input payload for API mocking: JSON object, string, or structured fixture object.
194
+ */
195
+ export type InterceptInput<TData = unknown> =
196
+ | InterceptFixtureObject<TData>
197
+ | TData
198
+ | string;
199
+
200
+ interface Mock {
201
+ /**
202
+ * Dynamically set or change the fixture response for this mock instance.
203
+ * Supports fixture file paths, structured `{ statusCode, body, headers }` objects, or raw data.
204
+ *
205
+ * @param fixture - Data payload or Fixture reference.
206
+ * @param options - Optional status code and header overrides.
207
+ * @example
208
+ * ```ts
209
+ * const mock = await browser.intercept("/api/user", "GET");
210
+ * await mock.respondWith({ name: "Admin", role: "superadmin" });
211
+ * ```
212
+ */
213
+ respondWith<TData = unknown>(
214
+ fixture: InterceptInput<TData>,
215
+ options?: InterceptFixtureOptions
216
+ ): Promise<void>;
217
+ }
218
+
23
219
  interface Browser {
220
+ /**
221
+ * Intercepts and mocks network API requests matching the specified endpoint.
222
+ * Supports automatic base URL resolution and TestSpectra JSON Fixtures.
223
+ *
224
+ * @param path - URL path or route to intercept (e.g. `"/api/users"` or `"https://api.example.com/v1/*"`).
225
+ * @param method - HTTP request method (`"GET"`, `"POST"`, `"PUT"`, `"DELETE"`, `"PATCH"`).
226
+ * @param fixture - Optional initial response payload or Fixture object.
227
+ * @param options - Optional status code and header configuration.
228
+ * @example
229
+ * ```ts
230
+ * // Intercept with JSON Fixture
231
+ * await browser.intercept("/api/status", "GET", Fixture.userData);
232
+ *
233
+ * // Intercept with custom payload & status code
234
+ * await browser.intercept("/api/auth/login", "POST", { token: "xyz" }, { statusCode: 200 });
235
+ * ```
236
+ * @returns `Mock` instance allowing dynamic response modification.
237
+ */
238
+ intercept<TData = unknown>(
239
+ path: string,
240
+ method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH",
241
+ fixture?: InterceptInput<TData>,
242
+ options?: InterceptFixtureOptions
243
+ ): Promise<Mock>;
244
+
245
+ /**
246
+ * Asserts that the current browser page URL exactly matches the expected URL.
247
+ *
248
+ * @param expectedUrl - The exact URL expected.
249
+ * @example
250
+ * ```ts
251
+ * await browser.shouldHaveUrl("https://app.example.com/dashboard");
252
+ * ```
253
+ */
24
254
  shouldHaveUrl(expectedUrl: string): Promise<void>;
255
+
256
+ /**
257
+ * Asserts that the current browser page URL contains the given substring.
258
+ *
259
+ * @param expectedUrl - Substring expected in the current URL.
260
+ * @example
261
+ * ```ts
262
+ * await browser.shouldContainUrl("/dashboard");
263
+ * ```
264
+ */
25
265
  shouldContainUrl(expectedUrl: string): Promise<void>;
266
+
267
+ /**
268
+ * Asserts that the current browser page title matches the expected title.
269
+ *
270
+ * @param expectedTitle - The exact title expected.
271
+ * @example
272
+ * ```ts
273
+ * await browser.shouldHaveTitle("Dashboard - TestSpectra");
274
+ * ```
275
+ */
26
276
  shouldHaveTitle(expectedTitle: string): Promise<void>;
277
+
278
+ /**
279
+ * Asserts that the current browser page title contains the expected substring.
280
+ *
281
+ * @param expectedTitle - Substring expected in the title.
282
+ * @example
283
+ * ```ts
284
+ * await browser.shouldContainTitle("Dashboard");
285
+ * ```
286
+ */
27
287
  shouldContainTitle(expectedTitle: string): Promise<void>;
28
288
  }
29
289
  }
30
290
 
31
291
  interface Promise<T> {
292
+ /** Asserts that the element promise resolves to a visible element. */
32
293
  shouldBeVisible(this: Promise<WebdriverIO.Element>): Promise<WebdriverIO.Element>;
294
+ /** Asserts that the element promise resolves to a hidden/non-visible element. */
33
295
  shouldNotBeVisible(this: Promise<WebdriverIO.Element>): Promise<WebdriverIO.Element>;
296
+ /** Asserts that the element promise resolves to an existing element in the DOM. */
34
297
  shouldExist(this: Promise<WebdriverIO.Element>): Promise<WebdriverIO.Element>;
298
+ /** Asserts that the element promise resolves to an element that does not exist in the DOM. */
35
299
  shouldNotExist(this: Promise<WebdriverIO.Element>): Promise<WebdriverIO.Element>;
300
+ /** Asserts that the element promise resolves to an enabled element. */
36
301
  shouldBeEnabled(this: Promise<WebdriverIO.Element>): Promise<WebdriverIO.Element>;
302
+ /** Asserts that the element promise resolves to a disabled element. */
37
303
  shouldBeDisabled(this: Promise<WebdriverIO.Element>): Promise<WebdriverIO.Element>;
304
+ /** Asserts that the element promise resolves to a selected element. */
38
305
  shouldBeSelected(this: Promise<WebdriverIO.Element>): Promise<WebdriverIO.Element>;
306
+ /** Asserts that the element promise resolves to a checked checkbox or radio. */
39
307
  shouldBeChecked(this: Promise<WebdriverIO.Element>): Promise<WebdriverIO.Element>;
308
+ /** Asserts that the element promise resolves to an element with the exact value. */
40
309
  shouldHaveValue(this: Promise<WebdriverIO.Element>, expectedValue: string): Promise<WebdriverIO.Element>;
310
+ /** Asserts that the element promise resolves to an element whose value contains the substring. */
41
311
  shouldContainValue(this: Promise<WebdriverIO.Element>, expectedValue: string): Promise<WebdriverIO.Element>;
312
+ /** Asserts that the element promise resolves to an element with the exact text content. */
42
313
  shouldHaveText(this: Promise<WebdriverIO.Element>, expectedText: string): Promise<WebdriverIO.Element>;
314
+ /** Asserts that the element promise resolves to an element whose text contains the substring. */
43
315
  shouldContainText(this: Promise<WebdriverIO.Element>, expectedText: string): Promise<WebdriverIO.Element>;
316
+ /** Asserts that the element promise resolves to an element having the CSS class. */
44
317
  shouldHaveClass(this: Promise<WebdriverIO.Element>, className: string): Promise<WebdriverIO.Element>;
318
+ /** Asserts that the element promise resolves to an element having the attribute. */
45
319
  shouldHaveAttribute(this: Promise<WebdriverIO.Element>, attributeName: string, expectedValue?: string): Promise<WebdriverIO.Element>;
46
320
  }
47
321
  }
48
322
 
323
+
49
324
  /**
50
325
  * Install direct callable assertion methods onto WebdriverIO browser/element and Promise prototypes.
51
326
  */
@@ -2,11 +2,35 @@ import { MultiElementMatcher } from "../types.js";
2
2
  import { executeMultiMatcher } from "../matchers.js";
3
3
  import { SingleElementRunner } from "./single.js";
4
4
 
5
+ /**
6
+ * Representation of a queued assertion against an element collection.
7
+ */
5
8
  type CollectionAssertion = {
6
9
  matcher: MultiElementMatcher;
7
10
  args: any[];
8
11
  };
9
12
 
13
+ /**
14
+ * Fluent assertion, filtering, and iteration runner for multi-element collections.
15
+ *
16
+ * Implements `PromiseLike<void>`, allowing assertions across matching elements,
17
+ * array index access (`.eq()`, `.first()`, `.last()`), and sequential iteration (`.each()`).
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * // Assert collection size
22
+ * await Spectra.getAll(".cart-item").should("have.length", 3);
23
+ *
24
+ * // Target specific element from collection
25
+ * await Spectra.getAll(".todo-item").first().click();
26
+ * await Spectra.getAll(".todo-item").eq(2).should("have.text", "Buy Milk");
27
+ *
28
+ * // Iteration
29
+ * await Spectra.getAll(".nav-link").each(async (link, i) => {
30
+ * await link.should("be.visible");
31
+ * });
32
+ * ```
33
+ */
10
34
  export class MultiElementRunner implements PromiseLike<void> {
11
35
  private _selector: string;
12
36
  private _assertions: CollectionAssertion[] = [];
@@ -17,6 +41,18 @@ export class MultiElementRunner implements PromiseLike<void> {
17
41
 
18
42
  // --- Collection Assertions ---
19
43
 
44
+ /**
45
+ * Queues an assertion matcher against the multi-element collection.
46
+ *
47
+ * @param matcher - Multi-element matcher string (e.g. `'have.length'`, `'be.empty'`).
48
+ * @param args - Expected values or limits for the matcher.
49
+ * @example
50
+ * ```ts
51
+ * await Spectra.getAll(".product-card").should("have.length.greaterThan", 0);
52
+ * await Spectra.getAll(".error-badge").should("be.empty");
53
+ * ```
54
+ * @returns Current collection runner instance for chaining.
55
+ */
20
56
  should(matcher: MultiElementMatcher, ...args: any[]): this {
21
57
  this._assertions.push({ matcher, args });
22
58
  return this;
@@ -24,15 +60,43 @@ export class MultiElementRunner implements PromiseLike<void> {
24
60
 
25
61
  // --- Item Navigation ---
26
62
 
63
+ /**
64
+ * Returns a `SingleElementRunner` targeting the element at the specified 0-based index.
65
+ *
66
+ * @param index - 0-based index of the element within the matched collection.
67
+ * @example
68
+ * ```ts
69
+ * await Spectra.getAll("li.menu-item").eq(1).click();
70
+ * ```
71
+ * @returns `SingleElementRunner` for the indexed element.
72
+ */
27
73
  eq(index: number): SingleElementRunner {
28
74
  const indexedSelector = `(${this._selector})[${index + 1}]`;
29
75
  return new SingleElementRunner(indexedSelector);
30
76
  }
31
77
 
78
+ /**
79
+ * Returns a `SingleElementRunner` targeting the first element in the collection (`index = 0`).
80
+ *
81
+ * @example
82
+ * ```ts
83
+ * await Spectra.getAll(".result-item").first().click();
84
+ * ```
85
+ * @returns `SingleElementRunner` for the first element.
86
+ */
32
87
  first(): SingleElementRunner {
33
88
  return this.eq(0);
34
89
  }
35
90
 
91
+ /**
92
+ * Returns a `SingleElementRunner` targeting the last element in the collection.
93
+ *
94
+ * @example
95
+ * ```ts
96
+ * await Spectra.getAll(".step-indicator").last().should("have.class", "current");
97
+ * ```
98
+ * @returns `SingleElementRunner` for the last element.
99
+ */
36
100
  last(): SingleElementRunner {
37
101
  const indexedSelector = `(${this._selector})[last()]`;
38
102
  return new SingleElementRunner(indexedSelector);
@@ -40,6 +104,17 @@ export class MultiElementRunner implements PromiseLike<void> {
40
104
 
41
105
  // --- Iteration Callback ---
42
106
 
107
+ /**
108
+ * Iterates asynchronously through every matched element in the collection sequentially.
109
+ *
110
+ * @param callback - Async function called for each element with `(runner, index)`.
111
+ * @example
112
+ * ```ts
113
+ * await Spectra.getAll(".checkbox").each(async (item, index) => {
114
+ * await item.should("be.visible");
115
+ * });
116
+ * ```
117
+ */
43
118
  async each(
44
119
  callback: (el: SingleElementRunner, index: number) => Promise<void>
45
120
  ): Promise<void> {
@@ -53,6 +128,10 @@ export class MultiElementRunner implements PromiseLike<void> {
53
128
 
54
129
  // --- Execution when awaited ---
55
130
 
131
+ /**
132
+ * Standard Promise `then` implementation.
133
+ * Executes all queued collection assertions sequentially when awaited.
134
+ */
56
135
  async then<TResult1 = void, TResult2 = never>(
57
136
  onfulfilled?: ((value: void) => TResult1 | PromiseLike<TResult1>) | null,
58
137
  onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null
@@ -71,3 +150,4 @@ export class MultiElementRunner implements PromiseLike<void> {
71
150
  }
72
151
  }
73
152
  }
153
+
@@ -1,12 +1,35 @@
1
- import { SingleElementMatcher, ElementTarget } from "../types.js";
1
+ import { SingleElementMatcher, ElementTarget, TypeOptions } from "../types.js";
2
2
  import { executeSingleMatcher, resolveElement } from "../matchers.js";
3
3
 
4
+ /**
5
+ * Representation of a queued assertion against an element or page.
6
+ */
4
7
  type AssertionItem = {
5
8
  target?: ElementTarget;
6
9
  matcher: SingleElementMatcher;
7
10
  args: any[];
8
11
  };
9
12
 
13
+ /**
14
+ * Fluent interaction and assertion runner for a single element or browser context.
15
+ *
16
+ * Implements `PromiseLike<void>`, allowing it to be awaited directly or chained with
17
+ * multiple actions and `.should(...)` assertions.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * // Direct action + chained assertion
22
+ * await Spectra.get("#submit-btn")
23
+ * .click()
24
+ * .should("not.be.visible");
25
+ *
26
+ * // Query + multiple assertions
27
+ * await Spectra.get(LoginPage.usernameInput)
28
+ * .should("be.visible")
29
+ * .should("be.enabled")
30
+ * .should("have.value", "admin");
31
+ * ```
32
+ */
10
33
  export class SingleElementRunner implements PromiseLike<void> {
11
34
  private _target: ElementTarget | undefined;
12
35
  private _action: (() => Promise<any>) | null = null;
@@ -19,6 +42,15 @@ export class SingleElementRunner implements PromiseLike<void> {
19
42
 
20
43
  // --- Chained Actions on current target ---
21
44
 
45
+ /**
46
+ * Clicks on the target element.
47
+ *
48
+ * @example
49
+ * ```ts
50
+ * await Spectra.get("#login-btn").click();
51
+ * ```
52
+ * @returns Current runner instance for method chaining.
53
+ */
22
54
  click(): this {
23
55
  const target = this.requireTarget("click");
24
56
  this._action = async () => {
@@ -28,6 +60,15 @@ export class SingleElementRunner implements PromiseLike<void> {
28
60
  return this;
29
61
  }
30
62
 
63
+ /**
64
+ * Double-clicks on the target element.
65
+ *
66
+ * @example
67
+ * ```ts
68
+ * await Spectra.get(".file-row").doubleClick();
69
+ * ```
70
+ * @returns Current runner instance for method chaining.
71
+ */
31
72
  doubleClick(): this {
32
73
  const target = this.requireTarget("doubleClick");
33
74
  this._action = async () => {
@@ -37,6 +78,16 @@ export class SingleElementRunner implements PromiseLike<void> {
37
78
  return this;
38
79
  }
39
80
 
81
+ /**
82
+ * Performs a long-press touch or hold gesture on the target element.
83
+ *
84
+ * @param durationMs - Duration in milliseconds to hold (default: 1000).
85
+ * @example
86
+ * ```ts
87
+ * await Spectra.get("#context-menu-trigger").longPress(1500);
88
+ * ```
89
+ * @returns Current runner instance for method chaining.
90
+ */
40
91
  longPress(durationMs = 1000): this {
41
92
  const target = this.requireTarget("longPress");
42
93
  this._action = async () => {
@@ -53,7 +104,18 @@ export class SingleElementRunner implements PromiseLike<void> {
53
104
  return this;
54
105
  }
55
106
 
56
- type(value: string, options?: { clearFirst?: boolean }): this {
107
+ /**
108
+ * Types string value into the target input element.
109
+ *
110
+ * @param value - Text string to type into the element.
111
+ * @param options - Optional typing options (e.g. `clearFirst: true`).
112
+ * @example
113
+ * ```ts
114
+ * await Spectra.get("#search-input").type("iPhone 15", { clearFirst: true });
115
+ * ```
116
+ * @returns Current runner instance for method chaining.
117
+ */
118
+ type(value: string, options?: TypeOptions): this {
57
119
  const target = this.requireTarget("type");
58
120
  this._action = async () => {
59
121
  const el = await resolveElement(target);
@@ -65,6 +127,15 @@ export class SingleElementRunner implements PromiseLike<void> {
65
127
  return this;
66
128
  }
67
129
 
130
+ /**
131
+ * Clears the current value of the target input element.
132
+ *
133
+ * @example
134
+ * ```ts
135
+ * await Spectra.get("#search-input").clear();
136
+ * ```
137
+ * @returns Current runner instance for method chaining.
138
+ */
68
139
  clear(): this {
69
140
  const target = this.requireTarget("clear");
70
141
  this._action = async () => {
@@ -74,6 +145,16 @@ export class SingleElementRunner implements PromiseLike<void> {
74
145
  return this;
75
146
  }
76
147
 
148
+ /**
149
+ * Selects an option from a `<select>` dropdown by its visible text.
150
+ *
151
+ * @param value - Visible text of the option to select.
152
+ * @example
153
+ * ```ts
154
+ * await Spectra.get("#country-select").select("United States");
155
+ * ```
156
+ * @returns Current runner instance for method chaining.
157
+ */
77
158
  select(value: string): this {
78
159
  const target = this.requireTarget("select");
79
160
  this._action = async () => {
@@ -83,6 +164,15 @@ export class SingleElementRunner implements PromiseLike<void> {
83
164
  return this;
84
165
  }
85
166
 
167
+ /**
168
+ * Moves the mouse cursor over the target element (hover).
169
+ *
170
+ * @example
171
+ * ```ts
172
+ * await Spectra.get("#dropdown-menu-trigger").hover();
173
+ * ```
174
+ * @returns Current runner instance for method chaining.
175
+ */
86
176
  hover(): this {
87
177
  const target = this.requireTarget("hover");
88
178
  this._action = async () => {
@@ -92,6 +182,16 @@ export class SingleElementRunner implements PromiseLike<void> {
92
182
  return this;
93
183
  }
94
184
 
185
+ /**
186
+ * Waits for the target element to become displayed in the DOM.
187
+ *
188
+ * @param timeoutMs - Maximum duration in milliseconds to wait (default: 10000).
189
+ * @example
190
+ * ```ts
191
+ * await Spectra.get("#modal-dialog").waitForElement(5000);
192
+ * ```
193
+ * @returns Current runner instance for method chaining.
194
+ */
95
195
  waitForElement(timeoutMs = 10000): this {
96
196
  const target = this.requireTarget("waitForElement");
97
197
  this._action = async () => {
@@ -103,8 +203,35 @@ export class SingleElementRunner implements PromiseLike<void> {
103
203
 
104
204
  // --- Fluent Assertion Matchers ---
105
205
 
206
+ /**
207
+ * Queues an assertion matcher against the current target element or page.
208
+ *
209
+ * @param matcher - Single element matcher string (e.g. `'be.visible'`, `'have.text'`).
210
+ * @param args - Additional parameters for the matcher (e.g. expected text or value).
211
+ * @example
212
+ * ```ts
213
+ * await Spectra.get("#status-badge").should("be.visible");
214
+ * await Spectra.get("#username").should("have.value", "alice");
215
+ * await Spectra.get("#banner").should("have.class", "alert-success");
216
+ * ```
217
+ * @returns Current runner instance for method chaining.
218
+ */
106
219
  should(matcher: SingleElementMatcher, ...args: any[]): this;
220
+
221
+ /**
222
+ * Queues an assertion matcher targeting a specific element.
223
+ *
224
+ * @param target - Custom element target for this specific assertion.
225
+ * @param matcher - Single element matcher string.
226
+ * @param args - Additional parameters for the matcher.
227
+ * @example
228
+ * ```ts
229
+ * await Spectra.should(LoginPage.submitBtn, "be.enabled");
230
+ * ```
231
+ * @returns Current runner instance for method chaining.
232
+ */
107
233
  should(target: ElementTarget, matcher: SingleElementMatcher, ...args: any[]): this;
234
+
108
235
  should(a: ElementTarget | SingleElementMatcher, b?: any, ...rest: any[]): this {
109
236
  const isFirstArgMatcher =
110
237
  typeof a === "string" &&
@@ -136,6 +263,10 @@ export class SingleElementRunner implements PromiseLike<void> {
136
263
 
137
264
  // --- Execution when awaited ---
138
265
 
266
+ /**
267
+ * Standard Promise `then` implementation.
268
+ * Executes queued action first (if any), followed sequentially by all queued assertions.
269
+ */
139
270
  async then<TResult1 = void, TResult2 = never>(
140
271
  onfulfilled?: ((value: void) => TResult1 | PromiseLike<TResult1>) | null,
141
272
  onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null
@@ -157,6 +288,9 @@ export class SingleElementRunner implements PromiseLike<void> {
157
288
  }
158
289
  }
159
290
 
291
+ /**
292
+ * Helper that throws an error if an action is called without a defined target.
293
+ */
160
294
  private requireTarget(actionName: string): ElementTarget {
161
295
  if (!this._target) {
162
296
  throw new Error(`Cannot execute '${actionName}' without specifying an element target.`);
@@ -164,3 +298,4 @@ export class SingleElementRunner implements PromiseLike<void> {
164
298
  return this._target;
165
299
  }
166
300
  }
301
+