T-J92O-md-test-apps
State: closed/done · Impact: high · Complexity: medium
Neither the engine nor the layer can be run in a browser without a product around it, so every visual or performance check today goes through the notes product. This task adds two test apps: a Vite demo that exercises the engine in isolation and a Nuxt playground that exercises every layer component, each with Playwright and the shared performance harness the budgets are measured with.
| Location | Role today |
|---|---|
packages/ts/json-canvas-vue/demo/ | Precedent: Vite + TS demo nested in its library, moon.yml, playwright.config.ts booting the dev server, e2e specs under tests/ |
packages/ts/obsidian-bases/demo/ | Precedent: Nuxt demo nested in its library |
.moon/workspace.yml | sources: registers nested demo projects (json-canvas-demo) because the packages/ts/* glob stops at the parent |
package.json | Root workspaces lists packages/ts/json-canvas-vue/demo and packages/ts/obsidian-bases/demo explicitly |
packages/ts/obsidian-md/test/fixtures/every-feature.md | The fixture the demo ships until the corpus lands |
packages/ts/ui/playwright.config.ts | Chromium and WebKit project shape |
The corpus fixtures and headless bench come from T-0GV4-md-engine-line-endings-corpus; the layer comes from T-A0HT-md-ui-layer-skeleton.
Proposed
Section titled “Proposed”| App | Purpose | Shape |
|---|---|---|
packages/ts/obsidian-editor/demo/ | Engine in isolation: corpus fixture picker, mode switch, plugin toggles (omit), bench tab running the bench cases in the browser, a Vue tab mounting useObsidianEditor | Vite + TS with @vitejs/plugin-vue for the Vue tab; moon.yml (check, build, e2e); root workspaces entry; moon source obsidian-editor-demo; dev port 4781 |
packages/ts/markdown-ui/playground/ | Layer in isolation: one page per Md* component, a fixture vault, large-note fixtures, Playwright e2e and perf | Nuxt app extends: ['@sksizer/markdown-ui'], ssr: false; moon.yml (check, e2e, perf); root workspaces entry; moon source markdown-ui-playground; dev port 4893 |
Playground fixtures under packages/ts/markdown-ui/playground/fixtures/: vault/ (ten notes with
wikilinks, embeds, tags, a table, math, mermaid, <details>), generate.ts writes
large/lines-2000.md, large/lines-10000.md and large/bytes-600k.md (deterministic content,
committed), provider.ts is an in-memory MarkdownProvider with loadNote, saveAttachment
(object URLs) and onInvalidate.
Perf harness packages/ts/markdown-ui/playground/tests/perf-harness.ts:
measure(page, name, fn): Promise<number> // performance.mark/measure around fn, returns mscollectLongTasks(page): Promise<LongTask[]> // PerformanceObserver('longtask') bufferheapUsed(page): Promise<number> // CDP Performance.getMetrics JSHeapUsedSizewithTrace(page, name, fn) // saves a Chromium trace under test-results/traces/packages/ts/markdown-ui/playground/tests/perf.e2e.ts ships with one case (open lines-2000.md
in live mode, first paint under 300 ms) as the harness proof; the full budget matrix is
T-I630-md-ui-playground-e2e-perf. playground-smoke.e2e.ts opens every component page and
asserts it renders. demo-smoke.e2e.ts loads each corpus fixture and switches modes.
Approach
Section titled “Approach”- Scaffold the demo (
package.json,vite.config.ts,index.html,src/main.ts,src/vue-tab.ts,moon.yml,playwright.config.ts,tsconfig.json); import corpus fixtures withimport.meta.glob; wire the bench tab to the bench runner’s exported cases. - Register the demo in root
package.jsonworkspacesand.moon/workspace.ymlsources;bun install;moon run obsidian-editor-demo:check. - Scaffold the playground (
package.json,nuxt.config.ts,app/app.vue,app/pages/index.vue, one page per component:surface,viewer,mode-toggle,mermaid;moon.yml,playwright.config.ts,tsconfig.json). - Write the fixture vault,
generate.ts, the generated large files, andprovider.ts. - Write
perf-harness.ts,perf.e2e.ts(one case),playground-smoke.e2e.ts. - Register the playground in root
workspacesand moonsources;bun install;moon run markdown-ui-playground:check. - Run both e2e suites locally (
bunx playwright install chromiumonce).
Files to touch
Section titled “Files to touch”| Location | Kind | Change |
|---|---|---|
packages/ts/obsidian-editor/demo/package.json | new | Vite app manifest |
packages/ts/obsidian-editor/demo/vite.config.ts | new | Vue plugin, port 4781 |
packages/ts/obsidian-editor/demo/index.html | new | Entry |
packages/ts/obsidian-editor/demo/src/main.ts | new | Fixture picker, mode switch, plugin toggles, bench tab |
packages/ts/obsidian-editor/demo/src/vue-tab.ts | new | Mounts useObsidianEditor |
packages/ts/obsidian-editor/demo/moon.yml | new | check, build, e2e |
packages/ts/obsidian-editor/demo/playwright.config.ts | new | Boots bun run dev |
packages/ts/obsidian-editor/demo/tests/demo-smoke.e2e.ts | new | Loads fixtures, switches modes |
packages/ts/obsidian-editor/demo/tsconfig.json | new | Vite TS config |
packages/ts/markdown-ui/playground/package.json | new | Nuxt app manifest |
packages/ts/markdown-ui/playground/nuxt.config.ts | new | extends: ['@sksizer/markdown-ui'], ssr: false, port 4893 |
packages/ts/markdown-ui/playground/app/app.vue | new | Nav over component pages |
packages/ts/markdown-ui/playground/app/pages/index.vue | new | Index |
packages/ts/markdown-ui/playground/app/pages/surface.vue | new | MdSurface over the fixture vault and the large notes |
packages/ts/markdown-ui/playground/app/pages/viewer.vue | new | MdViewer |
packages/ts/markdown-ui/playground/app/pages/mode-toggle.vue | new | MdModeToggle |
packages/ts/markdown-ui/playground/app/pages/mermaid.vue | new | MdMermaidBlock in light and dark |
packages/ts/markdown-ui/playground/fixtures/vault/ | new | Ten notes |
packages/ts/markdown-ui/playground/fixtures/generate.ts | new | Writes the large fixtures |
packages/ts/markdown-ui/playground/fixtures/large/ | new | lines-2000.md, lines-10000.md, bytes-600k.md |
packages/ts/markdown-ui/playground/fixtures/provider.ts | new | In-memory MarkdownProvider |
packages/ts/markdown-ui/playground/tests/perf-harness.ts | new | measure, collectLongTasks, heapUsed, withTrace |
packages/ts/markdown-ui/playground/tests/perf.e2e.ts | new | One budget case |
packages/ts/markdown-ui/playground/tests/playground-smoke.e2e.ts | new | Every page renders |
packages/ts/markdown-ui/playground/moon.yml | new | check, e2e, perf |
packages/ts/markdown-ui/playground/playwright.config.ts | new | Boots nuxt dev, Chromium |
packages/ts/markdown-ui/playground/tsconfig.json | new | Nuxt TS config |
package.json | modify | Two workspaces entries |
.moon/workspace.yml | modify | obsidian-editor-demo, markdown-ui-playground sources |
packages/ts/obsidian-editor/README.md | modify | ”Testing” names the demo |
The layer README from T-A0HT-md-ui-layer-skeleton gains a section naming the playground and how to run e2e and perf.
Acceptance criteria
Section titled “Acceptance criteria”- AC-1:
moon run obsidian-editor-demo:check markdown-ui-playground:checkpasses. - AC-2:
moon run obsidian-editor-demo:e2epasses: each corpus fixture loads andlive→source→livekeeps the document text. - AC-3:
moon run markdown-ui-playground:e2epasses: the four component pages (surface,viewer,mode-toggle,mermaid) render their component root (.md-surface,.md-reading,[data-testid="md-mode-toggle"],.obsmd-mermaid). - AC-4:
moon run markdown-ui-playground:perfruns the perf spec; the 2 000-line live open case measures under 300 ms and a trace file exists under the playground’stest-results/traces/. - AC-5: the harness exports
measure,collectLongTasks,heapUsed,withTrace, each exercised by the perf spec. - AC-6:
bun install --frozen-lockfileat the root succeeds andbun pm lslists@sksizer/obsidian-editor-demoand@sksizer/markdown-ui-playground. - AC-7:
generate.tsis deterministic: running it twice leavesgit statusclean. - AC-8:
grep -rn "from '@nuxt/ui'" packages/ts/markdown-ui/playground/appreturns nothing.
Out of scope
Section titled “Out of scope”- Per-component e2e specs and the full perf budget matrix (T-I630-md-ui-playground-e2e-perf).
- Headless bench and baseline (T-0GV4-md-engine-line-endings-corpus).
- Pages for components that do not exist yet; T-98EU-md-ui-toolbar-insert-frontmatter, T-8ZHI-md-ui-overlays-bubble-link-table and T-RJVA-md-ui-find-outline-hover-lifts add their own playground pages.
Dependencies
Section titled “Dependencies”- T-A0HT-md-ui-layer-skeleton for the layer the playground extends.
- The demo’s fixture picker and bench tab read T-0GV4-md-engine-line-endings-corpus’s corpus and bench; until it lands the demo ships with the every-feature fixture alone and no bench tab.
- S-0010: the playground extends the layer and imports no
@nuxt/uidirectly.
Discovery context
Section titled “Discovery context”Member of milestone M-931L; the test apps section of decision D-K3EM-markdown-editor-chrome-and-plugin-environment.