/**
* Auth Context Tests
* Tests for the authentication context and has_voted state fix
*/
import React from "react"
import { render, screen, waitFor } from "@testing-library/react"
import { AuthProvider, useAuth } from "@/lib/auth-context"
import * as api from "@/lib/api"
// Mock the API module
jest.mock("@/lib/api", () => ({
authApi: {
login: jest.fn(),
register: jest.fn(),
getProfile: jest.fn(),
logout: jest.fn(),
},
getAuthToken: jest.fn(),
setAuthToken: jest.fn(),
clearAuthToken: jest.fn(),
}))
// Mock window.localStorage
const localStorageMock = {
getItem: jest.fn(),
setItem: jest.fn(),
removeItem: jest.fn(),
clear: jest.fn(),
}
global.localStorage = localStorageMock as any
describe("Auth Context - Bug #2: has_voted State Fix", () => {
beforeEach(() => {
jest.clearAllMocks()
localStorageMock.getItem.mockReturnValue(null)
})
test("login response includes has_voted field", async () => {
const mockLoginResponse = {
data: {
access_token: "test-token",
id: 1,
email: "test@example.com",
first_name: "Test",
last_name: "User",
has_voted: false,
expires_in: 1800,
},
status: 200,
}
;(api.authApi.login as jest.Mock).mockResolvedValue(mockLoginResponse)
;(api.setAuthToken as jest.Mock).mockImplementation(() => {})
let authContextValue: any
const TestComponent = () => {
authContextValue = useAuth()
return
{authContextValue.isLoading ? "Loading..." : "Ready"}
}
const { rerender } = render(
)
// Simulate login
await waitFor(async () => {
await authContextValue.login("test@example.com", "password123")
})
expect(authContextValue.user).toBeDefined()
expect(authContextValue.user?.has_voted).toBeDefined()
expect(typeof authContextValue.user?.has_voted).toBe("boolean")
})
test("register response includes has_voted field", async () => {
const mockRegisterResponse = {
data: {
access_token: "test-token",
id: 2,
email: "newuser@example.com",
first_name: "New",
last_name: "User",
has_voted: false,
expires_in: 1800,
},
status: 200,
}
;(api.authApi.register as jest.Mock).mockResolvedValue(mockRegisterResponse)
;(api.setAuthToken as jest.Mock).mockImplementation(() => {})
let authContextValue: any
const TestComponent = () => {
authContextValue = useAuth()
return {authContextValue.isLoading ? "Loading..." : "Ready"}
}
render(
)
// Simulate registration
await waitFor(async () => {
await authContextValue.register(
"newuser@example.com",
"password123",
"New",
"User",
"ID123456"
)
})
expect(authContextValue.user?.has_voted).toBe(false)
})
test("has_voted is correctly set from server response, not hardcoded", async () => {
const mockLoginResponseVoted = {
data: {
access_token: "test-token",
id: 3,
email: "voted@example.com",
first_name: "Voted",
last_name: "User",
has_voted: true, // User has already voted
expires_in: 1800,
},
status: 200,
}
;(api.authApi.login as jest.Mock).mockResolvedValue(mockLoginResponseVoted)
;(api.setAuthToken as jest.Mock).mockImplementation(() => {})
let authContextValue: any
const TestComponent = () => {
authContextValue = useAuth()
return {authContextValue.isLoading ? "Loading..." : "Ready"}
}
render(
)
// Simulate login with user who has voted
await waitFor(async () => {
await authContextValue.login("voted@example.com", "password123")
})
// Verify has_voted is true (from server) not false (hardcoded)
expect(authContextValue.user?.has_voted).toBe(true)
})
test("has_voted defaults to false if not in response", async () => {
const mockLoginResponseNoField = {
data: {
access_token: "test-token",
id: 4,
email: "nofield@example.com",
first_name: "No",
last_name: "Field",
// has_voted missing from response
expires_in: 1800,
},
status: 200,
}
;(api.authApi.login as jest.Mock).mockResolvedValue(mockLoginResponseNoField)
;(api.setAuthToken as jest.Mock).mockImplementation(() => {})
let authContextValue: any
const TestComponent = () => {
authContextValue = useAuth()
return {authContextValue.isLoading ? "Loading..." : "Ready"}
}
render(
)
await waitFor(async () => {
await authContextValue.login("nofield@example.com", "password123")
})
// Should default to false if not present
expect(authContextValue.user?.has_voted).toBe(false)
})
test("profile refresh updates has_voted state", async () => {
const mockProfileResponse = {
data: {
id: 5,
email: "profile@example.com",
first_name: "Profile",
last_name: "User",
has_voted: true,
created_at: new Date().toISOString(),
},
status: 200,
}
;(api.authApi.getProfile as jest.Mock).mockResolvedValue(mockProfileResponse)
;(api.getAuthToken as jest.Mock).mockReturnValue("test-token")
let authContextValue: any
const TestComponent = () => {
authContextValue = useAuth()
return (
{authContextValue.user?.has_voted !== undefined
? `has_voted: ${authContextValue.user.has_voted}`
: "no user"}
)
}
render(
)
// Simulate profile refresh
await waitFor(async () => {
await authContextValue.refreshProfile()
})
expect(authContextValue.user?.has_voted).toBe(true)
})
})
describe("Auth Context - API Token Type Fix", () => {
test("AuthToken interface includes has_voted field", () => {
// This test ensures the TypeScript interface is correct
const token: api.AuthToken = {
access_token: "token",
expires_in: 1800,
id: 1,
email: "test@example.com",
first_name: "Test",
last_name: "User",
has_voted: false,
}
expect(token.has_voted).toBeDefined()
expect(typeof token.has_voted).toBe("boolean")
})
})