WFDASH-WEBAPP/src/lib/dev-identity.test.ts
SJCoetz 05abe499b0 feat(sprint): add new sprint pricing workflow and supporting code
Add full sprint pricing workflow and supporting infrastructure:
- New sidebar navigation entry for the sprint dashboard
- PocketBase category collection schema and migration script
- Server API routes for sprint item claims, attachments, counts, and file proxying
- Dev identity utilities and UI switcher for multi-user testing
- Reusable FilterTabs component replacing ItemStatusTabs
- Updated TypeScript types for sprint-related entities

Also include:
- Fix PocketBase file URL method casing (getUrl → getURL) across codebase
- Add development utility, smoke test, and helper scripts
- Update package.json with new sprint migration command
2026-07-03 07:29:43 +02:00

101 lines
2.9 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
DEFAULT_DEV_EMAIL,
DEV_IDENTITY_COOKIE,
DEV_IDENTITY_HEADER,
getServerIdentity,
} from "./dev-identity";
import type { NextRequest } from "next/server";
/**
* Minimal NextRequest stub — only the bits getServerIdentity reads.
* Avoids pulling in Next's actual class for unit tests.
*/
function makeReq(opts: {
header?: string;
cookie?: string;
envEmail?: string;
}): NextRequest {
const headers = new Headers();
if (opts.header) headers.set(DEV_IDENTITY_HEADER, opts.header);
// Build a minimal cookie jar NextRequest understands.
const cookieValue = opts.cookie
? `${DEV_IDENTITY_COOKIE}=${opts.cookie}`
: "";
const req = {
headers,
cookies: {
get(name: string) {
if (name !== DEV_IDENTITY_COOKIE) return undefined;
if (!cookieValue) return undefined;
// mimic NextRequest's behavior: returns the raw value
const eq = cookieValue.indexOf("=");
return { name, value: cookieValue.slice(eq + 1) };
},
},
} as unknown as NextRequest;
if (opts.envEmail !== undefined) {
process.env.DEV_USER_EMAIL = opts.envEmail;
} else {
delete process.env.DEV_USER_EMAIL;
}
return req;
}
describe("getServerIdentity", () => {
it("returns the X-User-Email header when present", () => {
const req = makeReq({ header: "alice@example.com" });
expect(getServerIdentity(req)).toBe("alice@example.com");
});
it("falls back to the cookie when the header is missing", () => {
const req = makeReq({
cookie: encodeURIComponent("bob@example.com"),
});
expect(getServerIdentity(req)).toBe("bob@example.com");
});
it("falls back to DEV_USER_EMAIL when header and cookie are missing", () => {
const req = makeReq({ envEmail: "ci@example.com" });
expect(getServerIdentity(req)).toBe("ci@example.com");
});
it("falls back to the default when nothing is set", () => {
const req = makeReq({});
expect(getServerIdentity(req)).toBe(DEFAULT_DEV_EMAIL);
});
it("prefers the header over the cookie", () => {
const req = makeReq({
header: "header@example.com",
cookie: encodeURIComponent("cookie@example.com"),
});
expect(getServerIdentity(req)).toBe("header@example.com");
});
it("prefers the cookie over the env default", () => {
const req = makeReq({
cookie: encodeURIComponent("cookie@example.com"),
envEmail: "env@example.com",
});
expect(getServerIdentity(req)).toBe("cookie@example.com");
});
it("trims whitespace from all sources", () => {
const req = makeReq({ header: " spaced@example.com " });
expect(getServerIdentity(req)).toBe("spaced@example.com");
});
it("ignores empty values and falls through to the next source", () => {
const req = makeReq({
header: " ",
cookie: encodeURIComponent(" "),
envEmail: "env@example.com",
});
expect(getServerIdentity(req)).toBe("env@example.com");
});
});