[verified] redesign trash with deadline groups
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
import type { APIRequestContext, Page } from '@playwright/test'
|
||||
import { expect, test } from './fixtures'
|
||||
|
||||
async function csrf(request: APIRequestContext) {
|
||||
const state = await request.storageState()
|
||||
return state.cookies.find(cookie => cookie.name === 'dodo_csrf')?.value ?? ''
|
||||
}
|
||||
|
||||
async function mutate(request: APIRequestContext, baseURL: string, path: string, options: Parameters<APIRequestContext['fetch']>[1]) {
|
||||
return request.fetch(path, { ...options, headers: { ...options?.headers, 'x-csrf-token': await csrf(request), origin: baseURL } })
|
||||
}
|
||||
|
||||
async function openTrash(page: Page) {
|
||||
if ((await page.viewportSize())!.width <= 930) {
|
||||
await page.locator('.topbar').getByRole('button', { name: /展开菜单|收起菜单/ }).click()
|
||||
}
|
||||
await page.locator('.sidebar').getByRole('button', { name: '回收站', exact: true }).click()
|
||||
}
|
||||
|
||||
test('Trash uses compact deadline groups without exposing child-level actions', async ({ page, request, baseURL }) => {
|
||||
const suffix = `${test.info().project.name}-${Date.now()}`
|
||||
const bootstrap = await request.get('/api/v1/bootstrap')
|
||||
const inbox = (await bootstrap.json()).lists.find((item: { is_inbox: boolean }) => item.is_inbox)
|
||||
expect(inbox).toBeTruthy()
|
||||
|
||||
const createDeleted = async (title: string, dueAt?: string) => {
|
||||
const created = await mutate(request, baseURL!, '/api/v1/tasks', {
|
||||
method: 'POST', data: { title, list_id: inbox.id, ...(dueAt ? { due_at: dueAt, due_has_time: false } : {}) },
|
||||
})
|
||||
expect(created.ok(), await created.text()).toBeTruthy()
|
||||
const task = await created.json() as { id: string }
|
||||
expect((await mutate(request, baseURL!, `/api/v1/tasks/${task.id}`, { method: 'DELETE' })).ok()).toBeTruthy()
|
||||
return task
|
||||
}
|
||||
|
||||
const overdueTitle = `回收站过期-${suffix}`
|
||||
const futureTitle = `回收站未来-${suffix}`
|
||||
const undatedTitle = `回收站无日期-${suffix}`
|
||||
await createDeleted(overdueTitle, '2026-01-02T15:59:00.000Z')
|
||||
await createDeleted(futureTitle, '2099-12-30T15:59:00.000Z')
|
||||
await createDeleted(undatedTitle)
|
||||
|
||||
await page.goto('/')
|
||||
await openTrash(page)
|
||||
|
||||
await expect(page.locator('.trash-page-context')).toContainText('删除的任务保留在这里,可整组恢复或永久删除。')
|
||||
for (const group of ['已过期', '未来截止', '无截止日期']) {
|
||||
await expect(page.getByRole('heading', { name: group, exact: true })).toBeVisible()
|
||||
}
|
||||
for (const title of [overdueTitle, futureTitle, undatedTitle]) {
|
||||
const row = page.locator('.task-row--trash').filter({ hasText: title })
|
||||
await expect(row).toHaveCount(1)
|
||||
await expect(row.getByRole('button', { name: '恢复' })).toBeVisible()
|
||||
await expect(row.getByRole('button', { name: '永久删除' })).toBeVisible()
|
||||
expect(await row.locator('.task-check').count()).toBe(0)
|
||||
}
|
||||
await expect(page.locator('.trash-safety-note')).toContainText('不支持子任务脱离父任务单独恢复或删除')
|
||||
|
||||
const geometry = await page.evaluate(() => ({
|
||||
viewport: innerWidth,
|
||||
document: document.documentElement.scrollWidth,
|
||||
controls: [...document.querySelectorAll<HTMLElement>('.trash-list button')].map(button => {
|
||||
const rect = button.getBoundingClientRect()
|
||||
return { width: rect.width, height: rect.height }
|
||||
}),
|
||||
}))
|
||||
expect(geometry.document).toBe(geometry.viewport)
|
||||
for (const control of geometry.controls) {
|
||||
expect(control.width).toBeGreaterThanOrEqual(44)
|
||||
expect(control.height).toBeGreaterThanOrEqual(44)
|
||||
}
|
||||
})
|
||||
@@ -101,6 +101,9 @@ test('task rows use the body for detail and Trash keeps distinct actions', async
|
||||
await page.getByRole('button', { name: '关闭详情' }).click()
|
||||
|
||||
await openSidebarView(page, '回收站')
|
||||
await expect(page.locator('.trash-page-context')).toContainText('删除的任务保留在这里,可整组恢复或永久删除。')
|
||||
await expect(page.getByRole('heading', { name: '无截止日期', exact: true })).toBeVisible()
|
||||
await expect(page.locator('.trash-safety-note')).toContainText('不支持子任务脱离父任务单独恢复或删除')
|
||||
const restoreRow = await taskRow(page, restoreTitle)
|
||||
const purgeRow = await taskRow(page, purgeTitle)
|
||||
for (const deletedRow of [restoreRow, purgeRow]) {
|
||||
|
||||
Reference in New Issue
Block a user