Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
46 changes: 24 additions & 22 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,23 @@ compiler cannot check — a Tauri command name, an i18n key, a second copy of a
behavior. A green run is not a claim that every behavior is covered; a source-shape
assertion passes as long as the line it matches is still spelled that way.

### Where a test goes

Tests are grouped by feature, not by the fix that added them:

- `scripts/<feature>.test.ts` and `scripts/<feature>.spec.ts` hold behavior tests (the
runner rules below decide which of the two).
- `scripts/<feature>.checks.test.ts` / `.checks.spec.ts` hold the cases that read source as
text, kept apart from the behavior tests.
- `scripts/<feature>.<area>.test.ts` / `.spec.ts` is for a part of a feature that must run
in its own process (module mocks, a process-wide shim such as `installShimDom()`) or would
make the main file unreadable.

A new case goes into the existing file for its feature, as a `test` inside the `describe`
it belongs to or a new `describe`. A new file is for a new feature or one of the reasons
above, not for a new fix. Name a test by the behavior it claims; put the issue number and
the bug history in a comment above it.

### Which runner a test belongs to

**Write it as `*.spec.ts` (vitest) when the subject is a `.svelte.ts` runes module, or when
Expand Down Expand Up @@ -215,34 +232,19 @@ unchanged. Two things bite:
answer, so a bare `invoke: () => Promise.resolve(null)` leaves `osType` null and the
font defaults it indexes undefined.

One shimmed file is still where it is, because a rename does not reach what is wrong
with it:

- `foldStatePerDocument.test.ts` cuts functions out of `.svelte` files with its own
brace-pairing scanner. The logic has to move into a `.svelte.ts` module first.

Of the other two:

- `tabReadingPosition.test.ts` called `installShimDom()`, which assigns
`globalThis.document` — under vitest that replaces jsdom's. Its anchor harness was
rewritten onto the real DOM (`tabReadingPosition.spec.ts`), which it could be because
`findAnchorElement` reads structure and attributes and measures nothing.
- `checkedReadMigration.test.ts` was two files in one, which is why neither answer fit
it. Six of its tests are the never-migrate categories — an unchecked command existing
nowhere in `src` *or* in the Rust crate, and four statement-order claims about a
`.svelte` component — and stayed. The three that drive `ensureFullContent` are a runes
module run for real, and are `checkedReadMigration.spec.ts` now. A file that shims
runes is worth opening before it is worth renaming: the split may be per test rather
than per file.
A test that shims runes is worth reading before it is worth moving: the split may be per
test rather than per file. A harness that calls `installShimDom()` assigns
`globalThis.document`, which under vitest replaces jsdom's; such a harness is rewritten onto
the real DOM rather than carried over.

### A real DOM is not a layout

jsdom implements the DOM, not CSS layout: `offsetTop`, `offsetHeight` and every
`getBoundingClientRect()` are 0. So migrating a file buys real answers about structure,
attributes, traversal and parsing, and buys nothing at all about geometry. A test whose
subject is a position on screen has to construct the boxes either way —
`scrollSyncAcrossFolds.test.ts` lays a document out with collapsed folds in it, and
`anchorJumpUnderZoom.spec.ts` builds elements whose rects carry a zoom factor while their
`layout.scrollSync.test.ts` lays a document out with collapsed folds in it, and
`navigation.spec.ts` builds elements whose rects carry a zoom factor while their
`offsetWidth` does not. Neither is worse for being under `node --test` or better for being
under vitest; the geometry is the fixture.

Expand Down Expand Up @@ -283,7 +285,7 @@ mandatory for `tauri-plugin-updater` to compare versions correctly.
The lock file is the one that gets forgotten, because nothing in the editing
loop reads it — a bump without it lands green and stays wrong until the next
person's `cargo build` rewrites the line and leaves them a dirty working tree.
`scripts/versionSync.test.ts` asserts the three agree.
`scripts/release.checks.test.ts` asserts the three agree.

## Releasing

Expand Down
4 changes: 2 additions & 2 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ If you ever lose the private key:

### 5. `alecdotdev/Markpad` is load-bearing

The updater endpoint in `src-tauri/tauri.conf.json` points at **`sftwrdotdev/Markpad`**. (`scripts/releaseWorkflow.test.ts` holds that name and the endpoint together — if the repository ever moves again, this line moves with it.)
The updater endpoint in `src-tauri/tauri.conf.json` points at **`sftwrdotdev/Markpad`**. (`scripts/release.checks.test.ts` holds that name and the endpoint together — if the repository ever moves again, this line moves with it.)

That only helps builds made from here on. The endpoint is compiled into the binary, so every copy up to and including v2.7.0 asks GitHub for `https://github.com/alecdotdev/Markpad/releases/latest/download/latest.json` and reaches the current feed only because GitHub answers with a 301. Those installs use that redirect for as long as they run.

Expand Down Expand Up @@ -112,7 +112,7 @@ Back it up in the same place as the minisign private key, and treat it with the

## Per-release workflow

The workflow uses `npm ci`, so its installed dependency graph is exactly the committed lockfile. Do not replace it with `npm install` in release jobs. `scripts/releaseWorkflow.test.ts` guards that.
The workflow uses `npm ci`, so its installed dependency graph is exactly the committed lockfile. Do not replace it with `npm install` in release jobs. `scripts/release.checks.test.ts` guards that.

[`snapcraft.yaml`](snapcraft.yaml) builds nothing. It packages the `.deb` the release already shipped (`plugin: dump`, `source-type: deb`), so the snap carries the same binary as the `.deb` and the AppImage. The same test asserts it is packaging rather than building.

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
"preview": "vite preview",
"test": "node --test --import tsx \"scripts/*.test.ts\"",
"test:vitest": "vitest run",
"test:frontmatter": "node --test --import tsx scripts/frontMatter.test.ts scripts/frontMatterProseBlock.test.ts",
"test:workflows": "node --test --import tsx scripts/exportHtml.test.ts scripts/exportOpenPrompt.test.ts scripts/editorToolbar.test.ts scripts/titlebarToolbar.test.ts",
"test:frontmatter": "node --test --import tsx scripts/editing.test.ts scripts/editing.checks.test.ts",
"test:workflows": "node --test --import tsx scripts/export.test.ts scripts/shortcuts.toolbar.test.ts",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"build:test-bundle": "node scripts/build-test-bundle.mjs",
Expand Down
100 changes: 0 additions & 100 deletions scripts/anchorJumpUnderZoom.spec.ts

This file was deleted.

16 changes: 0 additions & 16 deletions scripts/assetScopeDotDirs.test.ts

This file was deleted.

121 changes: 0 additions & 121 deletions scripts/backgroundEditorPosition.test.ts

This file was deleted.

50 changes: 0 additions & 50 deletions scripts/calloutMarker.test.ts

This file was deleted.

Loading
Loading