diff --git a/frontend/tests/MitreTechniquePicker.test.tsx b/frontend/tests/MitreTechniquePicker.test.tsx index f1e1d42..9a416cc 100644 --- a/frontend/tests/MitreTechniquePicker.test.tsx +++ b/frontend/tests/MitreTechniquePicker.test.tsx @@ -219,6 +219,26 @@ describe('MitreTechniquePicker', () => { expect(screen.queryByRole('listbox')).toBeNull(); }); + it('typing while techniqueId is null does not reset inputValue between keystrokes', async () => { + mock.onGet('/mitre/techniques').reply(200, []); + const user = userEvent.setup({ advanceTimers: (ms) => vi.advanceTimersByTime(ms) }); + + renderWithProviders( + , + ); + + const input = screen.getByRole('combobox') as HTMLInputElement; + await user.click(input); + await user.type(input, 'T10'); + + // Input must retain the full typed value — no mid-stroke reset + expect(input.value).toBe('T10'); + }); + it('shows inline error when API returns 503', async () => { mock.onGet('/mitre/techniques').reply(503, { error: 'mitre bundle not loaded' }); const user = userEvent.setup({ advanceTimers: (ms) => vi.advanceTimersByTime(ms) }); diff --git a/frontend/tests/SimulationList.test.tsx b/frontend/tests/SimulationList.test.tsx index 8c18068..ecd2c07 100644 --- a/frontend/tests/SimulationList.test.tsx +++ b/frontend/tests/SimulationList.test.tsx @@ -1,5 +1,5 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; -import { screen, waitFor } from '@testing-library/react'; +import { screen, waitFor, fireEvent } from '@testing-library/react'; import MockAdapter from 'axios-mock-adapter'; import { apiClient } from '@/api/client'; import { SimulationList } from '@/components/SimulationList'; @@ -104,6 +104,25 @@ describe('SimulationList — admin/redteam', () => { }); expect(screen.getByTestId('new-simulation-btn')).toBeInTheDocument(); }); + + it('clicking a row uses SPA navigation and does not trigger window.location change', async () => { + mock.onGet('/engagements/42/simulations').reply(200, SIMULATIONS); + const originalHref = window.location.href; + + renderWithProviders(, { + routerProps: { initialEntries: ['/engagements/42'] }, + }); + + await waitFor(() => { + expect(screen.getByText('Lateral movement test')).toBeInTheDocument(); + }); + + const row = screen.getByText('Lateral movement test').closest('tr') as HTMLElement; + fireEvent.click(row); + + // window.location.href must be unchanged (no full-page reload) + expect(window.location.href).toBe(originalHref); + }); }); describe('SimulationList — SOC role (no edit button)', () => {