Files
grafana/public/app/features/dashboard/components/PanelEditor/state/actions.test.ts
Torkel Ödegaard d62ca1283c PanelState: Introduce a new separate redux panel state not keyed by panel.id (#40302)
* Initial pass to move panel state to it's own, and make it by key not panel.id

* Progress

* Not making much progress, having panel.key be mutable is causing a lot of issues

* Think this is starting to work

* Began fixing tests

* Add selector

* Bug fixes and changes to cleanup, and fixing all flicking when switching library panels

* Removed console.log

* fixes after merge

* fixing tests

* fixing tests

* Added new test for changePlugin thunk
2021-10-13 08:53:36 +02:00

176 lines
6.2 KiB
TypeScript

import { thunkTester } from '../../../../../../test/core/thunk/thunkTester';
import { closeEditor, initialState, PanelEditorState } from './reducers';
import { exitPanelEditor, initPanelEditor, skipPanelUpdate } from './actions';
import { cleanUpPanelState, panelModelAndPluginReady } from 'app/features/panel/state/reducers';
import { DashboardModel, PanelModel } from '../../../state';
import { getPanelPlugin } from 'app/features/plugins/__mocks__/pluginMocks';
describe('panelEditor actions', () => {
describe('initPanelEditor', () => {
it('initPanelEditor should create edit panel model as clone', async () => {
const dashboard = new DashboardModel({
panels: [{ id: 12, type: 'graph' }],
});
const sourcePanel = new PanelModel({ id: 12, type: 'graph' });
const dispatchedActions = await thunkTester({
panelEditor: { ...initialState },
plugins: {
panels: {},
},
})
.givenThunk(initPanelEditor)
.whenThunkIsDispatched(sourcePanel, dashboard);
expect(dispatchedActions.length).toBe(2);
expect(dispatchedActions[0].type).toBe(panelModelAndPluginReady.type);
expect(dispatchedActions[1].payload.sourcePanel).toBe(sourcePanel);
expect(dispatchedActions[1].payload.panel).not.toBe(sourcePanel);
expect(dispatchedActions[1].payload.panel.id).toBe(sourcePanel.id);
});
});
describe('panelEditorCleanUp', () => {
it('should update source panel', async () => {
const sourcePanel = new PanelModel({ id: 12, type: 'graph' });
const dashboard = new DashboardModel({
panels: [{ id: 12, type: 'graph' }],
});
const panel = dashboard.initEditPanel(sourcePanel);
panel.updateOptions({ prop: true });
const state: PanelEditorState = {
...initialState(),
getPanel: () => panel,
getSourcePanel: () => sourcePanel,
};
const dispatchedActions = await thunkTester({
panelEditor: state,
dashboard: {
getModel: () => dashboard,
},
})
.givenThunk(exitPanelEditor)
.whenThunkIsDispatched();
expect(dispatchedActions.length).toBe(2);
expect(dispatchedActions[0].type).toBe(cleanUpPanelState.type);
expect(dispatchedActions[1].type).toBe(closeEditor.type);
expect(sourcePanel.getOptions()).toEqual({ prop: true });
expect(sourcePanel.id).toEqual(12);
});
it('should dispatch panelModelAndPluginReady if type changed', async () => {
const sourcePanel = new PanelModel({ id: 12, type: 'graph' });
const dashboard = new DashboardModel({
panels: [{ id: 12, type: 'graph' }],
});
const panel = dashboard.initEditPanel(sourcePanel);
panel.type = 'table';
panel.plugin = getPanelPlugin({ id: 'table' });
panel.updateOptions({ prop: true });
const state: PanelEditorState = {
...initialState(),
getPanel: () => panel,
getSourcePanel: () => sourcePanel,
};
const panelDestroy = (panel.destroy = jest.fn());
const dispatchedActions = await thunkTester({
panelEditor: state,
dashboard: {
getModel: () => dashboard,
},
})
.givenThunk(exitPanelEditor)
.whenThunkIsDispatched();
expect(dispatchedActions.length).toBe(3);
expect(dispatchedActions[0].type).toBe(panelModelAndPluginReady.type);
expect(sourcePanel.plugin).toEqual(panel.plugin);
expect(panelDestroy.mock.calls.length).toEqual(1);
});
it('should discard changes when shouldDiscardChanges is true', async () => {
const sourcePanel = new PanelModel({ id: 12, type: 'graph' });
sourcePanel.plugin = {
customFieldConfigs: {},
} as any;
const dashboard = new DashboardModel({
panels: [{ id: 12, type: 'graph' }],
});
const panel = dashboard.initEditPanel(sourcePanel);
panel.updateOptions({ prop: true });
const state: PanelEditorState = {
...initialState(),
shouldDiscardChanges: true,
getPanel: () => panel,
getSourcePanel: () => sourcePanel,
};
const dispatchedActions = await thunkTester({
panelEditor: state,
dashboard: {
getModel: () => dashboard,
},
})
.givenThunk(exitPanelEditor)
.whenThunkIsDispatched();
expect(dispatchedActions.length).toBe(2);
expect(sourcePanel.getOptions()).toEqual({});
});
});
describe('skipPanelUpdate', () => {
describe('when called with panel with an library uid different from the modified panel', () => {
it('then it should return true', () => {
const meta: any = {};
const modified: any = { libraryPanel: { uid: '123', name: 'Name', meta, version: 1 } };
const panel: any = { libraryPanel: { uid: '456', name: 'Name', meta, version: 1 } };
expect(skipPanelUpdate(modified, panel)).toEqual(true);
});
});
describe('when called with a panel that is the same as the modified panel', () => {
it('then it should return true', () => {
const meta: any = {};
const modified: any = { id: 14, libraryPanel: { uid: '123', name: 'Name', meta, version: 1 } };
const panel: any = { id: 14, libraryPanel: { uid: '123', name: 'Name', meta, version: 1 } };
expect(skipPanelUpdate(modified, panel)).toEqual(true);
});
});
describe('when called with a panel that is repeated', () => {
it('then it should return true', () => {
const meta: any = {};
const modified: any = { libraryPanel: { uid: '123', name: 'Name', meta, version: 1 } };
const panel: any = { repeatPanelId: 14, libraryPanel: { uid: '123', name: 'Name', meta, version: 1 } };
expect(skipPanelUpdate(modified, panel)).toEqual(true);
});
});
describe('when called with a panel that is a duplicate of the modified panel', () => {
it('then it should return false', () => {
const meta: any = {};
const modified: any = { libraryPanel: { uid: '123', name: 'Name', meta, version: 1 } };
const panel: any = { libraryPanel: { uid: '123', name: 'Name', meta, version: 1 } };
expect(skipPanelUpdate(modified, panel)).toEqual(false);
});
});
});
});