Files
xiaoxia-saas/apps/web/e2e/core-upload.spec.ts
T
2026-06-23 23:12:19 +08:00

121 lines
5.1 KiB
TypeScript

import { expect, test } from '@playwright/test';
const PASSWORD = 'SmokePass123!';
type WorkspaceResponse = { id?: string; workspace_id?: string };
type ProjectResponse = { id: string };
type LibraryResponse = { id: string };
test.describe('Core media upload flow', () => {
test('uploads a MOV asset from the browser and shows it as ready', async ({ page, request }) => {
test.setTimeout(120_000);
const suffix = Date.now().toString(36);
const email = `e2e-mov-${suffix}@example.com`;
const username = `e2e_mov_${suffix}`;
const apiBase = '/api/v1';
const register = await request.post(`${apiBase}/auth/register`, {
data: {
email,
username,
password: PASSWORD,
display_name: username,
},
});
expect(register.status(), await register.text()).toBe(201);
const login = await request.post(`${apiBase}/auth/login`, {
data: { email, password: PASSWORD },
});
expect(login.status(), await login.text()).toBe(200);
const loginData = (await login.json()) as { access_token: string };
const headers = { Authorization: `Bearer ${loginData.access_token}` };
const workspace = await request.post(`${apiBase}/workspaces`, {
headers,
data: { name: `E2E Workspace ${suffix}` },
});
expect(workspace.status(), await workspace.text()).toBe(201);
const workspaceData = (await workspace.json()) as WorkspaceResponse;
const workspaceId = workspaceData.id || workspaceData.workspace_id;
expect(workspaceId).toBeTruthy();
const project = await request.post(`${apiBase}/projects`, {
headers,
data: {
workspace_id: workspaceId,
name: `E2E Project ${suffix}`,
description: 'Playwright upload smoke',
},
});
expect(project.status(), await project.text()).toBe(200);
const projectData = (await project.json()) as ProjectResponse;
const library = await request.post(`${apiBase}/asset-libraries`, {
headers,
data: {
workspace_id: workspaceId,
project_id: projectData.id,
name: `E2E Video Library ${suffix}`,
kind: 'video',
},
});
expect(library.status(), await library.text()).toBe(200);
const libraryData = (await library.json()) as LibraryResponse;
await page.goto('/login');
await page.getByPlaceholder('邮箱').fill(email);
await page.getByPlaceholder('密码').fill(PASSWORD);
await page.getByRole('button', { name: /登\s*录/ }).click();
await expect(page).toHaveURL(/\/workspaces/, { timeout: 20_000 });
await page.goto(`/projects/${projectData.id}/assets`);
const uploadButton = page.getByRole('button', { name: /点击或拖拽文件到这里批量上传素材/ });
await expect(uploadButton).toBeEnabled({ timeout: 20_000 });
const fileInput = page.locator('.ant-upload input[type="file"]:not([disabled])').first();
await expect(fileInput).toBeAttached({ timeout: 20_000 });
const completeResponsePromise = page.waitForResponse(
(response) => response.url().includes('/api/v1/upload/direct/complete') && response.request().method() === 'POST',
{ timeout: 60_000 }
);
await fileInput.setInputFiles({
name: 'e2e-sample.MOV',
mimeType: 'video/quicktime',
buffer: Buffer.from('playwright mov upload smoke'),
});
const completeResponse = await completeResponsePromise;
expect(completeResponse.status(), await completeResponse.text()).toBe(200);
await expect(page.getByText(/上传失败|素材列表加载失败|素材库加载失败/)).toHaveCount(0, { timeout: 5_000 });
await expect
.poll(
async () => {
const assets = await request.get(`${apiBase}/assets`, {
headers,
params: { library_id: libraryData.id },
});
if (!assets.ok()) {
return `http_${assets.status()}`;
}
const data = (await assets.json()) as { items: Array<{ name: string; status: string; file_type?: string; mime_type?: string }> };
const asset = data.items.find((item) => item.name === 'e2e-sample.MOV');
return asset ? `${asset.mime_type || asset.file_type || ''}:${asset.status}` : 'missing';
},
{ timeout: 30_000, intervals: [1_000, 2_000, 3_000] }
)
.toMatch(/^(video\/quicktime|video\/mp4|video)?:ready$/);
await page.reload();
await expect(page.getByText('素材智能诊断')).toBeVisible({ timeout: 20_000 });
await expect(page.getByText(/推荐素材:1/)).toBeVisible({ timeout: 20_000 });
await expect(page.getByText(/视频素材数量偏少|素材准备度良好/)).toBeVisible({ timeout: 20_000 });
await expect(page.getByRole('cell', { name: 'e2e-sample.MOV', exact: true })).toBeVisible({ timeout: 20_000 });
await page.getByRole('row', { name: /e2e-sample\.MOV/ }).getByRole('button', { name: /通\s*过/ }).click();
await expect(page.getByText('复核状态已更新')).toBeVisible({ timeout: 10_000 });
await expect(page.getByText('已通过')).toBeVisible({ timeout: 20_000 });
await expect(page.getByText(/素材列表加载失败|上传失败/)).toHaveCount(0);
});
});