50c59ca9d4
Co-Authored-By: Claude Code <noreply@anthropic.com>
120 lines
6.1 KiB
TypeScript
120 lines
6.1 KiB
TypeScript
// 相册管理 e2e(真实后端 + compose 基础设施):登录 → 创建(zh+en)→ 列表可见 →
|
||
// 编辑开关 → 标签更新;详情页:成员邀请(账号前缀搜索种子 staff)→ 分类创建 →
|
||
// banner 直传(init→PUT→complete)预览 → 管理照片列表(种子照片状态)→ 隐藏。
|
||
// 选择器一律 data-test(test.use testIdAttribute),与文案解耦。
|
||
import { expect, test, type Page } from '@playwright/test'
|
||
import { adminCredentials, loginAsAdmin, seedFixture } from './helpers'
|
||
|
||
test.use({ testIdAttribute: 'data-test' })
|
||
|
||
test.beforeAll(() => {
|
||
// 幂等种子 staff 账号(已存在则跳过;密码占位不可登录,仅用于邀请)
|
||
seedFixture('staff', 'staff-e2e', 'Staff E2E')
|
||
})
|
||
|
||
/** UI 创建相册(zh+en 标题),返回标题后缀 */
|
||
async function createAlbumViaUi(page: Page): Promise<string> {
|
||
const suffix = Date.now().toString(36) + Math.random().toString(36).slice(2, 6)
|
||
await page.getByTestId('album-create-btn').click()
|
||
await expect(page.getByTestId('album-form-dialog')).toBeVisible()
|
||
await page.getByTestId('album-form-title-zh-CN').fill(`E2E相册 ${suffix}`)
|
||
// 非激活页签的内容被隐藏(v-show):先切到英文页签再填写
|
||
await page.getByRole('tab', { name: '英文' }).click()
|
||
await page.getByTestId('album-form-title-en').fill(`E2E Album ${suffix}`)
|
||
// ElDatePicker 透传 attr 被 ElTooltip 吞掉:组件里用普通 div 挂 data-test,这里进 div 找 input
|
||
await page.getByTestId('album-form-start-at').locator('input').fill('2026-10-01 10:00:00')
|
||
await page.keyboard.press('Enter')
|
||
await page.getByTestId('album-form-submit').click()
|
||
await expect(page.getByTestId('album-form-dialog')).toBeHidden()
|
||
await expect(page.getByTestId('album-list-table').getByText(`E2E相册 ${suffix}`)).toBeVisible()
|
||
return suffix
|
||
}
|
||
|
||
/** 列表内定位目标相册行 */
|
||
function albumRow(page: Page, suffix: string) {
|
||
return page.getByTestId('album-list-table').locator('tr', { hasText: `E2E相册 ${suffix}` })
|
||
}
|
||
|
||
test('创建相册(zh+en)→ 列表可见 → 关闭上传开关 → 标签更新', async ({ page }) => {
|
||
await loginAsAdmin(page)
|
||
const suffix = await createAlbumViaUi(page)
|
||
|
||
const row = albumRow(page, suffix)
|
||
await row.getByTestId('album-edit-btn').click()
|
||
await expect(page.getByTestId('album-form-dialog')).toBeVisible()
|
||
await page.getByTestId('album-form-switch-upload').click()
|
||
await page.getByTestId('album-form-submit').click()
|
||
await expect(page.getByTestId('album-form-dialog')).toBeHidden()
|
||
|
||
await expect(row.getByTestId('album-switch-upload')).toContainText('关')
|
||
})
|
||
|
||
test('详情:邀请成员 → 建分类 → 传 banner → 照片管理(隐藏)', async ({ page }) => {
|
||
await loginAsAdmin(page)
|
||
const suffix = await createAlbumViaUi(page)
|
||
|
||
// ── 进入详情 ──
|
||
await albumRow(page, suffix).getByTestId('album-detail-btn').click()
|
||
await expect(page.getByTestId('album-detail-card')).toBeVisible()
|
||
const albumId = /\/albums\/detail\/([^/?#]+)/.exec(page.url())?.[1] ?? ''
|
||
expect(albumId).not.toBe('')
|
||
|
||
// ── 成员:前缀搜索种子 staff 账号并邀请 ──
|
||
await page.getByTestId('album-members-tab').click()
|
||
const searchSelect = page.getByTestId('member-search-select')
|
||
await searchSelect.click()
|
||
await searchSelect.locator('input').fill('staff-e2e')
|
||
await page.getByTestId('member-option-staff-e2e').click()
|
||
await page.getByTestId('member-invite-btn').click()
|
||
await expect(page.getByTestId('member-list-table').getByText('staff-e2e')).toBeVisible()
|
||
// owner 徽标(admin 自己)可见
|
||
await expect(
|
||
page.getByTestId('member-list-table').getByTestId('member-role-tag').first()
|
||
).toBeVisible()
|
||
|
||
// ── 分类:zh/en 名称 ──
|
||
await page.getByTestId('album-categories-tab').click()
|
||
await page.getByTestId('category-create-btn').click()
|
||
await page.getByTestId('category-form-name-zh').fill(`E2E分类 ${suffix}`)
|
||
await page.getByTestId('category-form-name-en').fill(`E2E Category ${suffix}`)
|
||
await page.getByTestId('category-form-submit').click()
|
||
await expect(page.getByTestId('category-form-dialog')).toBeHidden()
|
||
await expect(page.getByTestId('category-list-table').getByText(`E2E分类 ${suffix}`)).toBeVisible()
|
||
|
||
// ── banner:真实小 jpeg 走 file chooser → init/PUT/complete → 预览 ──
|
||
const fileChooserPromise = page.waitForEvent('filechooser')
|
||
await page.getByTestId('album-banner-pick').click()
|
||
const fileChooser = await fileChooserPromise
|
||
await fileChooser.setFiles({
|
||
name: 'banner-e2e.jpg',
|
||
mimeType: 'image/jpeg',
|
||
buffer: Buffer.from(
|
||
'/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwcJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPDs0NDT/wAALCAABAAEBAREA/8QAFAABAQAAAAAAAAAAAAAAAAAAAAv/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8AmgA//9k=',
|
||
'base64'
|
||
)
|
||
})
|
||
await expect(page.getByTestId('album-banner-status-done')).toBeVisible({ timeout: 20_000 })
|
||
await expect(page.getByTestId('album-banner-preview-img')).toBeVisible()
|
||
|
||
// ── 照片管理:直种两种状态 → 列表可见 → 隐藏已发布照片 ──
|
||
seedFixture('photos', albumId, adminCredentials().account)
|
||
await page.reload()
|
||
await expect(page.getByTestId('photo-list-table')).toBeVisible()
|
||
|
||
// 用处理状态标签(就绪)锚定行:隐藏后行的可见性文案变化,锚点保持稳定
|
||
const publishedRow = page
|
||
.getByTestId('photo-list-table')
|
||
.locator('tr')
|
||
.filter({ has: page.getByTestId('photo-state-tag').filter({ hasText: '就绪' }) })
|
||
.first()
|
||
await expect(publishedRow.getByTestId('photo-state-tag')).toHaveText('就绪')
|
||
await expect(publishedRow.getByTestId('photo-visibility-tag')).toHaveText('已发布')
|
||
|
||
await publishedRow.getByTestId('photo-hide-btn').click()
|
||
await page.getByRole('button', { name: '确定' }).click()
|
||
await expect(publishedRow.getByTestId('photo-visibility-tag')).toHaveText('已隐藏')
|
||
|
||
// 处理失败状态标签也在列(种子第二行)
|
||
await expect(page.getByTestId('photo-list-table').getByText('处理失败')).toBeVisible()
|
||
})
|