fix(#411): QA-005 — production logging, error classification, session-expired state
logAuthError now always logs (not dev-only). Replaced isBackendError with parseAuthError-based classification. signOut uses proper error type. Session expiry sets explicit session_expired state. Login page logs in prod. Fixed pre-existing lint violations in auth package (campsite rule). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -34,6 +34,8 @@ describe("CallbackPage", (): void => {
|
||||
isLoading: false,
|
||||
isAuthenticated: false,
|
||||
authError: null,
|
||||
sessionExpiring: false,
|
||||
sessionMinutesRemaining: 0,
|
||||
signOut: vi.fn(),
|
||||
});
|
||||
});
|
||||
@@ -51,6 +53,8 @@ describe("CallbackPage", (): void => {
|
||||
isLoading: false,
|
||||
isAuthenticated: false,
|
||||
authError: null,
|
||||
sessionExpiring: false,
|
||||
sessionMinutesRemaining: 0,
|
||||
signOut: vi.fn(),
|
||||
});
|
||||
|
||||
@@ -141,6 +145,8 @@ describe("CallbackPage", (): void => {
|
||||
isLoading: false,
|
||||
isAuthenticated: false,
|
||||
authError: null,
|
||||
sessionExpiring: false,
|
||||
sessionMinutesRemaining: 0,
|
||||
signOut: vi.fn(),
|
||||
});
|
||||
|
||||
|
||||
@@ -45,9 +45,8 @@ vi.mock("@/lib/auth/fetch-with-retry", () => ({
|
||||
}));
|
||||
|
||||
// Mock parseAuthError to use the real implementation
|
||||
vi.mock("@/lib/auth/auth-errors", async () => {
|
||||
const actual = await vi.importActual<typeof import("@/lib/auth/auth-errors")>("@/lib/auth/auth-errors");
|
||||
return actual;
|
||||
vi.mock("@/lib/auth/auth-errors", async (importOriginal) => {
|
||||
return importOriginal();
|
||||
});
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
@@ -193,7 +192,9 @@ describe("LoginPage", (): void => {
|
||||
expect(screen.queryByRole("button", { name: /continue with/i })).not.toBeInTheDocument();
|
||||
|
||||
// Should show the unavailability banner (fix #5)
|
||||
expect(screen.getByText("Some sign-in options may be temporarily unavailable.")).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText("Some sign-in options may be temporarily unavailable.")
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("falls back to email-only on non-ok response", async (): Promise<void> => {
|
||||
|
||||
@@ -58,9 +58,7 @@ export default function LoginPage(): ReactElement {
|
||||
}
|
||||
} catch (err: unknown) {
|
||||
if (!cancelled) {
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
console.error("[Auth] Failed to load auth config:", err);
|
||||
}
|
||||
console.error("[Auth] Failed to load auth config:", err);
|
||||
setConfig(EMAIL_ONLY_CONFIG);
|
||||
setUrlError("Some sign-in options may be temporarily unavailable.");
|
||||
}
|
||||
@@ -91,9 +89,7 @@ export default function LoginPage(): ReactElement {
|
||||
setError(null);
|
||||
signIn.oauth2({ providerId, callbackURL: "/" }).catch((err: unknown) => {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
console.error(`[Auth] OAuth sign-in initiation failed for ${providerId}:`, message);
|
||||
}
|
||||
console.error(`[Auth] OAuth sign-in initiation failed for ${providerId}:`, message);
|
||||
setError("Unable to connect to the sign-in provider. Please try again in a moment.");
|
||||
setOauthLoading(null);
|
||||
});
|
||||
@@ -118,9 +114,7 @@ export default function LoginPage(): ReactElement {
|
||||
}
|
||||
} catch (err: unknown) {
|
||||
const parsed = parseAuthError(err);
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
console.error("[Auth] Credentials sign-in failed:", err);
|
||||
}
|
||||
console.error("[Auth] Credentials sign-in failed:", err);
|
||||
setError(parsed.message);
|
||||
} finally {
|
||||
setCredentialsLoading(false);
|
||||
|
||||
Reference in New Issue
Block a user