TEST_STRATEGY.md — Confluence Expansion Testing (Phase 0)
Stack (unchanged, per ARCHITECTURE.md §12): Vitest/Jest unit (co-located), Jest + Testcontainers integration (
tests/integration/), Playwright E2E (tests/e2e/specs/), k6 performance (tests/performance/), OWASP/ASVS security suites (tests/security/). Existing baselines: 171 unit files, 33 integration suites, 34 E2E specs.
1. Principles
- Every task ships tests before it closes (AGENTS.md DoD). A feature is not done when its UI exists — done when its API + negative paths are proven.
- Negative cases are mandatory for every permission-adjacent feature (spec §22; SECURITY_REVIEW.md §4 is the master negative-test list).
- Regression guard: the existing 33 integration suites + 34 E2E specs
(incl.
final-flow.spec.ts) run on every change; the 100k-profile perf lane gates the migration + new hot queries. - Upgrade test: post-migration, run the full integration suite against a copy of the current dev DB (spec §18) — proves existing data survives.
- Determinism: all tests use the existing seam/fixtures patterns
(
tests/integration/helpers/,apps/api/src/modules/internal/test seams); no network, no real AI provider (AI tests use the existing mock gateway seam from Phase 12).
2. Unit tests (new, co-located)
| Area | What | Where |
|---|---|---|
| Block-tree diff (version compare) | LCS over block ids; content-hash changed detection; empty diff; large-tree perf (10k blocks < 200 ms) | packages/shared/src/diff/… + tests |
| Template variable substitution | Typed substitution, missing-variable behavior, length limits, no HTML interpretation | apps/api/src/modules/templates/… (pages module) |
| Review transition matrix | All legal/illegal transitions (draft→in_review→approved/changes→published, withdraw) | apps/api/src/modules/pages/review.service.ts |
| Backlink filter | canView filtering of sources, fail-closed | pages module |
| CSV import parsing | Header mapping, type coercion per property type, row error collection, formula-cell escaping, size caps | databases module |
| Whiteboard schema (v1) | Zod round-trip, object count/size limits, freehand decimation, grouping bounds, connector endpoints, schemaVersion gate (property tests, 200 random canvases) | packages/whiteboard/… |
| Task inbox query builder | Scope (inbox/all), status, due filters, idempotent reminder key | tasks module |
| Recent-items FIFO | Cap 50, dedupe on (itemType, refId), per-user isolation | search module |
| AI capability prompts/tools | Tool schema validation, citation-only source ids, permission-filtered doc set (mock retriever) | ai module |
| Activity feed projection | Audit-action whitelist, permission filtering | notifications module |
3. Integration tests (Testcontainers; tests/integration/)
New suites (one file per domain, mirroring existing naming):
spaces.integration.test.ts— directory scoping (member vs non-member → no-leak 404), stats authorization, archive/restore, cross-workspace move (dual permission: edit-source + create-destination; negative: view-only source → 403).pages-bulk-duplicate.integration.test.ts— duplicate recursion (blocks, database snapshot, comments NOT copied, positions re-based), bulk action partial failure (3/5 authorized → per-id codes), audit events present.backlinks.integration.test.ts— reference via child_page/synced_block/ linked_database/comment mention → appears; private source → filtered; cache bust after reference change.templates.integration.test.ts— categories/search, variable instantiation (valid + invalid values → 400), builtin edit/delete → 403, version create/restore (restore = new version), default-template setting.version-compare.integration.test.ts— compare add/remove/change; compare == identical → empty; preview authz; revocation → 403; restore appends (length +1, old versions intact).review-workflow.integration.test.ts— full happy path (submit → approve → published) + every illegal transition → 400/403; notifications delivered (REVIEW_REQUESTED to reviewers, APPROVAL_DECISION to editor); audit before/after state.tasks.integration.test.ts— create/assign/status; inbox scoping (user A never sees user B's unshared task pages); due reminder idempotency (job key fires once); task block permissions.whiteboards.integration.test.ts— canvas write/read round-trip; oversize canvas → 413; unknown schemaVersion → read-only flag; page-permission inheritance (non-member → 404); comment attach; version snapshot on save; convert-selection → page blocks.csv-import.integration.test.ts— dry-run mapping, 1k-row import, per-row errors, re-import idempotency guard, file-pipeline integration (scan step).search-extras.integration.test.ts— recent items per-user isolation, saved searches, related-pages section, label/lifecycle filters, reindex job idempotency + grant rebuild (stale grant removed after revocation).activity-watches.integration.test.ts— feed permission filtering (non-member events excluded), watch fan-out with recheck (revoked watcher not notified).ai-assistant-capabilities.integration.test.ts(mock gateway seam) — extract-actions creates tasks as requester; generate-faqs page real blocks; find-duplicates permission-filtered; negative: doc not viewable by requester → never retrieved/cited (extends ai-security pattern); find-stale/suggest-metadata output shape.
4. E2E tests (Playwright, tests/e2e/specs/)
Maps to spec §22 user journeys (1–14) — the existing 34 specs already cover journeys 1, 3, 4, 7, 14 partially; new specs:
confluence-spaces.spec.ts— journey 1 extended: create typed space → directory shows it → stats → archive/restore.confluence-templates.spec.ts— journey 2: create from built-in template (meeting notes) with variables → editable blocks → template versioned.confluence-versions.spec.ts— journey 5: edit → compare two versions (diff UI) → restore → history +1, old version intact.confluence-collaboration.spec.ts— journey 6: inline comment with selection survives an edit to the same block → mention → notify → resolve; deep link opens page + highlights comment.confluence-search.spec.ts— journeys 7+8: search finds permitted; restricted page absent (already partially insearch.spec.ts— extend with recently-viewed tab + saved search + related section).confluence-databases.spec.ts— journey 9 extended: CSV import → records in all views; saved view management.confluence-whiteboard.spec.ts— journey 10: create whiteboard page → sticky note + shape + connector + freehand → undo/redo → reload survives → convert selection → page.confluence-tasks-reviews.spec.ts— journey 11: create task from page reference → assign → due reminder → submit page for review → approve → state chip + notifications.confluence-ai.spec.ts— journey 12: ask AI → extract actions → tasks appear in inbox; verify citations + a restricted doc is not cited.confluence-export.spec.ts— journey 13: export authorized content (CSV + share link) — regression.confluence-regression.spec.ts— journey 14: final-flow re-run + the 14 new surfaces smoke.
Plus: concurrency (two-browser whiteboard LWW notice + page CRDT unchanged), permission revocation (each new surface), large whiteboard (2,000 objects render < 2 s), keyboard/a11y pass on the new dialogs (WCAG 2.2 AA, same conventions as existing specs).
5. Security tests (tests/security/ extensions)
- Extend the ASVS suite: new endpoints enumerated in the endpoint-coverage matrix (no endpoint without an authz test).
- Negative matrix per SECURITY_REVIEW.md §4 (9 items) — each is an explicit test case, not an assertion inside another test.
- XSS: whiteboard object label + template variable value → rendered escaped (Playwright DOM assertion).
- IDOR sweep script extended with all new ids (whiteboard, task, review, template version, saved search).
- Dependency scan unchanged (no new deps expected — whiteboard is in-house; if any dep is added, license review is a blocking gate, spec §2.13).
6. Performance (k6, tests/performance/)
- New profiles: backlinks query (100k-page workspace), task inbox (10k tasks), whiteboard 2,000-object render (browser-side metric in E2E), version compare (10k-block doc), CSV import 10k rows (throughput + memory).
- Gates: backlinks p95 < 100 ms (else A-008 upgrade trigger fires), inbox p95 < 200 ms, compare p95 < 500 ms.
- Existing 100k fixtures reused; new seed helper
seed-tasks-whiteboards.mjs.
7. Coverage targets
- New service logic: ≥ 90% branch (repo convention for engines/services).
- New Zod schemas: 100% of schema files exercised in unit tests.
- E2E: every user journey in spec §22 has ≥ 1 green spec before release.
- Security: 100% of new endpoints in the negative-test matrix.
8. CI wiring
New suites join the existing lanes (no new infrastructure):
lint → typecheck → unit → integration → build → security → e2e, with the
perf lane (report-only in dev, hard gates in staging per existing convention).
Docker-gated E2E follows the committed-CI-ready convention used in Phase 7–8.