The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/public/app/plugins/datasource/loki/querybuilder/components/NestedQuery.test.tsx

102 lines
3.3 KiB

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();
});
});