import { Page, expect } from '@playwright/test'; export interface ContentData { type: 'news' | 'product' | 'service' | 'case'; title: string; slug: string; excerpt?: string; content?: string; category?: string; tags?: string[]; status?: 'draft' | 'published' | 'archived'; } export class AdminContentPage { constructor(private page: Page) {} async goto() { await this.page.goto('/admin/content'); await this.page.waitForLoadState('networkidle'); } async gotoCreate() { await this.page.goto('/admin/content/new'); await this.page.waitForLoadState('domcontentloaded'); await this.page.waitForSelector('input[placeholder="请输入标题"]', { timeout: 60000 }); } async createContent(data: ContentData): Promise { await this.gotoCreate(); await this.page.fill('input[placeholder="请输入标题"]', data.title); await this.page.fill('input[placeholder="url-slug"]', data.slug); if (data.excerpt) { await this.page.fill('textarea', data.excerpt); } if (data.type) { await this.page.locator('select').first().selectOption(data.type); } if (data.status) { await this.page.locator('select').nth(1).selectOption(data.status); } if (data.category) { await this.page.fill('input[placeholder="分类名称"]', data.category); } await this.page.click('button:has-text("发布")'); await this.page.waitForURL(/\/admin\/content\/[a-zA-Z0-9]+/, { timeout: 15000 }); const url = this.page.url(); const match = url.match(/\/admin\/content\/([a-zA-Z0-9]+)/); return match ? match[1] : null; } async deleteContent(contentId: string) { await this.goto(); const row = this.page.locator(`tr:has-text("${contentId}")`); if (await row.count() > 0) { await row.locator('button:has-text("删除")').click(); await this.page.locator('button:has-text("确认"), button:has-text("确定")').click(); await this.page.waitForResponse(resp => resp.url().includes('/api/admin/content') && resp.request().method() === 'DELETE', { timeout: 10000 } ); } } async expectContentInList(title: string) { await this.goto(); const row = this.page.locator(`tr:has-text("${title}")`); await expect(row).toBeVisible(); } async expectContentNotInList(title: string) { await this.goto(); const row = this.page.locator(`tr:has-text("${title}")`); await expect(row).not.toBeVisible(); } }