deerflow2/frontend/tests/e2e/thread-routing.spec.ts

108 lines
3.4 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { expect, test } from "@playwright/test";
import { v4 as uuid } from "uuid";
import {
THREAD_FOR_WELCOME,
newChatEntry,
openChat,
reuseThreadChatEntry,
sendMessage,
skipIfMissingThread,
waitForAnyMessages,
waitForMessageListReady,
} from "./support/chat-helpers";
test.use({
screenshot: "on",
video: "on",
});
test.describe("线程路由(无 isnew", () => {
test("/new 始终走欢迎态,发送后进入具体 thread 路由", async ({
page,
}, testInfo) => {
skipIfMissingThread(testInfo, THREAD_FOR_WELCOME, "FRONTEND_E2E_THREAD_ID");
await openChat(page, newChatEntry(THREAD_FOR_WELCOME!));
await expect(page.getByTestId("welcome-suggestions")).toBeVisible();
});
test("/chats/:thread_id 直接复用并渲染历史", async ({ page }, testInfo) => {
skipIfMissingThread(testInfo, THREAD_FOR_WELCOME, "FRONTEND_E2E_THREAD_ID");
await openChat(page, reuseThreadChatEntry(THREAD_FOR_WELCOME!));
await waitForMessageListReady(page, { requireMessages: false });
const messageCount = await waitForAnyMessages(page);
testInfo.skip(messageCount === 0, "当前线程没有可见历史消息。");
await expect(page).toHaveURL(
new RegExp(`/workspace/chats/${THREAD_FOR_WELCOME!}`),
);
await expect(page.locator(".is-user, .is-assistant").first()).toBeVisible();
});
test("/new 使用 uuid thread_id 发送后触发 stream(cod=0) 并进入 thread 路由", async ({
page,
}) => {
const threadId = uuid();
const text = `e2e-${threadId.slice(0, 8)}`;
await openChat(page, newChatEntry(threadId));
await expect(page.getByTestId("welcome-suggestions")).toBeVisible();
const streamRequestPromise = page.waitForRequest(
(request) => {
const url = request.url();
if (!url.includes("/stream")) return false;
if (!url.includes(threadId)) return false;
try {
const parsed = new URL(url);
return parsed.searchParams.get("cancel_on_disconnect") === "0";
} catch {
return url.includes("cancel_on_disconnect=0");
}
},
{ timeout: 30_000 },
);
await sendMessage(page, text);
await expect(
page.locator(".is-user").filter({ hasText: text }),
).toHaveCount(1);
await expect
.poll(async () => await page.locator(".is-assistant").count(), {
timeout: 30_000,
})
.toBeGreaterThan(0);
const streamRequest = await streamRequestPromise;
expect(streamRequest.url()).toContain("cancel_on_disconnect=0");
await expect(page).toHaveURL(
new RegExp(`/workspace/chats/${threadId}\\?is_chatting=true`),
{ timeout: 30_000 },
);
});
test("streaming 中点击停止可中断输出", async ({ page }) => {
const threadId = uuid();
const text =
"请逐行输出 1 到 500 的数字并在每一行前面加上“第N行”前缀不要省略。";
await openChat(page, newChatEntry(threadId));
await expect(page.getByTestId("welcome-suggestions")).toBeVisible();
await sendMessage(page, text);
const submitButton = page.locator("button[aria-label='Submit']");
await expect(submitButton).toHaveText("停止", { timeout: 30_000 });
await expect(submitButton).toBeEnabled();
await submitButton.click();
// 点击停止后应退出 streaming 态,按钮文本不再是“停止”
await expect(submitButton).toHaveText("发送", { timeout: 30_000 });
});
});