feat(frontend): i18n template pages (list, form, picker modal)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -92,22 +92,20 @@ describe('TemplateFormPage — new mode', () => {
|
||||
|
||||
it('renders the form with name field in empty state', () => {
|
||||
renderNew();
|
||||
expect(screen.getByLabelText(/Name/i)).toBeInTheDocument();
|
||||
expect(screen.getByLabelText(/Description/i)).toBeInTheDocument();
|
||||
expect(screen.getByLabelText(/Commands/i)).toBeInTheDocument();
|
||||
expect(screen.getByLabelText(/Prerequisites/i)).toBeInTheDocument();
|
||||
// All inputs should be empty
|
||||
expect(screen.getByLabelText(/Name/i)).toHaveValue('');
|
||||
expect(screen.getByLabelText(/^Nom/i)).toBeInTheDocument();
|
||||
expect(screen.getByLabelText(/^Description/i)).toBeInTheDocument();
|
||||
expect(screen.getByLabelText(/^Commandes/i)).toBeInTheDocument();
|
||||
expect(screen.getByLabelText(/^Prérequis/i)).toBeInTheDocument();
|
||||
expect(screen.getByLabelText(/^Nom/i)).toHaveValue('');
|
||||
});
|
||||
|
||||
it('shows validation error when name is empty on submit', async () => {
|
||||
const user = userEvent.setup();
|
||||
renderNew();
|
||||
// Name field is empty by default — click Save directly
|
||||
const saveBtn = screen.getByRole('button', { name: /Save/i });
|
||||
const saveBtn = screen.getByRole('button', { name: /Enregistrer/i });
|
||||
await user.click(saveBtn);
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Name is required')).toBeInTheDocument();
|
||||
expect(screen.getByText('Le nom est obligatoire')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -115,8 +113,8 @@ describe('TemplateFormPage — new mode', () => {
|
||||
mock.onPost('/templates').reply(201, { ...TEMPLATE, id: 99 });
|
||||
const user = userEvent.setup();
|
||||
renderNew();
|
||||
await user.type(screen.getByLabelText(/Name/i), 'My Template');
|
||||
await user.click(screen.getByRole('button', { name: /Save/i }));
|
||||
await user.type(screen.getByLabelText(/^Nom/i), 'My Template');
|
||||
await user.click(screen.getByRole('button', { name: /Enregistrer/i }));
|
||||
await waitFor(() => {
|
||||
expect(mock.history.post.length).toBe(1);
|
||||
});
|
||||
@@ -128,8 +126,8 @@ describe('TemplateFormPage — new mode', () => {
|
||||
mock.onPost('/templates').reply(409, { error: 'template name already exists' });
|
||||
const user = userEvent.setup();
|
||||
renderNew();
|
||||
await user.type(screen.getByLabelText(/Name/i), 'Duplicate');
|
||||
await user.click(screen.getByRole('button', { name: /Save/i }));
|
||||
await user.type(screen.getByLabelText(/^Nom/i), 'Duplicate');
|
||||
await user.click(screen.getByRole('button', { name: /Enregistrer/i }));
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('template name already exists')).toBeInTheDocument();
|
||||
});
|
||||
@@ -137,7 +135,7 @@ describe('TemplateFormPage — new mode', () => {
|
||||
|
||||
it('does not show Delete button in new mode', () => {
|
||||
renderNew();
|
||||
expect(screen.queryByText('Delete')).toBeNull();
|
||||
expect(screen.queryByText('Supprimer')).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -176,7 +174,7 @@ describe('TemplateFormPage — edit mode', () => {
|
||||
await waitFor(() => {
|
||||
expect(screen.getByDisplayValue('Mimikatz LSASS Dump')).toBeInTheDocument();
|
||||
});
|
||||
expect(screen.getByText('Delete')).toBeInTheDocument();
|
||||
expect(screen.getByText('Supprimer')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('submits PATCH on save', async () => {
|
||||
@@ -187,7 +185,7 @@ describe('TemplateFormPage — edit mode', () => {
|
||||
await waitFor(() => {
|
||||
expect(screen.getByDisplayValue('Mimikatz LSASS Dump')).toBeInTheDocument();
|
||||
});
|
||||
await user.click(screen.getByRole('button', { name: /Save/i }));
|
||||
await user.click(screen.getByRole('button', { name: /Enregistrer/i }));
|
||||
await waitFor(() => {
|
||||
expect(mock.history.patch.length).toBe(1);
|
||||
});
|
||||
@@ -201,14 +199,14 @@ describe('TemplateFormPage — edit mode', () => {
|
||||
const user = userEvent.setup();
|
||||
renderEdit(5);
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Delete')).toBeInTheDocument();
|
||||
expect(screen.getByText('Supprimer')).toBeInTheDocument();
|
||||
});
|
||||
await user.click(screen.getByText('Delete'));
|
||||
await user.click(screen.getByText('Supprimer'));
|
||||
await waitFor(() => {
|
||||
expect(screen.getByRole('dialog')).toBeInTheDocument();
|
||||
});
|
||||
// Click the Delete button inside the dialog
|
||||
const dialogDeleteBtn = screen.getAllByText('Delete').find(
|
||||
// Click the Supprimer button inside the dialog
|
||||
const dialogDeleteBtn = screen.getAllByText('Supprimer').find(
|
||||
(el) => el.tagName === 'BUTTON' && el.closest('[role="dialog"]')
|
||||
) as HTMLElement;
|
||||
await user.click(dialogDeleteBtn);
|
||||
|
||||
@@ -76,7 +76,7 @@ describe('TemplatePickerModal', () => {
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('empty-state')).toBeInTheDocument();
|
||||
});
|
||||
expect(screen.getByText(/No templates available/i)).toBeInTheDocument();
|
||||
expect(screen.getByText(/Aucun template disponible/i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('lists templates with name and MITRE count', async () => {
|
||||
@@ -128,9 +128,9 @@ describe('TemplatePickerModal', () => {
|
||||
/>
|
||||
);
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Cancel')).toBeInTheDocument();
|
||||
expect(screen.getByText('Annuler')).toBeInTheDocument();
|
||||
});
|
||||
await user.click(screen.getByText('Cancel'));
|
||||
await user.click(screen.getByText('Annuler'));
|
||||
expect(onClose).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ describe('TemplatesListPage', () => {
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Mimikatz LSASS Dump')).toBeInTheDocument();
|
||||
});
|
||||
expect(screen.getAllByText(/New/i).length).toBeGreaterThan(0);
|
||||
expect(screen.getAllByText(/Nouveau/i).length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('shows Edit and Delete actions', async () => {
|
||||
@@ -109,8 +109,8 @@ describe('TemplatesListPage', () => {
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Mimikatz LSASS Dump')).toBeInTheDocument();
|
||||
});
|
||||
expect(screen.getAllByText('Edit').length).toBe(2);
|
||||
expect(screen.getAllByText('Delete').length).toBe(2);
|
||||
expect(screen.getAllByText('Modifier').length).toBe(2);
|
||||
expect(screen.getAllByText('Supprimer').length).toBe(2);
|
||||
});
|
||||
|
||||
it('calls delete endpoint on confirm', async () => {
|
||||
@@ -124,10 +124,10 @@ describe('TemplatesListPage', () => {
|
||||
|
||||
renderWithProviders(<TemplatesListPage />);
|
||||
await waitFor(() => {
|
||||
expect(screen.getAllByText('Delete')[0]).toBeInTheDocument();
|
||||
expect(screen.getAllByText('Supprimer')[0]).toBeInTheDocument();
|
||||
});
|
||||
|
||||
const deleteButtons = screen.getAllByText('Delete');
|
||||
const deleteButtons = screen.getAllByText('Supprimer');
|
||||
await user.click(deleteButtons[0]);
|
||||
|
||||
await waitFor(() => {
|
||||
|
||||
Reference in New Issue
Block a user