import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { fireEvent, render } from "@testing-library/react"; import { getArticle } from "../../lib/api"; import { Language } from "../../lib/types"; import useNavState from "../../store/navStore"; import useUIStore from "../../store/uiStore"; import Panel from "./Panel"; jest.mock("../../store/uiStore"); jest.mock("../../store/navStore"); jest.mock("../../lib/api"); jest.mock("../../constants", () => Promise.resolve({ API_URL: "http://localhost:8000/api", // Mock the API_URL to a local server for testing }) ); const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false, }, }, }); const renderWithClient = (ui: React.ReactElement) => { const { rerender, ...result } = render( {ui} ); return { ...result, rerender: (rerenderUi: React.ReactElement) => rerender( {rerenderUi} ), }; }; const wrapper = ({ children }) => ( {children} ); describe("Panel Component", () => { const mockSetSelectedParagraphId = jest.fn(); const mockUseUIStore = { selectedParagraphId: null, setSelectedParagraphId: mockSetSelectedParagraphId, }; const mockNavState = { celexId: "123", articleId: 1, }; beforeEach(() => { jest.mocked(useNavState).mockReturnValue(mockNavState); jest.mocked(useUIStore).mockReturnValue(mockUseUIStore); }); afterEach(() => { jest.clearAllMocks(); queryClient.clear(); }); test("renders loading state", () => { (getArticle as jest.Mock).mockReturnValue(new Promise(() => {})); const { getByText } = render(, { wrapper }); expect(getByText("Loading...")).toBeInTheDocument(); }); test("renders error state", async () => { (getArticle as jest.Mock).mockRejectedValue(new Error("Failed to fetch")); const { findByText } = renderWithClient(); expect( await findByText("An error has occurred: Failed to fetch") ).toBeInTheDocument(); }); test("renders article content", async () => { const mockData = `
Test Content
`; jest.mocked(getArticle).mockResolvedValue(mockData); const result = renderWithClient(); expect(await result.findByText("Test Content")).toBeInTheDocument(); }); test("highlights a paragraph on click", async () => { const mockData = `
Paragraph 1
Paragraph 2
`; (getArticle as jest.Mock).mockResolvedValue(mockData); const result = renderWithClient(); const paragraph1 = await result.findByText("Paragraph 1"); const paragraph2 = await result.findByText("Paragraph 2"); fireEvent.click(paragraph1); expect(paragraph1.classList.contains("highlight")).toBe(true); expect(paragraph2.classList.contains("highlight")).toBe(false); expect(mockSetSelectedParagraphId).toHaveBeenCalledWith("1"); fireEvent.click(paragraph2); expect(paragraph1.classList.contains("highlight")).toBe(false); expect(paragraph2.classList.contains("highlight")).toBe(true); expect(mockSetSelectedParagraphId).toHaveBeenCalledWith("2"); }); test("renders LanguageSwitcher and updates language", async () => { jest .mocked(getArticle) .mockResolvedValue( "
Test Content
" ); const result = renderWithClient(); const languageSwitcher = await result.findByRole("combobox"); expect(languageSwitcher).toBeInTheDocument(); fireEvent.change(languageSwitcher, { target: { value: Language.ENG } }); expect(jest.mocked(getArticle)).toHaveBeenCalledWith( "123", 1, Language.ENG ); }); });