Files
MyNote/apps/desktop/tests/e2e/codeblock-selectall.spec.ts
T
hunter-dev dc8d844a1f feat(info): 信息面板 UI 重做 + 双向批量关联 + 代码块内全选复制
1. 信息面板 UI 重做:设计 token 统一、lucide 图标、分区小节、星标/标签/关联 chip 化
2. 关联文档升级:新增 doc:link-batch IPC,A↔B 双向写入 links;面板支持快速双向关联 + 批量勾选关联/解除
3. 代码块内全选复制:Ctrl+A 在代码块内仅全选该代码块(TyporaKeys selectInsideCodeBlock),Ctrl+C 复制纯代码;代码块内 Ctrl+V 按纯文本粘贴
4. 修复 React error #62:btn 改为函数后遗漏 style={btn} 裸用,导致 render 期间更新
2026-09-09 20:11:08 +08:00

68 lines
3.6 KiB
TypeScript

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');
await page.waitForTimeout(800);
const invoke = (ch: string, args: any) => page.evaluate(({ ch, args }) => (globalThis as any).dsh.invoke(ch, args), { ch, args });
const clip = () => app.evaluate(({ clipboard }) => clipboard.readText());
return { app, page, invoke, clip };
}
// 代码块内 Ctrl+A 全选后 Ctrl+C:应只复制代码块内容(纯代码无围栏),即使文档有其他内容
test('代码块内 Ctrl+A 全选复制纯代码(不受文档其他内容影响)', async () => {
const tmp = await fs.mkdtemp(nodePath.join(os.tmpdir(), 'hn-sel1-'));
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 });
// 文档:代码块上下都有其他内容,确保 Ctrl+A 只选代码块而非整篇
const body = '# 标题\n\n上方段落\n\n```bash\nsudo apt-get update\nls -la\n```\n\n下方段落';
await a.invoke('doc:write', { path: 'code.md', meta: {}, body });
await a.page.evaluate((p: string) => (globalThis as any).__STORE__?.getState?.().openDoc(p), 'code.md');
await a.page.waitForTimeout(1500);
const code = a.page.locator('.ProseMirror pre code');
await code.click();
await a.page.keyboard.press('Control+a');
await a.page.waitForTimeout(200);
// 校验选中范围只是代码块内容(可通过 selection anchor 判断,或直接 Ctrl+C 后看剪贴板)
await a.page.keyboard.press('Control+c');
await a.page.waitForTimeout(300);
const text = await a.clip();
console.log('SELALL_CLIP', JSON.stringify(text));
expect(text.trim().replace(/\r\n/g, '\n')).toBe('sudo apt-get update\nls -la');
await a.app.close();
});
// 代码块内 Ctrl+V 粘贴按纯文本插入(不产生 markdown 转换/围栏)
test('代码块内 Ctrl+V 粘贴纯文本', async () => {
const tmp = await fs.mkdtemp(nodePath.join(os.tmpdir(), 'hn-sel2-'));
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.invoke('doc:write', { path: 'code2.md', meta: {}, body: '```js\nlet x = 1;\n```' });
await a.page.evaluate((p: string) => (globalThis as any).__STORE__?.getState?.().openDoc(p), 'code2.md');
await a.page.waitForTimeout(1500);
const code = a.page.locator('.ProseMirror pre code');
await code.click();
// 全选代码块,然后粘贴纯文本
await a.page.keyboard.press('Control+a');
await a.page.evaluate(() => navigator.clipboard.writeText('# not a heading\n- not a list'));
await a.page.waitForTimeout(200);
await a.page.keyboard.press('Control+v');
await a.page.waitForTimeout(500);
const inner = await a.page.evaluate(() => (document.querySelector('.ProseMirror pre code') as HTMLElement)?.innerText ?? '');
console.log('PASTE_INNER', JSON.stringify(inner));
// 粘贴内容按纯文本插入(不出现标题/列表节点结构变化)
expect(inner).toContain('# not a heading');
expect(inner).toContain('- not a list');
await a.app.close();
});