Commit 044bea09 by Hugo Häggmark Committed by GitHub

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
parent 6c32a4c0
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);
......
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({
......
......@@ -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,
......
......@@ -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({
......
......@@ -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', () => {
......
......@@ -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);
......
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 () => {
......
......@@ -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);
});
});
});
......
......@@ -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',
......
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 {
......
......@@ -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;
}
......@@ -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 {
......
......@@ -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();
......
......@@ -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();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment