@testspectra/cli 1.1.8-rc.2 → 1.1.8-rc.20
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/README.md +47 -0
- package/bin/spectra.js +0 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/commands/__tests__/run-e2e.test.js +49 -49
- package/dist/commands/add.js +2 -1
- package/dist/commands/devices.js +1 -0
- package/dist/commands/doctor.js +1 -0
- package/dist/commands/init.js +150 -149
- package/dist/commands/install.js +2 -0
- package/dist/commands/license.js +1 -0
- package/dist/commands/test.js +5 -3
- package/dist/generator/__tests__/tsconfig-isolation.test.js +2 -1
- package/dist/generator/__tests__/type-generator.test.js +38 -0
- package/dist/generator/tsconfig-generator.js +1 -1
- package/dist/generator/type-generator.d.ts +5 -2
- package/dist/generator/type-generator.js +14 -17
- package/dist/index.js +11 -11
- package/dist/linter/__tests__/component-test-imports.test.js +51 -51
- package/dist/linter/__tests__/shared-lib-boundary.test.js +15 -15
- package/dist/linter/__tests__/spec-schema.test.js +167 -167
- package/dist/linter/discovery.d.ts +3 -3
- package/dist/linter/discovery.js +5 -5
- package/dist/linter/schemas/spec.schema.d.ts +2 -2
- package/dist/linter/schemas/suite.schema.d.ts +4 -4
- package/dist/runner/bridge.js +53 -4
- package/package.json +34 -29
- package/templates/default/CLAUDE.md +16 -16
- package/templates/default/global-hooks/after/mobile.hook.ts +3 -3
- package/templates/default/global-hooks/after/web.hook.ts +3 -3
- package/templates/default/global-hooks/before/mobile.hook.ts +3 -3
- package/templates/default/global-hooks/before/web.hook.ts +3 -3
- package/templates/default/package.json +2 -2
- package/templates/default/page-objects/AuthPage/mobile.ts +5 -5
- package/templates/default/page-objects/AuthPage/web.ts +10 -10
- package/templates/default/page-objects/MatchersPage/mobile.ts +70 -70
- package/templates/default/page-objects/MatchersPage/web.ts +43 -43
- package/templates/default/page-objects/NavigationPage/mobile.ts +14 -14
- package/templates/default/page-objects/NavigationPage/web.ts +8 -8
- package/templates/default/page-objects/PlaygroundPage/mobile.ts +42 -42
- package/templates/default/page-objects/PlaygroundPage/web.ts +31 -31
- package/templates/default/specs/ApiInterception/TC-0008-fetch-mocking/mobile.test.ts +53 -53
- package/templates/default/specs/ApiInterception/TC-0008-fetch-mocking/spec.md +19 -19
- package/templates/default/specs/ApiInterception/TC-0008-fetch-mocking/web.test.ts +31 -31
- package/templates/default/specs/ApiInterception/TC-0009-post-mocking/android.test.ts +3 -3
- package/templates/default/specs/ApiInterception/TC-0009-post-mocking/common.test.ts +3 -3
- package/templates/default/specs/ApiInterception/TC-0009-post-mocking/mobile.test.ts +27 -27
- package/templates/default/specs/ApiInterception/TC-0009-post-mocking/spec.md +19 -19
- package/templates/default/specs/ApiInterception/TC-0009-post-mocking/web.test.ts +26 -26
- package/templates/default/specs/ApiInterception/TC-0012-direct-and-late-response/common.test.ts +30 -30
- package/templates/default/specs/ApiInterception/TC-0012-direct-and-late-response/spec.md +22 -22
- package/templates/default/specs/ApiInterception/TC-0013-real-network-call-recorded/common.test.ts +27 -27
- package/templates/default/specs/ApiInterception/TC-0013-real-network-call-recorded/spec.md +20 -20
- package/templates/default/specs/ApiInterception/TC-0015-mock-server-sent-events/spec.md +24 -24
- package/templates/default/specs/ApiInterception/TC-0015-mock-server-sent-events/web.test.ts +26 -26
- package/templates/default/specs/ApiInterception/TC-0016-bypass-websocket-with-app-level-mock/spec.md +37 -37
- package/templates/default/specs/ApiInterception/TC-0016-bypass-websocket-with-app-level-mock/web.test.ts +21 -21
- package/templates/default/specs/ApiInterception/TC-0017-bypass-captcha-with-test-mode-flag/spec.md +29 -29
- package/templates/default/specs/ApiInterception/TC-0017-bypass-captcha-with-test-mode-flag/web.test.ts +16 -16
- package/templates/default/specs/ApiInterception/suite.md +10 -10
- package/templates/default/specs/ApiSeeding/TC-0014-seed-and-cleanup-via-hooks/common.test.ts +30 -30
- package/templates/default/specs/ApiSeeding/TC-0014-seed-and-cleanup-via-hooks/spec.md +23 -23
- package/templates/default/specs/ApiSeeding/hooks/after/common.hook.ts +16 -16
- package/templates/default/specs/ApiSeeding/hooks/before/common.hook.ts +28 -28
- package/templates/default/specs/ApiSeeding/suite.md +9 -9
- package/templates/default/specs/Authentication/TC-0021-seed-authenticated-session/mobile.test.ts +7 -7
- package/templates/default/specs/Authentication/TC-0021-seed-authenticated-session/spec.md +19 -19
- package/templates/default/specs/Authentication/TC-0021-seed-authenticated-session/web.test.ts +9 -9
- package/templates/default/specs/Authentication/suite.md +9 -9
- package/templates/default/specs/BrowserContext/TC-0007-title-and-navigation/mobile.test.ts +9 -9
- package/templates/default/specs/BrowserContext/TC-0007-title-and-navigation/spec.md +17 -17
- package/templates/default/specs/BrowserContext/TC-0007-title-and-navigation/web.test.ts +19 -19
- package/templates/default/specs/BrowserContext/TC-0022-history-navigation/mobile.test.ts +17 -17
- package/templates/default/specs/BrowserContext/TC-0022-history-navigation/spec.md +28 -28
- package/templates/default/specs/BrowserContext/TC-0022-history-navigation/web.test.ts +26 -26
- package/templates/default/specs/ContentMatchers/TC-0005-text-and-values/common.test.ts +26 -26
- package/templates/default/specs/ContentMatchers/TC-0005-text-and-values/spec.md +19 -19
- package/templates/default/specs/ContentMatchers/TC-0006-collections-and-empty/mobile.test.ts +11 -11
- package/templates/default/specs/ContentMatchers/TC-0006-collections-and-empty/spec.md +17 -17
- package/templates/default/specs/ContentMatchers/TC-0006-collections-and-empty/web.test.ts +11 -11
- package/templates/default/specs/ContentMatchers/TC-0020-scoped-element-access/common.test.ts +14 -14
- package/templates/default/specs/ContentMatchers/TC-0020-scoped-element-access/spec.md +21 -21
- package/templates/default/specs/DeepLink/TC-0018-navigate-via-deep-link/mobile.test.ts +28 -28
- package/templates/default/specs/DeepLink/TC-0018-navigate-via-deep-link/spec.md +29 -29
- package/templates/default/specs/DeepLink/suite.md +9 -9
- package/templates/default/specs/ElementMatchers/TC-0003-visibility-and-dom/mobile.test.ts +11 -11
- package/templates/default/specs/ElementMatchers/TC-0003-visibility-and-dom/spec.md +17 -17
- package/templates/default/specs/ElementMatchers/TC-0003-visibility-and-dom/web.test.ts +11 -11
- package/templates/default/specs/ElementMatchers/TC-0004-states-and-attributes/mobile.test.ts +29 -29
- package/templates/default/specs/ElementMatchers/TC-0004-states-and-attributes/spec.md +19 -19
- package/templates/default/specs/ElementMatchers/TC-0004-states-and-attributes/web.test.ts +29 -29
- package/templates/default/specs/ElementMatchers/suite.md +10 -10
- package/templates/default/specs/EnvironmentConfig/TC-0019-read-custom-environment-variable/common.test.ts +5 -5
- package/templates/default/specs/EnvironmentConfig/TC-0019-read-custom-environment-variable/spec.md +16 -16
- package/templates/default/specs/EnvironmentConfig/suite.md +9 -9
- package/templates/default/specs/PermissionRationale/TC-0010-camera-permission-allow/mobile.test.ts +26 -26
- package/templates/default/specs/PermissionRationale/TC-0010-camera-permission-allow/spec.md +22 -22
- package/templates/default/specs/PermissionRationale/TC-0011-camera-permission-deny/mobile.test.ts +13 -13
- package/templates/default/specs/PermissionRationale/TC-0011-camera-permission-deny/spec.md +20 -20
- package/templates/default/specs/PermissionRationale/suite.md +9 -9
- package/templates/default/specs/Playground/TC-0001-form-controls/mobile.test.ts +6 -6
- package/templates/default/specs/Playground/TC-0001-form-controls/spec.md +18 -18
- package/templates/default/specs/Playground/TC-0001-form-controls/web.test.ts +6 -6
- package/templates/default/specs/Playground/TC-0002-toggle-elements/mobile.test.ts +6 -6
- package/templates/default/specs/Playground/TC-0002-toggle-elements/spec.md +18 -18
- package/templates/default/specs/Playground/TC-0002-toggle-elements/web.test.ts +6 -6
- package/templates/default/spectra.config.ts +52 -52
- package/templates/default/support/actions/fillCredentials/mobile.action.ts +4 -4
- package/templates/default/support/actions/fillCredentials/web.action.ts +4 -4
- package/templates/default/support/actions/seedSession/mobile.action.ts +9 -9
- package/templates/default/support/actions/seedSession/web.action.ts +13 -13
- package/templates/default/support/steps/togglePlaygroundStates/mobile.step.ts +5 -5
- package/templates/default/support/steps/togglePlaygroundStates/web.step.ts +5 -5
- package/templates/default/support/steps/verifyPlaygroundState/mobile.step.ts +6 -6
- package/templates/default/support/steps/verifyPlaygroundState/web.step.ts +6 -6
- package/templates/nx/.nx/workspace-data/{59842386-c7c4-44ca-b2c2-20e1700bd13d.db-shm → 70094CFD-E89B-57A1-9619-2FC5F4963C54.db-shm} +0 -0
- package/templates/nx/.nx/workspace-data/70094CFD-E89B-57A1-9619-2FC5F4963C54.db-wal +0 -0
- package/templates/nx/.nx/workspace-data/d/daemon.log +6269 -1577
- package/templates/nx/.nx/workspace-data/file-map.json +129 -129
- package/templates/nx/.nx/workspace-data/lockfile.hash +1 -1
- package/templates/nx/.nx/workspace-data/nx_files.nxt +0 -0
- package/templates/nx/.nx/workspace-data/parsed-lock-file.json +535 -535
- package/templates/nx/.nx/workspace-data/project-graph.json +589 -590
- package/templates/nx/CLAUDE.md +10 -10
- package/templates/nx/package.json +2 -2
- package/templates/nx/packages/matchers/e2e/project.json +2 -2
- package/templates/nx/packages/matchers/e2e/specs/ApiInterception/TC-0008-fetch-mocking/mobile.test.ts +27 -27
- package/templates/nx/packages/matchers/e2e/specs/ApiInterception/TC-0008-fetch-mocking/web.test.ts +27 -27
- package/templates/nx/packages/matchers/e2e/specs/ApiInterception/TC-0009-post-mocking/mobile.test.ts +24 -24
- package/templates/nx/packages/matchers/e2e/specs/ApiInterception/TC-0009-post-mocking/web.test.ts +24 -24
- package/templates/nx/packages/matchers/e2e/specs/BrowserContext/TC-0007-title-and-navigation/mobile.test.ts +3 -3
- package/templates/nx/packages/matchers/e2e/specs/BrowserContext/TC-0007-title-and-navigation/web.test.ts +19 -19
- package/templates/nx/packages/matchers/e2e/specs/ContentMatchers/TC-0005-text-and-values/mobile.test.ts +3 -3
- package/templates/nx/packages/matchers/e2e/specs/ContentMatchers/TC-0005-text-and-values/web.test.ts +17 -17
- package/templates/nx/packages/matchers/e2e/specs/ContentMatchers/TC-0006-collections-and-empty/mobile.test.ts +3 -3
- package/templates/nx/packages/matchers/e2e/specs/ContentMatchers/TC-0006-collections-and-empty/web.test.ts +11 -11
- package/templates/nx/packages/matchers/e2e/specs/ElementMatchers/TC-0003-visibility-and-dom/mobile.test.ts +3 -3
- package/templates/nx/packages/matchers/e2e/specs/ElementMatchers/TC-0003-visibility-and-dom/web.test.ts +11 -11
- package/templates/nx/packages/matchers/e2e/specs/ElementMatchers/TC-0004-states-and-attributes/mobile.test.ts +3 -3
- package/templates/nx/packages/matchers/e2e/specs/ElementMatchers/TC-0004-states-and-attributes/web.test.ts +29 -29
- package/templates/nx/packages/matchers/e2e/specs/EnvironmentConfig/TC-0019-read-custom-environment-variable/common.test.ts +5 -5
- package/templates/nx/packages/matchers/e2e/specs/EnvironmentConfig/TC-0019-read-custom-environment-variable/spec.md +16 -16
- package/templates/nx/packages/matchers/e2e/specs/EnvironmentConfig/suite.md +9 -9
- package/templates/nx/packages/playground/e2e/project.json +2 -2
- package/templates/nx/packages/playground/e2e/specs/Playground/TC-0001-form-controls/mobile.test.ts +3 -3
- package/templates/nx/packages/playground/e2e/specs/Playground/TC-0001-form-controls/web.test.ts +6 -6
- package/templates/nx/packages/playground/e2e/specs/Playground/TC-0002-toggle-elements/mobile.test.ts +3 -3
- package/templates/nx/packages/playground/e2e/specs/Playground/TC-0002-toggle-elements/web.test.ts +6 -6
- package/templates/nx/pnpm-lock.yaml +6663 -6663
- package/templates/nx/pnpm-workspace.yaml +9 -9
- package/templates/nx/shared/testing/page-objects/MatchersPage/mobile.ts +33 -33
- package/templates/nx/shared/testing/page-objects/MatchersPage/web.ts +91 -91
- package/templates/nx/shared/testing/page-objects/NavigationPage/mobile.ts +5 -5
- package/templates/nx/shared/testing/page-objects/NavigationPage/web.ts +8 -8
- package/templates/nx/shared/testing/page-objects/PlaygroundPage/mobile.ts +26 -26
- package/templates/nx/shared/testing/page-objects/PlaygroundPage/web.ts +31 -31
- package/templates/nx/shared/testing/project.json +18 -19
- package/templates/nx/shared/testing/support/actions/fillCredentials/mobile.action.ts +4 -4
- package/templates/nx/shared/testing/support/actions/fillCredentials/web.action.ts +4 -4
- package/templates/nx/shared/testing/support/steps/togglePlaygroundStates/mobile.step.ts +3 -3
- package/templates/nx/shared/testing/support/steps/togglePlaygroundStates/web.step.ts +5 -5
- package/templates/nx/shared/testing/support/steps/verifyPlaygroundState/mobile.step.ts +4 -4
- package/templates/nx/shared/testing/support/steps/verifyPlaygroundState/web.step.ts +6 -6
- package/templates/nx/spectra.config.ts +52 -52
- package/templates/react-component/.cursorrules +17 -17
- package/templates/react-component/.vscode/extensions.json +5 -5
- package/templates/react-component/CLAUDE.md +14 -14
- package/templates/react-component/README.md +69 -69
- package/templates/react-component/fixtures/component-mock.json +12 -12
- package/templates/react-component/global-hooks/after/web.hook.ts +3 -3
- package/templates/react-component/global-hooks/before/web.hook.ts +3 -3
- package/templates/react-component/package.json +27 -27
- package/templates/react-component/page-objects/BadgeComponent/web.ts +23 -23
- package/templates/react-component/page-objects/ButtonComponent/web.ts +23 -23
- package/templates/react-component/page-objects/InputComponent/web.ts +13 -13
- package/templates/react-component/specs/BadgeComponent/TC-0002-badge-severities-and-dot/spec.md +18 -18
- package/templates/react-component/specs/BadgeComponent/TC-0002-badge-severities-and-dot/web.test.tsx +11 -11
- package/templates/react-component/specs/BadgeComponent/TC-0006-badge-success-with-dot/spec.md +18 -18
- package/templates/react-component/specs/BadgeComponent/TC-0006-badge-success-with-dot/web.test.tsx +10 -10
- package/templates/react-component/specs/BadgeComponent/TC-0007-badge-by-severity-lookup/spec.md +18 -18
- package/templates/react-component/specs/BadgeComponent/TC-0007-badge-by-severity-lookup/web.test.tsx +16 -16
- package/templates/react-component/specs/BadgeComponent/suite.md +12 -12
- package/templates/react-component/specs/ButtonComponent/TC-0001-button-rendering-and-click/spec.md +19 -19
- package/templates/react-component/specs/ButtonComponent/TC-0001-button-rendering-and-click/web.test.tsx +28 -28
- package/templates/react-component/specs/ButtonComponent/TC-0004-disabled-button-not-clickable/spec.md +19 -19
- package/templates/react-component/specs/ButtonComponent/TC-0004-disabled-button-not-clickable/web.test.tsx +22 -22
- package/templates/react-component/specs/ButtonComponent/TC-0005-button-renders-icon/spec.md +18 -18
- package/templates/react-component/specs/ButtonComponent/TC-0005-button-renders-icon/web.test.tsx +8 -8
- package/templates/react-component/specs/ButtonComponent/suite.md +12 -12
- package/templates/react-component/specs/InputComponent/TC-0003-input-typing-and-clear/spec.md +20 -20
- package/templates/react-component/specs/InputComponent/TC-0003-input-typing-and-clear/web.test.tsx +28 -28
- package/templates/react-component/specs/InputComponent/TC-0008-disabled-input-not-editable/spec.md +18 -18
- package/templates/react-component/specs/InputComponent/TC-0008-disabled-input-not-editable/web.test.tsx +9 -9
- package/templates/react-component/specs/InputComponent/suite.md +12 -12
- package/templates/react-component/spectra.config.ts +27 -27
- package/templates/react-component/src/components/Badge/Badge.tsx +60 -60
- package/templates/react-component/src/components/Button/Button.tsx +57 -57
- package/templates/react-component/src/components/Input/Input.tsx +41 -41
- package/templates/react-component/src/test-utils.tsx +23 -23
- package/templates/react-component/support/actions/fillInputField/web.action.ts +9 -9
- package/templates/react-component/support/steps/verifyButtonState/web.step.ts +12 -12
- package/bin/.testspectra-runner.hash +0 -1
- package/bin/testspectra-runner.exe +0 -0
- package/templates/nx/.nx/workspace-data/59842386-c7c4-44ca-b2c2-20e1700bd13d.db-wal +0 -0
- package/templates/nx/.nx/workspace-data/d/server-process.json +0 -3
- /package/templates/nx/.nx/workspace-data/{59842386-c7c4-44ca-b2c2-20e1700bd13d.db → 70094CFD-E89B-57A1-9619-2FC5F4963C54.db} +0 -0
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
it("Mock and assert GET API requests using browser.intercept", async () => {
|
|
2
|
-
// Navigate to API Fetch section
|
|
3
|
-
await MatchersPage.open("api-fetch");
|
|
4
|
-
|
|
5
|
-
// The app fetches the host demo server's self-hosted endpoint (http://localhost:5200/api/posts) —
|
|
6
|
-
// the device's global HTTP proxy (set up transparently at bootstrap) routes it through the
|
|
7
|
-
// worker's mock proxy without the app knowing or needing any special host/prefix, the same
|
|
8
|
-
// way the CDP web driver intercepts traffic for free. Clear any mock left registered by an
|
|
9
|
-
// earlier test in this same continuous session before adding this one.
|
|
10
|
-
Spectra.clearMocks();
|
|
11
|
-
const mock = await Spectra.intercept(
|
|
12
|
-
"api/posts",
|
|
13
|
-
"GET",
|
|
14
|
-
Fixture.apiData.mockPosts
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
// Trigger fetch button in mobile demo app
|
|
18
|
-
await MatchersPage.fetchApiButton.click();
|
|
19
|
-
|
|
20
|
-
// Assert status and mocked elements
|
|
21
|
-
await MatchersPage.fetchStatusBadge.shouldHaveText("200 OK");
|
|
22
|
-
await MatchersPage.fetchedItems.shouldHaveLength(Fixture.apiData.mockPosts.length);
|
|
23
|
-
await MatchersPage.fetchedItems.first().shouldContainText(Fixture.apiData.mockPosts[0].title);
|
|
24
|
-
|
|
25
|
-
// Dynamically update fixture response
|
|
26
|
-
await mock.respondWith([
|
|
27
|
-
{ id: 99, title: "Dynamic Updated Mock Title", body: "Updated on the fly" }
|
|
28
|
-
]);
|
|
29
|
-
await MatchersPage.fetchApiButton.click();
|
|
30
|
-
await MatchersPage.fetchedItems.shouldHaveLength(1);
|
|
31
|
-
await MatchersPage.fetchedItems.first().shouldContainText("Dynamic Updated Mock Title");
|
|
32
|
-
|
|
33
|
-
// Reset to the base mock and queue a single one-time response — asserts a transient state
|
|
34
|
-
// (e.g. one retry attempt) without disturbing what every other call returns.
|
|
35
|
-
Spectra.clearMocks();
|
|
36
|
-
const queuedMock = await Spectra.intercept(
|
|
37
|
-
"api/posts",
|
|
38
|
-
"GET",
|
|
39
|
-
Fixture.apiData.mockPosts
|
|
40
|
-
);
|
|
41
|
-
await queuedMock.respondOnce([
|
|
42
|
-
{ id: 777, title: "One-Time Queued Response", body: "Only served once" }
|
|
43
|
-
]);
|
|
44
|
-
|
|
45
|
-
await MatchersPage.fetchApiButton.click();
|
|
46
|
-
await MatchersPage.fetchedItems.shouldHaveLength(1);
|
|
47
|
-
await MatchersPage.fetchedItems.first().shouldContainText("One-Time Queued Response");
|
|
48
|
-
|
|
49
|
-
// The queued response is consumed by the call above — this one reverts to the base rule.
|
|
50
|
-
await MatchersPage.fetchApiButton.click();
|
|
51
|
-
await MatchersPage.fetchedItems.shouldHaveLength(Fixture.apiData.mockPosts.length);
|
|
52
|
-
await MatchersPage.fetchedItems.first().shouldContainText(Fixture.apiData.mockPosts[0].title);
|
|
53
|
-
});
|
|
1
|
+
it("Mock and assert GET API requests using browser.intercept", async () => {
|
|
2
|
+
// Navigate to API Fetch section
|
|
3
|
+
await MatchersPage.open("api-fetch");
|
|
4
|
+
|
|
5
|
+
// The app fetches the host demo server's self-hosted endpoint (http://localhost:5200/api/posts) —
|
|
6
|
+
// the device's global HTTP proxy (set up transparently at bootstrap) routes it through the
|
|
7
|
+
// worker's mock proxy without the app knowing or needing any special host/prefix, the same
|
|
8
|
+
// way the CDP web driver intercepts traffic for free. Clear any mock left registered by an
|
|
9
|
+
// earlier test in this same continuous session before adding this one.
|
|
10
|
+
Spectra.clearMocks();
|
|
11
|
+
const mock = await Spectra.intercept(
|
|
12
|
+
"api/posts",
|
|
13
|
+
"GET",
|
|
14
|
+
Fixture.apiData.mockPosts
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
// Trigger fetch button in mobile demo app
|
|
18
|
+
await MatchersPage.fetchApiButton.click();
|
|
19
|
+
|
|
20
|
+
// Assert status and mocked elements
|
|
21
|
+
await MatchersPage.fetchStatusBadge.shouldHaveText("200 OK");
|
|
22
|
+
await MatchersPage.fetchedItems.shouldHaveLength(Fixture.apiData.mockPosts.length);
|
|
23
|
+
await MatchersPage.fetchedItems.first().shouldContainText(Fixture.apiData.mockPosts[0].title);
|
|
24
|
+
|
|
25
|
+
// Dynamically update fixture response
|
|
26
|
+
await mock.respondWith([
|
|
27
|
+
{ id: 99, title: "Dynamic Updated Mock Title", body: "Updated on the fly" }
|
|
28
|
+
]);
|
|
29
|
+
await MatchersPage.fetchApiButton.click();
|
|
30
|
+
await MatchersPage.fetchedItems.shouldHaveLength(1);
|
|
31
|
+
await MatchersPage.fetchedItems.first().shouldContainText("Dynamic Updated Mock Title");
|
|
32
|
+
|
|
33
|
+
// Reset to the base mock and queue a single one-time response — asserts a transient state
|
|
34
|
+
// (e.g. one retry attempt) without disturbing what every other call returns.
|
|
35
|
+
Spectra.clearMocks();
|
|
36
|
+
const queuedMock = await Spectra.intercept(
|
|
37
|
+
"api/posts",
|
|
38
|
+
"GET",
|
|
39
|
+
Fixture.apiData.mockPosts
|
|
40
|
+
);
|
|
41
|
+
await queuedMock.respondOnce([
|
|
42
|
+
{ id: 777, title: "One-Time Queued Response", body: "Only served once" }
|
|
43
|
+
]);
|
|
44
|
+
|
|
45
|
+
await MatchersPage.fetchApiButton.click();
|
|
46
|
+
await MatchersPage.fetchedItems.shouldHaveLength(1);
|
|
47
|
+
await MatchersPage.fetchedItems.first().shouldContainText("One-Time Queued Response");
|
|
48
|
+
|
|
49
|
+
// The queued response is consumed by the call above — this one reverts to the base rule.
|
|
50
|
+
await MatchersPage.fetchApiButton.click();
|
|
51
|
+
await MatchersPage.fetchedItems.shouldHaveLength(Fixture.apiData.mockPosts.length);
|
|
52
|
+
await MatchersPage.fetchedItems.first().shouldContainText(Fixture.apiData.mockPosts[0].title);
|
|
53
|
+
});
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
---
|
|
2
|
-
id: TC-0008-fetch-mocking
|
|
3
|
-
title: Mock and assert GET API requests using browser.intercept
|
|
4
|
-
priority: High
|
|
5
|
-
caseType: Positive
|
|
6
|
-
status: ready-for-automation
|
|
7
|
-
coverage:
|
|
8
|
-
web: automated
|
|
9
|
-
mobile: automated
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
# Mock and assert GET API requests using browser.intercept
|
|
13
|
-
|
|
14
|
-
## Test Steps
|
|
15
|
-
1. Open API fetch section in matchers page
|
|
16
|
-
2. Intercept GET /api/posts with mock posts fixture data
|
|
17
|
-
3. Click fetch API button
|
|
18
|
-
4. Assert status badge displays 200 OK and rendered items match fixture
|
|
19
|
-
5. Update mock response dynamically and verify updated items rendered
|
|
1
|
+
---
|
|
2
|
+
id: TC-0008-fetch-mocking
|
|
3
|
+
title: Mock and assert GET API requests using browser.intercept
|
|
4
|
+
priority: High
|
|
5
|
+
caseType: Positive
|
|
6
|
+
status: ready-for-automation
|
|
7
|
+
coverage:
|
|
8
|
+
web: automated
|
|
9
|
+
mobile: automated
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Mock and assert GET API requests using browser.intercept
|
|
13
|
+
|
|
14
|
+
## Test Steps
|
|
15
|
+
1. Open API fetch section in matchers page
|
|
16
|
+
2. Intercept GET /api/posts with mock posts fixture data
|
|
17
|
+
3. Click fetch API button
|
|
18
|
+
4. Assert status badge displays 200 OK and rendered items match fixture
|
|
19
|
+
5. Update mock response dynamically and verify updated items rendered
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
it("Mock and assert GET API requests using browser.intercept", async () => {
|
|
2
|
-
// Navigate to API Fetch section
|
|
3
|
-
await MatchersPage.open("api-fetch");
|
|
4
|
-
|
|
5
|
-
// The app fetches the demo server's own self-hosted endpoint (/api/posts) — served by the
|
|
6
|
-
// built-in demo app (started with `--demo`), so no external network is involved. Clear any mock
|
|
7
|
-
// left registered by an earlier test in this same continuous session before adding this one,
|
|
8
|
-
// since rules aren't scoped per-test and the first matching rule wins.
|
|
9
|
-
Spectra.clearMocks();
|
|
10
|
-
const mock = await Spectra.intercept(
|
|
11
|
-
"api/posts",
|
|
12
|
-
"GET",
|
|
13
|
-
Fixture.apiData.mockPosts
|
|
14
|
-
);
|
|
15
|
-
|
|
16
|
-
// Trigger fetch button
|
|
17
|
-
await MatchersPage.fetchApiButton.click();
|
|
18
|
-
|
|
19
|
-
// Assert status and mocked elements
|
|
20
|
-
await MatchersPage.fetchStatusBadge.shouldHaveText("200 OK");
|
|
21
|
-
await MatchersPage.fetchedItems.shouldHaveLength(Fixture.apiData.mockPosts.length);
|
|
22
|
-
await MatchersPage.fetchedItems.first().shouldContainText(Fixture.apiData.mockPosts[0].title);
|
|
23
|
-
|
|
24
|
-
// Dynamically update fixture response
|
|
25
|
-
await mock.respondWith([
|
|
26
|
-
{ id: 99, title: "Dynamic Updated Mock Title", body: "Updated on the fly" }
|
|
27
|
-
]);
|
|
28
|
-
await MatchersPage.fetchApiButton.click();
|
|
29
|
-
await MatchersPage.fetchedItems.shouldHaveLength(1);
|
|
30
|
-
await MatchersPage.fetchedItems.first().shouldContainText("Dynamic Updated Mock Title");
|
|
31
|
-
});
|
|
1
|
+
it("Mock and assert GET API requests using browser.intercept", async () => {
|
|
2
|
+
// Navigate to API Fetch section
|
|
3
|
+
await MatchersPage.open("api-fetch");
|
|
4
|
+
|
|
5
|
+
// The app fetches the demo server's own self-hosted endpoint (/api/posts) — served by the
|
|
6
|
+
// built-in demo app (started with `--demo`), so no external network is involved. Clear any mock
|
|
7
|
+
// left registered by an earlier test in this same continuous session before adding this one,
|
|
8
|
+
// since rules aren't scoped per-test and the first matching rule wins.
|
|
9
|
+
Spectra.clearMocks();
|
|
10
|
+
const mock = await Spectra.intercept(
|
|
11
|
+
"api/posts",
|
|
12
|
+
"GET",
|
|
13
|
+
Fixture.apiData.mockPosts
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
// Trigger fetch button
|
|
17
|
+
await MatchersPage.fetchApiButton.click();
|
|
18
|
+
|
|
19
|
+
// Assert status and mocked elements
|
|
20
|
+
await MatchersPage.fetchStatusBadge.shouldHaveText("200 OK");
|
|
21
|
+
await MatchersPage.fetchedItems.shouldHaveLength(Fixture.apiData.mockPosts.length);
|
|
22
|
+
await MatchersPage.fetchedItems.first().shouldContainText(Fixture.apiData.mockPosts[0].title);
|
|
23
|
+
|
|
24
|
+
// Dynamically update fixture response
|
|
25
|
+
await mock.respondWith([
|
|
26
|
+
{ id: 99, title: "Dynamic Updated Mock Title", body: "Updated on the fly" }
|
|
27
|
+
]);
|
|
28
|
+
await MatchersPage.fetchApiButton.click();
|
|
29
|
+
await MatchersPage.fetchedItems.shouldHaveLength(1);
|
|
30
|
+
await MatchersPage.fetchedItems.first().shouldContainText("Dynamic Updated Mock Title");
|
|
31
|
+
});
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
it('Mock and assert POST API requests using browser.intercept', async () => {
|
|
2
|
-
// TODO: Implement test steps and assertions
|
|
3
|
-
});
|
|
1
|
+
it('Mock and assert POST API requests using browser.intercept', async () => {
|
|
2
|
+
// TODO: Implement test steps and assertions
|
|
3
|
+
});
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
it('Mock and assert POST API requests using browser.intercept', async () => {
|
|
2
|
-
// TODO: Implement test steps and assertions
|
|
3
|
-
});
|
|
1
|
+
it('Mock and assert POST API requests using browser.intercept', async () => {
|
|
2
|
+
// TODO: Implement test steps and assertions
|
|
3
|
+
});
|
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
it("Mock and assert POST API requests using browser.intercept", async () => {
|
|
2
|
-
// Navigate to API POST section
|
|
3
|
-
await MatchersPage.open("api-post");
|
|
4
|
-
|
|
5
|
-
// Setup POST API interception with status 201 — the app posts to the host demo server's
|
|
6
|
-
// self-hosted endpoint (http://localhost:5200/api/posts), transparently routed through the
|
|
7
|
-
// worker's mock proxy via the device's global HTTP proxy set up at bootstrap.
|
|
8
|
-
Spectra.clearMocks();
|
|
9
|
-
await Spectra.intercept(
|
|
10
|
-
"api/posts",
|
|
11
|
-
"POST",
|
|
12
|
-
Fixture.apiData.mockPostResponse,
|
|
13
|
-
{ statusCode: 201 }
|
|
14
|
-
);
|
|
15
|
-
|
|
16
|
-
// Fill in form fields from Fixture
|
|
17
|
-
await MatchersPage.postTitleInput.type(Fixture.apiData.mockNewPost.title);
|
|
18
|
-
await MatchersPage.postBodyInput.type(Fixture.apiData.mockNewPost.body);
|
|
19
|
-
|
|
20
|
-
// Submit POST form
|
|
21
|
-
await MatchersPage.submitPostButton.click();
|
|
22
|
-
|
|
23
|
-
// Assert response elements and status
|
|
24
|
-
await MatchersPage.postStatusBadge.shouldHaveText("201 Created");
|
|
25
|
-
await MatchersPage.postSuccessBanner.shouldBeVisible();
|
|
26
|
-
await MatchersPage.postResponseJson.shouldContainText(Fixture.apiData.mockNewPost.title);
|
|
27
|
-
});
|
|
1
|
+
it("Mock and assert POST API requests using browser.intercept", async () => {
|
|
2
|
+
// Navigate to API POST section
|
|
3
|
+
await MatchersPage.open("api-post");
|
|
4
|
+
|
|
5
|
+
// Setup POST API interception with status 201 — the app posts to the host demo server's
|
|
6
|
+
// self-hosted endpoint (http://localhost:5200/api/posts), transparently routed through the
|
|
7
|
+
// worker's mock proxy via the device's global HTTP proxy set up at bootstrap.
|
|
8
|
+
Spectra.clearMocks();
|
|
9
|
+
await Spectra.intercept(
|
|
10
|
+
"api/posts",
|
|
11
|
+
"POST",
|
|
12
|
+
Fixture.apiData.mockPostResponse,
|
|
13
|
+
{ statusCode: 201 }
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
// Fill in form fields from Fixture
|
|
17
|
+
await MatchersPage.postTitleInput.type(Fixture.apiData.mockNewPost.title);
|
|
18
|
+
await MatchersPage.postBodyInput.type(Fixture.apiData.mockNewPost.body);
|
|
19
|
+
|
|
20
|
+
// Submit POST form
|
|
21
|
+
await MatchersPage.submitPostButton.click();
|
|
22
|
+
|
|
23
|
+
// Assert response elements and status
|
|
24
|
+
await MatchersPage.postStatusBadge.shouldHaveText("201 Created");
|
|
25
|
+
await MatchersPage.postSuccessBanner.shouldBeVisible();
|
|
26
|
+
await MatchersPage.postResponseJson.shouldContainText(Fixture.apiData.mockNewPost.title);
|
|
27
|
+
});
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
---
|
|
2
|
-
id: TC-0009-post-mocking
|
|
3
|
-
title: Mock and assert POST API requests using browser.intercept
|
|
4
|
-
priority: High
|
|
5
|
-
caseType: Positive
|
|
6
|
-
status: ready-for-automation
|
|
7
|
-
coverage:
|
|
8
|
-
web: automated
|
|
9
|
-
mobile: automated
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
# Mock and assert POST API requests using browser.intercept
|
|
13
|
-
|
|
14
|
-
## Test Steps
|
|
15
|
-
1. Open API POST section in matchers page
|
|
16
|
-
2. Intercept POST /api/posts with mock response returning 201 status
|
|
17
|
-
3. Fill post title and post body inputs from fixture
|
|
18
|
-
4. Click submit POST button
|
|
19
|
-
5. Assert status badge displays 201 Created and response JSON contains new title
|
|
1
|
+
---
|
|
2
|
+
id: TC-0009-post-mocking
|
|
3
|
+
title: Mock and assert POST API requests using browser.intercept
|
|
4
|
+
priority: High
|
|
5
|
+
caseType: Positive
|
|
6
|
+
status: ready-for-automation
|
|
7
|
+
coverage:
|
|
8
|
+
web: automated
|
|
9
|
+
mobile: automated
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Mock and assert POST API requests using browser.intercept
|
|
13
|
+
|
|
14
|
+
## Test Steps
|
|
15
|
+
1. Open API POST section in matchers page
|
|
16
|
+
2. Intercept POST /api/posts with mock response returning 201 status
|
|
17
|
+
3. Fill post title and post body inputs from fixture
|
|
18
|
+
4. Click submit POST button
|
|
19
|
+
5. Assert status badge displays 201 Created and response JSON contains new title
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
it("Mock and assert POST API requests using browser.intercept", async () => {
|
|
2
|
-
// Navigate to API POST section
|
|
3
|
-
await MatchersPage.open("api-post");
|
|
4
|
-
|
|
5
|
-
// Setup POST API interception with status 201 — the app posts to the demo server's own
|
|
6
|
-
// self-hosted endpoint (/api/posts), no external network involved.
|
|
7
|
-
Spectra.clearMocks();
|
|
8
|
-
await Spectra.intercept(
|
|
9
|
-
"api/posts",
|
|
10
|
-
"POST",
|
|
11
|
-
Fixture.apiData.mockPostResponse,
|
|
12
|
-
{ statusCode: 201 }
|
|
13
|
-
);
|
|
14
|
-
|
|
15
|
-
// Fill in form fields from Fixture
|
|
16
|
-
await MatchersPage.postTitleInput.type(Fixture.apiData.mockNewPost.title);
|
|
17
|
-
await MatchersPage.postBodyInput.type(Fixture.apiData.mockNewPost.body);
|
|
18
|
-
|
|
19
|
-
// Submit POST form
|
|
20
|
-
await MatchersPage.submitPostButton.click();
|
|
21
|
-
|
|
22
|
-
// Assert response elements and status
|
|
23
|
-
await MatchersPage.postStatusBadge.shouldHaveText("201 Created");
|
|
24
|
-
await MatchersPage.postSuccessBanner.shouldBeVisible();
|
|
25
|
-
await MatchersPage.postResponseJson.shouldContainText(Fixture.apiData.mockNewPost.title);
|
|
26
|
-
});
|
|
1
|
+
it("Mock and assert POST API requests using browser.intercept", async () => {
|
|
2
|
+
// Navigate to API POST section
|
|
3
|
+
await MatchersPage.open("api-post");
|
|
4
|
+
|
|
5
|
+
// Setup POST API interception with status 201 — the app posts to the demo server's own
|
|
6
|
+
// self-hosted endpoint (/api/posts), no external network involved.
|
|
7
|
+
Spectra.clearMocks();
|
|
8
|
+
await Spectra.intercept(
|
|
9
|
+
"api/posts",
|
|
10
|
+
"POST",
|
|
11
|
+
Fixture.apiData.mockPostResponse,
|
|
12
|
+
{ statusCode: 201 }
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
// Fill in form fields from Fixture
|
|
16
|
+
await MatchersPage.postTitleInput.type(Fixture.apiData.mockNewPost.title);
|
|
17
|
+
await MatchersPage.postBodyInput.type(Fixture.apiData.mockNewPost.body);
|
|
18
|
+
|
|
19
|
+
// Submit POST form
|
|
20
|
+
await MatchersPage.submitPostButton.click();
|
|
21
|
+
|
|
22
|
+
// Assert response elements and status
|
|
23
|
+
await MatchersPage.postStatusBadge.shouldHaveText("201 Created");
|
|
24
|
+
await MatchersPage.postSuccessBanner.shouldBeVisible();
|
|
25
|
+
await MatchersPage.postResponseJson.shouldContainText(Fixture.apiData.mockNewPost.title);
|
|
26
|
+
});
|
package/templates/default/specs/ApiInterception/TC-0012-direct-and-late-response/common.test.ts
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
it("Intercept a direct (immediate) response and a late (delayed) response using Fixture data", async () => {
|
|
2
|
-
await MatchersPage.open("api-fetch");
|
|
3
|
-
|
|
4
|
-
// The app fetches the self-hosted demo endpoint (/api/posts on web, the same path served by
|
|
5
|
-
// the demo server and reached through the device proxy on mobile) — no external network, so
|
|
6
|
-
// there's no upstream latency leaking into the "immediate" assertion below. On web, CDP's
|
|
7
|
-
// Fetch domain intercepts it; on Android, the device's global HTTP proxy routes it through the
|
|
8
|
-
// same worker-side mock engine. Neither platform needs the app, or this test, to know anything
|
|
9
|
-
// special about being under test.
|
|
10
|
-
Spectra.clearMocks();
|
|
11
|
-
|
|
12
|
-
// Direct (immediate) response — Fixture data returned with no artificial latency.
|
|
13
|
-
const mock = await Spectra.intercept("api/posts", "GET", Fixture.apiData.mockPosts);
|
|
14
|
-
await MatchersPage.fetchApiButton.click();
|
|
15
|
-
await MatchersPage.fetchStatusBadge.shouldHaveText("200 OK");
|
|
16
|
-
await MatchersPage.fetchedItems.shouldHaveLength(Fixture.apiData.mockPosts.length);
|
|
17
|
-
await MatchersPage.fetchedItems.first().shouldContainText(Fixture.apiData.mockPosts[0].title);
|
|
18
|
-
|
|
19
|
-
// Late (delayed) response — same mock rule, switched to hold the response back via `delayMs`.
|
|
20
|
-
// The loading indicator must still be visible right after the click, proving this is real
|
|
21
|
-
// network-level latency (the request genuinely stays pending) rather than a client-side-only
|
|
22
|
-
// spinner timer. The delay is set past the default assertion timeout on purpose, to demonstrate
|
|
23
|
-
// the per-assertion `{ timeoutMs }` override below — without it, these assertions would fail-fast
|
|
24
|
-
// before the delayed response ever arrives.
|
|
25
|
-
await mock.respondWith(Fixture.apiData.mockPosts, { delayMs: 2500 });
|
|
26
|
-
await MatchersPage.fetchApiButton.click();
|
|
27
|
-
await MatchersPage.fetchLoadingIndicator.shouldBeVisible();
|
|
28
|
-
await MatchersPage.fetchStatusBadge.shouldHaveText("200 OK", { timeoutMs: 3500 });
|
|
29
|
-
await MatchersPage.fetchedItems.shouldHaveLength(Fixture.apiData.mockPosts.length, { timeoutMs: 3500 });
|
|
30
|
-
});
|
|
1
|
+
it("Intercept a direct (immediate) response and a late (delayed) response using Fixture data", async () => {
|
|
2
|
+
await MatchersPage.open("api-fetch");
|
|
3
|
+
|
|
4
|
+
// The app fetches the self-hosted demo endpoint (/api/posts on web, the same path served by
|
|
5
|
+
// the demo server and reached through the device proxy on mobile) — no external network, so
|
|
6
|
+
// there's no upstream latency leaking into the "immediate" assertion below. On web, CDP's
|
|
7
|
+
// Fetch domain intercepts it; on Android, the device's global HTTP proxy routes it through the
|
|
8
|
+
// same worker-side mock engine. Neither platform needs the app, or this test, to know anything
|
|
9
|
+
// special about being under test.
|
|
10
|
+
Spectra.clearMocks();
|
|
11
|
+
|
|
12
|
+
// Direct (immediate) response — Fixture data returned with no artificial latency.
|
|
13
|
+
const mock = await Spectra.intercept("api/posts", "GET", Fixture.apiData.mockPosts);
|
|
14
|
+
await MatchersPage.fetchApiButton.click();
|
|
15
|
+
await MatchersPage.fetchStatusBadge.shouldHaveText("200 OK");
|
|
16
|
+
await MatchersPage.fetchedItems.shouldHaveLength(Fixture.apiData.mockPosts.length);
|
|
17
|
+
await MatchersPage.fetchedItems.first().shouldContainText(Fixture.apiData.mockPosts[0].title);
|
|
18
|
+
|
|
19
|
+
// Late (delayed) response — same mock rule, switched to hold the response back via `delayMs`.
|
|
20
|
+
// The loading indicator must still be visible right after the click, proving this is real
|
|
21
|
+
// network-level latency (the request genuinely stays pending) rather than a client-side-only
|
|
22
|
+
// spinner timer. The delay is set past the default assertion timeout on purpose, to demonstrate
|
|
23
|
+
// the per-assertion `{ timeoutMs }` override below — without it, these assertions would fail-fast
|
|
24
|
+
// before the delayed response ever arrives.
|
|
25
|
+
await mock.respondWith(Fixture.apiData.mockPosts, { delayMs: 2500 });
|
|
26
|
+
await MatchersPage.fetchApiButton.click();
|
|
27
|
+
await MatchersPage.fetchLoadingIndicator.shouldBeVisible();
|
|
28
|
+
await MatchersPage.fetchStatusBadge.shouldHaveText("200 OK", { timeoutMs: 3500 });
|
|
29
|
+
await MatchersPage.fetchedItems.shouldHaveLength(Fixture.apiData.mockPosts.length, { timeoutMs: 3500 });
|
|
30
|
+
});
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
---
|
|
2
|
-
id: TC-0012-direct-and-late-response
|
|
3
|
-
title: Intercept a direct (immediate) response and a late (delayed) response using Fixture data
|
|
4
|
-
priority: High
|
|
5
|
-
caseType: Positive
|
|
6
|
-
status: ready-for-automation
|
|
7
|
-
coverage:
|
|
8
|
-
web: automated
|
|
9
|
-
mobile: automated
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
# Intercept a direct (immediate) response and a late (delayed) response using Fixture data
|
|
13
|
-
|
|
14
|
-
## Test Steps
|
|
15
|
-
1. Open the API fetch section in the matchers page
|
|
16
|
-
2. Intercept GET /api/posts with mock posts fixture data
|
|
17
|
-
3. Click the fetch API button
|
|
18
|
-
4. Assert the status badge displays 200 OK and the immediate fixture items render
|
|
19
|
-
5. Update the mock response with an artificial 50ms delay
|
|
20
|
-
6. Click the fetch API button
|
|
21
|
-
7. Assert the loading indicator is visible while the request is held
|
|
22
|
-
8. Assert the status badge displays 200 OK and the delayed fixture items render
|
|
1
|
+
---
|
|
2
|
+
id: TC-0012-direct-and-late-response
|
|
3
|
+
title: Intercept a direct (immediate) response and a late (delayed) response using Fixture data
|
|
4
|
+
priority: High
|
|
5
|
+
caseType: Positive
|
|
6
|
+
status: ready-for-automation
|
|
7
|
+
coverage:
|
|
8
|
+
web: automated
|
|
9
|
+
mobile: automated
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Intercept a direct (immediate) response and a late (delayed) response using Fixture data
|
|
13
|
+
|
|
14
|
+
## Test Steps
|
|
15
|
+
1. Open the API fetch section in the matchers page
|
|
16
|
+
2. Intercept GET /api/posts with mock posts fixture data
|
|
17
|
+
3. Click the fetch API button
|
|
18
|
+
4. Assert the status badge displays 200 OK and the immediate fixture items render
|
|
19
|
+
5. Update the mock response with an artificial 50ms delay
|
|
20
|
+
6. Click the fetch API button
|
|
21
|
+
7. Assert the loading indicator is visible while the request is held
|
|
22
|
+
8. Assert the status badge displays 200 OK and the delayed fixture items render
|
package/templates/default/specs/ApiInterception/TC-0013-real-network-call-recorded/common.test.ts
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
it("Make a genuine (non-intercepted) network call and verify it is recorded", async () => {
|
|
2
|
-
await MatchersPage.open("api-fetch");
|
|
3
|
-
|
|
4
|
-
// Deliberately no Spectra.intercept() call — this is a genuine request that actually leaves
|
|
5
|
-
// the app and hits a real server, not a mock. It targets the demo server's own self-hosted
|
|
6
|
-
// endpoint (started with `--demo`) instead of an external public API, so it's deterministic
|
|
7
|
-
// and fast everywhere. On web the browser reaches localhost directly; on Android it's
|
|
8
|
-
// transparently routed through the device's global HTTP proxy with no matching mock rule, so
|
|
9
|
-
// the worker's proxy just forwards it for real. Clear any mock a previous test in this suite
|
|
10
|
-
// left registered (e.g. against /api/posts) so it can't accidentally catch this request too —
|
|
11
|
-
// this test uses a different resource (/api/todos/1) specifically to avoid that collision,
|
|
12
|
-
// plus a cache-busting query param so a repeat run doesn't get a 304 Not Modified from the
|
|
13
|
-
// device/browser's own HTTP cache.
|
|
14
|
-
Spectra.clearMocks();
|
|
15
|
-
const cacheBuster = Date.now();
|
|
16
|
-
await MatchersPage.fetchCustomUrlInput.type(`http://localhost:5200/api/todos/1?cb=${cacheBuster}`);
|
|
17
|
-
await MatchersPage.fetchApiButton.click();
|
|
18
|
-
await MatchersPage.fetchStatusBadge.shouldHaveText("200 OK");
|
|
19
|
-
|
|
20
|
-
const entry = Spectra.browser.recordedNetwork.find((e) => e.url.includes(`todos/1?cb=${cacheBuster}`));
|
|
21
|
-
if (!entry) {
|
|
22
|
-
throw new Error("Expected a recorded network entry for the real demo-server call, found none");
|
|
23
|
-
}
|
|
24
|
-
if (entry.status !== 200) {
|
|
25
|
-
throw new Error(`Expected recorded entry status 200, got ${entry.status}`);
|
|
26
|
-
}
|
|
27
|
-
});
|
|
1
|
+
it("Make a genuine (non-intercepted) network call and verify it is recorded", async () => {
|
|
2
|
+
await MatchersPage.open("api-fetch");
|
|
3
|
+
|
|
4
|
+
// Deliberately no Spectra.intercept() call — this is a genuine request that actually leaves
|
|
5
|
+
// the app and hits a real server, not a mock. It targets the demo server's own self-hosted
|
|
6
|
+
// endpoint (started with `--demo`) instead of an external public API, so it's deterministic
|
|
7
|
+
// and fast everywhere. On web the browser reaches localhost directly; on Android it's
|
|
8
|
+
// transparently routed through the device's global HTTP proxy with no matching mock rule, so
|
|
9
|
+
// the worker's proxy just forwards it for real. Clear any mock a previous test in this suite
|
|
10
|
+
// left registered (e.g. against /api/posts) so it can't accidentally catch this request too —
|
|
11
|
+
// this test uses a different resource (/api/todos/1) specifically to avoid that collision,
|
|
12
|
+
// plus a cache-busting query param so a repeat run doesn't get a 304 Not Modified from the
|
|
13
|
+
// device/browser's own HTTP cache.
|
|
14
|
+
Spectra.clearMocks();
|
|
15
|
+
const cacheBuster = Date.now();
|
|
16
|
+
await MatchersPage.fetchCustomUrlInput.type(`http://localhost:5200/api/todos/1?cb=${cacheBuster}`);
|
|
17
|
+
await MatchersPage.fetchApiButton.click();
|
|
18
|
+
await MatchersPage.fetchStatusBadge.shouldHaveText("200 OK");
|
|
19
|
+
|
|
20
|
+
const entry = Spectra.browser.recordedNetwork.find((e) => e.url.includes(`todos/1?cb=${cacheBuster}`));
|
|
21
|
+
if (!entry) {
|
|
22
|
+
throw new Error("Expected a recorded network entry for the real demo-server call, found none");
|
|
23
|
+
}
|
|
24
|
+
if (entry.status !== 200) {
|
|
25
|
+
throw new Error(`Expected recorded entry status 200, got ${entry.status}`);
|
|
26
|
+
}
|
|
27
|
+
});
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
---
|
|
2
|
-
id: TC-0013-real-network-call-recorded
|
|
3
|
-
title: Make a genuine (non-intercepted) network call and verify it is recorded
|
|
4
|
-
priority: High
|
|
5
|
-
caseType: Positive
|
|
6
|
-
status: ready-for-automation
|
|
7
|
-
coverage:
|
|
8
|
-
web: automated
|
|
9
|
-
mobile: automated
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
# Make a genuine (non-intercepted) network call and verify it is recorded
|
|
13
|
-
|
|
14
|
-
## Test Steps
|
|
15
|
-
1. Open the API fetch section in the matchers page
|
|
16
|
-
2. Clear any active mocks left by a previous test
|
|
17
|
-
3. Enter a real (non-intercepted) demo-server todo endpoint URL with a cache-busting query param
|
|
18
|
-
4. Click the fetch API button
|
|
19
|
-
5. Assert the status badge displays 200 OK
|
|
20
|
-
6. Assert the network report records the genuine call with status 200
|
|
1
|
+
---
|
|
2
|
+
id: TC-0013-real-network-call-recorded
|
|
3
|
+
title: Make a genuine (non-intercepted) network call and verify it is recorded
|
|
4
|
+
priority: High
|
|
5
|
+
caseType: Positive
|
|
6
|
+
status: ready-for-automation
|
|
7
|
+
coverage:
|
|
8
|
+
web: automated
|
|
9
|
+
mobile: automated
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Make a genuine (non-intercepted) network call and verify it is recorded
|
|
13
|
+
|
|
14
|
+
## Test Steps
|
|
15
|
+
1. Open the API fetch section in the matchers page
|
|
16
|
+
2. Clear any active mocks left by a previous test
|
|
17
|
+
3. Enter a real (non-intercepted) demo-server todo endpoint URL with a cache-busting query param
|
|
18
|
+
4. Click the fetch API button
|
|
19
|
+
5. Assert the status badge displays 200 OK
|
|
20
|
+
6. Assert the network report records the genuine call with status 200
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
---
|
|
2
|
-
id: TC-0015-mock-server-sent-events
|
|
3
|
-
title: Mock a Server-Sent Events (EventSource) stream via the existing network-intercept engine
|
|
4
|
-
priority: Medium
|
|
5
|
-
caseType: Positive
|
|
6
|
-
status: ready-for-automation
|
|
7
|
-
coverage:
|
|
8
|
-
web: automated
|
|
9
|
-
mobile: unsupported
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
# Mock a Server-Sent Events (EventSource) stream via the existing network-intercept engine
|
|
13
|
-
|
|
14
|
-
Mobile coverage is `unsupported`: React Native has no built-in `EventSource` — a real project
|
|
15
|
-
targeting mobile would add a userland SSE client library, at which point whether/how it's
|
|
16
|
-
mockable depends entirely on that library's own networking implementation, not something
|
|
17
|
-
TestSpectra's driver can generalize over.
|
|
18
|
-
|
|
19
|
-
## Test Steps
|
|
20
|
-
1. Open the SSE matcher section
|
|
21
|
-
2. Intercept GET /api/sse-feed with a text/event-stream mock body
|
|
22
|
-
3. Click the connect button
|
|
23
|
-
4. Assert two SSE messages render
|
|
24
|
-
5. Assert the first message contains "hello from mock SSE" and the last contains "second event"
|
|
1
|
+
---
|
|
2
|
+
id: TC-0015-mock-server-sent-events
|
|
3
|
+
title: Mock a Server-Sent Events (EventSource) stream via the existing network-intercept engine
|
|
4
|
+
priority: Medium
|
|
5
|
+
caseType: Positive
|
|
6
|
+
status: ready-for-automation
|
|
7
|
+
coverage:
|
|
8
|
+
web: automated
|
|
9
|
+
mobile: unsupported
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Mock a Server-Sent Events (EventSource) stream via the existing network-intercept engine
|
|
13
|
+
|
|
14
|
+
Mobile coverage is `unsupported`: React Native has no built-in `EventSource` — a real project
|
|
15
|
+
targeting mobile would add a userland SSE client library, at which point whether/how it's
|
|
16
|
+
mockable depends entirely on that library's own networking implementation, not something
|
|
17
|
+
TestSpectra's driver can generalize over.
|
|
18
|
+
|
|
19
|
+
## Test Steps
|
|
20
|
+
1. Open the SSE matcher section
|
|
21
|
+
2. Intercept GET /api/sse-feed with a text/event-stream mock body
|
|
22
|
+
3. Click the connect button
|
|
23
|
+
4. Assert two SSE messages render
|
|
24
|
+
5. Assert the first message contains "hello from mock SSE" and the last contains "second event"
|