aps-agent/apps/web/e2e/core-journey.spec.ts

98 lines
5.3 KiB
TypeScript
Raw 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.

// ============================================================
// 核心用户路径 E2E 冒烟(矩阵 118 · 前端 E2E)
// 登录(JMS)→ 跑一版排产(柔性)→ 结果块出现 → 视口切换(世界对比/柔性工作台)→ 命令面板
// 全部为中文断言;依赖后端(默认 127.0.0.1:8003)+ JMS 网络可达。
// 设置 APS_E2E_SKIP_JMS=1 时跳过本文件(CI 无外网场景),只保留访客冒烟。
// 注意:默认 preview(生产构建)模式运行;dev 模式 StrictMode 结果捕获缺陷已于 round-42
// 修复并验证(E2E_MODE=dev 附加冒烟),preview 仍为默认门禁。
// ============================================================
import { test, expect, type Page } from '@playwright/test';
const SKIP_JMS = process.env.APS_E2E_SKIP_JMS === '1';
const JMS = {
tenant: process.env.E2E_JMS_TENANT || 'platform',
username: process.env.E2E_JMS_USER || 'zhangzhen',
password: process.env.E2E_JMS_PASSWORD || 'sz@zz@1116',
};
async function login(page: Page): Promise<void> {
await page.goto('/');
const trigger = page.locator('.guest-login-trigger');
await expect(trigger).toBeEnabled({ timeout: 30_000 });
await trigger.click();
const dialog = page.locator('.auth-login-dialog');
await expect(dialog).toBeVisible();
await dialog.locator('input[placeholder="请输入企业名称"]').fill(JMS.tenant);
await dialog.locator('input[placeholder="请输入用户名"]').fill(JMS.username);
await dialog.locator('input[placeholder="请输入密码"]').fill(JMS.password);
await dialog.locator('.login-submit').click();
// 成功 → 弹窗关闭;若后端要求图形验证码则报清晰错误(本地 jms 未开启)
await expect(dialog).toBeHidden({ timeout: 30_000 }).catch(async (error) => {
if (await dialog.locator('.login-captcha-field').count()) {
throw new Error('登录要求图形验证码,E2E 冒烟无法自动处理(请用预置测试账号或关闭验证码)');
}
throw error;
});
// 进入工作台:登录态下出现排产指令输入框
await expect(page.locator('textarea[placeholder^="输入排产指令"]')).toBeVisible({ timeout: 60_000 });
await expect(page.locator('.sidebar-brand')).toContainText('工业智核');
await expect(page.locator('.sidebar-account-area')).toContainText(/张振|zhangzhen/);
}
test.describe('核心用户路径(JMS)', () => {
test.skip(SKIP_JMS, 'APS_E2E_SKIP_JMS=1:跳过需要外网 JMS 的核心路径');
test('登录 → 跑一版排产 → 结果块 → 视口切换 → 命令面板', async ({ page }) => {
await login(page);
// ---------- 跑一版排产(柔性,当前种子数据可直接出结果) ----------
const composer = page.locator('textarea[placeholder^="输入排产指令"]');
await composer.fill('跑一版柔性排产');
await composer.press('Enter');
// 智能体回复出现(SSE 流式正文非空,中文断言)
await expect(page.locator('.msg.agent .bubble')).toContainText(/.+/, { timeout: 240_000 });
// 结果块出现:柔性排产结果卡(中文标题断言)
const resultBlock = page.locator('.flex-block-title', { hasText: '柔性排产' });
await expect(resultBlock).toBeVisible({ timeout: 240_000 });
// 结果入口可用:右侧“会话结果/再点收起”按钮(preview 模式下结果捕获后自动打开视口)
const resultButton = page.locator(
'.right-rail button[data-tip="会话结果"], .right-rail button[data-tip="再点收起"]',
);
await expect(resultButton).toBeEnabled({ timeout: 120_000 });
// ---------- 视口切换 ----------
// 结果捕获成功后视口已自动打开;未打开则点击“会话结果”兜底
const vpToolbar = page.locator('.vp-toolbar');
await expect(vpToolbar).toBeVisible({ timeout: 30_000 }).catch(async () => {
await resultButton.click();
await expect(vpToolbar).toBeVisible({ timeout: 30_000 });
});
// 页签存在:世界对比
const diffTab = page.locator('.seg .tab', { hasText: '世界对比' });
await expect(diffTab).toBeVisible();
await diffTab.click();
await expect(page.locator('.world-diff')).toBeVisible();
// 右侧工具:柔性工作台(任务要求“柔性工作台页签存在”)
const flexButton = page.locator('.right-rail button[data-tip="柔性工作台"]');
await expect(flexButton).toBeVisible();
await flexButton.click();
await expect(page.locator('.flex-bench')).toBeVisible();
// ---------- 命令面板 ----------
await page.keyboard.press('Control+K');
const paletteInput = page.locator('.palette input');
await expect(paletteInput).toBeVisible();
// 未过滤时面板条目可用(柔性工作台面板项)
await expect(page.locator('.palette-item', { hasText: '柔性工作台' })).toBeVisible();
// 中文过滤:世界 → 两个世界对比视图命令
await paletteInput.fill('世界');
await expect(page.locator('.palette-item', { hasText: '两个世界对比' })).toBeVisible();
// 中文过滤:柔性 → 柔性工作台面板项
await paletteInput.fill('柔性');
await expect(page.locator('.palette-item', { hasText: '柔性工作台' })).toBeVisible();
await page.keyboard.press('Escape');
await expect(page.locator('.palette')).toBeHidden();
});
});