Loki: Add tests for NestedQuery.tsx (#56538)

* WIP: Testing the NestedQuery component

* Add tests for NestedQuery.jsx

* Add aria-labels to select elements

* Update aria-labels

* Create datasource using createLokiDatasource()
This commit is contained in:
Gareth Dawson 2022-10-11 09:22:32 +01:00 committed by GitHub
parent 8d9da34827
commit fa09aef4ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 104 additions and 1 deletions

View File

@ -0,0 +1,102 @@
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
import { createLokiDatasource } from '../../mocks';
import { LokiVisualQueryBinary } from '../types';
import { NestedQuery, Props as NestedQueryProps } from './NestedQuery';
type Operator = '+' | '-' | '*' | '/' | '%' | '^' | '==' | '!=' | '>' | '<' | '>=' | '<=';
type VectorMatchType = 'on' | 'ignoring';
const createMockProps = (
operator: Operator = '/',
vectorMatchesType: VectorMatchType = 'on',
showExplain = false
): NestedQueryProps => {
const nestedQuery: LokiVisualQueryBinary = {
operator: operator,
vectorMatchesType: vectorMatchesType,
query: {
labels: [],
operations: [],
},
};
const datasource = createLokiDatasource();
const props: NestedQueryProps = {
nestedQuery: nestedQuery,
index: 0,
datasource: datasource,
onChange: jest.fn(),
onRemove: jest.fn(),
onRunQuery: jest.fn(),
showExplain: showExplain,
};
return props;
};
// All test assertions need to be awaited for, because the component uses `useEffect` to update the state.
describe('render all elements', () => {
it('renders the operator label', async () => {
const props = createMockProps();
render(<NestedQuery {...props} />);
expect(await screen.findByText('Operator')).toBeInTheDocument();
});
it('renders the expected operator value', async () => {
const props = createMockProps('!=');
render(<NestedQuery {...props} />);
expect(await screen.findByText('!=')).toBeInTheDocument();
});
it('renders the vector matches label', async () => {
const props = createMockProps();
render(<NestedQuery {...props} />);
expect(await screen.findByText('Vector matches')).toBeInTheDocument();
});
it('renders the expected vector matches value', async () => {
const props = createMockProps(undefined, 'ignoring');
render(<NestedQuery {...props} />);
expect(await screen.findByText('ignoring')).toBeInTheDocument();
});
});
describe('exit the nested query', () => {
it('onRemove is called when clicking (x)', async () => {
const props = createMockProps();
render(<NestedQuery {...props} />);
fireEvent.click(await screen.findByLabelText('Remove nested query'));
await waitFor(() => expect(props.onRemove).toHaveBeenCalledTimes(1));
});
});
describe('change operator', () => {
it('onChange is called with the correct args', async () => {
const props = createMockProps('/', 'on');
render(<NestedQuery {...props} />);
userEvent.click(await screen.findByLabelText('Select operator'));
fireEvent.click(await screen.findByText('+'));
await waitFor(() => expect(props.onChange).toHaveBeenCalledTimes(1));
await waitFor(() =>
expect(props.onChange).toHaveBeenCalledWith(0, {
operator: '+',
vectorMatchesType: 'on',
query: { labels: [], operations: [] },
})
);
});
});
describe('explain mode', () => {
it('shows the explanation when set to true', async () => {
const props = createMockProps(undefined, undefined, true);
render(<NestedQuery {...props} />);
expect(await screen.findByText('Fetch all log lines matching label filters.')).toBeInTheDocument();
});
});

View File

@ -29,6 +29,7 @@ export const NestedQuery = React.memo<Props>(
<div className={styles.header}>
<div className={styles.name}>Operator</div>
<Select
aria-label="Select operator"
width="auto"
options={operators}
value={toOption(nestedQuery.operator)}
@ -70,7 +71,7 @@ export const NestedQuery = React.memo<Props>(
/>
</div>
<FlexItem grow={1} />
<IconButton name="times" size="sm" onClick={() => onRemove(index)} />
<IconButton ariaLabel="Remove nested query" name="times" size="sm" onClick={() => onRemove(index)} />
</div>
<div className={styles.body}>
<EditorRows>