@testspectra/skills 1.2.31 → 1.2.33

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.
@@ -173,13 +173,24 @@ collection carry the scope forward too. No behavior difference on web vs. Androi
173
173
  | `await Spectra.browser.openTab(url?, { isolated: true })` | Open a tab as a second browser: own cookies and storage |
174
174
  | `await Spectra.browser.switchToTab(index)` | Act on tab `index` (0 = first; tabs the app opens follow in order) |
175
175
  | `await Spectra.browser.closeTab()` | Close the active tab (any but the last), act on the one before |
176
+ | `await Spectra.browser.openTab({ userAgent })` | Open a tab whose user agent is `userAgent` (also with `isolated`) |
176
177
  | `await Spectra.browser.shouldHaveTabCount(n)` | Assert `n` tabs open |
178
+ | `await Spectra.browser.getClipboardText()` | Read the page clipboard (origin granted `clipboardReadWrite`) |
179
+ | `await Spectra.browser.shouldHaveClipboardText(text)` | Assert the clipboard text, polling |
180
+ | `await Spectra.browser.getPageLoadCount(tab?)` | Loads of a tab since the test case began / the tab attached |
181
+ | `await Spectra.browser.shouldHavePageLoadCount(n, { tab? })` | Assert a tab's load count: only the refreshed tab grew |
182
+ | `await Spectra.browser.waitForDownload({ timeout? })` | Next file the page downloads: `{ fileName, path, size, text(), rows() }` |
183
+ | `await file.shouldHaveRows(rows, { header? })` | Assert the CSV / first XLSX sheet; `header: false`: `rows` omit the header row |
184
+ | `await file.shouldContainRow(row)` | Assert one row of the file equals `row` |
185
+ | `await Spectra.browser.shouldHaveDownloaded(name \| /re/)` | Assert a download with that name completed, polling |
186
+ | `await Spectra.browser.shouldNotHaveDownloaded({ within? })` | Assert no download this test case, nor in `within` ms (1000) |
187
+ | `await Spectra.browser.shouldHaveDownloadCount(n)` | Assert `n` downloads completed |
177
188
  | `await Spectra.browser.installClock()` | Fake page clock, before the page loads |
178
189
  | `await Spectra.browser.advanceClock(ms)` | Jump the clock; timers that fall due run |
179
190
  | `await Spectra.browser.shouldHaveOpenedDialog(msg?)` | Assert a JS dialog opened (each is answered as it opens) |
180
191
  | `await Spectra.browser.shouldNotHaveOpenedDialog()` | Assert none opened, nor opens for 500ms |
181
192
 
182
- Tabs, the clock and dialogs are web only, and reset when the next test case starts: one tab, no fake clock, no dialogs recorded. Install the clock before `Spectra.navigate`: timers the current document started earlier do not move.
193
+ Tabs, the clock, dialogs and downloads are web only, and reset when the next test case starts: one tab, no fake clock, no dialogs or downloads recorded. Install the clock before `Spectra.navigate`: timers the current document started earlier do not move.
183
194
 
184
195
  ---
185
196
 
@@ -35,6 +35,7 @@ interface MockHandle {
35
35
  shouldHaveCallCount(count: number, options?: { timeout?: number }): Promise<void>; // polls; 0 proves no request went out
36
36
  shouldHaveStatus(status: number, options?: { count?: number; timeout?: number }): Promise<void>; // default: the last answer
37
37
  shouldHaveRequestBody(expected: string | object, options?: { timeout?: number }): Promise<void>; // object: JSON subset; string: substring
38
+ shouldHaveResponseBody(expected: string | object, options?: { count?: number; timeout?: number }): Promise<void>; // the answer's body; default: the last
38
39
  readonly callCount: number;
39
40
  readonly calls: InterceptedRequest[];
40
41
  }
@@ -141,12 +142,15 @@ await OtpPage.boxes.setValue('000000');
141
142
  await verify.waitForResponse(); // default timeout: the implicit wait
142
143
  await verify.shouldHaveStatus(422);
143
144
  await verify.shouldHaveRequestBody({ code: '000000' });
145
+ await verify.shouldHaveResponseBody({ reason: 'invalid_code' }); // the response body: JSON subset or substring
144
146
  await OtpPage.error.shouldHaveText('Invalid code');
