84518a783f
Deploy / Build Production Runtime Images (push) Successful in 9m0s
Deploy / Deploy Production (push) Successful in 45s
Deploy / Production Browser E2E (push) Successful in 32s
CI/CD Pipeline / Validate Code Quality And Tests (push) Has been cancelled
Deploy / Deploy Staging (push) Has been skipped
121 lines
5.1 KiB
TypeScript
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);
|
|
});
|
|
});
|