Chore: Fixes various strict null errors (#21763)

* Chore: Removes strict null checks in ReducerTester

* Chore: Fixes strict null errors in ConfigureStore

* Chore: Fixes strict null errors in reducer tests

* Chore: Fixes strict null errors in reducers tests

* Chore: Fixes strict null errors in reducers tests

* Chore: Fixes strict null errors in toggleLogActionsMiddleware

* Chore: Fixes strict null errors in navModelReducer

* Core: Fixes strict null errors in public/app/features/admin/state

* Chore: Fixes strict null errors in public/app/features/dashboard/state/reducers.test.ts

* Chore: Fixes strict null errors in public/app/features/explore/state/reducers.test.ts

* Chore: Fixes strict null errors in public/app/features/datasources/state/reducers.test.ts

* Chore: Fixes strict null errors in public/e2e-test/scenarios/templating/templatevariables-crud.test.ts

* Chore: Fixes strict null errors in public/app/features/dashboard/containers/DashboardPage.test.tsx
This commit is contained in:
Hugo Häggmark 2020-01-28 09:13:56 +01:00 committed by GitHub
parent 6c32a4c0ab
commit 044bea0935
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 181 additions and 152 deletions

View File

@ -1,9 +1,11 @@
import { AnyAction, Dispatch, Store } from 'redux';
import { AnyAction, Dispatch, Middleware, MiddlewareAPI } from 'redux';
import { StoreState } from 'app/types/store';
import { toggleLogActions } from '../reducers/application';
export const toggleLogActionsMiddleware = (store: Store<StoreState>) => (next: Dispatch) => (action: AnyAction) => {
export const toggleLogActionsMiddleware: Middleware<{}, StoreState> = (store: MiddlewareAPI<Dispatch, StoreState>) => (
next: Dispatch
) => (action: AnyAction) => {
const isLogActionsAction = action.type === toggleLogActions.type;
if (isLogActionsAction) {
return next(action);

View File

@ -1,10 +1,11 @@
import { reducerTester } from '../../../test/core/redux/reducerTester';
import { initialState, navIndexReducer, updateNavIndex } from './navModel';
import { NavIndex } from '@grafana/data';
describe('applicationReducer', () => {
describe('when updateNavIndex is dispatched', () => {
it('then state should be correct', () => {
reducerTester()
reducerTester<NavIndex>()
.givenReducer(navIndexReducer, { ...initialState })
.whenActionIsDispatched(
updateNavIndex({

View File

@ -6,9 +6,9 @@ import {
ldapReducer,
ldapSyncStatusLoadedAction,
userAdminReducer,
userProfileLoadedAction,
userMappingInfoFailedAction,
userMappingInfoLoadedAction,
userProfileLoadedAction,
userSessionsLoadedAction,
} from './reducers';
import { LdapState, LdapUser, UserAdminState, UserDTO } from 'app/types';
@ -70,7 +70,7 @@ describe('LDAP page reducer', () => {
available: true,
host: 'localhost',
port: 389,
error: null,
error: (null as unknown) as string,
},
])
)
@ -81,7 +81,7 @@ describe('LDAP page reducer', () => {
available: true,
host: 'localhost',
port: 389,
error: null,
error: (null as unknown) as string,
},
],
ldapError: null,

View File

@ -5,11 +5,11 @@ import {
LdapState,
LdapUser,
SyncInfo,
UserAdminError,
UserAdminState,
UserDTO,
UserOrg,
UserSession,
UserAdminError,
} from 'app/types';
const initialLdapState: LdapState = {
@ -77,6 +77,7 @@ const initialUserAdminState: UserAdminState = {
sessions: [],
orgs: [],
isLoading: true,
error: null,
};
export const userAdminSlice = createSlice({

View File

@ -15,11 +15,11 @@ jest.mock('app/features/dashboard/components/DashboardSettings/SettingsCtrl', ()
interface ScenarioContext {
cleanUpDashboardMock: ToolkitActionCreatorWithoutPayloadMockType;
dashboard?: DashboardModel;
dashboard?: DashboardModel | null;
setDashboardProp: (overrides?: any, metaOverrides?: any) => void;
wrapper?: ShallowWrapper<Props, State, DashboardPage>;
mount: (propOverrides?: Partial<Props>) => void;
setup?: (fn: () => void) => void;
setup: (fn: () => void) => void;
}
function getTestDashboard(overrides?: any, metaOverrides?: any): DashboardModel {
@ -53,7 +53,7 @@ function dashboardPageScenario(description: string, scenarioFn: (ctx: ScenarioCo
},
setDashboardProp: (overrides?: any, metaOverrides?: any) => {
ctx.dashboard = getTestDashboard(overrides, metaOverrides);
ctx.wrapper.setProps({ dashboard: ctx.dashboard });
ctx.wrapper?.setProps({ dashboard: ctx.dashboard });
},
mount: (propOverrides?: Partial<Props>) => {
const props: Props = {
@ -102,7 +102,7 @@ describe('DashboardPage', () => {
dashboardPageScenario('Dashboard is fetching slowly', ctx => {
ctx.setup(() => {
ctx.mount();
ctx.wrapper.setProps({
ctx.wrapper?.setProps({
isInitSlow: true,
initPhase: DashboardInitPhase.Fetching,
});
@ -132,7 +132,7 @@ describe('DashboardPage', () => {
ctx.setup(() => {
ctx.mount();
ctx.setDashboardProp();
ctx.wrapper.setProps({
ctx.wrapper?.setProps({
urlFullscreen: true,
urlEdit: true,
urlPanelId: '1',
@ -140,14 +140,16 @@ describe('DashboardPage', () => {
});
it('Should update model state to fullscreen & edit', () => {
expect(ctx.dashboard.meta.fullscreen).toBe(true);
expect(ctx.dashboard.meta.isEditing).toBe(true);
expect(ctx.dashboard).not.toBe(null);
expect(ctx.dashboard?.meta.fullscreen).toBe(true);
expect(ctx.dashboard?.meta.isEditing).toBe(true);
});
it('Should update component state to fullscreen and edit', () => {
const state = ctx.wrapper.state();
expect(state.isEditing).toBe(true);
expect(state.isFullscreen).toBe(true);
const state = ctx.wrapper?.state();
expect(state).not.toBe(null);
expect(state?.isEditing).toBe(true);
expect(state?.isFullscreen).toBe(true);
});
});
@ -155,29 +157,32 @@ describe('DashboardPage', () => {
ctx.setup(() => {
ctx.mount();
ctx.setDashboardProp();
ctx.wrapper.setState({ scrollTop: 100 });
ctx.wrapper.setProps({
ctx.wrapper?.setState({ scrollTop: 100 });
ctx.wrapper?.setProps({
urlFullscreen: true,
urlEdit: true,
urlPanelId: '1',
});
ctx.wrapper.setProps({
ctx.wrapper?.setProps({
urlFullscreen: false,
urlEdit: false,
urlPanelId: null,
urlPanelId: (null as unknown) as string,
});
});
it('Should update model state normal state', () => {
expect(ctx.dashboard.meta.fullscreen).toBe(false);
expect(ctx.dashboard.meta.isEditing).toBe(false);
expect(ctx.dashboard).not.toBe(null);
expect(ctx.dashboard?.meta.fullscreen).toBe(false);
expect(ctx.dashboard?.meta.isEditing).toBe(false);
});
it('Should update component state to normal and restore scrollTop', () => {
const state = ctx.wrapper.state();
expect(state.isEditing).toBe(false);
expect(state.isFullscreen).toBe(false);
expect(state.scrollTop).toBe(100);
const state = ctx.wrapper?.state();
expect(ctx.wrapper).not.toBe(null);
expect(state).not.toBe(null);
expect(state?.isEditing).toBe(false);
expect(state?.isFullscreen).toBe(false);
expect(state?.scrollTop).toBe(100);
});
});
@ -185,7 +190,7 @@ describe('DashboardPage', () => {
ctx.setup(() => {
ctx.mount();
ctx.setDashboardProp();
ctx.wrapper.setProps({
ctx.wrapper?.setProps({
editview: 'settings',
});
});
@ -195,7 +200,7 @@ describe('DashboardPage', () => {
});
it('should set animation state', () => {
expect(ctx.wrapper.state().isSettingsOpening).toBe(true);
expect(ctx.wrapper?.state().isSettingsOpening).toBe(true);
});
});
@ -203,16 +208,19 @@ describe('DashboardPage', () => {
ctx.setup(() => {
ctx.mount();
ctx.setDashboardProp();
ctx.wrapper.setState({ scrollTop: 100 });
ctx.wrapper.instance().onAddPanel();
ctx.wrapper?.setState({ scrollTop: 100 });
ctx.wrapper?.instance().onAddPanel();
});
it('should set scrollTop to 0', () => {
expect(ctx.wrapper.state().scrollTop).toBe(0);
expect(ctx.wrapper).not.toBe(null);
expect(ctx.wrapper?.state()).not.toBe(null);
expect(ctx.wrapper?.state().scrollTop).toBe(0);
});
it('should add panel widget to dashboard panels', () => {
expect(ctx.dashboard.panels[0].type).toBe('add-panel');
expect(ctx.dashboard).not.toBe(null);
expect(ctx.dashboard?.panels[0].type).toBe('add-panel');
});
});
@ -223,7 +231,7 @@ describe('DashboardPage', () => {
panels: [{ id: 0, type: 'graph' }],
schemaVersion: 17,
});
ctx.wrapper.setProps({
ctx.wrapper?.setProps({
urlEdit: true,
urlFullscreen: true,
urlPanelId: '0',
@ -231,8 +239,11 @@ describe('DashboardPage', () => {
});
it('Should go into edit mode', () => {
expect(ctx.wrapper.state().isEditing).toBe(true);
expect(ctx.wrapper.state().fullscreenPanel.id).toBe(0);
const state = ctx.wrapper?.state();
expect(ctx.wrapper).not.toBe(null);
expect(state).not.toBe(null);
expect(state?.fullscreenPanel).not.toBe(null);
expect(state?.fullscreenPanel?.id).toBe(0);
});
});
@ -243,7 +254,7 @@ describe('DashboardPage', () => {
panels: [{ id: 0, type: 'graph' }],
schemaVersion: 17,
});
ctx.wrapper.unmount();
ctx.wrapper?.unmount();
});
it('Should call clean up action', () => {

View File

@ -5,6 +5,7 @@ import {
panelEditorCleanUp,
panelEditorInitCompleted,
panelEditorReducer,
PanelEditorState,
PanelEditorTab,
PanelEditorTabIds,
} from './reducers';
@ -18,7 +19,7 @@ describe('panelEditorReducer', () => {
getPanelEditorTab(PanelEditorTabIds.Visualization),
getPanelEditorTab(PanelEditorTabIds.Advanced),
];
reducerTester()
reducerTester<PanelEditorState>()
.givenReducer(panelEditorReducer, initialState)
.whenActionIsDispatched(panelEditorInitCompleted({ activeTab, tabs }))
.thenStateShouldEqual({ activeTab, tabs });
@ -33,7 +34,7 @@ describe('panelEditorReducer', () => {
getPanelEditorTab(PanelEditorTabIds.Visualization),
getPanelEditorTab(PanelEditorTabIds.Advanced),
];
reducerTester()
reducerTester<PanelEditorState>()
.givenReducer(panelEditorReducer, { activeTab, tabs })
.whenActionIsDispatched(panelEditorCleanUp())
.thenStateShouldEqual(initialState);

View File

@ -1,12 +1,12 @@
import {
loadDashboardPermissions,
dashboardInitFetching,
dashboardInitCompleted,
dashboardInitFailed,
dashboardInitFetching,
dashboardInitSlow,
loadDashboardPermissions,
} from './actions';
import { OrgRole, PermissionLevel, DashboardState, DashboardInitPhase } from 'app/types';
import { initialState, dashboardReducer } from './reducers';
import { DashboardInitPhase, DashboardState, OrgRole, PermissionLevel } from 'app/types';
import { dashboardReducer, initialState } from './reducers';
import { DashboardModel } from './DashboardModel';
describe('dashboard reducer', () => {
@ -22,7 +22,7 @@ describe('dashboard reducer', () => {
});
it('should add permissions to state', async () => {
expect(state.permissions.length).toBe(2);
expect(state.permissions?.length).toBe(2);
});
});
@ -36,7 +36,7 @@ describe('dashboard reducer', () => {
});
it('should set model', async () => {
expect(state.model.title).toBe('My dashboard');
expect(state.model?.title).toBe('My dashboard');
});
it('should set reset isInitSlow', async () => {
@ -53,7 +53,7 @@ describe('dashboard reducer', () => {
});
it('should set model', async () => {
expect(state.model.title).toBe('Dashboard init failed');
expect(state.model?.title).toBe('Dashboard init failed');
});
it('should set reset isInitSlow', async () => {
@ -61,7 +61,7 @@ describe('dashboard reducer', () => {
});
it('should set initError', async () => {
expect(state.initError.message).toBe('Oh no');
expect(state.initError?.message).toBe('Oh no');
});
it('should set phase failed', async () => {

View File

@ -4,22 +4,22 @@ import {
dataSourceMetaLoaded,
dataSourcePluginsLoad,
dataSourcePluginsLoaded,
dataSourceSettingsReducer,
dataSourcesLoaded,
dataSourcesReducer,
initDataSourceSettingsFailed,
initDataSourceSettingsSucceeded,
initialDataSourceSettingsState,
initialState,
setDataSourceName,
setDataSourcesLayoutMode,
setDataSourcesSearchQuery,
setDataSourceTypeSearchQuery,
setIsDefault,
dataSourceSettingsReducer,
initialDataSourceSettingsState,
initDataSourceSettingsSucceeded,
initDataSourceSettingsFailed,
} from './reducers';
import { getMockDataSource, getMockDataSources } from '../__mocks__/dataSourcesMocks';
import { LayoutModes } from 'app/core/components/LayoutSelector/LayoutSelector';
import { DataSourcesState, DataSourceSettingsState } from 'app/types';
import { DataSourceSettingsState, DataSourcesState } from 'app/types';
import { PluginMeta, PluginMetaInfo, PluginType } from '@grafana/data';
import { GenericDataSourcePlugin } from '../settings/PluginSettings';
@ -42,7 +42,7 @@ describe('dataSourcesReducer', () => {
it('then state should be correct', () => {
const dataSources = getMockDataSources(0);
reducerTester()
reducerTester<DataSourcesState>()
.givenReducer(dataSourcesReducer, initialState)
.whenActionIsDispatched(dataSourcesLoaded(dataSources))
.thenStateShouldEqual({ ...initialState, hasFetched: true, dataSources, dataSourcesCount: 1 });
@ -53,7 +53,7 @@ describe('dataSourcesReducer', () => {
it('then state should be correct', () => {
const dataSource = getMockDataSource();
reducerTester()
reducerTester<DataSourcesState>()
.givenReducer(dataSourcesReducer, initialState)
.whenActionIsDispatched(dataSourceLoaded(dataSource))
.thenStateShouldEqual({ ...initialState, dataSource });
@ -62,7 +62,7 @@ describe('dataSourcesReducer', () => {
describe('when setDataSourcesSearchQuery is dispatched', () => {
it('then state should be correct', () => {
reducerTester()
reducerTester<DataSourcesState>()
.givenReducer(dataSourcesReducer, initialState)
.whenActionIsDispatched(setDataSourcesSearchQuery('some query'))
.thenStateShouldEqual({ ...initialState, searchQuery: 'some query' });
@ -73,7 +73,7 @@ describe('dataSourcesReducer', () => {
it('then state should be correct', () => {
const layoutMode: LayoutModes = LayoutModes.Grid;
reducerTester()
reducerTester<DataSourcesState>()
.givenReducer(dataSourcesReducer, initialState)
.whenActionIsDispatched(setDataSourcesLayoutMode(layoutMode))
.thenStateShouldEqual({ ...initialState, layoutMode: LayoutModes.Grid });
@ -84,7 +84,7 @@ describe('dataSourcesReducer', () => {
it('then state should be correct', () => {
const state: DataSourcesState = { ...initialState, plugins: [mockPlugin()] };
reducerTester()
reducerTester<DataSourcesState>()
.givenReducer(dataSourcesReducer, state)
.whenActionIsDispatched(dataSourcePluginsLoad())
.thenStateShouldEqual({ ...initialState, isLoadingDataSources: true });
@ -96,7 +96,7 @@ describe('dataSourcesReducer', () => {
const dataSourceTypes = [mockPlugin()];
const state: DataSourcesState = { ...initialState, isLoadingDataSources: true };
reducerTester()
reducerTester<DataSourcesState>()
.givenReducer(dataSourcesReducer, state)
.whenActionIsDispatched(dataSourcePluginsLoaded({ plugins: dataSourceTypes, categories: [] }))
.thenStateShouldEqual({ ...initialState, plugins: dataSourceTypes, isLoadingDataSources: false });
@ -105,7 +105,7 @@ describe('dataSourcesReducer', () => {
describe('when setDataSourceTypeSearchQuery is dispatched', () => {
it('then state should be correct', () => {
reducerTester()
reducerTester<DataSourcesState>()
.givenReducer(dataSourcesReducer, initialState)
.whenActionIsDispatched(setDataSourceTypeSearchQuery('type search query'))
.thenStateShouldEqual({ ...initialState, dataSourceTypeSearchQuery: 'type search query' });
@ -116,7 +116,7 @@ describe('dataSourcesReducer', () => {
it('then state should be correct', () => {
const dataSourceMeta = mockPlugin();
reducerTester()
reducerTester<DataSourcesState>()
.givenReducer(dataSourcesReducer, initialState)
.whenActionIsDispatched(dataSourceMetaLoaded(dataSourceMeta))
.thenStateShouldEqual({ ...initialState, dataSourceMeta });
@ -125,19 +125,19 @@ describe('dataSourcesReducer', () => {
describe('when setDataSourceName is dispatched', () => {
it('then state should be correct', () => {
reducerTester()
reducerTester<DataSourcesState>()
.givenReducer(dataSourcesReducer, initialState)
.whenActionIsDispatched(setDataSourceName('some name'))
.thenStateShouldEqual({ ...initialState, dataSource: { name: 'some name' } });
.thenStateShouldEqual({ ...initialState, dataSource: { name: 'some name' } } as DataSourcesState);
});
});
describe('when setIsDefault is dispatched', () => {
it('then state should be correct', () => {
reducerTester()
reducerTester<DataSourcesState>()
.givenReducer(dataSourcesReducer, initialState)
.whenActionIsDispatched(setIsDefault(true))
.thenStateShouldEqual({ ...initialState, dataSource: { isDefault: true } });
.thenStateShouldEqual({ ...initialState, dataSource: { isDefault: true } } as DataSourcesState);
});
});
});

View File

@ -1,4 +1,12 @@
import { DataQuery, DataSourceApi, dateTime, LoadingState, LogsDedupStrategy, toDataFrame } from '@grafana/data';
import {
DataQuery,
DataSourceApi,
dateTime,
LoadingState,
LogsDedupStrategy,
RawTimeRange,
toDataFrame,
} from '@grafana/data';
import {
createEmptyQueryResponse,
@ -24,6 +32,7 @@ import {
} from './actionTypes';
import { serializeStateToUrlParam } from 'app/core/utils/explore';
import { updateLocation } from '../../../core/actions';
import { UrlQueryMap } from '@grafana/runtime';
describe('Explore item reducer', () => {
describe('scanning', () => {
@ -33,7 +42,7 @@ describe('Explore item reducer', () => {
scanning: false,
};
reducerTester()
reducerTester<ExploreItemState>()
.givenReducer(itemReducer, initialState)
.whenActionIsDispatched(scanStartAction({ exploreId: ExploreId.left }))
.thenStateShouldEqual({
@ -45,10 +54,10 @@ describe('Explore item reducer', () => {
const initialState = {
...makeExploreItemState(),
scanning: true,
scanRange: {},
scanRange: {} as RawTimeRange,
};
reducerTester()
reducerTester<ExploreItemState>()
.givenReducer(itemReducer, initialState)
.whenActionIsDispatched(scanStopAction({ exploreId: ExploreId.left }))
.thenStateShouldEqual({
@ -62,8 +71,8 @@ describe('Explore item reducer', () => {
describe('changing datasource', () => {
describe('when changeMode is dispatched', () => {
it('then it should set correct state', () => {
reducerTester()
.givenReducer(itemReducer, {})
reducerTester<ExploreItemState>()
.givenReducer(itemReducer, ({} as unknown) as ExploreItemState)
.whenActionIsDispatched(changeModeAction({ exploreId: ExploreId.left, mode: ExploreMode.Logs }))
.thenStatePredicateShouldEqual((resultingState: ExploreItemState) => {
expect(resultingState.mode).toEqual(ExploreMode.Logs);
@ -90,11 +99,11 @@ describe('Explore item reducer', () => {
} as DataSourceApi;
const queries: DataQuery[] = [];
const queryKeys: string[] = [];
const initialState: Partial<ExploreItemState> = {
const initialState: ExploreItemState = ({
datasourceInstance: null,
queries,
queryKeys,
};
} as unknown) as ExploreItemState;
const expectedState: any = {
datasourceInstance,
queries,
@ -109,7 +118,7 @@ describe('Explore item reducer', () => {
queryResponse: createEmptyQueryResponse(),
};
reducerTester()
reducerTester<ExploreItemState>()
.givenReducer(itemReducer, initialState)
.whenActionIsDispatched(updateDatasourceInstanceAction({ exploreId: ExploreId.left, datasourceInstance }))
.thenStateShouldEqual(expectedState);
@ -135,7 +144,7 @@ describe('Explore item reducer', () => {
state: LoadingState.Streaming,
},
};
reducerTester()
reducerTester<ExploreItemState>()
.givenReducer(itemReducer, initialState)
.whenActionIsDispatched(changeRefreshIntervalAction({ exploreId: ExploreId.left, refreshInterval: 'LIVE' }))
.thenStateShouldEqual(expectedState);
@ -155,7 +164,7 @@ describe('Explore item reducer', () => {
state: LoadingState.Done,
},
};
reducerTester()
reducerTester<ExploreItemState>()
.givenReducer(itemReducer, initialState)
.whenActionIsDispatched(changeRefreshIntervalAction({ exploreId: ExploreId.left, refreshInterval: '' }))
.thenStateShouldEqual(expectedState);
@ -165,12 +174,12 @@ describe('Explore item reducer', () => {
describe('toggling panels', () => {
describe('when toggleGraphAction is dispatched', () => {
it('then it should set correct state', () => {
reducerTester()
.givenReducer(itemReducer, { graphResult: [] })
reducerTester<ExploreItemState>()
.givenReducer(itemReducer, ({ graphResult: [] } as unknown) as ExploreItemState)
.whenActionIsDispatched(toggleGraphAction({ exploreId: ExploreId.left }))
.thenStateShouldEqual({ showingGraph: true, graphResult: [] })
.thenStateShouldEqual(({ showingGraph: true, graphResult: [] } as unknown) as ExploreItemState)
.whenActionIsDispatched(toggleGraphAction({ exploreId: ExploreId.left }))
.thenStateShouldEqual({ showingGraph: false, graphResult: null });
.thenStateShouldEqual(({ showingGraph: false, graphResult: null } as unknown) as ExploreItemState);
});
});
@ -187,12 +196,12 @@ describe('Explore item reducer', () => {
],
});
reducerTester()
.givenReducer(itemReducer, { tableResult: table })
reducerTester<ExploreItemState>()
.givenReducer(itemReducer, ({ tableResult: table } as unknown) as ExploreItemState)
.whenActionIsDispatched(toggleTableAction({ exploreId: ExploreId.left }))
.thenStateShouldEqual({ showingTable: true, tableResult: table })
.thenStateShouldEqual(({ showingTable: true, tableResult: table } as unknown) as ExploreItemState)
.whenActionIsDispatched(toggleTableAction({ exploreId: ExploreId.left }))
.thenStateShouldEqual({ showingTable: false, tableResult: null });
.thenStateShouldEqual(({ showingTable: false, tableResult: null } as unknown) as ExploreItemState);
});
});
});
@ -200,12 +209,12 @@ describe('Explore item reducer', () => {
describe('changing range', () => {
describe('when changeRangeAction is dispatched', () => {
it('then it should set correct state', () => {
reducerTester()
.givenReducer(itemReducer, {
reducerTester<ExploreItemState>()
.givenReducer(itemReducer, ({
update: { ...makeInitialUpdateState(), range: true },
range: null,
absoluteRange: null,
})
} as unknown) as ExploreItemState)
.whenActionIsDispatched(
changeRangeAction({
exploreId: ExploreId.left,
@ -213,11 +222,11 @@ describe('Explore item reducer', () => {
range: { from: dateTime('2019-01-01'), to: dateTime('2019-01-02'), raw: { from: 'now-1d', to: 'now' } },
})
)
.thenStateShouldEqual({
.thenStateShouldEqual(({
update: { ...makeInitialUpdateState(), range: false },
absoluteRange: { from: 1546297200000, to: 1546383600000 },
range: { from: dateTime('2019-01-01'), to: dateTime('2019-01-02'), raw: { from: 'now-1d', to: 'now' } },
});
} as unknown) as ExploreItemState);
});
});
});
@ -242,7 +251,11 @@ export const setup = (urlStateOverrides?: any) => {
};
const urlState: ExploreUrlState = { ...urlStateDefaults, ...urlStateOverrides };
const serializedUrlState = serializeStateToUrlParam(urlState);
const initialState = { split: false, left: { urlState, update }, right: { urlState, update } };
const initialState = ({
split: false,
left: { urlState, update },
right: { urlState, update },
} as unknown) as ExploreState;
return {
initialState,
@ -253,76 +266,76 @@ export const setup = (urlStateOverrides?: any) => {
describe('Explore reducer', () => {
describe('split view', () => {
it("should make right pane a duplicate of the given item's state on split open", () => {
const leftItemMock = {
const leftItemMock = ({
containerWidth: 100,
} as ExploreItemState;
} as unknown) as ExploreItemState;
const initialState = {
const initialState = ({
split: null,
left: leftItemMock as ExploreItemState,
right: makeExploreItemState(),
} as ExploreState;
} as unknown) as ExploreState;
reducerTester()
reducerTester<ExploreState>()
.givenReducer(exploreReducer, initialState)
.whenActionIsDispatched(splitOpenAction({ itemState: leftItemMock }))
.thenStateShouldEqual({
.thenStateShouldEqual(({
split: true,
left: leftItemMock,
right: leftItemMock,
});
} as unknown) as ExploreState);
});
describe('split close', () => {
it('should keep right pane as left when left is closed', () => {
const leftItemMock = {
const leftItemMock = ({
containerWidth: 100,
} as ExploreItemState;
} as unknown) as ExploreItemState;
const rightItemMock = {
const rightItemMock = ({
containerWidth: 200,
} as ExploreItemState;
} as unknown) as ExploreItemState;
const initialState = {
const initialState = ({
split: null,
left: leftItemMock,
right: rightItemMock,
} as ExploreState;
} as unknown) as ExploreState;
// closing left item
reducerTester()
reducerTester<ExploreState>()
.givenReducer(exploreReducer, initialState)
.whenActionIsDispatched(splitCloseAction({ itemId: ExploreId.left }))
.thenStateShouldEqual({
.thenStateShouldEqual(({
split: false,
left: rightItemMock,
right: initialExploreState.right,
});
} as unknown) as ExploreState);
});
it('should reset right pane when it is closed ', () => {
const leftItemMock = {
const leftItemMock = ({
containerWidth: 100,
} as ExploreItemState;
} as unknown) as ExploreItemState;
const rightItemMock = {
const rightItemMock = ({
containerWidth: 200,
} as ExploreItemState;
} as unknown) as ExploreItemState;
const initialState = {
const initialState = ({
split: null,
left: leftItemMock,
right: rightItemMock,
} as ExploreState;
} as unknown) as ExploreState;
// closing left item
reducerTester()
reducerTester<ExploreState>()
.givenReducer(exploreReducer, initialState)
.whenActionIsDispatched(splitCloseAction({ itemId: ExploreId.right }))
.thenStateShouldEqual({
.thenStateShouldEqual(({
split: false,
left: leftItemMock,
right: initialExploreState.right,
});
} as unknown) as ExploreState);
});
});
});
@ -330,20 +343,20 @@ describe('Explore reducer', () => {
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({});
reducerTester<ExploreState>()
.givenReducer(exploreReducer, ({} as unknown) as ExploreState)
.whenActionIsDispatched(updateLocation({ query: (null as unknown) as UrlQueryMap }))
.thenStateShouldEqual(({} as unknown) as ExploreState);
});
});
describe('and payload contains a query', () => {
describe("but does not contain 'left'", () => {
it('then it should just return state', () => {
reducerTester()
.givenReducer(exploreReducer, {})
reducerTester<ExploreState>()
.givenReducer(exploreReducer, ({} as unknown) as ExploreState)
.whenActionIsDispatched(updateLocation({ query: {} }))
.thenStateShouldEqual({});
.thenStateShouldEqual(({} as unknown) as ExploreState);
});
});
@ -352,7 +365,7 @@ describe('Explore reducer', () => {
const { initialState, serializedUrlState } = setup();
const expectedState = { ...initialState, split: true };
reducerTester()
reducerTester<ExploreState>()
.givenReducer(exploreReducer, initialState)
.whenActionIsDispatched(
updateLocation({
@ -370,11 +383,11 @@ describe('Explore reducer', () => {
describe('but urlState is not set in state', () => {
it('then it should just add urlState and update in state', () => {
const { initialState, serializedUrlState } = setup();
const urlState: ExploreUrlState = null;
const stateWithoutUrlState = { ...initialState, left: { urlState } };
const urlState: ExploreUrlState = (null as unknown) as ExploreUrlState;
const stateWithoutUrlState = ({ ...initialState, left: { urlState } } as unknown) as ExploreState;
const expectedState = { ...initialState };
reducerTester()
reducerTester<ExploreState>()
.givenReducer(exploreReducer, stateWithoutUrlState)
.whenActionIsDispatched(
updateLocation({
@ -393,7 +406,7 @@ describe('Explore reducer', () => {
const { initialState, serializedUrlState } = setup();
const expectedState = { ...initialState };
reducerTester()
reducerTester<ExploreState>()
.givenReducer(exploreReducer, initialState)
.whenActionIsDispatched(
updateLocation({
@ -432,7 +445,7 @@ describe('Explore reducer', () => {
},
};
reducerTester()
reducerTester<ExploreState>()
.givenReducer(exploreReducer, stateWithDifferentDataSource)
.whenActionIsDispatched(
updateLocation({
@ -473,7 +486,7 @@ describe('Explore reducer', () => {
},
};
reducerTester()
reducerTester<ExploreState>()
.givenReducer(exploreReducer, stateWithDifferentDataSource)
.whenActionIsDispatched(
updateLocation({
@ -511,7 +524,7 @@ describe('Explore reducer', () => {
},
};
reducerTester()
reducerTester<ExploreState>()
.givenReducer(exploreReducer, stateWithDifferentDataSource)
.whenActionIsDispatched(
updateLocation({
@ -552,7 +565,7 @@ describe('Explore reducer', () => {
},
};
reducerTester()
reducerTester<ExploreState>()
.givenReducer(exploreReducer, stateWithDifferentDataSource)
.whenActionIsDispatched(
updateLocation({
@ -571,7 +584,7 @@ describe('Explore reducer', () => {
const { initialState, serializedUrlState } = setup();
const expectedState = { ...initialState };
reducerTester()
reducerTester<ExploreState>()
.givenReducer(exploreReducer, initialState)
.whenActionIsDispatched(
updateLocation({

View File

@ -17,14 +17,14 @@ export function addRootReducer(reducers: any) {
export function configureStore() {
const logger = createLogger({
predicate: (getState: () => StoreState) => {
predicate: getState => {
return getState().application.logActions;
},
});
const middleware = process.env.NODE_ENV !== 'production' ? [toggleLogActionsMiddleware, thunk, logger] : [thunk];
const store = reduxConfigureStore({
const store = reduxConfigureStore<StoreState>({
reducer: createRootReducer(),
middleware,
devTools: process.env.NODE_ENV !== 'production',

View File

@ -1,5 +1,5 @@
import { LayoutMode } from '../core/components/LayoutSelector/LayoutSelector';
import { DataSourceSettings, DataSourcePluginMeta } from '@grafana/data';
import { DataSourcePluginMeta, DataSourceSettings } from '@grafana/data';
import { GenericDataSourcePlugin } from 'app/features/datasources/settings/PluginSettings';
export interface DataSourcesState {
@ -17,12 +17,12 @@ export interface DataSourcesState {
}
export interface DataSourceSettingsState {
plugin?: GenericDataSourcePlugin;
plugin?: GenericDataSourcePlugin | null;
testingStatus?: {
message?: string;
status?: string;
message?: string | null;
status?: string | null;
};
loadError?: string;
loadError?: string | null;
}
export interface DataSourcePluginCategory {

View File

@ -77,9 +77,9 @@ export type LdapConnectionInfo = LdapServerInfo[];
export interface LdapState {
connectionInfo: LdapConnectionInfo;
user?: LdapUser;
syncInfo?: SyncInfo;
connectionError?: LdapError;
userError?: LdapError;
ldapError?: LdapError;
user?: LdapUser | null;
syncInfo?: SyncInfo | null;
connectionError?: LdapError | null;
userError?: LdapError | null;
ldapError?: LdapError | null;
}

View File

@ -90,11 +90,11 @@ export interface UserOrg {
}
export interface UserAdminState {
user: UserDTO;
user: UserDTO | null;
sessions: UserSession[];
orgs: UserOrg[];
isLoading: boolean;
error?: UserAdminError;
error?: UserAdminError | null;
}
export interface UserAdminError {

View File

@ -17,7 +17,7 @@ e2eScenario({
createTestDashboard: true,
skipScenario: true,
scenario: async (browser: Browser, page: Page, datasourceName?: string, dashboardPage?: TestPage<DashboardPage>) => {
await dashboardPage.pageObjects.settings.click();
await dashboardPage?.pageObjects.settings.click();
await dashboardSettingsPage.init(page);
await dashboardSettingsPage.pageObjects.variablesSection.click();
@ -57,7 +57,7 @@ e2eScenario({
await variablesPage.pageObjects.goBackButton.click();
await dashboardPage.pageObjects.settings.click();
await dashboardPage?.pageObjects.settings.click();
await dashboardSettingsPage.init(page);
await dashboardSettingsPage.pageObjects.variablesSection.click();
@ -76,7 +76,7 @@ e2eScenario({
const asserts = queryVariables.slice(0, queryVariableIndex + 1);
await createQueryVariable({
page: variablePage,
datasourceName,
datasourceName: datasourceName as string,
name,
label,
query,
@ -92,9 +92,9 @@ e2eScenario({
await variablesPage.pageObjects.goBackButton.click();
await assertVariableLabelsAndComponents(dashboardPage, asserts);
await assertVariableLabelsAndComponents(dashboardPage as TestPage<DashboardPage>, asserts);
await dashboardPage.pageObjects.settings.click();
await dashboardPage?.pageObjects.settings.click();
await dashboardSettingsPage.pageObjects.variablesSection.click();

View File

@ -37,7 +37,7 @@ describe('reducerTester', () => {
describe('when reducer mutates state', () => {
it('then it should throw', () => {
expect(() => {
reducerTester()
reducerTester<DummyState>()
.givenReducer(mutatingReducer, initialState)
.whenActionIsDispatched(dummyAction('some string'));
}).toThrow();
@ -47,7 +47,7 @@ describe('reducerTester', () => {
describe('when reducer does not mutate state', () => {
it('then it should not throw', () => {
expect(() => {
reducerTester()
reducerTester<DummyState>()
.givenReducer(okReducer, initialState)
.whenActionIsDispatched(dummyAction('some string'));
}).not.toThrow();