From 08f427e476db3b2cb4b6ab82f42ffa9dbe4fa14d Mon Sep 17 00:00:00 2001 From: Janne Savolainen Date: Fri, 17 Mar 2023 15:41:18 +0200 Subject: [PATCH] Implement sending message to channel in main Signed-off-by: Janne Savolainen --- .../get-web-contents.injectable.ts | 10 +++ ...send-message-to-channel.injectable.test.ts | 85 +++++++++++++++++++ .../send-message-to-channel.injectable.ts | 38 +++++++++ 3 files changed, 133 insertions(+) create mode 100644 packages/technical-features/messaging/main/src/send-message-to-channel/get-web-contents.injectable.ts create mode 100644 packages/technical-features/messaging/main/src/send-message-to-channel/send-message-to-channel.injectable.test.ts create mode 100644 packages/technical-features/messaging/main/src/send-message-to-channel/send-message-to-channel.injectable.ts diff --git a/packages/technical-features/messaging/main/src/send-message-to-channel/get-web-contents.injectable.ts b/packages/technical-features/messaging/main/src/send-message-to-channel/get-web-contents.injectable.ts new file mode 100644 index 0000000000..5526782775 --- /dev/null +++ b/packages/technical-features/messaging/main/src/send-message-to-channel/get-web-contents.injectable.ts @@ -0,0 +1,10 @@ +import { getInjectable } from "@ogre-tools/injectable"; +import { webContents } from "electron"; + +const getWebContentsInjectable = getInjectable({ + id: "web-contents", + instantiate: () => () => webContents.getAllWebContents(), + causesSideEffects: true, +}); + +export default getWebContentsInjectable; diff --git a/packages/technical-features/messaging/main/src/send-message-to-channel/send-message-to-channel.injectable.test.ts b/packages/technical-features/messaging/main/src/send-message-to-channel/send-message-to-channel.injectable.test.ts new file mode 100644 index 0000000000..3c4d26c57f --- /dev/null +++ b/packages/technical-features/messaging/main/src/send-message-to-channel/send-message-to-channel.injectable.test.ts @@ -0,0 +1,85 @@ +import { registerFeature } from "@k8slens/feature-core"; +import { createContainer, DiContainer } from "@ogre-tools/injectable"; +import { messagingFeatureForMain } from "../feature"; +import { getMessageChannel, sendMessageToChannelInjectionToken } from "@k8slens/messaging"; +import getWebContentsInjectable from "./get-web-contents.injectable"; +import type { WebContents } from "electron"; + +const someChannel = getMessageChannel("some-channel"); + +describe("send-message-to-channel", () => { + let di: DiContainer; + + beforeEach(() => { + di = createContainer("irrelevant"); + + registerFeature(di, messagingFeatureForMain); + }); + + it("given no web contents, when sending a message, does not do anything", () => { + di.override(getWebContentsInjectable, () => () => []); + + const sendMessageToChannel = di.inject(sendMessageToChannelInjectionToken); + + expect(() => sendMessageToChannel(someChannel, "some-message")).not.toThrow(); + }); + + it("given multiple web contents, when sending a message, sends message to all web contents", () => { + const sendToWebContentsMock = jest.fn(); + + di.override(getWebContentsInjectable, () => () => [ + { + send: (...args: any[]) => sendToWebContentsMock("some-web-content", ...args), + isDestroyed: () => false, + isCrashed: () => false, + } as unknown as WebContents, + + { + send: (...args: any[]) => sendToWebContentsMock("some-other-web-content", ...args), + isDestroyed: () => false, + isCrashed: () => false, + } as unknown as WebContents, + ]); + + const sendMessageToChannel = di.inject(sendMessageToChannelInjectionToken); + + sendMessageToChannel(someChannel, "some-message"); + + expect(sendToWebContentsMock.mock.calls).toEqual([ + ["some-web-content", "some-channel", "some-message"], + ["some-other-web-content", "some-channel", "some-message"], + ]); + }); + + it("given non alive web content, when sending a message, sends message to all web contents being alive", () => { + const sendToWebContentsMock = jest.fn(); + + di.override(getWebContentsInjectable, () => () => [ + { + send: (...args: any[]) => sendToWebContentsMock("some-alive-content", ...args), + isDestroyed: () => false, + isCrashed: () => false, + } as unknown as WebContents, + + { + send: (...args: any[]) => sendToWebContentsMock("destroyed-web-content", ...args), + isDestroyed: () => true, + isCrashed: () => false, + } as unknown as WebContents, + + { + send: (...args: any[]) => sendToWebContentsMock("crashed-web-content", ...args), + isDestroyed: () => false, + isCrashed: () => true, + } as unknown as WebContents, + ]); + + const sendMessageToChannel = di.inject(sendMessageToChannelInjectionToken); + + sendMessageToChannel(someChannel, "some-message"); + + expect(sendToWebContentsMock.mock.calls).toEqual([ + ["some-alive-content", "some-channel", "some-message"], + ]); + }); +}); diff --git a/packages/technical-features/messaging/main/src/send-message-to-channel/send-message-to-channel.injectable.ts b/packages/technical-features/messaging/main/src/send-message-to-channel/send-message-to-channel.injectable.ts new file mode 100644 index 0000000000..a95fc3742b --- /dev/null +++ b/packages/technical-features/messaging/main/src/send-message-to-channel/send-message-to-channel.injectable.ts @@ -0,0 +1,38 @@ +import { getInjectable } from "@ogre-tools/injectable"; +import { pipeline } from "@ogre-tools/fp"; +import { SendMessageToChannel, sendMessageToChannelInjectionToken } from "@k8slens/messaging"; +import getWebContentsInjectable from "./get-web-contents.injectable"; +import { reject } from "lodash/fp"; +import type { WebContents } from "electron"; + +const isDestroyed = (webContent: WebContents) => webContent.isDestroyed(); +const isCrashed = (webContent: WebContents) => webContent.isCrashed(); + +const forEach = + (predicate: (item: T) => void) => + (items: T[]) => + items.forEach(predicate); + +const sendMessageToChannelInjectable = getInjectable({ + id: "send-message-to-channel", + + instantiate: (di) => { + const getWebContents = di.inject(getWebContentsInjectable); + + return ((channel, message) => { + pipeline( + getWebContents(), + reject(isDestroyed), + reject(isCrashed), + + forEach((webContent) => { + webContent.send(channel.id, message); + }), + ); + }) as SendMessageToChannel; + }, + + injectionToken: sendMessageToChannelInjectionToken, +}); + +export default sendMessageToChannelInjectable;