test(coverage): cover the diff for ported auth + dsr changes
Close the cover-the-diff (L1, ADR-020) gaps the port opened: - auth router: exercise the signUp/signOut procedure handlers through the container-resolved caller (reformatted onto new lines by the port). - core-dsr export: add an audit-doc case with array-valued changedFields / piiCategories and an absent actorRoles, covering the optional-field branches of the new audit-trail mapper. - coverage:diff excludes: mirror the vitest coverage excludes for core-trpc/src/providers/** and core-shared/src/trpc/context.ts so changes to coverage-excluded framework glue don't fail the diff gate. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
This commit is contained in:
@@ -66,6 +66,23 @@ describe("authRouter", () => {
|
|||||||
.toConstantValue(original);
|
.toConstantValue(original);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("signUp resolves the container controller and returns a session", async () => {
|
||||||
|
const caller = authRouter.createCaller({});
|
||||||
|
const result = await caller.signUp({
|
||||||
|
username: "carol",
|
||||||
|
password: "password_carol",
|
||||||
|
confirmPassword: "password_carol",
|
||||||
|
});
|
||||||
|
expect(result.name).toBe("session");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("signOut resolves the container controller (returns void)", async () => {
|
||||||
|
const caller = authRouter.createCaller({});
|
||||||
|
await expect(
|
||||||
|
caller.signOut({ sessionId: "some-session-id" }),
|
||||||
|
).resolves.toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("authRouter error mapping", () => {
|
describe("authRouter error mapping", () => {
|
||||||
|
|||||||
@@ -333,6 +333,71 @@ describe("PayloadDataExport — audit log in the bundle (A14)", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("maps the array-valued and absent optional audit fields", async () => {
|
||||||
|
const auditLog = new RecordingAuditLog();
|
||||||
|
const find = vi.fn(async (args: { collection: string }) => {
|
||||||
|
if (args.collection === "audit-logs") {
|
||||||
|
return {
|
||||||
|
docs: [
|
||||||
|
{
|
||||||
|
id: "log-2",
|
||||||
|
actorId: "alice",
|
||||||
|
actorType: "user",
|
||||||
|
// actorRoles absent → the `: []` default branch
|
||||||
|
action: "UPDATE",
|
||||||
|
resourceType: "subject-data",
|
||||||
|
resourceId: "row-9",
|
||||||
|
// array-valued optionals → the Array.isArray true branches
|
||||||
|
changedFields: ["displayName", "email"],
|
||||||
|
scopeFeature: "core-dsr",
|
||||||
|
scopeEnvironment: "test",
|
||||||
|
scopeTenant: "default",
|
||||||
|
reason: "art-16-request",
|
||||||
|
correlationId: "corr-2",
|
||||||
|
requestId: "req-2",
|
||||||
|
ipTruncated: "203.0.113.0",
|
||||||
|
userAgent: "agent",
|
||||||
|
containsPii: true,
|
||||||
|
piiCategories: ["contact-email", "identification-username"],
|
||||||
|
outcome: "success",
|
||||||
|
errorCode: "none",
|
||||||
|
createdAt: "2026-02-02T00:00:00.000Z",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return { docs: [{ id: "alice", email: "a@ex.com" }] };
|
||||||
|
});
|
||||||
|
const getPayload = vi.fn(async () => ({ find }));
|
||||||
|
const config = {
|
||||||
|
collections: [
|
||||||
|
{
|
||||||
|
slug: "users",
|
||||||
|
custom: {
|
||||||
|
subject: { field: "id", kind: "self" },
|
||||||
|
pii: { email: { exportable: true } },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ slug: "audit-logs" },
|
||||||
|
],
|
||||||
|
} as unknown as SanitizedConfig;
|
||||||
|
|
||||||
|
const exporter = new PayloadDataExport(config, auditLog, getPayload);
|
||||||
|
const bundle = await exporter.exportSubjectData("alice", "json");
|
||||||
|
|
||||||
|
const entry = bundle.auditLog![0]!;
|
||||||
|
expect(entry.actorRoles).toEqual([]);
|
||||||
|
expect(entry.changedFields).toEqual(["displayName", "email"]);
|
||||||
|
expect(entry.piiCategories).toEqual([
|
||||||
|
"contact-email",
|
||||||
|
"identification-username",
|
||||||
|
]);
|
||||||
|
expect(entry.reason).toBe("art-16-request");
|
||||||
|
expect(entry.requestId).toBe("req-2");
|
||||||
|
expect(entry.errorCode).toBe("none");
|
||||||
|
expect(entry.resource).toEqual({ type: "subject-data", id: "row-9" });
|
||||||
|
});
|
||||||
|
|
||||||
it("leaves bundle.auditLog undefined when the audit-logs collection is absent", async () => {
|
it("leaves bundle.auditLog undefined when the audit-logs collection is absent", async () => {
|
||||||
const config = makeMockConfig([
|
const config = makeMockConfig([
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -65,6 +65,12 @@ const ALLOWED_GLOBS = [
|
|||||||
/\/application\/services\//,
|
/\/application\/services\//,
|
||||||
/\/integrations\/cms\//,
|
/\/integrations\/cms\//,
|
||||||
/\/ui\//,
|
/\/ui\//,
|
||||||
|
// core-trpc React context providers — excluded from vitest coverage in
|
||||||
|
// core-trpc/vitest.config.ts ("integration-tested in the apps").
|
||||||
|
/\/src\/providers\//,
|
||||||
|
// core-shared tRPC context factory — excluded from vitest coverage in
|
||||||
|
// core-shared/vitest.config.ts ("wired at app bootstrap, not unit-testable").
|
||||||
|
/\/src\/trpc\/context\.ts$/,
|
||||||
// Tooling packages that don't generate a vitest lcov (no @vitest/coverage-v8)
|
// Tooling packages that don't generate a vitest lcov (no @vitest/coverage-v8)
|
||||||
/^packages\/core-testing\//,
|
/^packages\/core-testing\//,
|
||||||
/^packages\/core-eslint\//,
|
/^packages\/core-eslint\//,
|
||||||
|
|||||||
Reference in New Issue
Block a user