import assert from "node:assert/strict"; // End-to-end admin PIN flow through the real UI: enable a PIN in Settings, log out, make a // normal edit, get prompted by the login dialog the 401 triggers, reject a wrong PIN, accept // the right one, confirm the pending edit actually reaches the backend, then turn the PIN // off again so the rest of the shared suite keeps running unauthenticated. export async function runAuthSmoke({ evaluate, navigate, fill, savedState, waitFor }) { const statusText = () => evaluate(`document.querySelector("#authSettings strong")?.textContent || ""`); const openSystemTab = async () => { await navigate("settings", "settingsForm"); await evaluate(`document.querySelector('[data-settings-tab="system"]').click()`); await waitFor(async () => Boolean(await evaluate(`document.getElementById("authPinForm")`)), "admin PIN panel rendered"); }; await openSystemTab(); assert.match(await statusText(), /^Off/); await fill("authPinForm", { newPin: "4711", confirmPin: "4711" }); await evaluate(`document.getElementById("authPinForm").requestSubmit()`); await waitFor(async () => /logged in in this browser/.test(await statusText()), "PIN enabled and logged in"); await evaluate(`document.getElementById("authLogout").click()`); await waitFor(async () => /not logged in/.test(await statusText()), "logged out"); console.log("PASS enabling the admin PIN in Settings logs this browser in, and logging out works"); try { await navigate("classes", "classForm"); await fill("classForm", { name: "Auth Protected Class" }); await evaluate(`document.getElementById("classForm").requestSubmit()`); await waitFor(async () => Boolean(await evaluate(`document.getElementById("authLoginForm")`)), "a blocked save opens the PIN dialog"); assert.ok(!(await savedState()).classes.some((item) => item.name === "Auth Protected Class"), "nothing is saved without the PIN"); await evaluate(`(() => { const form = document.getElementById("authLoginForm"); form.elements.namedItem("pin").value = "0000"; form.requestSubmit(); })()`); await waitFor(async () => (await evaluate(`document.getElementById("authLoginError")?.hidden`)) === false, "wrong PIN shows an error"); await evaluate(`(() => { const form = document.getElementById("authLoginForm"); form.elements.namedItem("pin").value = "4711"; form.requestSubmit(); })()`); await waitFor(async () => !(await evaluate(`Boolean(document.getElementById("authLoginForm"))`)), "dialog closes on the right PIN"); await waitFor(async () => (await savedState()).classes.some((item) => item.name === "Auth Protected Class"), "the pending edit is saved after logging in"); console.log("PASS a save while logged out prompts for the PIN, rejects a wrong one, and goes through after the right one"); } finally { await evaluate(`fetch("/api/auth/login", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ pin: "4711" }) }).then(() => fetch("/api/auth/disable", { method: "POST" }))`); } await openSystemTab(); assert.match(await statusText(), /^Off/, "PIN protection is off again for the rest of the suite"); }