Merge remote-tracking branch 'origin/demo' into feat/monitoringpage-pim
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
import { useState } from 'react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { renderWithProviders, screen } from '../../../../test-utils/test-utils.tsx';
|
||||
import GestureValueEditor from '../../../../../src/pages/VisProgPage/visualProgrammingUI/components/GestureValueEditor';
|
||||
|
||||
function TestHarness({ initialValue = '', initialType=true, placeholder = 'Gesture name' } : { initialValue?: string, initialType?: boolean, placeholder?: string }) {
|
||||
const [value, setValue] = useState(initialValue);
|
||||
const [_, setType] = useState(initialType)
|
||||
return (
|
||||
<GestureValueEditor value={value} setValue={setValue} setType={setType} placeholder={placeholder} />
|
||||
);
|
||||
}
|
||||
|
||||
describe('GestureValueEditor', () => {
|
||||
let user: ReturnType<typeof userEvent.setup>;
|
||||
|
||||
beforeEach(() => {
|
||||
user = userEvent.setup();
|
||||
});
|
||||
|
||||
test('renders in tag mode by default and allows selecting a tag via button and select', async () => {
|
||||
renderWithProviders(<TestHarness />);
|
||||
|
||||
// Tag selector should be present
|
||||
const select = screen.getByTestId('tagSelectorTestID') as HTMLSelectElement;
|
||||
expect(select).toBeInTheDocument();
|
||||
expect(select.value).toBe('');
|
||||
|
||||
// Choose a tag via select
|
||||
await user.selectOptions(select, 'happy');
|
||||
expect(select.value).toBe('happy');
|
||||
|
||||
// The corresponding tag button should reflect the selection (have the selected class)
|
||||
const happyButton = screen.getByRole('button', { name: /happy/i });
|
||||
expect(happyButton).toBeInTheDocument();
|
||||
expect(happyButton.className).toMatch(/selected/);
|
||||
});
|
||||
|
||||
test('switches to single mode and shows suggestions list', async () => {
|
||||
renderWithProviders(<TestHarness initialValue={'happy'} />);
|
||||
|
||||
const singleButton = screen.getByRole('button', { name: /^single$/i });
|
||||
await user.click(singleButton);
|
||||
|
||||
// Input should be present with placeholder
|
||||
const input = screen.getByPlaceholderText('Gesture name') as HTMLInputElement;
|
||||
expect(input).toBeInTheDocument();
|
||||
|
||||
// Because switching to single populates suggestions, we expect at least one suggestion item
|
||||
const suggestion = await screen.findByText(/Listening_1/);
|
||||
expect(suggestion).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('typing filters suggestions and selecting a suggestion commits the value and hides the list', async () => {
|
||||
renderWithProviders(<TestHarness />);
|
||||
|
||||
// Switch to single mode
|
||||
await user.click(screen.getByRole('button', { name: /^single$/i }));
|
||||
const input = screen.getByPlaceholderText('Gesture name') as HTMLInputElement;
|
||||
|
||||
// Type a substring that matches some suggestions
|
||||
await user.type(input, 'Listening_2');
|
||||
|
||||
// The suggestion should appear and include the text we typed
|
||||
const matching = await screen.findByText(/Listening_2/);
|
||||
expect(matching).toBeInTheDocument();
|
||||
|
||||
// Click the suggestion
|
||||
await user.click(matching);
|
||||
|
||||
// After selecting, input should contain that suggestion and suggestions should be hidden
|
||||
expect(input.value).toContain('Listening_2');
|
||||
expect(screen.queryByText(/Listening_1/)).toBeNull();
|
||||
});
|
||||
|
||||
test('typing a non-matching string hides the suggestions list', async () => {
|
||||
renderWithProviders(<TestHarness />);
|
||||
await user.click(screen.getByRole('button', { name: /^single$/i }));
|
||||
const input = screen.getByPlaceholderText('Gesture name') as HTMLInputElement;
|
||||
|
||||
await user.type(input, 'no-match-zzz');
|
||||
|
||||
// There should be no suggestion that includes that gibberish
|
||||
expect(screen.queryByText(/no-match-zzz/)).toBeNull();
|
||||
});
|
||||
|
||||
test('switching back to tag mode clears value when it is not a valid tag and preserves it when it is', async () => {
|
||||
renderWithProviders(<TestHarness />);
|
||||
|
||||
// Switch to single mode and pick a suggestion (which is not a semantic tag)
|
||||
await user.click(screen.getByRole('button', { name: /^single$/i }));
|
||||
const input = screen.getByPlaceholderText('Gesture name') as HTMLInputElement;
|
||||
await user.type(input, 'Listening_3');
|
||||
const suggestion = await screen.findByText(/Listening_3/);
|
||||
await user.click(suggestion);
|
||||
|
||||
// Switch back to tag mode -> value should be cleared (not in tag list)
|
||||
await user.click(screen.getByRole('button', { name: /^tag$/i }));
|
||||
const select = screen.getByTestId('tagSelectorTestID') as HTMLSelectElement;
|
||||
expect(select.value).toBe('');
|
||||
|
||||
// Now pick a valid tag and switch to single then back to tag
|
||||
await user.selectOptions(select, 'happy');
|
||||
expect(select.value).toBe('happy');
|
||||
|
||||
// Switch to single and then back to tag; since 'happy' is a valid tag, it should remain
|
||||
await user.click(screen.getByRole('button', { name: /^single$/i }));
|
||||
await user.click(screen.getByRole('button', { name: /^tag$/i }));
|
||||
expect(select.value).toBe('happy');
|
||||
});
|
||||
|
||||
test('focus on input re-shows filtered suggestions when customValue is present', async () => {
|
||||
renderWithProviders(<TestHarness />);
|
||||
|
||||
// Switch to single mode and type to filter
|
||||
await user.click(screen.getByRole('button', { name: /^single$/i }));
|
||||
const input = screen.getByPlaceholderText('Gesture name') as HTMLInputElement;
|
||||
|
||||
await user.type(input, 'Listening_4');
|
||||
const found = await screen.findByText(/Listening_4/);
|
||||
expect(found).toBeInTheDocument();
|
||||
|
||||
// Blur the input
|
||||
input.blur();
|
||||
expect(found).toBeInTheDocument();
|
||||
|
||||
// Focus the input again and ensure the suggestions remain or reappear
|
||||
await user.click(input);
|
||||
const foundAgain = await screen.findByText(/Listening_4/);
|
||||
expect(foundAgain).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user