From cbf307507c79c853d135d914ec9558008a99258a Mon Sep 17 00:00:00 2001 From: bboysoul Date: Mon, 21 Sep 2026 06:10:54 +0800 Subject: [PATCH] feat: redesign task pagination controls --- frontend/e2e/task-pagination-position.spec.ts | 42 ++++++++++++++++--- frontend/src/App.vue | 4 +- frontend/src/style.css | 3 +- frontend/src/visual-polish.test.ts | 11 ++++- 4 files changed, 51 insertions(+), 9 deletions(-) diff --git a/frontend/e2e/task-pagination-position.spec.ts b/frontend/e2e/task-pagination-position.spec.ts index 795a68b..32ff66c 100644 --- a/frontend/e2e/task-pagination-position.spec.ts +++ b/frontend/e2e/task-pagination-position.spec.ts @@ -39,17 +39,49 @@ test('task pagination stays below the list and returns to the list start after n const pager = page.locator('.pager') await expect(taskList.locator('.task-row')).toHaveCount(50) await expect(pager).toBeVisible() - await expect(pager).toContainText('1 / 2') + await expect(pager.locator('.pager-status')).toHaveText('1/ 2') const firstPageGeometry = await page.evaluate(() => { const list = document.querySelector('.task-list')!.getBoundingClientRect() - const pagerBox = document.querySelector('.pager')!.getBoundingClientRect() - return { listBottom: list.bottom, pagerTop: pagerBox.top } + const pagerElement = document.querySelector('.pager')! + const pagerBox = pagerElement.getBoundingClientRect() + const previous = pagerElement.querySelector('.pager-button--previous')! + const next = pagerElement.querySelector('.pager-button--next')! + const status = pagerElement.querySelector('.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) - await pager.getByRole('button', { name: '下一页' }).click() - await expect(pager).toContainText('2 / 2') + 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(() => { diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 3da0220..bfc9e95 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -1,7 +1,7 @@