import { createJob } from "@shared/testing/factories.js";
import { act, fireEvent, render, screen } from "@testing-library/react";
import type React from "react";
import { MemoryRouter } from "react-router-dom";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { useSettings } from "../hooks/useSettings";
import { JobHeader } from "./JobHeader";
// Mock useSettings
vi.mock("../hooks/useSettings", () => ({
useSettings: vi.fn(),
}));
// Mock api
vi.mock("../api", () => ({
checkSponsor: vi.fn(),
}));
// Mock Tooltip components to simplify testing
vi.mock("@/components/ui/tooltip", () => ({
TooltipProvider: ({ children }: { children: React.ReactNode }) => (
<>{children}>
),
Tooltip: ({ children }: { children: React.ReactNode }) => <>{children}>,
TooltipTrigger: ({ children }: { children: React.ReactNode }) => (
<>{children}>
),
TooltipContent: ({ children }: { children: React.ReactNode }) => (
{children}
),
}));
const mockJob = createJob({
id: "job-1",
title: "Software Engineer",
employer: "Tech Corp",
location: "London",
salary: "£60,000",
deadline: "2025-12-31",
status: "discovered",
source: "linkedin",
suitabilityScore: 85,
suitabilityReason: "Strong match",
});
describe("JobHeader", () => {
const renderWithRouter = (ui: React.ReactElement) =>
render({ui});
beforeEach(() => {
vi.clearAllMocks();
(useSettings as any).mockReturnValue({
showSponsorInfo: true,
});
});
it("renders basic job information", () => {
renderWithRouter();
expect(screen.getByText("Software Engineer")).toBeInTheDocument();
expect(screen.getByText("Tech Corp")).toBeInTheDocument();
expect(screen.getByText("London")).toBeInTheDocument();
expect(screen.getByText("£60,000")).toBeInTheDocument();
});
it("links the title and view button to the job page", () => {
renderWithRouter();
expect(
screen.getByRole("link", { name: "Software Engineer" }),
).toHaveAttribute("href", "/job/job-1");
expect(screen.getByRole("link", { name: /view/i })).toHaveAttribute(
"href",
"/job/job-1",
);
});
it("shows 'Check Sponsorship Status' button when sponsorMatchScore is null", async () => {
const onCheckSponsor = vi.fn().mockResolvedValue(undefined);
renderWithRouter(
,
);
const button = screen.getByText("Check Sponsorship Status");
expect(button).toBeInTheDocument();
await act(async () => {
fireEvent.click(button);
});
expect(onCheckSponsor).toHaveBeenCalled();
});
it("shows 'Confirmed Sponsor' when score >= 95", () => {
const jobWithSponsor = {
...mockJob,
sponsorMatchScore: 98,
sponsorMatchNames: '["Tech Corp Ltd"]',
};
renderWithRouter();
expect(screen.getByText("Confirmed Sponsor")).toBeInTheDocument();
});
it("shows 'Potential Sponsor' when score is between 80 and 94", () => {
const jobWithPotential = {
...mockJob,
sponsorMatchScore: 85,
sponsorMatchNames: '["Techy Corp"]',
};
renderWithRouter();
expect(screen.getByText("Potential Sponsor")).toBeInTheDocument();
});
it("shows 'Sponsor Not Found' when score < 80", () => {
const jobNoSponsor = {
...mockJob,
sponsorMatchScore: 40,
sponsorMatchNames: '["Other Corp"]',
};
renderWithRouter();
expect(screen.getByText("Sponsor Not Found")).toBeInTheDocument();
});
it("hides sponsor info when showSponsorInfo is false", () => {
(useSettings as any).mockReturnValue({
showSponsorInfo: false,
});
const jobWithSponsor = { ...mockJob, sponsorMatchScore: 98 };
renderWithRouter();
expect(screen.queryByText("Confirmed Sponsor")).not.toBeInTheDocument();
expect(
screen.queryByText("Check Sponsorship Status"),
).not.toBeInTheDocument();
});
it("hides the view button when already on a job page", () => {
render(
,
);
expect(
screen.queryByRole("link", { name: /view/i }),
).not.toBeInTheDocument();
});
});