test(auth): restore plugin engine-hook coverage via invokeAuthHandler

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-20 01:43:38 +05:30
co-authored by Claude Opus 5
parent 7f5e1bc3cf
commit 5720f93db1
+102
View File
@@ -1,8 +1,45 @@
import { expect, test } from "bun:test";
import type { Context } from "@wrnexus/core";
import { createPluginRunner } from "@wrnexus/plugin";
import { authPlugin } from "../src/plugin.ts";
import { AUTH_ROUTE_DEFINITIONS } from "../src/routes/definitions.ts";
import { readFileSync } from "node:fs";
import { createAuthEngine } from "../src/engine.ts";
import { MemoryAuthStore } from "../src/stores/memory.ts";
import { invokeAuthHandler } from "../src/routes/api.ts";
function routeContext(request: Request): Context {
const values = new Map<string, unknown>();
return {
req: request,
url: new URL(request.url),
params: {},
locals: {},
lang: "en",
t: (key: string) => key,
ip: "127.0.0.1",
user: null,
cookies: {
get: (name: string) => (name === "wrn-csrf" ? "plugin-test-csrf-token" : undefined),
} as Context["cookies"],
localStorage: {} as Context["localStorage"],
session: {
id: () => "plugin-test-session",
get: <T>(key: string) => values.get(key) as T | undefined,
getAll: () => Object.fromEntries(values),
set: (key: string, value: unknown) => {
values.set(key, value);
},
delete: (key: string) => {
values.delete(key);
},
regenerate: () => {},
clear: () => {
values.clear();
},
},
} as Context;
}
test("plugin contributes components, runtime, styles, migration, and toolbar", async () => {
const metadata = new Map<string, unknown>();
@@ -69,6 +106,71 @@ test("config.auth controls route groups and migrations without explicit plugin o
expect(contributions.routes.some((route) => route.path === "/api/auth/login")).toBe(true);
});
test("a hook set on config.auth.engine fires when a request goes through the route layer", async () => {
const calls: string[] = [];
const engine = createAuthEngine({
store: new MemoryAuthStore(),
secret: "plugin-navigation-hooks-secret-longer-than-thirty-two-characters",
onSignedIn(ctx, returnTo) {
calls.push(`in:${returnTo}`);
return Response.redirect(new URL(returnTo ?? "/account", ctx.url), 303);
},
onSignedOut(ctx) {
calls.push("out");
return Response.redirect(new URL("/sign-in", ctx.url), 303);
},
});
await engine.register({
email: "plugin-navigation@example.com",
password: "StrongPassword123",
});
const runner = createPluginRunner(authPlugin(), {
root: process.cwd(),
mode: "development",
command: "dev",
metadata: new Map(),
warn() {},
});
await runner.configure({
auth: { engine, routes: true },
});
const loginResponse = await invokeAuthHandler(
"login",
routeContext(
new Request("https://example.test/api/auth/login", {
method: "POST",
headers: {
"content-type": "application/json",
"x-csrf-token": "plugin-test-csrf-token",
},
body: JSON.stringify({
identifier: "plugin-navigation@example.com",
password: "StrongPassword123",
returnTo: "/dashboard",
}),
}),
),
);
expect(loginResponse.status).toBe(303);
expect(loginResponse.headers.get("location")).toBe("https://example.test/dashboard");
const logoutResponse = await invokeAuthHandler(
"logout",
routeContext(
new Request("https://example.test/api/auth/logout", {
method: "POST",
headers: { "x-csrf-token": "plugin-test-csrf-token" },
}),
),
);
expect(logoutResponse.status).toBe(303);
expect(logoutResponse.headers.get("location")).toBe("https://example.test/sign-in");
expect(calls).toEqual(["in:/dashboard", "out"]);
});
test("auth runtime contains built-in browser schemas", async () => {
const metadata = new Map<string, unknown>();
const runner = createPluginRunner(authPlugin({ includeMigrations: false }), {