feat: simplify today into plain list
ci / gitleaks (push) Successful in 10s
ci / docker (push) Successful in 7m27s

This commit is contained in:
2026-09-17 18:04:40 +08:00
parent 73aca652f1
commit 66589dd458
9 changed files with 228 additions and 143 deletions
+34 -29
View File
@@ -20,42 +20,47 @@ async function assertInsideViewport(locator: Locator, page: Page) {
expect(box!.y + box!.height).toBeLessThanOrEqual(viewport!.height + 1)
}
test('Today paper composition has no overlap or horizontal overflow', async ({ page }) => {
test('Today plain-list composition has no overlap or horizontal overflow', async ({ page }) => {
await page.goto('/')
await expect(await bottomTab(page, '今天')).toHaveAttribute('aria-current', 'page')
const board = page.locator('.today-board')
const environment = page.locator('.today-environment')
const tracks = board.locator('.today-track')
await expect(board).toBeVisible()
await expect(environment).toBeVisible()
await expect(tracks).toHaveCount(2)
const geometry = await board.evaluate((node) => {
const boardRect = node.getBoundingClientRect()
const environmentRect = node.querySelector('.today-environment')!.getBoundingClientRect()
const trackRects = [...node.querySelectorAll('.today-track')].map(item => item.getBoundingClientRect())
const context = page.locator('.today-context')
const environment = page.locator('.today-environment')
const title = page.locator('.today-page-title')
const remaining = page.locator('.today-remaining')
const filter = page.locator('.today-inline-filter')
const firstSection = page.locator('.today-section-toggle').first()
for (const locator of [context, environment, title, remaining, filter, firstSection]) {
await expect(locator).toBeVisible()
}
const geometry = await page.locator('main').evaluate((main) => {
const selectors = ['.today-environment', '.today-page-title', '.today-remaining', '.today-inline-filter', '.today-section-toggle']
const rects = selectors.map(selector => main.querySelector(selector)!.getBoundingClientRect())
const context = main.querySelector('.today-context')!
const contextRect = context.getBoundingClientRect()
return {
boardRight: boardRect.right,
boardBottom: boardRect.bottom,
boardScrollWidth: node.scrollWidth,
boardClientWidth: node.clientWidth,
environmentBottom: environmentRect.bottom,
trackTops: trackRects.map(rect => rect.top),
trackRights: trackRects.map(rect => rect.right),
trackBottoms: trackRects.map(rect => rect.bottom),
mainScrollWidth: main.scrollWidth,
mainClientWidth: main.clientWidth,
contextScrollWidth: context.scrollWidth,
contextClientWidth: context.clientWidth,
contextLeft: contextRect.left,
contextRight: contextRect.right,
rects: rects.map(rect => ({ left: rect.left, right: rect.right, top: rect.top, bottom: rect.bottom, width: rect.width, height: rect.height })),
}
})
expect(geometry.boardScrollWidth).toBeLessThanOrEqual(geometry.boardClientWidth)
expect(Math.min(...geometry.trackTops)).toBeGreaterThanOrEqual(geometry.environmentBottom - 1)
expect(Math.max(...geometry.trackRights)).toBeLessThanOrEqual(geometry.boardRight + 1)
expect(Math.max(...geometry.trackBottoms)).toBeLessThanOrEqual(geometry.boardBottom + 1)
for (const track of await tracks.all()) {
const head = track.locator('.today-track-head')
const labels = head.locator('strong, span')
await expect(labels).toHaveCount(2)
const boxes = await labels.evaluateAll(nodes => nodes.map(node => node.getBoundingClientRect()))
expect(Math.abs(boxes[0].top - boxes[1].top)).toBeLessThan(4)
expect(geometry.mainScrollWidth).toBeLessThanOrEqual(geometry.mainClientWidth)
expect(geometry.contextScrollWidth).toBeLessThanOrEqual(geometry.contextClientWidth)
for (const rect of geometry.rects) {
expect(rect.width).toBeGreaterThan(0)
expect(rect.height).toBeGreaterThan(0)
expect(rect.left).toBeGreaterThanOrEqual(geometry.contextLeft - 1)
expect(rect.right).toBeLessThanOrEqual(geometry.contextRight + 1)
}
for (let index = 0; index < geometry.rects.length - 1; index += 1) {
expect(geometry.rects[index].bottom).toBeLessThanOrEqual(geometry.rects[index + 1].top + 1)
}
})
test('Today task persists through detail, completion and reopen', async ({ page }, testInfo) => {