145
147
  ```
146
148
 
147
149
  The spy handle has the same `waitForResponse` / `shouldHaveCallCount` / `shouldHaveStatus` /
148
- `shouldHaveRequestBody` / `callCount` / `calls` as above. Only requests answered after the spy is
149
- made count. `requestBody` is cut to 500 characters: expect a part of a long body as a string.
150
+ `shouldHaveRequestBody` / `shouldHaveResponseBody` / `callCount` / `calls` as above. Only requests
151
+ answered after the spy is made count. `requestBody` and `responseBody` are cut to 500 characters:
152
+ expect a part of a long body as a string. `responseBody` is recorded for text Fetch/XHR responses
153
+ only; any other fails the assertion saying why.
150
154
 
151
155
  Intercept with `delayMs` only when the step reads the page while the request is in flight; then
152
156
  `waitForResponse()` before checking the result:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testspectra/skills",
3
- "version": "1.2.31",
3
+ "version": "1.2.33",
4
4
  "description": "Installer & manager for modular AI agent skills that standardize TestSpectra script authoring (specs, page objects, steps, actions, hooks, fixtures, matchers)",
5
5
  "keywords": [
6
6
  "agents",
@@ -173,13 +173,24 @@ collection carry the scope forward too. No behavior difference on web vs. Androi
173
173
  | `await Spectra.browser.openTab(url?, { isolated: true })` | Open a tab as a second browser: own cookies and storage |
174
174
  | `await Spectra.browser.switchToTab(index)` | Act on tab `index` (0 = first; tabs the app opens follow in order) |
175
175
  | `await Spectra.browser.closeTab()` | Close the active tab (any but the last), act on the one before |
176
+ | `await Spectra.browser.openTab({ userAgent })` | Open a tab whose user agent is `userAgent` (also with `isolated`) |
176
177
  | `await Spectra.browser.shouldHaveTabCount(n)` | Assert `n` tabs open |
178
+ | `await Spectra.browser.getClipboardText()` | Read the page clipboard (origin granted `clipboardReadWrite`) |
179
+ | `await Spectra.browser.shouldHaveClipboardText(text)` | Assert the clipboard text, polling |
180
+ | `await Spectra.browser.getPageLoadCount(tab?)` | Loads of a tab since the test case began / the tab attached |
181
+ | `await Spectra.browser.shouldHavePageLoadCount(n, { tab? })` | Assert a tab's load count: only the refreshed tab grew |
182
+ | `await Spectra.browser.waitForDownload({ timeout? })` | Next file the page downloads: `{ fileName, path, size, text(), rows() }` |
183
+ | `await file.shouldHaveRows(rows, { header? })` | Assert the CSV / first XLSX sheet; `header: false`: `rows` omit the header row |
184
+ | `await file.shouldContainRow(row)` | Assert one row of the file equals `row` |
185
+ | `await Spectra.browser.shouldHaveDownloaded(name \| /re/)` | Assert a download with that name completed, polling |
186
+ | `await Spectra.browser.shouldNotHaveDownloaded({ within? })` | Assert no download this test case, nor in `within` ms (1000) |
187
+ | `await Spectra.browser.shouldHaveDownloadCount(n)` | Assert `n` downloads completed |
177
188
  | `await Spectra.browser.installClock()` | Fake page clock, before the page loads |
178
189
  | `await Spectra.browser.advanceClock(ms)` | Jump the clock; timers that fall due run |
179
190
  | `await Spectra.browser.shouldHaveOpenedDialog(msg?)` | Assert a JS dialog opened (each is answered as it opens) |
180
191
  | `await Spectra.browser.shouldNotHaveOpenedDialog()` | Assert none opened, nor opens for 500ms |
181
192
 
182
- Tabs, the clock and dialogs are web only, and reset when the next test case starts: one tab, no fake clock, no dialogs recorded. Install the clock before `Spectra.navigate`: timers the current document started earlier do not move.
193
+ Tabs, the clock, dialogs and downloads are web only, and reset when the next test case starts: one tab, no fake clock, no dialogs or downloads recorded. Install the clock before `Spectra.navigate`: timers the current document started earlier do not move.
183
194
 
184
195
  ---
185
196
 
@@ -35,6 +35,7 @@ interface MockHandle {
35
35
  shouldHaveCallCount(count: number, options?: { timeout?: number }): Promise<void>; // polls; 0 proves no request went out
36
36
  shouldHaveStatus(status: number, options?: { count?: number; timeout?: number }): Promise<void>; // default: the last answer
37
37
  shouldHaveRequestBody(expected: string | object, options?: { timeout?: number }): Promise<void>; // object: JSON subset; string: substring
38
+ shouldHaveResponseBody(expected: string | object, options?: { count?: number; timeout?: number }): Promise<void>; // the answer's body; default: the last
38
39
  readonly callCount: number;
39
40
  readonly calls: InterceptedRequest[];
40
41
  }
@@ -141,12 +142,15 @@ await OtpPage.boxes.setValue('000000');
141
142
  await verify.waitForResponse(); // default timeout: the implicit wait
142
143
  await verify.shouldHaveStatus(422);
143
144
  await verify.shouldHaveRequestBody({ code: '000000' });
145
+ await verify.shouldHaveResponseBody({ reason: 'invalid_code' }); // the response body: JSON subset or substring
144
146
  await OtpPage.error.shouldHaveText('Invalid code');
145
147
  ```
146
148
 
147
149
  The spy handle has the same `waitForResponse` / `shouldHaveCallCount` / `shouldHaveStatus` /
148
- `shouldHaveRequestBody` / `callCount` / `calls` as above. Only requests answered after the spy is
149
- made count. `requestBody` is cut to 500 characters: expect a part of a long body as a string.
150
+ `shouldHaveRequestBody` / `shouldHaveResponseBody` / `callCount` / `calls` as above. Only requests
151
+ answered after the spy is made count. `requestBody` and `responseBody` are cut to 500 characters:
152
+ expect a part of a long body as a string. `responseBody` is recorded for text Fetch/XHR responses
153
+ only; any other fails the assertion saying why.
150
154
 
151
155
  Intercept with `delayMs` only when the step reads the page while the request is in flight; then
152
156
  `waitForResponse()` before checking the result: