Files
WRNexusJS/packages/auth/test/components.test.ts
T
Clintchiz 2c960fc1dc
Quality / quality (ubuntu-latest) (push) Failing after 9m49s
Quality / quality (windows-latest) (push) Canceled after 0s
refactor: migrate legacy wire namespace to wrn
2026-08-12 18:51:15 +05:30

111 lines
4.7 KiB
TypeScript

import { expect, test } from "bun:test";
import { readdirSync, readFileSync } from "node:fs";
import { join } from "node:path";
const directory = join(import.meta.dir, "..", "components");
test("all authentication components use theme tokens and Tailwind utilities", () => {
const files = readdirSync(directory).filter((file) => file.endsWith(".wrn"));
expect(files.length).toBeGreaterThanOrEqual(16);
for (const file of files) {
const source = readFileSync(join(directory, file), "utf8");
expect(source).toContain("component ");
expect(source).toContain("--wrn-");
expect(source).not.toContain("<style");
}
});
test("passkey component declares the automatic package runtime", () => {
const source = readFileSync(join(directory, "PasskeyButton.wrn"), "utf8");
expect(source).toContain('data-wrnexus-runtime="auth"');
expect(source).not.toContain("<script");
});
test("SignIn exposes a slot for CAPTCHA and application-specific controls", () => {
const source = readFileSync(join(directory, "SignIn.wrn"), "utf8");
expect(source).toContain("<slot></slot>");
expect(source.indexOf("<slot></slot>")).toBeLessThan(source.indexOf('data-error="_form"'));
});
test("packaged auth forms use built-in schemas instead of native browser validation", () => {
const files = readdirSync(directory).filter((file) => file.endsWith(".wrn"));
for (const file of files) {
const source = readFileSync(join(directory, file), "utf8");
if (!source.includes("<form")) continue;
expect(source).not.toContain(" required");
for (const form of source.matchAll(/<form[\s\S]*?>/g)) {
if (!form[0].includes("data-schema")) continue;
expect(form[0]).toContain("novalidate");
}
}
});
test("passwordless and passkey components preserve MFA continuation metadata", () => {
const otp = readFileSync(join(directory, "OtpSignIn.wrn"), "utf8");
const passkey = readFileSync(join(directory, "PasskeyButton.wrn"), "utf8");
const signIn = readFileSync(join(directory, "SignIn.wrn"), "utf8");
expect(otp).toContain("data-mfa-href");
expect(passkey).toContain("data-mfa-href");
expect(signIn).toContain("mfaHref='{mfaHref}'");
expect(signIn).toContain('name="deviceFingerprint"');
expect(signIn).toContain('name="deviceName"');
});
test("recovery forms expose a form slot for CAPTCHA and policy controls", () => {
const source = readFileSync(join(directory, "ForgotPassword.wrn"), "utf8");
const formStart = source.indexOf("<form");
const formEnd = source.indexOf("</form>");
const slot = source.indexOf("<slot></slot>");
expect(formStart).toBeGreaterThanOrEqual(0);
expect(slot).toBeGreaterThan(formStart);
expect(slot).toBeLessThan(formEnd);
});
test("account forms use the dedicated password components", () => {
const signIn = readFileSync(join(directory, "SignIn.wrn"), "utf8");
const signUp = readFileSync(join(directory, "SignUp.wrn"), "utf8");
expect(signIn).toContain("<TogglePassword");
expect(signIn).not.toContain('id="auth-sign-in-password"');
expect(signUp).toContain("<StrongPassword");
expect(signUp).not.toContain('id="auth-sign-up-password"');
});
test("authentication journeys use themed UI form controls", () => {
const expected = {
"SignIn.wrn": ["<Input", "<TogglePassword", "<Checkbox", "<Button"],
"SignUp.wrn": ["<Input", "<StrongPassword", "<Checkbox", "<Button"],
"ForgotPassword.wrn": ["<Input", "<Button"],
"ResetPassword.wrn": ["<StrongPassword", "<Button"],
"MagicLinkSignIn.wrn": ["<Input", "<Button"],
"InvitationAccept.wrn": ["<Input", "<StrongPassword", "<Button"],
"OtpSignIn.wrn": ["<Input", "<PinInput", "<Button"],
"TwoFactorChallenge.wrn": ["<Select", "<PinInput", "<Button"],
"AuthenticatorSetup.wrn": ["<Input", "<PinInput", "<Button"],
"VerifyEmail.wrn": ["<Input", "<Button"],
"VerifyPhone.wrn": ["<PinInput", "<Button"],
};
for (const [file, controls] of Object.entries(expected)) {
const source = readFileSync(join(directory, file), "utf8");
for (const control of controls) expect(source).toContain(control);
}
});
test("verification components can resend without application-owned schema files", () => {
const email = readFileSync(join(directory, "VerifyEmail.wrn"), "utf8");
const phone = readFileSync(join(directory, "VerifyPhone.wrn"), "utf8");
for (const source of [email, phone]) {
expect(source).toContain('name="identifier"');
expect(source).toContain("auth-verification-request");
expect(source).toContain("novalidate");
}
});
test("auth browser runtime refuses cross-origin navigation targets", () => {
const source = readFileSync(join(directory, "..", "assets", "client", "auth.js"), "utf8");
expect(source).toContain("if (url.origin !== location.origin) return false");
expect(source).toContain("!window.AbortController");
});