Skip to content

Commit dfa923d

Browse files
committed
CONSOLE-5073: Fix redux related types
1 parent ee31cd8 commit dfa923d

10 files changed

Lines changed: 72 additions & 49 deletions

File tree

frontend/packages/console-app/src/components/detect-namespace/__tests__/namespace.spec.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useState } from 'react';
22
import { act, renderHook } from '@testing-library/react';
33
import { useDispatch } from 'react-redux';
4+
import type { Location } from 'react-router-dom-v5-compat';
45
import { useLocation } from 'react-router-dom-v5-compat';
56
import { k8sGet } from '@console/dynamic-plugin-sdk/src/utils/k8s';
67
import { ALL_NAMESPACES_KEY } from '@console/shared/src/constants';
@@ -41,19 +42,22 @@ jest.mock('../../user-preferences/namespace/usePreferredNamespace', () => ({
4142
usePreferredNamespace: jest.fn(),
4243
}));
4344

44-
const useDispatchMock = useDispatch as jest.Mock;
45-
const useFlagMock = useFlag as jest.Mock;
46-
const useLocationMock = useLocation as jest.Mock;
47-
const useLastNamespaceMock = useLastNamespace as jest.Mock;
48-
const usePreferredNamespaceMock = usePreferredNamespace as jest.Mock;
49-
const k8sGetMock = k8sGet as jest.Mock;
50-
const useStateMock = useState as jest.Mock;
45+
const useDispatchMock = useDispatch as jest.MockedFunction<typeof useDispatch>;
46+
const useFlagMock = useFlag as jest.MockedFunction<typeof useFlag>;
47+
const useLocationMock = useLocation as jest.MockedFunction<typeof useLocation>;
48+
const useLastNamespaceMock = useLastNamespace as jest.MockedFunction<typeof useLastNamespace>;
49+
const usePreferredNamespaceMock = usePreferredNamespace as jest.MockedFunction<
50+
typeof usePreferredNamespace
51+
>;
52+
const k8sGetMock = k8sGet as jest.MockedFunction<typeof k8sGet>;
53+
const useStateMock = useState as jest.MockedFunction<typeof useState>;
5154

5255
const activeNamespace = 'active-ns';
5356
const urlNamespace: string = 'url-ns';
54-
const getLocationData = (valid = true) => ({
55-
pathname: valid ? `home/ns/${urlNamespace}` : 'home/invalid',
56-
});
57+
const getLocationData = (valid = true) =>
58+
({
59+
pathname: valid ? `home/ns/${urlNamespace}` : 'home/invalid',
60+
} as Location);
5761
const lastNamespace: string = 'last-ns';
5862
const preferredNamespace: string = 'preferred-ns';
5963

frontend/packages/console-app/src/components/tour/__tests__/tour-context.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jest.mock('@console/dynamic-plugin-sdk/src/perspective/useActivePerspective', ()
2323
default: () => ['dev', jest.fn()],
2424
}));
2525

26-
const useSelectorMock = useSelector as jest.Mock;
26+
const useSelectorMock = useSelector as jest.MockedFunction<typeof useSelector>;
2727
const useResolvedExtensionsMock = useResolvedExtensions as jest.Mock;
2828
const useUserPreferenceCompatibilityMock = useUserPreferenceCompatibility as jest.Mock;
2929

frontend/packages/console-shared/src/components/editor/__tests__/CodeEditorToolbar.spec.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,17 @@ jest.mock('../../../hooks/ols-hook', () => ({
1717
useOLSConfig: jest.fn(),
1818
}));
1919

