Jobber/orchestrator/src/client/components/JobHeader.test.tsx
Shaheer Sarfaraz fe0aebe01a
Small bits and bobs, codebase quality (#129)
* initial change

* nav highlighting

* icon change

* deeeedoooop

* text

* show version number on all pages

* icon

* remove unused code

* add knip

* formatting

* remove unused code

* types fix

* remove notion completely from the codebase.

* update test for new url structure

* clean up the fucking shop boys

* make a "create job" factory and use that

* moar factories

* formatting
2026-02-10 20:01:58 +00:00

152 lines
4.4 KiB
TypeScript

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 }) => (
<div data-testid="tooltip-content">{children}</div>
),
}));
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(<MemoryRouter>{ui}</MemoryRouter>);
beforeEach(() => {
vi.clearAllMocks();
(useSettings as any).mockReturnValue({
showSponsorInfo: true,
});
});
it("renders basic job information", () => {
renderWithRouter(<JobHeader job={mockJob} />);
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(<JobHeader job={mockJob} />);
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(
<JobHeader job={mockJob} onCheckSponsor={onCheckSponsor} />,
);
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(<JobHeader job={jobWithSponsor} />);
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(<JobHeader job={jobWithPotential} />);
expect(screen.getByText("Potential Sponsor")).toBeInTheDocument();
});
it("shows 'Sponsor Not Found' when score < 80", () => {
const jobNoSponsor = {
...mockJob,
sponsorMatchScore: 40,
sponsorMatchNames: '["Other Corp"]',
};
renderWithRouter(<JobHeader job={jobNoSponsor} />);
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(<JobHeader job={jobWithSponsor} />);
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(
<MemoryRouter initialEntries={["/job/job-1"]}>
<JobHeader job={mockJob} />
</MemoryRouter>,
);
expect(
screen.queryByRole("link", { name: /view/i }),
).not.toBeInTheDocument();
});
});