feat(cv): redesign document editing with revision-safe letters and writing tools

This commit is contained in:
cesnimda
2026-10-25 22:44:14 +01:00
parent 01e10996c5
commit 2bfaf6c14b
57 changed files with 2859 additions and 118 deletions
@@ -2,7 +2,7 @@ import React, { useState } from "react";
import "@testing-library/jest-dom";
import { fireEvent, render, screen, waitFor, within } from "@testing-library/react";
import CvCustomizeTab from "./components/cv/CvCustomizeTab";
import { applyCvTheme, CvTheme, CvVariantSettings, emptyCvVariantSettings } from "./cvBuilder";
import { applyCvTheme, cvBuilderApi, CvTheme, CvVariantSettings, emptyCvVariantSettings } from "./cvBuilder";
import { ConfirmProvider } from "./confirm";
import { I18nProvider } from "./i18n/I18nProvider";
@@ -12,7 +12,19 @@ const themes: CvTheme[] = [
{ id: "technical", name: "Technical", category: "Technical", description: "Sidebar", layout: "sidebar-left", accent: "#0f766e", photoShape: "circle", supportsIcons: true, atsFriendly: true, requiresPro: true, available: false, swatches: [] },
];
beforeEach(() => localStorage.clear());
beforeEach(() => {
localStorage.clear();
global.ResizeObserver = class { observe() {} unobserve() {} disconnect() {} };
jest.spyOn(cvBuilderApi, "themePreview").mockImplementation(async themeId => ({ themeId, html: "<html><body>Sample</body></html>", suggestedFileName: "sample.pdf" }));
});
afterEach(() => jest.restoreAllMocks());
async function applyCandidate() {
const candidate = await screen.findByRole("dialog", { name: /Preview design/ });
const apply = within(candidate).getByRole("button", { name: "Apply template" });
await waitFor(() => expect(apply).toBeEnabled());
fireEvent.click(apply);
}
function mount(initial = emptyCvVariantSettings(), mode: "customize" | "template" = "customize", availableThemes = themes) {
const update = jest.fn();
@@ -101,15 +113,19 @@ test("[PRES-C08 C10 E09] locks prevent selection and confirmed template resets p
fireEvent.keyDown(locked, { key: "Enter" });
expect(update).not.toHaveBeenCalled();
fireEvent.keyDown(screen.getByRole("button", { name: "Modern" }), { key: " " });
expect(update).not.toHaveBeenCalled();
await applyCandidate();
fireEvent.click(within(await screen.findByRole("dialog", { name: "Apply template defaults?" })).getByRole("button", { name: "Cancel" }));
await waitFor(() => expect(screen.queryByRole("dialog")).not.toBeInTheDocument());
expect(update).not.toHaveBeenCalled();
fireEvent.keyDown(screen.getByRole("button", { name: "Code" }), { key: "Enter" });
await applyCandidate();
const dialog = await screen.findByRole("dialog", { name: "Apply template defaults?" });
fireEvent.click(within(dialog).getByRole("button", { name: "Cancel" }));
await waitFor(() => expect(screen.queryByRole("dialog")).not.toBeInTheDocument());
expect(update).not.toHaveBeenCalled();
fireEvent.click(screen.getByRole("button", { name: "Code" }));
await applyCandidate();
fireEvent.click(within(await screen.findByRole("dialog", { name: "Apply template defaults?" })).getByRole("button", { name: "Apply template" }));
await waitFor(() => expect(update).toHaveBeenLastCalledWith(applyCvTheme(initial, "code")));
expect(settings().overrides).toEqual(initial.overrides);