Files
photo-live/apps/admin/e2e/albums.spec.ts
T
浅念 4f6790d630 feat(ui06): B2 shared components + B3a core pages — album cards, photo grid, viewer, summary header
- 类型补齐契约字段:Summary.cover / AdminPhoto.preview(SignedUrl;服务端已返回,B0 核对)
- AlbumCoverCard:封面卡(公开/状态/上传 pill,无封面中性占位,不显示 owner 名)
- 相册列表:默认封面卡片网格(3列/1700+4列)+ 表格切换 + 已加载内搜索 + 公开状态筛选 + 摘要行
- AlbumSummaryHeader:300×144 封面 + 两列紧凑资料 + 高级折叠(ownerId/统计时间收敛)
- 详情页壳:页头(编辑/分享固定主操作)替换 ElDescriptions 大区;banner 区 B3c 收纳
- PhotoGrid + PhotoPreviewDialog:照片网格默认(preview.thumb 签名 URL)+ 深色大图(browse URL、
  行内隐藏/恢复/软删除复用表格状态机);网格勾选与表格 selection 合并批量目标
- e2e 适配默认网格视图(albums/governance 断言前切表格);batchHide fixture 补 preview
- typecheck/lint/vitest 87 项全绿

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-22 23:19:21 +08:00

124 lines
6.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 相册管理 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()
// UI06:列表默认封面卡片网格;表格断言前先切换
await page.getByTestId('album-view-table').click()
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()
// UI06:照片默认网格视图;表格断言前先切换
await page.getByTestId('photo-view-table').click()
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()
})