Skip to content

Commit f4de8d0

Browse files
committed
Update use-echo.test.ts
1 parent 9a419b0 commit f4de8d0

File tree

1 file changed

+259
-0
lines changed

1 file changed

+259
-0
lines changed

packages/react/tests/use-echo.test.ts

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ vi.mock("laravel-echo", () => {
1010
leaveChannel: vi.fn(),
1111
listen: vi.fn(),
1212
stopListening: vi.fn(),
13+
notification: vi.fn(),
1314
};
1415

1516
const mockPublicChannel = {
@@ -854,3 +855,261 @@ describe("useEchoPresence hook", async () => {
854855
expect(result.current.channel).not.toBeNull();
855856
});
856857
});
858+
859+
describe("useEchoNotification hook", async () => {
860+
let echoModule: typeof import("../src/hooks/use-echo");
861+
let configModule: typeof import("../src/config/index");
862+
let echoInstance: Echo<"null">;
863+
864+
beforeEach(async () => {
865+
vi.resetModules();
866+
867+
echoInstance = new Echo({
868+
broadcaster: "null",
869+
});
870+
871+
echoModule = await getEchoModule();
872+
configModule = await getConfigModule();
873+
874+
configModule.configureEcho({
875+
broadcaster: "null",
876+
});
877+
});
878+
879+
afterEach(() => {
880+
vi.clearAllMocks();
881+
});
882+
883+
it("subscribes to a private channel and listens for notifications", async () => {
884+
const mockCallback = vi.fn();
885+
const channelName = "test-channel";
886+
887+
const { result } = renderHook(() =>
888+
echoModule.useEchoNotification(channelName, mockCallback),
889+
);
890+
891+
expect(result.current).toHaveProperty("leaveChannel");
892+
expect(typeof result.current.leave).toBe("function");
893+
expect(result.current).toHaveProperty("leave");
894+
expect(typeof result.current.leaveChannel).toBe("function");
895+
expect(result.current).toHaveProperty("listen");
896+
expect(typeof result.current.listen).toBe("function");
897+
expect(result.current).toHaveProperty("stopListening");
898+
expect(typeof result.current.stopListening).toBe("function");
899+
});
900+
901+
it("sets up a notification listener on a channel", async () => {
902+
const mockCallback = vi.fn();
903+
const channelName = "test-channel";
904+
905+
renderHook(() =>
906+
echoModule.useEchoNotification(channelName, mockCallback),
907+
);
908+
909+
expect(echoInstance.private).toHaveBeenCalledWith(channelName);
910+
911+
const channel = echoInstance.private(channelName);
912+
expect(channel.notification).toHaveBeenCalled();
913+
});
914+
915+
it("handles notification filtering by event type", async () => {
916+
const mockCallback = vi.fn();
917+
const channelName = "test-channel";
918+
const eventType = "specific-type";
919+
920+
renderHook(() =>
921+
echoModule.useEchoNotification(
922+
channelName,
923+
mockCallback,
924+
eventType,
925+
),
926+
);
927+
928+
const channel = echoInstance.private(channelName);
929+
expect(channel.notification).toHaveBeenCalled();
930+
931+
const notificationCallback = vi.mocked(channel.notification).mock
932+
.calls[0][0];
933+
934+
const matchingNotification = {
935+
type: eventType,
936+
data: { message: "test" },
937+
};
938+
const nonMatchingNotification = {
939+
type: "other-type",
940+
data: { message: "test" },
941+
};
942+
943+
notificationCallback(matchingNotification);
944+
notificationCallback(nonMatchingNotification);
945+
946+
expect(mockCallback).toHaveBeenCalledWith(matchingNotification);
947+
expect(mockCallback).toHaveBeenCalledTimes(1);
948+
expect(mockCallback).not.toHaveBeenCalledWith(nonMatchingNotification);
949+
});
950+
951+
it("handles multiple notification event types", async () => {
952+
const mockCallback = vi.fn();
953+
const channelName = "test-channel";
954+
const events = ["type1", "type2"];
955+
956+
renderHook(() =>
957+
echoModule.useEchoNotification(channelName, mockCallback, events),
958+
);
959+
960+
const channel = echoInstance.private(channelName);
961+
expect(channel.notification).toHaveBeenCalled();
962+
963+
const notificationCallback = vi.mocked(channel.notification).mock
964+
.calls[0][0];
965+
966+
const notification1 = { type: events[0], data: {} };
967+
const notification2 = { type: events[1], data: {} };
968+
const notification3 = { type: "type3", data: {} };
969+
970+
notificationCallback(notification1);
971+
notificationCallback(notification2);
972+
notificationCallback(notification3);
973+
974+
expect(mockCallback).toHaveBeenCalledWith(notification1);
975+
expect(mockCallback).toHaveBeenCalledWith(notification2);
976+
expect(mockCallback).toHaveBeenCalledTimes(2);
977+
expect(mockCallback).not.toHaveBeenCalledWith(notification3);
978+
});
979+
980+
it("accepts all notifications when no event types specified", async () => {
981+
const mockCallback = vi.fn();
982+
const channelName = "test-channel";
983+
984+
renderHook(() =>
985+
echoModule.useEchoNotification(channelName, mockCallback),
986+
);
987+
988+
const channel = echoInstance.private(channelName);
989+
expect(channel.notification).toHaveBeenCalled();
990+
991+
const notificationCallback = vi.mocked(channel.notification).mock
992+
.calls[0][0];
993+
994+
const notification1 = { type: "type1", data: {} };
995+
const notification2 = { type: "type2", data: {} };
996+
997+
notificationCallback(notification1);
998+
notificationCallback(notification2);
999+
1000+
expect(mockCallback).toHaveBeenCalledWith(notification1);
1001+
expect(mockCallback).toHaveBeenCalledWith(notification2);
1002+
1003+
expect(mockCallback).toHaveBeenCalledTimes(2);
1004+
});
1005+
1006+
it("cleans up subscriptions on unmount", async () => {
1007+
const mockCallback = vi.fn();
1008+
const channelName = "test-channel";
1009+
1010+
const { unmount } = renderHook(() =>
1011+
echoModule.useEchoNotification(channelName, mockCallback),
1012+
);
1013+
1014+
expect(echoInstance.private).toHaveBeenCalledWith(channelName);
1015+
1016+
expect(() => unmount()).not.toThrow();
1017+
1018+
expect(echoInstance.leaveChannel).toHaveBeenCalledWith(
1019+
`private-${channelName}`,
1020+
);
1021+
});
1022+
1023+
it("won't subscribe multiple times to the same channel", async () => {
1024+
const mockCallback = vi.fn();
1025+
const channelName = "test-channel";
1026+
1027+
const { unmount: unmount1 } = renderHook(() =>
1028+
echoModule.useEchoNotification(channelName, mockCallback),
1029+
);
1030+
1031+
const { unmount: unmount2 } = renderHook(() =>
1032+
echoModule.useEchoNotification(channelName, mockCallback),
1033+
);
1034+
1035+
expect(echoInstance.private).toHaveBeenCalledTimes(1);
1036+
1037+
expect(() => unmount1()).not.toThrow();
1038+
expect(echoInstance.leaveChannel).not.toHaveBeenCalled();
1039+
1040+
expect(() => unmount2()).not.toThrow();
1041+
expect(echoInstance.leaveChannel).toHaveBeenCalledWith(
1042+
`private-${channelName}`,
1043+
);
1044+
});
1045+
1046+
it("can leave a channel", async () => {
1047+
const mockCallback = vi.fn();
1048+
const channelName = "test-channel";
1049+
1050+
const { result } = renderHook(() =>
1051+
echoModule.useEchoNotification(channelName, mockCallback),
1052+
);
1053+
1054+
result.current.leaveChannel();
1055+
1056+
expect(echoInstance.leaveChannel).toHaveBeenCalledWith(
1057+
`private-${channelName}`,
1058+
);
1059+
});
1060+
1061+
it("can leave all channel variations", async () => {
1062+
const mockCallback = vi.fn();
1063+
const channelName = "test-channel";
1064+
1065+
const { result } = renderHook(() =>
1066+
echoModule.useEchoNotification(channelName, mockCallback),
1067+
);
1068+
1069+
result.current.leave();
1070+
1071+
expect(echoInstance.leave).toHaveBeenCalledWith(channelName);
1072+
});
1073+
1074+
it("can manually start and stop listening", async () => {
1075+
const mockCallback = vi.fn();
1076+
const channelName = "test-channel";
1077+
1078+
const { result } = renderHook(() =>
1079+
echoModule.useEchoNotification(channelName, mockCallback),
1080+
);
1081+
1082+
const channel = echoInstance.private(channelName);
1083+
expect(channel.notification).toHaveBeenCalledTimes(1);
1084+
1085+
result.current.stopListening();
1086+
result.current.listen();
1087+
1088+
expect(channel.notification).toHaveBeenCalledTimes(1);
1089+
});
1090+
1091+
it("stopListening prevents new notification listeners", async () => {
1092+
const mockCallback = vi.fn();
1093+
const channelName = "test-channel";
1094+
1095+
const { result } = renderHook(() =>
1096+
echoModule.useEchoNotification(channelName, mockCallback),
1097+
);
1098+
1099+
result.current.stopListening();
1100+
1101+
expect(result.current.stopListening).toBeDefined();
1102+
expect(typeof result.current.stopListening).toBe("function");
1103+
});
1104+
1105+
it("callback and events are optional", async () => {
1106+
const channelName = "test-channel";
1107+
1108+
const { result } = renderHook(() =>
1109+
echoModule.useEchoNotification(channelName),
1110+
);
1111+
1112+
expect(result.current).toHaveProperty("channel");
1113+
expect(result.current.channel).not.toBeNull();
1114+
});
1115+
});

0 commit comments

Comments
 (0)