61 lines
3.5 KiB
TypeScript
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([]);
|
||
|
|
});
|
||
|
|
}
|