deerflow2/frontend/tests/e2e/artifacts-and-thread-reuse....

168 lines
5.7 KiB
TypeScript

import { expect, test } from "@playwright/test";
import {
PRIMARY_THREAD_ID,
THREAD_WITH_ARTIFACTS,
THREAD_WITH_HTML_ARTIFACT,
THREAD_WITH_IMAGE_ARTIFACT,
openChat,
reuseThreadChatEntry,
sendMessage,
skipIfMissingThread,
waitForAnyMessages,
waitForMessageListReady,
} from "./support/chat-helpers";
test.describe("聊天工作台 / Artifact 面板", () => {
test("DF-ART-001 含 artifacts 的线程展示入口并可打开文件列表", async ({
page,
}, testInfo) => {
skipIfMissingThread(
testInfo,
THREAD_WITH_ARTIFACTS,
"FRONTEND_E2E_ARTIFACTS_THREAD_ID",
);
await openChat(page, reuseThreadChatEntry(THREAD_WITH_ARTIFACTS!));
await waitForMessageListReady(page, { requireMessages: false });
const messageCount = await waitForAnyMessages(page);
testInfo.skip(messageCount === 0, "当前线程没有可见历史消息。");
testInfo.skip(
(await page.getByTestId("artifacts-open-button").count()) === 0,
"当前线程未展示 artifacts 入口。",
);
await expect(page.getByTestId("artifacts-open-button")).toBeVisible();
await page.getByTestId("artifacts-open-button").click();
await expect(page.getByTestId("artifact-file-list").first()).toBeVisible();
});
test("DF-ART-002 可打开图片 artifact 详情", async ({ page }, testInfo) => {
skipIfMissingThread(
testInfo,
THREAD_WITH_IMAGE_ARTIFACT,
"FRONTEND_E2E_IMAGE_ARTIFACT_THREAD_ID",
);
await openChat(page, reuseThreadChatEntry(THREAD_WITH_IMAGE_ARTIFACT!));
await waitForMessageListReady(page, { requireMessages: false });
const messageCount = await waitForAnyMessages(page);
testInfo.skip(messageCount === 0, "当前线程没有可见历史消息。");
testInfo.skip(
(await page.getByTestId("artifacts-open-button").count()) === 0,
"当前线程未展示 artifacts 入口。",
);
await page.getByTestId("artifacts-open-button").click();
const imageFile = page
.locator(
"[data-testid='artifact-file-list'] [data-testid='artifact-file-card']",
)
.filter({ hasText: /\.(png|jpe?g|gif|webp|svg)/i })
.first();
testInfo.skip(
(await imageFile.count()) === 0,
"当前线程没有可预览的图片 artifact。",
);
await imageFile.click();
await expect(page.getByTitle(/Artifact preview(?::.*)?$/i)).toBeVisible();
});
test("DF-ART-003 可打开 HTML artifact 详情", async ({ page }, testInfo) => {
skipIfMissingThread(
testInfo,
THREAD_WITH_HTML_ARTIFACT,
"FRONTEND_E2E_HTML_ARTIFACT_THREAD_ID",
);
await openChat(page, reuseThreadChatEntry(THREAD_WITH_HTML_ARTIFACT!));
await waitForMessageListReady(page, { requireMessages: false });
const messageCount = await waitForAnyMessages(page);
testInfo.skip(messageCount === 0, "当前线程没有可见历史消息。");
testInfo.skip(
(await page.getByTestId("artifacts-open-button").count()) === 0,
"当前线程未展示 artifacts 入口。",
);
await page.getByTestId("artifacts-open-button").click();
const htmlFile = page
.locator(
"[data-testid='artifact-file-list'] [data-testid='artifact-file-card']",
)
.filter({ hasText: /\.html?/i })
.first();
testInfo.skip(
(await htmlFile.count()) === 0,
"当前线程没有 HTML artifact。",
);
const htmlArtifactResponsePromise = page.waitForResponse((response) => {
const url = decodeURIComponent(response.url());
return (
response.status() === 200 &&
/\/api\/threads\/[^/]+\/artifacts\//.test(url) &&
/\.html?($|\?)/i.test(url)
);
});
await htmlFile.click();
const htmlArtifactResponse = await htmlArtifactResponsePromise;
expect(
htmlArtifactResponse.headers()["content-disposition"] ?? "",
).toContain("attachment;");
await expect(page.getByTitle(/Artifact preview(?::.*)?$/i)).toBeVisible();
});
test("DF-ART-004 关闭 artifact 面板后恢复聊天主视图", async ({
page,
}, testInfo) => {
skipIfMissingThread(
testInfo,
THREAD_WITH_ARTIFACTS,
"FRONTEND_E2E_ARTIFACTS_THREAD_ID",
);
await openChat(page, reuseThreadChatEntry(THREAD_WITH_ARTIFACTS!));
await waitForMessageListReady(page, { requireMessages: false });
const messageCount = await waitForAnyMessages(page);
testInfo.skip(messageCount === 0, "当前线程没有可见历史消息。");
testInfo.skip(
(await page.getByTestId("artifacts-open-button").count()) === 0,
"当前线程未展示 artifacts 入口。",
);
await page.getByTestId("artifacts-open-button").click();
await expect(page.getByTestId("artifact-file-list").first()).toBeVisible();
await page.getByTestId("artifacts-panel-close").click();
await expect(page.getByTestId("artifacts-open-button")).toBeVisible();
await expect(page.getByRole("log").first()).toBeVisible();
});
test("DF-ART-005 生成简单 HTML 后出现 artifact-file-card", async ({
page,
}, testInfo) => {
test.setTimeout(180_000);
skipIfMissingThread(testInfo, PRIMARY_THREAD_ID, "FRONTEND_E2E_THREAD_ID");
await openChat(page, reuseThreadChatEntry(PRIMARY_THREAD_ID!));
await waitForMessageListReady(page, { requireMessages: false });
await sendMessage(page, "生成一个简单的html文件");
await expect
.poll(
async () => await page.getByTestId("artifacts-open-button").count(),
{ timeout: 120_000 },
)
.toBeGreaterThan(0);
await page.getByTestId("artifacts-open-button").click();
await expect
.poll(async () => await page.getByTestId("artifact-file-card").count(), {
timeout: 30_000,
})
.toBeGreaterThan(0);
});
});