[Azure Monitor]: Preserve logs builder query when switching to KQL mode (#116161)
This commit is contained in:
+247
@@ -0,0 +1,247 @@
|
||||
import { render, screen, waitFor, cleanup } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
|
||||
import { CoreApp, LoadingState, PanelData } from '@grafana/data';
|
||||
import { config, reportInteraction } from '@grafana/runtime';
|
||||
|
||||
import { AzureQueryType, LogsEditorMode } from '../../dataquery.gen';
|
||||
import { selectors } from '../../e2e/selectors';
|
||||
import createMockQuery from '../../mocks/query';
|
||||
import { AzureMonitorQuery } from '../../types/query';
|
||||
import { selectOptionInTest } from '../../utils/testUtils';
|
||||
|
||||
import { QueryHeader } from './QueryHeader';
|
||||
|
||||
jest.mock('@grafana/runtime', () => ({
|
||||
...jest.requireActual('@grafana/runtime'),
|
||||
reportInteraction: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('Azure Monitor QueryHeader', () => {
|
||||
const setAzureLogsCheatSheetModalOpen = jest.fn();
|
||||
const onRunQuery = jest.fn();
|
||||
|
||||
const renderComponent = (query: AzureMonitorQuery, props?: Partial<React.ComponentProps<typeof QueryHeader>>) => {
|
||||
return render(
|
||||
<QueryHeader
|
||||
query={query}
|
||||
onQueryChange={props?.onQueryChange ?? jest.fn()}
|
||||
setAzureLogsCheatSheetModalOpen={setAzureLogsCheatSheetModalOpen}
|
||||
data={props?.data}
|
||||
onRunQuery={onRunQuery}
|
||||
app={props?.app}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
config.featureToggles = {};
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('renders the service selector', async () => {
|
||||
const query = createMockQuery();
|
||||
|
||||
renderComponent(query);
|
||||
|
||||
expect(screen.getByTestId(selectors.components.queryEditor.header.select)).toBeInTheDocument();
|
||||
expect(screen.getByLabelText(/Service/i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('changes query type when a new service is selected', async () => {
|
||||
const query = createMockQuery();
|
||||
const onQueryChange = jest.fn();
|
||||
|
||||
renderComponent(query, { onQueryChange });
|
||||
|
||||
const serviceSelect = await screen.findByLabelText(/Service/i);
|
||||
|
||||
await selectOptionInTest(serviceSelect, 'Logs');
|
||||
|
||||
await waitFor(() => {
|
||||
expect(onQueryChange).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
const lastCall = onQueryChange.mock.calls[onQueryChange.mock.calls.length - 1][0];
|
||||
|
||||
expect(lastCall).toEqual(
|
||||
expect.objectContaining({
|
||||
queryType: AzureQueryType.LogAnalytics,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('initializes logs editor mode to Raw when a raw query exists and builder is enabled', async () => {
|
||||
config.featureToggles.azureMonitorLogsBuilderEditor = true;
|
||||
|
||||
const query: AzureMonitorQuery = {
|
||||
...createMockQuery(),
|
||||
queryType: AzureQueryType.LogAnalytics,
|
||||
azureLogAnalytics: {
|
||||
query: 'SecurityEvent | take 10',
|
||||
},
|
||||
};
|
||||
|
||||
const onQueryChange = jest.fn();
|
||||
|
||||
renderComponent(query, { onQueryChange });
|
||||
|
||||
await waitFor(() =>
|
||||
expect(onQueryChange).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
azureLogAnalytics: expect.objectContaining({
|
||||
mode: LogsEditorMode.Raw,
|
||||
}),
|
||||
})
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('renders the logs editor mode radio buttons when builder is enabled', async () => {
|
||||
config.featureToggles.azureMonitorLogsBuilderEditor = true;
|
||||
|
||||
const query: AzureMonitorQuery = {
|
||||
...createMockQuery(),
|
||||
queryType: AzureQueryType.LogAnalytics,
|
||||
azureLogAnalytics: {
|
||||
mode: LogsEditorMode.Builder,
|
||||
},
|
||||
};
|
||||
|
||||
renderComponent(query);
|
||||
|
||||
expect(screen.getByRole('radiogroup')).toBeInTheDocument();
|
||||
|
||||
expect(screen.getByLabelText('Builder')).toBeInTheDocument();
|
||||
expect(screen.getByLabelText('KQL')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows the kick start button when in Logs + Raw mode', async () => {
|
||||
const query: AzureMonitorQuery = {
|
||||
...createMockQuery(),
|
||||
queryType: AzureQueryType.LogAnalytics,
|
||||
azureLogAnalytics: {
|
||||
mode: LogsEditorMode.Raw,
|
||||
},
|
||||
};
|
||||
|
||||
renderComponent(query);
|
||||
|
||||
expect(screen.getByRole('button', { name: /Kick start your query/i })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('opens the logs cheat sheet modal and reports interaction when kick start button is clicked', async () => {
|
||||
const user = userEvent.setup();
|
||||
|
||||
const query: AzureMonitorQuery = {
|
||||
...createMockQuery(),
|
||||
queryType: AzureQueryType.LogAnalytics,
|
||||
azureLogAnalytics: {
|
||||
mode: LogsEditorMode.Raw,
|
||||
},
|
||||
};
|
||||
|
||||
renderComponent(query);
|
||||
|
||||
await user.click(screen.getByRole('button', { name: /Kick start your query/i }));
|
||||
|
||||
expect(setAzureLogsCheatSheetModalOpen).toHaveBeenCalled();
|
||||
expect(reportInteraction).toHaveBeenCalledWith(
|
||||
'grafana_azure_logs_query_patterns_opened',
|
||||
expect.objectContaining({
|
||||
version: 'v2',
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('shows confirmation modal when switching from Raw to Builder with existing KQL', async () => {
|
||||
const user = userEvent.setup();
|
||||
config.featureToggles.azureMonitorLogsBuilderEditor = true;
|
||||
|
||||
const query: AzureMonitorQuery = {
|
||||
...createMockQuery(),
|
||||
queryType: AzureQueryType.LogAnalytics,
|
||||
azureLogAnalytics: {
|
||||
mode: LogsEditorMode.Raw,
|
||||
query: 'SecurityEvent | take 10',
|
||||
},
|
||||
};
|
||||
|
||||
renderComponent(query);
|
||||
|
||||
await user.click(screen.getByLabelText('Builder'));
|
||||
|
||||
expect(screen.getByText(/Switch editor mode\?/i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('applies mode change when confirming the switch modal', async () => {
|
||||
const user = userEvent.setup();
|
||||
config.featureToggles.azureMonitorLogsBuilderEditor = true;
|
||||
|
||||
const query: AzureMonitorQuery = {
|
||||
...createMockQuery(),
|
||||
queryType: AzureQueryType.LogAnalytics,
|
||||
azureLogAnalytics: {
|
||||
mode: LogsEditorMode.Raw,
|
||||
query: 'SecurityEvent | take 10',
|
||||
},
|
||||
};
|
||||
|
||||
const onQueryChange = jest.fn();
|
||||
|
||||
renderComponent(query, { onQueryChange });
|
||||
|
||||
await user.click(screen.getByLabelText('Builder'));
|
||||
await user.click(screen.getByText(/Switch to Builder/i));
|
||||
|
||||
await waitFor(() =>
|
||||
expect(onQueryChange).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
azureLogAnalytics: expect.objectContaining({
|
||||
mode: LogsEditorMode.Builder,
|
||||
query: undefined,
|
||||
}),
|
||||
})
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('renders the Run query button in Builder mode when not in Explore', async () => {
|
||||
config.featureToggles.azureMonitorLogsBuilderEditor = true;
|
||||
|
||||
const query: AzureMonitorQuery = {
|
||||
...createMockQuery(),
|
||||
queryType: AzureQueryType.LogAnalytics,
|
||||
azureLogAnalytics: {
|
||||
mode: LogsEditorMode.Builder,
|
||||
},
|
||||
};
|
||||
|
||||
renderComponent(query, { app: CoreApp.Dashboard });
|
||||
|
||||
expect(screen.getByTestId(selectors.components.queryEditor.logsQueryEditor.runQuery.button)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('disables the Run query button spinner while loading', async () => {
|
||||
config.featureToggles.azureMonitorLogsBuilderEditor = true;
|
||||
|
||||
const query: AzureMonitorQuery = {
|
||||
...createMockQuery(),
|
||||
queryType: AzureQueryType.LogAnalytics,
|
||||
azureLogAnalytics: {
|
||||
mode: LogsEditorMode.Builder,
|
||||
},
|
||||
};
|
||||
|
||||
renderComponent(query, {
|
||||
app: CoreApp.Dashboard,
|
||||
data: { state: LoadingState.Loading } as PanelData,
|
||||
});
|
||||
|
||||
expect(screen.getByTestId(selectors.components.queryEditor.logsQueryEditor.runQuery.button)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -84,12 +84,9 @@ export const QueryHeader = ({
|
||||
}
|
||||
|
||||
const goingToBuilder = newMode === LogsEditorMode.Builder;
|
||||
const goingToRaw = newMode === LogsEditorMode.Raw;
|
||||
|
||||
const hasRawKql = !!query.azureLogAnalytics?.query;
|
||||
const hasBuilderQuery = !!query.azureLogAnalytics?.builderQuery;
|
||||
|
||||
if ((goingToBuilder && hasRawKql) || (goingToRaw && hasBuilderQuery)) {
|
||||
if (goingToBuilder && hasRawKql) {
|
||||
setPendingModeChange(newMode);
|
||||
setShowModeSwitchWarning(true);
|
||||
} else {
|
||||
@@ -103,7 +100,7 @@ export const QueryHeader = ({
|
||||
azureLogAnalytics: {
|
||||
...query.azureLogAnalytics,
|
||||
mode,
|
||||
query: '',
|
||||
query: mode === LogsEditorMode.Builder ? undefined : query.azureLogAnalytics?.query,
|
||||
builderQuery: mode === LogsEditorMode.Raw ? undefined : query.azureLogAnalytics?.builderQuery,
|
||||
dashboardTime: mode === LogsEditorMode.Builder ? true : undefined,
|
||||
},
|
||||
@@ -123,10 +120,7 @@ export const QueryHeader = ({
|
||||
'components.query-header.body-switching-to-builder',
|
||||
'Switching to Builder will discard your current KQL query and clear the KQL editor. Are you sure?'
|
||||
)
|
||||
: t(
|
||||
'components.query-header.body-switching-to-kql',
|
||||
'Switching to KQL will discard your current builder settings. Are you sure?'
|
||||
)
|
||||
: null
|
||||
}
|
||||
confirmText={t('components.query-header.confirmText-switch-to', 'Switch to {{newMode}}', {
|
||||
newMode: pendingModeChange === LogsEditorMode.Builder ? 'Builder' : 'KQL',
|
||||
|
||||
-1
@@ -204,7 +204,6 @@
|
||||
"query-header": {
|
||||
"aria-label-kick-start": "Azure logs kick start your query button",
|
||||
"body-switching-to-builder": "Switching to Builder will discard your current KQL query and clear the KQL editor. Are you sure?",
|
||||
"body-switching-to-kql": "Switching to KQL will discard your current builder settings. Are you sure?",
|
||||
"button-kick-start-your-query": "Kick start your query",
|
||||
"button-run-query": "Run query",
|
||||
"confirmText-switch-to": "Switch to {{newMode}}",
|
||||
|
||||
Reference in New Issue
Block a user