From eee8fb49e7abff4cc1ed44ced945cc5ac7e61886 Mon Sep 17 00:00:00 2001 From: Janne Savolainen Date: Thu, 19 May 2022 14:35:03 +0300 Subject: [PATCH] Make stuff happening when root frame is rendered unit testable Signed-off-by: Janne Savolainen --- ...end-to-agnostic-channel-injection-token.ts | 2 +- .../root-frame-rendered-channel.injectable.ts | 21 +++++++++++ .../catalog-sync-to-renderer.injectable.ts | 2 ++ src/main/getDiForUnitTesting.ts | 4 +++ .../start-kube-config-sync.injectable.ts | 2 ++ ...me-rendered-channel-listener.injectable.ts | 35 +++++++++++++++++++ .../test-utils/get-application-builder.tsx | 11 ++++++ ...-that-root-frame-is-rendered.injectable.ts | 22 ++++++++++++ src/renderer/frames/root-frame/root-frame.tsx | 23 +++++++++--- 9 files changed, 117 insertions(+), 5 deletions(-) create mode 100644 src/common/root-frame-rendered-channel/root-frame-rendered-channel.injectable.ts create mode 100644 src/main/start-main-application/runnables/root-frame-rendered-channel-listener/root-frame-rendered-channel-listener.injectable.ts create mode 100644 src/renderer/frames/root-frame/notify-that-root-frame-is-rendered.injectable.ts diff --git a/src/common/channel/send-to-agnostic-channel-injection-token.ts b/src/common/channel/send-to-agnostic-channel-injection-token.ts index ffb5719c32..6bc5b97107 100644 --- a/src/common/channel/send-to-agnostic-channel-injection-token.ts +++ b/src/common/channel/send-to-agnostic-channel-injection-token.ts @@ -7,7 +7,7 @@ import type { Channel } from "./channel-injection-token"; export type SendToAgnosticChannel = >( channel: TChannel, - message: TChannel["_messageTemplate"] + message?: TChannel["_messageTemplate"] ) => void; export const sendToAgnosticChannelInjectionToken = diff --git a/src/common/root-frame-rendered-channel/root-frame-rendered-channel.injectable.ts b/src/common/root-frame-rendered-channel/root-frame-rendered-channel.injectable.ts new file mode 100644 index 0000000000..ab16382f7a --- /dev/null +++ b/src/common/root-frame-rendered-channel/root-frame-rendered-channel.injectable.ts @@ -0,0 +1,21 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import type { Channel } from "../channel/channel-injection-token"; +import { channelInjectionToken } from "../channel/channel-injection-token"; + +export type RootFrameRenderedChannel = Channel; + +const rootFrameRenderedChannelInjectable = getInjectable({ + id: "root-frame-rendered-channel", + + instantiate: (): RootFrameRenderedChannel => ({ + id: "root-frame-rendered", + }), + + injectionToken: channelInjectionToken, +}); + +export default rootFrameRenderedChannelInjectable; diff --git a/src/main/catalog-sync-to-renderer/catalog-sync-to-renderer.injectable.ts b/src/main/catalog-sync-to-renderer/catalog-sync-to-renderer.injectable.ts index 37dfd2f7fd..7e588481a8 100644 --- a/src/main/catalog-sync-to-renderer/catalog-sync-to-renderer.injectable.ts +++ b/src/main/catalog-sync-to-renderer/catalog-sync-to-renderer.injectable.ts @@ -17,6 +17,8 @@ const catalogSyncToRendererInjectable = getInjectable({ startCatalogSyncToRenderer(catalogEntityRegistry), ); }, + + causesSideEffects: true, }); export default catalogSyncToRendererInjectable; diff --git a/src/main/getDiForUnitTesting.ts b/src/main/getDiForUnitTesting.ts index bd212e6144..e1ac3490ca 100644 --- a/src/main/getDiForUnitTesting.ts +++ b/src/main/getDiForUnitTesting.ts @@ -82,6 +82,8 @@ import publishIsConfiguredInjectable from "./update-app/publish-is-configured.in import checkForPlatformUpdatesInjectable from "./update-app/check-for-platform-updates/check-for-platform-updates.injectable"; import setUpdateOnQuitInjectable from "./electron-app/features/set-update-on-quit.injectable"; import downloadPlatformUpdateInjectable from "./update-app/download-platform-update/download-platform-update.injectable"; +import startCatalogSyncInjectable from "./catalog-sync-to-renderer/start-catalog-sync.injectable"; +import startKubeConfigSyncInjectable from "./start-main-application/runnables/kube-config-sync/start-kube-config-sync.injectable"; export function getDiForUnitTesting(opts: GetDiForUnitTestingOptions = {}) { const { @@ -190,6 +192,8 @@ const overrideRunnablesHavingSideEffects = (di: DiContainer) => { setupSystemCaInjectable, setupListenerForCurrentClusterFrameInjectable, setupRunnablesAfterWindowIsOpenedInjectable, + startCatalogSyncInjectable, + startKubeConfigSyncInjectable, ].forEach((injectable) => { di.override(injectable, () => ({ run: () => {} })); }); diff --git a/src/main/start-main-application/runnables/kube-config-sync/start-kube-config-sync.injectable.ts b/src/main/start-main-application/runnables/kube-config-sync/start-kube-config-sync.injectable.ts index d6d964c7df..80c725e17d 100644 --- a/src/main/start-main-application/runnables/kube-config-sync/start-kube-config-sync.injectable.ts +++ b/src/main/start-main-application/runnables/kube-config-sync/start-kube-config-sync.injectable.ts @@ -25,6 +25,8 @@ const startKubeConfigSyncInjectable = getInjectable({ }; }, + causesSideEffects: true, + injectionToken: afterRootFrameIsReadyInjectionToken, }); diff --git a/src/main/start-main-application/runnables/root-frame-rendered-channel-listener/root-frame-rendered-channel-listener.injectable.ts b/src/main/start-main-application/runnables/root-frame-rendered-channel-listener/root-frame-rendered-channel-listener.injectable.ts new file mode 100644 index 0000000000..ef9da6f6d7 --- /dev/null +++ b/src/main/start-main-application/runnables/root-frame-rendered-channel-listener/root-frame-rendered-channel-listener.injectable.ts @@ -0,0 +1,35 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { channelListenerInjectionToken } from "../../../../common/channel/channel-listener-injection-token"; +import rootFrameRenderedChannelInjectable from "../../../../common/root-frame-rendered-channel/root-frame-rendered-channel.injectable"; +import { runManyFor } from "../../../../common/runnable/run-many-for"; +import { afterRootFrameIsReadyInjectionToken } from "../../runnable-tokens/after-root-frame-is-ready-injection-token"; + +const rootFrameRenderedChannelListenerInjectable = getInjectable({ + id: "root-frame-rendered-channel-listener", + + instantiate: (di) => { + const channel = di.inject(rootFrameRenderedChannelInjectable); + + const runMany = runManyFor(di); + + const runRunnablesAfterRootFrameIsReady = runMany( + afterRootFrameIsReadyInjectionToken, + ); + + return { + channel, + + handler: async () => { + await runRunnablesAfterRootFrameIsReady(); + }, + }; + }, + + injectionToken: channelListenerInjectionToken, +}); + +export default rootFrameRenderedChannelListenerInjectable; diff --git a/src/renderer/components/test-utils/get-application-builder.tsx b/src/renderer/components/test-utils/get-application-builder.tsx index 19764b8408..4ac51dc4f6 100644 --- a/src/renderer/components/test-utils/get-application-builder.tsx +++ b/src/renderer/components/test-utils/get-application-builder.tsx @@ -48,6 +48,7 @@ import type { TrayMenuItem } from "../../../main/tray/tray-menu-item/tray-menu-i import electronTrayInjectable from "../../../main/tray/electron-tray/electron-tray.injectable"; import applicationWindowInjectable from "../../../main/start-main-application/lens-window/application-window/application-window.injectable"; import { Notifications } from "../notifications/notifications"; +import notifyThatRootFrameIsRenderedInjectable from "../../frames/root-frame/notify-that-root-frame-is-rendered.injectable"; type Callback = (dis: DiContainers) => void | Promise; @@ -89,6 +90,7 @@ interface DiContainers { interface Environment { renderSidebar: () => React.ReactNode; + beforeRender: () => void; onAllowKubeResource: () => void; } @@ -119,6 +121,12 @@ export const getApplicationBuilder = () => { application: { renderSidebar: () => null, + beforeRender: () => { + const nofifyThatRootFrameIsRendered = rendererDi.inject(notifyThatRootFrameIsRenderedInjectable); + + nofifyThatRootFrameIsRendered(); + }, + onAllowKubeResource: () => { throw new Error( "Tried to allow kube resource when environment is not cluster frame.", @@ -128,6 +136,7 @@ export const getApplicationBuilder = () => { clusterFrame: { renderSidebar: () => , + beforeRender: () => {}, onAllowKubeResource: () => {}, } as Environment, }; @@ -380,6 +389,8 @@ export const getApplicationBuilder = () => { await callback(dis); } + environment.beforeRender(); + rendered = render( {environment.renderSidebar()} diff --git a/src/renderer/frames/root-frame/notify-that-root-frame-is-rendered.injectable.ts b/src/renderer/frames/root-frame/notify-that-root-frame-is-rendered.injectable.ts new file mode 100644 index 0000000000..9f37e769b7 --- /dev/null +++ b/src/renderer/frames/root-frame/notify-that-root-frame-is-rendered.injectable.ts @@ -0,0 +1,22 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { sendToAgnosticChannelInjectionToken } from "../../../common/channel/send-to-agnostic-channel-injection-token"; +import rootFrameRenderedChannelInjectable from "../../../common/root-frame-rendered-channel/root-frame-rendered-channel.injectable"; + +const notifyThatRootFrameIsRenderedInjectable = getInjectable({ + id: "notify-that-root-frame-is-rendered", + + instantiate: (di) => { + const sendToAgnosticChannel = di.inject(sendToAgnosticChannelInjectionToken); + const rootFrameRenderedChannel = di.inject(rootFrameRenderedChannelInjectable); + + return () => { + sendToAgnosticChannel(rootFrameRenderedChannel); + }; + }, +}); + +export default notifyThatRootFrameIsRenderedInjectable; diff --git a/src/renderer/frames/root-frame/root-frame.tsx b/src/renderer/frames/root-frame/root-frame.tsx index 41fdea10ac..415a130e90 100644 --- a/src/renderer/frames/root-frame/root-frame.tsx +++ b/src/renderer/frames/root-frame/root-frame.tsx @@ -11,17 +11,21 @@ import { ErrorBoundary } from "../../components/error-boundary"; import { Notifications } from "../../components/notifications"; import { ConfirmDialog } from "../../components/confirm-dialog"; import { CommandContainer } from "../../components/command-palette/command-container"; -import { ipcRenderer } from "electron"; -import { IpcRendererNavigationEvents } from "../../navigation/events"; +import { withInjectables } from "@ogre-tools/injectable-react"; +import notifyThatRootFrameIsRenderedInjectable from "./notify-that-root-frame-is-rendered.injectable"; injectSystemCAs(); +interface Dependencies { + notifyThatRootFrameIsRendered: () => void; +} + @observer -export class RootFrame extends React.Component { +class NonInjectedRootFrame extends React.Component { static displayName = "RootFrame"; componentDidMount() { - ipcRenderer.send(IpcRendererNavigationEvents.LOADED); + this.props.notifyThatRootFrameIsRendered(); } render() { @@ -37,3 +41,14 @@ export class RootFrame extends React.Component { ); } } + +export const RootFrame = withInjectables( + NonInjectedRootFrame, + + { + getProps: (di, props) => ({ + notifyThatRootFrameIsRendered: di.inject(notifyThatRootFrameIsRenderedInjectable), + ...props, + }), + }, +);