52 lines
2.2 KiB
TypeScript
52 lines
2.2 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { loginErrorMessage } from "./login-errors";
|
|
|
|
const errorResponse = (status: number, payload: unknown) => new Response(JSON.stringify(payload), { status });
|
|
|
|
describe("login error messages", () => {
|
|
it("identifies a site security rejection without blaming the account", async () => {
|
|
expect(await loginErrorMessage(errorResponse(403, { detail: "Cross-origin state change rejected" }))).toBe(
|
|
"Sign-in was blocked by the site's security configuration. Please contact an administrator.",
|
|
);
|
|
});
|
|
|
|
it.each(["User is blocked", "User access has expired", "Unknown upstream error"])(
|
|
"keeps a generic account message for %s",
|
|
async (detail) => {
|
|
expect(await loginErrorMessage(errorResponse(403, { detail }))).toBe(
|
|
"This account cannot sign in. Please contact an administrator.",
|
|
);
|
|
},
|
|
);
|
|
|
|
it.each([
|
|
null,
|
|
[],
|
|
{ detail: ["Cross-origin state change rejected"] },
|
|
{ detail: "Cross-origin state change rejected: private upstream detail" },
|
|
{ detail: "<script>private upstream detail</script>" },
|
|
])("does not render or loosely match unexpected response bodies: %j", async (payload) => {
|
|
expect(await loginErrorMessage(errorResponse(403, payload))).toBe(
|
|
"This account cannot sign in. Please contact an administrator.",
|
|
);
|
|
});
|
|
|
|
it("handles a non-JSON proxy denial safely", async () => {
|
|
expect(await loginErrorMessage(new Response("<html>Forbidden</html>", { status: 403 }))).toBe(
|
|
"This account cannot sign in. Please contact an administrator.",
|
|
);
|
|
});
|
|
|
|
it.each([
|
|
[401, "Check your username and password, then try again."],
|
|
[400, "Check your username and password, then try again."],
|
|
[429, "Too many attempts. Please wait a moment and try again."],
|
|
[500, "Sign-in is temporarily unavailable. Please try again shortly."],
|
|
[502, "Sign-in is temporarily unavailable. Please try again shortly."],
|
|
])("preserves the existing message for HTTP %s", async (status, expected) => {
|
|
expect(
|
|
await loginErrorMessage(errorResponse(status as number, { detail: "Cross-origin state change rejected" })),
|
|
).toBe(expected);
|
|
});
|
|
});
|