From 5ec8e370f778953cf16468d3d5b7aae13746adea Mon Sep 17 00:00:00 2001 From: Abdul Date: Wed, 22 Feb 2023 12:26:41 -0300 Subject: [PATCH] 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 --- .yarn/sdks/integrations.yml | 2 +- .../query/components/QueryEditorRow.tsx | 2 +- .../query/components/QueryEditorRows.test.tsx | 156 ++++++++++++++++++ .../query/components/QueryEditorRows.tsx | 4 +- .../query/components/QueryGroup.test.tsx | 149 +++++++++++++++++ .../features/query/components/QueryGroup.tsx | 7 +- 6 files changed, 314 insertions(+), 6 deletions(-) create mode 100644 public/app/features/query/components/QueryEditorRows.test.tsx create mode 100644 public/app/features/query/components/QueryGroup.test.tsx diff --git a/.yarn/sdks/integrations.yml b/.yarn/sdks/integrations.yml index 401be99859b..7e42d1884d8 100644 --- a/.yarn/sdks/integrations.yml +++ b/.yarn/sdks/integrations.yml @@ -2,5 +2,5 @@ # Manual changes might be lost! integrations: - - vim - vscode + - vim diff --git a/public/app/features/query/components/QueryEditorRow.tsx b/public/app/features/query/components/QueryEditorRow.tsx index 13fc765567a..ea1605dd3f5 100644 --- a/public/app/features/query/components/QueryEditorRow.tsx +++ b/public/app/features/query/components/QueryEditorRow.tsx @@ -490,7 +490,7 @@ export class QueryEditorRow extends PureComponent +
{ + 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( + + ); + + 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) { + Object.assign(props, overrides); + + return { + renderResult: render(), + }; +} diff --git a/public/app/features/query/components/QueryEditorRows.tsx b/public/app/features/query/components/QueryEditorRows.tsx index 2cd7579f6cf..17297eef12a 100644 --- a/public/app/features/query/components/QueryEditorRows.tsx +++ b/public/app/features/query/components/QueryEditorRows.tsx @@ -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 { {(provided) => { return ( -
+
{queries.map((query, index) => { const dataSourceSettings = getDataSourceSettings(query, dsSettings); const onChangeDataSourceSettings = dsSettings.meta.mixed diff --git a/public/app/features/query/components/QueryGroup.test.tsx b/public/app/features/query/components/QueryGroup.test.tsx new file mode 100644 index 00000000000..cc3f2ba70a3 --- /dev/null +++ b/public/app/features/query/components/QueryGroup.test.tsx @@ -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) { + 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(), + }; +} diff --git a/public/app/features/query/components/QueryGroup.tsx b/public/app/features/query/components/QueryGroup.tsx index 42ec327726d..e1f3d08df61 100644 --- a/public/app/features/query/components/QueryGroup.tsx +++ b/public/app/features/query/components/QueryGroup.tsx @@ -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 { 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 { icon="question-circle" title="Open data source help" onClick={this.onOpenHelp} + data-testid="query-tab-help-button" />
@@ -375,7 +377,6 @@ export class QueryGroup extends PureComponent { renderQueries(dsSettings: DataSourceInstanceSettings) { const { onRunQueries } = this.props; const { data, queries } = this.state; - if (isSharedDashboardQuery(dsSettings.name)) { return ( { onClick={this.onAddQueryClick} variant="secondary" aria-label={selectors.components.QueryTab.addQuery} + data-testid="query-tab-add-query" > Query @@ -439,6 +441,7 @@ export class QueryGroup extends PureComponent { onClick={this.onAddExpressionClick} variant="secondary" className={styles.expressionButton} + data-testid="query-tab-add-expression" > Expression