Commit Graph

7 Commits

Author SHA1 Message Date
claude code agent 227 baa41d66ad test(infra): coverage-gate + acceptInvitation atomicity int-spec + turn-end unit (#324)
Tail of #244. Three items:

1. Coverage-gate (main). develop had no coverage tooling at all. Added
   @vitest/coverage-v8@4.1.6 (pinned to the vitest already in use) to the three
   vitest packages — git-sync, editor-ext (which also gains its missing direct
   `vitest` devDep), apps/client — and enabled v8 coverage with per-package
   thresholds (no root vitest config exists, so per-package is the only
   meaningful scope). v8 provider is chosen deliberately: istanbul broke on the
   ESM `@docmost/editor-ext` barrel; v8 collects native runtime coverage and
   never re-parses ESM. `enabled: true` wires the gate into the plain `test`
   script, so `pnpm -r test` (the CI entrypoint) enforces it without a manual
   `--coverage`. Thresholds set ~4-5 pts below measured current coverage so the
   gate PASSES today and FAILS on regression (verified: forcing lines=95 on
   editor-ext exits 1). `all: false` — coverage counts test-touched files;
   documented in the configs (with `all: true` the many untested type/barrel
   files would sink the % and make the gate meaningless).
   Measured→threshold (S/B/F/L): git-sync 91.78/79.16/76.76/92.46 → 88/75/72/88;
   editor-ext 58.58/48.1/64.96/58.91 → 54/44/60/54; client 59.93/58/48.47/59.39
   → 55/53/44/55. All exit 0.

2. acceptInvitation atomicity int-spec. New
   apps/server/test/integration/workspace-accept-invitation-atomicity.int-spec.ts
   (+ createDefaultGroup/createInvitation seeders in test/integration/db.ts per
   its convention). Wires the real WorkspaceInvitationService with real
   User/Group/GroupUser repos against the test Kysely, stubbing only the
   post-commit collaborators. Asserts the invariant protected by
   users_email_workspace_id_unique: (a) two CONCURRENT accepts → exactly one
   fulfilled, one BadRequestException('Invitation already accepted'), membership
   count == 1, invitation consumed; (b) repeated sequential accept → still one
   membership; (c) the survivor is in the workspace default group (whole-tx, no
   torn state). Ran against real Postgres+Redis: 3/3 pass.

3. turn-end decision unit test. `decideTurnEnd` does not exist as a symbol; the
   turn-end logic lives in chat-thread.tsx's onFinish handler. Added a focused
   block to the existing chat-thread.test.tsx (matching its hoisted-mock style):
   clean finish → flush queued (continue); abort/disconnect/error → queue
   preserved (end) with the correct notice; parent notified on every terminal
   outcome. 8 passed (3 existing + 5 new).

Verified: git-sync 712, editor-ext 247, client 888 (all with the gate, exit 0);
int-spec 3/3 (real Postgres); tsc --noEmit clean for client + server;
pnpm install --frozen-lockfile consistent (lockfile additive).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 12:37:28 +03:00
claude code agent 227 caac5c7f36 test(html-embed): exercise the REAL admin-gate write paths + import round-trip
Release-cycle test audit: the strip boundary was tested only via a stand-in
helper re-implemented in the spec, so a deleted/misplaced guard kept CI green
(the missing create() guard was proof). Replace it with tests against real code:
- persistence.extension.onStoreDocument: real ydoc from a rich doc (columns/
  table/mention/htmlEmbed) -> non-admin strip removes only htmlEmbed, every other
  node preserved (data-loss guard); admin keeps; empty fragment no-throw.
- collaboration.handler.updatePageContent: real path, user?.role gate, decoded
  ydoc embed-free for non-admin, kept for admin.
- transclusion unsync: member stripped, admin preserved.
- editor-ext gains a vitest setup (was zero tests) + a markdown round-trip:
  the <!--html-embed:BASE64--> marker -> htmlEmbed node with decoded source, and
  hasHtmlEmbedNode matches it — pinning the marked/turndown shape the import
  strip relies on. tsconfig now excludes specs from the shipped dist.
- Fail-closed identity: source-pinned contracts that the gate keys on
  fileTask.creatorId (zip) / request userId (single) / callerRole (create) /
  authUser.role (duplicate), and missing-user -> strip (services can't load under
  jest's ESM graph; helpers replay the exact predicate).
Adds the verified-safe ^src/ jest moduleNameMapper (identical fail set).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 14:52:29 +03:00
Philipinho bca85a49d6 pin marked version 2026-03-29 03:03:35 +01:00
Philip Okugbe 5506eb194b feat: page history diff (#1891)
* Show actual history changes
* V2 - WIP
* feat: page history diff
* fix: exclude content from history listing

---------

Co-authored-by: Jason Norwood-Young <jason@10layer.com>
2026-02-03 11:55:20 -08:00
Philip Okugbe 38e9eef2dc feat: excalidraw integration (#214)
* update tiptap version

* excalidraw init

* cleanup

* better file handling and other fixes

* use different modal to fix excalidraw cursor position issue
* see https://github.com/excalidraw/excalidraw/issues/7312
* fix websocket in vite dev mode

* WIP

* add align attribute

* fix table

* menu icons

* Render image in excalidraw html
* add size to custom SVG components

* rewrite undefined font urls
2024-08-31 19:11:07 +01:00
Philipinho 1f4bd129a8 editor improvements
* add callout, youtube embed, image, video, table, detail, math
* fix attachments module
* other fixes
2024-06-20 14:57:00 +01:00
Philipinho 9a8b605f70 * add new tiptap editor extension monorepo package
* move tiptap packages to main package.json
* add tiptap extensions schema to collaborative backend
* add basic README
2024-01-14 23:05:41 +01:00