main
mjs 74 lines 4.09 KB
Raw
1 import assert from "node:assert/strict";
2 import { readFileSync } from "node:fs";
3 import test from "node:test";
4
5 const verifyPage = readFileSync(new URL("../app/verify-email/page.tsx", import.meta.url), "utf8");
6 const workspace = readFileSync(new URL("../app/components/investment-workspace.tsx", import.meta.url), "utf8");
7 const resetPage = readFileSync(new URL("../app/reset-password/page.tsx", import.meta.url), "utf8");
8
9 test("verification success is an exclusive public confirmation with a scheduled sign-in redirect", () => {
10 const success = verifyPage.match(/if \(state === "SUCCESS"\)[\s\S]*?\n }\n\n if \(state === "INVALID"\)/)?.[0] ?? "";
11 assert.match(success, /Email verified successfully\./);
12 assert.match(success, /Redirecting you to sign in\.\.\./);
13 assert.match(success, /Sign in now/);
14 assert.match(verifyPage, /window\.setTimeout\(\(\) => router\.push\("\/"\), 1500\)/);
15 assert.doesNotMatch(success, /Resend verification email|Check your email|Verify email/);
16 });
17
18 test("invalid verification links expose only recovery actions", () => {
19 const invalid = verifyPage.match(/if \(state === "INVALID"\)[\s\S]*?\n }\n\n return/ )?.[0] ?? "";
20 assert.match(invalid, /Verification link expired/);
21 assert.match(invalid, /This verification link is invalid or expired\./);
22 assert.match(invalid, /Resend verification email/);
23 assert.doesNotMatch(invalid, /Email verified successfully\./);
24 });
25
26 test("public verification route does not mount the authenticated workspace", () => {
27 assert.match(verifyPage, /authApi\.verifyEmail\(token\)/);
28 assert.doesNotMatch(verifyPage, /InvestmentWorkspace|portfolioApi|Your session expired/);
29 });
30
31 test("pending registration keeps resend available without normal-mode manual token entry", () => {
32 assert.match(workspace, /Check your email and open the verification link\./);
33 assert.match(workspace, /Resend verification email/);
34 assert.match(workspace, /frontendConfig\.authDevLoginEnabled \? <input name="token"/);
35 });
36
37 test("logout clears authenticated state and returns to the canonical login route", () => {
38 const logout = workspace.match(/function logout\(\) \{[\s\S]*?\n }\n\n if \(authLoading\)/)?.[0] ?? "";
39 assert.match(logout, /removeItem\("aip\.accessToken"\)/);
40 assert.match(logout, /removeItem\("aip\.user"\)/);
41 assert.match(logout, /window\.history\.replaceState\(\{\}, "", "\/"\)/);
42 assert.match(logout, /setError\(null\)/);
43 assert.match(logout, /setAccessToken\(null\)/);
44 assert.match(logout, /setAuthenticatedUser\(null\)/);
45 });
46
47 test("registration surfaces the safe active-account guidance and permits pending re-registration", () => {
48 assert.match(workspace, /submit\(form\)\.catch\(\(err\) => setMessage\(getApiFailure\(err\)\.message\)\)/);
49 assert.match(workspace, /We sent a verification link to your email address\./);
50 });
51
52 test("public sign-in exposes an enumeration-safe resend-verification recovery", () => {
53 assert.match(workspace, /setMode\("RESEND"\)/);
54 assert.match(workspace, /authApi\.resendVerification\(email\)/);
55 assert.match(workspace, /If this account is awaiting verification, a new verification email has been sent\./);
56 assert.doesNotMatch(workspace.match(/mode === "RESEND"[\s\S]*?return;/)?.[0] ?? "", /token/);
57 });
58
59 test("public password fields use inline accessible eye controls", () => {
60 assert.match(workspace, /className="password-input"/);
61 assert.match(workspace, /className="password-toggle"/);
62 assert.match(workspace, /aria-label=\{visible \? "Hide password" : "Show password"\}/);
63 assert.match(workspace, /name="confirmPassword"/);
64 assert.doesNotMatch(workspace, /Show or hide password/);
65 assert.match(resetPage, /className="password-toggle"/);
66 assert.match(resetPage, /new URLSearchParams\(window\.location\.search\)\.get\("token"\)/);
67 assert.doesNotMatch(resetPage, /token\}\s*<\//);
68 });
69
70 test("public auth cannot mount workspace requests with only a stale token", () => {
71 assert.match(workspace, /if \(accessToken && authenticatedUser\) \{\s*void loadPortfolios\(\)/);
72 assert.match(workspace, /if \(accessToken && authenticatedUser\) \{\s*void loadBrokers\(\)/);
73 assert.match(workspace, /setError\(null\)/);
74 });