Files
kandev/apps/web/e2e/tests/chat/mobile-queue-admission-reliability.spec.ts
T
2026-09-14 19:19:09 +01:00

107 lines
4.5 KiB
TypeScript

import { expect, type Page } from "@playwright/test";
import { test } from "../../fixtures/test-base";
import type { SeedData } from "../../fixtures/test-base";
import type { ApiClient } from "../../helpers/api-client";
import { registerSeparateQueueRows } from "../../helpers/message-queue-settings";
import { waitForActiveSessionForegroundActivity } from "../../helpers/session-store";
import { typeWhileBusy, waitForComposerQueueMode } from "../../helpers/type-while-busy";
import { routeMainWebSocketWithQueueAdmissionDrops } from "../../helpers/ws-drop";
import { openQuickChatWithAgent, sendQuickChatMessage } from "./quick-chat-helpers";
import { SessionPage } from "../../pages/session-page";
registerSeparateQueueRows(test);
async function expectTouchTarget(locator: ReturnType<SessionPage["submitButton"]>): Promise<void> {
await expect(locator).toBeVisible();
const box = await locator.boundingBox();
expect(box).not.toBeNull();
expect(box!.width).toBeGreaterThanOrEqual(44);
expect(box!.height).toBeGreaterThanOrEqual(44);
}
async function seedMobileBusyTask(
testPage: Page,
apiClient: ApiClient,
seedData: SeedData,
): Promise<{ session: SessionPage; taskId: string; sessionId: string }> {
const task = await apiClient.createTaskWithAgent(
seedData.workspaceId,
"Mobile queue admission request recovery",
seedData.agentProfileId,
{
description: "/e2e:simple-message",
workflow_id: seedData.workflowId,
workflow_step_id: seedData.startStepId,
repository_ids: [seedData.repositoryId],
},
);
await testPage.goto(`/t/${task.id}`);
const session = new SessionPage(testPage);
await session.waitForLoad();
await session.waitForChatIdle({ timeout: 30_000 });
await session.sendMessageViaButton("/sleep 30");
await session.agentStatus().waitFor({ state: "visible", timeout: 20_000 });
await waitForActiveSessionForegroundActivity(testPage, "generating");
if (!task.session_id) throw new Error("createTaskWithAgent did not return a session_id");
return { session, taskId: task.id, sessionId: task.session_id };
}
test.describe("mobile queue admission reliability", () => {
test.describe.configure({ retries: 1 });
test("retries a pre-server lost Task admission once and clears the draft", async ({
testPage,
apiClient,
seedData,
}) => {
test.setTimeout(120_000);
const drops = await routeMainWebSocketWithQueueAdmissionDrops(testPage);
const { session, taskId, sessionId } = await seedMobileBusyTask(testPage, apiClient, seedData);
await waitForComposerQueueMode(session.activeChat());
const prompt = "recover the lost mobile queue request";
drops.dropNextQueueAddRequest();
const editor = session.activeChat().locator(".tiptap.ProseMirror:visible");
await typeWhileBusy(testPage, editor, prompt);
await expectTouchTarget(session.submitButton());
await session.tapSubmitWhenReady();
const identity = await apiClient.getQueueSessionIdentity(taskId, sessionId);
await expect(editor).toHaveText("", { timeout: 45_000 });
await expect(session.activeChat().getByTestId("queue-chip")).toBeVisible({ timeout: 15_000 });
await expect
.poll(async () => (await apiClient.getQueueStatus(identity)).count, { timeout: 15_000 })
.toBe(1);
await expect.poll(() => drops.queueAddRequestCount()).toBe(2);
await expect.poll(() => drops.droppedRequestCount()).toBe(1);
});
test("reconciles a lost accepted Quick Chat response through a touch submit", async ({
testPage,
}) => {
test.setTimeout(120_000);
const drops = await routeMainWebSocketWithQueueAdmissionDrops(testPage);
const dialog = await openQuickChatWithAgent(testPage);
await sendQuickChatMessage(dialog, testPage, "/sleep 30");
await expect(testPage.getByRole("status", { name: /Agent is (starting|running)/ })).toBeVisible(
{
timeout: 15_000,
},
);
await waitForComposerQueueMode(dialog);
const prompt = "recover the mobile Quick Chat admission";
drops.dropNextQueueAddResponse();
const editor = dialog.locator(".tiptap.ProseMirror:visible");
await typeWhileBusy(testPage, editor, prompt);
const submit = dialog.getByTestId("submit-message-button");
await expectTouchTarget(submit);
await submit.tap();
await expect(editor).toHaveText("", { timeout: 30_000 });
await expect(dialog.getByTestId("queue-chip")).toBeVisible({ timeout: 15_000 });
await expect.poll(() => drops.queueAddRequestCount()).toBe(1);
await expect.poll(() => drops.droppedResponseCount()).toBe(1);
});
});