123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- import React from 'react';
- import { of } from 'rxjs';
- import { serializeStateToUrlParam } from '@grafana/data';
- import { config } from '@grafana/runtime';
- import { silenceConsoleOutput } from '../../../../test/core/utils/silenceConsoleOutput';
- import { ExploreId } from '../../../types';
- import {
- assertDataSourceFilterVisibility,
- assertLoadMoreQueryHistoryNotVisible,
- assertQueryHistory,
- assertQueryHistoryComment,
- assertQueryHistoryElementsShown,
- assertQueryHistoryExists,
- assertQueryHistoryIsStarred,
- assertQueryHistoryTabIsSelected,
- } from './helper/assert';
- import {
- commentQueryHistory,
- closeQueryHistory,
- deleteQueryHistory,
- inputQuery,
- loadMoreQueryHistory,
- openQueryHistory,
- runQuery,
- selectOnlyActiveDataSource,
- selectStarredTabFirst,
- starQueryHistory,
- switchToQueryHistoryTab,
- } from './helper/interactions';
- import { makeLogsQueryResponse } from './helper/query';
- import {
- localStorageHasAlreadyBeenMigrated,
- setupExplore,
- setupLocalStorageRichHistory,
- tearDown,
- waitForExplore,
- } from './helper/setup';
- const fetchMock = jest.fn();
- const postMock = jest.fn();
- const getMock = jest.fn();
- const reportInteractionMock = jest.fn();
- jest.mock('@grafana/runtime', () => ({
- ...jest.requireActual('@grafana/runtime'),
- getBackendSrv: () => ({ fetch: fetchMock, post: postMock, get: getMock }),
- reportInteraction: (...args: object[]) => {
- reportInteractionMock(...args);
- },
- }));
- jest.mock('app/core/core', () => ({
- contextSrv: {
- hasAccess: () => true,
- isSignedIn: true,
- },
- }));
- jest.mock('app/core/services/PreferencesService', () => ({
- PreferencesService: function () {
- return {
- patch: jest.fn(),
- load: jest.fn().mockResolvedValue({
- queryHistory: {
- homeTab: 'query',
- },
- }),
- };
- },
- }));
- jest.mock('react-virtualized-auto-sizer', () => {
- return {
- __esModule: true,
- default(props: any) {
- return <div>{props.children({ width: 1000 })}</div>;
- },
- };
- });
- describe('Explore: Query History', () => {
- const USER_INPUT = 'my query';
- const RAW_QUERY = `{"expr":"${USER_INPUT}"}`;
- silenceConsoleOutput();
- afterEach(() => {
- config.queryHistoryEnabled = false;
- fetchMock.mockClear();
- postMock.mockClear();
- getMock.mockClear();
- reportInteractionMock.mockClear();
- tearDown();
- });
- it('adds new query history items after the query is run.', async () => {
- // when Explore is opened
- const { datasources, unmount } = setupExplore();
- (datasources.loki.query as jest.Mock).mockReturnValueOnce(makeLogsQueryResponse());
- await waitForExplore();
- // and a user runs a query and opens query history
- await inputQuery(USER_INPUT);
- await runQuery();
- await openQueryHistory();
- // the query that was run is in query history
- await assertQueryHistoryExists(RAW_QUERY);
- // when Explore is opened again
- unmount();
- setupExplore({ clearLocalStorage: false });
- await waitForExplore();
- // previously added query is in query history
- await openQueryHistory();
- await assertQueryHistoryExists(RAW_QUERY);
- expect(reportInteractionMock).toBeCalledWith('grafana_explore_query_history_opened', {
- queryHistoryEnabled: false,
- });
- });
- it('adds recently added query if the query history panel is already open', async () => {
- const urlParams = {
- left: serializeStateToUrlParam({
- datasource: 'loki',
- queries: [{ refId: 'A', expr: 'query #1' }],
- range: { from: 'now-1h', to: 'now' },
- }),
- };
- const { datasources } = setupExplore({ urlParams });
- (datasources.loki.query as jest.Mock).mockReturnValueOnce(makeLogsQueryResponse());
- await waitForExplore();
- await openQueryHistory();
- await inputQuery('query #2');
- await runQuery();
- await assertQueryHistory(['{"expr":"query #2"}', '{"expr":"query #1"}']);
- });
- it('updates the state in both Explore panes', async () => {
- const urlParams = {
- left: serializeStateToUrlParam({
- datasource: 'loki',
- queries: [{ refId: 'A', expr: 'query #1' }],
- range: { from: 'now-1h', to: 'now' },
- }),
- right: serializeStateToUrlParam({
- datasource: 'loki',
- queries: [{ refId: 'A', expr: 'query #2' }],
- range: { from: 'now-1h', to: 'now' },
- }),
- };
- const { datasources } = setupExplore({ urlParams });
- (datasources.loki.query as jest.Mock).mockReturnValue(makeLogsQueryResponse());
- await waitForExplore();
- await waitForExplore(ExploreId.right);
- // queries in history
- await openQueryHistory(ExploreId.left);
- await assertQueryHistory(['{"expr":"query #2"}', '{"expr":"query #1"}'], ExploreId.left);
- await openQueryHistory(ExploreId.right);
- await assertQueryHistory(['{"expr":"query #2"}', '{"expr":"query #1"}'], ExploreId.right);
- // star one one query
- starQueryHistory(1, ExploreId.left);
- await assertQueryHistoryIsStarred([false, true], ExploreId.left);
- await assertQueryHistoryIsStarred([false, true], ExploreId.right);
- expect(reportInteractionMock).toBeCalledWith('grafana_explore_query_history_starred', {
- queryHistoryEnabled: false,
- newValue: true,
- });
- deleteQueryHistory(0, ExploreId.left);
- await assertQueryHistory(['{"expr":"query #1"}'], ExploreId.left);
- await assertQueryHistory(['{"expr":"query #1"}'], ExploreId.right);
- expect(reportInteractionMock).toBeCalledWith('grafana_explore_query_history_deleted', {
- queryHistoryEnabled: false,
- });
- });
- it('add comments to query history', async () => {
- const urlParams = {
- left: serializeStateToUrlParam({
- datasource: 'loki',
- queries: [{ refId: 'A', expr: 'query #1' }],
- range: { from: 'now-1h', to: 'now' },
- }),
- };
- const { datasources } = setupExplore({ urlParams });
- (datasources.loki.query as jest.Mock).mockReturnValueOnce(makeLogsQueryResponse());
- await waitForExplore();
- await openQueryHistory();
- await assertQueryHistory(['{"expr":"query #1"}'], ExploreId.left);
- await commentQueryHistory(0, 'test comment');
- await assertQueryHistoryComment(['test comment'], ExploreId.left);
- });
- it('updates query history settings', async () => {
- // open settings page
- setupExplore();
- await waitForExplore();
- await openQueryHistory();
- // assert default values
- assertQueryHistoryTabIsSelected('Query history');
- assertDataSourceFilterVisibility(true);
- await switchToQueryHistoryTab('Settings');
- // change settings
- await selectStarredTabFirst();
- await selectOnlyActiveDataSource();
- await closeQueryHistory();
- await openQueryHistory();
- // assert new settings
- assertQueryHistoryTabIsSelected('Starred');
- assertDataSourceFilterVisibility(false);
- });
- describe('local storage migration', () => {
- it('does not migrate if query history is not enabled', async () => {
- config.queryHistoryEnabled = false;
- const { datasources } = setupExplore();
- setupLocalStorageRichHistory('loki');
- (datasources.loki.query as jest.Mock).mockReturnValueOnce(makeLogsQueryResponse());
- getMock.mockReturnValue({ result: { queryHistory: [] } });
- await waitForExplore();
- await openQueryHistory();
- expect(postMock).not.toBeCalledWith('/api/query-history/migrate', { queries: [] });
- expect(reportInteractionMock).toBeCalledWith('grafana_explore_query_history_opened', {
- queryHistoryEnabled: false,
- });
- });
- it('migrates query history from local storage', async () => {
- config.queryHistoryEnabled = true;
- const { datasources } = setupExplore();
- setupLocalStorageRichHistory('loki');
- (datasources.loki.query as jest.Mock).mockReturnValueOnce(makeLogsQueryResponse());
- fetchMock.mockReturnValue(of({ data: { result: { queryHistory: [] } } }));
- await waitForExplore();
- await openQueryHistory();
- expect(fetchMock).toBeCalledWith(
- expect.objectContaining({
- url: expect.stringMatching('/api/query-history/migrate'),
- data: { queries: [expect.objectContaining({ datasourceUid: 'loki' })] },
- })
- );
- fetchMock.mockReset();
- fetchMock.mockReturnValue(of({ data: { result: { queryHistory: [] } } }));
- await closeQueryHistory();
- await openQueryHistory();
- expect(fetchMock).not.toBeCalledWith(
- expect.objectContaining({
- url: expect.stringMatching('/api/query-history/migrate'),
- })
- );
- expect(reportInteractionMock).toBeCalledWith('grafana_explore_query_history_opened', {
- queryHistoryEnabled: true,
- });
- });
- });
- it('pagination', async () => {
- config.queryHistoryEnabled = true;
- localStorageHasAlreadyBeenMigrated();
- const { datasources } = setupExplore();
- (datasources.loki.query as jest.Mock).mockReturnValueOnce(makeLogsQueryResponse());
- fetchMock.mockReturnValue(
- of({
- data: { result: { queryHistory: [{ datasourceUid: 'loki', queries: [{ expr: 'query' }] }], totalCount: 2 } },
- })
- );
- await waitForExplore();
- await openQueryHistory();
- await assertQueryHistory(['{"expr":"query"}']);
- assertQueryHistoryElementsShown(1, 2);
- await loadMoreQueryHistory();
- await assertQueryHistory(['{"expr":"query"}', '{"expr":"query"}']);
- assertLoadMoreQueryHistoryNotVisible();
- });
- });
|