fix(e2e): wait for shell-ready after group chat reload (#94)
* fix(e2e): wait for shell-ready after group chat reload After voice/connect and full page reload on a group route, bootstrap can still be in flight. Use waitForChatComposer (data-ready + Message combobox) instead of asserting the composer immediately, matching #87. Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> * fix(e2e): wait for shell before approval transcript after reload Transcript messages are not painted until bootstrap finishes; match group-chats and #87 by waiting on data-ready before asserting durable approval copy survives reload. Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> * style: format approval-resume e2e import Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> * fix(e2e): wait for archived sidebar after space delete After deleting a space the Archived section can appear only once bootstrap finishes; wait for shell-ready after archive reload and assert the Archived toggle before clicking. Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> * fix(e2e): expect archived sidebar when last bot is archived After archiving the only bot, the shell is ready without a Message composer. Wait for data-ready and the Archived toggle instead of waitForChatComposer on reload. Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> * fix(e2e): wait for shell in composer-paste openComposer helper Third paste spec failed when Message appeared before bootstrap finished; reuse waitForChatComposer after navigating to /app. Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>
This commit is contained in:
parent
a974f09520
commit
d1f7034aa5
@ -1,5 +1,5 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { captureScreenshot, completeOnboarding, signup } from "./helpers";
|
||||
import { captureScreenshot, completeOnboarding, signup, waitForChatComposer } from "./helpers";
|
||||
|
||||
test.describe.configure({ mode: "serial" });
|
||||
|
||||
@ -47,8 +47,9 @@ test("approval input resumes durable work", async ({ page }, testInfo) => {
|
||||
await expect(handledAnswer).toBeVisible();
|
||||
await expect(page.getByText("Answered: Paris", { exact: true })).toBeVisible();
|
||||
|
||||
await page.reload();
|
||||
await expect(resumed).toBeVisible({ timeout: 20_000 });
|
||||
await page.reload({ waitUntil: "domcontentloaded" });
|
||||
await waitForChatComposer(page);
|
||||
await expect(resumed).toBeVisible({ timeout: 30_000 });
|
||||
await expect(handledAnswer).toBeVisible();
|
||||
await expect(page.getByText("Answered: Paris", { exact: true })).toBeVisible();
|
||||
await captureScreenshot(page, testInfo, "24-approval-resumed-after-reload");
|
||||
|
||||
@ -1,15 +1,14 @@
|
||||
import { expect, type Page, test } from "@playwright/test";
|
||||
import { captureScreenshot, completeOnboarding, signup } from "./helpers";
|
||||
import { captureScreenshot, completeOnboarding, signup, waitForChatComposer } from "./helpers";
|
||||
|
||||
async function openComposer(page: Page) {
|
||||
const stamp = Date.now();
|
||||
await signup(page, `composer-paste-${stamp}@rakazo.test`, "password12", "Paste Test");
|
||||
await completeOnboarding(page);
|
||||
await page.goto("/app");
|
||||
await page.goto("/app", { waitUntil: "domcontentloaded" });
|
||||
await page.waitForURL(/\/app\/[^/]+$/);
|
||||
const composer = page.getByRole("combobox", { name: /Message/ });
|
||||
await expect(composer).toBeVisible();
|
||||
return composer;
|
||||
await waitForChatComposer(page);
|
||||
return page.getByRole("combobox", { name: /Message/ });
|
||||
}
|
||||
|
||||
test("pasting an image into the composer creates an attachment", async ({ page }, testInfo) => {
|
||||
|
||||
@ -8,6 +8,7 @@ import {
|
||||
openNewGroup,
|
||||
rpc,
|
||||
signup,
|
||||
waitForChatComposer,
|
||||
} from "./helpers";
|
||||
|
||||
async function createBot(page: Page, name: string) {
|
||||
@ -86,9 +87,9 @@ test("create group from + and see two bots in one transcript", async ({ page },
|
||||
provider: "scripted",
|
||||
apiKey: "fake-group-voice-key",
|
||||
});
|
||||
await page.reload();
|
||||
await page.reload({ waitUntil: "domcontentloaded" });
|
||||
await expect(page).toHaveURL(groupUrl);
|
||||
await expect(page.getByRole("combobox", { name: "Message" })).toBeVisible();
|
||||
await waitForChatComposer(page);
|
||||
|
||||
const groups = await rpc<
|
||||
Array<{
|
||||
@ -237,9 +238,7 @@ test("create group from + and see two bots in one transcript", async ({ page },
|
||||
const cityAsk = page.locator("p").filter({ hasText: /^Which city should I use\?$/ });
|
||||
if ((await cityAsk.count()) === 0) {
|
||||
await page.reload({ waitUntil: "domcontentloaded" });
|
||||
await expect(page.getByRole("combobox", { name: "Message" })).toBeVisible({
|
||||
timeout: 15_000,
|
||||
});
|
||||
await waitForChatComposer(page);
|
||||
}
|
||||
await expect(cityAsk).toBeVisible({ timeout: 15_000 });
|
||||
await page.getByRole("button", { name: "Edit first" }).click();
|
||||
@ -289,7 +288,7 @@ test("create group from + and see two bots in one transcript", async ({ page },
|
||||
await expect(page).toHaveURL(new RegExp(`/app/g/${reviewGroup.id}$`));
|
||||
await expect(page.getByTestId("transcript")).not.toContainText("Answered: Paris");
|
||||
releaseReviewSnapshot();
|
||||
await expect(page.getByRole("combobox", { name: "Message" })).toBeVisible();
|
||||
await waitForChatComposer(page);
|
||||
await page.unroute("**/rpc/threads/get");
|
||||
await projekte
|
||||
.getByRole("button", { name: /^Draft team/ })
|
||||
@ -321,7 +320,7 @@ test("create group from + and see two bots in one transcript", async ({ page },
|
||||
await captureScreenshot(page, testInfo, "group-settings-mobile");
|
||||
|
||||
await rpc(page, "groups/remove", { groupId: reviewGroup.id });
|
||||
await page.goto(`/app/g/${reviewGroup.id}`);
|
||||
await page.goto(`/app/g/${reviewGroup.id}`, { waitUntil: "domcontentloaded" });
|
||||
await page.waitForURL(/\/app\/(?!g\/)[^/]+$/);
|
||||
await expect(page.getByRole("combobox", { name: /Message/ })).toBeVisible();
|
||||
await waitForChatComposer(page);
|
||||
});
|
||||
|
||||
@ -182,10 +182,18 @@ test("deleting the last bot in a space stays in the app after first use", async
|
||||
const [chief] = await rpc<Array<{ id: string }>>(page, "bots/list", {});
|
||||
expect(chief).toBeTruthy();
|
||||
await rpc(page, "bots/archive", { botId: chief!.id });
|
||||
await page.reload();
|
||||
await page.reload({ waitUntil: "domcontentloaded" });
|
||||
await expect(page.getByTestId("shell-root")).toHaveAttribute("data-ready", "true", {
|
||||
timeout: 30_000,
|
||||
});
|
||||
await expect(page).not.toHaveURL(/\/onboarding/);
|
||||
|
||||
const sidebar = page.locator("aside").first();
|
||||
// No active bot thread after archiving the only bot — shell shows Archived, not Message.
|
||||
await expect(page.getByRole("combobox", { name: "Message" })).toHaveCount(0);
|
||||
await expect(sidebar.getByRole("button", { name: /^Archived/ })).toBeVisible({
|
||||
timeout: 30_000,
|
||||
});
|
||||
await openNewSpace(page);
|
||||
const dialog = page.getByRole("dialog", { name: "New space" });
|
||||
await dialog.getByLabel("Name").fill("Side");
|
||||
@ -214,6 +222,8 @@ test("deleting the last bot in a space stays in the app after first use", async
|
||||
.getByRole("button", { name: "Delete", exact: true })
|
||||
.click();
|
||||
await expect(sidebar.getByText("Side", { exact: true })).toHaveCount(0);
|
||||
await sidebar.getByRole("button", { name: /^Archived/ }).click();
|
||||
const archivedToggle = sidebar.getByRole("button", { name: /^Archived/ });
|
||||
await expect(archivedToggle).toBeVisible({ timeout: 30_000 });
|
||||
await archivedToggle.click();
|
||||
await expect(sidebar.getByText("Chief", { exact: true })).toBeVisible();
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user