Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions src/components/navbar.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { screen } from "@testing-library/react"
import { http, HttpResponse } from "msw"
import { describe, expect, it } from "vitest"
import { renderWithFileRoutes } from "@/test/renderers"
import { server } from "@/test/setup"

// Regression guard for issue #23 (recurring): the navbar must render the
// human-readable display_name returned by /auth/me, never the raw user id
// (which for Steam OAuth is the SteamID64). The actual root cause of the
// linked bug lives in the auth API — but this test pins the *frontend*
// contract so a rename like `display_name` → `displayName`, a dropped
// setDisplayName call, or a navbar swap to userId/email can't silently
// reintroduce the same visible regression here.

const STEAM_ID = "76561198000000000"

function authMeHandler(body: {
id: string
email: string
display_name: string | null
avatar_url: string | null
}) {
return http.get("*/auth/me", () => HttpResponse.json(body))
}

// The consent fetch fires right after /auth/me succeeds. Stub it so the
// AuthProvider's catch-all doesn't surface as an unhandled-request warning.
const consentsHandler = http.get("*/user/consents", () =>
HttpResponse.json({ current_policy_version: "test", consents: {} })
)

describe("Navbar", () => {
it("renders the Steam display_name, not the SteamID64", async () => {
server.use(
authMeHandler({
id: STEAM_ID,
email: "player@example.com",
display_name: "ZeroEmpires",
avatar_url: null,
}),
consentsHandler
)

await renderWithFileRoutes(<></>)

expect(await screen.findByText("ZeroEmpires")).toBeInTheDocument()
expect(screen.queryByText(STEAM_ID)).not.toBeInTheDocument()
expect(screen.queryByText("player@example.com")).not.toBeInTheDocument()
})

it("falls back to email when display_name is null", async () => {
server.use(
authMeHandler({
id: STEAM_ID,
email: "player@example.com",
display_name: null,
avatar_url: null,
}),
consentsHandler
)

await renderWithFileRoutes(<></>)

expect(await screen.findByText("player@example.com")).toBeInTheDocument()
expect(screen.queryByText(STEAM_ID)).not.toBeInTheDocument()
})
})
2 changes: 1 addition & 1 deletion src/test/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { cleanup } from "@testing-library/react"
import { setupServer } from "msw/node"
import { afterAll, afterEach, beforeAll, vi } from "vitest"

const server = setupServer(...handlers)
export const server = setupServer(...handlers)

beforeAll(() => server.listen())
afterAll(() => server.close())
Expand Down
2 changes: 2 additions & 0 deletions vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export default defineConfig({
environment: "jsdom",
env: {
VITE_LOG_LEVEL: "warn",
// Absolute URL so ky/MSW can parse it; the host is fake — MSW intercepts.
VITE_API_URL: "http://localhost/api",
},
setupFiles: ["./src/test/setup.ts"],
include: ["src/**/*.{test,spec}.{ts,tsx}"],
Expand Down
Loading