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, title: string) { const bootstrap = await request.get('/api/v1/bootstrap') expect(bootstrap.ok(), await bootstrap.text()).toBeTruthy() const inbox = (await bootstrap.json()).lists.find((item: { is_inbox: boolean }) => item.is_inbox) const response = await request.post('/api/v1/tasks', { data: { title, list_id: inbox.id }, headers: { 'x-csrf-token': await csrf(request), origin: baseURL }, }) expect(response.ok(), await response.text()).toBeTruthy() } async function dragSeparator(page: Page, label: string, deltaX: number) { const separator = page.getByRole('separator', { name: label }) const box = await separator.boundingBox() expect(box).not.toBeNull() const x = box!.x + box!.width / 2 const y = box!.y + Math.min(120, box!.height / 2) await page.mouse.move(x, y) await page.mouse.down() await page.mouse.move(x + deltaX, y, { steps: 5 }) await page.mouse.up() } test('desktop panes resize by pointer and keyboard and restore after reload', async ({ page, request, baseURL }, testInfo) => { test.skip((page.viewportSize()?.width ?? 0) <= 930, 'desktop-only behavior') const title = `三栏拖动-${testInfo.project.name}-${Date.now()}` await createTask(request, baseURL!, title) await page.goto('/') const sidebar = page.locator('.sidebar') const main = page.locator('main') const sidebarSeparator = page.getByRole('separator', { name: '调整菜单栏宽度' }) await expect(sidebarSeparator).toBeVisible() await expect(sidebarSeparator).toHaveAttribute('aria-valuenow', '236') const sidebarBefore = await sidebar.boundingBox() await dragSeparator(page, '调整菜单栏宽度', 64) const sidebarDraggedWidth = Number(await sidebarSeparator.getAttribute('aria-valuenow')) expect(sidebarDraggedWidth - sidebarBefore!.width).toBeGreaterThanOrEqual(63) expect(sidebarDraggedWidth - sidebarBefore!.width).toBeLessThanOrEqual(65) await expect(sidebar).toHaveCSS('width', `${sidebarDraggedWidth}px`) const sidebarAfter = await sidebar.boundingBox() expect((await main.boundingBox())!.x).toBeCloseTo(sidebarAfter!.x + sidebarAfter!.width, 0) await sidebarSeparator.press('ArrowLeft') const sidebarKeyboardWidth = sidebarDraggedWidth - 12 await expect(sidebarSeparator).toHaveAttribute('aria-valuenow', String(sidebarKeyboardWidth)) await expect(sidebar).toHaveCSS('width', `${sidebarKeyboardWidth}px`) await sidebar.getByRole('button', { name: '收集箱', exact: true }).click() const row = page.locator('.task-row').filter({ has: page.locator('strong', { hasText: title }) }) await expect(row).toHaveCount(1) await row.locator('.task-main').click() const detail = page.getByRole('dialog', { name: '任务详情' }) const detailSeparator = page.getByRole('separator', { name: '调整任务详情宽度' }) await expect(detailSeparator).toBeVisible() const detailBefore = await detail.boundingBox() await dragSeparator(page, '调整任务详情宽度', -70) const detailAfter = await detail.boundingBox() const expectedDetailWidth = Math.min(detailBefore!.width + 70, (page.viewportSize()?.width ?? 0) - sidebarKeyboardWidth - 330) expect(detailAfter!.width).toBeCloseTo(expectedDetailWidth, 0) const mainAfter = await main.boundingBox() expect(mainAfter!.x + mainAfter!.width).toBeCloseTo(detailAfter!.x, 0) const widths = await page.evaluate(() => ({ sidebar: localStorage.getItem('dodo.desktop-pane.sidebar'), detail: localStorage.getItem('dodo.desktop-pane.detail'), })) expect(widths).toEqual({ sidebar: String(Math.round(sidebarKeyboardWidth)), detail: String(Math.round(detailAfter!.width)) }) await page.reload() await expect(sidebar).toHaveCSS('width', `${Math.round(sidebarKeyboardWidth)}px`) const restoredRow = page.locator('.task-row').filter({ has: page.locator('strong', { hasText: title }) }) await restoredRow.locator('.task-main').click() await expect(detail).toHaveCSS('width', `${Math.round(detailAfter!.width)}px`) await page.setViewportSize({ width: 930, height: 900 }) await expect(sidebarSeparator).toBeHidden() await expect(detailSeparator).toBeHidden() })