Files
gitmost/apps/client/vitest.setup.ts
claude code agent 227 0647faefcd chore(comments): address PR #143 review (operator doc, badge test, dedup, type)
- [warn 1] Document the is_agent operator setup so it survives plan deletion:
  added an AI-agent block to .env.example (use a DEDICATED account, set is_agent
  via SQL, never flag a human/shared account) + a CHANGELOG "Added" entry.
- [warn 2] Test the badge deep-link side effects: ai-agent-badge.test.tsx now
  renders inside an explicit jotai store, clicks the badge, and asserts the
  active chat id, window-open, cleared draft, closed history modal, AND that
  stopPropagation keeps a parent onClick from firing.
- [suggestion 3] Hoist the window.matchMedia stub into vitest.setup.ts and drop
  the duplicated beforeAll block from the three test files (ai-agent-badge,
  comment-list-item, role-cards).
- [suggestion 4] Merge the two near-duplicate "non-clickable" cases via it.each.
- [follow-up 6] Introduce a single ProvenanceSource = 'user' | 'agent' type in
  jwt-payload.ts and reference it from AuthProvenanceData, JwtPayload/
  JwtCollabPayload, and resolveSource() — so a typo can't slip through as a bare
  string. (Server auth chain; client IComment mirroring left as a follow-up.)

Follow-up 5 (shared agentSourceFields write-stamp helper) is deferred as the
review marked it — the 6 REST sites use varied shapes (create-spread vs
resolve-conditional-null vs page move), so it's a separate focused refactor.

Tests: client badge/comment/role-cards suites 11/11 pass; server auth+comment
suites 62 pass; typecheck clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 23:56:26 +03:00

66 lines
2.4 KiB
TypeScript

// Vitest global setup (test-infra only — no production app source).
//
// Under Node 25 / jsdom 25 / vitest 4 the jsdom `localStorage` exposed on the
// global is not a usable Storage: its methods (`setItem`/`getItem`/...) are not
// callable, so any code touching `localStorage` throws `... is not a function`.
// Production code such as `isHtmlEmbedFeatureEnabled()` reads
// `localStorage.getItem("currentUser")`, which made dependent tests fail.
//
// We install a correct in-memory Storage stub on the global BEFORE tests run so
// the Web Storage contract holds: string coercion of keys/values, `null` for
// missing keys, working `length`/`key(index)`, and `clear()`.
import { vi } from "vitest";
// Minimal, spec-faithful in-memory implementation of the Web Storage API.
function createStorage(): Storage {
let store = new Map<string, string>();
const storage: Storage = {
get length(): number {
return store.size;
},
clear(): void {
store = new Map<string, string>();
},
getItem(key: string): string | null {
// Missing keys must return `null`, not `undefined`.
const value = store.get(String(key));
return value === undefined ? null : value;
},
setItem(key: string, value: string): void {
// Web Storage coerces both key and value to strings.
store.set(String(key), String(value));
},
removeItem(key: string): void {
store.delete(String(key));
},
key(index: number): string | null {
// Insertion order matches Map iteration order; out-of-range => null.
const keys = Array.from(store.keys());
return index >= 0 && index < keys.length ? keys[index] : null;
},
};
return storage;
}
// Install on the jsdom global. `vi.stubGlobal` also reflects onto `window`
// (jsdom shares `globalThis` and `window`), so both `localStorage` and
// `window.localStorage` resolve to the same working stub.
vi.stubGlobal("localStorage", createStorage());
vi.stubGlobal("sessionStorage", createStorage());
// MantineProvider (and other components) read `window.matchMedia` on mount, which
// jsdom does not implement. Provide a minimal stub here so any test rendering
// Mantine works without re-stubbing matchMedia in every file.
vi.stubGlobal("matchMedia", (query: string) => ({
matches: false,
media: query,
onchange: null,
addListener: vi.fn(),
removeListener: vi.fn(),
addEventListener: vi.fn(),
removeEventListener: vi.fn(),
dispatchEvent: vi.fn(),
}));