110 lines
6.9 KiB
TypeScript
110 lines
6.9 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
import type { ViteDevServer } from 'vite';
|
|
import { createCanvasMyWorksServer } from './canvas-my-works-layout-harness.mjs';
|
|
|
|
let server: ViteDevServer;
|
|
let baseUrl: string;
|
|
test.use({ headless: true, channel: process.env.MAKELORE_LAYOUT_BROWSER_CHANNEL, video: 'off' });
|
|
test.beforeAll(async () => {
|
|
server = await createCanvasMyWorksServer();
|
|
baseUrl = server.resolvedUrls!.local[0];
|
|
});
|
|
test.afterAll(async () => { await server?.close(); });
|
|
|
|
for (const viewport of [{ width: 1600, height: 1000 }, { width: 1440, height: 960 }, { width: 390, height: 844 }]) {
|
|
test(`Canvas My Works stays usable and returns to its source at ${viewport.width}px`, async ({ page }, testInfo) => {
|
|
const pageErrors: string[] = [];
|
|
const unexpectedRequests: string[] = [];
|
|
page.on('pageerror', (error) => pageErrors.push(error.message));
|
|
page.on('request', (request) => {
|
|
const url = request.url();
|
|
if (/^https?:/.test(url) && !url.startsWith(baseUrl)) unexpectedRequests.push(url);
|
|
});
|
|
await page.setViewportSize(viewport);
|
|
await page.goto(baseUrl);
|
|
expect(pageErrors, 'Canvas fixture must initialize without module or browser errors').toEqual([]);
|
|
const split = page.getByTestId('canvas-workspace-split');
|
|
await expect(split).toBeVisible();
|
|
if (viewport.width >= 1024) await page.getByRole('button', { name: '展开创作对话', exact: true }).click();
|
|
await page.getByRole('textbox', { name: '告诉 AI 你想创作什么' }).fill('这是一段尚未发送的本地草稿');
|
|
const previousFocus = await split.getAttribute('data-focus');
|
|
const previousPanel = await split.getAttribute('data-compact-panel');
|
|
const trigger = page.getByRole('button', { name: '我的作品', exact: true });
|
|
await trigger.click();
|
|
const drawer = page.getByTestId('design-my-works-drawer');
|
|
await expect(drawer).toBeVisible();
|
|
const image = drawer.getByRole('button', { name: '查看图片:我的游戏小世界', exact: true });
|
|
const video = drawer.getByRole('button', { name: '查看视频:机器人动起来了', exact: true });
|
|
await expect(image).toBeVisible();
|
|
await expect(video).toBeVisible();
|
|
await expect(image.getByText('图片', { exact: true })).toBeVisible();
|
|
await expect(video.getByText('视频', { exact: true })).toBeVisible();
|
|
await expect(video.getByText('00:10', { exact: true })).toBeVisible();
|
|
await expect(image.locator('img')).toBeVisible();
|
|
const drawerBox = (await drawer.boundingBox())!;
|
|
expect(drawerBox.x).toBeGreaterThanOrEqual(-1);
|
|
expect(drawerBox.x + drawerBox.width).toBeLessThanOrEqual(viewport.width + 1);
|
|
expect(drawerBox.height).toBeLessThanOrEqual(viewport.height + 1);
|
|
const firstBox = (await image.boundingBox())!;
|
|
const secondBox = (await video.boundingBox())!;
|
|
expect(Math.abs(firstBox.y - secondBox.y)).toBeLessThanOrEqual(1);
|
|
expect(secondBox.x).toBeGreaterThan(firstBox.x + firstBox.width);
|
|
expect(await drawer.evaluate((node) => node.scrollWidth <= node.clientWidth)).toBe(true);
|
|
const footerBox = (await drawer.locator('.my-works-footer').boundingBox())!;
|
|
for (const tile of await drawer.getByRole('button', { name: /^查看/ }).all()) {
|
|
const tileBox = (await tile.boundingBox())!;
|
|
expect(tileBox.y + tileBox.height).toBeLessThanOrEqual(footerBox.y);
|
|
}
|
|
await page.screenshot({ path: testInfo.outputPath(`canvas-my-works-${viewport.width}-list.png`), fullPage: true });
|
|
|
|
const filters = drawer.getByRole('group', { name: '作品类型' });
|
|
await filters.getByRole('button', { name: '视频', exact: true }).click();
|
|
await expect(drawer.getByRole('button', { name: /^查看视频/ })).toHaveCount(3);
|
|
await expect(drawer.getByRole('button', { name: /^查看图片/ })).toHaveCount(0);
|
|
await video.click();
|
|
const preview = drawer.getByTestId('my-works-preview');
|
|
await expect(preview.locator('video')).toHaveAttribute('controls', '');
|
|
await expect(preview.locator('video')).not.toHaveAttribute('autoplay', '');
|
|
await expect(page.getByRole('dialog')).toHaveCount(1);
|
|
await expect(drawer.getByRole('button', { name: '保存到电脑', exact: true })).toBeVisible();
|
|
await page.screenshot({ path: testInfo.outputPath(`canvas-my-works-${viewport.width}-video-preview.png`), fullPage: true });
|
|
await drawer.getByRole('button', { name: '返回作品', exact: true }).click();
|
|
await filters.getByRole('button', { name: '图片', exact: true }).click();
|
|
await expect(drawer.getByRole('button', { name: /^查看图片/ })).toHaveCount(3);
|
|
await image.click();
|
|
await expect(preview.locator('img')).toBeVisible();
|
|
await drawer.getByRole('button', { name: '返回作品', exact: true }).click();
|
|
await page.keyboard.press('Escape');
|
|
await expect(drawer).toHaveCount(0);
|
|
await expect(trigger).toBeFocused();
|
|
await expect(split).toHaveAttribute('data-focus', previousFocus!);
|
|
await expect(split).toHaveAttribute('data-compact-panel', previousPanel!);
|
|
await expect(page.getByRole('textbox', { name: '告诉 AI 你想创作什么' })).toHaveValue('这是一段尚未发送的本地草稿');
|
|
await expect.poll(() => page.evaluate('window.__canvasMyWorksQA.state().draft')).toBe('这是一段尚未发送的本地草稿');
|
|
|
|
// Real return-to-source callback guards unsent drafts and then selects the
|
|
// actual fixture Workspace, opens its task record, and exposes compact works.
|
|
await trigger.click();
|
|
await drawer.getByRole('button', { name: '查看图片:出发去冒险', exact: true }).click();
|
|
await drawer.getByRole('button', { name: '回到这次创作', exact: true }).click();
|
|
await expect(drawer.getByRole('alert')).toHaveText('当前创作还有未发送或未保存的内容,请先回到工作区处理,再切换项目。');
|
|
await expect.poll(() => page.evaluate('window.__canvasMyWorksQA.state().workspaceId')).toBe('qa-workspace-1');
|
|
await drawer.getByRole('button', { name: '关闭我的作品', exact: true }).click();
|
|
await expect(drawer).toHaveCount(0);
|
|
await page.getByRole('textbox', { name: '告诉 AI 你想创作什么' }).fill('');
|
|
await trigger.click();
|
|
await drawer.getByRole('button', { name: '查看图片:出发去冒险', exact: true }).click();
|
|
await drawer.getByRole('button', { name: '回到这次创作', exact: true }).click();
|
|
await expect(drawer).toHaveCount(0);
|
|
await expect.poll(() => page.evaluate('window.__canvasMyWorksQA.state().workspaceId')).toBe('qa-workspace-2');
|
|
await expect(split).toHaveAttribute('data-focus', '');
|
|
await expect(split).toHaveAttribute('data-compact-panel', 'works');
|
|
const record = page.getByTestId('design-plan-history-qa-task-3');
|
|
await expect(record).toBeVisible();
|
|
await expect(record).toHaveAttribute('open', '');
|
|
await page.screenshot({ path: testInfo.outputPath(`canvas-my-works-${viewport.width}-source.png`), fullPage: true });
|
|
expect(pageErrors).toEqual([]);
|
|
expect(unexpectedRequests).toEqual([]);
|
|
});
|
|
}
|