diff --git a/apps/web/e2e/group-chats.spec.ts b/apps/web/e2e/group-chats.spec.ts index 8804b9f..46046dc 100644 --- a/apps/web/e2e/group-chats.spec.ts +++ b/apps/web/e2e/group-chats.spec.ts @@ -3,6 +3,7 @@ import { captureScreenshot, completeOnboarding, createNamedBot, + fulfillFetchedRpc, openNewGroup, rpc, signup, @@ -35,7 +36,7 @@ async function showFirstMemberWorking(route: Route) { const body = (await response.json()) as { json?: Record }; const payload = body.json; if (!payload) { - await route.fulfill({ response }); + await fulfillFetchedRpc(route, response, body); return; } if ("groups" in payload) payload.groups = patchGroupMembers(payload.groups); @@ -49,7 +50,7 @@ async function showFirstMemberWorking(route: Route) { const current = payload.current as { groups?: unknown }; current.groups = patchGroupMembers(current.groups); } - await route.fulfill({ response, json: body }); + await fulfillFetchedRpc(route, response, body); } test("create group from + and see two bots in one transcript", async ({ page }, testInfo) => { diff --git a/apps/web/e2e/helpers.ts b/apps/web/e2e/helpers.ts index 1c686da..1e0bd68 100644 --- a/apps/web/e2e/helpers.ts +++ b/apps/web/e2e/helpers.ts @@ -1,4 +1,6 @@ -import { expect, type Locator, type Page, type TestInfo } from "@playwright/test"; +import { expect, type Locator, type Page, type Route, type TestInfo } from "@playwright/test"; + +type RpcEnvelope = { json?: Record }; /** Unterhaltungen rows only — `.sidebar-projekte` is nested inside the same shell block on main. */ export function unterhaltungenOnly(page: Page) { @@ -29,6 +31,19 @@ export async function rpc(page: Page, procedure: string, body: unknown): Prom return parsed.json as T; } +/** Fulfill a fetched RPC response without passing a consumed `response` into `route.fulfill`. */ +export async function fulfillFetchedRpc( + route: Route, + response: Awaited>, + body: RpcEnvelope, +) { + await route.fulfill({ + status: response.status(), + headers: response.headers(), + json: body, + }); +} + /** Patch a fetched RPC response without passing a consumed `response` into `route.fulfill`. */ export async function routePatchRpc( page: Page, @@ -38,11 +53,7 @@ export async function routePatchRpc( await page.route(`**/rpc/${procedure}`, async (route) => { const response = await route.fetch(); const body = (await response.json()) as { json: Record }; - await route.fulfill({ - status: response.status(), - headers: response.headers(), - json: { json: patch(body.json) }, - }); + await fulfillFetchedRpc(route, response, { json: patch(body.json) }); }); } diff --git a/apps/web/e2e/host-computer-prompt.spec.ts b/apps/web/e2e/host-computer-prompt.spec.ts index 5d79e8f..04cba6e 100644 --- a/apps/web/e2e/host-computer-prompt.spec.ts +++ b/apps/web/e2e/host-computer-prompt.spec.ts @@ -1,5 +1,5 @@ import { expect, test } from "@playwright/test"; -import { captureScreenshot, completeOnboarding, signup } from "./helpers"; +import { captureScreenshot, completeOnboarding, fulfillFetchedRpc, signup } from "./helpers"; for (const platform of ["darwin", "win32"]) { test(`host computer choice explains file access on ${platform}`, async ({ page }, testInfo) => { @@ -29,11 +29,13 @@ for (const platform of ["darwin", "win32"]) { }, platform); await page.route(/\/rpc\/(me|bootstrap)$/, async (route) => { const response = await route.fetch(); - const body = await response.json(); + const body = (await response.json()) as { json: Record & { me?: Record } }; const me = route.request().url().endsWith("/me") ? body.json : body.json.me; - me.canChooseHostComputer = true; - me.computerHost = null; - await route.fulfill({ response, json: body }); + if (me) { + me.canChooseHostComputer = true; + me.computerHost = null; + } + await fulfillFetchedRpc(route, response, body); }); await page.reload(); const dialog = page.getByRole("dialog", { name: "Where should bots run?" }); diff --git a/apps/web/e2e/mobile-sidebar-swipe.spec.ts b/apps/web/e2e/mobile-sidebar-swipe.spec.ts index f4c6ef5..d7a20e7 100644 --- a/apps/web/e2e/mobile-sidebar-swipe.spec.ts +++ b/apps/web/e2e/mobile-sidebar-swipe.spec.ts @@ -1,6 +1,6 @@ import type { Page } from "@playwright/test"; import { expect, test } from "@playwright/test"; -import { captureScreenshot, completeOnboarding, signup } from "./helpers"; +import { captureScreenshot, completeOnboarding, routePatchRpc, signup } from "./helpers"; test.use({ hasTouch: true, @@ -9,11 +9,7 @@ test.use({ }); async function prepareOnboarding(page: Page) { - await page.route("**/rpc/me", async (route) => { - const response = await route.fetch(); - const body = (await response.json()) as { json: Record }; - await route.fulfill({ response, json: { json: { ...body.json, needsModel: false } } }); - }); + await routePatchRpc(page, "me", (json) => ({ ...json, needsModel: false })); await page.route("**/rpc/integrationSetup/get", (route) => route.fulfill({ json: { diff --git a/apps/web/e2e/onboarding-model-auto-skip.spec.ts b/apps/web/e2e/onboarding-model-auto-skip.spec.ts index f970cee..94c09b2 100644 --- a/apps/web/e2e/onboarding-model-auto-skip.spec.ts +++ b/apps/web/e2e/onboarding-model-auto-skip.spec.ts @@ -1,17 +1,10 @@ import { expect, test } from "@playwright/test"; -import { signup } from "./helpers"; +import { routePatchRpc, signup } from "./helpers"; test("onboarding skips model connect when a default model is already available", async ({ page, }) => { - await page.route("**/rpc/me", async (route) => { - const response = await route.fetch(); - const body = (await response.json()) as { json: Record }; - await route.fulfill({ - response, - json: { json: { ...body.json, needsModel: false } }, - }); - }); + await routePatchRpc(page, "me", (json) => ({ ...json, needsModel: false })); await page.route("**/rpc/integrationSetup/get", (route) => route.fulfill({ diff --git a/apps/web/e2e/onboarding-model-required.spec.ts b/apps/web/e2e/onboarding-model-required.spec.ts index 77dad43..aa4e7b0 100644 --- a/apps/web/e2e/onboarding-model-required.spec.ts +++ b/apps/web/e2e/onboarding-model-required.spec.ts @@ -1,15 +1,8 @@ import { expect, type Page, test } from "@playwright/test"; -import { signup } from "./helpers"; +import { routePatchRpc, signup } from "./helpers"; async function forceNeedsModel(page: Page) { - await page.route("**/rpc/me", async (route) => { - const response = await route.fetch(); - const body = (await response.json()) as { json: Record }; - await route.fulfill({ - response, - json: { json: { ...body.json, needsModel: true } }, - }); - }); + await routePatchRpc(page, "me", (json) => ({ ...json, needsModel: true })); } test("onboarding shows the look picker when a model is still required", async ({ page }) => {