import { test, expect } from '@playwright/test'; import { _electron as electron } from 'playwright'; import { promises as fs } from 'node:fs'; import nodePath from 'node:path'; import os from 'node:os'; const MAIN_JS = nodePath.join(process.cwd(), 'dist-electron/main/index.js'); async function launch(userData: string) { const app = await electron.launch({ args: ['--user-data-dir=' + userData, MAIN_JS] }); const page = await app.firstWindow(); await page.waitForLoadState('domcontentloaded'); const invoke = (ch: string, args: any) => page.evaluate(({ ch, args }) => (globalThis as any).dsh.invoke(ch, args), { ch, args }); return { app, page, invoke }; } async function newDoc(a: { page: any; invoke: any }, title: string) { await a.page.getByRole('button', { name: /新建文档/ }).click(); await a.page.getByPlaceholder(/输入文档标题/).fill(title); await a.page.getByPlaceholder(/输入文档标题/).press('Enter'); await expect(a.page.getByTestId('tabbar').getByText(title, { exact: true })).toBeVisible({ timeout: 10000 }); } // FR-T6/W6:标签栏可隐藏/显示 test('FR-T6/W6:标签栏可隐藏/显示', async () => { const tmp = await fs.mkdtemp(nodePath.join(os.tmpdir(), 'hn-t6-')); const ud = nodePath.join(tmp, 'ud'); const v = nodePath.join(tmp, 'v'); await fs.mkdir(ud, { recursive: true }); await fs.mkdir(v, { recursive: true }); const a = await launch(ud); await a.invoke('vault:switch', { root: v }); await newDoc(a, 'T6doc'); // 标签栏应可见 await expect(a.page.getByTestId('tabbar')).toBeVisible(); // 点击切换按钮隐藏 await a.page.getByTestId('tabbar-toggle').click(); await a.page.waitForTimeout(300); // 标签栏应隐藏 await expect(a.page.getByTestId('tabbar')).toHaveCount(0, { timeout: 3000 }); // 再点显示 await a.page.getByTestId('tabbar-toggle').click(); await a.page.waitForTimeout(300); await expect(a.page.getByTestId('tabbar')).toBeVisible(); await a.app.close(); }); // FR-W7:极简模式隐藏标签栏 test('FR-W7:极简模式隐藏标签栏', async () => { const tmp = await fs.mkdtemp(nodePath.join(os.tmpdir(), 'hn-w7-')); const ud = nodePath.join(tmp, 'ud'); const v = nodePath.join(tmp, 'v'); await fs.mkdir(ud, { recursive: true }); await fs.mkdir(v, { recursive: true }); const a = await launch(ud); await a.invoke('vault:switch', { root: v }); await newDoc(a, 'W7doc'); await expect(a.page.getByTestId('tabbar')).toBeVisible(); // 点击极简模式 await a.page.getByTitle('极简模式').click(); await a.page.waitForTimeout(300); // 标签栏应隐藏 await expect(a.page.getByTestId('tabbar')).toHaveCount(0, { timeout: 3000 }); // 退出极简 await a.page.getByTitle('极简模式').click(); await a.page.waitForTimeout(300); await expect(a.page.getByTestId('tabbar')).toBeVisible(); await a.app.close(); }); // FR-W2:最大化按钮图标随状态切换 test('FR-W2:最大化按钮图标切换', async () => { const tmp = await fs.mkdtemp(nodePath.join(os.tmpdir(), 'hn-w2-')); const ud = nodePath.join(tmp, 'ud'); const v = nodePath.join(tmp, 'v'); await fs.mkdir(ud, { recursive: true }); await fs.mkdir(v, { recursive: true }); const a = await launch(ud); await a.invoke('vault:switch', { root: v }); const maxBtn = a.page.getByTestId('maximize-btn'); // 初始可能未最大化(图标按钮无文本,用 innerHTML 比较图标是否切换) const initialText = await maxBtn.innerHTML(); // 点击最大化 await maxBtn.click(); await a.page.waitForTimeout(300); const afterClickText = await maxBtn.innerHTML(); // 图标应变化 expect(initialText).not.toBe(afterClickText); // 再点还原 await maxBtn.click(); await a.page.waitForTimeout(300); const afterRestoreText = await maxBtn.innerHTML(); expect(afterRestoreText).toBe(initialText); await a.app.close(); });