feat(ui): redesign job workspace sections
This commit is contained in:
@@ -3,7 +3,7 @@ import "@testing-library/jest-dom";
|
||||
import { fireEvent, render as rtlRender, screen, waitFor } from "@testing-library/react";
|
||||
|
||||
import {
|
||||
ApplicationCoverLetterSection, ApplicationCvSection, ApplicationPackageDraftsSection,
|
||||
ApplicationCoverLetterSection, ApplicationCvSection, ApplicationPackageDraftsSection, SubmittedPackagesSection,
|
||||
} from "./components/ApplicationAssets";
|
||||
import { api } from "./api";
|
||||
import { I18nProvider } from "./i18n/I18nProvider";
|
||||
@@ -74,6 +74,22 @@ beforeEach(() => {
|
||||
|
||||
afterEach(() => window.localStorage.removeItem("uiLanguage"));
|
||||
|
||||
test("document package history is read-only and separates captured notes from answers", async () => {
|
||||
const summary = { id: 91, version: 1, cvVariantId: 3, cvVariantName: "Original CV", cvVariantVersion: 2, cvThemeId: "nordic", hasCv: false, hasCoverLetter: true, createdAtUtc: "2026-07-19T10:00:00Z", attachments: [] };
|
||||
mockedApi.get.mockImplementation((url: string) => Promise.resolve({ data: url.endsWith('/91') ? {
|
||||
summary, renderedCvHtml: null, coverLetterText: "Frozen letter", applicationMaterialJson: JSON.stringify({ Notes: "Human notes\n\n<<<APPLICATION_ANSWER_DRAFT>>>\nFrozen answer\n<<<END_APPLICATION_ANSWER_DRAFT>>>" }),
|
||||
} : [summary] } as any));
|
||||
render(<SubmittedPackagesSection jobId={7} allowCapture={false} />);
|
||||
fireEvent.click(await screen.findByRole("button", { name: "View preserved package" }));
|
||||
expect(await screen.findByRole("dialog")).toHaveTextContent("immutable submission snapshot");
|
||||
expect(screen.getByText("Human notes", { exact: true })).toBeInTheDocument();
|
||||
expect(screen.getByText("Frozen answer", { exact: true })).toBeInTheDocument();
|
||||
expect(screen.queryByText(/<<<APPLICATION/)).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: "Freeze current package" })).not.toBeInTheDocument();
|
||||
expect(mockedApi.post).not.toHaveBeenCalled();
|
||||
expect(mockedApi.put).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
// ---------- CV ----------
|
||||
|
||||
test("cv section shows the attached variant and the ones available to attach", async () => {
|
||||
@@ -161,7 +177,7 @@ test("editing marks the draft dirty and saving sends the new text", async () =>
|
||||
const onDirtyChange = jest.fn();
|
||||
|
||||
render(<ApplicationCoverLetterSection jobId={7} onDirtyChange={onDirtyChange} />);
|
||||
fireEvent.change(await screen.findByLabelText("Cover letter"), { target: { value: "Dear hiring team" } });
|
||||
fireEvent.change(await screen.findByRole("textbox", { name: "Cover letter" }), { target: { value: "Dear hiring team" } });
|
||||
|
||||
expect(screen.getByText("Unsaved changes")).toBeInTheDocument();
|
||||
expect(onDirtyChange).toHaveBeenLastCalledWith(true);
|
||||
@@ -177,7 +193,7 @@ test("discarding returns to the saved text", async () => {
|
||||
routeGet();
|
||||
|
||||
render(<ApplicationCoverLetterSection jobId={7} />);
|
||||
fireEvent.change(await screen.findByLabelText("Cover letter"), { target: { value: "scratch" } });
|
||||
fireEvent.change(await screen.findByRole("textbox", { name: "Cover letter" }), { target: { value: "scratch" } });
|
||||
fireEvent.click(screen.getByRole("button", { name: /Discard changes/i }));
|
||||
|
||||
expect(await screen.findByDisplayValue("Dear team")).toBeInTheDocument();
|
||||
@@ -202,7 +218,7 @@ test("an empty cover letter offers the template and an empty history", async ()
|
||||
|
||||
expect(await screen.findByText(/No versions yet/i)).toBeInTheDocument();
|
||||
fireEvent.click(screen.getByRole("button", { name: /Start from template/i }));
|
||||
expect((screen.getByLabelText("Cover letter") as HTMLTextAreaElement).value)
|
||||
expect((screen.getByRole("textbox", { name: "Cover letter" }) as HTMLTextAreaElement).value)
|
||||
.toContain("Dear Hiring Manager");
|
||||
});
|
||||
|
||||
@@ -213,7 +229,7 @@ test("the empty cover-letter template and rich-text controls follow Bokmål UI l
|
||||
render(<ApplicationCoverLetterSection jobId={7} />);
|
||||
|
||||
fireEvent.click(await screen.findByRole("button", { name: /start fra mal/i }));
|
||||
expect((screen.getByLabelText("Søknadsbrev") as HTMLTextAreaElement).value)
|
||||
expect((screen.getByRole("textbox", { name: "Søknadsbrev" }) as HTMLTextAreaElement).value)
|
||||
.toContain("Kjære rekrutteringsansvarlig");
|
||||
expect(screen.getByRole("button", { name: "Fet" })).toBeInTheDocument();
|
||||
expect(screen.getByRole("button", { name: "Lenke" })).toBeInTheDocument();
|
||||
@@ -250,9 +266,9 @@ test("AI cover letter suggestions use the linked CV and require explicit apply",
|
||||
action: "generate",
|
||||
}),
|
||||
));
|
||||
expect(screen.getByLabelText("Cover letter")).toHaveValue("Dear team");
|
||||
expect(screen.getByRole("textbox", { name: "Cover letter" })).toHaveValue("Dear team");
|
||||
fireEvent.click(await screen.findByRole("button", { name: /Apply to editor/i }));
|
||||
expect(screen.getByLabelText("Cover letter")).toHaveValue("A tailored, truthful suggestion.");
|
||||
expect(screen.getByRole("textbox", { name: "Cover letter" })).toHaveValue("A tailored, truthful suggestion.");
|
||||
|
||||
mockedApi.put.mockResolvedValue({ data: { ...coverLetter, text: "A tailored, truthful suggestion." } } as any);
|
||||
fireEvent.click(screen.getByRole("button", { name: "Save" }));
|
||||
@@ -272,10 +288,10 @@ test("[PRES-W06] rejecting an AI cover letter preserves the saved draft without
|
||||
expect(screen.queryByText(/\{name\}/)).not.toBeInTheDocument();
|
||||
fireEvent.click(screen.getByRole("button", { name: "Generate" }));
|
||||
await screen.findByText("Unaccepted letter");
|
||||
expect(screen.getByLabelText("Cover letter")).toHaveValue("Dear team");
|
||||
expect(screen.getByRole("textbox", { name: "Cover letter" })).toHaveValue("Dear team");
|
||||
fireEvent.click(screen.getByRole("button", { name: "Reject" }));
|
||||
expect(screen.queryByText("Unaccepted letter")).not.toBeInTheDocument();
|
||||
expect(screen.getByLabelText("Cover letter")).toHaveValue("Dear team");
|
||||
expect(screen.getByRole("textbox", { name: "Cover letter" })).toHaveValue("Dear team");
|
||||
expect(screen.getByRole("button", { name: "Save" })).toBeDisabled();
|
||||
expect(onDirtyChange).not.toHaveBeenCalledWith(true);
|
||||
expect(mockedApi.put).not.toHaveBeenCalled();
|
||||
|
||||
Reference in New Issue
Block a user