mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Expressions: Add tests for the QueryEditorRows and QueryGroup components (#63394)
* add QueryGroup onAddQueryClick and onExpressionClick tests * add test's for the query group component - new query/expression should be expanded - adds query/expression onclick * add open data source help modal test * add disabled expression test * add query editor rows test * rm unused attributes, rm renderScenario required override
This commit is contained in:
parent
33277fccde
commit
5ec8e370f7
2
.yarn/sdks/integrations.yml
vendored
2
.yarn/sdks/integrations.yml
vendored
@ -2,5 +2,5 @@
|
||||
# Manual changes might be lost!
|
||||
|
||||
integrations:
|
||||
- vim
|
||||
- vscode
|
||||
- vim
|
||||
|
@ -490,7 +490,7 @@ export class QueryEditorRow<TQuery extends DataQuery> extends PureComponent<Prop
|
||||
const DatasourceCheatsheet = datasource.components?.QueryEditorHelp;
|
||||
|
||||
return (
|
||||
<div aria-label={selectors.components.QueryEditorRows.rows}>
|
||||
<div data-testid="query-editor-row" aria-label={selectors.components.QueryEditorRows.rows}>
|
||||
<QueryOperationRow
|
||||
id={this.id}
|
||||
draggable={true}
|
||||
|
156
public/app/features/query/components/QueryEditorRows.test.tsx
Normal file
156
public/app/features/query/components/QueryEditorRows.test.tsx
Normal file
@ -0,0 +1,156 @@
|
||||
import { fireEvent, queryByLabelText, render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
|
||||
import { type DataQuery } from '@grafana/schema';
|
||||
import { mockDataSource } from 'app/features/alerting/unified/mocks';
|
||||
import { DataSourceType } from 'app/features/alerting/unified/utils/datasource';
|
||||
import createMockPanelData from 'app/plugins/datasource/azuremonitor/__mocks__/panelData';
|
||||
|
||||
import { QueryEditorRows, Props } from './QueryEditorRows';
|
||||
|
||||
const mockDS = mockDataSource({
|
||||
name: 'CloudManager',
|
||||
type: DataSourceType.Alertmanager,
|
||||
});
|
||||
|
||||
const mockVariable = mockDataSource({
|
||||
name: '${dsVariable}',
|
||||
type: 'datasource',
|
||||
});
|
||||
|
||||
jest.mock('@grafana/runtime/src/services/dataSourceSrv', () => {
|
||||
return {
|
||||
getDataSourceSrv: () => ({
|
||||
get: () => Promise.resolve({ ...mockDS, getRef: () => {} }),
|
||||
getList: ({ variables }: { variables: boolean }) => (variables ? [mockDS, mockVariable] : [mockDS]),
|
||||
getInstanceSettings: () => ({
|
||||
...mockDS,
|
||||
meta: {
|
||||
...mockDS.meta,
|
||||
alerting: true,
|
||||
mixed: true,
|
||||
},
|
||||
}),
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
const props: Props = {
|
||||
queries: [
|
||||
{
|
||||
datasource: mockDS,
|
||||
refId: 'A',
|
||||
},
|
||||
{
|
||||
datasource: mockDS,
|
||||
refId: 'B',
|
||||
},
|
||||
],
|
||||
dsSettings: mockDataSource(),
|
||||
onQueriesChange: function (queries: DataQuery[]): void {
|
||||
throw new Error('Function not implemented.');
|
||||
},
|
||||
onAddQuery: function (query: DataQuery): void {
|
||||
throw new Error('Function not implemented.');
|
||||
},
|
||||
onRunQueries: function (): void {
|
||||
throw new Error('Function not implemented.');
|
||||
},
|
||||
data: createMockPanelData(),
|
||||
};
|
||||
|
||||
jest.mock('@grafana/runtime/src/services/dataSourceSrv', () => {
|
||||
return {
|
||||
getDataSourceSrv: () => ({
|
||||
get: () => Promise.resolve(mockDS),
|
||||
getList: ({ variables }: { variables: boolean }) => (variables ? [mockDS, mockVariable] : [mockDS]),
|
||||
getInstanceSettings: () => mockDS,
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
describe('QueryEditorRows', () => {
|
||||
it('Should render queries', async () => {
|
||||
const {
|
||||
renderResult: { rerender },
|
||||
} = renderScenario();
|
||||
expect((await screen.findByTestId('query-editor-rows')).children.length).toBe(2);
|
||||
|
||||
rerender(
|
||||
<QueryEditorRows
|
||||
{...props}
|
||||
queries={[
|
||||
{
|
||||
datasource: mockDS,
|
||||
refId: 'A',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
|
||||
expect((await screen.findByTestId('query-editor-rows')).children.length).toBe(1);
|
||||
});
|
||||
|
||||
it('Should be able to expand and collapse queries', async () => {
|
||||
renderScenario();
|
||||
const queryEditorRows = await screen.findAllByTestId('query-editor-row');
|
||||
|
||||
for (const childQuery of queryEditorRows) {
|
||||
const toggleExpandButton = queryByLabelText(childQuery, 'toggle collapse and expand query row') as HTMLElement;
|
||||
|
||||
expect(toggleExpandButton).toBeInTheDocument();
|
||||
expect(toggleExpandButton.getAttribute('aria-expanded')).toBe('true');
|
||||
|
||||
fireEvent.click(toggleExpandButton);
|
||||
|
||||
expect(toggleExpandButton.getAttribute('aria-expanded')).toBe('false');
|
||||
}
|
||||
});
|
||||
|
||||
it('Should be able to duplicate queries', async () => {
|
||||
const onAddQuery = jest.fn();
|
||||
const onQueryCopied = jest.fn();
|
||||
|
||||
renderScenario({ onAddQuery, onQueryCopied });
|
||||
const queryEditorRows = await screen.findAllByTestId('query-editor-row');
|
||||
queryEditorRows.map(async (childQuery) => {
|
||||
const duplicateQueryButton = queryByLabelText(
|
||||
childQuery,
|
||||
'Duplicate query query operation action'
|
||||
) as HTMLElement;
|
||||
|
||||
expect(duplicateQueryButton).toBeInTheDocument();
|
||||
|
||||
fireEvent.click(duplicateQueryButton);
|
||||
});
|
||||
|
||||
expect(onAddQuery).toHaveBeenCalledTimes(queryEditorRows.length);
|
||||
expect(onQueryCopied).toHaveBeenCalledTimes(queryEditorRows.length);
|
||||
});
|
||||
|
||||
it('Should be able to delete queries', async () => {
|
||||
const onQueriesChange = jest.fn();
|
||||
const onQueryRemoved = jest.fn();
|
||||
renderScenario({ onQueriesChange, onQueryRemoved });
|
||||
|
||||
const queryEditorRows = await screen.findAllByTestId('query-editor-row');
|
||||
queryEditorRows.map(async (childQuery) => {
|
||||
const deleteQueryButton = queryByLabelText(childQuery, 'Remove query query operation action') as HTMLElement;
|
||||
|
||||
expect(deleteQueryButton).toBeInTheDocument();
|
||||
|
||||
fireEvent.click(deleteQueryButton);
|
||||
});
|
||||
|
||||
expect(onQueriesChange).toHaveBeenCalledTimes(queryEditorRows.length);
|
||||
expect(onQueryRemoved).toHaveBeenCalledTimes(queryEditorRows.length);
|
||||
});
|
||||
});
|
||||
|
||||
function renderScenario(overrides?: Partial<Props>) {
|
||||
Object.assign(props, overrides);
|
||||
|
||||
return {
|
||||
renderResult: render(<QueryEditorRows {...props} />),
|
||||
};
|
||||
}
|
@ -14,7 +14,7 @@ import { getDataSourceSrv, reportInteraction } from '@grafana/runtime';
|
||||
|
||||
import { QueryEditorRow } from './QueryEditorRow';
|
||||
|
||||
interface Props {
|
||||
export interface Props {
|
||||
// The query configuration
|
||||
queries: DataQuery[];
|
||||
dsSettings: DataSourceInstanceSettings;
|
||||
@ -151,7 +151,7 @@ export class QueryEditorRows extends PureComponent<Props> {
|
||||
<Droppable droppableId="transformations-list" direction="vertical">
|
||||
{(provided) => {
|
||||
return (
|
||||
<div ref={provided.innerRef} {...provided.droppableProps}>
|
||||
<div data-testid="query-editor-rows" ref={provided.innerRef} {...provided.droppableProps}>
|
||||
{queries.map((query, index) => {
|
||||
const dataSourceSettings = getDataSourceSettings(query, dsSettings);
|
||||
const onChangeDataSourceSettings = dsSettings.meta.mixed
|
||||
|
149
public/app/features/query/components/QueryGroup.test.tsx
Normal file
149
public/app/features/query/components/QueryGroup.test.tsx
Normal file
@ -0,0 +1,149 @@
|
||||
import { act, render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
|
||||
import config from 'app/core/config';
|
||||
import { mockDataSource } from 'app/features/alerting/unified/mocks';
|
||||
import { DataSourceType } from 'app/features/alerting/unified/utils/datasource';
|
||||
|
||||
import { PanelQueryRunner } from '../state/PanelQueryRunner';
|
||||
|
||||
import { Props, QueryGroup } from './QueryGroup';
|
||||
|
||||
const mockDS = mockDataSource({
|
||||
name: 'CloudManager',
|
||||
type: DataSourceType.Alertmanager,
|
||||
});
|
||||
|
||||
const mockVariable = mockDataSource({
|
||||
name: '${dsVariable}',
|
||||
type: 'datasource',
|
||||
});
|
||||
|
||||
jest.mock('@grafana/runtime/src/services/dataSourceSrv', () => {
|
||||
return {
|
||||
getDataSourceSrv: () => ({
|
||||
get: () => Promise.resolve({ ...mockDS, getRef: () => {} }),
|
||||
getList: ({ variables }: { variables: boolean }) => (variables ? [mockDS, mockVariable] : [mockDS]),
|
||||
getInstanceSettings: () => ({
|
||||
...mockDS,
|
||||
meta: {
|
||||
...mockDS.meta,
|
||||
alerting: true,
|
||||
mixed: true,
|
||||
},
|
||||
}),
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
describe('QueryGroup', () => {
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
config.expressionsEnabled = true;
|
||||
});
|
||||
it('Should add expression on click', async () => {
|
||||
renderScenario({});
|
||||
|
||||
const addExpressionButton = await screen.findByTestId('query-tab-add-expression');
|
||||
const queryRowsContainer = await screen.findByTestId('query-editor-rows');
|
||||
expect(queryRowsContainer.children.length).toBe(2);
|
||||
|
||||
await addExpressionButton.click();
|
||||
expect(queryRowsContainer.children.length).toBe(3);
|
||||
});
|
||||
|
||||
it('Should add query on click', async () => {
|
||||
renderScenario({});
|
||||
|
||||
const addQueryButton = await screen.findByTestId('query-tab-add-query');
|
||||
const queryRowsContainer = await screen.findByTestId('query-editor-rows');
|
||||
expect(queryRowsContainer.children.length).toBe(2);
|
||||
|
||||
await addQueryButton.click();
|
||||
|
||||
expect(queryRowsContainer.children.length).toBe(3);
|
||||
});
|
||||
|
||||
it('New expression should be expanded', async () => {
|
||||
renderScenario({});
|
||||
|
||||
const addExpressionButton = await screen.findByTestId('query-tab-add-expression');
|
||||
const queryRowsContainer = await screen.findByTestId('query-editor-rows');
|
||||
await addExpressionButton.click();
|
||||
|
||||
const lastQueryEditorRow = (await screen.findAllByTestId('query-editor-row')).at(-1);
|
||||
const lastEditorToggleRow = (await screen.findAllByLabelText('toggle collapse and expand query row')).at(-1);
|
||||
|
||||
expect(lastEditorToggleRow?.getAttribute('aria-expanded')).toBe('true');
|
||||
expect(lastQueryEditorRow?.firstElementChild?.children.length).toBe(2);
|
||||
expect(queryRowsContainer.children.length).toBe(3);
|
||||
});
|
||||
|
||||
it('New query should be expanded', async () => {
|
||||
renderScenario({});
|
||||
|
||||
const addQueryButton = await screen.findByTestId('query-tab-add-query');
|
||||
const queryRowsContainer = await screen.findByTestId('query-editor-rows');
|
||||
await addQueryButton.click();
|
||||
|
||||
const lastQueryEditorRow = (await screen.findAllByTestId('query-editor-row')).at(-1);
|
||||
const lastEditorToggleRow = (await screen.findAllByLabelText('toggle collapse and expand query row')).at(-1);
|
||||
|
||||
expect(lastEditorToggleRow?.getAttribute('aria-expanded')).toBe('true');
|
||||
expect(lastQueryEditorRow?.firstElementChild?.children.length).toBe(2);
|
||||
expect(queryRowsContainer.children.length).toBe(3);
|
||||
});
|
||||
|
||||
it('Should open data source help modal', async () => {
|
||||
renderScenario({});
|
||||
|
||||
const openHelpButton = await screen.findByTestId('query-tab-help-button');
|
||||
await act(async () => {
|
||||
await openHelpButton.click();
|
||||
});
|
||||
|
||||
const helpModal = await screen.findByRole('dialog');
|
||||
expect(helpModal).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Should not show add expression button when expressions are disabled', async () => {
|
||||
config.expressionsEnabled = false;
|
||||
renderScenario({});
|
||||
const addExpressionButton = screen.queryByTestId('query-tab-add-expression');
|
||||
expect(addExpressionButton).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
function renderScenario(overrides: Partial<Props>) {
|
||||
const props: Props = {
|
||||
onOptionsChange: jest.fn(),
|
||||
queryRunner: new PanelQueryRunner({
|
||||
getDataSupport: jest.fn(),
|
||||
getFieldOverrideOptions: jest.fn(),
|
||||
getTransformations: jest.fn(),
|
||||
}),
|
||||
options: {
|
||||
queries: [
|
||||
{
|
||||
datasource: mockDS,
|
||||
refId: 'A',
|
||||
},
|
||||
{
|
||||
datasource: mockDS,
|
||||
refId: 'B',
|
||||
},
|
||||
],
|
||||
dataSource: mockDS,
|
||||
},
|
||||
onRunQueries: function (): void {
|
||||
throw new Error('Function not implemented.');
|
||||
},
|
||||
};
|
||||
|
||||
Object.assign(props, overrides);
|
||||
|
||||
return {
|
||||
props,
|
||||
renderResult: render(<QueryGroup {...props} />),
|
||||
};
|
||||
}
|
@ -32,7 +32,7 @@ import { QueryEditorRows } from './QueryEditorRows';
|
||||
import { QueryGroupOptionsEditor } from './QueryGroupOptions';
|
||||
import { SavedQueryPicker } from './SavedQueryPicker';
|
||||
|
||||
interface Props {
|
||||
export interface Props {
|
||||
queryRunner: PanelQueryRunner;
|
||||
options: QueryGroupOptions;
|
||||
onOpenQueryInspector?: () => void;
|
||||
@ -94,6 +94,7 @@ export class QueryGroup extends PureComponent<Props, State> {
|
||||
try {
|
||||
const ds = await this.dataSourceSrv.get(options.dataSource);
|
||||
const dsSettings = this.dataSourceSrv.getInstanceSettings(options.dataSource);
|
||||
|
||||
const defaultDataSource = await this.dataSourceSrv.get();
|
||||
const datasource = ds.getRef();
|
||||
const queries = options.queries.map((q) => ({
|
||||
@ -290,6 +291,7 @@ export class QueryGroup extends PureComponent<Props, State> {
|
||||
icon="question-circle"
|
||||
title="Open data source help"
|
||||
onClick={this.onOpenHelp}
|
||||
data-testid="query-tab-help-button"
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.dataSourceRowItemOptions}>
|
||||
@ -375,7 +377,6 @@ export class QueryGroup extends PureComponent<Props, State> {
|
||||
renderQueries(dsSettings: DataSourceInstanceSettings) {
|
||||
const { onRunQueries } = this.props;
|
||||
const { data, queries } = this.state;
|
||||
|
||||
if (isSharedDashboardQuery(dsSettings.name)) {
|
||||
return (
|
||||
<DashboardQueryEditor
|
||||
@ -429,6 +430,7 @@ export class QueryGroup extends PureComponent<Props, State> {
|
||||
onClick={this.onAddQueryClick}
|
||||
variant="secondary"
|
||||
aria-label={selectors.components.QueryTab.addQuery}
|
||||
data-testid="query-tab-add-query"
|
||||
>
|
||||
Query
|
||||
</Button>
|
||||
@ -439,6 +441,7 @@ export class QueryGroup extends PureComponent<Props, State> {
|
||||
onClick={this.onAddExpressionClick}
|
||||
variant="secondary"
|
||||
className={styles.expressionButton}
|
||||
data-testid="query-tab-add-expression"
|
||||
>
|
||||
<span>Expression </span>
|
||||
</Button>
|
||||
|
Loading…
Reference in New Issue
Block a user