96 lines
4.6 KiB
TypeScript
96 lines
4.6 KiB
TypeScript
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 createTask(request: APIRequestContext, baseURL: string, listId: string, title: string) {
|
|
const response = await request.post('/api/v1/tasks', {
|
|
data: { title, list_id: listId },
|
|
headers: { 'x-csrf-token': await csrf(request), origin: baseURL },
|
|
})
|
|
expect(response.ok(), await response.text()).toBeTruthy()
|
|
}
|
|
|
|
async function openInbox(page: Page) {
|
|
const inbox = page.locator('.sidebar').getByRole('button', { name: '收集箱', exact: true })
|
|
if (await page.evaluate(() => window.innerWidth <= 930)) {
|
|
await page.locator('main .topbar > button').first().click()
|
|
}
|
|
await inbox.click()
|
|
}
|
|
|
|
test('task pagination stays below the list and returns to the list start after navigation', async ({ page, request, baseURL }) => {
|
|
const bootstrapResponse = await request.get('/api/v1/bootstrap')
|
|
expect(bootstrapResponse.ok()).toBeTruthy()
|
|
const inbox = (await bootstrapResponse.json()).lists.find((item: { is_inbox: boolean }) => item.is_inbox)
|
|
expect(inbox).toBeTruthy()
|
|
|
|
for (let index = 1; index <= 51; index += 1) {
|
|
await createTask(request, baseURL!, inbox.id, `分页验收任务 ${String(index).padStart(2, '0')}`)
|
|
}
|
|
|
|
await page.goto('/')
|
|
await openInbox(page)
|
|
|
|
const taskList = page.locator('.task-list')
|
|
const pager = page.locator('.pager')
|
|
await expect(taskList.locator('.task-row')).toHaveCount(50)
|
|
await expect(pager).toBeVisible()
|
|
await expect(pager.locator('.pager-status')).toHaveText('1/ 2')
|
|
|
|
const firstPageGeometry = await page.evaluate(() => {
|
|
const list = document.querySelector<HTMLElement>('.task-list')!.getBoundingClientRect()
|
|
const pagerElement = document.querySelector<HTMLElement>('.pager')!
|
|
const pagerBox = pagerElement.getBoundingClientRect()
|
|
const previous = pagerElement.querySelector<HTMLButtonElement>('.pager-button--previous')!
|
|
const next = pagerElement.querySelector<HTMLButtonElement>('.pager-button--next')!
|
|
const status = pagerElement.querySelector<HTMLElement>('.pager-status')!
|
|
const previousBox = previous.getBoundingClientRect()
|
|
const nextBox = next.getBoundingClientRect()
|
|
const statusBox = status.getBoundingClientRect()
|
|
const pagerCenter = pagerBox.left + pagerBox.width / 2
|
|
return {
|
|
listBottom: list.bottom,
|
|
pagerTop: pagerBox.top,
|
|
previousWidth: previousBox.width,
|
|
nextWidth: nextBox.width,
|
|
previousHeight: previousBox.height,
|
|
nextHeight: nextBox.height,
|
|
statusCenterOffset: Math.abs(statusBox.left + statusBox.width / 2 - pagerCenter),
|
|
rootScrollWidth: document.documentElement.scrollWidth,
|
|
viewportWidth: innerWidth,
|
|
}
|
|
})
|
|
expect(firstPageGeometry.pagerTop).toBeGreaterThanOrEqual(firstPageGeometry.listBottom)
|
|
expect(Math.abs(firstPageGeometry.previousWidth - firstPageGeometry.nextWidth)).toBeLessThanOrEqual(1)
|
|
expect(firstPageGeometry.previousHeight).toBeGreaterThanOrEqual(44)
|
|
expect(firstPageGeometry.nextHeight).toBeGreaterThanOrEqual(44)
|
|
expect(firstPageGeometry.statusCenterOffset).toBeLessThanOrEqual(1)
|
|
expect(firstPageGeometry.rootScrollWidth).toBeLessThanOrEqual(firstPageGeometry.viewportWidth)
|
|
|
|
const nextButton = pager.getByRole('button', { name: '下一页' })
|
|
await page.locator('body').click({ position: { x: 1, y: 1 } })
|
|
for (let index = 0; index < 300; index += 1) {
|
|
await page.keyboard.press('Tab')
|
|
if (await nextButton.evaluate(element => element === document.activeElement)) break
|
|
}
|
|
await expect(nextButton).toBeFocused()
|
|
const focusOutline = await nextButton.evaluate(element => getComputedStyle(element).outlineStyle)
|
|
expect(focusOutline).not.toBe('none')
|
|
await nextButton.click()
|
|
await expect(pager.locator('.pager-status')).toHaveText('2/ 2')
|
|
await expect(taskList.locator('.task-row')).toHaveCount(1)
|
|
|
|
const secondPageGeometry = await page.evaluate(() => {
|
|
const list = document.querySelector<HTMLElement>('.task-list')!.getBoundingClientRect()
|
|
const pagerBox = document.querySelector<HTMLElement>('.pager')!.getBoundingClientRect()
|
|
return { listTop: list.top, listBottom: list.bottom, pagerTop: pagerBox.top, viewportHeight: innerHeight }
|
|
})
|
|
expect(secondPageGeometry.listTop).toBeGreaterThanOrEqual(-1)
|
|
expect(secondPageGeometry.listTop).toBeLessThan(secondPageGeometry.viewportHeight / 2)
|
|
expect(secondPageGeometry.pagerTop).toBeGreaterThanOrEqual(secondPageGeometry.listBottom)
|
|
})
|