fix(cv): expose editor errors and controls
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import '@testing-library/jest-dom';
|
||||
import { fireEvent, render, screen } from '@testing-library/react';
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
||||
import { createMemoryRouter, RouterProvider } from 'react-router-dom';
|
||||
|
||||
import CvBuilderEditor from './views/CvBuilderEditor';
|
||||
@@ -56,11 +56,11 @@ beforeEach(() => {
|
||||
mockedApi.post.mockResolvedValue({ data: { themeId: 'nordic', html: '<p>cv</p>', suggestedFileName: 'cv.pdf' } } as any);
|
||||
});
|
||||
|
||||
function routeGet(onVariant: () => Promise<any>) {
|
||||
function routeGet(onVariant: () => Promise<any>, outline: any = { sections: [] }) {
|
||||
mockedApi.get.mockImplementation((url: string) => {
|
||||
if (url === '/cv/variants/3') return onVariant();
|
||||
if (url === '/cv/themes') return Promise.resolve({ data: [] } as any);
|
||||
if (url === '/cv/outline') return Promise.resolve({ data: { sections: [] } } as any);
|
||||
if (url === '/cv/outline') return Promise.resolve({ data: outline } as any);
|
||||
return Promise.resolve({ data: [] } as any);
|
||||
});
|
||||
}
|
||||
@@ -173,3 +173,42 @@ test('custom entries can be added, edited, reordered and deleted with confirmati
|
||||
expect(screen.queryByLabelText('Custom section title')).not.toBeInTheDocument();
|
||||
confirm.mockRestore();
|
||||
});
|
||||
|
||||
test('profile-backed sections expand, reorder, hide and persist variant-only overrides', async () => {
|
||||
routeGet(() => Promise.resolve({ data: variant } as any), {
|
||||
sections: [{
|
||||
key: 'experience', title: 'Experience', kind: 'entries', bullets: [], tags: [], entries: [
|
||||
{ key: 'job-1', title: 'Engineer', subtitle: 'First Co', bullets: ['Built APIs'], tags: [] },
|
||||
{ key: 'job-2', title: 'Lead', subtitle: 'Second Co', bullets: ['Led teams'], tags: [] },
|
||||
],
|
||||
}],
|
||||
});
|
||||
mockedApi.put.mockResolvedValue({ data: variant } as any);
|
||||
renderAt(3);
|
||||
|
||||
fireEvent.click(await screen.findByRole('button', { name: 'Expand Experience entries' }));
|
||||
expect(screen.getByRole('button', { name: 'Collapse Experience entries' })).toHaveAttribute('aria-expanded', 'true');
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Move Engineer entry down' }));
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Hide Lead entry' }));
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Move Experience section down' }));
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Save now' }));
|
||||
|
||||
expect(await screen.findByText('Saved')).toBeInTheDocument();
|
||||
expect(mockedApi.put).toHaveBeenLastCalledWith('/cv/variants/3', expect.objectContaining({
|
||||
settings: expect.objectContaining({
|
||||
sections: expect.arrayContaining([expect.objectContaining({ key: 'experience', itemOrder: ['job-2', 'job-1'] })]),
|
||||
overrides: expect.objectContaining({ 'job-2': expect.objectContaining({ hidden: true }) }),
|
||||
}),
|
||||
}));
|
||||
});
|
||||
|
||||
test('preview failure is visible and retryable without leaving the editor', async () => {
|
||||
routeGet(() => Promise.resolve({ data: variant } as any));
|
||||
mockedApi.post.mockRejectedValueOnce(new Error('preview offline')).mockResolvedValueOnce({ data: { themeId: 'modern', html: '<p>retry</p>', suggestedFileName: 'cv.pdf' } } as any);
|
||||
renderAt(3);
|
||||
|
||||
expect(await screen.findByText('Preview unavailable')).toBeInTheDocument();
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Retry preview' }));
|
||||
await waitFor(() => expect(screen.getByTitle('CV preview')).toHaveAttribute('srcdoc', '<p>retry</p>'));
|
||||
await waitFor(() => expect(screen.queryByText('Preview unavailable')).not.toBeInTheDocument());
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user