Skip to content

test: replace the text checks with bindings, lint and parsed config - #1035

Merged
PathGao merged 142 commits into
masterfrom
tests-checks-to-tools
Oct 26, 2026
Merged

PathGao merged 142 commits into
masterfrom
tests-checks-to-tools

Conversation

@PathGao

@PathGao PathGao commented Oct 26, 2026

Copy link
Copy Markdown
Collaborator

Follow-up to #1032. The scripts/*.checks.* files read source and config as text; this replaces each case with the mechanism built for it, and deletes all 13 files.

  • Rust↔TS calls: tauri-specta (=2.0.0-rc.26, specta and its crates pinned exactly; it is a release candidate). All 68 commands and the five Rust-emitted events go through src/lib/bindings.ts, which a #[test] writes and which is committed; CI fails if it is stale. Names, argument names and payloads are unchanged; errors still reject with the same string. save_theme takes an Appearance enum and SemanticSpan.kind is an enum (same wire strings), and a few shared constants are exported from Rust instead of written twice. Commands that take JSON in a string stay strings. The exporter is a dev-dependency only.
  • Code conventions: ESLint (eslint, typescript-eslint, eslint-plugin-svelte, svelte-eslint-parser, exact pins; npm run lint in CI). Raw invoke/listen/emit/emitTo/once are allowed only in bindings.ts and the new windowEvents.ts, which types the window-to-window events. Each former convention check is its own markpad/<name> rule. clippy.toml bans WebviewWindowBuilder::focused and std::env::var. Four Rust conventions clippy cannot state live in scripts/conventions.test.ts, a documented structural check.
  • Config and data: parsed, not matched. Workflows and snapcraft.yaml via yaml, JSON via JSON.parse, Cargo.toml via cargo metadata, stylesheets via postcss (exact devDependency). CI runs cargo with --locked. A post-vite build step checks the startup chunks' source maps for Monaco, replacing the import-graph walker.
  • Print and export CSS resolve the real cascade in jsdom (export.print.test.ts, which also takes over fix(export): give an exported file the page margin on screen too #1034's cases).
  • Translation keys are typed: t() rejects a key the English table does not define.

Every replacement was checked by reintroducing the old bug and watching the new mechanism fail (rename one side for the bindings and typed keys, plant the violation for a lint rule, edit the value for a data test).

Deleted without replacement, because they read CSS inside a .svelte component's <style>:

  • "the stylesheet reads the width the markup writes": the preview column follows Preview → Max width through the inline --preview-max-width the viewer's <style> reads.
  • "styles.css switches transitions off under .tab-switching", viewer half: the .tab-switching rules stay in styles.css, not in the viewer.

Known limits: an ESLint rule whose target is renamed passes silently (there is no "must match" mode); the tauri-specta 2.0 release may need an API update.

Verified: node --test and vitest (also shuffled), svelte-check, npm run lint, cargo fmt/clippy/test with --locked, bindings diff, vite build + startup-chunk check, npm audit all green. Not clicked through in a built app.

Merge the ~200 per-fix test files into a few files per feature area.
Source-reading cases move to <feature>.checks.* files, separate from
behavior tests. No assertion changed: the same 1752 test names pass.
…Handlers.ts

test: run the editing keys against the extracted handlers instead of cutting them out of Editor.svelte
…nt-matter scroll end out of Editor.svelte

test: run them instead of reading Editor.svelte
…Bar.svelte

Move the window-tag editor, menu flags and window dismissal out of
TitleBar.svelte into stores/titleBarPopovers.svelte.ts, and the Home
menu export gate into canExportTab. Rewrite the tag-editor, export-gate
and context-menu-dismiss checks as behaviour specs and delete
scripts/windowTagEditor.ts.
…them directly

The close handler, quit, update settle, last-tab close, merge and pinned
group open move out of MarkdownViewer.svelte unchanged, as does the
set_window_meta report. Source-reading checks for them are replaced by
behavior tests; checks that lifted these functions now run the module.
…ns.ts

Editor.svelte and MarkdownViewer.svelte call createdEditorOptions,
updatedEditorOptions and editorReadOnly, so the option tests run the
functions instead of lifting the literal out of the component.
test: check every theme name the editor asks for against what defineAppThemes
and the VS Code theme loader actually define.
…ng else covers

clipboard_read_image, save_window_state and create_transfer_window are
asserted to return a future in a Rust test that only compiles if they are
async. Dropped: the Monaco anchor count (the patch throws on it), the Cargo
version pair (the manifest version test), the strip verification (the PR
build runs it), the unsigned macOS path (the signing harness runs it),
generate_handler names (a compile error), the single-implementation meta
check and the one-"main" Rust rule.
The Windows test binary failed to load (STATUS_ENTRYPOINT_NOT_FOUND):
tauri's test feature pulls in Common Controls v6 entry points and a test
binary carries no manifest declaring them. The three tests that need the
mock runtime, and the feature itself, now apply to macOS and Linux only.
…the store

Open file mode, preview full width and the merged auto-save switch are
loaded from a seeded legacy key, changed, and checked to leave the legacy
key in place. Replaces the regexes over settings.svelte.ts. The
--preview-max-width pair in the viewer's component CSS is dropped with the
other component-CSS checks.
The static import-graph walk could not see what Rollup emits. The new CI step
builds with source maps and fails if any chunk the entry reaches through
static imports holds a monaco-editor or monaco-vim module.

The workflow, snapcraft, tauri.conf and locale cases move from
release.checks.test.ts to release.workflows.test.ts. Each one parses its file
with yaml or JSON.parse and asserts the field; shell inside a run step is
matched only within that step. Cargo.toml's version comes from cargo metadata,
and CI runs cargo test and clippy with --locked so a stale Cargo.lock fails.
File associations, capability grants and CSP directives are read from the
parsed JSON, and locale cases walk the imported dictionaries instead of
grepping their source. Each case moves into its feature's behavior file.
…the Save As wording to documents.test.ts

The theme case parses src/app.html, runs its inline script after the store
writes a theme, and reads the painted attribute and background. Dropped: the
installed Monaco outdent check (editor.chords.spec.ts finds outdent on
Shift+Tab in Monaco's registry) and the toast.unsupportedFile pin (the key
type checks it).
Every invoke('…') in src/ is now commands.*() from src/lib/bindings.ts,
so a command renamed, removed or retyped on either side is a svelte-check
error. The clipboard, completion and Vim helpers call commands directly
instead of taking an injected invoke; their node tests answer through
window.__TAURI_INTERNALS__ (scripts/tauriInvoke.ts) and still assert the
wire-level command and arguments.

save_theme takes an Appearance enum, so its three words are one Rust
definition the startup reader shares and the frontend gets as a type.
Stored theme.txt contents are unchanged.

The checks that matched invoke('…') text for a command name across
languages go (C3, C42, C145, and the command halves of the save_theme
and window-state contracts); the claim-is-not-completion half of C145 is
a broker unit test. The single-caller checks follow the commands.* spelling.
folder-changed, file-changed, file-path, tab-transfer-offer and
tab-transfer-claimed are heard through events.*(appWindow).listen, still
scoped to the window, with payloads typed by the Rust structs that emit
them. The viewer's listener table keeps only the events the frontend
emits itself. The file-changed name check goes: the name now exists once,
in the Rust event struct.
postcss becomes a direct devDependency at the version vite already locked
(8.5.31). The find widget, palette, theme, task list, print and fold cases
read rules, selectors and declarations from the parsed styles.css, and the
title bar's z-index comes from TitleBar.svelte's <style> through
svelte/compiler. Each case moves into its feature's behavior file.

The two guards that read a component's markup or <style> against styles.css
(preview width variable, .tab-switching staying out of MarkdownViewer) are
removed: what they protect only shows in a browser's computed style.
Rust now exports the vocabulary the frontend matches against as
constants in bindings.ts: the ENCODING_UNMAPPABLE refusal code, the
list-marker and task-box fragments TASK_SOURCE_RE is built from, and the
Markdown link extensions. listSyntax.ts, markdownLinks.ts and
documentSession import them, so each has one definition.

SemanticSpan.kind is a SemanticKind enum. semanticTokens.ts lists every
kind at runtime and checks, at the type level, that the list matches the
union and that every kind's token type is in the legend; the theme
fall-through test iterates that list instead of reading semantic.rs.

Casts that restated a generated return type are removed, so a changed
return is a type error at the call site.

Deleted, now svelte-check errors: C1, C2, C8, C10, C13, C19, C103, the
outline command signature and the pinned-tag command names.
# Conflicts:
#	scripts/editor.checks.test.ts
#	scripts/editor.test.ts
#	scripts/export.checks.test.ts
#	scripts/preview.checks.test.ts
#	scripts/release.checks.test.ts
The fold, width and print-media cases read the stylesheet with a
hand-written brace walker and regexes. They now load the real sheets into
jsdom and read getComputedStyle. jsdom ignores @media print, so a postcss
pass unwraps the print blocks in place for the paper cases.
# Conflicts:
#	scripts/documents.checks.test.ts
#	scripts/editing.checks.test.ts
#	scripts/editor.checks.test.ts
#	scripts/editor.vim.test.ts
#	scripts/export.checks.test.ts
#	scripts/release.checks.test.ts
#	scripts/settings.checks.spec.ts
#	scripts/windows.checks.test.ts
#	src-tauri/src/commands.rs
#	src/lib/sessions/windowSession.svelte.ts
The merge put specta-typescript and tauri-specta's typescript feature under the
non-Windows dev-dependencies, so export_bindings could not build on Windows CI.
Only tauri's test feature stays there.
# Conflicts:
#	scripts/export.checks.test.ts
eslint.config.js holds one rule per code convention (a selector, a count,
or an ordering), built with typescript-eslint and eslint-plugin-svelte so
selectors see TypeScript and Svelte template nodes, never comments.
Rust is reached only through the generated bindings; events between
windows go through src/lib/windowEvents.ts, which names them and their
payloads. npm run lint runs in test.yml.
Every case in scripts/*.checks.* is now a lint rule in eslint.config.js,
a clippy setting (src-tauri/clippy.toml: no focused(false), no raw
std::env::var), a behavior test (Save As forgets a refusal, every editor
menu label is in every language, the semantic-token theme fallthrough),
or one of four Rust conventions in scripts/conventions.test.ts. The
checks files and the sourceTree helpers only they used are gone.
The export print and screen cases from export.spec.ts move into
export.print.test.ts on its helpers, and export.spec.ts goes. Its helper
now resolves var() and drops screen blocks when printing, and its paper
geometry follows the 1cm page margin.
The Windows lib test binary failed to load (STATUS_ENTRYPOINT_NOT_FOUND)
once export_bindings linked every command, dialog code included:
tauri-build puts the Common Controls v6 manifest into the app binary only.
On MSVC the linker now embeds the same manifest into every target, and
tauri-build is told not to add a second copy.
@PathGao
PathGao merged commit 3ed5675 into master Oct 26, 2026
4 checks passed
@PathGao
PathGao deleted the tests-checks-to-tools branch October 26, 2026 14:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant