* initial implementation * onboarding doesn't pop until invalid values are present * link to job page * proactive inputs working slightly * onboarding gate reinstated * better proactive buttons * fully manual tracking for now. * edit and delete timeline events * status showing correctly * tests update * tests * Update orchestrator/src/server/services/applicationTracking.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update orchestrator/src/server/services/applicationTracking.test.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update orchestrator/src/server/services/applicationTracking.test.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update orchestrator/src/client/pages/job/Timeline.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update orchestrator/src/client/pages/JobPage.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * add tests for application tracking routes and remove unused actionId from client API * remove unnecessary await from synchronous transitionStage calls and improve test isolation * relax externalUrl validation to allow non-URL metadata * add toast notifications for data loading and event logging in JobPage * comments * fix: resolve type error in sponsor-matching.test.ts * fix ci * tests fix for github * lint * github comments * build fix * dedupe * format * types fix * Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * formatting * title and group id are discrete fields * backfill * hide view button on page * show relevant dropdown options * confetti! * remove redundant * confirm delete is a custom element now * formatting * fix styling --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
114 lines
3.1 KiB
TypeScript
114 lines
3.1 KiB
TypeScript
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
|
|
import type React from "react";
|
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
import { LogEventModal } from "./LogEventModal";
|
|
|
|
vi.mock("@/components/ui/alert-dialog", () => ({
|
|
AlertDialog: ({ children }: { children: React.ReactNode }) => (
|
|
<div>{children}</div>
|
|
),
|
|
AlertDialogContent: ({ children }: { children: React.ReactNode }) => (
|
|
<div>{children}</div>
|
|
),
|
|
AlertDialogDescription: ({ children }: { children: React.ReactNode }) => (
|
|
<div>{children}</div>
|
|
),
|
|
AlertDialogFooter: ({ children }: { children: React.ReactNode }) => (
|
|
<div>{children}</div>
|
|
),
|
|
AlertDialogHeader: ({ children }: { children: React.ReactNode }) => (
|
|
<div>{children}</div>
|
|
),
|
|
AlertDialogTitle: ({ children }: { children: React.ReactNode }) => (
|
|
<div>{children}</div>
|
|
),
|
|
AlertDialogCancel: ({
|
|
children,
|
|
...props
|
|
}: {
|
|
children: React.ReactNode;
|
|
}) => (
|
|
<button type="button" {...props}>
|
|
{children}
|
|
</button>
|
|
),
|
|
}));
|
|
|
|
vi.mock("@/components/ui/select", () => ({
|
|
Select: ({
|
|
children,
|
|
value,
|
|
onValueChange,
|
|
}: {
|
|
children: React.ReactNode;
|
|
value?: string;
|
|
onValueChange?: (value: string) => void;
|
|
}) => (
|
|
<select
|
|
data-testid="select"
|
|
value={value}
|
|
onChange={(event) => onValueChange?.(event.target.value)}
|
|
>
|
|
{children}
|
|
</select>
|
|
),
|
|
SelectContent: ({ children }: { children: React.ReactNode }) => (
|
|
<>{children}</>
|
|
),
|
|
SelectItem: ({
|
|
children,
|
|
value,
|
|
}: {
|
|
children: React.ReactNode;
|
|
value: string;
|
|
}) => <option value={value}>{children}</option>,
|
|
SelectTrigger: () => null,
|
|
SelectValue: () => null,
|
|
}));
|
|
|
|
describe("LogEventModal", () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
it("shows the rejection reason selector and submits the form", async () => {
|
|
const onLog = vi.fn().mockResolvedValue(undefined);
|
|
const onClose = vi.fn();
|
|
|
|
render(<LogEventModal isOpen onClose={onClose} onLog={onLog} />);
|
|
|
|
const stageSelect = screen.getAllByTestId("select")[0];
|
|
fireEvent.change(stageSelect, { target: { value: "rejected" } });
|
|
|
|
expect(screen.getByText("Reason")).toBeInTheDocument();
|
|
|
|
const reasonSelect = screen.getAllByTestId("select")[1];
|
|
fireEvent.change(reasonSelect, { target: { value: "Visa" } });
|
|
|
|
fireEvent.click(screen.getByRole("button", { name: /log event/i }));
|
|
|
|
await waitFor(() =>
|
|
expect(onLog).toHaveBeenCalledWith(
|
|
expect.objectContaining({ stage: "rejected", reasonCode: "Visa" }),
|
|
undefined,
|
|
),
|
|
);
|
|
});
|
|
|
|
it("blocks submit when the title is cleared", async () => {
|
|
const onLog = vi.fn().mockResolvedValue(undefined);
|
|
const onClose = vi.fn();
|
|
|
|
render(<LogEventModal isOpen onClose={onClose} onLog={onLog} />);
|
|
|
|
const titleInput = screen.getByPlaceholderText("e.g. Recruiter Screen");
|
|
fireEvent.change(titleInput, { target: { value: "" } });
|
|
|
|
fireEvent.click(screen.getByRole("button", { name: /log event/i }));
|
|
|
|
expect(await screen.findByText("Title is required")).toBeInTheDocument();
|
|
expect(onLog).not.toHaveBeenCalled();
|
|
});
|
|
});
|