diff --git a/src/app/Shared/Services/NotificationChannel.service.tsx b/src/app/Shared/Services/NotificationChannel.service.tsx index d3e747879c..ffcd717853 100644 --- a/src/app/Shared/Services/NotificationChannel.service.tsx +++ b/src/app/Shared/Services/NotificationChannel.service.tsx @@ -127,7 +127,7 @@ export class NotificationChannel { fn.apply(this.notifications, [ 'WebSocket connection lost', msg, - 'Client Status', + NotificationCategory.WsClientActivity, fn === this.notifications.info, ]); }, diff --git a/src/app/Shared/Services/Notifications.service.tsx b/src/app/Shared/Services/Notifications.service.tsx index e7f52707e4..9a61e65fe1 100644 --- a/src/app/Shared/Services/Notifications.service.tsx +++ b/src/app/Shared/Services/Notifications.service.tsx @@ -98,7 +98,12 @@ export class NotificationService { cryostatStatusNotifications(): Observable { return this.notifications().pipe( - map((a) => a.filter((n) => this.isJvmDiscovery(n) && !NotificationService.isProblemNotification(n))), + map((a) => + a.filter( + (n) => + (this.isWsClientActivity(n) || this.isJvmDiscovery(n)) && !NotificationService.isProblemNotification(n), + ), + ), ); } @@ -148,7 +153,11 @@ export class NotificationService { } private isActionNotification(n: Notification): boolean { - return !this.isJvmDiscovery(n) && !NotificationService.isProblemNotification(n); + return !this.isWsClientActivity(n) && !this.isJvmDiscovery(n) && !NotificationService.isProblemNotification(n); + } + + private isWsClientActivity(n: Notification): boolean { + return n.category === NotificationCategory.WsClientActivity; } private isJvmDiscovery(n: Notification): boolean { diff --git a/src/app/Shared/Services/api.types.ts b/src/app/Shared/Services/api.types.ts index 11cf9fa6f8..86cd9f6d77 100644 --- a/src/app/Shared/Services/api.types.ts +++ b/src/app/Shared/Services/api.types.ts @@ -537,6 +537,7 @@ export interface Notification { } export enum NotificationCategory { + WsClientActivity = 'WsClientActivity', TargetJvmDiscovery = 'TargetJvmDiscovery', ActiveRecordingCreated = 'ActiveRecordingCreated', ActiveRecordingStopped = 'ActiveRecordingStopped', diff --git a/src/app/Shared/Services/api.utils.ts b/src/app/Shared/Services/api.utils.ts index b4cc3df1a6..5eb3caf731 100644 --- a/src/app/Shared/Services/api.utils.ts +++ b/src/app/Shared/Services/api.utils.ts @@ -222,6 +222,19 @@ export const messageKeys = new Map([ }, } as NotificationMessageMapper, ], + [ + NotificationCategory.WsClientActivity, + { + variant: AlertVariant.info, + title: 'WebSocket Client Activity', + body: (evt) => { + const addr = Object.keys(evt.message)[0]; + const status = evt.message[addr]; + return `Client at ${addr} ${status}`; + }, + hidden: true, + } as NotificationMessageMapper, + ], [ NotificationCategory.ActiveRecordingCreated, { diff --git a/src/mirage/index.ts b/src/mirage/index.ts index 9bc8be6245..5de3574e1e 100644 --- a/src/mirage/index.ts +++ b/src/mirage/index.ts @@ -27,7 +27,25 @@ export const startMirage = ({ environment = 'development' } = {}) => { // Create a mock server socket to send notifications let websocket: Client; - wsServer.on('connection', (_) => {}); + wsServer.on('connection', (socket) => { + websocket = socket; + socket.on('message', (_) => { + socket.send( + JSON.stringify({ + meta: { + category: 'WsClientActivity', + type: { + type: 'application', + subtype: 'json', + }, + }, + message: { + '127.0.0.1': 'accepted', + }, + }), + ); + }); + }); // Create a MirageJS Server to intercept network requests return createServer({ diff --git a/src/test/Settings/NotificationControl.test.tsx b/src/test/Settings/NotificationControl.test.tsx index 290fa8e062..3c4779a352 100644 --- a/src/test/Settings/NotificationControl.test.tsx +++ b/src/test/Settings/NotificationControl.test.tsx @@ -147,14 +147,14 @@ describe('', () => { await user.click(expandButton); - const targetDiscovery = screen.getByLabelText('Target JVM Discovery'); - expect(targetDiscovery).toBeInTheDocument(); - expect(targetDiscovery).toBeVisible(); - expect(targetDiscovery).toBeChecked(); + const webSocketAct = screen.getByLabelText('WebSocket Client Activity'); + expect(webSocketAct).toBeInTheDocument(); + expect(webSocketAct).toBeVisible(); + expect(webSocketAct).toBeChecked(); - await user.click(targetDiscovery); + await user.click(webSocketAct); - expect(targetDiscovery).not.toBeChecked(); + expect(webSocketAct).not.toBeChecked(); expect(enableSwitch).not.toBeChecked(); }); }); diff --git a/src/test/Settings/__snapshots__/NotificationControl.test.tsx.snap b/src/test/Settings/__snapshots__/NotificationControl.test.tsx.snap index 81dc3ffc8d..1bbb529eaa 100644 --- a/src/test/Settings/__snapshots__/NotificationControl.test.tsx.snap +++ b/src/test/Settings/__snapshots__/NotificationControl.test.tsx.snap @@ -239,6 +239,45 @@ exports[` renders correctly 1`] = ` data-ouia-component-id="OUIA-Generated-Switch-2" data-ouia-component-type="PF4/Switch" data-ouia-safe={true} + htmlFor="WsClientActivity" + > + + + + + + +
+