/** * 1080P E2E — 针对**测试服**(airflow-studio.test.airlabs.art)使用团管账号 tudou。 * 这是对 resolution-1080p.spec.ts 的测试服版本,验证 CI/CD 部署后线上真实行为。 */ import { test, expect, Page } from '@playwright/test'; const BASE_URL = 'https://airflow-studio.test.airlabs.art'; const API_URL = 'https://airflow-studio-api.test.airlabs.art'; const USERNAME = 'tudou'; const PASSWORD = 'seaislee'; async function login(page: Page) { const resp = await page.request.post(`${API_URL}/api/v1/auth/login`, { data: { username: USERNAME, password: PASSWORD }, }); if (!resp.ok()) { const err = await resp.text(); throw new Error(`Login failed: ${resp.status()} ${err}`); } const body = await resp.json(); await page.goto(BASE_URL); await page.evaluate(({ access, refresh }) => { localStorage.setItem('access_token', access); localStorage.setItem('refresh_token', refresh); }, { access: body.tokens.access, refresh: body.tokens.refresh }); await page.goto(`${BASE_URL}/app`); await page.waitForTimeout(2000); // 关闭公告 const knowBtn = page.getByRole('button', { name: /我知道了|知道了|关闭/ }).first(); if (await knowBtn.isVisible().catch(() => false)) { await knowBtn.click(); await page.waitForTimeout(300); } } test.describe.serial('[测试服] 1080P 分辨率支持 — tudou 团管账号', () => { test('Sidebar 显示「今日剩余次数」(无钻石图标)', async ({ page }) => { await login(page); // 含"今日剩余次数"文案 await expect(page.getByText('今日剩余次数')).toBeVisible(); // 确认钻石 SVG 不存在(旧的 diamond path) const diamondPath = page.locator('path[d^="M6 3h12l4 8"]'); expect(await diamondPath.count()).toBe(0); }); test('Toolbar 默认分辨率显示 720P', async ({ page }) => { await login(page); const resolutionBtn = page.getByRole('button', { name: '720P', exact: true }).first(); await expect(resolutionBtn).toBeVisible(); }); test('AirDrama 模式可切换到 1080P', async ({ page }) => { await login(page); await page.getByRole('button', { name: '720P', exact: true }).first().click(); await page.waitForTimeout(200); await page.getByText('1080P', { exact: true }).click(); await page.waitForTimeout(300); await expect(page.getByRole('button', { name: '1080P', exact: true }).first()).toBeVisible(); }); test('1080P 下 Fast 模型在 Dropdown 中置灰', async ({ page }) => { await login(page); // 先切 1080P await page.getByRole('button', { name: '720P', exact: true }).first().click(); await page.waitForTimeout(200); await page.getByText('1080P', { exact: true }).click(); await page.waitForTimeout(300); // 打开模型 Dropdown await page.getByRole('button', { name: /AirDrama$/, exact: false }).first().click(); await page.waitForTimeout(200); // Fast 项应带"不支持 1080P" await expect(page.getByText(/AirDrama Fast.*不支持 1080P/)).toBeVisible(); }); test('Fast 模式下 1080P 在 Dropdown 中置灰', async ({ page }) => { await login(page); // 切 Fast 模型 await page.getByRole('button', { name: /AirDrama$/, exact: false }).first().click(); await page.waitForTimeout(200); await page.getByText('AirDrama Fast', { exact: true }).click(); await page.waitForTimeout(300); // 打开分辨率 Dropdown await page.getByRole('button', { name: '720P', exact: true }).first().click(); await page.waitForTimeout(200); // 1080P 项应带"Fast 不支持" await expect(page.getByText(/1080P.*Fast 不支持/)).toBeVisible(); }); test('ProfilePage 预警文案显示「今日生成次数」而非「额度」', async ({ page }) => { await login(page); await page.goto(`${BASE_URL}/profile`); await page.waitForTimeout(1500); // Page 应不含"今日额度"这种老文案 const body = await page.textContent('body'); // 能找到"今日"相关字样,不是"额度" if (body && body.includes('今日')) { // 如果出现"今日",必须是跟"次数"搭配,不是跟"额度" expect(body).not.toMatch(/今日额度/); } }); test('提交 Fast+1080P 组合被后端 400 拒绝', async ({ page }) => { await login(page); // 直接调 API 测试(绕过前端 UI 约束,验证后端 fail loud) const loginResp = await page.request.post(`${API_URL}/api/v1/auth/login`, { data: { username: USERNAME, password: PASSWORD }, }); const { tokens } = await loginResp.json(); const resp = await page.request.post(`${API_URL}/api/v1/video/generate`, { headers: { Authorization: `Bearer ${tokens.access}` }, data: { prompt: 'E2E 测试 Fast+1080P', mode: 'universal', model: 'seedance_2.0_fast', aspect_ratio: '16:9', duration: 5, resolution: '1080p', references: [], }, }); expect(resp.status()).toBe(400); const body = await resp.json(); expect(body.error).toBe('invalid_resolution'); expect(body.message).toContain('1080P'); expect(body.message).toContain('Fast'); }); test('提交 adaptive ratio 被后端 400 拒绝', async ({ page }) => { await login(page); const loginResp = await page.request.post(`${API_URL}/api/v1/auth/login`, { data: { username: USERNAME, password: PASSWORD }, }); const { tokens } = await loginResp.json(); const resp = await page.request.post(`${API_URL}/api/v1/video/generate`, { headers: { Authorization: `Bearer ${tokens.access}` }, data: { prompt: 'E2E adaptive', mode: 'universal', model: 'seedance_2.0', aspect_ratio: 'adaptive', duration: 5, resolution: '720p', references: [], }, }); expect(resp.status()).toBe(400); }); });