Skip to content

Commit 4a58803

Browse files
momesginMo Mesgin
andauthored
replace hardcoded namespace with findLableSelector (#17753)
Co-authored-by: Mo Mesgin <mmesgin@Mos-M2-MacBook-Pro.local>
1 parent 86a3bab commit 4a58803

2 files changed

Lines changed: 215 additions & 6 deletions

File tree

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
import { nextTick } from 'vue';
2+
import { shallowMount } from '@vue/test-utils';
3+
import IstioOverview from '@shell/pages/c/_cluster/istio/index.vue';
4+
import { SERVICE } from '@shell/config/types';
5+
import Loading from '@shell/components/Loading';
6+
7+
const createMockService = (name: string, namespace: string, label: string, proxyUrlReturn: string) => ({
8+
id: `${ namespace }/${ name }`,
9+
type: 'service',
10+
metadata: {
11+
name,
12+
namespace,
13+
labels: { app: label },
14+
},
15+
proxyUrl: jest.fn(() => proxyUrlReturn),
16+
});
17+
18+
describe('page: IstioOverview', () => {
19+
const createWrapper = (overrides: Record<string, any> = {}) => {
20+
const mockDispatch = jest.fn();
21+
const mockSchemaFor = jest.fn();
22+
const mockResolve = jest.fn(() => ({ href: '/c/_/monitoring' }));
23+
24+
const defaultMocks = {
25+
$fetchState: { pending: false },
26+
$store: {
27+
dispatch: mockDispatch,
28+
getters: {
29+
'prefs/theme': 'dark',
30+
'i18n/t': (key: string) => key,
31+
'cluster/schemaFor': mockSchemaFor,
32+
},
33+
},
34+
$route: { params: { cluster: '_' } },
35+
$router: { resolve: mockResolve },
36+
};
37+
38+
const wrapper = shallowMount(IstioOverview, {
39+
global: {
40+
mocks: { ...defaultMocks, ...(overrides.mocks || {}) },
41+
directives: { 'clean-html': () => {} },
42+
stubs: { t: true, ...(overrides.stubs || {}) },
43+
},
44+
});
45+
46+
return {
47+
wrapper, mockDispatch, mockSchemaFor, mockResolve
48+
};
49+
};
50+
51+
describe('fetch', () => {
52+
it('dispatches findLabelSelector for kiali with correct label selector', async() => {
53+
const { wrapper, mockDispatch, mockSchemaFor } = createWrapper();
54+
55+
mockSchemaFor.mockReturnValue({});
56+
mockDispatch.mockResolvedValue({ data: [] });
57+
58+
await (IstioOverview as any).fetch.call(wrapper.vm);
59+
60+
expect(mockDispatch).toHaveBeenCalledWith('cluster/findLabelSelector', {
61+
type: SERVICE,
62+
matching: { labelSelector: { matchLabels: { app: 'kiali' } } },
63+
opt: { transient: true },
64+
});
65+
});
66+
67+
it('dispatches findLabelSelector for jaeger with correct label selector', async() => {
68+
const { wrapper, mockDispatch, mockSchemaFor } = createWrapper();
69+
70+
mockSchemaFor.mockReturnValue({});
71+
mockDispatch.mockResolvedValue({ data: [] });
72+
73+
await (IstioOverview as any).fetch.call(wrapper.vm);
74+
75+
expect(mockDispatch).toHaveBeenCalledWith('cluster/findLabelSelector', {
76+
type: SERVICE,
77+
matching: { labelSelector: { matchLabels: { app: 'jaeger' } } },
78+
opt: { transient: true },
79+
});
80+
});
81+
82+
it('sets kialiService and jaegerService from response data', async() => {
83+
const mockKiali = createMockService('kiali', 'istio-system', 'kiali', '/proxy/kiali');
84+
const mockJaeger = createMockService('jaeger-query', 'istio-system', 'jaeger', '/proxy/jaeger');
85+
const { wrapper, mockDispatch, mockSchemaFor } = createWrapper();
86+
87+
mockSchemaFor.mockReturnValue({});
88+
mockDispatch
89+
.mockResolvedValueOnce({ data: [mockKiali] })
90+
.mockResolvedValueOnce({ data: [mockJaeger] });
91+
92+
await (IstioOverview as any).fetch.call(wrapper.vm);
93+
94+
expect(wrapper.vm.kialiService).toStrictEqual(mockKiali);
95+
expect(wrapper.vm.jaegerService).toStrictEqual(mockJaeger);
96+
});
97+
98+
it('skips dispatches when schemaFor returns falsy', async() => {
99+
const { wrapper, mockDispatch, mockSchemaFor } = createWrapper();
100+
101+
mockSchemaFor.mockReturnValue(null);
102+
103+
await (IstioOverview as any).fetch.call(wrapper.vm);
104+
105+
expect(mockDispatch).not.toHaveBeenCalledWith('cluster/findLabelSelector', expect.anything());
106+
expect(wrapper.vm.kialiService).toBeNull();
107+
expect(wrapper.vm.jaegerService).toBeNull();
108+
});
109+
110+
it('sets services to null when response data is empty', async() => {
111+
const { wrapper, mockDispatch, mockSchemaFor } = createWrapper();
112+
113+
mockSchemaFor.mockReturnValue({});
114+
mockDispatch.mockResolvedValue({ data: [] });
115+
116+
await (IstioOverview as any).fetch.call(wrapper.vm);
117+
118+
expect(wrapper.vm.kialiService).toBeNull();
119+
expect(wrapper.vm.jaegerService).toBeNull();
120+
});
121+
});
122+
123+
describe('computed properties', () => {
124+
it('kialiUrl returns null when kialiService is null', () => {
125+
const { wrapper } = createWrapper();
126+
127+
expect(wrapper.vm.kialiUrl).toBeNull();
128+
});
129+
130+
it('kialiUrl calls proxyUrl with correct arguments when service exists', async() => {
131+
const mockKiali = createMockService('kiali', 'istio-system', 'kiali', '/proxy/kiali');
132+
const { wrapper } = createWrapper();
133+
134+
wrapper.setData({ kialiService: mockKiali });
135+
await nextTick();
136+
137+
expect(wrapper.vm.kialiUrl).toStrictEqual('/proxy/kiali');
138+
expect(mockKiali.proxyUrl).toHaveBeenCalledWith('http', '20001');
139+
});
140+
141+
it('jaegerUrl returns null when jaegerService is null', () => {
142+
const { wrapper } = createWrapper();
143+
144+
expect(wrapper.vm.jaegerUrl).toBeNull();
145+
});
146+
147+
it('jaegerUrl calls proxyUrl with correct arguments and appends /jaeger/search', async() => {
148+
const mockJaeger = createMockService('jaeger-query', 'istio-system', 'jaeger', '/proxy/jaeger');
149+
const { wrapper } = createWrapper();
150+
151+
wrapper.setData({ jaegerService: mockJaeger });
152+
await nextTick();
153+
154+
expect(wrapper.vm.jaegerUrl).toStrictEqual('/proxy/jaeger/jaeger/search');
155+
expect(mockJaeger.proxyUrl).toHaveBeenCalledWith('http', '16686');
156+
});
157+
});
158+
159+
describe('template rendering', () => {
160+
it('shows Loading component when fetchState is pending', () => {
161+
const { wrapper } = createWrapper({ mocks: { $fetchState: { pending: true } } });
162+
163+
expect(wrapper.findComponent(Loading).exists()).toBe(true);
164+
expect(wrapper.find('.links').exists()).toBe(false);
165+
});
166+
167+
it('shows disabled state when service URLs are null', () => {
168+
const { wrapper } = createWrapper();
169+
const containers = wrapper.findAll('.link-container');
170+
171+
expect(containers).toHaveLength(2);
172+
containers.forEach((container) => {
173+
expect(container.classes()).toContain('disabled');
174+
});
175+
expect(wrapper.findAll('.disabled-msg')).toHaveLength(2);
176+
});
177+
178+
it('hides disabled state when services are set', async() => {
179+
const mockKiali = createMockService('kiali', 'istio-system', 'kiali', '/proxy/kiali');
180+
const mockJaeger = createMockService('jaeger-query', 'istio-system', 'jaeger', '/proxy/jaeger');
181+
const { wrapper } = createWrapper();
182+
183+
wrapper.setData({ kialiService: mockKiali, jaegerService: mockJaeger });
184+
await nextTick();
185+
186+
const containers = wrapper.findAll('.link-container');
187+
188+
containers.forEach((container) => {
189+
expect(container.classes()).not.toContain('disabled');
190+
});
191+
expect(wrapper.findAll('.disabled-msg')).toHaveLength(0);
192+
});
193+
});
194+
});

shell/pages/c/_cluster/istio/index.vue

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,27 @@ export default {
88
components: { Loading },
99
1010
async fetch() {
11-
try {
12-
this.kialiService = await this.$store.dispatch('cluster/find', { type: SERVICE, id: 'istio-system/kiali' });
13-
} catch {}
14-
try {
15-
this.jaegerService = await this.$store.dispatch('cluster/find', { type: SERVICE, id: 'istio-system/tracing' });
16-
} catch {}
11+
if (this.$store.getters['cluster/schemaFor'](SERVICE)) {
12+
try {
13+
const kialiResponse = await this.$store.dispatch('cluster/findLabelSelector', {
14+
type: SERVICE,
15+
matching: { labelSelector: { matchLabels: { app: 'kiali' } } },
16+
opt: { transient: true }
17+
});
18+
19+
this.kialiService = kialiResponse.data?.[0] || null;
20+
} catch {}
21+
22+
try {
23+
const jaegerResponse = await this.$store.dispatch('cluster/findLabelSelector', {
24+
type: SERVICE,
25+
matching: { labelSelector: { matchLabels: { app: 'jaeger' } } },
26+
opt: { transient: true }
27+
});
28+
29+
this.jaegerService = jaegerResponse.data?.[0] || null;
30+
} catch {}
31+
}
1732
},
1833
1934
data() {

0 commit comments

Comments
 (0)