Skip to content

Commit 39359f6

Browse files
[Test Improver] test: add unit tests for gc-root-store.js (#17806)
* test: add unit tests for gc-root-store.js Add 15 unit tests covering gcGetters.gcStores and all gcActions: - gcPreferencesUpdated (3 cases: enabled, disabled-was-on, disabled-was-off) - gcRouteChanged, gcStartIntervals, gcStopIntervals (delegation) - gcResetStores (dispatch for each store, empty stores) - garbageCollect (enabled/disabled setting, empty stores) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * ci: trigger checks --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent f4544f8 commit 39359f6

1 file changed

Lines changed: 225 additions & 0 deletions

File tree

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
import type { gcGetters as GcGettersType, gcActions as GcActionsType } from '@shell/utils/gc/gc-root-store';
2+
3+
let gcGetters: typeof GcGettersType;
4+
let gcActions: typeof GcActionsType;
5+
let mockGc: any;
6+
let mockGcInterval: any;
7+
let mockGcRoute: any;
8+
9+
describe('gc-root-store', () => {
10+
beforeEach(() => {
11+
mockGc = {
12+
gcEnabledForStore: jest.fn(),
13+
gcEnabledSetting: jest.fn(),
14+
};
15+
16+
mockGcInterval = {
17+
gcStartIntervals: jest.fn(),
18+
gcStopIntervals: jest.fn(),
19+
};
20+
21+
mockGcRoute = { gcRouteChanged: jest.fn() };
22+
23+
jest.resetModules();
24+
jest.mock('../gc', () => ({ default: mockGc, __esModule: true }));
25+
jest.mock('../gc-interval', () => ({ default: mockGcInterval, __esModule: true }));
26+
jest.mock('../gc-route-changed', () => ({ default: mockGcRoute, __esModule: true }));
27+
28+
const mod = require('../gc-root-store');
29+
30+
gcGetters = mod.gcGetters;
31+
gcActions = mod.gcActions;
32+
});
33+
34+
afterEach(() => {
35+
jest.restoreAllMocks();
36+
});
37+
38+
describe('gcGetters.gcStores', () => {
39+
it('returns stores for which gcEnabledForStore returns truthy', () => {
40+
const state = {
41+
cluster: { someKey: 'val' },
42+
management: { someKey: 'val' },
43+
other: { someKey: 'val' },
44+
};
45+
46+
mockGc.gcEnabledForStore.mockImplementation((storeState: any) => storeState === state.cluster || storeState === state.management);
47+
48+
expect(gcGetters.gcStores(state)).toStrictEqual([
49+
['cluster', state.cluster],
50+
['management', state.management],
51+
]);
52+
});
53+
54+
it('returns empty array when no stores have gc enabled', () => {
55+
const state = { cluster: { x: 1 }, management: { x: 2 } };
56+
57+
mockGc.gcEnabledForStore.mockReturnValue(false);
58+
59+
expect(gcGetters.gcStores(state)).toStrictEqual([]);
60+
});
61+
62+
it('skips non-object state entries (primitives)', () => {
63+
const state: any = {
64+
counter: 42,
65+
flag: true,
66+
cluster: { x: 1 },
67+
};
68+
69+
mockGc.gcEnabledForStore.mockImplementation((s: any) => s === state.cluster);
70+
71+
expect(gcGetters.gcStores(state)).toStrictEqual([['cluster', state.cluster]]);
72+
expect(mockGc.gcEnabledForStore).toHaveBeenCalledWith(state.cluster);
73+
expect(mockGc.gcEnabledForStore).not.toHaveBeenCalledWith(42);
74+
});
75+
76+
it('returns empty array for empty state', () => {
77+
expect(gcGetters.gcStores({})).toStrictEqual([]);
78+
});
79+
});
80+
81+
describe('gcActions.gcRouteChanged', () => {
82+
it('delegates to gcRoute.gcRouteChanged with ctx and to', () => {
83+
const ctx = { dispatch: jest.fn() };
84+
const to = { path: '/clusters' };
85+
86+
gcActions.gcRouteChanged(ctx, to);
87+
88+
expect(mockGcRoute.gcRouteChanged).toHaveBeenCalledWith(ctx, to);
89+
});
90+
});
91+
92+
describe('gcActions.gcStartIntervals', () => {
93+
it('delegates to gcInterval.gcStartIntervals with ctx', () => {
94+
const ctx = { dispatch: jest.fn() };
95+
96+
gcActions.gcStartIntervals(ctx);
97+
98+
expect(mockGcInterval.gcStartIntervals).toHaveBeenCalledWith(ctx);
99+
});
100+
});
101+
102+
describe('gcActions.gcStopIntervals', () => {
103+
it('delegates to gcInterval.gcStopIntervals with no arguments', () => {
104+
const ctx = { dispatch: jest.fn() };
105+
106+
gcActions.gcStopIntervals(ctx);
107+
108+
expect(mockGcInterval.gcStopIntervals).toHaveBeenCalledWith();
109+
});
110+
});
111+
112+
describe('gcActions.gcResetStores', () => {
113+
it('dispatches gcResetStore for each gc-enabled store', () => {
114+
const dispatch = jest.fn();
115+
const getters = {
116+
gcStores: [
117+
['cluster', {}],
118+
['management', {}],
119+
],
120+
};
121+
122+
gcActions.gcResetStores({ dispatch, getters });
123+
124+
expect(dispatch).toHaveBeenCalledWith('cluster/gcResetStore');
125+
expect(dispatch).toHaveBeenCalledWith('management/gcResetStore');
126+
expect(dispatch).toHaveBeenCalledTimes(2);
127+
});
128+
129+
it('dispatches nothing when gcStores is empty', () => {
130+
const dispatch = jest.fn();
131+
132+
gcActions.gcResetStores({ dispatch, getters: { gcStores: [] } });
133+
134+
expect(dispatch).not.toHaveBeenCalled();
135+
});
136+
});
137+
138+
describe('gcActions.garbageCollect', () => {
139+
it('dispatches garbageCollect to each gc-enabled store when gc setting is enabled', () => {
140+
mockGc.gcEnabledSetting.mockReturnValue(true);
141+
142+
const dispatch = jest.fn();
143+
const getters = {
144+
gcStores: [
145+
['cluster', {}],
146+
['management', {}],
147+
],
148+
};
149+
const ignoreTypes = ['some.type'];
150+
151+
gcActions.garbageCollect({
152+
rootState: {}, dispatch, getters
153+
}, ignoreTypes);
154+
155+
expect(dispatch).toHaveBeenCalledWith('cluster/garbageCollect', ignoreTypes);
156+
expect(dispatch).toHaveBeenCalledWith('management/garbageCollect', ignoreTypes);
157+
expect(dispatch).toHaveBeenCalledTimes(2);
158+
});
159+
160+
it('does not dispatch when gc setting is disabled', () => {
161+
mockGc.gcEnabledSetting.mockReturnValue(false);
162+
163+
const dispatch = jest.fn();
164+
165+
gcActions.garbageCollect({
166+
rootState: {}, dispatch, getters: { gcStores: [['cluster', {}]] }
167+
}, []);
168+
169+
expect(dispatch).not.toHaveBeenCalled();
170+
});
171+
172+
it('dispatches nothing when gcStores is empty even if setting is enabled', () => {
173+
mockGc.gcEnabledSetting.mockReturnValue(true);
174+
175+
const dispatch = jest.fn();
176+
177+
gcActions.garbageCollect({
178+
rootState: {}, dispatch, getters: { gcStores: [] }
179+
}, []);
180+
181+
expect(dispatch).not.toHaveBeenCalled();
182+
});
183+
});
184+
185+
describe('gcActions.gcPreferencesUpdated', () => {
186+
it('stops intervals and starts them when new preferences are enabled', () => {
187+
const dispatch = jest.fn();
188+
189+
gcActions.gcPreferencesUpdated({ dispatch }, {
190+
previouslyEnabled: false,
191+
newPreferences: { enabled: true },
192+
});
193+
194+
expect(dispatch).toHaveBeenCalledWith('gcStopIntervals', { root: true });
195+
expect(dispatch).toHaveBeenCalledWith('gcStartIntervals', { root: true });
196+
expect(dispatch).not.toHaveBeenCalledWith('gcResetStores', { root: true });
197+
});
198+
199+
it('stops intervals and resets stores when transitioning from enabled to disabled', () => {
200+
const dispatch = jest.fn();
201+
202+
gcActions.gcPreferencesUpdated({ dispatch }, {
203+
previouslyEnabled: true,
204+
newPreferences: { enabled: false },
205+
});
206+
207+
expect(dispatch).toHaveBeenCalledWith('gcStopIntervals', { root: true });
208+
expect(dispatch).toHaveBeenCalledWith('gcResetStores', { root: true });
209+
expect(dispatch).not.toHaveBeenCalledWith('gcStartIntervals', { root: true });
210+
});
211+
212+
it('stops intervals only when new preferences are disabled and was not previously enabled', () => {
213+
const dispatch = jest.fn();
214+
215+
gcActions.gcPreferencesUpdated({ dispatch }, {
216+
previouslyEnabled: false,
217+
newPreferences: { enabled: false },
218+
});
219+
220+
expect(dispatch).toHaveBeenCalledWith('gcStopIntervals', { root: true });
221+
expect(dispatch).not.toHaveBeenCalledWith('gcStartIntervals', { root: true });
222+
expect(dispatch).not.toHaveBeenCalledWith('gcResetStores', { root: true });
223+
});
224+
});
225+
});

0 commit comments

Comments
 (0)