20+
const useDispatchMock = useDispatch as jest.MockedFunction<typeof useDispatch>;
21+
const useOLSConfigMock = useOLSConfig as jest.MockedFunction<typeof useOLSConfig>;
22+
const useTranslationMock = useTranslation as jest.Mock;
23+
2024
describe('CodeEditorToolbar', () => {
2125
const mockDispatch = jest.fn();
2226

2327
beforeEach(() => {
2428
jest.clearAllMocks();
25-
(useTranslation as jest.Mock).mockReturnValue({ t: (key: string) => key });
26-
(useDispatch as jest.Mock).mockReturnValue(mockDispatch);
29+
useTranslationMock.mockReturnValue({ t: (key: string) => key });
30+
useDispatchMock.mockReturnValue(mockDispatch);
2731
});
2832

2933
it('should render null when showShortcuts is false and toolbarLinks is empty', () => {
@@ -37,19 +41,19 @@ describe('CodeEditorToolbar', () => {
3741
});
3842

3943
it('should render "Ask OpenShift Lightspeed" button when showLightspeedButton is true', () => {
40-
(useOLSConfig as jest.Mock).mockReturnValue(true);
44+
useOLSConfigMock.mockReturnValue(true);
4145
render(<AskOpenShiftLightspeedButton />);
4246
expect(screen.getByRole('button')).toBeInTheDocument();
4347
});
4448

4549
it('should not render "Ask OpenShift Lightspeed" button when showLightspeedButton is false', () => {
46-
(useOLSConfig as jest.Mock).mockReturnValue(false);
50+
useOLSConfigMock.mockReturnValue(false);
4751
render(<AskOpenShiftLightspeedButton />);
4852
expect(screen.queryByRole('button')).not.toBeInTheDocument();
4953
});
5054

5155
it('should dispatch OpenOLS action when "Ask OpenShift Lightspeed" button is clicked', () => {
52-
(useOLSConfig as jest.Mock).mockReturnValue(true);
56+
useOLSConfigMock.mockReturnValue(true);
5357
render(<AskOpenShiftLightspeedButton />);
5458
const button = screen.getByRole('button');
5559
fireEvent.click(button);

frontend/packages/console-shared/src/hooks/__tests__/useGetUserSettingConfigMap.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { useGetUserSettingConfigMap } from '../useGetUserSettingConfigMap';
88

99
// Mock dependencies
1010
const useK8sWatchResourceMock = useK8sWatchResource as jest.Mock;
11-
const useSelectorMock = useSelector as jest.Mock;
11+
const useSelectorMock = useSelector as jest.MockedFunction<typeof useSelector>;
1212

1313
jest.mock('@console/internal/components/utils/k8s-watch-hook', () => ({
1414
useK8sWatchResource: jest.fn(),

frontend/packages/console-shared/src/hooks/__tests__/useUser.spec.ts

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { renderHook } from '@testing-library/react';
22
import { useSelector, useDispatch } from 'react-redux';
3+
import type { K8sResourceKind } from '@console/dynamic-plugin-sdk/src';
34
import { useK8sGet } from '@console/internal/components/utils/k8s-get-hook';
45
import { useUser } from '../useUser';
56

@@ -19,6 +20,11 @@ jest.mock('@console/internal/components/utils/k8s-get-hook', () => ({
1920
useK8sGet: jest.fn(),
2021
}));
2122

23+
const baseUserResource: K8sResourceKind = {
24+
apiVersion: 'user.openshift.io/v1',
25+
kind: 'User',
26+
};
27+
2228
const mockSetUserResource = jest.fn((userResource) => ({
2329
type: 'setUserResource',
2430
payload: { userResource },
@@ -31,26 +37,30 @@ jest.mock('@console/dynamic-plugin-sdk', () => ({
3137
setUserResource: (userResource: unknown) => mockSetUserResource(userResource),
3238
}));
3339

34-
const mockDispatch = jest.fn();
35-
const mockUseSelector = useSelector as jest.Mock;
36-
const mockUseK8sGet = useK8sGet as jest.Mock;
37-
const mockUseDispatch = useDispatch as jest.Mock;
40+
const dispatchMock = jest.fn();
41+
const useSelectorMock = useSelector as jest.MockedFunction<typeof useSelector>;
42+
const useDispatchMock = useDispatch as jest.MockedFunction<typeof useDispatch>;
43+
const useK8sGetMock = useK8sGet as jest.MockedFunction<typeof useK8sGet>;
3844

3945
describe('useUser', () => {
4046
beforeEach(() => {
4147
jest.clearAllMocks();
42-
mockUseDispatch.mockReturnValue(mockDispatch);
48+
useDispatchMock.mockReturnValue(dispatchMock);
4349
});
4450

4551
it('should return user data with displayName from fullName when available', () => {
4652
const mockUser = { username: 'testuser@example.com', uid: '123' };
47-
const mockUserResource = { fullName: 'Test User', identities: ['testuser'] };
53+
const mockUserResource = {
54+
...baseUserResource,
55+
fullName: 'Test User',
56+
identities: ['testuser'],
57+
};
4858

49-
mockUseSelector
59+
useSelectorMock
5060
.mockReturnValueOnce(mockUser) // for getUser
5161
.mockReturnValueOnce(mockUserResource); // for getUserResource
5262

53-
mockUseK8sGet.mockReturnValue([mockUserResource, true, null]);
63+
useK8sGetMock.mockReturnValue([mockUserResource, true, null]);
5464

5565
const { result } = renderHook(() => useUser());
5666

@@ -63,11 +73,11 @@ describe('useUser', () => {
6373

6474
it('should fallback to username when fullName is not available', () => {
6575
const mockUser = { username: 'testuser@example.com', uid: '123' };
66-
const mockUserResource = { identities: ['testuser'] }; // No fullName
76+
const mockUserResource = { ...baseUserResource, identities: ['testuser'] }; // No fullName
6777

68-
mockUseSelector.mockReturnValueOnce(mockUser).mockReturnValueOnce(mockUserResource);
78+
useSelectorMock.mockReturnValueOnce(mockUser).mockReturnValueOnce(mockUserResource);
6979

70-
mockUseK8sGet.mockReturnValue([mockUserResource, true, null]);
80+
useK8sGetMock.mockReturnValue([mockUserResource, true, null]);
7181

7282
const { result } = renderHook(() => useUser());
7383

@@ -77,27 +87,27 @@ describe('useUser', () => {
7787

7888
it('should dispatch setUserResource when user resource is loaded', () => {
7989
const mockUser = { username: 'testuser@example.com' };
80-
const mockUserResource = { fullName: 'Test User' };
90+
const mockUserResource = { ...baseUserResource, fullName: 'Test User' };
8191

82-
mockUseSelector.mockReturnValueOnce(mockUser).mockReturnValueOnce(null); // No userResource in Redux yet
92+
useSelectorMock.mockReturnValueOnce(mockUser).mockReturnValueOnce(null); // No userResource in Redux yet
8393

84-
mockUseK8sGet.mockReturnValue([mockUserResource, true, null]);
94+
useK8sGetMock.mockReturnValue([mockUserResource, true, null]);
8595

8696
renderHook(() => useUser());
8797

88-
expect(mockDispatch).toHaveBeenCalledWith({
98+
expect(dispatchMock).toHaveBeenCalledWith({
8999
type: 'setUserResource',
90100
payload: { userResource: mockUserResource },
91101
});
92102
});
93103

94104
it('should handle edge cases with empty strings and fallback to "Unknown user"', () => {
95105
const mockUser = { username: '' }; // Empty username
96-
const mockUserResource = { fullName: ' ' }; // Whitespace-only fullName
106+
const mockUserResource = { ...baseUserResource, fullName: ' ' }; // Whitespace-only fullName
97107

98-
mockUseSelector.mockReturnValueOnce(mockUser).mockReturnValueOnce(mockUserResource);
108+
useSelectorMock.mockReturnValueOnce(mockUser).mockReturnValueOnce(mockUserResource);
99109

100-
mockUseK8sGet.mockReturnValue([mockUserResource, true, null]);
110+
useK8sGetMock.mockReturnValue([mockUserResource, true, null]);
101111

102112
const { result } = renderHook(() => useUser());
103113

@@ -106,11 +116,11 @@ describe('useUser', () => {
106116

107117
it('should trim whitespace from fullName and username', () => {
108118
const mockUser = { username: ' testuser@example.com ' };
109-
const mockUserResource = { fullName: ' Test User ' };
119+
const mockUserResource = { ...baseUserResource, fullName: ' Test User ' };
110120

111-
mockUseSelector.mockReturnValueOnce(mockUser).mockReturnValueOnce(mockUserResource);
121+
useSelectorMock.mockReturnValueOnce(mockUser).mockReturnValueOnce(mockUserResource);
112122

113-
mockUseK8sGet.mockReturnValue([mockUserResource, true, null]);
123+
useK8sGetMock.mockReturnValue([mockUserResource, true, null]);
114124

115125
const { result } = renderHook(() => useUser());
116126

frontend/packages/console-shared/src/hooks/__tests__/useUserPreference.spec.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@ import {
1111
import { useUserPreference } from '../useUserPreference';
1212

1313
const useK8sWatchResourceMock = useK8sWatchResource as jest.Mock;
14-
const createConfigMapMock = createConfigMap as jest.Mock;
15-
const updateConfigMapMock = updateConfigMap as jest.Mock;
16-
const useSelectorMock = useSelector as jest.Mock;
17-
const useFavoritesOptionsMock = useFavoritesOptions as jest.Mock;
14+
const createConfigMapMock = createConfigMap as jest.MockedFunction<typeof createConfigMap>;
15+
const updateConfigMapMock = updateConfigMap as jest.MockedFunction<typeof updateConfigMap>;
16+
const useSelectorMock = useSelector as jest.MockedFunction<typeof useSelector>;
17+
const useFavoritesOptionsMock = useFavoritesOptions as jest.MockedFunction<
18+
typeof useFavoritesOptions
19+
>;
1820

1921
jest.mock('@console/internal/components/useFavoritesOptions', () => ({
2022
useFavoritesOptions: jest.fn(),

frontend/packages/console-shared/src/test-utils/unit-test-utils.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ type WrapperProps = {
2525
};
2626

2727
// Create a Redux store with reducer and initial state.
28-
const rootReducer = combineReducers<RootState>(baseReducers);
28+
const rootReducer = combineReducers(baseReducers);
2929
const setupStore = (initialState?: Partial<RootState>) => {
3030
const store = createStore(rootReducer, initialState);
3131
// Set the store in storeHandler so that modules like rbac.tsx can access it

frontend/packages/dev-console/src/utils/__tests__/usePerspectiveDetection.spec.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ jest.mock('react-redux', () => ({
77
useSelector: jest.fn(),
88
}));
99

10+
const useSelectorMock = useSelector as jest.MockedFunction<typeof useSelector>;
11+
1012
describe('usePerspectiveDetection', () => {
1113
it('should return loading as true if CAN_GET_NS flag is pending', () => {
12-
(useSelector as jest.Mock).mockImplementation(() => ({
14+
useSelectorMock.mockImplementation(() => ({
1315
CAN_GET_NS: undefined,
1416
}));
1517

@@ -21,7 +23,7 @@ describe('usePerspectiveDetection', () => {
2123
});
2224

2325
it('should return loading as false if CAN_GET_NS flag is loaded', () => {
24-
(useSelector as jest.Mock).mockImplementation(() => ({
26+
useSelectorMock.mockImplementation(() => ({
2527
CAN_GET_NS: false,
2628
}));
2729

frontend/packages/knative-plugin/src/components/add/__tests__/EventSink.spec.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
} from '../__mocks__/Kamelet-data';
88
import EventSink from '../EventSink';
99

10-
const useSelectorMock = useSelector as jest.Mock;
10+
const useSelectorMock = useSelector as jest.MockedFunction<typeof useSelector>;
1111

1212
jest.mock('react-redux', () => {
1313
const originalModule = jest.requireActual('react-redux');

frontend/public/redux.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,10 @@ export const baseReducers = Object.freeze({
3636
...SDKReducers,
3737
});
3838

39+
// TODO: Refactor to redux toolkit configureStore
3940
const store = createStore(
40-
combineReducers<RootState>(baseReducers),
41-
{},
41+
combineReducers(baseReducers),
42+
{} as RootState,
4243
composeEnhancers(applyMiddleware(thunk, featureFlagMiddleware)),
4344
);
4445

@@ -56,7 +57,7 @@ export const applyReduxExtensions = (reducerExtensions: ResolvedExtension<ReduxR
5657
? baseReducers
5758
: { plugins: combineReducers(pluginReducers), ...baseReducers };
5859

59-
store.replaceReducer(combineReducers<RootState>(nextReducers));
60+
store.replaceReducer(combineReducers(nextReducers));
6061
};
6162

6263
if (process.env.NODE_ENV !== 'production') {

0 commit comments

Comments
 (0)