refactor: fixed unsafe roles dialog and hook logic, added tests
This commit is contained in:
@@ -98,6 +98,7 @@ export interface Device {
|
||||
state: MessageState,
|
||||
) => void;
|
||||
setDialogOpen: (dialog: DialogVariant, open: boolean) => void;
|
||||
getDialogOpen: (dialog: DialogVariant) => boolean;
|
||||
processPacket: (data: ProcessPacketParams) => void;
|
||||
setMessageDraft: (message: string) => void;
|
||||
}
|
||||
@@ -597,6 +598,13 @@ export const useDeviceStore = createStore<DeviceState>((set, get) => ({
|
||||
}),
|
||||
);
|
||||
},
|
||||
getDialogOpen: (dialog: DialogVariant) => {
|
||||
const device = get().devices.get(id);
|
||||
if (!device) {
|
||||
throw new Error("Device not found");
|
||||
}
|
||||
return device.dialog[dialog];
|
||||
},
|
||||
processPacket(data: ProcessPacketParams) {
|
||||
set(
|
||||
produce<DeviceState>((draft) => {
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { eventBus } from "@core/utils/eventBus.ts";
|
||||
|
||||
describe("EventBus", () => {
|
||||
beforeEach(() => {
|
||||
// Reset event listeners before each test
|
||||
(eventBus as any).listeners = {};
|
||||
});
|
||||
|
||||
it("should register an event listener and trigger it on emit", () => {
|
||||
const mockCallback = vi.fn();
|
||||
|
||||
eventBus.on("dialog:unsafeRoles", mockCallback);
|
||||
eventBus.emit("dialog:unsafeRoles", { action: "confirm" });
|
||||
|
||||
expect(mockCallback).toHaveBeenCalledWith({ action: "confirm" });
|
||||
});
|
||||
|
||||
it("should remove an event listener with off", () => {
|
||||
const mockCallback = vi.fn();
|
||||
|
||||
eventBus.on("dialog:unsafeRoles", mockCallback);
|
||||
eventBus.off("dialog:unsafeRoles", mockCallback);
|
||||
eventBus.emit("dialog:unsafeRoles", { action: "dismiss" });
|
||||
|
||||
expect(mockCallback).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should return an unsubscribe function from on", () => {
|
||||
const mockCallback = vi.fn();
|
||||
const unsubscribe = eventBus.on("dialog:unsafeRoles", mockCallback);
|
||||
|
||||
unsubscribe();
|
||||
eventBus.emit("dialog:unsafeRoles", { action: "confirm" });
|
||||
|
||||
expect(mockCallback).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should allow multiple listeners for the same event", () => {
|
||||
const mockCallback1 = vi.fn();
|
||||
const mockCallback2 = vi.fn();
|
||||
|
||||
eventBus.on("dialog:unsafeRoles", mockCallback1);
|
||||
eventBus.on("dialog:unsafeRoles", mockCallback2);
|
||||
eventBus.emit("dialog:unsafeRoles", { action: "confirm" });
|
||||
|
||||
expect(mockCallback1).toHaveBeenCalledWith({ action: "confirm" });
|
||||
expect(mockCallback2).toHaveBeenCalledWith({ action: "confirm" });
|
||||
});
|
||||
|
||||
it("should only remove the specific listener when off is called", () => {
|
||||
const mockCallback1 = vi.fn();
|
||||
const mockCallback2 = vi.fn();
|
||||
|
||||
eventBus.on("dialog:unsafeRoles", mockCallback1);
|
||||
eventBus.on("dialog:unsafeRoles", mockCallback2);
|
||||
eventBus.off("dialog:unsafeRoles", mockCallback1);
|
||||
eventBus.emit("dialog:unsafeRoles", { action: "dismiss" });
|
||||
|
||||
expect(mockCallback1).not.toHaveBeenCalled();
|
||||
expect(mockCallback2).toHaveBeenCalledWith({ action: "dismiss" });
|
||||
});
|
||||
|
||||
it("should not fail when calling off on a non-existent listener", () => {
|
||||
const mockCallback = vi.fn();
|
||||
eventBus.off("dialog:unsafeRoles", mockCallback);
|
||||
eventBus.emit("dialog:unsafeRoles", { action: "confirm" });
|
||||
|
||||
expect(mockCallback).not.toHaveBeenCalled(); // No error should occur
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,44 @@
|
||||
export type EventMap = {
|
||||
'dialog:unsafeRoles': {
|
||||
action: 'confirm' | 'dismiss';
|
||||
};
|
||||
// add more events as required
|
||||
};
|
||||
|
||||
export type EventName = keyof EventMap;
|
||||
export type EventCallback<T extends EventName> = (data: EventMap[T]) => void;
|
||||
|
||||
class EventBus {
|
||||
private listeners: { [K in EventName]?: Array<EventCallback<K>> } = {};
|
||||
|
||||
public on<T extends EventName>(event: T, callback: EventCallback<T>): () => void {
|
||||
if (!this.listeners[event]) {
|
||||
this.listeners[event] = [];
|
||||
}
|
||||
|
||||
this.listeners[event]?.push(callback as any);
|
||||
|
||||
return () => {
|
||||
this.off(event, callback);
|
||||
};
|
||||
}
|
||||
|
||||
public off<T extends EventName>(event: T, callback: EventCallback<T>): void {
|
||||
if (!this.listeners[event]) return;
|
||||
|
||||
const callbackIndex = this.listeners[event]?.indexOf(callback as any);
|
||||
if (callbackIndex !== undefined && callbackIndex > -1) {
|
||||
this.listeners[event]?.splice(callbackIndex, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public emit<T extends EventName>(event: T, data: EventMap[T]): void {
|
||||
if (!this.listeners[event]) return;
|
||||
|
||||
this.listeners[event]?.forEach(callback => {
|
||||
callback(data);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const eventBus = new EventBus();
|
||||
Reference in New Issue
Block a user