test: unit tests for the 10 candidates (#139) #142

Merged
vvzvlad merged 1 commits from test/unit-tests-139 into develop 2026-06-23 04:16:51 +03:00

Implements the 10 unit-test candidates from #139 (gap-audit of the QA plan). Tests-only PR, with three minimal, behavior-preserving extractions the issue called for.

Test files (path → #tests)

  1. dictation/utils/encode-wav.test.ts — 7 (WAV header + PCM16 clamp)
  2. editor-ext/embed-provider.spec.ts — 19 (all 11 providers: canonical / already-embed / junk)
  3. editor-ext/utils.spec.ts — 8 (sanitizeUrl XSS boundary, isInternalFileUrl)
  4. editor-ext/indent.spec.ts — 6 (clampIndent 0..8)
  5. label/dto/label.dto.spec.ts — 6 (name regex; ~ only non-leading)
  6. page/dto/move-page.dto.spec.ts — 3 (incl. 1 test.failing — see below)
  7. home/components/can-create-page.test.ts — 4 (role gate)
  8. page-history/components/history-diff.test.ts — 7 (diff decorations + counts)
  9. notification/notification.constants.spec.ts — 6 (incl. 1 test.failing)
  10. search/search.service.spec.ts — +8 (buildTsQuery adversarial inputs)

Minimal extractions (so the logic is purely testable)

  • #7 canCreatePage → new sibling can-create-page.ts (importing the component pulls in main.tsx).
  • #8 pure computeHistoryDiff(...) → new history-diff.ts; history-editor.tsx imports it (editor side-effects stay in the component).
  • #10 buildTsQuery(raw) extracted in search.service.ts and now sanitizes the input (strips all but Unicode letters/numbers/whitespace) so operator inputs (&,!,*,<->,\) degrade to a safe/empty query instead of a to_tsquery 500 — while normal/accented/CJK queries are unchanged.

Two genuine bugs locked via test.failing (suite stays green, flips red when fixed)

  • #6 MovePageDto.position @MaxLength(12) rejects dense fractional-index keys that generateJitteredKeyBetween legitimately produces (13+ chars) → a move in a deep tree 400s. (A fresh key is ~5 chars and passes @MinLength(5).)
  • #9 the 'direct' tab whitelist (5 types) diverges from the notification repo's type != PAGE_UPDATED filter (which also returns verification/approval types). 'updates' matches exactly (green).

Verification

editor-ext build clean; client+server tsc clean; all new suites green (editor-ext 32, client 18, server 31 = 81), no regressions in the touched existing suites (search, editor-ext full).

🤖 Generated with Claude Code

Implements the 10 unit-test candidates from #139 (gap-audit of the QA plan). Tests-only PR, with three **minimal, behavior-preserving** extractions the issue called for. ### Test files (path → #tests) 1. `dictation/utils/encode-wav.test.ts` — 7 (WAV header + PCM16 clamp) 2. `editor-ext/embed-provider.spec.ts` — 19 (all 11 providers: canonical / already-embed / junk) 3. `editor-ext/utils.spec.ts` — 8 (`sanitizeUrl` XSS boundary, `isInternalFileUrl`) 4. `editor-ext/indent.spec.ts` — 6 (`clampIndent` 0..8) 5. `label/dto/label.dto.spec.ts` — 6 (name regex; `~` only non-leading) 6. `page/dto/move-page.dto.spec.ts` — 3 (incl. 1 `test.failing` — see below) 7. `home/components/can-create-page.test.ts` — 4 (role gate) 8. `page-history/components/history-diff.test.ts` — 7 (diff decorations + counts) 9. `notification/notification.constants.spec.ts` — 6 (incl. 1 `test.failing`) 10. `search/search.service.spec.ts` — +8 (`buildTsQuery` adversarial inputs) ### Minimal extractions (so the logic is purely testable) - **#7** `canCreatePage` → new sibling `can-create-page.ts` (importing the component pulls in `main.tsx`). - **#8** pure `computeHistoryDiff(...)` → new `history-diff.ts`; `history-editor.tsx` imports it (editor side-effects stay in the component). - **#10** `buildTsQuery(raw)` extracted in `search.service.ts` and now **sanitizes** the input (strips all but Unicode letters/numbers/whitespace) so operator inputs (`&`,`!`,`*`,`<->`,`\`) degrade to a safe/empty query instead of a `to_tsquery` 500 — while normal/accented/CJK queries are unchanged. ### Two genuine bugs locked via `test.failing` (suite stays green, flips red when fixed) - **#6** `MovePageDto.position` `@MaxLength(12)` rejects dense fractional-index keys that `generateJitteredKeyBetween` legitimately produces (13+ chars) → a move in a deep tree 400s. (A fresh key is ~5 chars and passes `@MinLength(5)`.) - **#9** the `'direct'` tab whitelist (5 types) diverges from the notification repo's `type != PAGE_UPDATED` filter (which also returns verification/approval types). `'updates'` matches exactly (green). ### Verification editor-ext build clean; client+server `tsc` clean; **all new suites green** (editor-ext 32, client 18, server 31 = 81), no regressions in the touched existing suites (`search`, editor-ext full). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Ghost added 1 commit 2026-06-23 04:15:40 +03:00
Adds co-located unit tests for ten targets (client → vitest *.test.ts(x),
server → jest *.spec.ts), plus minimal behavior-preserving extractions/exports
where the issue required a pure function to test:

- encode-wav: WAV header + PCM16 clamping
- editor-ext embed-provider / utils (sanitizeUrl, isInternalFileUrl) / indent
  (export clampIndent)
- label.dto @Matches regex
- move-page.dto vs generateJitteredKeyBetween parity (bug locked via test.failing)
- new-note-button canCreatePage (extracted to can-create-page.ts)
- history-editor diff (extracted pure computeHistoryDiff into history-diff.ts)
- notification getTypesForTab + repo contract (direct-tab divergence locked via
  test.failing)
- search buildTsQuery (extracted + sanitizes operator inputs so adversarial
  queries no longer risk a to_tsquery 500)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
vvzvlad merged commit 0fabaa5bfb into develop 2026-06-23 04:16:51 +03:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: vvzvlad/gitmost#142