aps-agent/apps/web/e2e/planning-missing-data.spec.ts

61 lines
3.5 KiB
TypeScript

import { expect, test, type Page, type TestInfo } from '@playwright/test';
import path from 'node:path';
async function send(page: Page, text: string): Promise<void> {
await page.locator('.composer textarea').fill(text);
await expect(page.locator('.composer button.send')).toBeEnabled();
await page.locator('.composer button.send').click();
}
for (const viewport of [{ name: 'desktop', width: 1440, height: 900 }, { name: 'mobile', width: 390, height: 844 }]) {
test(`missing planning data is explained without suggesting a trial (${viewport.name})`, async ({ page }, info: TestInfo) => {
test.setTimeout(120_000);
await page.setViewportSize(viewport);
const errors: string[] = [];
page.on('pageerror', error => errors.push(error.message));
page.on('console', message => { if (message.type() === 'error') errors.push(message.text()); });
await page.goto('/');
await expect(page.locator('section.chat[data-session-ready="true"]')).toBeVisible({ timeout: 60_000 });
const projectName = `缺数引导-${viewport.name}-${Date.now()}`;
const creation = await page.evaluate(async name => {
const response = await fetch('/api/projects', {
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name }),
});
return { ok: response.ok, body: await response.json() };
}, projectName);
expect(creation.ok, JSON.stringify(creation.body)).toBeTruthy();
const workspace = await page.evaluate(async () => (await fetch('/api/workspace')).json()) as Record<string, any>;
await page.reload();
await expect(page.locator(`section.chat[data-session-id="${workspace.activeSessionId}"][data-session-ready="true"]`))
.toBeVisible({ timeout: 60_000 });
await send(page, '分析一下这个文件夹');
await expect(page.locator('.thinking-title').last()).toHaveText('检查完成 · 需补资料', { timeout: 60_000 });
await expect(page.locator('.bubble-md').last()).toContainText('当前资料未通过排产检查');
await expect(page.locator('.bubble-md').last()).toContainText('未生成方案');
const card = page.locator('.planning-data-card').first();
await expect(card).toContainText('需要补充');
await expect(card.locator('.planning-data-counts strong')).toHaveText(['0', '0', '0', '0']);
const guide = page.locator('.guidance-block').last();
await expect(guide).toContainText('排产还差这些');
await expect(guide).toContainText('先告诉我排哪些单');
await expect(guide).toContainText('产品怎么做还没定');
await expect(guide).toContainText('还缺能干活的设备/工序能力');
await expect(page.locator('body')).not.toContainText('甘特为空,需先试排生成草稿');
await expect(page.getByRole('button', { name: '生成交期优先试排方案', exact: true })).toHaveCount(0);
const cardCount = await page.locator('.planning-data-card').count();
const request = page.waitForRequest(req => new URL(req.url()).pathname === '/api/chat'
&& req.method() === 'POST' && req.postDataJSON().text === '排产还缺什么');
await send(page, '排产还缺什么');
await request;
await expect(page.locator('.guidance-block')).toHaveCount(2, { timeout: 60_000 });
await expect(page.locator('.planning-data-card')).toHaveCount(cardCount);
await expect(page.locator('.bubble-md').last()).toContainText('要开排还差');
await page.screenshot({ path: path.join(info.outputDir, `${viewport.name}-missing-data.png`), fullPage: true });
expect(errors).toEqual([]);
});
}