feat: v0.4.3 — 浮动工具栏定位引擎重做 + 程序化编辑统一刷新管线
- 浮动工具栏 mirror 镜像测量:隐藏镜像层复制 textarea 排版样式,选区锚点插零宽字符读像素坐标,CJK/软换行/跨行选区误差全部消除 - 实测尺寸替代魔法数字;滚动 rAF 节流重定位;滚出视口自动隐藏;a11y:role=toolbar + aria-label、visibility 移出 Tab 序列、键盘可达 - 修复死开关/监听器泄漏/销毁后 focus 崩溃/blur 焦点抖动误隐藏 - _afterProgrammaticEdit 统一 8 条程序化路径的渲染/行号/字数/大纲/事件刷新;右键菜单 label 转义、copyAsHTML Firefox 降级、paste 失败提示、Esc 退出全屏 - 测试 871 → 895,e2e 22 → 28 项断言(含真实浏览器浮动工具栏布局验证)
This commit is contained in:
@@ -115,6 +115,51 @@ const check = (name, cond) => {
|
||||
const status = await page.evaluate(() => window.__ed.getStatus());
|
||||
check('getStatus 返回结构', status.mode === 'split' && status.theme === 'dark' && status.locale === 'zh-CN');
|
||||
|
||||
// 12. 浮动工具栏(真实浏览器布局验证:mirror 镜像测量定位)
|
||||
// 放在依赖旧值/历史栈的用例之后执行(本节自行填充测试内容)
|
||||
await page.locator('.me-textarea').fill('# 标题\n\n第二行中文文本内容\n\n第三行 more text');
|
||||
await page.waitForTimeout(50);
|
||||
await page.locator('.me-textarea').evaluate((el) => {
|
||||
el.focus();
|
||||
const start = el.value.indexOf('第二行');
|
||||
el.setSelectionRange(start, start + 6);
|
||||
el.dispatchEvent(new MouseEvent('mouseup', { bubbles: true }));
|
||||
});
|
||||
await page.waitForSelector('.me-float-toolbar.me-visible', { timeout: 3000 });
|
||||
check('浮动工具栏选区后显示', true);
|
||||
const pos = await page.evaluate(() => {
|
||||
const bar = document.querySelector('.me-float-toolbar');
|
||||
const ta = document.querySelector('.me-textarea');
|
||||
const bb = bar.getBoundingClientRect();
|
||||
const tb = ta.getBoundingClientRect();
|
||||
return { barL: bb.left, barR: bb.right, barT: bb.top, barB: bb.bottom, taL: tb.left, taR: tb.right, taT: tb.top, taB: tb.bottom };
|
||||
});
|
||||
check('浮动工具栏水平定位在编辑区内', pos.barR > pos.taL && pos.barL < pos.taR);
|
||||
check('浮动工具栏垂直定位在选区行附近', pos.barT >= pos.taT - 50 && pos.barB <= pos.taB + 50);
|
||||
// 等待显示过渡动画结束后再点击(避免 actionability 等待期间竞态)
|
||||
await page.waitForTimeout(300);
|
||||
await page.locator('.me-float-toolbar .me-btn').first().click();
|
||||
check('浮动工具栏 bold 命令', (await page.locator('.me-textarea').inputValue()).includes('**第二行中文文**'));
|
||||
check('命令执行后浮动工具栏隐藏', (await page.locator('.me-float-toolbar.me-visible').count()) === 0);
|
||||
|
||||
// 12.5 长行折行选区(软换行场景下工具栏不跑出可视区)
|
||||
await page.locator('.me-textarea').fill('# T\n\n' + '很长的中文内容用于触发自动折行的测试文本'.repeat(20));
|
||||
await page.waitForTimeout(50);
|
||||
await page.locator('.me-textarea').evaluate((el) => {
|
||||
el.focus();
|
||||
el.setSelectionRange(el.value.length - 20, el.value.length);
|
||||
el.dispatchEvent(new MouseEvent('mouseup', { bubbles: true }));
|
||||
});
|
||||
await page.waitForTimeout(100);
|
||||
check('长行折行选区工具栏保持可视区内', (await page.evaluate(() => {
|
||||
const bar = document.querySelector('.me-float-toolbar');
|
||||
const ta = document.querySelector('.me-textarea');
|
||||
if (!bar || !bar.classList.contains('me-visible')) return false;
|
||||
const bb = bar.getBoundingClientRect();
|
||||
const tb = ta.getBoundingClientRect();
|
||||
return bb.top >= tb.top - 50 && bb.bottom <= tb.bottom + 50;
|
||||
})));
|
||||
|
||||
await browser.close();
|
||||
server.close();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user