feat(M10/M3/M2): FR-M4/M6/X1/X2/B6/D1/D3 元数据/导出/弹层/迁移——EditorToolbar 加星标按钮(M4); DocMeta 加 createdAt+frontmatter 读写+DocInfoPanel 显示+创建时写入(M6); copyMd 失败 catch+错误提示(X1); @media print 干净排版+hljs配色(X2); SettingsPanel/CheatSheet Esc 关闭(B6); migration-service 旧版板块转换+init+switch 检测(D1/D3); meta-export E2E 3 项
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
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-M4:编辑区星标按钮
|
||||
test('FR-M4:编辑区星标按钮', async () => {
|
||||
const tmp = await fs.mkdtemp(nodePath.join(os.tmpdir(), 'hn-m4-'));
|
||||
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, 'StarTest');
|
||||
await a.page.getByTitle('星标').click();
|
||||
await a.page.waitForTimeout(500);
|
||||
const star = await a.page.evaluate(() => (window as any).__STORE__?.getState?.().meta?.star);
|
||||
expect(star).toBe(true);
|
||||
await a.app.close();
|
||||
});
|
||||
|
||||
// FR-B6:Esc 关闭设置面板
|
||||
test('FR-B6:Esc 关闭设置面板', async () => {
|
||||
const tmp = await fs.mkdtemp(nodePath.join(os.tmpdir(), 'hn-b6-'));
|
||||
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 a.page.getByTitle('设置').click();
|
||||
await a.page.waitForTimeout(500);
|
||||
await a.page.keyboard.press('Escape');
|
||||
await a.page.waitForTimeout(500);
|
||||
await expect(a.page.getByText('设置', { exact: true })).toHaveCount(0, { timeout: 3000 });
|
||||
await a.app.close();
|
||||
});
|
||||
|
||||
// FR-D1:迁移旧版板块数据
|
||||
test('FR-D1:检测并迁移旧版板块数据', async () => {
|
||||
const tmp = await fs.mkdtemp(nodePath.join(os.tmpdir(), 'hn-d1-'));
|
||||
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 oldDir = nodePath.join(v, '.hunter', 'boards', 'MyBoard');
|
||||
await fs.mkdir(oldDir, { recursive: true });
|
||||
await fs.writeFile(nodePath.join(oldDir, 'note.json'), JSON.stringify({ title: 'OldNote', content: 'legacy content', createdAt: 1700000000000 }));
|
||||
const a = await launch(ud);
|
||||
await a.invoke('vault:switch', { root: v });
|
||||
await a.page.waitForTimeout(1000);
|
||||
const convertedDir = nodePath.join(v, 'MyBoard');
|
||||
const files = await fs.readdir(convertedDir).catch(() => []);
|
||||
const mdFiles = files.filter(f => f.endsWith('.md'));
|
||||
expect(mdFiles.length).toBeGreaterThan(0);
|
||||
const mdContent = await fs.readFile(nodePath.join(convertedDir, mdFiles[0]), 'utf8');
|
||||
expect(mdContent).toContain('legacy content');
|
||||
await a.app.close();
|
||||
});
|
||||
Reference in New Issue
Block a user