Skip to content

Commit 11a4e19

Browse files
committed
frontend: TopBar: Visual support for displaying authenticated users
Fetch and display authenticated user information per cluster in the user menu. Fallback to showing the cluster name if no user info is available. Update TopBar stories to reflect multi-user scenarios. Update e2e tests to match the new menu item structure. Signed-off-by: alokdangre <alokdangre@gmail.com>
1 parent d4e21f4 commit 11a4e19

File tree

16 files changed

+370
-124
lines changed

16 files changed

+370
-124
lines changed

e2e-tests/tests/headlampPage.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ export class HeadlampPage {
112112
await this.page.click('button[aria-label="Account of current user"]');
113113

114114
// Wait for the logout option to be visible and click on it
115-
await this.page.waitForSelector('a.MuiMenuItem-root:has-text("Log out")');
116-
await this.page.click('a.MuiMenuItem-root:has-text("Log out")');
115+
await this.page.waitForSelector('.MuiMenuItem-root:has-text("Log out")');
116+
await this.page.click('.MuiMenuItem-root:has-text("Log out")');
117117
await this.page.waitForLoadState('load');
118118

119119
// Expects the URL to contain c/test/token

frontend/src/components/App/TopBar.stories.tsx

Lines changed: 107 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { configureStore } from '@reduxjs/toolkit';
1818
import { Meta, StoryFn } from '@storybook/react';
1919
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
2020
import { get } from 'lodash';
21+
import { http, HttpResponse } from 'msw';
2122
import { PropsWithChildren } from 'react';
2223
import { Provider } from 'react-redux';
2324
import { MemoryRouter } from 'react-router-dom';
@@ -62,6 +63,7 @@ export default {
6263
);
6364
},
6465
],
66+
parameters: {},
6567
} as Meta;
6668

6769
function OurTopBar(args: PropsWithChildren<PureTopBarProps>) {
@@ -116,6 +118,16 @@ OneCluster.args = {
116118
cluster: 'ak8s-desktop',
117119
clusters: { 'ak8s-desktop': '' },
118120
};
121+
OneCluster.parameters = {
122+
msw: {
123+
handlers: [
124+
http.post(
125+
'http://localhost:4466/clusters/ak8s-desktop/apis/authentication.k8s.io/v1/selfsubjectreviews',
126+
() => HttpResponse.json({ status: { userInfo: { username: 'one-cluster-user' } } })
127+
),
128+
],
129+
},
130+
};
119131

120132
export const TwoCluster = PureTemplate.bind({});
121133
TwoCluster.args = {
@@ -131,9 +143,22 @@ WithUserInfo.args = {
131143
logout: () => {},
132144
cluster: 'ak8s-desktop',
133145
clusters: { 'ak8s-desktop': '' },
134-
userInfo: {
135-
username: 'Ada Lovelace',
136-
email: 'ada@example.com',
146+
};
147+
WithUserInfo.parameters = {
148+
msw: {
149+
handlers: [
150+
http.post(
151+
'http://localhost:4466/clusters/ak8s-desktop/apis/authentication.k8s.io/v1/selfsubjectreviews',
152+
() =>
153+
HttpResponse.json({
154+
status: {
155+
userInfo: {
156+
username: 'Ada Lovelace',
157+
},
158+
},
159+
})
160+
),
161+
],
137162
},
138163
};
139164

@@ -143,8 +168,22 @@ WithEmailOnly.args = {
143168
logout: () => {},
144169
cluster: 'ak8s-desktop',
145170
clusters: { 'ak8s-desktop': '' },
146-
userInfo: {
147-
email: 'grace@example.com',
171+
};
172+
WithEmailOnly.parameters = {
173+
msw: {
174+
handlers: [
175+
http.post(
176+
'http://localhost:4466/clusters/ak8s-desktop/apis/authentication.k8s.io/v1/selfsubjectreviews',
177+
() =>
178+
HttpResponse.json({
179+
status: {
180+
userInfo: {
181+
username: 'grace@example.com',
182+
},
183+
},
184+
})
185+
),
186+
],
148187
},
149188
};
150189

@@ -154,7 +193,17 @@ UndefinedData.args = {
154193
logout: () => {},
155194
cluster: 'ak8s-desktop',
156195
clusters: { 'ak8s-desktop': '' },
157-
userInfo: undefined,
196+
};
197+
UndefinedData.parameters = {
198+
msw: {
199+
handlers: [
200+
// Return 404 to simulate missing API or data
201+
http.post(
202+
'http://localhost:4466/clusters/ak8s-desktop/apis/authentication.k8s.io/v1/selfsubjectreviews',
203+
() => new HttpResponse(null, { status: 404 })
204+
),
205+
],
206+
},
158207
};
159208

160209
export const EmptyUserInfo = PureTemplate.bind({});
@@ -163,8 +212,57 @@ EmptyUserInfo.args = {
163212
logout: () => {},
164213
cluster: 'ak8s-desktop',
165214
clusters: { 'ak8s-desktop': '' },
166-
userInfo: {
167-
email: '',
168-
username: '',
215+
};
216+
EmptyUserInfo.parameters = {
217+
msw: {
218+
handlers: [
219+
http.post(
220+
'http://localhost:4466/clusters/ak8s-desktop/apis/authentication.k8s.io/v1/selfsubjectreviews',
221+
() => HttpResponse.json({})
222+
),
223+
],
224+
},
225+
};
226+
227+
export const MultiCluster = PureTemplate.bind({});
228+
MultiCluster.args = {
229+
appBarActions: [],
230+
logout: () => {},
231+
cluster: 'admin-cluster',
232+
clusters: {
233+
'admin-cluster': '',
234+
'view-cluster': '',
235+
'other-cluster': '',
236+
},
237+
selectedClusters: ['admin-cluster', 'view-cluster'],
238+
};
239+
MultiCluster.parameters = {
240+
msw: {
241+
handlers: [
242+
http.post(
243+
'http://localhost:4466/clusters/admin-cluster/apis/authentication.k8s.io/v1/selfsubjectreviews',
244+
() =>
245+
HttpResponse.json({
246+
status: {
247+
userInfo: {
248+
username: 'admin-user',
249+
groups: ['system:masters'],
250+
},
251+
},
252+
})
253+
),
254+
http.post(
255+
'http://localhost:4466/clusters/view-cluster/apis/authentication.k8s.io/v1/selfsubjectreviews',
256+
() =>
257+
HttpResponse.json({
258+
status: {
259+
userInfo: {
260+
username: 'view-user',
261+
groups: ['view-group'],
262+
},
263+
},
264+
})
265+
),
266+
],
169267
},
170268
};

0 commit comments

Comments
 (0)