mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Variables: Refreshes all panels even if panel is full screen (#34097)
* Variables: Refreshes all panels even if panel is full screen * Chore: updates after PR comments
This commit is contained in:
parent
062e1d5ab8
commit
57d898cd5a
@ -37,6 +37,7 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1`
|
|||||||
"getVariablesFromState": [Function],
|
"getVariablesFromState": [Function],
|
||||||
"gnetId": null,
|
"gnetId": null,
|
||||||
"graphTooltip": 0,
|
"graphTooltip": 0,
|
||||||
|
"hasChangesThatAffectsAllPanels": false,
|
||||||
"id": null,
|
"id": null,
|
||||||
"links": Array [],
|
"links": Array [],
|
||||||
"meta": Object {
|
"meta": Object {
|
||||||
@ -175,6 +176,7 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1`
|
|||||||
"getVariablesFromState": [Function],
|
"getVariablesFromState": [Function],
|
||||||
"gnetId": null,
|
"gnetId": null,
|
||||||
"graphTooltip": 0,
|
"graphTooltip": 0,
|
||||||
|
"hasChangesThatAffectsAllPanels": false,
|
||||||
"id": null,
|
"id": null,
|
||||||
"links": Array [],
|
"links": Array [],
|
||||||
"meta": Object {
|
"meta": Object {
|
||||||
@ -283,6 +285,7 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1`
|
|||||||
"getVariablesFromState": [Function],
|
"getVariablesFromState": [Function],
|
||||||
"gnetId": null,
|
"gnetId": null,
|
||||||
"graphTooltip": 0,
|
"graphTooltip": 0,
|
||||||
|
"hasChangesThatAffectsAllPanels": false,
|
||||||
"id": null,
|
"id": null,
|
||||||
"links": Array [],
|
"links": Array [],
|
||||||
"meta": Object {
|
"meta": Object {
|
||||||
@ -413,6 +416,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti
|
|||||||
"getVariablesFromState": [Function],
|
"getVariablesFromState": [Function],
|
||||||
"gnetId": null,
|
"gnetId": null,
|
||||||
"graphTooltip": 0,
|
"graphTooltip": 0,
|
||||||
|
"hasChangesThatAffectsAllPanels": false,
|
||||||
"id": null,
|
"id": null,
|
||||||
"links": Array [],
|
"links": Array [],
|
||||||
"meta": Object {
|
"meta": Object {
|
||||||
@ -551,6 +555,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti
|
|||||||
"getVariablesFromState": [Function],
|
"getVariablesFromState": [Function],
|
||||||
"gnetId": null,
|
"gnetId": null,
|
||||||
"graphTooltip": 0,
|
"graphTooltip": 0,
|
||||||
|
"hasChangesThatAffectsAllPanels": false,
|
||||||
"id": null,
|
"id": null,
|
||||||
"links": Array [],
|
"links": Array [],
|
||||||
"meta": Object {
|
"meta": Object {
|
||||||
@ -659,6 +664,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti
|
|||||||
"getVariablesFromState": [Function],
|
"getVariablesFromState": [Function],
|
||||||
"gnetId": null,
|
"gnetId": null,
|
||||||
"graphTooltip": 0,
|
"graphTooltip": 0,
|
||||||
|
"hasChangesThatAffectsAllPanels": false,
|
||||||
"id": null,
|
"id": null,
|
||||||
"links": Array [],
|
"links": Array [],
|
||||||
"meta": Object {
|
"meta": Object {
|
||||||
@ -771,6 +777,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti
|
|||||||
"getVariablesFromState": [Function],
|
"getVariablesFromState": [Function],
|
||||||
"gnetId": null,
|
"gnetId": null,
|
||||||
"graphTooltip": 0,
|
"graphTooltip": 0,
|
||||||
|
"hasChangesThatAffectsAllPanels": false,
|
||||||
"id": null,
|
"id": null,
|
||||||
"links": Array [],
|
"links": Array [],
|
||||||
"meta": Object {
|
"meta": Object {
|
||||||
|
@ -84,6 +84,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
|||||||
"getVariablesFromState": [Function],
|
"getVariablesFromState": [Function],
|
||||||
"gnetId": null,
|
"gnetId": null,
|
||||||
"graphTooltip": 0,
|
"graphTooltip": 0,
|
||||||
|
"hasChangesThatAffectsAllPanels": false,
|
||||||
"id": null,
|
"id": null,
|
||||||
"links": Array [],
|
"links": Array [],
|
||||||
"meta": Object {
|
"meta": Object {
|
||||||
@ -355,6 +356,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
|||||||
"getVariablesFromState": [Function],
|
"getVariablesFromState": [Function],
|
||||||
"gnetId": null,
|
"gnetId": null,
|
||||||
"graphTooltip": 0,
|
"graphTooltip": 0,
|
||||||
|
"hasChangesThatAffectsAllPanels": false,
|
||||||
"id": null,
|
"id": null,
|
||||||
"links": Array [],
|
"links": Array [],
|
||||||
"meta": Object {
|
"meta": Object {
|
||||||
@ -626,6 +628,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
|||||||
"getVariablesFromState": [Function],
|
"getVariablesFromState": [Function],
|
||||||
"gnetId": null,
|
"gnetId": null,
|
||||||
"graphTooltip": 0,
|
"graphTooltip": 0,
|
||||||
|
"hasChangesThatAffectsAllPanels": false,
|
||||||
"id": null,
|
"id": null,
|
||||||
"links": Array [],
|
"links": Array [],
|
||||||
"meta": Object {
|
"meta": Object {
|
||||||
@ -897,6 +900,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = `
|
|||||||
"getVariablesFromState": [Function],
|
"getVariablesFromState": [Function],
|
||||||
"gnetId": null,
|
"gnetId": null,
|
||||||
"graphTooltip": 0,
|
"graphTooltip": 0,
|
||||||
|
"hasChangesThatAffectsAllPanels": false,
|
||||||
"id": null,
|
"id": null,
|
||||||
"links": Array [],
|
"links": Array [],
|
||||||
"meta": Object {
|
"meta": Object {
|
||||||
|
@ -6,6 +6,7 @@ import { variableAdapters } from '../../variables/adapters';
|
|||||||
import { createAdHocVariableAdapter } from '../../variables/adhoc/adapter';
|
import { createAdHocVariableAdapter } from '../../variables/adhoc/adapter';
|
||||||
import { createQueryVariableAdapter } from '../../variables/query/adapter';
|
import { createQueryVariableAdapter } from '../../variables/query/adapter';
|
||||||
import { createCustomVariableAdapter } from '../../variables/custom/adapter';
|
import { createCustomVariableAdapter } from '../../variables/custom/adapter';
|
||||||
|
import { expect } from '../../../../test/lib/common';
|
||||||
|
|
||||||
jest.mock('app/core/services/context_srv', () => ({}));
|
jest.mock('app/core/services/context_srv', () => ({}));
|
||||||
variableAdapters.setInit(() => [
|
variableAdapters.setInit(() => [
|
||||||
@ -764,3 +765,123 @@ describe('DashboardModel', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('exitViewPanel', () => {
|
||||||
|
function getTestContext() {
|
||||||
|
const panel: any = { setIsViewing: jest.fn() };
|
||||||
|
const dashboard = new DashboardModel({});
|
||||||
|
dashboard.startRefresh = jest.fn();
|
||||||
|
dashboard.panelInView = panel;
|
||||||
|
|
||||||
|
return { dashboard, panel };
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('when called', () => {
|
||||||
|
it('then panelInView is set to undefined', () => {
|
||||||
|
const { dashboard, panel } = getTestContext();
|
||||||
|
|
||||||
|
dashboard.exitViewPanel(panel);
|
||||||
|
|
||||||
|
expect(dashboard.panelInView).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('then setIsViewing is called on panel', () => {
|
||||||
|
const { dashboard, panel } = getTestContext();
|
||||||
|
|
||||||
|
dashboard.exitViewPanel(panel);
|
||||||
|
|
||||||
|
expect(panel.setIsViewing).toHaveBeenCalledWith(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('then startRefresh is not called', () => {
|
||||||
|
const { dashboard, panel } = getTestContext();
|
||||||
|
|
||||||
|
dashboard.exitViewPanel(panel);
|
||||||
|
|
||||||
|
expect(dashboard.startRefresh).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('and there is a change that affects all panels', () => {
|
||||||
|
it('then startRefresh is not called', () => {
|
||||||
|
const { dashboard, panel } = getTestContext();
|
||||||
|
dashboard.setChangeAffectsAllPanels();
|
||||||
|
|
||||||
|
dashboard.exitViewPanel(panel);
|
||||||
|
|
||||||
|
expect(dashboard.startRefresh).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('exitPanelEditor', () => {
|
||||||
|
function getTestContext() {
|
||||||
|
const panel: any = { destroy: jest.fn() };
|
||||||
|
const dashboard = new DashboardModel({});
|
||||||
|
dashboard.startRefresh = jest.fn();
|
||||||
|
dashboard.panelInEdit = panel;
|
||||||
|
|
||||||
|
return { dashboard, panel };
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('when called', () => {
|
||||||
|
it('then panelInEdit is set to undefined', () => {
|
||||||
|
const { dashboard } = getTestContext();
|
||||||
|
|
||||||
|
dashboard.exitPanelEditor();
|
||||||
|
|
||||||
|
expect(dashboard.panelInEdit).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('then destroy is called on panel', () => {
|
||||||
|
const { dashboard, panel } = getTestContext();
|
||||||
|
|
||||||
|
dashboard.exitPanelEditor();
|
||||||
|
|
||||||
|
expect(panel.destroy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('then startRefresh is not called', () => {
|
||||||
|
const { dashboard } = getTestContext();
|
||||||
|
|
||||||
|
dashboard.exitPanelEditor();
|
||||||
|
|
||||||
|
expect(dashboard.startRefresh).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('and there is a change that affects all panels', () => {
|
||||||
|
it('then startRefresh is not called', () => {
|
||||||
|
const { dashboard } = getTestContext();
|
||||||
|
dashboard.setChangeAffectsAllPanels();
|
||||||
|
|
||||||
|
dashboard.exitPanelEditor();
|
||||||
|
|
||||||
|
expect(dashboard.startRefresh).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('setChangeAffectsAllPanels', () => {
|
||||||
|
it.each`
|
||||||
|
panelInEdit | panelInView | expected
|
||||||
|
${null} | ${null} | ${false}
|
||||||
|
${undefined} | ${undefined} | ${false}
|
||||||
|
${null} | ${{}} | ${true}
|
||||||
|
${undefined} | ${{}} | ${true}
|
||||||
|
${{}} | ${null} | ${true}
|
||||||
|
${{}} | ${undefined} | ${true}
|
||||||
|
${{}} | ${{}} | ${true}
|
||||||
|
`(
|
||||||
|
'when called and panelInEdit:{$panelInEdit} and panelInView:{$panelInView}',
|
||||||
|
({ panelInEdit, panelInView, expected }) => {
|
||||||
|
const dashboard = new DashboardModel({});
|
||||||
|
dashboard.panelInEdit = panelInEdit;
|
||||||
|
dashboard.panelInView = panelInView;
|
||||||
|
|
||||||
|
dashboard.setChangeAffectsAllPanels();
|
||||||
|
|
||||||
|
expect(dashboard['hasChangesThatAffectsAllPanels']).toEqual(expected);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
@ -92,6 +92,7 @@ export class DashboardModel {
|
|||||||
panels: PanelModel[];
|
panels: PanelModel[];
|
||||||
panelInEdit?: PanelModel;
|
panelInEdit?: PanelModel;
|
||||||
panelInView?: PanelModel;
|
panelInView?: PanelModel;
|
||||||
|
private hasChangesThatAffectsAllPanels: boolean;
|
||||||
|
|
||||||
// ------------------
|
// ------------------
|
||||||
// not persisted
|
// not persisted
|
||||||
@ -114,6 +115,7 @@ export class DashboardModel {
|
|||||||
panelInView: true,
|
panelInView: true,
|
||||||
getVariablesFromState: true,
|
getVariablesFromState: true,
|
||||||
formatDate: true,
|
formatDate: true,
|
||||||
|
hasChangesThatAffectsAllPanels: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(data: any, meta?: DashboardMeta, private getVariablesFromState: GetVariables = getVariables) {
|
constructor(data: any, meta?: DashboardMeta, private getVariablesFromState: GetVariables = getVariables) {
|
||||||
@ -154,6 +156,7 @@ export class DashboardModel {
|
|||||||
|
|
||||||
this.addBuiltInAnnotationQuery();
|
this.addBuiltInAnnotationQuery();
|
||||||
this.sortPanelsByGridPos();
|
this.sortPanelsByGridPos();
|
||||||
|
this.hasChangesThatAffectsAllPanels = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
addBuiltInAnnotationQuery() {
|
addBuiltInAnnotationQuery() {
|
||||||
@ -365,11 +368,28 @@ export class DashboardModel {
|
|||||||
exitViewPanel(panel: PanelModel) {
|
exitViewPanel(panel: PanelModel) {
|
||||||
this.panelInView = undefined;
|
this.panelInView = undefined;
|
||||||
panel.setIsViewing(false);
|
panel.setIsViewing(false);
|
||||||
|
this.refreshIfChangeAffectsAllPanels();
|
||||||
}
|
}
|
||||||
|
|
||||||
exitPanelEditor() {
|
exitPanelEditor() {
|
||||||
this.panelInEdit!.destroy();
|
this.panelInEdit!.destroy();
|
||||||
this.panelInEdit = undefined;
|
this.panelInEdit = undefined;
|
||||||
|
this.refreshIfChangeAffectsAllPanels();
|
||||||
|
}
|
||||||
|
|
||||||
|
setChangeAffectsAllPanels() {
|
||||||
|
if (this.panelInEdit || this.panelInView) {
|
||||||
|
this.hasChangesThatAffectsAllPanels = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private refreshIfChangeAffectsAllPanels() {
|
||||||
|
if (!this.hasChangesThatAffectsAllPanels) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hasChangesThatAffectsAllPanels = false;
|
||||||
|
this.startRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ensureListExist(data: any) {
|
private ensureListExist(data: any) {
|
||||||
|
@ -111,7 +111,7 @@ export const initDashboardTemplating = (list: VariableModel[]): ThunkResult<void
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const addSystemTemplateVariables = (dashboard: DashboardModel): ThunkResult<void> => {
|
export const addSystemTemplateVariables = (dashboard: DashboardModel): ThunkResult<void> => {
|
||||||
return (dispatch, getState) => {
|
return (dispatch) => {
|
||||||
const dashboardModel: DashboardVariableModel = {
|
const dashboardModel: DashboardVariableModel = {
|
||||||
...initialVariableModelState,
|
...initialVariableModelState,
|
||||||
id: '__dashboard',
|
id: '__dashboard',
|
||||||
@ -493,6 +493,7 @@ export const variableUpdated = (
|
|||||||
return Promise.all(promises).then(() => {
|
return Promise.all(promises).then(() => {
|
||||||
if (emitChangeEvents) {
|
if (emitChangeEvents) {
|
||||||
const dashboard = getState().dashboard.getModel();
|
const dashboard = getState().dashboard.getModel();
|
||||||
|
dashboard?.setChangeAffectsAllPanels();
|
||||||
dashboard?.processRepeats();
|
dashboard?.processRepeats();
|
||||||
locationService.partial(getQueryWithVariables(getState));
|
locationService.partial(getQueryWithVariables(getState));
|
||||||
dashboard?.startRefresh();
|
dashboard?.startRefresh();
|
||||||
@ -526,6 +527,7 @@ export const onTimeRangeUpdated = (
|
|||||||
try {
|
try {
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
const dashboard = getState().dashboard.getModel();
|
const dashboard = getState().dashboard.getModel();
|
||||||
|
dashboard?.setChangeAffectsAllPanels();
|
||||||
dashboard?.startRefresh();
|
dashboard?.startRefresh();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
@ -54,11 +54,13 @@ const getTestContext = () => {
|
|||||||
const templateSrvMock = ({ updateTimeRange: updateTimeRangeMock } as unknown) as TemplateSrv;
|
const templateSrvMock = ({ updateTimeRange: updateTimeRangeMock } as unknown) as TemplateSrv;
|
||||||
const dependencies: OnTimeRangeUpdatedDependencies = { templateSrv: templateSrvMock };
|
const dependencies: OnTimeRangeUpdatedDependencies = { templateSrv: templateSrvMock };
|
||||||
const templateVariableValueUpdatedMock = jest.fn();
|
const templateVariableValueUpdatedMock = jest.fn();
|
||||||
|
const setChangeAffectsAllPanelsMock = jest.fn();
|
||||||
const dashboard = ({
|
const dashboard = ({
|
||||||
getModel: () =>
|
getModel: () =>
|
||||||
(({
|
(({
|
||||||
templateVariableValueUpdated: templateVariableValueUpdatedMock,
|
templateVariableValueUpdated: templateVariableValueUpdatedMock,
|
||||||
startRefresh: startRefreshMock,
|
startRefresh: startRefreshMock,
|
||||||
|
setChangeAffectsAllPanels: setChangeAffectsAllPanelsMock,
|
||||||
} as unknown) as DashboardModel),
|
} as unknown) as DashboardModel),
|
||||||
} as unknown) as DashboardState;
|
} as unknown) as DashboardState;
|
||||||
const startRefreshMock = jest.fn();
|
const startRefreshMock = jest.fn();
|
||||||
@ -82,6 +84,7 @@ const getTestContext = () => {
|
|||||||
updateTimeRangeMock,
|
updateTimeRangeMock,
|
||||||
templateVariableValueUpdatedMock,
|
templateVariableValueUpdatedMock,
|
||||||
startRefreshMock,
|
startRefreshMock,
|
||||||
|
setChangeAffectsAllPanelsMock,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -95,6 +98,7 @@ describe('when onTimeRangeUpdated is dispatched', () => {
|
|||||||
updateTimeRangeMock,
|
updateTimeRangeMock,
|
||||||
templateVariableValueUpdatedMock,
|
templateVariableValueUpdatedMock,
|
||||||
startRefreshMock,
|
startRefreshMock,
|
||||||
|
setChangeAffectsAllPanelsMock,
|
||||||
} = getTestContext();
|
} = getTestContext();
|
||||||
|
|
||||||
const tester = await reduxTester<RootReducerType>({ preloadedState })
|
const tester = await reduxTester<RootReducerType>({ preloadedState })
|
||||||
@ -117,6 +121,7 @@ describe('when onTimeRangeUpdated is dispatched', () => {
|
|||||||
expect(updateTimeRangeMock).toHaveBeenCalledWith(range);
|
expect(updateTimeRangeMock).toHaveBeenCalledWith(range);
|
||||||
expect(templateVariableValueUpdatedMock).toHaveBeenCalledTimes(1);
|
expect(templateVariableValueUpdatedMock).toHaveBeenCalledTimes(1);
|
||||||
expect(startRefreshMock).toHaveBeenCalledTimes(1);
|
expect(startRefreshMock).toHaveBeenCalledTimes(1);
|
||||||
|
expect(setChangeAffectsAllPanelsMock).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -130,6 +135,7 @@ describe('when onTimeRangeUpdated is dispatched', () => {
|
|||||||
updateTimeRangeMock,
|
updateTimeRangeMock,
|
||||||
templateVariableValueUpdatedMock,
|
templateVariableValueUpdatedMock,
|
||||||
startRefreshMock,
|
startRefreshMock,
|
||||||
|
setChangeAffectsAllPanelsMock,
|
||||||
} = getTestContext();
|
} = getTestContext();
|
||||||
|
|
||||||
const base = await reduxTester<RootReducerType>({ preloadedState })
|
const base = await reduxTester<RootReducerType>({ preloadedState })
|
||||||
@ -154,6 +160,7 @@ describe('when onTimeRangeUpdated is dispatched', () => {
|
|||||||
expect(updateTimeRangeMock).toHaveBeenCalledWith(range);
|
expect(updateTimeRangeMock).toHaveBeenCalledWith(range);
|
||||||
expect(templateVariableValueUpdatedMock).toHaveBeenCalledTimes(0);
|
expect(templateVariableValueUpdatedMock).toHaveBeenCalledTimes(0);
|
||||||
expect(startRefreshMock).toHaveBeenCalledTimes(1);
|
expect(startRefreshMock).toHaveBeenCalledTimes(1);
|
||||||
|
expect(setChangeAffectsAllPanelsMock).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -168,6 +175,7 @@ describe('when onTimeRangeUpdated is dispatched', () => {
|
|||||||
updateTimeRangeMock,
|
updateTimeRangeMock,
|
||||||
templateVariableValueUpdatedMock,
|
templateVariableValueUpdatedMock,
|
||||||
startRefreshMock,
|
startRefreshMock,
|
||||||
|
setChangeAffectsAllPanelsMock,
|
||||||
} = getTestContext();
|
} = getTestContext();
|
||||||
|
|
||||||
adapter.updateOptions = jest.fn().mockRejectedValue(new Error('Something broke'));
|
adapter.updateOptions = jest.fn().mockRejectedValue(new Error('Something broke'));
|
||||||
@ -196,6 +204,7 @@ describe('when onTimeRangeUpdated is dispatched', () => {
|
|||||||
expect(updateTimeRangeMock).toHaveBeenCalledWith(range);
|
expect(updateTimeRangeMock).toHaveBeenCalledWith(range);
|
||||||
expect(templateVariableValueUpdatedMock).toHaveBeenCalledTimes(0);
|
expect(templateVariableValueUpdatedMock).toHaveBeenCalledTimes(0);
|
||||||
expect(startRefreshMock).toHaveBeenCalledTimes(0);
|
expect(startRefreshMock).toHaveBeenCalledTimes(0);
|
||||||
|
expect(setChangeAffectsAllPanelsMock).toHaveBeenCalledTimes(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user