7c48bab1f2
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>
43 lines
1.7 KiB
TypeScript
43 lines
1.7 KiB
TypeScript
import { describe, it, expect } from "vitest";
|
|
import { canCreatePage } from "./can-create-page.ts";
|
|
import { ISpace } from "@/features/space/types/space.types.ts";
|
|
import { SpaceRole } from "@/lib/types.ts";
|
|
|
|
// Unit tests for `canCreatePage` (new-note-button.tsx). The home screen has no
|
|
// active space, so the "New note" button resolves its target from the user's
|
|
// writable spaces. This predicate mirrors the server space-ability mapping
|
|
// (ADMIN/WRITER can manage pages, READER is read-only). The /spaces list endpoint
|
|
// only returns membership.role (not CASL permissions), so a regression here would
|
|
// either hide the button for legitimate writers or offer it to read-only members.
|
|
|
|
function spaceWithRole(role?: SpaceRole): ISpace {
|
|
// Only `membership.role` is consulted by the predicate; the rest is filler.
|
|
return {
|
|
membership: role ? ({ role } as any) : undefined,
|
|
} as ISpace;
|
|
}
|
|
|
|
describe("canCreatePage", () => {
|
|
it("is true for ADMIN and WRITER roles", () => {
|
|
expect(canCreatePage(spaceWithRole(SpaceRole.ADMIN))).toBe(true);
|
|
expect(canCreatePage(spaceWithRole(SpaceRole.WRITER))).toBe(true);
|
|
});
|
|
|
|
it("is false for the READER role", () => {
|
|
expect(canCreatePage(spaceWithRole(SpaceRole.READER))).toBe(false);
|
|
});
|
|
|
|
it("is false when membership / role is missing", () => {
|
|
expect(canCreatePage(spaceWithRole(undefined))).toBe(false);
|
|
expect(canCreatePage({} as ISpace)).toBe(false);
|
|
});
|
|
|
|
it("filters an empty space list down to nothing writable", () => {
|
|
const spaces: ISpace[] = [
|
|
spaceWithRole(SpaceRole.READER),
|
|
spaceWithRole(undefined),
|
|
];
|
|
expect(spaces.filter(canCreatePage)).toHaveLength(0);
|
|
});
|
|
});
|