grafana/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilderOptions.tes...

185 lines
7.0 KiB
TypeScript
Raw Normal View History

import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { LokiQuery, LokiQueryType } from '../../types';
import { LokiQueryBuilderOptions } from './LokiQueryBuilderOptions';
describe('LokiQueryBuilderOptions', () => {
it('can change query type', async () => {
const { props } = setup();
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
expect(screen.getByLabelText('Range')).toBeChecked();
await userEvent.click(screen.getByLabelText('Instant'));
expect(props.onChange).toHaveBeenCalledWith({
...props.query,
queryType: LokiQueryType.Instant,
});
});
it('can change legend format', async () => {
const { props } = setup();
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
// First autosize input is a Legend
const element = screen.getAllByTestId('autosize-input')[0];
await userEvent.type(element, 'asd');
await userEvent.keyboard('{enter}');
expect(props.onChange).toHaveBeenCalledWith({
...props.query,
legendFormat: 'asd',
});
});
it('can change line limit to valid value', async () => {
const { props } = setup({ expr: '{foo="bar"}' });
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
// Second autosize input is a Line limit
const element = screen.getAllByTestId('autosize-input')[1];
await userEvent.type(element, '10');
await userEvent.keyboard('{enter}');
expect(props.onChange).toHaveBeenCalledWith({
...props.query,
maxLines: 10,
});
});
it('does not change line limit to invalid numeric value', async () => {
const { props } = setup({ expr: '{foo="bar"}' });
// We need to start with some value to be able to change it
props.query.maxLines = 10;
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
// Second autosize input is a Line limit
const element = screen.getAllByTestId('autosize-input')[1];
await userEvent.type(element, '-10');
await userEvent.keyboard('{enter}');
expect(props.onChange).toHaveBeenCalledWith({
...props.query,
maxLines: undefined,
});
});
it('does not change line limit to invalid text value', async () => {
const { props } = setup({ expr: '{foo="bar"}' });
// We need to start with some value to be able to change it
props.query.maxLines = 10;
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
// Second autosize input is a Line limit
const element = screen.getAllByTestId('autosize-input')[1];
await userEvent.type(element, 'asd');
await userEvent.keyboard('{enter}');
expect(props.onChange).toHaveBeenCalledWith({
...props.query,
maxLines: undefined,
});
});
it('shows correct options for log query', async () => {
setup({ expr: '{foo="bar"}' });
expect(screen.getByText('Line limit: 20')).toBeInTheDocument();
expect(screen.getByText('Type: Range')).toBeInTheDocument();
Loki: Added support to split queries by stream shard (#94245) * Add shard query splitting implementation * Shard query splitting: reuse function from query splitting * Shard query splitting: remove max line limit * Shard query splitting: update test * Shard query splitting: fix types and non-sharded queries * Merge responses: fix log merging * Merge responses: remove legacy code * Query splitting: add support to retry failed requests * Query splitting: unit test request retrying * Query splitting: add unsubscriptions * Shard query splitting: fix retrying * Shard query splitting: switch to dynamic grouping * Shard query splitting: update group size thresholds and fix -1 query * Shard query splitting: update initial group size + don't retry parse errors * Shard query splitting: update unit test * chore: update mock value * Shard query splitting: add support for multiple targets * chore: update description * Shard query splitting: use group targets * chore: filter hidden queries * Shard query splitting: issue initial log query without sharding * Splitting: fix retrying in both methods * Merge responses: keep execution time * Shard query splitting: remove no-shard attempt * Shard query splitting: adjust groups based on rate of change * chore: clean up experiments * Shard query splittng: remove log query restrictions * Shard query splitting: remove fallback to time splitting * Loki: add new query direction * Missing generated file * LokiOptionField: integrate new query direction * Shard query splitting: delegate non-scan queries to time splitting * Query splitting: do not retry queries with parse errors * Loki datasource: add placeholder for feature flag * Shard query splitting: add function with support criteria * Shard query splitting: refactor query modification and shard logs volume * Shard query splitting: update unit tests * chore: Update scan direction tooltip * chore: formatting * LogsVolumePanel: fix missing state in logs volume panel data * Merge responses: better handle missing nanoseconds * LokiQueryOptionFields: display query direction for log queries * loki: process scan direction as backward * Loki datasource: restrict sharding to Explore * Retrying: invert criteria and move to response utils * Formatting * Use log volume refId constant * Fix import order * Create feature flag * Use feature toggle * LogsVolumePanel: prevent flashing no data while streaming
2024-10-23 19:21:03 +08:00
expect(screen.getByText('Direction: Backward')).toBeInTheDocument();
expect(screen.queryByText(/step/i)).not.toBeInTheDocument();
});
it('shows correct options for metric query', async () => {
setup({ expr: 'rate({foo="bar"}[5m]', step: '1m', resolution: 2 });
expect(screen.queryByText('Line limit: 20')).not.toBeInTheDocument();
expect(screen.getByText('Type: Range')).toBeInTheDocument();
expect(screen.getByText('Step: 1m')).toBeInTheDocument();
expect(screen.getByText('Resolution: 1/2')).toBeInTheDocument();
Loki: Added support to split queries by stream shard (#94245) * Add shard query splitting implementation * Shard query splitting: reuse function from query splitting * Shard query splitting: remove max line limit * Shard query splitting: update test * Shard query splitting: fix types and non-sharded queries * Merge responses: fix log merging * Merge responses: remove legacy code * Query splitting: add support to retry failed requests * Query splitting: unit test request retrying * Query splitting: add unsubscriptions * Shard query splitting: fix retrying * Shard query splitting: switch to dynamic grouping * Shard query splitting: update group size thresholds and fix -1 query * Shard query splitting: update initial group size + don't retry parse errors * Shard query splitting: update unit test * chore: update mock value * Shard query splitting: add support for multiple targets * chore: update description * Shard query splitting: use group targets * chore: filter hidden queries * Shard query splitting: issue initial log query without sharding * Splitting: fix retrying in both methods * Merge responses: keep execution time * Shard query splitting: remove no-shard attempt * Shard query splitting: adjust groups based on rate of change * chore: clean up experiments * Shard query splittng: remove log query restrictions * Shard query splitting: remove fallback to time splitting * Loki: add new query direction * Missing generated file * LokiOptionField: integrate new query direction * Shard query splitting: delegate non-scan queries to time splitting * Query splitting: do not retry queries with parse errors * Loki datasource: add placeholder for feature flag * Shard query splitting: add function with support criteria * Shard query splitting: refactor query modification and shard logs volume * Shard query splitting: update unit tests * chore: Update scan direction tooltip * chore: formatting * LogsVolumePanel: fix missing state in logs volume panel data * Merge responses: better handle missing nanoseconds * LokiQueryOptionFields: display query direction for log queries * loki: process scan direction as backward * Loki datasource: restrict sharding to Explore * Retrying: invert criteria and move to response utils * Formatting * Use log volume refId constant * Fix import order * Create feature flag * Use feature toggle * LogsVolumePanel: prevent flashing no data while streaming
2024-10-23 19:21:03 +08:00
expect(screen.queryByText(/Direction/)).not.toBeInTheDocument();
});
it('does not shows resolution field if resolution is not set', async () => {
setup({ expr: 'rate({foo="bar"}[5m]' });
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
expect(screen.queryByText('Resolution')).not.toBeInTheDocument();
});
it('does not shows resolution field if resolution is set to default value 1', async () => {
setup({ expr: 'rate({foo="bar"}[5m]', resolution: 1 });
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
expect(screen.queryByText('Resolution')).not.toBeInTheDocument();
});
it('does shows resolution field with warning if resolution is set to non-default value', async () => {
setup({ expr: 'rate({foo="bar"}[5m]', resolution: 2 });
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
expect(screen.getByText('Resolution')).toBeInTheDocument();
expect(
screen.getByText("The 'Resolution' is deprecated. Use 'Step' editor instead to change step parameter.")
).toBeInTheDocument();
});
it('shows correct options for metric query with invalid step', async () => {
setup({ expr: 'rate({foo="bar"}[5m]', step: 'abc' });
expect(screen.queryByText('Line limit: 20')).not.toBeInTheDocument();
expect(screen.getByText('Type: Range')).toBeInTheDocument();
expect(screen.getByText('Step: Invalid value')).toBeInTheDocument();
});
it('shows error when invalid value in step', async () => {
setup({ expr: 'rate({foo="bar"}[5m]', step: 'a' });
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
expect(screen.getByText(/Invalid step/)).toBeInTheDocument();
});
it('does not shows error when valid value in step', async () => {
setup({ expr: 'rate({foo="bar"}[5m]', step: '1m' });
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
expect(screen.queryByText(/Invalid step/)).not.toBeInTheDocument();
});
it('does not shows error when valid millisecond value in step', async () => {
setup({ expr: 'rate({foo="bar"}[5m]', step: '1ms' });
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
expect(screen.queryByText(/Invalid step/)).not.toBeInTheDocument();
});
it('does not shows error when valid day value in step', async () => {
setup({ expr: 'rate({foo="bar"}[5m]', step: '1d' });
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
expect(screen.queryByText(/Invalid step/)).not.toBeInTheDocument();
});
it('does not show instant type when using a log query', async () => {
setup({ expr: '{foo="bar"}', queryType: LokiQueryType.Instant });
expect(screen.queryByText(/Instant/)).not.toBeInTheDocument();
});
it('does not show instant type in the options when using a log query', async () => {
setup({ expr: '{foo="bar"}', step: '1m' });
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
expect(screen.queryByText(/Instant/)).not.toBeInTheDocument();
});
});
function setup(queryOverrides: Partial<LokiQuery> = {}) {
const props = {
query: {
refId: 'A',
expr: '',
...queryOverrides,
},
onRunQuery: jest.fn(),
onChange: jest.fn(),
maxLines: 20,
queryStats: { streams: 0, chunks: 0, bytes: 0, entries: 0 },
};
const { container } = render(<LokiQueryBuilderOptions {...props} />);
return { container, props };
}