fix(reference): update terminology from Response to ResponseView for consistency in documentation

This commit is contained in:
Bob Qiu authored and GitHub committed 2026-11-02 16:34:00 +08:00
1 parent 685c9cf256
commit 514b1ba817
1 file changed
+23 -20
+23 -20
View File
@@ -25,7 +25,7 @@ Every test injects only the `user` fixture (`async ({ user }) => {...}`) — nev
| Folder (a Collection sub-container — creation + its own Auth/Headers/Scripts/Environment/Docs tab) | `folderFlow` | `flows/folder.flow.ts` | `pages/folder.page.ts` (extends `TabPanelPage`; composes `AuthTabComponent` as `.auth` and `ScriptTabComponent` as `.scripts`) | `models/folder.ts` |
| Import | `importFlow` | `flows/import.flow.ts` | `pages/import.page.ts` | `models/curl-command.ts` (other sources import raw string/file path) |
| Export | `exportFlow` | `flows/export.flow.ts` | `pages/export.page.ts` | none — takes `Collection`/`Project` + `ExportFormat` (`enums/export-format.ts`), or `ApiSpecExportFormat` (`enums/api-spec-export-format.ts`) for the OpenAPI-spec-only export |
| Response (read-only, returned by `send`/`connect`) | — (via `user.pageManager.responsePage`) | — | `pages/response.page.ts` | `models/response.ts` |
| ResponseView (read-only, returned by `send`/`connect`) | — (via `user.pageManager.responsePage`) | — | `pages/response.page.ts` | `models/response.ts` |
| Preferences (app-wide Settings, not a domain entity) | `preferencesFlow` | `flows/preferences.flow.ts` | `pages/preferences.page.ts` | `models/settings.ts` (simple fields only; complex ones out of scope — `dataFolders`/`pluginSandboxEnabled`/`showLegacyUnitTests`/`filterResponsesByEnv`/`timeout`/`proxyEnabled`/`httpProxy`/`httpsProxy`/`noProxy`/`sidebarFocusForCollections` (defaults `false` in the `user` fixture, see below) all wired into `set()`) |
| AI Settings — "url" backend (Preferences → AI Settings tab, `tests/preferences/ai-backend-settings.spec.ts`) | `preferencesFlow` (`set({ aiUrlBackend })` — configured/deactivated entirely through the real UI form, no bridge call) | `flows/preferences.flow.ts` | `pages/preferences.page.ts` | `models/settings.ts`'s `AiUrlBackendSettings` (synthetic `Settings` field, not a real `AppSettings` member) |
| Cloud (Vault) Credentials (Preferences → Credentials tab's "Create Cloud Credential" — AWS/GCP/HashiCorp auth for the `vault` template tag, `tests/template-tag/external-vault-credentials.spec.ts`) | `preferencesFlow` (`set({ cloudCredentials })` — no separate CloudCredentialFlow/Page) | `flows/preferences.flow.ts` | `pages/preferences.page.ts` | `models/settings.ts`'s `CloudCredential` (reuses `insomnia-data`'s own per-provider `credentials` shapes, narrowed to the one auth mode each has a create method for) |
@@ -357,7 +357,7 @@ These five share nearly the same shape. `create()`/`send()` are consistent; only
```ts
// HttpRequestFlow
create(parent: Collection | Folder, request: HttpRequest): Promise<HttpRequest>
send(request: HttpRequest): Promise<Response>
send(request: HttpRequest): Promise<ResponseView>
get(item: string | { name: string; id?: string }, parent?: Collection): Promise<HttpRequest | undefined>
// Confirmed live: a freshly created request already has implicit default headers (Accept, Host, User-Agent)
// showing up in httpRequestPage.getHeaders() — it's NOT an empty array like a fresh request's params are.
@@ -398,7 +398,7 @@ get(item: string | { name: string; id?: string }, parent?: Collection): Promise<
// GraphQLRequestFlow — identical shape
create(parent: Collection | Folder, request: GraphQLRequest): Promise<GraphQLRequest>
send(request: GraphQLRequest): Promise<Response>
send(request: GraphQLRequest): Promise<ResponseView>
get(item, parent?: Collection): Promise<GraphQLRequest | undefined>
// create() auto-clicks "Prettify GraphQL" right after setBody() (whenever request.body is given), so the query persisted/read back is already reformatted — a request created with a one-line query comes back multi-line. GraphQLRequestPage.prettify() is the underlying Page method (switches to the content-type tab, clicks the plain-text "Prettify GraphQL" button — no aria-label/data-testid on it) if you need to call it directly (e.g. re-prettifying after a later setBody()).
@@ -413,32 +413,33 @@ streamMessage(request: GrpcRequest, body: string): Promise<void> // s
commit(request: GrpcRequest): Promise<GrpcResponse> // closes the client half ("Commit"), then reads back status + message(s)
cancel(request: GrpcRequest): Promise<GrpcResponse> // cancels an in-flight unary/server-streaming call, or an open client/bidi stream
// A gRPC business error (server calls back with a non-OK status, e.g. INVALID_ARGUMENT) surfaces as an error dialog, not a GrpcResponse — `send()`/`commit()` reject; assert with `await expect(grpcRequestFlow.send(request)).rejects.toThrow(/INVALID_ARGUMENT.../)`. (Real app quirk: `isGrpcConnectionError()`'s `Array.find(...) !== null` check is always true since `.find()` returns `undefined` on no match, so every gRPC business error pops the same ErrorModal a connection error would.)
// pageManager.responsePage.getGrpcMessage(index = 0): Promise<unknown> reads one streamed response by its "Response N" tab (JSON-parsed, raw text when not JSON, undefined when the tab doesn't exist) — no Flow wrapper; send() already returns the messages.
// fetchServerReflection() is @throwOnDialog-decorated — against an unreachable server it rejects with the error dialog's text, same pattern as send()/commit(): `await expect(pageManager.grpcRequestPage.fetchServerReflection()).rejects.toThrow(/Uh Oh!.*UNAVAILABLE/s)`.
// GrpcRequestPage's getMethodType()/isRunning()/openProtoFile()/useRequestStubs() were removed as dead code (no test ever called them) — re-add a public getter/action there if a future test needs to read the method-type tab, check the running state, or drive proto-file import/stub-generation directly.
// misc/grpc-server.js's lotsOfReplies (server-streaming) reads an optional "x-reply-delay-ms" metadata header to control the delay between writes (default 50ms) — set it higher (e.g. 1000) in a request's headers to widen the window for a reliable mid-stream cancel test.
// WebSocketRequestFlow
create(parent: Collection | Folder, request: WebSocketRequest): Promise<WebSocketRequest>
send(request: WebSocketRequest): Promise<Response> // opens the connection
sendMessage(request: WebSocketRequest, body: WebSocketRequestBody, callback = () => {}, timeout = DEFAULT_TIMEOUT): Promise<Response>
send(request: WebSocketRequest, options?: { expectConnected?: boolean }): Promise<ResponseView> // opens the connection; `expectConnected: false` for a connection that is expected to be refused/fail right away (unreachable server/proxy) — returns right after the click instead of waiting for the button to flip to "Disconnect"
sendMessage(request: WebSocketRequest, body: WebSocketRequestBody, callback = () => {}, timeout = DEFAULT_TIMEOUT): Promise<ResponseView>
// sends one message over an already-open connection; call repeatedly with different bodies to send several messages of different content types (body.contentType accepts any ContentType value — see tests/web-socket-request/send-multiple-message-types.spec.ts for an example using two of them)
disconnect(request: WebSocketRequest, callback: () => Promise<void> | void = () => {}, timeout = DEFAULT_TIMEOUT): Promise<Response>
disconnect(request: WebSocketRequest, callback: () => Promise<void> | void = () => {}, timeout = DEFAULT_TIMEOUT): Promise<ResponseView>
get(item, parent?: Collection): Promise<WebSocketRequest | undefined>
// SocketIORequestFlow
create(parent: Collection | Folder, request: SocketIORequest): Promise<SocketIORequest>
connect(request: SocketIORequest): Promise<void>
sendMessage(request: SocketIORequest): Promise<Response>
disconnect(request: SocketIORequest, callback = () => {}, timeout = DEFAULT_TIMEOUT): Promise<Response>
sendMessage(request: SocketIORequest): Promise<ResponseView>
disconnect(request: SocketIORequest, callback = () => {}, timeout = DEFAULT_TIMEOUT): Promise<ResponseView>
get(item, parent?: Collection): Promise<SocketIORequest | undefined>
// EventStreamRequestFlow
create(parent: Collection | Folder, request: EventStreamRequest): Promise<EventStreamRequest>
send(request: EventStreamRequest): Promise<Response> // opens the SSE connection
send(request: EventStreamRequest, options?: { expectConnected?: boolean }): Promise<ResponseView> // opens the SSE connection; same `expectConnected: false` option as WebSocketRequestFlow.send()
get(item, parent?: Collection): Promise<EventStreamRequest | undefined>
// No Flow-level disconnect() — the one that used to be here was removed as dead code (no test called it).
// To close the connection, call the inherited pageManager.eventStreamRequestPage.disconnect(callback?, timeout?): Promise<void>
// directly (see the generic RequestPage helpers below), then pageManager.responsePage.get() if you need the Response back.
// directly (see the generic RequestPage helpers below), then pageManager.responsePage.get() if you need the ResponseView back.
```
Every `get()` above takes an optional second `parent?: Collection` (the Http/GraphQL/gRPC/WebSocket versions ignore it and always search the project tree).
@@ -532,7 +533,7 @@ Both `AuthTabComponent` and its sibling `ScriptTabComponent` (see `folderFlow`/s
Real examples: `tests/http-request/oauth1-authentication.spec.ts` (OAuth 1.0 — signed `Authorization: OAuth ...` header), `tests/http-request/oauth2-authorization-code.spec.ts` / `oauth2-authorization-code-pkce.spec.ts` (S256 + plain) / `oauth2-implicit.spec.ts` (ID Token / ID+Access Token) / `oauth2-client-credentials.spec.ts` / `oauth2-password.spec.ts` / `oauth2-token-refresh-clear.spec.ts` (refresh + clear) / `oauth2-folder-inherited-auth.spec.ts`.
### `Response` (returned by `send`/`disconnect`/`callTool`)
### `ResponseView` (`models/response.ts`) (returned by `send`/`disconnect`/`callTool`)
```ts
{ statusCode?: number; statusMessage?: string; elapsedTime?: number; bytesContent?: number;
@@ -544,7 +545,7 @@ Real examples: `tests/http-request/oauth1-authentication.spec.ts` (OAuth 1.0 —
`events` is what SSE/WebSocket/Socket.IO/MCP streamed messages land in — read via `pageManager.responsePage.getEvents()` or `await response.events?.()`.
`tests` is what `insomnia.test()`/`insomnia.expect()` calls in a pre-request or after-response script populate — read via `await response.tests?.()` (already included in every `send()`'s returned `Response`; `ResponsePage.getTestResults()` is a private helper behind the lazy `tests` function, not something a spec calls directly). `status` is the literal rendered badge text ("PASS"/"FAIL"/possibly "SKIP" — the tab bar also has a "Skipped" filter, unconfirmed live); `error` is only set on a FAIL row, containing the raw `" | error: ... | ACTUAL: ... | EXPECTED: ..."` text. **Gotcha confirmed live**: the test-name `<span>` has a CSS `capitalize` class, so `.innerText()` returns the visually-transformed text ("Transient Var" for a test named `'transient var'`) — `getTestResults()` uses `.textContent()` instead to get the real, untransformed name back. Rows are not returned in script-declaration order — the app groups/sorts them (FAIL rows before PASS rows, observed consistently), so assert with `expect.arrayContaining(...)`, not an exact-order array. Real example: `tests/http-request/after-response-script-test-results.spec.ts`.
`tests` is what `insomnia.test()`/`insomnia.expect()` calls in a pre-request or after-response script populate — read via `await response.tests?.()` (already included in every `send()`'s returned `ResponseView`; `ResponsePage.getTestResults()` is a private helper behind the lazy `tests` function, not something a spec calls directly). `status` is the literal rendered badge text ("PASS"/"FAIL"/possibly "SKIP" — the tab bar also has a "Skipped" filter, unconfirmed live); `error` is only set on a FAIL row, containing the raw `" | error: ... | ACTUAL: ... | EXPECTED: ..."` text. **Gotcha confirmed live**: the test-name `<span>` has a CSS `capitalize` class, so `.innerText()` returns the visually-transformed text ("Transient Var" for a test named `'transient var'`) — `getTestResults()` uses `.textContent()` instead to get the real, untransformed name back. Rows are not returned in script-declaration order — the app groups/sorts them (FAIL rows before PASS rows, observed consistently), so assert with `expect.arrayContaining(...)`, not an exact-order array. Real example: `tests/http-request/after-response-script-test-results.spec.ts`.
**Known gap, not yet resolved**: `insomnia.environment.set()`/`.baseEnvironment.set()` calls made inside an **after-response** script (as opposed to pre-request, where they're already proven reliable — see `pre-request-script-environment-variables.spec.ts`) were not observed to persist when read back afterward via `environmentFlow.get()`, even after re-navigating to the environment editor and waiting a couple of seconds. Root cause unconfirmed (may be a timing/debounce issue specific to after-response scripts, or the read-back path itself) — don't rely on after-response environment writes being visible to a subsequent `environmentFlow.get()`/`.link()` until this is investigated further. `insomnia.globals`/`.baseGlobals` were also probed and appear to write into the same sub/base environment `insomnia.environment`/`.baseEnvironment` already point at (not a separate scope) — but this was only observed once, alongside the same persistence gap above, so treat it as unconfirmed too.
@@ -553,10 +554,10 @@ Real examples: `tests/http-request/oauth1-authentication.spec.ts` (OAuth 1.0 —
```ts
create(parent: Project, client: McpClient): Promise<McpClient> // McpClient = new McpClient(name, url = "", authentication?: RequestAuthentication) — applied after the URL is set
get(item: string | { name: string; id?: string }): Promise<McpClient | undefined>
connect(client: McpClient): Promise<void>
connect(client: McpClient, options?: { expectConnected?: boolean }): Promise<void> // same `expectConnected: false` option as WebSocketRequestFlow.send()
disconnect(client: McpClient): Promise<void> // clicks Disconnect (McpClientPage.disconnect force-clicks it: the URL form is aria-disabled while connected, so a normal click times out as "not enabled")
getTools(client: McpClient): Promise<string[]>
callTool(client: McpClient, tool: string, args: Record<string, string>, callback: () => Promise<void> | void = () => {}, timeout = DEFAULT_TIMEOUT): Promise<Response>
callTool(client: McpClient, tool: string, args: Record<string, string>, callback: () => Promise<void> | void = () => {}, timeout = DEFAULT_TIMEOUT): Promise<ResponseView>
```
Real example with the live mock MCP server: `tests/mcp-client/happy-path.spec.ts`.
@@ -578,7 +579,7 @@ deleteRoute(route: MockRoute): Promise<void>
getRoutePaths(server: MockServer): Promise<string[]> // sidebar route names (the sidebar shows abbreviated methods, so only paths are read)
getRoute(route: MockRoute): Promise<{ method: string; path: string }> // read from the open route's URL bar (full method name)
getUrl(route: MockRoute): Promise<string> // from the "Show URL" dialog: `${server url}/bin/mock_<id>${path}`
test(route: MockRoute): Promise<Response> // clicks Test; the mock response pane shares `data-testid="response-pane"`, so ResponsePage's Response model works
test(route: MockRoute): Promise<ResponseView> // clicks Test; the mock response pane shares `data-testid="response-pane"`, so ResponsePage's ResponseView model works
getHistory(route: MockRoute): Promise<MockRouteHistoryEntry[]> // History tab rows, `{ method, url }`, newest first (url is the full URL)
createRouteFromResponse(server: MockServer, path?: string): Promise<MockRoute> // call right after httpRequestFlow.send(): "→ Mock" tab, "Create"
overwriteRouteFromResponse(server: MockServer, route: MockRoute): Promise<void> // same tab, picks the route, "Overwrite"
@@ -798,6 +799,8 @@ await preferencesFlow.set({ validateSSL: false });
Non-obvious UI fact baked into `PreferencesPage`: the "Validate certificates" checkbox is a custom-styled control whose native `input[type="checkbox"]` ignores direct clicks/`.check()` — the wrapping `<label>` is the actual clickable target (same quirk for `proxyEnabled`/`filterResponsesByEnv`). Also, the Preferences dialog's own ARIA role name is a generic `"Modal"` shared by every modal in the app, so `PreferencesPage` scopes it by visible heading text (`"Insomnia Preferences"`) instead of by role name. Real example: `tests/cookie/secure-cookie-not-sent-over-http.spec.ts`, `tests/cookie/http-only-cookie-always-sent.spec.ts`.
`hideSecretValuesInPreviewAndConsole` (General tab; on by default, masks vault/secret values as `••••••` in the template-tag Live Preview and Console — toggling it pops an informational alert that `PreferencesPage` dismisses itself) is also a plain boolean field: `preferencesFlow.set({ hideSecretValuesInPreviewAndConsole: false })`.
`timeout` (General tab, "Request timeout (ms)") is also the timeout that governs pre-request/after-response script execution — see `AppFlow`'s hidden-window notes below. `proxyEnabled`/`httpProxy`/`httpsProxy`/`noProxy` (any one of the four opens the Proxy tab) route outgoing requests through a configured proxy; real example: `tests/preferences/proxy-settings.spec.ts` (asserts the timeline console shows `"Trying <proxy-host>"` via `responsePage.getConsole()` even though nothing is listening at that address). `filterResponsesByEnv` real example: `tests/preferences/filter-responses-by-environment.spec.ts`.
### AI Settings — "url" backend (Preferences → AI Settings tab, `tests/preferences/ai-backend-settings.spec.ts`)
@@ -909,7 +912,7 @@ Use `vaultKey` (+ matching `vaultSalt`) to pre-unlock the vault for a scenario t
### Konnect sidebar sync (`tests/konnect/`)
No Flow — call `user.pageManager.konnectPage` directly, same pattern as `commandPalettePage`. Configuring a PAT hits the real Konnect API surface at `KONNECT_API_URL` (`misc/launch.ts` points this at `MOCK_API_SERVER`), whose `GET /v2/control-planes` route `misc/mock-api.js` already stubs to return `{ data: [] }` — any non-empty string is accepted as a "valid" PAT with no further mock-server work needed.
No Flow — call `user.pageManager.konnectPage` directly, same pattern as `commandPalettePage`. Read-only presence checks (poll them with `expect.poll`): `isControlPlaneVisible(name): Promise<boolean>` (synced control-plane project node in the sidebar tree) and `isServiceVisible(name): Promise<boolean>` (synced gateway-service collection node); `clickSync()` clicks the sidebar's "Sync Konnect" button to trigger another sync. Configuring a PAT hits the real Konnect API surface at `KONNECT_API_URL` (`misc/launch.ts` points this at `MOCK_API_SERVER`), whose `GET /v2/control-planes` route `misc/mock-api.js` already stubs to return `{ data: [] }` — any non-empty string is accepted as a "valid" PAT with no further mock-server work needed.
**There is no separate Konnect "tab" any more.** The sidebar is a single container that renders either a pre-configuration intro card or the normal project tree depending on whether a PAT is already saved — a spec first switches into the Konnect organization itself via `workspacePage.switchOrganization("Control Planes")` (opens the header's "Organizations" switcher and picks the option by name), then drives `konnectPage` against whatever the sidebar shows next:
@@ -1236,7 +1239,7 @@ mergeBranchResolvingConflicts(branch: string, version: "Current" | "Incoming"):
deleteBranch(branch: string, switchToBranch = "master"): Promise<void> // checks out switchToBranch first (can't delete the checked-out branch), then deletes `branch`
```
**Direct `gitSyncPage` calls with no Flow wrapper** (the real specs use these — destructure `gitSyncPage` from `user.pageManager`): `openCommitDialog()`/`closeCommitDialog()`/`isCommitDialogOpen()`, `commitStaged(message?)` (fills the Message field, **clearing it when omitted** since it keeps its text between attempts), `getStagedChanges()`/`getUnstagedChanges()`, `stageChange(fileName)`/`unstageChange(fileName)`, `openHistory()`/`getLatestCommit()`/`closeHistory()`, `getCurrentBranch()`. The "Stage All Changes" prompt — shown when Commit is clicked with **nothing staged** — has `getStageAllPromptText()` (waits for it; text contains "There are no staged changes to commit"), `cancelStageAllPrompt()` (leaves the modal open, nothing committed), and `confirmStageAllPrompt()` ("Yes": stages everything + commits, waits for the modal to close). `isCommitDisabled()` was removed — the Commit button is no longer disabled with nothing staged, it opens this prompt instead. `openCommitDialog()` now also waits for at least one change row, so reading staged/unstaged right after it can't see a still-empty list.
**Direct `gitSyncPage` calls with no Flow wrapper** (the real specs use these — destructure `gitSyncPage` from `user.pageManager`): `openCommitDialog()`/`closeCommitDialog()`/`isCommitDialogOpen()`, `commitStaged(message?)` (fills the Message field, **clearing it when omitted** since it keeps its text between attempts), `getStagedChanges()`/`getUnstagedChanges()`, `stageChange(fileName)`/`unstageChange(fileName)`, `unstageAllChanges()` ("Unstage all changes" button; waits for the staged list to empty), `discardChange(fileName)` (hover the unstaged row, Discard change, confirm; waits for the row to leave the list), `openHistory()`/`getLatestCommit()`/`closeHistory()`, `getCurrentBranch()`. The "Stage All Changes" prompt — shown when Commit is clicked with **nothing staged** — has `getStageAllPromptText()` (waits for it; text contains "There are no staged changes to commit"), `cancelStageAllPrompt()` (leaves the modal open, nothing committed), and `confirmStageAllPrompt()` ("Yes": stages everything + commits, waits for the modal to close). `isCommitDisabled()` was removed — the Commit button is no longer disabled with nothing staged, it opens this prompt instead. `openCommitDialog()` now also waits for at least one change row, so reading staged/unstaged right after it can't see a still-empty list.
`Commit` (`models/commit.ts`): `{ message: string; id?: string }` — positional constructor (`new Commit(message)`), `id` populated after `commit()`/`commitAndPush()` read it back from the History modal's row `data-key` (the real git OID).
@@ -1471,7 +1474,7 @@ A `"local"` delete's workspace reliably reappears as an **unsynced dashboard car
**A brand-new collection's own local commit sequence runs synchronously inside its creation, before the "New Collection" dialog closes** — confirmed live: `workspaceFlow.createCollection()` doesn't return until `switchAndCreateBackendProjectIfNotExist`/`status`/`stage`/`takeSnapshot` finish, well under 1 second, all inside one blocking, focus-trapped modal that no other click or IPC event can interrupt while it's open. So an INS-2026-style "unrelated UI action interleaved with a fresh collection's own creation" can't be driven through the UI at all on a stock build — and there's no test-only way to widen that window without a hook in the app's own source, which is out of scope here (see `SKILL.md`'s Scope Constraint).
**`tests/cloud-sync/unrelated-action-during-collection-creation.spec.ts` covers the closest test-only-feasible variant instead**: it reuses `concurrent-workspace-creation-race.spec.ts`'s proven mechanism (stall `"My Environment"`'s `pull()` via `setCloudSyncGraphQLDelay(ms, projectId)` — stalling `push()` instead is already known to pass unconditionally, a false-positive) and layers a genuinely concurrent, unrelated mutation on top: while the pull is stalled, it renames that same workspace (`workspaceFlow.rename()`) **and** creates a brand-new sibling collection Y. Confirmed live: the rename survives intact, alongside the same invariants the race spec already checks (blob count grows once released, pull queries stay scoped to their own project id, neither snapshot gains the other's `key`).
**`tests/cloud-sync/unrelated-action-during-collection-creation.spec.ts` covers the closest test-only-feasible variant instead**: it reuses `concurrent-workspace-creation-race.spec.ts`'s proven mechanism (stall `"My Environment"`'s `pull()` via `setCloudSyncGraphQLDelay(ms, projectId)` — stalling `push()` instead is already known to pass unconditionally, a false-positive) and layers a genuinely concurrent, unrelated mutation on top: while the pull is stalled, it renames that same workspace (`workspaceFlow.renameCollection()`) **and** creates a brand-new sibling collection Y. Confirmed live: the rename survives intact, alongside the same invariants the race spec already checks (blob count grows once released, pull queries stay scoped to their own project id, neither snapshot gains the other's `key`).
## `appFlow` (main process / app lifecycle, not a UI domain)
@@ -1614,7 +1617,7 @@ No spec-facing API changed — this only affects local/CI environment setup, not
| Server | Constant(s) | Base URL | Use for |
| ----------------------------- | ------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `misc/mock-api.js` | `MOCK_API_SERVER` | `http://localhost:4010` | Insomnia cloud API mock (session, AI, updates, Cloud Sync) — not usually targeted directly by test bodies. Three flags are mutable via admin routes rather than fixed responses: `PUT /_admin/features/git-sync`, `PUT /_admin/storage-rule/git-sync`, and `PUT /_admin/features/konnect-entitlement` (body `{ enabled: boolean }`), wrapped by `misc/fixtures.ts`'s `setGitSyncFeatureFlag()`/`setGitSyncStorageRule()`/`setKonnectEntitlement()` — see the create-project dialog helpers above and the Konnect section above. Also serves `GET /mock-llm/models` (a static, always-on route, not a toggleable flag) — a fake OpenAI-compatible models list backing `MOCK_LLM_SERVER` (`${MOCK_API_SERVER}/mock-llm`), used by the AI Settings "url" backend's real "Load Models" fetch (see above). `POST /graphql` backs Cloud Sync's VCS API (see `cloudSyncFlow` above) — four fixture workspaces (three fetchable plus "Ghost Collection"), same fake session/symmetric key `misc/fixtures.ts` already injects; `PUT /_admin/cloud-sync/new-commit` (body `{ enabled, sessionId, projectId? }` — `projectId` picks which fixture workspace's alternate snapshot history to serve, `"My Environment"`'s by default; see `CLOUD_SYNC_NEW_COMMIT_SNAPSHOTS`) and `POST /_admin/cloud-sync/reset` (wrapped by `misc/fixtures.ts`'s `resetCloudSyncState()`) toggle its mutable state; `POST /_admin/cloud-sync/delay` (body `{ sessionId, ms, projectId? }`, wrapped by `setCloudSyncGraphQLDelay()`) holds every subsequent GraphQL response for the session by `ms` before replying — scoped to `projectId` when given, or every request otherwise — a concurrency-testing knob, not something `resetCloudSyncState()` clears (see `cloudSyncFlow` above). `GET /_admin/cloud-sync/request-log?sessionId=...` (wrapped by `getCloudSyncGraphQLRequestLog()`) reads back the same session's `requestLog: []` — every GraphQL request logged as `{ operationName, projectId, at }` at arrival time (before any delay hold), in order — for asserting the actual on-the-wire project id a request carried, not just its eventual effect on disk; **this one** *is* cleared by `resetCloudSyncState()`. Also backs the "Invite collaborators" dialog (see `organizationFlow` above) — `GET .../organizations/:id/collaborators` and its own per-session `collaboratorsBySession` state (keyed by the same `x-session-id` header the flags above use, so concurrent Playwright workers don't see each other's invites) start seeded with two members and one pending invite (`existing-collaborator-0/1/2@example.com`); `POST .../collaborators/start-adding` (body `{ emails: string[] }`) appends each as a new pending invite; `PATCH .../invites/:invitationId` and `PATCH .../members/:userId/roles` (body `{ roles: string[] }`) change a pending invite's or an existing member's role. `GET .../collaborators/search` always returns the same fixed list of 8 (`searchable-collaborator-0..7@example.com`) regardless of the query text — it doesn't actually filter server-side. Also backs the Vault Key flow (see `preferencesFlow` above) via `POST /v1/user/vault(/reset)`/`vault-verify-a`/`vault-verify-m1` — a **real SRP exchange** against `@getinsomnia/srp-js` (the exact same package/version the app itself uses), so an incorrect vault key genuinely fails server-side `checkM1()` rather than a canned rejection; state (the stored salt/verifier, any in-flight exchange) is isolated per `x-session-id` the same way Cloud Sync's is, and `POST /_admin/vault/reset` (wrapped by `misc/fixtures.ts`'s `resetVaultState()`, called before every launch) clears it. |
| `misc/echo-server.js` | `HTTP_SERVER` / `HTTP_SERVER_HTTPS` / `HTTP_SERVER_CUSTOM_CA_HTTPS` / `HTTP_SERVER_MTLS` | `http://localhost:4060` (+ `https://localhost:4061`/`:4062`/`:4063`, same routes) | HTTP echo — request/response assertions. Routes: `GET /status/404` (404 `{error:"not found"}`), `OPTIONS` on any path (204 + CORS headers), `GET /cookies` (echoes cookies), `POST`/`QUERY /post` (httpbin-style echo — `QUERY` accepted alongside `POST` specifically for the `HttpMethod.Query` scenario, since raw Node `http` matches routes by exact `req.method`, not Express-style wildcard), `POST /posts` (jsonplaceholder-style create), `POST /graphql` (canned Rick & Morty response), `GET /v2/swagger.json` (serves `misc/fixtures/petstore-swagger.json`, whose own `host`/`schemes` point back at this server), `GET /v2/pet/:petId` (canned Pet, backs the imported doc's "Find pet by ID"), `POST /calculator.asmx` (SOAP Add), any other path/method combo → empty `{}` (e.g. `GET /post` still falls through to this fallback — only `POST`/`QUERY` are wired for that route). `HTTP_SERVER_HTTPS` serves the identical `handleRequest` over TLS with a self-signed cert (`misc/fixtures/generated/localhost-cert.pem`/`localhost-key.pem`, CN=`localhost`) — call `preferencesFlow.set({ validateSSL: false })` before sending to it, or Insomnia rejects the cert. `HTTP_SERVER_CUSTOM_CA_HTTPS` (4062) serves a server cert signed by `misc/fixtures/generated/mtls-ca.pem` instead of a bare self-signed one — rejected by Insomnia's default trust store until that CA is added via `certificatesFlow.setCaCertificate()`, at which point it's trusted **without** `validateSSL: false`. `HTTP_SERVER_MTLS` (4063) uses the same CA-signed server cert but additionally sets `requestCert: true, rejectUnauthorized: true` against that CA — the TLS handshake itself fails without a valid client certificate (verified live via plain `curl`/`openssl`, independent of the app), so a request needs both `validateSSL: false` (to skip trusting the server cert, same as `HTTP_SERVER_HTTPS`) **and** a client certificate added via `certificatesFlow.addClientCertificate()` signed by that same CA (`misc/fixtures/generated/mtls-client-cert.pem`/`mtls-client-key.pem`) to succeed. `x-reply-delay-ms` delays every route uniformly (checked once at the top of `handleRequest`, before any route matching) on all four ports. |
| `misc/echo-server.js` | `HTTP_SERVER` / `HTTP_SERVER_HTTPS` / `HTTP_SERVER_CUSTOM_CA_HTTPS` / `HTTP_SERVER_MTLS` | `http://localhost:4060` (+ `https://localhost:4061`/`:4062`/`:4063`, same routes); the plain HTTP port listens dual-stack, so `http://[::1]:4060` reaches it too | HTTP echo — request/response assertions. Routes: `GET /status/404` (404 `{error:"not found"}`), `OPTIONS` on any path (204 + CORS headers), `GET /cookies` (echoes cookies), `POST`/`QUERY /post` (httpbin-style echo — `QUERY` accepted alongside `POST` specifically for the `HttpMethod.Query` scenario, since raw Node `http` matches routes by exact `req.method`, not Express-style wildcard), `POST /posts` (jsonplaceholder-style create), `POST /graphql` (canned Rick & Morty response), `GET /v2/swagger.json` (serves `misc/fixtures/petstore-swagger.json`, whose own `host`/`schemes` point back at this server), `GET /v2/pet/:petId` (canned Pet, backs the imported doc's "Find pet by ID"), `POST /calculator.asmx` (SOAP Add), any other path/method combo → empty `{}` (e.g. `GET /post` still falls through to this fallback — only `POST`/`QUERY` are wired for that route). `HTTP_SERVER_HTTPS` serves the identical `handleRequest` over TLS with a self-signed cert (`misc/fixtures/generated/localhost-cert.pem`/`localhost-key.pem`, CN=`localhost`) — call `preferencesFlow.set({ validateSSL: false })` before sending to it, or Insomnia rejects the cert. `HTTP_SERVER_CUSTOM_CA_HTTPS` (4062) serves a server cert signed by `misc/fixtures/generated/mtls-ca.pem` instead of a bare self-signed one — rejected by Insomnia's default trust store until that CA is added via `certificatesFlow.setCaCertificate()`, at which point it's trusted **without** `validateSSL: false`. `HTTP_SERVER_MTLS` (4063) uses the same CA-signed server cert but additionally sets `requestCert: true, rejectUnauthorized: true` against that CA — the TLS handshake itself fails without a valid client certificate (verified live via plain `curl`/`openssl`, independent of the app), so a request needs both `validateSSL: false` (to skip trusting the server cert, same as `HTTP_SERVER_HTTPS`) **and** a client certificate added via `certificatesFlow.addClientCertificate()` signed by that same CA (`misc/fixtures/generated/mtls-client-cert.pem`/`mtls-client-key.pem`) to succeed. `x-reply-delay-ms` delays every route uniformly (checked once at the top of `handleRequest`, before any route matching) on all four ports. |
| `misc/event-stream-server.js` | `EVENT_STREAM_SERVER` / `EVENT_STREAM_SERVER_HTTPS` | `http://localhost:4050` (+ `https://localhost:4051`, same `handleRequest`) | SSE requests. Route `GET /sse-events/:count` sends one "Starting Events" message, then `count` "Hello from the server!" events 1s apart. `x-reply-delay-ms` delays the whole connection opening — before the "Starting Events" message, so a test can disconnect before any event arrives. |
| `misc/ws-echo-server.js` | `WS_SERVER` / `WS_SERVER_WSS` | `ws://localhost:4040` (+ `wss://localhost:4041`, same connection handler) | WebSocket requests. `x-reply-delay-ms` is read once from the initial handshake request and delays both the "Request served by ..." banner and every echoed message by that amount. |
| `misc/socket-server.js` | `SOCKET_SERVER` / `SOCKET_SERVER_WSS` | `ws://localhost:3000` (+ `wss://localhost:3001`, same `io` instance via `io.attach()`) | Socket.IO requests. A second namespace `/protected` (`SOCKET_SERVER_PROTECTED`) accepts only handshakes whose `auth.token` equals `SOCKET_SERVER_AUTH_TOKEN`; others fail with `unauthorized`. `x-reply-delay-ms` is read once from `socket.handshake.headers` and delays every echoed event by that amount. |
@@ -1640,7 +1643,7 @@ pageManager.responsePage.getEvents(): Promise<StreamEvent[] | undefined> // liv
pageManager.<domain>RequestPage.send()/connect()/disconnect(callback?, timeout?): Promise<void>
// inherited from the shared pages/request.page.ts base — low-level; prefer <domain>RequestFlow.send()
// unless you need to trigger it without navigating to the Response pane (e.g. asserting an
// error dialog appears instead of a Response — see tests/environment/unlinked-environment-variable.spec.ts)
// error dialog appears instead of a ResponseView — see tests/environment/unlinked-environment-variable.spec.ts)
pageManager.<domain>RequestPage.setMethod(method: HttpMethod): Promise<void> / .getMethod(): Promise<string>
// also inherited from pages/request.page.ts — no Flow method changes an already-created request's
// method (only <x>RequestFlow.create()'s applyRequestFields() sets it once, at creation time), so