You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
211 lines
7.3 KiB
211 lines
7.3 KiB
import { test, expect } from "@playwright/test";
|
|
import { readFileSync } from "node:fs";
|
|
import { E2E_ADMIN, FIXED_CAPTCHA } from "../fixtures/test-users";
|
|
|
|
const MOCK_REPLY = "你好!这是一个测试回复。";
|
|
|
|
function getLastSystemPrompt(): string {
|
|
try {
|
|
return readFileSync("/tmp/e2e-last-system-prompt.txt", "utf-8");
|
|
} catch {
|
|
return "";
|
|
}
|
|
}
|
|
|
|
async function loginViaUI(page: import("@playwright/test").Page) {
|
|
await page.goto("/auth/login");
|
|
await page.fill("#login-username", E2E_ADMIN.username);
|
|
await page.fill("#login-password", E2E_ADMIN.password);
|
|
await page.fill("#login-captcha", FIXED_CAPTCHA);
|
|
await page.click('button[type="submit"]');
|
|
await page.waitForURL("/", { timeout: 15000 });
|
|
await expect(page.locator(".agent-textarea")).toBeVisible({ timeout: 10000 });
|
|
await page.waitForTimeout(1000);
|
|
const newChatBtn = page.locator(".new-chat-btn").first();
|
|
if (await newChatBtn.isVisible()) {
|
|
await newChatBtn.click();
|
|
await page.waitForTimeout(500);
|
|
}
|
|
}
|
|
|
|
test.describe("Agent 对话", () => {
|
|
test("首页显示欢迎页和示例卡片", async ({ page }) => {
|
|
await loginViaUI(page);
|
|
|
|
await expect(page.locator(".agent-welcome")).toBeVisible({ timeout: 10000 });
|
|
await expect(page.locator(".welcome-title")).toContainText("有什么可以帮你的");
|
|
await expect(page.locator(".example-card")).toHaveCount(4);
|
|
});
|
|
|
|
test("输入框和发送按钮存在", async ({ page }) => {
|
|
await loginViaUI(page);
|
|
|
|
await expect(page.locator(".agent-textarea")).toBeVisible({ timeout: 10000 });
|
|
await expect(page.locator(".btn-send")).toBeVisible();
|
|
});
|
|
|
|
test("空消息时发送按钮禁用", async ({ page }) => {
|
|
await loginViaUI(page);
|
|
|
|
const sendBtn = page.locator(".btn-send");
|
|
await expect(sendBtn).toBeDisabled();
|
|
});
|
|
|
|
test("输入内容后发送按钮启用", async ({ page }) => {
|
|
await loginViaUI(page);
|
|
|
|
await page.fill(".agent-textarea", "测试消息");
|
|
await expect(page.locator(".btn-send")).toBeEnabled();
|
|
});
|
|
|
|
test("点击示例卡片直接发送消息", async ({ page }) => {
|
|
await loginViaUI(page);
|
|
|
|
const firstExample = page.locator(".example-card").first();
|
|
const exampleText = await firstExample.innerText();
|
|
await firstExample.click();
|
|
|
|
await expect(page.locator(".agent-message.is-user .user-bubble")).toContainText(exampleText, { timeout: 10000 });
|
|
});
|
|
|
|
test("发送消息后显示用户消息和助手回复", async ({ page }) => {
|
|
await loginViaUI(page);
|
|
|
|
const testMessage = "你好,这是一条测试消息";
|
|
await page.fill(".agent-textarea", testMessage);
|
|
await page.click(".btn-send");
|
|
|
|
await expect(page.locator(".agent-message.is-user .user-bubble")).toContainText(testMessage, { timeout: 10000 });
|
|
|
|
await expect(page.locator(".agent-message.is-assistant")).toBeVisible({ timeout: 10000 });
|
|
|
|
await expect(
|
|
page.locator(".agent-message.is-assistant .agent-markdown"),
|
|
).toContainText(MOCK_REPLY, { timeout: 30000 });
|
|
});
|
|
|
|
test("发送消息后显示加载动画", async ({ page }) => {
|
|
await loginViaUI(page);
|
|
|
|
await page.fill(".agent-textarea", "测试加载状态");
|
|
await page.click(".btn-send");
|
|
|
|
await expect(page.locator(".assistant-loading")).toBeVisible({ timeout: 5000 });
|
|
});
|
|
|
|
test("Enter 键发送消息", async ({ page }) => {
|
|
await loginViaUI(page);
|
|
|
|
const testMessage = "通过回车发送";
|
|
await page.fill(".agent-textarea", testMessage);
|
|
await page.press(".agent-textarea", "Enter");
|
|
|
|
await expect(page.locator(".agent-message.is-user .user-bubble")).toContainText(testMessage, { timeout: 10000 });
|
|
});
|
|
|
|
test("流式响应完成后消息内容完整", async ({ page }) => {
|
|
await loginViaUI(page);
|
|
|
|
await page.fill(".agent-textarea", "请回复");
|
|
await page.click(".btn-send");
|
|
|
|
await expect(
|
|
page.locator(".agent-message.is-assistant .agent-markdown"),
|
|
).toContainText(MOCK_REPLY, { timeout: 30000 });
|
|
|
|
await expect(page.locator(".btn-stop")).not.toBeVisible({ timeout: 15000 });
|
|
await expect(page.locator(".btn-send")).toBeVisible();
|
|
});
|
|
|
|
test("连续对话保留历史消息", async ({ page }) => {
|
|
await loginViaUI(page);
|
|
|
|
const firstMsg = "第一条消息";
|
|
await page.fill(".agent-textarea", firstMsg);
|
|
await page.click(".btn-send");
|
|
|
|
await expect(page.locator(".agent-message.is-user .user-bubble").first()).toContainText(firstMsg, { timeout: 10000 });
|
|
await expect(
|
|
page.locator(".agent-message.is-assistant .agent-markdown").first(),
|
|
).toContainText(MOCK_REPLY, { timeout: 30000 });
|
|
|
|
const secondMsg = "第二条消息";
|
|
await page.fill(".agent-textarea", secondMsg);
|
|
await page.click(".btn-send");
|
|
|
|
await expect(page.locator(".agent-message.is-user")).toHaveCount(2, { timeout: 10000 });
|
|
await expect(page.locator(".agent-message.is-assistant")).toHaveCount(2, { timeout: 30000 });
|
|
});
|
|
|
|
test("修改系统提示词后发送消息使用自定义提示词", async ({ page }) => {
|
|
await loginViaUI(page);
|
|
|
|
const createBody = await page.evaluate(async () => {
|
|
const res = await fetch("/api/agents/default/sessions", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ systemPrompt: "You are a pirate. Always respond in pirate speak." }),
|
|
});
|
|
return res.json();
|
|
});
|
|
const sessionId = createBody.data.id;
|
|
|
|
await page.goto(`/chat/default?session=${sessionId}`);
|
|
await page.waitForTimeout(1000);
|
|
const newChatBtn = page.locator(".new-chat-btn").first();
|
|
if (await newChatBtn.isVisible()) {
|
|
await newChatBtn.click();
|
|
await page.waitForTimeout(500);
|
|
}
|
|
|
|
await page.fill(".agent-textarea", "hello");
|
|
await page.click(".btn-send");
|
|
|
|
await expect(
|
|
page.locator(".agent-message.is-assistant .agent-markdown").first(),
|
|
).toContainText(MOCK_REPLY, { timeout: 30000 });
|
|
|
|
const lastPrompt = getLastSystemPrompt();
|
|
expect(lastPrompt).toBe("You are a pirate. Always respond in pirate speak.");
|
|
});
|
|
|
|
test("重置系统提示词后回退到 Agent 默认", async ({ page }) => {
|
|
await loginViaUI(page);
|
|
|
|
const createBody = await page.evaluate(async () => {
|
|
const res = await fetch("/api/agents/default/sessions", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ systemPrompt: "temporary custom prompt" }),
|
|
});
|
|
return res.json();
|
|
});
|
|
const sessionId = createBody.data.id;
|
|
|
|
await page.evaluate(async (id) => {
|
|
await fetch(`/api/agents/default/sessions/${id}/config`, {
|
|
method: "PUT",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ systemPrompt: null }),
|
|
});
|
|
}, sessionId);
|
|
|
|
await page.goto(`/chat/default?session=${sessionId}`);
|
|
await page.waitForTimeout(1000);
|
|
const newChatBtn = page.locator(".new-chat-btn").first();
|
|
if (await newChatBtn.isVisible()) {
|
|
await newChatBtn.click();
|
|
await page.waitForTimeout(500);
|
|
}
|
|
|
|
await page.fill(".agent-textarea", "hello again");
|
|
await page.click(".btn-send");
|
|
|
|
await expect(
|
|
page.locator(".agent-message.is-assistant .agent-markdown").first(),
|
|
).toContainText(MOCK_REPLY, { timeout: 30000 });
|
|
|
|
const lastPrompt = getLastSystemPrompt();
|
|
expect(lastPrompt).toBe("You are a helpful AI assistant.");
|
|
});
|
|
});
|
|
|