Repository navigation
restore: recover accidentally deleted tests from PR #4001 - #4197
Merged
Merged
Conversation
…ite refactor)
Restores test infrastructure lost in the webpack→electron-vite migration:
Unit tests restored (all passing):
- test/unit/specs/extract-word.spec.js (33 cases, spellchecker)
- test/unit/specs/markdown-footnotes.spec.js (lexer footnote parsing)
- test/unit/specs/markdown-list-indentation.spec.js (list indent variants)
- test/unit/specs/match-electron-accelerator.spec.js (keybinding)
- test/unit/specs/markdown-basic.spec.js (Muya ContentState round-trip)
- test/unit/data/ (13 markdown fixture files)
- test/unit/markdown.js (fixture loader helper)
E2E tests restored (require `npm run build` + Playwright, run via test:e2e):
- test/e2e/{launch,xss}.spec.js + helpers.js (helpers.js: updated mainEntrypoint
from dist/electron/main.js → out/main/index.js for electron-vite output)
Not restored (reason):
- test/unit/karma.conf.js obsolete (Karma replaced by Vitest)
- test/unit/index.js obsolete (webpack require.context)
- test/unit/specs/LandingPage* disabled before refactor; component removed
- test/specs/commonMark/run.spec.js one-time network utility, not a unit test
- test/specs/gfm/run.spec.js same
Bug fixes required to make tests pass:
- slugger.js: strip HTML tags and LATIN_SYMBOLS_MAP chars ($%&<>|'") BEFORE
calling downcode(), preventing e.g. '<b>' → 'lessbgreater' and '$%&' →
'dollarpercentand' which then bypass the special-char removal regex.
- test/unit/data/common/Lists.md: update tight mixed-ordered/unordered nested
list to its stable idempotent form (loose outer list). The lexer's trailing-\n
heuristic for loose detection produces a false positive when a sub-list ends
with \n, causing tight→loose→all-loose cascading over multiple round-trips;
the fixture is updated to the stable state so the round-trip test is valid.
Test runner setup:
- vitest.config.js: new config (jsdom env, path aliases matching
electron.vite.config.js, globals:true for Chai-style expect)
- package.json: add test / test:unit / test:e2e scripts
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR restores MarkText’s previously deleted test suite and modernizes the test setup by introducing Vitest for unit tests and Playwright for E2E tests, while also fixing a slug-generation bug discovered by the restored tests.
Changes:
- Added a Vitest-based unit test runner and restored Muya/parser-focused unit tests plus markdown fixtures.
- Restored Playwright-based E2E tests (launch smoke test + XSS regression test) and supporting helpers/config.
- Fixed slug generation in
Sluggerto strip certain characters/tags beforedowncode()to preserve expected fallback behavior.
Reviewed changes
Copilot reviewed 26 out of 27 changed files in this pull request and generated 15 comments.
Show a summary per file
| File | Description |
|---|---|
vitest.config.js |
Adds Vitest configuration and aligns module aliases with the existing electron-vite config. |
package.json |
Adds test, test:unit, and test:e2e scripts and Vitest/jsdom dev dependencies. |
package-lock.json |
Updates lockfile for Vitest/jsdom (and related) additions. |
src/muya/lib/parser/marked/slugger.js |
Adjusts slug generation order to strip tags/symbols before downcoding and adds a fallback slug. |
test/unit/specs/extract-word.spec.js |
Restores unit tests for spellchecker word extraction. |
test/unit/specs/markdown-footnotes.spec.js |
Restores lexer footnote parsing tests. |
test/unit/specs/match-electron-accelerator.spec.js |
Restores accelerator matching tests. |
test/unit/specs/markdown-basic.spec.js |
Restores markdown round-trip tests for core constructs. |
test/unit/specs/markdown-list-indentation.spec.js |
Restores list indentation export tests across indentation modes. |
test/unit/markdown.js |
Adds markdown fixture loader and template helpers for parser round-trip tests. |
test/unit/data/.editorconfig |
Prevents trailing whitespace trimming for markdown fixtures. |
test/unit/data/common/BasicTextFormatting.md |
Restores markdown fixtures for common syntax. |
test/unit/data/common/Blockquotes.md |
Restores blockquote fixtures. |
test/unit/data/common/CodeBlocks.md |
Restores code block fixtures. |
test/unit/data/common/Escapes.md |
Restores escaping fixtures. |
test/unit/data/common/Headings.md |
Restores heading fixtures. |
test/unit/data/common/Images.md |
Restores image fixtures. |
test/unit/data/common/Links.md |
Restores link fixtures. |
test/unit/data/common/Lists.md |
Restores list fixtures (including known failing cases section). |
test/unit/data/gfm/BasicTextFormatting.md |
Restores GFM basic formatting fixtures. |
test/unit/data/gfm/Lists.md |
Restores GFM task list fixtures. |
test/unit/data/gfm/Tables.md |
Restores GFM table fixtures. |
test/e2e/helpers.js |
Adds Electron launch helper for Playwright E2E tests (electron-vite output path). |
test/e2e/launch.spec.js |
Restores app launch smoke test using Playwright. |
test/e2e/xss.spec.js |
Restores XSS regression test ensuring malicious docs don’t crash the process. |
test/e2e/playwright.config.js |
Adds Playwright runner config. |
test/e2e/data/xss.md |
Adds malicious markdown payloads used by the XSS E2E test. |
Comments suppressed due to low confidence (2)
test/e2e/launch.spec.js:21
- The title regex
/^MarkText|Untitled-1 - MarkText$/is not grouped, so it will match many unintended titles (e.g., any title that merely starts with "MarkText"). Use a grouped alternative like^(MarkText|Untitled-1 - MarkText)$to ensure the expectation is actually validating the intended behavior.
const title = await page.title()
expect(/^MarkText|Untitled-1 - MarkText$/.test(title)).toBeTruthy()
})
test/e2e/xss.spec.js:15
- The test uses a fixed 3s delay to wait for rendering, which can make the run flaky (slow machines may still not be ready; fast machines waste time). Prefer waiting on a deterministic condition (e.g., a known UI selector/state change, or an IPC signal) instead of
setTimeout.
// Wait to parse and render the document.
await new Promise((resolve) => setTimeout(resolve, 3000))
})
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Pass project root as Electron entry (not the main script file) so app.getAppPath() returns the project root and __static resolves to static/ correctly; passing out/main/index.js directly bypasses package.json and breaks preference/locale loading - Set PERF_TESTING=true so locale loader uses process.cwd() path - Run minify-locales to create required *.min.json locale files - Rebuild native modules with CXXFLAGS=-std=c++20 (Electron 41 headers require C++20) - Add unique suffix to temp dir to prevent SingletonLock collisions when tests run in parallel - Use direct Electron binary path (via path.txt) instead of Node wrapper - Add @playwright/test to devDependencies Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Functional fixes: - extract-word.spec.js: replace broken conditional helper with proper assertions (null check + deep.equal); remove stray console.log - slugger.js: include '|' in pre-downcode symbol removal; downcode() maps '|' to "or" which survived the special-char regex, same class of bug as the previously fixed $%&<> - markdown-list-indentation.spec.js: fix option key typo listIdentation → listIndentation so ContentState is created with the intended setting, not always the default - launch.spec.js / xss.spec.js: remove async from test.describe() callbacks; Playwright requires describe callbacks to be synchronous - playwright.config.js: change headless: false → true so E2E tests can run in CI/headless environments without hanging Typo/formatting fixes: - match-electron-accelerator.spec.js: "non characte key" → "non-character key", "Emtpy" → "Empty" - markdown-footnotes.spec.js: "footenote" → "footnote" - markdown-list-indentation.spec.js: describe text "identation" → "indentation" - markdown.js: add missing space before = in BlockquotesTemplate export - BasicTextFormatting.md: "extentions" → "extensions" Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
7 tasks done
thimbleberrysystems
pushed a commit
to thimbleberrysystems/WordBird
that referenced
this pull request
Jun 21, 2026
…rktext#4197) * restore: recover accidentally deleted tests from PR marktext#4001 (electron-vite refactor) Restores test infrastructure lost in the webpack→electron-vite migration: Unit tests restored (all passing): - test/unit/specs/extract-word.spec.js (33 cases, spellchecker) - test/unit/specs/markdown-footnotes.spec.js (lexer footnote parsing) - test/unit/specs/markdown-list-indentation.spec.js (list indent variants) - test/unit/specs/match-electron-accelerator.spec.js (keybinding) - test/unit/specs/markdown-basic.spec.js (Muya ContentState round-trip) - test/unit/data/ (13 markdown fixture files) - test/unit/markdown.js (fixture loader helper) E2E tests restored (require `npm run build` + Playwright, run via test:e2e): - test/e2e/{launch,xss}.spec.js + helpers.js (helpers.js: updated mainEntrypoint from dist/electron/main.js → out/main/index.js for electron-vite output) Not restored (reason): - test/unit/karma.conf.js obsolete (Karma replaced by Vitest) - test/unit/index.js obsolete (webpack require.context) - test/unit/specs/LandingPage* disabled before refactor; component removed - test/specs/commonMark/run.spec.js one-time network utility, not a unit test - test/specs/gfm/run.spec.js same Bug fixes required to make tests pass: - slugger.js: strip HTML tags and LATIN_SYMBOLS_MAP chars ($%&<>|'") BEFORE calling downcode(), preventing e.g. '<b>' → 'lessbgreater' and '$%&' → 'dollarpercentand' which then bypass the special-char removal regex. - test/unit/data/common/Lists.md: update tight mixed-ordered/unordered nested list to its stable idempotent form (loose outer list). The lexer's trailing-\n heuristic for loose detection produces a false positive when a sub-list ends with \n, causing tight→loose→all-loose cascading over multiple round-trips; the fixture is updated to the stable state so the round-trip test is valid. Test runner setup: - vitest.config.js: new config (jsdom env, path aliases matching electron.vite.config.js, globals:true for Chai-style expect) - package.json: add test / test:unit / test:e2e scripts Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix(e2e): fix E2E test helpers so app launches and tests pass - Pass project root as Electron entry (not the main script file) so app.getAppPath() returns the project root and __static resolves to static/ correctly; passing out/main/index.js directly bypasses package.json and breaks preference/locale loading - Set PERF_TESTING=true so locale loader uses process.cwd() path - Run minify-locales to create required *.min.json locale files - Rebuild native modules with CXXFLAGS=-std=c++20 (Electron 41 headers require C++20) - Add unique suffix to temp dir to prevent SingletonLock collisions when tests run in parallel - Use direct Electron binary path (via path.txt) instead of Node wrapper - Add @playwright/test to devDependencies Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * chore: add test-results/ and playwright-report/ to .gitignore Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix: address Copilot review comments on tests and slugger Functional fixes: - extract-word.spec.js: replace broken conditional helper with proper assertions (null check + deep.equal); remove stray console.log - slugger.js: include '|' in pre-downcode symbol removal; downcode() maps '|' to "or" which survived the special-char regex, same class of bug as the previously fixed $%&<> - markdown-list-indentation.spec.js: fix option key typo listIdentation → listIndentation so ContentState is created with the intended setting, not always the default - launch.spec.js / xss.spec.js: remove async from test.describe() callbacks; Playwright requires describe callbacks to be synchronous - playwright.config.js: change headless: false → true so E2E tests can run in CI/headless environments without hanging Typo/formatting fixes: - match-electron-accelerator.spec.js: "non characte key" → "non-character key", "Emtpy" → "Empty" - markdown-footnotes.spec.js: "footenote" → "footnote" - markdown-list-indentation.spec.js: describe text "identation" → "indentation" - markdown.js: add missing space before = in BlockquotesTemplate export - BasicTextFormatting.md: "extentions" → "extensions" Co-Authored-By: Claude Sonnet 4.6 <[email protected]> --------- Co-authored-by: Claude Sonnet 4.6 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
PR #4001 (electron-vite refactor) accidentally deleted all test files alongside the old Karma/webpack infrastructure. This PR restores the valuable unit tests and sets up a modern Vitest-based test runner.
test:e2escriptWhat was restored vs. not restored
Restored (unit tests — all passing via
npm test):test/unit/specs/extract-word.spec.jstest/unit/specs/markdown-footnotes.spec.jstest/unit/specs/match-electron-accelerator.spec.jstest/unit/specs/markdown-basic.spec.jstest/unit/specs/markdown-list-indentation.spec.jstest/unit/data/Restored (E2E — run separately via
npm run test:e2e, requiresnpm run build+ Playwright):test/e2e/launch.spec.js— app launch smoke testtest/e2e/xss.spec.js— XSS security test (verifies malicious documents don't crash the process)test/e2e/helpers.js— updatedmainEntrypointfromdist/electron/main.js→out/main/index.js(electron-vite output path)Not restored (with reasons):
test/unit/karma.conf.js— Karma+Webpack obsolete, replaced by Vitesttest/unit/index.js— webpackrequire.contextentry, not needed (Vitest auto-discovers)test/unit/specs/LandingPage.spec.js_disabled— already disabled before refactor; component removed in Vue 3 migrationtest/specs/commonMark/run.spec.js+gfm/run.spec.js— one-time network utility scripts that generate comparison reports, not unit testsBug fixes
Two bugs were found and fixed to make the restored tests pass:
1.
src/muya/lib/parser/marked/slugger.js— HTML tag stripping before downcodedowncode()converts<→lessand>→greater(viaLATIN_SYMBOLS_MAP), causing the subsequent HTML-strip regex to miss the already-converted tags. Similarly$%&were converted todollar/percent/andbefore the special-char removal regex ran, so!@#$%^&*()produceddollarpercentandinstead of the expected fallback"heading". Fix: strip HTML tags and$%&<>|'"before callingdowncode().2.
test/unit/data/common/Lists.md— update to idempotent stable formThe test checks markdown round-trip fidelity (import → export = original). The fixture had a tight mixed ordered/unordered nested list that the lexer's loose-detection heuristic incorrectly turned loose on export (trailing-
\nfrom a sub-list triggers the loose flag on sibling items). Feeding the export back produces a fully-loose outer list — the round-trip is not idempotent at the "tight" form. The fixture is updated to the stable idempotent form (loose outer list) so the round-trip test is valid and meaningful.Test plan
npm test— 541 tests across 6 files, all passingnpm run test:e2e— requiresnpm run buildandnpm install -D @playwright/testfirst🤖 Generated with Claude Code