- Swap CM6 editor with BlockNote block-based editor - Strip YAML frontmatter before passing to BlockNote, keep separate - Intercept link clicks for wikilink navigation - Remove all @codemirror/*, @lezer/*, codemirror-live-markdown deps - Remove frontmatterHide.ts (no longer needed) - Update Editor.css: remove .cm-* styles, add BlockNote container styles - Tab bar, diff toggle, inspector panel unchanged
84 lines
3.2 KiB
TypeScript
84 lines
3.2 KiB
TypeScript
import { test, expect } from '@playwright/test'
|
|
|
|
test('zero-shift detail: focused editor screenshots', async ({ page }) => {
|
|
await page.goto('http://localhost:5173')
|
|
await page.waitForTimeout(800)
|
|
|
|
// Open "Build Laputa App" which has headings and bullets
|
|
const noteItem = page.locator('.note-list__item', { hasText: 'Build Laputa App' })
|
|
await noteItem.click()
|
|
await page.waitForTimeout(800)
|
|
|
|
const cmEditor = page.locator('.cm-editor')
|
|
await expect(cmEditor).toBeVisible()
|
|
|
|
// Screenshot just the editor content area
|
|
const editorBox = await cmEditor.boundingBox()
|
|
if (!editorBox) throw new Error('Editor not visible')
|
|
|
|
// Crop to top portion of editor where headings and bullets are
|
|
const clip = {
|
|
x: editorBox.x,
|
|
y: editorBox.y,
|
|
width: editorBox.width,
|
|
height: Math.min(editorBox.height, 500),
|
|
}
|
|
|
|
// 1. Initial preview state (cursor not on headings/bullets)
|
|
await page.screenshot({ path: 'test-results/detail-01-preview.png', clip })
|
|
|
|
// 2. Click on "Overview" heading
|
|
const headingSpan = page.locator('.cm-header-2', { hasText: 'Overview' }).first()
|
|
const hBox = await headingSpan.boundingBox()
|
|
if (hBox) {
|
|
await page.mouse.click(hBox.x + hBox.width / 2, hBox.y + hBox.height / 2)
|
|
await page.waitForTimeout(500)
|
|
}
|
|
await page.screenshot({ path: 'test-results/detail-02-heading-active.png', clip })
|
|
|
|
// 3. Click on a bullet line
|
|
const bulletLine = page.locator('.cm-line', { hasText: 'Four-panel layout working' }).first()
|
|
const bBox = await bulletLine.boundingBox()
|
|
if (bBox) {
|
|
await page.mouse.click(bBox.x + bBox.width / 2, bBox.y + bBox.height / 2)
|
|
await page.waitForTimeout(500)
|
|
}
|
|
await page.screenshot({ path: 'test-results/detail-03-bullet-active.png', clip })
|
|
|
|
// 4. Click on plain paragraph to go back to preview
|
|
const para = page.locator('.cm-line', { hasText: 'Custom desktop app' }).first()
|
|
const pBox = await para.boundingBox()
|
|
if (pBox) {
|
|
await page.mouse.click(pBox.x + 10, pBox.y + pBox.height / 2)
|
|
await page.waitForTimeout(500)
|
|
}
|
|
await page.screenshot({ path: 'test-results/detail-04-back-preview.png', clip })
|
|
|
|
// 5. Check that heading marker (.cm-formatting-block inside .cm-heading-line) is position:absolute
|
|
const headingMarkers = page.locator('.cm-heading-line .cm-formatting-block')
|
|
const markerCount = await headingMarkers.count()
|
|
console.log(`Heading markers found: ${markerCount}`)
|
|
|
|
if (markerCount > 0) {
|
|
const position = await headingMarkers.first().evaluate(el =>
|
|
window.getComputedStyle(el).position
|
|
)
|
|
console.log(`Heading marker position: ${position}`)
|
|
expect(position).toBe('absolute')
|
|
}
|
|
|
|
// 6. Check that non-heading markers always have font-size != 0.01em
|
|
const bulletMarkers = page.locator('.cm-line:not(.cm-heading-line) .cm-formatting-block')
|
|
const bmCount = await bulletMarkers.count()
|
|
console.log(`Non-heading block markers found: ${bmCount}`)
|
|
|
|
if (bmCount > 0) {
|
|
const fontSize = await bulletMarkers.first().evaluate(el =>
|
|
window.getComputedStyle(el).fontSize
|
|
)
|
|
console.log(`Bullet marker font-size: ${fontSize}`)
|
|
// Should NOT be tiny (library default is 0.01em ≈ 0.15px)
|
|
expect(parseFloat(fontSize)).toBeGreaterThan(10)
|
|
}
|
|
})
|