| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578 |
- import {
- itemReducer,
- makeExploreItemState,
- exploreReducer,
- makeInitialUpdateState,
- initialExploreState,
- } from './reducers';
- import {
- ExploreId,
- ExploreItemState,
- ExploreUrlState,
- ExploreState,
- QueryTransaction,
- RangeScanner,
- } from 'app/types/explore';
- import { reducerTester } from 'test/core/redux/reducerTester';
- import {
- scanStartAction,
- scanStopAction,
- testDataSourcePendingAction,
- testDataSourceSuccessAction,
- testDataSourceFailureAction,
- updateDatasourceInstanceAction,
- splitOpenAction,
- splitCloseAction,
- } from './actionTypes';
- import { Reducer } from 'redux';
- import { ActionOf } from 'app/core/redux/actionCreatorFactory';
- import { updateLocation } from 'app/core/actions/location';
- import { LogsDedupStrategy, LogsModel } from 'app/core/logs_model';
- import { serializeStateToUrlParam } from 'app/core/utils/explore';
- import TableModel from 'app/core/table_model';
- import { DataSourceApi, DataQuery } from '@grafana/ui';
- describe('Explore item reducer', () => {
- describe('scanning', () => {
- test('should start scanning', () => {
- const scanner = jest.fn();
- const initalState = {
- ...makeExploreItemState(),
- scanning: false,
- scanner: undefined as RangeScanner,
- };
- reducerTester()
- .givenReducer(itemReducer as Reducer<ExploreItemState, ActionOf<any>>, initalState)
- .whenActionIsDispatched(scanStartAction({ exploreId: ExploreId.left, scanner }))
- .thenStateShouldEqual({
- ...makeExploreItemState(),
- scanning: true,
- scanner,
- });
- });
- test('should stop scanning', () => {
- const scanner = jest.fn();
- const initalState = {
- ...makeExploreItemState(),
- scanning: true,
- scanner,
- scanRange: {},
- };
- reducerTester()
- .givenReducer(itemReducer as Reducer<ExploreItemState, ActionOf<any>>, initalState)
- .whenActionIsDispatched(scanStopAction({ exploreId: ExploreId.left }))
- .thenStateShouldEqual({
- ...makeExploreItemState(),
- scanning: false,
- scanner: undefined,
- scanRange: undefined,
- });
- });
- });
- describe('testing datasource', () => {
- describe('when testDataSourcePendingAction is dispatched', () => {
- it('then it should set datasourceError', () => {
- reducerTester()
- .givenReducer(itemReducer, { datasourceError: {} })
- .whenActionIsDispatched(testDataSourcePendingAction({ exploreId: ExploreId.left }))
- .thenStateShouldEqual({ datasourceError: null });
- });
- });
- describe('when testDataSourceSuccessAction is dispatched', () => {
- it('then it should set datasourceError', () => {
- reducerTester()
- .givenReducer(itemReducer, { datasourceError: {} })
- .whenActionIsDispatched(testDataSourceSuccessAction({ exploreId: ExploreId.left }))
- .thenStateShouldEqual({ datasourceError: null });
- });
- });
- describe('when testDataSourceFailureAction is dispatched', () => {
- it('then it should set correct state', () => {
- const error = 'some error';
- const queryTransactions: QueryTransaction[] = [];
- const initalState: Partial<ExploreItemState> = {
- datasourceError: null,
- queryTransactions: [{} as QueryTransaction],
- graphResult: [],
- tableResult: {} as TableModel,
- logsResult: {} as LogsModel,
- update: {
- datasource: true,
- queries: true,
- range: true,
- ui: true,
- },
- };
- const expectedState = {
- datasourceError: error,
- queryTransactions,
- graphResult: undefined as any[],
- tableResult: undefined as TableModel,
- logsResult: undefined as LogsModel,
- update: makeInitialUpdateState(),
- };
- reducerTester()
- .givenReducer(itemReducer, initalState)
- .whenActionIsDispatched(testDataSourceFailureAction({ exploreId: ExploreId.left, error }))
- .thenStateShouldEqual(expectedState);
- });
- });
- });
- describe('changing datasource', () => {
- describe('when updateDatasourceInstanceAction is dispatched', () => {
- describe('and datasourceInstance supports graph, logs, table and has a startpage', () => {
- it('then it should set correct state', () => {
- const StartPage = {};
- const datasourceInstance = {
- meta: {
- metrics: {},
- logs: {},
- tables: {},
- },
- components: {
- ExploreStartPage: StartPage,
- },
- } as DataSourceApi;
- const queries: DataQuery[] = [];
- const queryKeys: string[] = [];
- const initalState: Partial<ExploreItemState> = {
- datasourceInstance: null,
- supportsGraph: false,
- supportsLogs: false,
- supportsTable: false,
- StartPage: null,
- showingStartPage: false,
- queries,
- queryKeys,
- };
- const expectedState = {
- datasourceInstance,
- supportsGraph: true,
- supportsLogs: true,
- supportsTable: true,
- StartPage,
- showingStartPage: true,
- queries,
- queryKeys,
- };
- reducerTester()
- .givenReducer(itemReducer, initalState)
- .whenActionIsDispatched(updateDatasourceInstanceAction({ exploreId: ExploreId.left, datasourceInstance }))
- .thenStateShouldEqual(expectedState);
- });
- });
- });
- });
- });
- export const setup = (urlStateOverrides?: any) => {
- const update = makeInitialUpdateState();
- const urlStateDefaults: ExploreUrlState = {
- datasource: 'some-datasource',
- queries: [],
- range: {
- from: '',
- to: '',
- },
- ui: {
- dedupStrategy: LogsDedupStrategy.none,
- showingGraph: false,
- showingTable: false,
- showingLogs: false,
- },
- };
- const urlState: ExploreUrlState = { ...urlStateDefaults, ...urlStateOverrides };
- const serializedUrlState = serializeStateToUrlParam(urlState);
- const initalState = { split: false, left: { urlState, update }, right: { urlState, update } };
- return {
- initalState,
- serializedUrlState,
- };
- };
- describe('Explore reducer', () => {
- describe('split view', () => {
- it("should make right pane a duplicate of the given item's state on split open", () => {
- const leftItemMock = {
- containerWidth: 100,
- } as ExploreItemState;
- const initalState = {
- split: null,
- left: leftItemMock as ExploreItemState,
- right: makeExploreItemState(),
- } as ExploreState;
- reducerTester()
- .givenReducer(exploreReducer as Reducer<ExploreState, ActionOf<any>>, initalState)
- .whenActionIsDispatched(splitOpenAction({ itemState: leftItemMock }))
- .thenStateShouldEqual({
- split: true,
- left: leftItemMock,
- right: leftItemMock,
- });
- });
- describe('split close', () => {
- it('should keep right pane as left when left is closed', () => {
- const leftItemMock = {
- containerWidth: 100,
- } as ExploreItemState;
- const rightItemMock = {
- containerWidth: 200,
- } as ExploreItemState;
- const initalState = {
- split: null,
- left: leftItemMock,
- right: rightItemMock,
- } as ExploreState;
- // closing left item
- reducerTester()
- .givenReducer(exploreReducer as Reducer<ExploreState, ActionOf<any>>, initalState)
- .whenActionIsDispatched(splitCloseAction({ itemId: ExploreId.left }))
- .thenStateShouldEqual({
- split: false,
- left: rightItemMock,
- right: initialExploreState.right,
- });
- });
- it('should reset right pane when it is closed ', () => {
- const leftItemMock = {
- containerWidth: 100,
- } as ExploreItemState;
- const rightItemMock = {
- containerWidth: 200,
- } as ExploreItemState;
- const initalState = {
- split: null,
- left: leftItemMock,
- right: rightItemMock,
- } as ExploreState;
- // closing left item
- reducerTester()
- .givenReducer(exploreReducer as Reducer<ExploreState, ActionOf<any>>, initalState)
- .whenActionIsDispatched(splitCloseAction({ itemId: ExploreId.right }))
- .thenStateShouldEqual({
- split: false,
- left: leftItemMock,
- right: initialExploreState.right,
- });
- });
- });
- });
- describe('when updateLocation is dispatched', () => {
- describe('and payload does not contain a query', () => {
- it('then it should just return state', () => {
- reducerTester()
- .givenReducer(exploreReducer, {})
- .whenActionIsDispatched(updateLocation({ query: null }))
- .thenStateShouldEqual({});
- });
- });
- describe('and payload contains a query', () => {
- describe("but does not contain 'left'", () => {
- it('then it should just return state', () => {
- reducerTester()
- .givenReducer(exploreReducer, {})
- .whenActionIsDispatched(updateLocation({ query: {} }))
- .thenStateShouldEqual({});
- });
- });
- describe("and query contains a 'right'", () => {
- it('then it should add split in state', () => {
- const { initalState, serializedUrlState } = setup();
- const expectedState = { ...initalState, split: true };
- reducerTester()
- .givenReducer(exploreReducer, initalState)
- .whenActionIsDispatched(
- updateLocation({
- query: {
- left: serializedUrlState,
- right: serializedUrlState,
- },
- })
- )
- .thenStateShouldEqual(expectedState);
- });
- });
- describe("and query contains a 'left'", () => {
- describe('but urlState is not set in state', () => {
- it('then it should just add urlState and update in state', () => {
- const { initalState, serializedUrlState } = setup();
- const urlState: ExploreUrlState = null;
- const stateWithoutUrlState = { ...initalState, left: { urlState } };
- const expectedState = { ...initalState };
- reducerTester()
- .givenReducer(exploreReducer, stateWithoutUrlState)
- .whenActionIsDispatched(
- updateLocation({
- query: {
- left: serializedUrlState,
- },
- path: '/explore',
- })
- )
- .thenStateShouldEqual(expectedState);
- });
- });
- describe("but '/explore' is missing in path", () => {
- it('then it should just add urlState and update in state', () => {
- const { initalState, serializedUrlState } = setup();
- const expectedState = { ...initalState };
- reducerTester()
- .givenReducer(exploreReducer, initalState)
- .whenActionIsDispatched(
- updateLocation({
- query: {
- left: serializedUrlState,
- },
- path: '/dashboard',
- })
- )
- .thenStateShouldEqual(expectedState);
- });
- });
- describe("and '/explore' is in path", () => {
- describe('and datasource differs', () => {
- it('then it should return update datasource', () => {
- const { initalState, serializedUrlState } = setup();
- const expectedState = {
- ...initalState,
- left: {
- ...initalState.left,
- update: {
- ...initalState.left.update,
- datasource: true,
- },
- },
- };
- const stateWithDifferentDataSource = {
- ...initalState,
- left: {
- ...initalState.left,
- urlState: {
- ...initalState.left.urlState,
- datasource: 'different datasource',
- },
- },
- };
- reducerTester()
- .givenReducer(exploreReducer, stateWithDifferentDataSource)
- .whenActionIsDispatched(
- updateLocation({
- query: {
- left: serializedUrlState,
- },
- path: '/explore',
- })
- )
- .thenStateShouldEqual(expectedState);
- });
- });
- describe('and range differs', () => {
- it('then it should return update range', () => {
- const { initalState, serializedUrlState } = setup();
- const expectedState = {
- ...initalState,
- left: {
- ...initalState.left,
- update: {
- ...initalState.left.update,
- range: true,
- },
- },
- };
- const stateWithDifferentDataSource = {
- ...initalState,
- left: {
- ...initalState.left,
- urlState: {
- ...initalState.left.urlState,
- range: {
- from: 'now',
- to: 'now-6h',
- },
- },
- },
- };
- reducerTester()
- .givenReducer(exploreReducer, stateWithDifferentDataSource)
- .whenActionIsDispatched(
- updateLocation({
- query: {
- left: serializedUrlState,
- },
- path: '/explore',
- })
- )
- .thenStateShouldEqual(expectedState);
- });
- });
- describe('and queries differs', () => {
- it('then it should return update queries', () => {
- const { initalState, serializedUrlState } = setup();
- const expectedState = {
- ...initalState,
- left: {
- ...initalState.left,
- update: {
- ...initalState.left.update,
- queries: true,
- },
- },
- };
- const stateWithDifferentDataSource = {
- ...initalState,
- left: {
- ...initalState.left,
- urlState: {
- ...initalState.left.urlState,
- queries: [{ expr: '{__filename__="some.log"}' }],
- },
- },
- };
- reducerTester()
- .givenReducer(exploreReducer, stateWithDifferentDataSource)
- .whenActionIsDispatched(
- updateLocation({
- query: {
- left: serializedUrlState,
- },
- path: '/explore',
- })
- )
- .thenStateShouldEqual(expectedState);
- });
- });
- describe('and ui differs', () => {
- it('then it should return update ui', () => {
- const { initalState, serializedUrlState } = setup();
- const expectedState = {
- ...initalState,
- left: {
- ...initalState.left,
- update: {
- ...initalState.left.update,
- ui: true,
- },
- },
- };
- const stateWithDifferentDataSource = {
- ...initalState,
- left: {
- ...initalState.left,
- urlState: {
- ...initalState.left.urlState,
- ui: {
- ...initalState.left.urlState.ui,
- showingGraph: true,
- },
- },
- },
- };
- reducerTester()
- .givenReducer(exploreReducer, stateWithDifferentDataSource)
- .whenActionIsDispatched(
- updateLocation({
- query: {
- left: serializedUrlState,
- },
- path: '/explore',
- })
- )
- .thenStateShouldEqual(expectedState);
- });
- });
- describe('and refreshInterval differs', () => {
- it('then it should return update refreshInterval', () => {
- const { initalState, serializedUrlState } = setup();
- const expectedState = {
- ...initalState,
- left: {
- ...initalState.left,
- update: {
- ...initalState.left.update,
- refreshInterval: true,
- },
- },
- };
- const stateWithDifferentDataSource = {
- ...initalState,
- left: {
- ...initalState.left,
- urlState: {
- ...initalState.left.urlState,
- refreshInterval: '5s',
- },
- },
- };
- reducerTester()
- .givenReducer(exploreReducer, stateWithDifferentDataSource)
- .whenActionIsDispatched(
- updateLocation({
- query: {
- left: serializedUrlState,
- },
- path: '/explore',
- })
- )
- .thenStateShouldEqual(expectedState);
- });
- });
- describe('and nothing differs', () => {
- fit('then it should return update ui', () => {
- const { initalState, serializedUrlState } = setup();
- const expectedState = { ...initalState };
- reducerTester()
- .givenReducer(exploreReducer, initalState)
- .whenActionIsDispatched(
- updateLocation({
- query: {
- left: serializedUrlState,
- },
- path: '/explore',
- })
- )
- .thenStateShouldEqual(expectedState);
- });
- });
- });
- });
- });
- });
- });
|