diff --git a/src/behaviours/application-update/analytics-for-installing-update.test.ts b/src/behaviours/application-update/analytics-for-installing-update.test.ts index b72946f80d..7f451b0076 100644 --- a/src/behaviours/application-update/analytics-for-installing-update.test.ts +++ b/src/behaviours/application-update/analytics-for-installing-update.test.ts @@ -21,7 +21,7 @@ import periodicalCheckForUpdatesInjectable from "../../main/application-update/p import { advanceFakeTime, useFakeTime } from "../../common/test-utils/use-fake-time"; describe("analytics for installing update", () => { - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; let checkForPlatformUpdatesMock: AsyncFnMock; let downloadPlatformUpdateMock: AsyncFnMock; let analyticsListenerMock: jest.Mock; @@ -30,11 +30,11 @@ describe("analytics for installing update", () => { beforeEach(async () => { useFakeTime("2015-10-21T07:28:00Z"); - applicationBuilder = getApplicationBuilder(); + builder = getApplicationBuilder(); analyticsListenerMock = jest.fn(); - applicationBuilder.beforeApplicationStart(({ mainDi }) => { + builder.beforeApplicationStart(mainDi => { mainDi.override(appVersionInjectable, () => "42.0.0"); checkForPlatformUpdatesMock = asyncFn(); @@ -56,7 +56,7 @@ describe("analytics for installing update", () => { eventBus.addListener(analyticsListenerMock); }); - mainDi = applicationBuilder.dis.mainDi; + mainDi = builder.mainDi; }); describe("given application is started and checking updates periodically", () => { @@ -64,7 +64,7 @@ describe("analytics for installing update", () => { mainDi.unoverride(periodicalCheckForUpdatesInjectable); mainDi.permitSideEffects(periodicalCheckForUpdatesInjectable); - await applicationBuilder.render(); + await builder.render(); }); @@ -101,7 +101,7 @@ describe("analytics for installing update", () => { beforeEach(async () => { analyticsListenerMock.mockClear(); - await applicationBuilder.render(); + await builder.render(); }); it("sends event to analytics about the current version", () => { @@ -119,7 +119,7 @@ describe("analytics for installing update", () => { it("when checking for updates using tray, sends event to analytics for being checked from tray", async () => { analyticsListenerMock.mockClear(); - applicationBuilder.tray.click("check-for-updates"); + builder.tray.click("check-for-updates"); expect(analyticsListenerMock.mock.calls).toEqual([ [ @@ -140,7 +140,7 @@ describe("analytics for installing update", () => { it("when checking for updates using application menu, sends event to analytics for being checked from application menu", async () => { analyticsListenerMock.mockClear(); - applicationBuilder.applicationMenu.click("root.check-for-updates"); + builder.applicationMenu.click("root.check-for-updates"); expect(analyticsListenerMock.mock.calls).toEqual([ [ diff --git a/src/behaviours/application-update/downgrading-version-update.test.ts b/src/behaviours/application-update/downgrading-version-update.test.ts index b50d9c940b..0462bee3d4 100644 --- a/src/behaviours/application-update/downgrading-version-update.test.ts +++ b/src/behaviours/application-update/downgrading-version-update.test.ts @@ -24,7 +24,7 @@ describe("downgrading version update", () => { beforeEach(() => { applicationBuilder = getApplicationBuilder(); - applicationBuilder.beforeApplicationStart(({ mainDi }) => { + applicationBuilder.beforeApplicationStart(mainDi => { checkForPlatformUpdatesMock = asyncFn(); mainDi.override( @@ -36,7 +36,7 @@ describe("downgrading version update", () => { mainDi.override(publishIsConfiguredInjectable, () => true); }); - mainDi = applicationBuilder.dis.mainDi; + mainDi = applicationBuilder.mainDi; }); [ diff --git a/src/behaviours/application-update/force-user-to-update-when-too-long-time-since-update-was-downloaded.test.ts b/src/behaviours/application-update/force-user-to-update-when-too-long-time-since-update-was-downloaded.test.ts index df46617467..ba8380e7b5 100644 --- a/src/behaviours/application-update/force-user-to-update-when-too-long-time-since-update-was-downloaded.test.ts +++ b/src/behaviours/application-update/force-user-to-update-when-too-long-time-since-update-was-downloaded.test.ts @@ -35,10 +35,7 @@ describe("force user to update when too long since update was downloaded", () => applicationBuilder = getApplicationBuilder(); - applicationBuilder.beforeApplicationStart(({ mainDi, rendererDi }) => { - rendererDi.unoverride(forceUpdateModalRootFrameComponentInjectable); - rendererDi.permitSideEffects(forceUpdateModalRootFrameComponentInjectable); - + applicationBuilder.beforeApplicationStart(mainDi => { checkForPlatformUpdatesMock = asyncFn(); mainDi.override(checkForPlatformUpdatesInjectable, () => checkForPlatformUpdatesMock); @@ -50,13 +47,17 @@ describe("force user to update when too long since update was downloaded", () => quitAndInstallUpdateMock = jest.fn(); mainDi.override(quitAndInstallUpdateInjectable, () => quitAndInstallUpdateMock); - - rendererDi.override(timeAfterUpdateMustBeInstalledInjectable, () => TIME_AFTER_UPDATE_MUST_BE_INSTALLED); - - rendererDi.override(secondsAfterInstallStartsInjectable, () => TIME_AFTER_INSTALL_STARTS / 1000); }); - mainDi = applicationBuilder.dis.mainDi; + applicationBuilder.beforeWindowStart(windowDi => { + windowDi.unoverride(forceUpdateModalRootFrameComponentInjectable); + windowDi.permitSideEffects(forceUpdateModalRootFrameComponentInjectable); + + windowDi.override(timeAfterUpdateMustBeInstalledInjectable, () => TIME_AFTER_UPDATE_MUST_BE_INSTALLED); + windowDi.override(secondsAfterInstallStartsInjectable, () => TIME_AFTER_INSTALL_STARTS / 1000); + }); + + mainDi = applicationBuilder.mainDi; }); describe("when application is started", () => { diff --git a/src/behaviours/application-update/installing-update-using-topbar-button.test.tsx b/src/behaviours/application-update/installing-update-using-topbar-button.test.tsx index c6ff69d145..5e5500498b 100644 --- a/src/behaviours/application-update/installing-update-using-topbar-button.test.tsx +++ b/src/behaviours/application-update/installing-update-using-topbar-button.test.tsx @@ -33,7 +33,7 @@ describe("encourage user to update when sufficient time passed since update was applicationBuilder = getApplicationBuilder(); - applicationBuilder.beforeApplicationStart(({ mainDi }) => { + applicationBuilder.beforeApplicationStart((mainDi) => { checkForPlatformUpdatesMock = asyncFn(); downloadPlatformUpdateMock = asyncFn(); @@ -76,7 +76,7 @@ describe("encourage user to update when sufficient time passed since update was let processCheckingForUpdates: (source: string) => Promise<{ updateIsReadyToBeInstalled: boolean }>; beforeEach(async () => { - processCheckingForUpdates = applicationBuilder.dis.mainDi.inject( + processCheckingForUpdates = applicationBuilder.mainDi.inject( processCheckingForUpdatesInjectable, ); @@ -105,8 +105,15 @@ describe("encourage user to update when sufficient time passed since update was expect(button).toHaveAttribute("data-warning-level", "light"); }); - // TODO: Implement after starting main and renderer is separated in ApplicationBuilder - xit("given closing the application window, when starting the application window again, still shows the button", () => { + it("given closing the application window, when starting the application window again, still shows the button", async () => { + applicationBuilder.applicationWindow.closeAll(); + + const window = applicationBuilder.applicationWindow.create("some-window-id"); + + await window.start(); + + const button = window.rendered.queryByTestId("update-button"); + expect(button).toBeInTheDocument(); }); diff --git a/src/behaviours/application-update/installing-update-using-tray.test.ts b/src/behaviours/application-update/installing-update-using-tray.test.ts index 1f8bf8992c..9bcb140638 100644 --- a/src/behaviours/application-update/installing-update-using-tray.test.ts +++ b/src/behaviours/application-update/installing-update-using-tray.test.ts @@ -13,19 +13,18 @@ import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; import type { DownloadPlatformUpdate } from "../../main/application-update/download-platform-update/download-platform-update.injectable"; import downloadPlatformUpdateInjectable from "../../main/application-update/download-platform-update/download-platform-update.injectable"; -import closeAllWindowsInjectable from "../../main/start-main-application/lens-window/hide-all-windows/close-all-windows.injectable"; -import applicationWindowInjectable from "../../main/start-main-application/lens-window/application-window/application-window.injectable"; -import type { LensWindow } from "../../main/start-main-application/lens-window/application-window/lens-window-injection-token"; +import type { LensWindow } from "../../main/start-main-application/lens-window/application-window/create-lens-window.injectable"; +import getCurrentApplicationWindowInjectable from "../../main/start-main-application/lens-window/application-window/get-current-application-window.injectable"; describe("installing update using tray", () => { - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; let checkForPlatformUpdatesMock: AsyncFnMock; let downloadPlatformUpdateMock: AsyncFnMock; beforeEach(() => { - applicationBuilder = getApplicationBuilder(); + builder = getApplicationBuilder(); - applicationBuilder.beforeApplicationStart(({ mainDi }) => { + builder.beforeApplicationStart((mainDi) => { checkForPlatformUpdatesMock = asyncFn(); downloadPlatformUpdateMock = asyncFn(); @@ -48,7 +47,7 @@ describe("installing update using tray", () => { let rendered: RenderResult; beforeEach(async () => { - rendered = await applicationBuilder.render(); + rendered = await builder.render(); }); it("renders", () => { @@ -56,23 +55,20 @@ describe("installing update using tray", () => { }); it("user cannot install update yet", () => { - expect(applicationBuilder.tray.get("install-update")).toBeNull(); + expect(builder.tray.get("install-update")).toBeNull(); }); describe("given all application windows are closed, when checking for updates", () => { - let applicationWindow: LensWindow; - let closeAllWindows: () => void; + let getCurrentApplicationWindow: () => LensWindow | undefined; beforeEach(() => { - const mainDi = applicationBuilder.dis.mainDi; + getCurrentApplicationWindow = builder.mainDi.inject( + getCurrentApplicationWindowInjectable, + ); - closeAllWindows = mainDi.inject(closeAllWindowsInjectable); + builder.applicationWindow.closeAll(); - applicationWindow = mainDi.inject(applicationWindowInjectable); - - closeAllWindows(); - - applicationBuilder.tray.click("check-for-updates"); + builder.tray.click("check-for-updates"); }); describe("when check for update resolves with new update", () => { @@ -84,37 +80,44 @@ describe("installing update using tray", () => { }); it("does not show application window yet", () => { - expect(applicationWindow.isVisible).toBe(false); + const actual = getCurrentApplicationWindow(); + + expect(actual).toBeUndefined(); }); describe("when download of update resolves with success", () => { beforeEach(async () => { - await downloadPlatformUpdateMock.resolve({ downloadWasSuccessful: true }); }); it("shows the application window", () => { - expect(applicationWindow.isVisible).toBe(true); + const actual = getCurrentApplicationWindow(); + + expect(actual).not.toBeUndefined(); }); it("given closing application window again and checking for updates again using tray, when check resolves with same version that was earlier downloaded, shows the application window", async () => { - closeAllWindows(); + builder.applicationWindow.closeAll(); - applicationBuilder.tray.click("check-for-updates"); + builder.tray.click("check-for-updates"); await checkForPlatformUpdatesMock.resolve({ updateWasDiscovered: true, version: "some-version", }); - expect(applicationWindow.isVisible).toBe(true); + const actual = getCurrentApplicationWindow(); + + expect(actual).not.toBeUndefined(); }); }); it("when download of update resolves with failure, does not show the application window", async () => { await downloadPlatformUpdateMock.resolve({ downloadWasSuccessful: false }); - expect(applicationWindow.isVisible).toBe(false); + const actual = getCurrentApplicationWindow(); + + expect(actual).toBeUndefined(); }); }); @@ -123,29 +126,31 @@ describe("installing update using tray", () => { updateWasDiscovered: false, }); - expect(applicationWindow.isVisible).toBe(false); + const actual = getCurrentApplicationWindow(); + + expect(actual).toBeUndefined(); }); }); describe("when user checks for updates using tray", () => { beforeEach(() => { - applicationBuilder.tray.click("check-for-updates"); + builder.tray.click("check-for-updates"); }); it("user cannot check for updates again", () => { expect( - applicationBuilder.tray.get("check-for-updates")?.enabled, + builder.tray.get("check-for-updates")?.enabled, ).toBe(false); }); it("name of tray item for checking updates indicates that checking is happening", () => { expect( - applicationBuilder.tray.get("check-for-updates")?.label, + builder.tray.get("check-for-updates")?.label, ).toBe("Checking for updates..."); }); it("user cannot install update yet", () => { - expect(applicationBuilder.tray.get("install-update")).toBeNull(); + expect(builder.tray.get("install-update")).toBeNull(); }); it("renders", () => { @@ -160,18 +165,18 @@ describe("installing update using tray", () => { }); it("user cannot install update", () => { - expect(applicationBuilder.tray.get("install-update")).toBeNull(); + expect(builder.tray.get("install-update")).toBeNull(); }); it("user can check for updates again", () => { expect( - applicationBuilder.tray.get("check-for-updates")?.enabled, + builder.tray.get("check-for-updates")?.enabled, ).toBe(true); }); it("name of tray item for checking updates no longer indicates that checking is happening", () => { expect( - applicationBuilder.tray.get("check-for-updates")?.label, + builder.tray.get("check-for-updates")?.label, ).toBe("Check for updates"); }); @@ -190,13 +195,13 @@ describe("installing update using tray", () => { it("user cannot check for updates again yet", () => { expect( - applicationBuilder.tray.get("check-for-updates")?.enabled, + builder.tray.get("check-for-updates")?.enabled, ).toBe(false); }); it("name of tray item for checking updates indicates that downloading is happening", () => { expect( - applicationBuilder.tray.get("check-for-updates")?.label, + builder.tray.get("check-for-updates")?.label, ).toBe("Downloading update some-version (0%)..."); }); @@ -204,12 +209,12 @@ describe("installing update using tray", () => { downloadPlatformUpdateMock.mock.calls[0][0]({ percentage: 42.424242 }); expect( - applicationBuilder.tray.get("check-for-updates")?.label, + builder.tray.get("check-for-updates")?.label, ).toBe("Downloading update some-version (42%)..."); }); it("user still cannot install update", () => { - expect(applicationBuilder.tray.get("install-update")).toBeNull(); + expect(builder.tray.get("install-update")).toBeNull(); }); it("renders", () => { @@ -223,19 +228,19 @@ describe("installing update using tray", () => { it("user cannot install update", () => { expect( - applicationBuilder.tray.get("install-update"), + builder.tray.get("install-update"), ).toBeNull(); }); it("user can check for updates again", () => { expect( - applicationBuilder.tray.get("check-for-updates")?.enabled, + builder.tray.get("check-for-updates")?.enabled, ).toBe(true); }); it("name of tray item for checking updates no longer indicates that downloading is happening", () => { expect( - applicationBuilder.tray.get("check-for-updates")?.label, + builder.tray.get("check-for-updates")?.label, ).toBe("Check for updates"); }); @@ -251,19 +256,19 @@ describe("installing update using tray", () => { it("user can install update", () => { expect( - applicationBuilder.tray.get("install-update")?.label, + builder.tray.get("install-update")?.label, ).toBe("Install update some-version"); }); it("user can check for updates again", () => { expect( - applicationBuilder.tray.get("check-for-updates")?.enabled, + builder.tray.get("check-for-updates")?.enabled, ).toBe(true); }); it("name of tray item for checking updates no longer indicates that downloading is happening", () => { expect( - applicationBuilder.tray.get("check-for-updates")?.label, + builder.tray.get("check-for-updates")?.label, ).toBe("Check for updates"); }); diff --git a/src/behaviours/application-update/installing-update.test.ts b/src/behaviours/application-update/installing-update.test.ts index efc7da8498..7063fcfaa1 100644 --- a/src/behaviours/application-update/installing-update.test.ts +++ b/src/behaviours/application-update/installing-update.test.ts @@ -20,7 +20,7 @@ import { useFakeTime } from "../../common/test-utils/use-fake-time"; import staticFilesDirectoryInjectable from "../../common/vars/static-files-directory.injectable"; describe("installing update", () => { - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; let quitAndInstallUpdateMock: jest.Mock; let checkForPlatformUpdatesMock: AsyncFnMock; let downloadPlatformUpdateMock: AsyncFnMock; @@ -29,9 +29,9 @@ describe("installing update", () => { beforeEach(() => { useFakeTime("2015-10-21T07:28:00Z"); - applicationBuilder = getApplicationBuilder(); + builder = getApplicationBuilder(); - applicationBuilder.beforeApplicationStart(({ mainDi }) => { + builder.beforeApplicationStart((mainDi) => { quitAndInstallUpdateMock = jest.fn(); checkForPlatformUpdatesMock = asyncFn(); downloadPlatformUpdateMock = asyncFn(); @@ -66,9 +66,9 @@ describe("installing update", () => { let processCheckingForUpdates: (source: string) => Promise<{ updateIsReadyToBeInstalled: boolean }>; beforeEach(async () => { - rendered = await applicationBuilder.render(); + rendered = await builder.render(); - processCheckingForUpdates = applicationBuilder.dis.mainDi.inject( + processCheckingForUpdates = builder.mainDi.inject( processCheckingForUpdatesInjectable, ); }); @@ -78,7 +78,7 @@ describe("installing update", () => { }); it("shows normal tray icon", () => { - expect(applicationBuilder.tray.getIconPath()).toBe( + expect(builder.tray.getIconPath()).toBe( "/some-static-files-directory/icons/trayIconTemplate.png", ); }); @@ -96,7 +96,7 @@ describe("installing update", () => { }); it("shows tray icon for checking for updates", () => { - expect(applicationBuilder.tray.getIconPath()).toBe( + expect(builder.tray.getIconPath()).toBe( "/some-static-files-directory/icons/trayIconCheckingForUpdatesTemplate.png", ); }); @@ -113,7 +113,7 @@ describe("installing update", () => { }); it("shows tray icon for normal", () => { - expect(applicationBuilder.tray.getIconPath()).toBe( + expect(builder.tray.getIconPath()).toBe( "/some-static-files-directory/icons/trayIconTemplate.png", ); }); @@ -140,7 +140,7 @@ describe("installing update", () => { }); it("still shows tray icon for downloading", () => { - expect(applicationBuilder.tray.getIconPath()).toBe( + expect(builder.tray.getIconPath()).toBe( "/some-static-files-directory/icons/trayIconCheckingForUpdatesTemplate.png", ); }); @@ -159,7 +159,7 @@ describe("installing update", () => { }); it("still shows normal tray icon", () => { - expect(applicationBuilder.tray.getIconPath()).toBe( + expect(builder.tray.getIconPath()).toBe( "/some-static-files-directory/icons/trayIconTemplate.png", ); }); @@ -179,7 +179,7 @@ describe("installing update", () => { }); it("shows tray icon for update being available", () => { - expect(applicationBuilder.tray.getIconPath()).toBe( + expect(builder.tray.getIconPath()).toBe( "/some-static-files-directory/icons/trayIconUpdateAvailableTemplate.png", ); }); @@ -196,7 +196,7 @@ describe("installing update", () => { }); it("shows tray icon for checking for updates", () => { - expect(applicationBuilder.tray.getIconPath()).toBe( + expect(builder.tray.getIconPath()).toBe( "/some-static-files-directory/icons/trayIconCheckingForUpdatesTemplate.png", ); }); @@ -214,7 +214,7 @@ describe("installing update", () => { }); it("shows tray icon for update being available", () => { - expect(applicationBuilder.tray.getIconPath()).toBe( + expect(builder.tray.getIconPath()).toBe( "/some-static-files-directory/icons/trayIconUpdateAvailableTemplate.png", ); }); @@ -233,7 +233,7 @@ describe("installing update", () => { }); it("shows tray icon for downloading update", () => { - expect(applicationBuilder.tray.getIconPath()).toBe( + expect(builder.tray.getIconPath()).toBe( "/some-static-files-directory/icons/trayIconCheckingForUpdatesTemplate.png", ); }); diff --git a/src/behaviours/application-update/periodical-checking-of-updates.test.ts b/src/behaviours/application-update/periodical-checking-of-updates.test.ts index 997f46f8e9..e5c7b1c17c 100644 --- a/src/behaviours/application-update/periodical-checking-of-updates.test.ts +++ b/src/behaviours/application-update/periodical-checking-of-updates.test.ts @@ -14,15 +14,15 @@ import { advanceFakeTime, useFakeTime } from "../../common/test-utils/use-fake-t const ENOUGH_TIME = 1000 * 60 * 60 * 2; describe("periodical checking of updates", () => { - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; let processCheckingForUpdatesMock: jest.Mock; beforeEach(() => { useFakeTime("2015-10-21T07:28:00Z"); - applicationBuilder = getApplicationBuilder(); + builder = getApplicationBuilder(); - applicationBuilder.beforeApplicationStart(({ mainDi }) => { + builder.beforeApplicationStart((mainDi) => { mainDi.unoverride(periodicalCheckForUpdatesInjectable); mainDi.permitSideEffects(periodicalCheckForUpdatesInjectable); @@ -39,12 +39,12 @@ describe("periodical checking of updates", () => { let rendered: RenderResult; beforeEach(async () => { - applicationBuilder.beforeApplicationStart(({ mainDi }) => { + builder.beforeApplicationStart((mainDi) => { mainDi.override(electronUpdaterIsActiveInjectable, () => true); mainDi.override(publishIsConfiguredInjectable, () => true); }); - rendered = await applicationBuilder.render(); + rendered = await builder.render(); }); it("renders", () => { @@ -74,12 +74,12 @@ describe("periodical checking of updates", () => { describe("given updater is enabled but no configuration exist, when started", () => { beforeEach(async () => { - applicationBuilder.beforeApplicationStart(({ mainDi }) => { + builder.beforeApplicationStart((mainDi) => { mainDi.override(electronUpdaterIsActiveInjectable, () => true); mainDi.override(publishIsConfiguredInjectable, () => false); }); - await applicationBuilder.render(); + await builder.render(); }); it("does not check for updates", () => { @@ -95,12 +95,12 @@ describe("periodical checking of updates", () => { describe("given updater is not enabled but and configuration exist, when started", () => { beforeEach(async () => { - applicationBuilder.beforeApplicationStart(({ mainDi }) => { + builder.beforeApplicationStart((mainDi) => { mainDi.override(electronUpdaterIsActiveInjectable, () => false); mainDi.override(publishIsConfiguredInjectable, () => true); }); - await applicationBuilder.render(); + await builder.render(); }); it("does not check for updates", () => { diff --git a/src/behaviours/application-update/selection-of-update-stability.test.ts b/src/behaviours/application-update/selection-of-update-stability.test.ts index c2407079df..ceb7584a09 100644 --- a/src/behaviours/application-update/selection-of-update-stability.test.ts +++ b/src/behaviours/application-update/selection-of-update-stability.test.ts @@ -22,27 +22,27 @@ import setUpdateOnQuitInjectable from "../../main/electron-app/features/set-upda import showInfoNotificationInjectable from "../../renderer/components/notifications/show-info-notification.injectable"; import processCheckingForUpdatesInjectable from "../../main/application-update/check-for-updates/process-checking-for-updates.injectable"; import appVersionInjectable from "../../common/vars/app-version.injectable"; +import type { DiContainer } from "@ogre-tools/injectable"; describe("selection of update stability", () => { - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; let quitAndInstallUpdateMock: jest.Mock; let checkForPlatformUpdatesMock: AsyncFnMock; let downloadPlatformUpdateMock: AsyncFnMock; let setUpdateOnQuitMock: jest.Mock; let showInfoNotificationMock: jest.Mock; + let mainDi: DiContainer; beforeEach(() => { - applicationBuilder = getApplicationBuilder(); + builder = getApplicationBuilder(); - applicationBuilder.beforeApplicationStart(({ mainDi, rendererDi }) => { + builder.beforeApplicationStart((mainDi) => { quitAndInstallUpdateMock = jest.fn(); checkForPlatformUpdatesMock = asyncFn(); downloadPlatformUpdateMock = asyncFn(); setUpdateOnQuitMock = jest.fn(); showInfoNotificationMock = jest.fn(() => () => {}); - rendererDi.override(showInfoNotificationInjectable, () => showInfoNotificationMock); - mainDi.override(setUpdateOnQuitInjectable, () => setUpdateOnQuitMock); mainDi.override( @@ -63,6 +63,14 @@ describe("selection of update stability", () => { mainDi.override(electronUpdaterIsActiveInjectable, () => true); mainDi.override(publishIsConfiguredInjectable, () => true); }); + + builder.beforeWindowStart((windowDi) => { + showInfoNotificationMock = jest.fn(() => () => {}); + + windowDi.override(showInfoNotificationInjectable, () => showInfoNotificationMock); + }); + + mainDi = builder.mainDi; }); describe("when started", () => { @@ -70,9 +78,9 @@ describe("selection of update stability", () => { let processCheckingForUpdates: (source: string) => Promise<{ updateIsReadyToBeInstalled: boolean }>; beforeEach(async () => { - rendered = await applicationBuilder.render(); + rendered = await builder.render(); - processCheckingForUpdates = applicationBuilder.dis.mainDi.inject(processCheckingForUpdatesInjectable); + processCheckingForUpdates = mainDi.inject(processCheckingForUpdatesInjectable); }); it("renders", () => { @@ -86,7 +94,7 @@ describe("selection of update stability", () => { }; beforeEach(() => { - selectedUpdateChannel = applicationBuilder.dis.mainDi.inject( + selectedUpdateChannel = mainDi.inject( selectedUpdateChannelInjectable, ); @@ -177,7 +185,7 @@ describe("selection of update stability", () => { }; beforeEach(() => { - selectedUpdateChannel = applicationBuilder.dis.mainDi.inject( + selectedUpdateChannel = mainDi.inject( selectedUpdateChannelInjectable, ); @@ -224,7 +232,7 @@ describe("selection of update stability", () => { }); it("given valid update channel selection is stored, when checking for updates, checks for updates from the update channel", async () => { - applicationBuilder.beforeApplicationStart(({ mainDi }) => { + builder.beforeApplicationStart((mainDi) => { // TODO: Switch to more natural way of setting initial value // TODO: UserStore is currently responsible for getting and setting initial value const selectedUpdateChannel = mainDi.inject(selectedUpdateChannelInjectable); @@ -232,9 +240,9 @@ describe("selection of update stability", () => { selectedUpdateChannel.setValue(updateChannels.beta.id); }); - await applicationBuilder.render(); + await builder.render(); - const processCheckingForUpdates = applicationBuilder.dis.mainDi.inject(processCheckingForUpdatesInjectable); + const processCheckingForUpdates = mainDi.inject(processCheckingForUpdatesInjectable); processCheckingForUpdates("irrelevant"); @@ -242,7 +250,7 @@ describe("selection of update stability", () => { }); it("given invalid update channel selection is stored, when checking for updates, checks for updates from the update channel", async () => { - applicationBuilder.beforeApplicationStart(({ mainDi }) => { + builder.beforeApplicationStart((mainDi) => { // TODO: Switch to more natural way of setting initial value // TODO: UserStore is currently responsible for getting and setting initial value const selectedUpdateChannel = mainDi.inject(selectedUpdateChannelInjectable); @@ -250,9 +258,9 @@ describe("selection of update stability", () => { selectedUpdateChannel.setValue("something-invalid" as UpdateChannelId); }); - await applicationBuilder.render(); + await builder.render(); - const processCheckingForUpdates = applicationBuilder.dis.mainDi.inject(processCheckingForUpdatesInjectable); + const processCheckingForUpdates = mainDi.inject(processCheckingForUpdatesInjectable); processCheckingForUpdates("irrelevant"); @@ -260,13 +268,13 @@ describe("selection of update stability", () => { }); it('given no update channel selection is stored and currently using stable release, when user checks for updates, checks for updates from "latest" update channel by default', async () => { - applicationBuilder.beforeApplicationStart(({ mainDi }) => { + builder.beforeApplicationStart((mainDi) => { mainDi.override(appVersionInjectable, () => "1.0.0"); }); - await applicationBuilder.render(); + await builder.render(); - const processCheckingForUpdates = applicationBuilder.dis.mainDi.inject(processCheckingForUpdatesInjectable); + const processCheckingForUpdates = mainDi.inject(processCheckingForUpdatesInjectable); processCheckingForUpdates("irrelevant"); @@ -277,13 +285,13 @@ describe("selection of update stability", () => { }); it('given no update channel selection is stored and currently using alpha release, when checking for updates, checks for updates from "alpha" channel', async () => { - applicationBuilder.beforeApplicationStart(({ mainDi }) => { + builder.beforeApplicationStart((mainDi) => { mainDi.override(appVersionInjectable, () => "1.0.0-alpha"); }); - await applicationBuilder.render(); + await builder.render(); - const processCheckingForUpdates = applicationBuilder.dis.mainDi.inject(processCheckingForUpdatesInjectable); + const processCheckingForUpdates = mainDi.inject(processCheckingForUpdatesInjectable); processCheckingForUpdates("irrelevant"); @@ -291,13 +299,13 @@ describe("selection of update stability", () => { }); it('given no update channel selection is stored and currently using beta release, when checking for updates, checks for updates from "beta" channel', async () => { - applicationBuilder.beforeApplicationStart(({ mainDi }) => { + builder.beforeApplicationStart((mainDi) => { mainDi.override(appVersionInjectable, () => "1.0.0-beta"); }); - await applicationBuilder.render(); + await builder.render(); - const processCheckingForUpdates = applicationBuilder.dis.mainDi.inject(processCheckingForUpdatesInjectable); + const processCheckingForUpdates = mainDi.inject(processCheckingForUpdatesInjectable); processCheckingForUpdates("irrelevant"); @@ -305,7 +313,7 @@ describe("selection of update stability", () => { }); it("given update channel selection is stored and currently using prerelease, when checking for updates, checks for updates from stored channel", async () => { - applicationBuilder.beforeApplicationStart(({ mainDi }) => { + builder.beforeApplicationStart((mainDi) => { mainDi.override(appVersionInjectable, () => "1.0.0-alpha"); // TODO: Switch to more natural way of setting initial value @@ -315,9 +323,9 @@ describe("selection of update stability", () => { selectedUpdateChannel.setValue(updateChannels.beta.id); }); - await applicationBuilder.render(); + await builder.render(); - const processCheckingForUpdates = applicationBuilder.dis.mainDi.inject(processCheckingForUpdatesInjectable); + const processCheckingForUpdates = mainDi.inject(processCheckingForUpdatesInjectable); processCheckingForUpdates("irrelevant"); diff --git a/src/behaviours/cluster/extension-api/disable-cluster-pages-when-cluster-is-not-relevant.test.tsx b/src/behaviours/cluster/extension-api/disable-cluster-pages-when-cluster-is-not-relevant.test.tsx index c6c3cd7fab..0c69f49f80 100644 --- a/src/behaviours/cluster/extension-api/disable-cluster-pages-when-cluster-is-not-relevant.test.tsx +++ b/src/behaviours/cluster/extension-api/disable-cluster-pages-when-cluster-is-not-relevant.test.tsx @@ -8,7 +8,6 @@ import type { RenderResult } from "@testing-library/react"; import type { ApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; import type { TestExtensionRenderer } from "../../../renderer/components/test-utils/get-extension-fake"; -import { getExtensionFakeFor } from "../../../renderer/components/test-utils/get-extension-fake"; import type { KubernetesCluster } from "../../../common/catalog-entities"; import React from "react"; import extensionShouldBeEnabledForClusterFrameInjectable from "../../../renderer/extension-loader/extension-should-be-enabled-for-cluster-frame.injectable"; @@ -24,13 +23,13 @@ describe("disable-cluster-pages-when-cluster-is-not-relevant", () => { builder.setEnvironmentToClusterFrame(); - builder.dis.rendererDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable); - - const getExtensionFake = getExtensionFakeFor(builder); + builder.beforeWindowStart((windowDi) => { + windowDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable); + }); isEnabledForClusterMock = asyncFn(); - const testExtension = getExtensionFake({ + const testExtension = { id: "test-extension-id", name: "test-extension", @@ -43,13 +42,14 @@ describe("disable-cluster-pages-when-cluster-is-not-relevant", () => { }, }], }, - }); - - rendererTestExtension = testExtension.renderer; + }; rendered = await builder.render(); builder.extensions.enable(testExtension); + + rendererTestExtension = + builder.extensions.get("test-extension-id").applicationWindows.only; }); describe("given not yet known if extension should be enabled for the cluster, when navigating", () => { diff --git a/src/behaviours/cluster/extension-api/disable-sidebar-items-when-cluster-is-not-relevant.test.tsx b/src/behaviours/cluster/extension-api/disable-sidebar-items-when-cluster-is-not-relevant.test.tsx index 28007355b1..f94a0049d9 100644 --- a/src/behaviours/cluster/extension-api/disable-sidebar-items-when-cluster-is-not-relevant.test.tsx +++ b/src/behaviours/cluster/extension-api/disable-sidebar-items-when-cluster-is-not-relevant.test.tsx @@ -7,7 +7,6 @@ import asyncFn from "@async-fn/jest"; import type { RenderResult } from "@testing-library/react"; import type { ApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; -import { getExtensionFakeFor } from "../../../renderer/components/test-utils/get-extension-fake"; import type { KubernetesCluster } from "../../../common/catalog-entities"; import React from "react"; import extensionShouldBeEnabledForClusterFrameInjectable from "../../../renderer/extension-loader/extension-should-be-enabled-for-cluster-frame.injectable"; @@ -22,13 +21,13 @@ describe("disable sidebar items when cluster is not relevant", () => { builder.setEnvironmentToClusterFrame(); - builder.dis.rendererDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable); - - const getExtensionFake = getExtensionFakeFor(builder); + builder.beforeWindowStart((windowDi) => { + windowDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable); + }); isEnabledForClusterMock = asyncFn(); - const testExtension = getExtensionFake({ + const testExtension = { id: "test-extension-id", name: "test-extension", @@ -52,7 +51,7 @@ describe("disable sidebar items when cluster is not relevant", () => { }, ], }, - }); + }; rendered = await builder.render(); diff --git a/src/behaviours/cluster/extension-api/reactively-disable-cluster-pages.test.tsx b/src/behaviours/cluster/extension-api/reactively-disable-cluster-pages.test.tsx index 4cc5e45576..57dc83d810 100644 --- a/src/behaviours/cluster/extension-api/reactively-disable-cluster-pages.test.tsx +++ b/src/behaviours/cluster/extension-api/reactively-disable-cluster-pages.test.tsx @@ -9,24 +9,21 @@ import React from "react"; import type { TestExtensionRenderer } from "../../../renderer/components/test-utils/get-extension-fake"; import type { ApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; -import { getExtensionFakeFor } from "../../../renderer/components/test-utils/get-extension-fake"; describe("reactively disable cluster pages", () => { let builder: ApplicationBuilder; let rendered: RenderResult; let someObservable: IObservableValue; - let rendererTestExtension: TestExtensionRenderer; + let testExtensionInstance: TestExtensionRenderer; beforeEach(async () => { builder = getApplicationBuilder(); builder.setEnvironmentToClusterFrame(); - const getExtensionFake = getExtensionFakeFor(builder); - someObservable = observable.box(false); - const testExtension = getExtensionFake({ + const testExtensionOptions = { id: "test-extension-id", name: "test-extension", @@ -39,17 +36,18 @@ describe("reactively disable cluster pages", () => { enabled: computed(() => someObservable.get()), }], }, - }); + }; rendered = await builder.render(); - builder.extensions.enable(testExtension); + builder.extensions.enable(testExtensionOptions); - rendererTestExtension = testExtension.renderer; + testExtensionInstance = + builder.extensions.get("test-extension-id").applicationWindows.only; }); it("when navigating to the page, does not show the page", () => { - rendererTestExtension.navigate(); + testExtensionInstance.navigate(); const actual = rendered.queryByTestId("some-test-page"); @@ -61,7 +59,7 @@ describe("reactively disable cluster pages", () => { someObservable.set(true); }); - rendererTestExtension.navigate(); + testExtensionInstance.navigate(); const actual = rendered.queryByTestId("some-test-page"); diff --git a/src/behaviours/cluster/kube-object-details/extension-api/disable-kube-object-detail-items-when-cluster-is-not-relevant.test.tsx b/src/behaviours/cluster/kube-object-details/extension-api/disable-kube-object-detail-items-when-cluster-is-not-relevant.test.tsx index a81071ad3e..90660f980f 100644 --- a/src/behaviours/cluster/kube-object-details/extension-api/disable-kube-object-detail-items-when-cluster-is-not-relevant.test.tsx +++ b/src/behaviours/cluster/kube-object-details/extension-api/disable-kube-object-detail-items-when-cluster-is-not-relevant.test.tsx @@ -8,7 +8,6 @@ import type { RenderResult } from "@testing-library/react"; import type { ApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder"; import type { KubernetesCluster } from "../../../../common/catalog-entities"; import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder"; -import { getExtensionFakeFor } from "../../../../renderer/components/test-utils/get-extension-fake"; import { getInjectable } from "@ogre-tools/injectable"; import { frontEndRouteInjectionToken } from "../../../../common/front-end-routing/front-end-route-injection-token"; import { computed } from "mobx"; @@ -30,9 +29,10 @@ describe("disable kube object detail items when cluster is not relevant", () => beforeEach(async () => { builder = getApplicationBuilder(); + builder.setEnvironmentToClusterFrame(); - builder.beforeApplicationStart(({ rendererDi }) => { - rendererDi.override( + builder.beforeWindowStart((windowDi) => { + windowDi.override( apiManagerInjectable, () => ({ @@ -42,21 +42,15 @@ describe("disable kube object detail items when cluster is not relevant", () => }), } as unknown as ApiManager), ); + + windowDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable); + + windowDi.register(testRouteInjectable, testRouteComponentInjectable); }); - const rendererDi = builder.dis.rendererDi; - - rendererDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable); - - rendererDi.register(testRouteInjectable, testRouteComponentInjectable); - - builder.setEnvironmentToClusterFrame(); - - const getExtensionFake = getExtensionFakeFor(builder); - isEnabledForClusterMock = asyncFn(); - const testExtension = getExtensionFake({ + const testExtension = { id: "test-extension-id", name: "test-extension", @@ -77,12 +71,14 @@ describe("disable kube object detail items when cluster is not relevant", () => }, ], }, - }); + }; rendered = await builder.render(); - const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken); - const testRoute = rendererDi.inject(testRouteInjectable); + const windowDi = builder.applicationWindow.only.di; + + const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken); + const testRoute = windowDi.inject(testRouteInjectable); navigateToRoute(testRoute); diff --git a/src/behaviours/cluster/kube-object-details/extension-api/reactively-hide-kube-object-detail-item.test.tsx b/src/behaviours/cluster/kube-object-details/extension-api/reactively-hide-kube-object-detail-item.test.tsx index 77c9c24552..5ca5961778 100644 --- a/src/behaviours/cluster/kube-object-details/extension-api/reactively-hide-kube-object-detail-item.test.tsx +++ b/src/behaviours/cluster/kube-object-details/extension-api/reactively-hide-kube-object-detail-item.test.tsx @@ -5,7 +5,6 @@ import type { RenderResult } from "@testing-library/react"; import type { ApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder"; -import { getExtensionFakeFor } from "../../../../renderer/components/test-utils/get-extension-fake"; import { getInjectable } from "@ogre-tools/injectable"; import { frontEndRouteInjectionToken } from "../../../../common/front-end-routing/front-end-route-injection-token"; import type { IObservableValue } from "mobx"; @@ -26,8 +25,10 @@ describe("reactively hide kube object detail item", () => { beforeEach(async () => { builder = getApplicationBuilder(); - builder.beforeApplicationStart(({ rendererDi }) => { - rendererDi.override( + builder.setEnvironmentToClusterFrame(); + + builder.beforeWindowStart((windowDi) => { + windowDi.override( apiManagerInjectable, () => ({ @@ -37,19 +38,13 @@ describe("reactively hide kube object detail item", () => { }), } as unknown as ApiManager), ); + + windowDi.register(testRouteInjectable, testRouteComponentInjectable); }); - const rendererDi = builder.dis.rendererDi; - - rendererDi.register(testRouteInjectable, testRouteComponentInjectable); - - builder.setEnvironmentToClusterFrame(); - - const getExtensionFake = getExtensionFakeFor(builder); - someObservable = observable.box(false); - const testExtension = getExtensionFake({ + const testExtension = { id: "test-extension-id", name: "test-extension", @@ -71,12 +66,14 @@ describe("reactively hide kube object detail item", () => { }, ], }, - }); + }; rendered = await builder.render(); - const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken); - const testRoute = rendererDi.inject(testRouteInjectable); + const windowDi = builder.applicationWindow.only.di; + + const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken); + const testRoute = windowDi.inject(testRouteInjectable); navigateToRoute(testRoute); diff --git a/src/behaviours/cluster/kube-object-menu/extension-api/disable-kube-object-menu-items-when-cluster-is-not-relevant.test.tsx b/src/behaviours/cluster/kube-object-menu/extension-api/disable-kube-object-menu-items-when-cluster-is-not-relevant.test.tsx index 8b48d76160..94bd91681f 100644 --- a/src/behaviours/cluster/kube-object-menu/extension-api/disable-kube-object-menu-items-when-cluster-is-not-relevant.test.tsx +++ b/src/behaviours/cluster/kube-object-menu/extension-api/disable-kube-object-menu-items-when-cluster-is-not-relevant.test.tsx @@ -8,7 +8,6 @@ import type { RenderResult } from "@testing-library/react"; import type { ApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder"; import type { KubernetesCluster } from "../../../../common/catalog-entities"; import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder"; -import { getExtensionFakeFor } from "../../../../renderer/components/test-utils/get-extension-fake"; import { getInjectable } from "@ogre-tools/injectable"; import { frontEndRouteInjectionToken } from "../../../../common/front-end-routing/front-end-route-injection-token"; import { computed } from "mobx"; @@ -29,19 +28,16 @@ describe("disable kube object menu items when cluster is not relevant", () => { beforeEach(async () => { builder = getApplicationBuilder(); - const rendererDi = builder.dis.rendererDi; - - rendererDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable); - - rendererDi.register(testRouteInjectable, testRouteComponentInjectable); - builder.setEnvironmentToClusterFrame(); - const getExtensionFake = getExtensionFakeFor(builder); + builder.beforeWindowStart((windowDi) => { + windowDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable); + windowDi.register(testRouteInjectable, testRouteComponentInjectable); + }); isEnabledForClusterMock = asyncFn(); - const testExtension = getExtensionFake({ + const testExtension = { id: "test-extension-id", name: "test-extension", @@ -60,12 +56,14 @@ describe("disable kube object menu items when cluster is not relevant", () => { }, ], }, - }); + }; rendered = await builder.render(); - const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken); - const testRoute = rendererDi.inject(testRouteInjectable); + const windowDi = builder.applicationWindow.only.di; + + const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken); + const testRoute = windowDi.inject(testRouteInjectable); navigateToRoute(testRoute); diff --git a/src/behaviours/cluster/kube-object-menu/extension-api/reactively-hide-kube-object-menu-item.test.tsx b/src/behaviours/cluster/kube-object-menu/extension-api/reactively-hide-kube-object-menu-item.test.tsx index 74f33a657a..61a5fe6e90 100644 --- a/src/behaviours/cluster/kube-object-menu/extension-api/reactively-hide-kube-object-menu-item.test.tsx +++ b/src/behaviours/cluster/kube-object-menu/extension-api/reactively-hide-kube-object-menu-item.test.tsx @@ -5,7 +5,6 @@ import type { RenderResult } from "@testing-library/react"; import type { ApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder"; -import { getExtensionFakeFor } from "../../../../renderer/components/test-utils/get-extension-fake"; import { getInjectable } from "@ogre-tools/injectable"; import { frontEndRouteInjectionToken } from "../../../../common/front-end-routing/front-end-route-injection-token"; import type { IObservableValue } from "mobx"; @@ -24,17 +23,15 @@ describe("reactively hide kube object menu item", () => { beforeEach(async () => { builder = getApplicationBuilder(); - const rendererDi = builder.dis.rendererDi; - - rendererDi.register(testRouteInjectable, testRouteComponentInjectable); - builder.setEnvironmentToClusterFrame(); - const getExtensionFake = getExtensionFakeFor(builder); + builder.beforeWindowStart((windowDi) => { + windowDi.register(testRouteInjectable, testRouteComponentInjectable); + }); someObservable = observable.box(false); - const testExtension = getExtensionFake({ + const testExtension = { id: "test-extension-id", name: "test-extension", @@ -53,12 +50,14 @@ describe("reactively hide kube object menu item", () => { }, ], }, - }); + }; rendered = await builder.render(); - const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken); - const testRoute = rendererDi.inject(testRouteInjectable); + const windowDi = builder.applicationWindow.only.di; + + const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken); + const testRoute = windowDi.inject(testRouteInjectable); navigateToRoute(testRoute); diff --git a/src/behaviours/cluster/kube-object-status-icon/extension-api/disable-kube-object-statuses-when-cluster-is-not-relevant.test.tsx b/src/behaviours/cluster/kube-object-status-icon/extension-api/disable-kube-object-statuses-when-cluster-is-not-relevant.test.tsx index da3ac641a9..7a459c258d 100644 --- a/src/behaviours/cluster/kube-object-status-icon/extension-api/disable-kube-object-statuses-when-cluster-is-not-relevant.test.tsx +++ b/src/behaviours/cluster/kube-object-status-icon/extension-api/disable-kube-object-statuses-when-cluster-is-not-relevant.test.tsx @@ -8,7 +8,6 @@ import type { RenderResult } from "@testing-library/react"; import type { ApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder"; import type { KubernetesCluster } from "../../../../common/catalog-entities"; import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder"; -import { getExtensionFakeFor } from "../../../../renderer/components/test-utils/get-extension-fake"; import { getInjectable } from "@ogre-tools/injectable"; import { frontEndRouteInjectionToken } from "../../../../common/front-end-routing/front-end-route-injection-token"; import { computed } from "mobx"; @@ -30,19 +29,16 @@ describe("disable kube object statuses when cluster is not relevant", () => { beforeEach(async () => { builder = getApplicationBuilder(); - const rendererDi = builder.dis.rendererDi; - - rendererDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable); - - rendererDi.register(testRouteInjectable, testRouteComponentInjectable); - builder.setEnvironmentToClusterFrame(); - const getExtensionFake = getExtensionFakeFor(builder); + builder.beforeWindowStart((windowDi) => { + windowDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable); + windowDi.register(testRouteInjectable, testRouteComponentInjectable); + }); isEnabledForClusterMock = asyncFn(); - const testExtension = getExtensionFake({ + const testExtension = { id: "test-extension-id", name: "test-extension", @@ -61,12 +57,14 @@ describe("disable kube object statuses when cluster is not relevant", () => { }, ], }, - }); + }; rendered = await builder.render(); - const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken); - const testRoute = rendererDi.inject(testRouteInjectable); + const windowDi = builder.applicationWindow.only.di; + + const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken); + const testRoute = windowDi.inject(testRouteInjectable); navigateToRoute(testRoute); diff --git a/src/behaviours/cluster/kube-object-status-icon/extension-api/reactively-hide-kube-object-status.test.tsx b/src/behaviours/cluster/kube-object-status-icon/extension-api/reactively-hide-kube-object-status.test.tsx index 3c9695d8fa..7dd45803a2 100644 --- a/src/behaviours/cluster/kube-object-status-icon/extension-api/reactively-hide-kube-object-status.test.tsx +++ b/src/behaviours/cluster/kube-object-status-icon/extension-api/reactively-hide-kube-object-status.test.tsx @@ -5,7 +5,6 @@ import type { RenderResult } from "@testing-library/react"; import type { ApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder"; -import { getExtensionFakeFor } from "../../../../renderer/components/test-utils/get-extension-fake"; import { getInjectable } from "@ogre-tools/injectable"; import { frontEndRouteInjectionToken } from "../../../../common/front-end-routing/front-end-route-injection-token"; import type { IObservableValue } from "mobx"; @@ -26,19 +25,16 @@ describe("reactively hide kube object status", () => { beforeEach(async () => { builder = getApplicationBuilder(); - const rendererDi = builder.dis.rendererDi; - - rendererDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable); - - rendererDi.register(testRouteInjectable, testRouteComponentInjectable); - builder.setEnvironmentToClusterFrame(); - const getExtensionFake = getExtensionFakeFor(builder); + builder.beforeWindowStart((windowDi) => { + windowDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable); + windowDi.register(testRouteInjectable, testRouteComponentInjectable); + }); someObservable = observable.box(false); - const testExtension = getExtensionFake({ + const testExtension = { id: "test-extension-id", name: "test-extension", @@ -57,12 +53,14 @@ describe("reactively hide kube object status", () => { }, ], }, - }); + }; rendered = await builder.render(); - const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken); - const testRoute = rendererDi.inject(testRouteInjectable); + const windowDi = builder.applicationWindow.only.di; + + const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken); + const testRoute = windowDi.inject(testRouteInjectable); navigateToRoute(testRoute); diff --git a/src/behaviours/cluster/kube-object-status-icon/show-status-for-a-kube-object.test.tsx b/src/behaviours/cluster/kube-object-status-icon/show-status-for-a-kube-object.test.tsx index a63344271d..eba681ef47 100644 --- a/src/behaviours/cluster/kube-object-status-icon/show-status-for-a-kube-object.test.tsx +++ b/src/behaviours/cluster/kube-object-status-icon/show-status-for-a-kube-object.test.tsx @@ -32,8 +32,6 @@ describe("show status for a kube object", () => { builder = getApplicationBuilder(); - const rendererDi = builder.dis.rendererDi; - infoStatusIsShown = false; const infoStatusInjectable = getInjectable({ @@ -95,34 +93,36 @@ describe("show status for a kube object", () => { }), }); - rendererDi.register( - testRouteInjectable, - testRouteComponentInjectable, - infoStatusInjectable, - warningStatusInjectable, - criticalStatusInjectable, - someAtomInjectable, - ); + builder.beforeWindowStart((windowDi) => { + windowDi.register( + testRouteInjectable, + testRouteComponentInjectable, + infoStatusInjectable, + warningStatusInjectable, + criticalStatusInjectable, + someAtomInjectable, + ); + }); builder.setEnvironmentToClusterFrame(); }); describe("given application starts and in test page", () => { - let rendererDi: DiContainer; + let windowDi: DiContainer; let rendered: RenderResult; let rerenderParent: () => void; beforeEach(async () => { rendered = await builder.render(); - rendererDi = builder.dis.rendererDi; + windowDi = builder.applicationWindow.only.di; - const someAtom = rendererDi.inject(someAtomInjectable); + const someAtom = windowDi.inject(someAtomInjectable); rerenderParent = rerenderParentFor(someAtom); - const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken); - const testRoute = rendererDi.inject(testRouteInjectable); + const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken); + const testRoute = windowDi.inject(testRouteInjectable); navigateToRoute(testRoute); }); @@ -141,7 +141,7 @@ describe("show status for a kube object", () => { describe("when status for irrelevant kube object kind emerges", () => { beforeEach(() => { - rendererDi.register(statusForIrrelevantKubeObjectKindInjectable); + windowDi.register(statusForIrrelevantKubeObjectKindInjectable); rerenderParent(); }); @@ -161,7 +161,7 @@ describe("show status for a kube object", () => { describe("when status for irrelevant kube object api version emerges", () => { beforeEach(() => { - rendererDi.register(statusForIrrelevantKubeObjectApiVersionInjectable); + windowDi.register(statusForIrrelevantKubeObjectApiVersionInjectable); rerenderParent(); }); diff --git a/src/behaviours/cluster/namespaces/edit-namespace-from-new-tab.test.tsx b/src/behaviours/cluster/namespaces/edit-namespace-from-new-tab.test.tsx index 41ff722bfb..efe0cdf554 100644 --- a/src/behaviours/cluster/namespaces/edit-namespace-from-new-tab.test.tsx +++ b/src/behaviours/cluster/namespaces/edit-namespace-from-new-tab.test.tsx @@ -44,34 +44,34 @@ describe("cluster/namespaces - edit namespace from new tab", () => { showSuccessNotificationMock = jest.fn(); showErrorNotificationMock = jest.fn(); - builder.beforeApplicationStart(({ rendererDi }) => { - rendererDi.override( + builder.beforeWindowStart((windowDi) => { + windowDi.override( directoryForLensLocalStorageInjectable, () => "/some-directory-for-lens-local-storage", ); - rendererDi.override(hostedClusterIdInjectable, () => "some-cluster-id"); + windowDi.override(hostedClusterIdInjectable, () => "some-cluster-id"); - storagesAreReady = controlWhenStoragesAreReady(rendererDi); + storagesAreReady = controlWhenStoragesAreReady(windowDi); - rendererDi.override( + windowDi.override( showSuccessNotificationInjectable, () => showSuccessNotificationMock, ); - rendererDi.override( + windowDi.override( showErrorNotificationInjectable, () => showErrorNotificationMock, ); - rendererDi.override(getRandomIdForEditResourceTabInjectable, () => + windowDi.override(getRandomIdForEditResourceTabInjectable, () => jest .fn(() => "some-irrelevant-random-id") .mockReturnValueOnce("some-first-tab-id") .mockReturnValueOnce("some-second-tab-id"), ); - rendererDi.override(callForResourceInjectable, () => async (selfLink: string) => { + windowDi.override(callForResourceInjectable, () => async (selfLink: string) => { if ( [ "/apis/some-api-version/namespaces/some-uid", @@ -84,7 +84,7 @@ describe("cluster/namespaces - edit namespace from new tab", () => { return undefined; }); - rendererDi.override(callForPatchResourceInjectable, () => async (namespace, ...args) => { + windowDi.override(callForPatchResourceInjectable, () => async (namespace, ...args) => { if ( [ "/apis/some-api-version/namespaces/some-uid", @@ -103,22 +103,22 @@ describe("cluster/namespaces - edit namespace from new tab", () => { describe("when navigating to namespaces", () => { let rendered: RenderResult; - let rendererDi: DiContainer; + let windowDi: DiContainer; beforeEach(async () => { rendered = await builder.render(); await storagesAreReady(); - rendererDi = builder.dis.rendererDi; + windowDi = builder.applicationWindow.only.di; - const navigateToNamespaces = rendererDi.inject( + const navigateToNamespaces = windowDi.inject( navigateToNamespacesInjectable, ); navigateToNamespaces(); - const dockStore = rendererDi.inject(dockStoreInjectable); + const dockStore = windowDi.inject(dockStoreInjectable); // TODO: Make TerminalWindow unit testable to allow realistic behaviour dockStore.closeTab("terminal"); @@ -168,7 +168,7 @@ describe("cluster/namespaces - edit namespace from new tab", () => { // TODO: Make implementation match the description (tests above) const namespaceStub = new Namespace(someNamespaceDataStub); - const createEditResourceTab = rendererDi.inject(createEditResourceTabInjectable); + const createEditResourceTab = windowDi.inject(createEditResourceTabInjectable); createEditResourceTab(namespaceStub); }); @@ -510,7 +510,7 @@ metadata: }); it("stores the changed configuration", async () => { - const readJsonFile = rendererDi.inject( + const readJsonFile = windowDi.inject( readJsonFileInjectable, ); @@ -719,7 +719,7 @@ metadata: // TODO: Make implementation match the description const namespaceStub = new Namespace(someOtherNamespaceDataStub); - const createEditResourceTab = rendererDi.inject(createEditResourceTabInjectable); + const createEditResourceTab = windowDi.inject(createEditResourceTabInjectable); createEditResourceTab(namespaceStub); }); diff --git a/src/behaviours/cluster/namespaces/edit-namespace-from-previously-opened-tab.test.tsx b/src/behaviours/cluster/namespaces/edit-namespace-from-previously-opened-tab.test.tsx index d4571b2611..a5f834563b 100644 --- a/src/behaviours/cluster/namespaces/edit-namespace-from-previously-opened-tab.test.tsx +++ b/src/behaviours/cluster/namespaces/edit-namespace-from-previously-opened-tab.test.tsx @@ -29,17 +29,17 @@ describe("cluster/namespaces - edit namespaces from previously opened tab", () = callForNamespaceMock = asyncFn(); - builder.beforeApplicationStart(({ rendererDi }) => { - rendererDi.override( + builder.beforeWindowStart((windowDi) => { + windowDi.override( directoryForLensLocalStorageInjectable, () => "/some-directory-for-lens-local-storage", ); - rendererDi.override(hostedClusterIdInjectable, () => "some-cluster-id"); + windowDi.override(hostedClusterIdInjectable, () => "some-cluster-id"); - storagesAreReady = controlWhenStoragesAreReady(rendererDi); + storagesAreReady = controlWhenStoragesAreReady(windowDi); - rendererDi.override(callForResourceInjectable, () => callForNamespaceMock); + windowDi.override(callForResourceInjectable, () => callForNamespaceMock); }); builder.allowKubeResource("namespaces"); @@ -49,33 +49,35 @@ describe("cluster/namespaces - edit namespaces from previously opened tab", () = let rendered: RenderResult; beforeEach(async () => { - const writeJsonFile = builder.dis.rendererDi.inject(writeJsonFileInjectable); + builder.beforeWindowStart(async (windowDi) => { + const writeJsonFile = windowDi.inject(writeJsonFileInjectable); - await writeJsonFile( - "/some-directory-for-lens-local-storage/some-cluster-id.json", - { - dock: { - height: 300, - tabs: [ - { - id: "some-first-tab-id", - kind: TabKind.EDIT_RESOURCE, - title: "Namespace: some-namespace", - pinned: false, + await writeJsonFile( + "/some-directory-for-lens-local-storage/some-cluster-id.json", + { + dock: { + height: 300, + tabs: [ + { + id: "some-first-tab-id", + kind: TabKind.EDIT_RESOURCE, + title: "Namespace: some-namespace", + pinned: false, + }, + ], + + isOpen: true, + }, + + edit_resource_store: { + "some-first-tab-id": { + resource: "/apis/some-api-version/namespaces/some-uid", + draft: "some-saved-configuration", }, - ], - - isOpen: true, - }, - - edit_resource_store: { - "some-first-tab-id": { - resource: "/apis/some-api-version/namespaces/some-uid", - draft: "some-saved-configuration", }, }, - }, - ); + ); + }); rendered = await builder.render(); diff --git a/src/behaviours/cluster/order-of-sidebar-items.test.tsx b/src/behaviours/cluster/order-of-sidebar-items.test.tsx index 368b1b065d..718d267e70 100644 --- a/src/behaviours/cluster/order-of-sidebar-items.test.tsx +++ b/src/behaviours/cluster/order-of-sidebar-items.test.tsx @@ -14,19 +14,21 @@ import { getApplicationBuilder } from "../../renderer/components/test-utils/get- describe("cluster - order of sidebar items", () => { let rendered: RenderResult; - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; beforeEach(() => { - applicationBuilder = getApplicationBuilder().setEnvironmentToClusterFrame(); + builder = getApplicationBuilder(); - applicationBuilder.beforeApplicationStart(({ rendererDi }) => { - rendererDi.register(testSidebarItemsInjectable); + builder.setEnvironmentToClusterFrame(); + + builder.beforeWindowStart((windowDi) => { + windowDi.register(testSidebarItemsInjectable); }); }); describe("when rendered", () => { beforeEach(async () => { - rendered = await applicationBuilder.render(); + rendered = await builder.render(); }); it("renders", () => { diff --git a/src/behaviours/cluster/sidebar-and-tab-navigation-for-core.test.tsx b/src/behaviours/cluster/sidebar-and-tab-navigation-for-core.test.tsx index e6cf1f4a64..caa9873208 100644 --- a/src/behaviours/cluster/sidebar-and-tab-navigation-for-core.test.tsx +++ b/src/behaviours/cluster/sidebar-and-tab-navigation-for-core.test.tsx @@ -27,24 +27,21 @@ import { advanceFakeTime, useFakeTime } from "../../common/test-utils/use-fake-t import storageSaveDelayInjectable from "../../renderer/utils/create-storage/storage-save-delay.injectable"; describe("cluster - sidebar and tab navigation for core", () => { - let applicationBuilder: ApplicationBuilder; - let rendererDi: DiContainer; + let builder: ApplicationBuilder; let rendered: RenderResult; beforeEach(() => { useFakeTime("2015-10-21T07:28:00Z"); - applicationBuilder = getApplicationBuilder(); - rendererDi = applicationBuilder.dis.rendererDi; + builder = getApplicationBuilder(); - applicationBuilder.setEnvironmentToClusterFrame(); + builder.setEnvironmentToClusterFrame(); - applicationBuilder.beforeApplicationStart(({ rendererDi }) => { - rendererDi.override(hostedClusterIdInjectable, () => "some-hosted-cluster-id"); + builder.beforeWindowStart((windowDi) => { + windowDi.override(hostedClusterIdInjectable, () => "some-hosted-cluster-id"); + windowDi.override(storageSaveDelayInjectable, () => 250); - rendererDi.override(storageSaveDelayInjectable, () => 250); - - rendererDi.override( + windowDi.override( directoryForLensLocalStorageInjectable, () => "/some-directory-for-lens-local-storage", ); @@ -53,24 +50,23 @@ describe("cluster - sidebar and tab navigation for core", () => { describe("given core registrations", () => { beforeEach(() => { - applicationBuilder.beforeApplicationStart(({ rendererDi }) => { - rendererDi.register(testRouteInjectable); - rendererDi.register(testRouteComponentInjectable); - rendererDi.register(testSidebarItemsInjectable); + builder.beforeWindowStart((windowDi) => { + windowDi.register(testRouteInjectable); + windowDi.register(testRouteComponentInjectable); + windowDi.register(testSidebarItemsInjectable); }); }); describe("given no state for expanded sidebar items exists, and navigated to child sidebar item, when rendered", () => { beforeEach(async () => { - applicationBuilder.beforeRender(({ rendererDi }) => { - const route = rendererDi.inject(testRouteInjectable); + rendered = await builder.render(); - const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken); + const windowDi = builder.applicationWindow.only.di; - navigateToRoute(route); - }); + const route = windowDi.inject(testRouteInjectable); + const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken); - rendered = await applicationBuilder.render(); + navigateToRoute(route); }); it("renders", () => { @@ -96,8 +92,8 @@ describe("cluster - sidebar and tab navigation for core", () => { describe("given state for expanded sidebar items already exists, when rendered", () => { beforeEach(async () => { - applicationBuilder.beforeRender(async ({ rendererDi }) => { - const writeJsonFileFake = rendererDi.inject(writeJsonFileInjectable); + builder.beforeWindowStart(async (windowDi) => { + const writeJsonFileFake = windowDi.inject(writeJsonFileInjectable); await writeJsonFileFake( "/some-directory-for-lens-local-storage/some-hosted-cluster-id.json", @@ -108,15 +104,13 @@ describe("cluster - sidebar and tab navigation for core", () => { }, }, ); - }); - applicationBuilder.beforeRender(async ({ rendererDi }) => { - const sidebarStorage = rendererDi.inject(sidebarStorageInjectable); + const sidebarStorage = windowDi.inject(sidebarStorageInjectable); await sidebarStorage.whenReady; }); - rendered = await applicationBuilder.render(); + rendered = await builder.render(); }); it("renders", () => { @@ -138,8 +132,8 @@ describe("cluster - sidebar and tab navigation for core", () => { describe("given state for expanded unknown sidebar items already exists, when rendered", () => { beforeEach(async () => { - applicationBuilder.beforeRender(async ({ rendererDi }) => { - const writeJsonFileFake = rendererDi.inject(writeJsonFileInjectable); + builder.beforeWindowStart(async (windowDi) => { + const writeJsonFileFake = windowDi.inject(writeJsonFileInjectable); await writeJsonFileFake( "/some-directory-for-lens-local-storage/some-hosted-cluster-id.json", @@ -152,7 +146,7 @@ describe("cluster - sidebar and tab navigation for core", () => { ); }); - rendered = await applicationBuilder.render(); + rendered = await builder.render(); }); it("renders without errors", () => { @@ -168,8 +162,8 @@ describe("cluster - sidebar and tab navigation for core", () => { describe("given empty state for expanded sidebar items already exists, when rendered", () => { beforeEach(async () => { - applicationBuilder.beforeRender(async ({ rendererDi }) => { - const writeJsonFileFake = rendererDi.inject(writeJsonFileInjectable); + builder.beforeWindowStart(async (windowDi) => { + const writeJsonFileFake = windowDi.inject(writeJsonFileInjectable); await writeJsonFileFake( "/some-directory-for-lens-local-storage/some-hosted-cluster-id.json", @@ -179,7 +173,7 @@ describe("cluster - sidebar and tab navigation for core", () => { ); }); - rendered = await applicationBuilder.render(); + rendered = await builder.render(); }); it("renders without errors", () => { @@ -194,8 +188,12 @@ describe("cluster - sidebar and tab navigation for core", () => { }); describe("given no initially persisted state for sidebar items, when rendered", () => { + let windowDi: DiContainer; + beforeEach(async () => { - rendered = await applicationBuilder.render(); + rendered = await builder.render(); + + windowDi = builder.applicationWindow.only.di; }); it("renders", () => { @@ -271,7 +269,7 @@ describe("cluster - sidebar and tab navigation for core", () => { it("when not enough time passes, does not store state for expanded sidebar items to file system yet", async () => { advanceFakeTime(250 - 1); - const pathExistsFake = rendererDi.inject(pathExistsInjectable); + const pathExistsFake = windowDi.inject(pathExistsInjectable); const actual = await pathExistsFake( "/some-directory-for-lens-local-storage/some-hosted-cluster-id.json", @@ -283,7 +281,7 @@ describe("cluster - sidebar and tab navigation for core", () => { it("when enough time passes, stores state for expanded sidebar items to file system", async () => { advanceFakeTime(250); - const readJsonFileFake = rendererDi.inject(readJsonFileInjectable); + const readJsonFileFake = windowDi.inject(readJsonFileInjectable); const actual = await readJsonFileFake( "/some-directory-for-lens-local-storage/some-hosted-cluster-id.json", diff --git a/src/behaviours/cluster/sidebar-and-tab-navigation-for-extensions.test.tsx b/src/behaviours/cluster/sidebar-and-tab-navigation-for-extensions.test.tsx index c3fc563696..8d3de582ad 100644 --- a/src/behaviours/cluster/sidebar-and-tab-navigation-for-extensions.test.tsx +++ b/src/behaviours/cluster/sidebar-and-tab-navigation-for-extensions.test.tsx @@ -13,35 +13,31 @@ import { getApplicationBuilder } from "../../renderer/components/test-utils/get- import writeJsonFileInjectable from "../../common/fs/write-json-file.injectable"; import pathExistsInjectable from "../../common/fs/path-exists.injectable"; import readJsonFileInjectable from "../../common/fs/read-json-file.injectable"; -import type { DiContainer } from "@ogre-tools/injectable"; import { navigateToRouteInjectionToken } from "../../common/front-end-routing/navigate-to-route-injection-token"; import assert from "assert"; import hostedClusterIdInjectable from "../../renderer/cluster-frame-context/hosted-cluster-id.injectable"; import { advanceFakeTime, useFakeTime } from "../../common/test-utils/use-fake-time"; -import { getExtensionFakeFor } from "../../renderer/components/test-utils/get-extension-fake"; import type { IObservableValue } from "mobx"; import { runInAction, computed, observable } from "mobx"; import storageSaveDelayInjectable from "../../renderer/utils/create-storage/storage-save-delay.injectable"; +import type { DiContainer } from "@ogre-tools/injectable"; describe("cluster - sidebar and tab navigation for extensions", () => { let applicationBuilder: ApplicationBuilder; - let rendererDi: DiContainer; let rendered: RenderResult; beforeEach(() => { useFakeTime("2015-10-21T07:28:00Z"); applicationBuilder = getApplicationBuilder(); - rendererDi = applicationBuilder.dis.rendererDi; applicationBuilder.setEnvironmentToClusterFrame(); - applicationBuilder.beforeApplicationStart(({ rendererDi }) => { - rendererDi.override(hostedClusterIdInjectable, () => "some-hosted-cluster-id"); + applicationBuilder.beforeWindowStart((windowDi) => { + windowDi.override(hostedClusterIdInjectable, () => "some-hosted-cluster-id"); + windowDi.override(storageSaveDelayInjectable, () => 250); - rendererDi.override(storageSaveDelayInjectable, () => 250); - - rendererDi.override( + windowDi.override( directoryForLensLocalStorageInjectable, () => "/some-directory-for-lens-local-storage", ); @@ -54,9 +50,7 @@ describe("cluster - sidebar and tab navigation for extensions", () => { beforeEach(() => { someObservable = observable.box(false); - const getExtensionFake = getExtensionFakeFor(applicationBuilder); - - const testExtension = getExtensionFake({ + const testExtension = { id: "some-extension-id", name: "some-extension-name", @@ -130,29 +124,31 @@ describe("cluster - sidebar and tab navigation for extensions", () => { }, ], }, - }); + }; applicationBuilder.extensions.enable(testExtension); }); describe("given no state for expanded sidebar items exists, and navigated to child sidebar item, when rendered", () => { beforeEach(async () => { - applicationBuilder.beforeRender(({ rendererDi }) => { - const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken); - const route = rendererDi - .inject(routesInjectable) - .get() - .find( - matches({ - path: "/extension/some-extension-name/some-child-page-id", - }), - ); - - assert(route); - navigateToRoute(route); - }); - rendered = await applicationBuilder.render(); + + const windowDi = applicationBuilder.applicationWindow.only.di; + + const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken); + + const route = windowDi + .inject(routesInjectable) + .get() + .find( + matches({ + path: "/extension/some-extension-name/some-child-page-id", + }), + ); + + assert(route); + navigateToRoute(route); + }); it("renders", () => { @@ -178,8 +174,8 @@ describe("cluster - sidebar and tab navigation for extensions", () => { describe("given state for expanded sidebar items already exists, when rendered", () => { beforeEach(async () => { - applicationBuilder.beforeRender(async ({ rendererDi }) => { - const writeJsonFileFake = rendererDi.inject(writeJsonFileInjectable); + applicationBuilder.beforeWindowStart(async (windowDi) => { + const writeJsonFileFake = windowDi.inject(writeJsonFileInjectable); await writeJsonFileFake( "/some-directory-for-lens-local-storage/some-hosted-cluster-id.json", @@ -214,8 +210,8 @@ describe("cluster - sidebar and tab navigation for extensions", () => { describe("given state for expanded unknown sidebar items already exists, when rendered", () => { beforeEach(async () => { - applicationBuilder.beforeRender(async ({ rendererDi }) => { - const writeJsonFileFake = rendererDi.inject(writeJsonFileInjectable); + applicationBuilder.beforeWindowStart(async (windowDi) => { + const writeJsonFileFake = windowDi.inject(writeJsonFileInjectable); await writeJsonFileFake( "/some-directory-for-lens-local-storage/some-hosted-cluster-id.json", @@ -244,8 +240,8 @@ describe("cluster - sidebar and tab navigation for extensions", () => { describe("given empty state for expanded sidebar items already exists, when rendered", () => { beforeEach(async () => { - applicationBuilder.beforeRender(async ({ rendererDi }) => { - const writeJsonFileFake = rendererDi.inject(writeJsonFileInjectable); + applicationBuilder.beforeWindowStart(async (windowDi) => { + const writeJsonFileFake = windowDi.inject(writeJsonFileInjectable); await writeJsonFileFake( "/some-directory-for-lens-local-storage/some-hosted-cluster-id.json", @@ -270,8 +266,12 @@ describe("cluster - sidebar and tab navigation for extensions", () => { }); describe("given no initially persisted state for sidebar items, when rendered", () => { + let windowDi: DiContainer; + beforeEach(async () => { rendered = await applicationBuilder.render(); + + windowDi = applicationBuilder.applicationWindow.only.di; }); it("renders", () => { @@ -387,7 +387,7 @@ describe("cluster - sidebar and tab navigation for extensions", () => { it("when not enough time passes, does not store state for expanded sidebar items to file system yet", async () => { advanceFakeTime(250 - 1); - const pathExistsFake = rendererDi.inject(pathExistsInjectable); + const pathExistsFake = windowDi.inject(pathExistsInjectable); const actual = await pathExistsFake( "/some-directory-for-lens-local-storage/some-hosted-cluster-id.json", @@ -399,7 +399,7 @@ describe("cluster - sidebar and tab navigation for extensions", () => { it("when enough time passes, stores state for expanded sidebar items to file system", async () => { advanceFakeTime(250); - const readJsonFileFake = rendererDi.inject(readJsonFileInjectable); + const readJsonFileFake = windowDi.inject(readJsonFileInjectable); const actual = await readJsonFileFake( "/some-directory-for-lens-local-storage/some-hosted-cluster-id.json", diff --git a/src/behaviours/cluster/visibility-of-sidebar-items.test.tsx b/src/behaviours/cluster/visibility-of-sidebar-items.test.tsx index 2fb837b9ed..52224b7cd1 100644 --- a/src/behaviours/cluster/visibility-of-sidebar-items.test.tsx +++ b/src/behaviours/cluster/visibility-of-sidebar-items.test.tsx @@ -16,24 +16,24 @@ import { getApplicationBuilder } from "../../renderer/components/test-utils/get- import { navigateToRouteInjectionToken } from "../../common/front-end-routing/navigate-to-route-injection-token"; describe("cluster - visibility of sidebar items", () => { - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; let rendered: RenderResult; beforeEach(() => { - applicationBuilder = getApplicationBuilder(); + builder = getApplicationBuilder(); - applicationBuilder.setEnvironmentToClusterFrame(); + builder.setEnvironmentToClusterFrame(); - applicationBuilder.beforeApplicationStart(({ rendererDi }) => { - rendererDi.register(testRouteInjectable); - rendererDi.register(testRouteComponentInjectable); - rendererDi.register(testSidebarItemsInjectable); + builder.beforeWindowStart((windowDi) => { + windowDi.register(testRouteInjectable); + windowDi.register(testRouteComponentInjectable); + windowDi.register(testSidebarItemsInjectable); }); }); describe("given kube resource for route is not allowed", () => { beforeEach(async () => { - rendered = await applicationBuilder.render(); + rendered = await builder.render(); }); it("renders", () => { @@ -48,7 +48,7 @@ describe("cluster - visibility of sidebar items", () => { describe("when kube resource becomes allowed", () => { beforeEach(() => { - applicationBuilder.allowKubeResource("namespaces"); + builder.allowKubeResource("namespaces"); }); it("renders", () => { diff --git a/src/behaviours/cluster/workloads/overview/extension-api/disable-workloads-overview-details-when-cluster-is-not-relevant.test.tsx b/src/behaviours/cluster/workloads/overview/extension-api/disable-workloads-overview-details-when-cluster-is-not-relevant.test.tsx index 35a108dde9..4b19be2cb5 100644 --- a/src/behaviours/cluster/workloads/overview/extension-api/disable-workloads-overview-details-when-cluster-is-not-relevant.test.tsx +++ b/src/behaviours/cluster/workloads/overview/extension-api/disable-workloads-overview-details-when-cluster-is-not-relevant.test.tsx @@ -8,7 +8,6 @@ import type { RenderResult } from "@testing-library/react"; import type { ApplicationBuilder } from "../../../../../renderer/components/test-utils/get-application-builder"; import type { KubernetesCluster } from "../../../../../common/catalog-entities"; import { getApplicationBuilder } from "../../../../../renderer/components/test-utils/get-application-builder"; -import { getExtensionFakeFor } from "../../../../../renderer/components/test-utils/get-extension-fake"; import extensionShouldBeEnabledForClusterFrameInjectable from "../../../../../renderer/extension-loader/extension-should-be-enabled-for-cluster-frame.injectable"; import apiManagerInjectable from "../../../../../common/k8s-api/api-manager/manager.injectable"; import navigateToWorkloadsOverviewInjectable from "../../../../../common/front-end-routing/routes/cluster/workloads/overview/navigate-to-workloads-overview.injectable"; @@ -24,21 +23,19 @@ describe("disable workloads overview details when cluster is not relevant", () = beforeEach(async () => { builder = getApplicationBuilder(); - builder.beforeApplicationStart(({ mainDi }) => { + builder.setEnvironmentToClusterFrame(); + + builder.beforeApplicationStart((mainDi) => { mainDi.override(apiManagerInjectable, () => ({})); }); - const rendererDi = builder.dis.rendererDi; - - rendererDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable); - - builder.setEnvironmentToClusterFrame(); - - const getExtensionFake = getExtensionFakeFor(builder); + builder.beforeWindowStart((windowDi) => { + windowDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable); + }); isEnabledForClusterMock = asyncFn(); - const testExtension = getExtensionFake({ + const testExtension = { id: "test-extension-id", name: "test-extension", @@ -55,11 +52,13 @@ describe("disable workloads overview details when cluster is not relevant", () = }, ], }, - }); + }; rendered = await builder.render(); - const navigateToWorkloadsOverview = rendererDi.inject( + const windowDi = builder.applicationWindow.only.di; + + const navigateToWorkloadsOverview = windowDi.inject( navigateToWorkloadsOverviewInjectable, ); diff --git a/src/behaviours/cluster/workloads/overview/extension-api/order-of-workload-overview-details.test.tsx b/src/behaviours/cluster/workloads/overview/extension-api/order-of-workload-overview-details.test.tsx index eb19bbd400..70d9983f2b 100644 --- a/src/behaviours/cluster/workloads/overview/extension-api/order-of-workload-overview-details.test.tsx +++ b/src/behaviours/cluster/workloads/overview/extension-api/order-of-workload-overview-details.test.tsx @@ -4,7 +4,6 @@ */ import type { RenderResult } from "@testing-library/react"; import { getApplicationBuilder } from "../../../../../renderer/components/test-utils/get-application-builder"; -import { getExtensionFakeFor } from "../../../../../renderer/components/test-utils/get-extension-fake"; import React from "react"; import getRandomIdInjectable from "../../../../../common/utils/get-random-id.injectable"; import { workloadOverviewDetailInjectionToken } from "../../../../../renderer/components/+workloads-overview/workload-overview-details/workload-overview-detail-injection-token"; @@ -17,16 +16,22 @@ describe("order of workload overview details", () => { beforeEach(async () => { const builder = getApplicationBuilder(); - builder.beforeApplicationStart(({ rendererDi }) => { - rendererDi.unoverride(getRandomIdInjectable); - rendererDi.permitSideEffects(getRandomIdInjectable); + builder.beforeWindowStart((windowDi) => { + windowDi.unoverride(getRandomIdInjectable); + windowDi.permitSideEffects(getRandomIdInjectable); + + windowDi.register( + someCoreItemWithLowOrderNumberInjectable, + someCoreItemWithHighOrderNumberInjectable, + someCoreItemWithDefaultOrderNumberInjectable, + ); }); builder.setEnvironmentToClusterFrame(); rendered = await builder.render(); - const testExtension = getExtensionFakeFor(builder)({ + const testExtension = { id: "some-extension-id", name: "some-extension", @@ -66,16 +71,9 @@ describe("order of workload overview details", () => { }, ], }, - }); + }; builder.extensions.enable(testExtension); - - - builder.dis.rendererDi.register( - someCoreItemWithLowOrderNumberInjectable, - someCoreItemWithHighOrderNumberInjectable, - someCoreItemWithDefaultOrderNumberInjectable, - ); }); it("shows items in correct order", () => { diff --git a/src/behaviours/cluster/workloads/overview/extension-api/reactively-hide-workloads-overview-details-item.test.tsx b/src/behaviours/cluster/workloads/overview/extension-api/reactively-hide-workloads-overview-details-item.test.tsx index 3b02d3dad9..fbc8ceebca 100644 --- a/src/behaviours/cluster/workloads/overview/extension-api/reactively-hide-workloads-overview-details-item.test.tsx +++ b/src/behaviours/cluster/workloads/overview/extension-api/reactively-hide-workloads-overview-details-item.test.tsx @@ -9,7 +9,6 @@ import React from "react"; import navigateToWorkloadsOverviewInjectable from "../../../../../common/front-end-routing/routes/cluster/workloads/overview/navigate-to-workloads-overview.injectable"; import type { ApplicationBuilder } from "../../../../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../../../../renderer/components/test-utils/get-application-builder"; -import { getExtensionFakeFor } from "../../../../../renderer/components/test-utils/get-extension-fake"; describe("reactively hide workloads overview details item", () => { let builder: ApplicationBuilder; @@ -19,15 +18,11 @@ describe("reactively hide workloads overview details item", () => { beforeEach(async () => { builder = getApplicationBuilder(); - const rendererDi = builder.dis.rendererDi; - builder.setEnvironmentToClusterFrame(); - const getExtensionFake = getExtensionFakeFor(builder); - someObservable = observable.box(false); - const testExtension = getExtensionFake({ + const testExtension = { id: "test-extension-id", name: "test-extension", @@ -44,11 +39,13 @@ describe("reactively hide workloads overview details item", () => { }, ], }, - }); + }; rendered = await builder.render(); - const navigateToWorkloadsOverview = rendererDi.inject( + const windowDi = builder.applicationWindow.only.di; + + const navigateToWorkloadsOverview = windowDi.inject( navigateToWorkloadsOverviewInjectable, ); diff --git a/src/behaviours/command-pallet/keyboard-shortcuts.test.tsx b/src/behaviours/command-pallet/keyboard-shortcuts.test.tsx index fba09862e3..ddf18b2f76 100644 --- a/src/behaviours/command-pallet/keyboard-shortcuts.test.tsx +++ b/src/behaviours/command-pallet/keyboard-shortcuts.test.tsx @@ -9,17 +9,20 @@ import platformInjectable from "../../common/vars/platform.injectable"; import { type ApplicationBuilder, getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; describe("Command Pallet: keyboard shortcut tests", () => { - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; let rendered: RenderResult; beforeEach(async () => { - applicationBuilder = getApplicationBuilder(); + builder = getApplicationBuilder(); }); describe("when on macOS", () => { beforeEach(async () => { - applicationBuilder.dis.rendererDi.override(platformInjectable, () => "darwin"); - rendered = await applicationBuilder.render(); + builder.beforeWindowStart((windowDi) => { + windowDi.override(platformInjectable, () => "darwin"); + }); + + rendered = await builder.render(); }); it("renders", () => { @@ -83,8 +86,11 @@ describe("Command Pallet: keyboard shortcut tests", () => { describe("when on linux", () => { beforeEach(async () => { - applicationBuilder.dis.rendererDi.override(platformInjectable, () => "linux"); - rendered = await applicationBuilder.render(); + builder.beforeWindowStart((windowDi) => { + windowDi.override(platformInjectable, () => "linux"); + }); + + rendered = await builder.render(); }); it("renders", () => { diff --git a/src/behaviours/extension-special-characters-in-page-registrations.test.tsx b/src/behaviours/extension-special-characters-in-page-registrations.test.tsx index f30e300582..ac038a5743 100644 --- a/src/behaviours/extension-special-characters-in-page-registrations.test.tsx +++ b/src/behaviours/extension-special-characters-in-page-registrations.test.tsx @@ -2,30 +2,27 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { FakeExtensionData, TestExtension } from "../renderer/components/test-utils/get-renderer-extension-fake"; -import { getRendererExtensionFakeFor } from "../renderer/components/test-utils/get-renderer-extension-fake"; import React from "react"; import type { RenderResult } from "@testing-library/react"; import currentPathInjectable from "../renderer/routes/current-path.injectable"; import type { ApplicationBuilder } from "../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../renderer/components/test-utils/get-application-builder"; +import type { DiContainer } from "@ogre-tools/injectable"; +import type { FakeExtensionOptions } from "../renderer/components/test-utils/get-extension-fake"; describe("extension special characters in page registrations", () => { - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; let rendered: RenderResult; - let testExtension: TestExtension; + let windowDi: DiContainer; beforeEach(async () => { - applicationBuilder = getApplicationBuilder(); - const getRendererExtensionFake = getRendererExtensionFakeFor(applicationBuilder); + builder = getApplicationBuilder(); - testExtension = getRendererExtensionFake( - extensionWithPagesHavingSpecialCharacters, - ); + rendered = await builder.render(); - applicationBuilder.extensions.renderer.enable(testExtension); + builder.extensions.enable(extensionWithPagesHavingSpecialCharacters); - rendered = await applicationBuilder.render(); + windowDi = builder.applicationWindow.only.di; }); it("renders", () => { @@ -34,6 +31,9 @@ describe("extension special characters in page registrations", () => { describe("when navigating to route with ID having special characters", () => { beforeEach(() => { + const testExtension = + builder.extensions.get("some-extension-id").applicationWindows.only; + testExtension.navigate("/some-page-id/"); }); @@ -42,22 +42,25 @@ describe("extension special characters in page registrations", () => { }); it("knows URL", () => { - const currentPath = applicationBuilder.dis.rendererDi.inject(currentPathInjectable); + const currentPath = windowDi.inject(currentPathInjectable); expect(currentPath.get()).toBe("/extension/some-extension-name--/some-page-id"); }); }); }); -const extensionWithPagesHavingSpecialCharacters: FakeExtensionData = { +const extensionWithPagesHavingSpecialCharacters: FakeExtensionOptions = { id: "some-extension-id", name: "@some-extension-name/", - globalPages: [ - { - id: "/some-page-id/", - components: { - Page: () =>
Some page
, + + rendererOptions: { + globalPages: [ + { + id: "/some-page-id/", + components: { + Page: () =>
Some page
, + }, }, - }, - ], + ], + }, }; diff --git a/src/behaviours/extensions/navigation-using-application-menu.test.ts b/src/behaviours/extensions/navigation-using-application-menu.test.ts index a8b9cc55b1..a9e7e23b74 100644 --- a/src/behaviours/extensions/navigation-using-application-menu.test.ts +++ b/src/behaviours/extensions/navigation-using-application-menu.test.ts @@ -12,18 +12,20 @@ import focusWindowInjectable from "../../renderer/navigation/focus-window.inject jest.mock("../../renderer/components/input/input"); describe("extensions - navigation using application menu", () => { - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; let rendered: RenderResult; let focusWindowMock: jest.Mock; beforeEach(async () => { - applicationBuilder = getApplicationBuilder().beforeApplicationStart(({ rendererDi }) => { + builder = getApplicationBuilder(); + + builder.beforeWindowStart((windowDi) => { focusWindowMock = jest.fn(); - rendererDi.override(focusWindowInjectable, () => focusWindowMock); + windowDi.override(focusWindowInjectable, () => focusWindowMock); }); - rendered = await applicationBuilder.render(); + rendered = await builder.render(); }); it("renders", () => { @@ -38,7 +40,7 @@ describe("extensions - navigation using application menu", () => { describe("when navigating to extensions using application menu", () => { beforeEach(() => { - applicationBuilder.applicationMenu.click("root.extensions"); + builder.applicationMenu.click("root.extensions"); }); it("focuses the window", () => { diff --git a/src/behaviours/helm-charts/add-custom-helm-repository-in-preferences.test.ts b/src/behaviours/helm-charts/add-custom-helm-repository-in-preferences.test.ts index b8d9fd0661..d8e14d25fa 100644 --- a/src/behaviours/helm-charts/add-custom-helm-repository-in-preferences.test.ts +++ b/src/behaviours/helm-charts/add-custom-helm-repository-in-preferences.test.ts @@ -19,7 +19,7 @@ import showErrorNotificationInjectable from "../../renderer/components/notificat import type { AsyncResult } from "../../common/utils/async-result"; describe("add custom helm repository in preferences", () => { - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; let showSuccessNotificationMock: jest.Mock; let showErrorNotificationMock: jest.Mock; let rendered: RenderResult; @@ -31,41 +31,35 @@ describe("add custom helm repository in preferences", () => { beforeEach(async () => { jest.useFakeTimers(); - applicationBuilder = getApplicationBuilder(); + builder = getApplicationBuilder(); execFileMock = asyncFn(); getActiveHelmRepositoriesMock = asyncFn(); + showSuccessNotificationMock = jest.fn(); + showErrorNotificationMock = jest.fn(); - applicationBuilder.beforeApplicationStart(({ mainDi, rendererDi }) => { - rendererDi.override(callForPublicHelmRepositoriesInjectable, () => async () => []); - - showSuccessNotificationMock = jest.fn(); - - rendererDi.override(showSuccessNotificationInjectable, () => showSuccessNotificationMock); - - showErrorNotificationMock = jest.fn(); - - rendererDi.override(showErrorNotificationInjectable, () => showErrorNotificationMock); - - // TODO: Figure out how to make async validators unit testable - rendererDi.override(isPathInjectable, () => ({ debounce: 0, validate: async () => {} })); - - mainDi.override( - getActiveHelmRepositoriesInjectable, - () => getActiveHelmRepositoriesMock, - ); - + builder.beforeApplicationStart((mainDi) => { + mainDi.override(getActiveHelmRepositoriesInjectable, () => getActiveHelmRepositoriesMock); mainDi.override(execFileInjectable, () => execFileMock); mainDi.override(helmBinaryPathInjectable, () => "some-helm-binary-path"); }); - rendered = await applicationBuilder.render(); + builder.beforeWindowStart((windowDi) => { + windowDi.override(callForPublicHelmRepositoriesInjectable, () => async () => []); + windowDi.override(showSuccessNotificationInjectable, () => showSuccessNotificationMock); + windowDi.override(showErrorNotificationInjectable, () => showErrorNotificationMock); + + // TODO: Figure out how to make async validators unit testable + windowDi.override(isPathInjectable, () => ({ debounce: 0, validate: async () => {} })); + }); + + rendered = await builder.render(); }); describe("when navigating to preferences containing helm repositories", () => { beforeEach(async () => { - applicationBuilder.preferences.navigate(); - applicationBuilder.preferences.navigation.click("kubernetes"); + builder.preferences.navigate(); + builder.preferences.navigation.click("kubernetes"); }); it("renders", () => { diff --git a/src/behaviours/helm-charts/add-helm-repository-from-list-in-preferences.test.ts b/src/behaviours/helm-charts/add-helm-repository-from-list-in-preferences.test.ts index c16fcd893f..c46c30086e 100644 --- a/src/behaviours/helm-charts/add-helm-repository-from-list-in-preferences.test.ts +++ b/src/behaviours/helm-charts/add-helm-repository-from-list-in-preferences.test.ts @@ -17,7 +17,7 @@ import showErrorNotificationInjectable from "../../renderer/components/notificat import type { AsyncResult } from "../../common/utils/async-result"; describe("add helm repository from list in preferences", () => { - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; let showSuccessNotificationMock: jest.Mock; let showErrorNotificationMock: jest.Mock; let rendered: RenderResult; @@ -28,41 +28,33 @@ describe("add helm repository from list in preferences", () => { let callForPublicHelmRepositoriesMock: AsyncFnMock<() => Promise>; beforeEach(async () => { - applicationBuilder = getApplicationBuilder(); + builder = getApplicationBuilder(); execFileMock = asyncFn(); getActiveHelmRepositoriesMock = asyncFn(); callForPublicHelmRepositoriesMock = asyncFn(); + showSuccessNotificationMock = jest.fn(); + showErrorNotificationMock = jest.fn(); - applicationBuilder.beforeApplicationStart(({ mainDi, rendererDi }) => { - showSuccessNotificationMock = jest.fn(); - - rendererDi.override(showSuccessNotificationInjectable, () => showSuccessNotificationMock); - - showErrorNotificationMock = jest.fn(); - - rendererDi.override(showErrorNotificationInjectable, () => showErrorNotificationMock); - - rendererDi.override( - callForPublicHelmRepositoriesInjectable, - () => callForPublicHelmRepositoriesMock, - ); - - mainDi.override( - getActiveHelmRepositoriesInjectable, - () => getActiveHelmRepositoriesMock, - ); + builder.beforeApplicationStart((mainDi) => { + mainDi.override(getActiveHelmRepositoriesInjectable, () => getActiveHelmRepositoriesMock); mainDi.override(execFileInjectable, () => execFileMock); mainDi.override(helmBinaryPathInjectable, () => "some-helm-binary-path"); }); - rendered = await applicationBuilder.render(); + builder.beforeWindowStart((windowDi) => { + windowDi.override(showSuccessNotificationInjectable, () => showSuccessNotificationMock); + windowDi.override(showErrorNotificationInjectable, () => showErrorNotificationMock); + windowDi.override(callForPublicHelmRepositoriesInjectable, () => callForPublicHelmRepositoriesMock); + }); + + rendered = await builder.render(); }); describe("when navigating to preferences containing helm repositories", () => { - beforeEach(async () => { - applicationBuilder.preferences.navigate(); - applicationBuilder.preferences.navigation.click("kubernetes"); + beforeEach(() => { + builder.preferences.navigate(); + builder.preferences.navigation.click("kubernetes"); }); it("renders", () => { @@ -100,7 +92,7 @@ describe("add helm repository from list in preferences", () => { describe("when select for adding public repositories is clicked", () => { beforeEach(() => { - applicationBuilder.select.openMenu( + builder.select.openMenu( "selection-of-active-public-helm-repository", ); }); @@ -113,7 +105,7 @@ describe("add helm repository from list in preferences", () => { beforeEach(async () => { getActiveHelmRepositoriesMock.mockClear(); - applicationBuilder.select.selectOption( + builder.select.selectOption( "selection-of-active-public-helm-repository", "Some to be added repository", ); @@ -207,7 +199,7 @@ describe("add helm repository from list in preferences", () => { describe("when select for selecting active repositories is clicked", () => { beforeEach(() => { - applicationBuilder.select.openMenu( + builder.select.openMenu( "selection-of-active-public-helm-repository", ); }); @@ -221,7 +213,7 @@ describe("add helm repository from list in preferences", () => { execFileMock.mockClear(); getActiveHelmRepositoriesMock.mockClear(); - applicationBuilder.select.selectOption( + builder.select.selectOption( "selection-of-active-public-helm-repository", "Some already active repository", ); diff --git a/src/behaviours/helm-charts/installing-chart/installing-helm-chart-from-new-tab.test.ts b/src/behaviours/helm-charts/installing-chart/installing-helm-chart-from-new-tab.test.ts index 4da41f669d..395522a751 100644 --- a/src/behaviours/helm-charts/installing-chart/installing-helm-chart-from-new-tab.test.ts +++ b/src/behaviours/helm-charts/installing-chart/installing-helm-chart-from-new-tab.test.ts @@ -23,7 +23,6 @@ import type { CallForHelmChartReadme } from "../../../renderer/components/+helm- import callForHelmChartReadmeInjectable from "../../../renderer/components/+helm-charts/details/readme/call-for-helm-chart-readme.injectable"; import type { CallForHelmChartVersions } from "../../../renderer/components/+helm-charts/details/versions/call-for-helm-chart-versions.injectable"; import callForHelmChartVersionsInjectable from "../../../renderer/components/+helm-charts/details/versions/call-for-helm-chart-versions.injectable"; -import { overrideFsWithFakes } from "../../../test-utils/override-fs-with-fakes"; import writeJsonFileInjectable from "../../../common/fs/write-json-file.injectable"; import directoryForLensLocalStorageInjectable from "../../../common/directory-for-lens-local-storage/directory-for-lens-local-storage.injectable"; import hostedClusterIdInjectable from "../../../renderer/cluster-frame-context/hosted-cluster-id.injectable"; @@ -33,7 +32,6 @@ import type { DiContainer } from "@ogre-tools/injectable"; describe("installing helm chart from new tab", () => { let builder: ApplicationBuilder; - let rendererDi: DiContainer; let callForHelmChartsMock: AsyncFnMock; let callForHelmChartVersionsMock: AsyncFnMock; let callForHelmChartReadmeMock: AsyncFnMock; @@ -43,9 +41,7 @@ describe("installing helm chart from new tab", () => { beforeEach(() => { builder = getApplicationBuilder(); - rendererDi = builder.dis.rendererDi; - - overrideFsWithFakes(rendererDi); + builder.setEnvironmentToClusterFrame(); callForHelmChartsMock = asyncFn(); callForHelmChartVersionsMock = asyncFn(); @@ -53,41 +49,41 @@ describe("installing helm chart from new tab", () => { callForHelmChartValuesMock = asyncFn(); callForCreateHelmReleaseMock = asyncFn(); - builder.beforeApplicationStart(({ rendererDi }) => { - rendererDi.override( + builder.beforeWindowStart((windowDi) => { + windowDi.override( directoryForLensLocalStorageInjectable, () => "/some-directory-for-lens-local-storage", ); - rendererDi.override(hostedClusterIdInjectable, () => "some-cluster-id"); + windowDi.override(hostedClusterIdInjectable, () => "some-cluster-id"); - rendererDi.override( + windowDi.override( callForHelmChartsInjectable, () => callForHelmChartsMock, ); - rendererDi.override( + windowDi.override( callForHelmChartVersionsInjectable, () => callForHelmChartVersionsMock, ); - rendererDi.override( + windowDi.override( callForHelmChartReadmeInjectable, () => callForHelmChartReadmeMock, ); - rendererDi.override( + windowDi.override( callForHelmChartValuesInjectable, () => callForHelmChartValuesMock, ); - rendererDi.override( + windowDi.override( callForCreateHelmReleaseInjectable, () => callForCreateHelmReleaseMock, ); // TODO: Replace store mocking with mock for the actual side-effect (where the namespaces are coming from) - rendererDi.override( + windowDi.override( namespaceStoreInjectable, () => ({ @@ -100,31 +96,32 @@ describe("installing helm chart from new tab", () => { } as unknown as NamespaceStore), ); - rendererDi.override(getRandomInstallChartTabIdInjectable, () => + windowDi.override(getRandomInstallChartTabIdInjectable, () => jest .fn(() => "some-irrelevant-tab-id") .mockReturnValueOnce("some-first-tab-id") .mockReturnValueOnce("some-second-tab-id"), ); }); - - builder.setEnvironmentToClusterFrame(); }); describe("given tab for installing chart was not previously opened and application is started, when navigating to helm charts", () => { let rendered: RenderResult; + let windowDi: DiContainer; beforeEach(async () => { rendered = await builder.render(); + windowDi = builder.applicationWindow.only.di; + builder.helmCharts.navigate({ chartName: "some-name", repo: "some-repository", }); - const writeJsonFile = rendererDi.inject(writeJsonFileInjectable); + const writeJsonFile = windowDi.inject(writeJsonFileInjectable); - writeJsonFile( + await writeJsonFile( "/some-directory-for-lens-local-storage/some-cluster-id.json", { dock: { @@ -135,7 +132,7 @@ describe("installing helm chart from new tab", () => { }, ); - const dockStore = rendererDi.inject(dockStoreInjectable); + const dockStore = windowDi.inject(dockStoreInjectable); // TODO: Make TerminalWindow unit testable to allow realistic behaviour dockStore.closeTab("terminal"); @@ -211,7 +208,7 @@ describe("installing helm chart from new tab", () => { await callForHelmChartReadmeMock.resolve("some-readme"); }); - it("renders", () => { + fit("renders", () => { expect(rendered.baseElement).toMatchSnapshot(); }); @@ -435,7 +432,7 @@ describe("installing helm chart from new tab", () => { }); it("shows the details of installed release", () => { - const currentPath = rendererDi + const currentPath = windowDi .inject(currentPathInjectable) .get(); @@ -723,7 +720,7 @@ describe("installing helm chart from new tab", () => { }); it("stores the selected version", async () => { - const readJsonFile = rendererDi.inject(readJsonFileInjectable); + const readJsonFile = windowDi.inject(readJsonFileInjectable); const actual = await readJsonFile( "/some-directory-for-lens-local-storage/some-cluster-id.json", @@ -800,7 +797,7 @@ describe("installing helm chart from new tab", () => { }); it("stores the selected namespace", async () => { - const readJsonFile = rendererDi.inject(readJsonFileInjectable); + const readJsonFile = windowDi.inject(readJsonFileInjectable); const actual = await readJsonFile( "/some-directory-for-lens-local-storage/some-cluster-id.json", @@ -913,7 +910,7 @@ describe("installing helm chart from new tab", () => { }); it("stores the changed configuration", async () => { - const readJsonFile = rendererDi.inject(readJsonFileInjectable); + const readJsonFile = windowDi.inject(readJsonFileInjectable); const actual = await readJsonFile( "/some-directory-for-lens-local-storage/some-cluster-id.json", @@ -981,7 +978,7 @@ describe("installing helm chart from new tab", () => { }); it("stores the changed custom name", async () => { - const readJsonFile = rendererDi.inject(readJsonFileInjectable); + const readJsonFile = windowDi.inject(readJsonFileInjectable); const actual = await readJsonFile( "/some-directory-for-lens-local-storage/some-cluster-id.json", diff --git a/src/behaviours/helm-charts/installing-chart/installing-helm-chart-from-previously-opened-tab.test.ts b/src/behaviours/helm-charts/installing-chart/installing-helm-chart-from-previously-opened-tab.test.ts index c9fa77f8aa..c49f3a7942 100644 --- a/src/behaviours/helm-charts/installing-chart/installing-helm-chart-from-previously-opened-tab.test.ts +++ b/src/behaviours/helm-charts/installing-chart/installing-helm-chart-from-previously-opened-tab.test.ts @@ -15,18 +15,15 @@ import namespaceStoreInjectable from "../../../renderer/components/+namespaces/s import type { NamespaceStore } from "../../../renderer/components/+namespaces/store"; import type { CallForHelmChartVersions } from "../../../renderer/components/+helm-charts/details/versions/call-for-helm-chart-versions.injectable"; import callForHelmChartVersionsInjectable from "../../../renderer/components/+helm-charts/details/versions/call-for-helm-chart-versions.injectable"; -import { overrideFsWithFakes } from "../../../test-utils/override-fs-with-fakes"; import writeJsonFileInjectable from "../../../common/fs/write-json-file.injectable"; import directoryForLensLocalStorageInjectable from "../../../common/directory-for-lens-local-storage/directory-for-lens-local-storage.injectable"; import hostedClusterIdInjectable from "../../../renderer/cluster-frame-context/hosted-cluster-id.injectable"; import { TabKind } from "../../../renderer/components/dock/dock/store"; import { controlWhenStoragesAreReady } from "../../../renderer/utils/create-storage/storages-are-ready"; -import type { DiContainer } from "@ogre-tools/injectable"; import callForCreateHelmReleaseInjectable from "../../../renderer/components/+helm-releases/create-release/call-for-create-helm-release.injectable"; describe("installing helm chart from previously opened tab", () => { let builder: ApplicationBuilder; - let rendererDi: DiContainer; let callForHelmChartVersionsMock: AsyncFnMock; let callForHelmChartValuesMock: AsyncFnMock; let storagesAreReady: () => Promise; @@ -34,45 +31,43 @@ describe("installing helm chart from previously opened tab", () => { beforeEach(() => { builder = getApplicationBuilder(); - rendererDi = builder.dis.rendererDi; - - overrideFsWithFakes(rendererDi); + builder.setEnvironmentToClusterFrame(); callForHelmChartVersionsMock = asyncFn(); callForHelmChartValuesMock = asyncFn(); - builder.beforeApplicationStart(({ rendererDi }) => { - rendererDi.override( + builder.beforeWindowStart((windowDi) => { + windowDi.override( directoryForLensLocalStorageInjectable, () => "/some-directory-for-lens-local-storage", ); - rendererDi.override(hostedClusterIdInjectable, () => "some-cluster-id"); + windowDi.override(hostedClusterIdInjectable, () => "some-cluster-id"); - storagesAreReady = controlWhenStoragesAreReady(rendererDi); + storagesAreReady = controlWhenStoragesAreReady(windowDi); - rendererDi.override( + windowDi.override( callForHelmChartVersionsInjectable, () => callForHelmChartVersionsMock, ); - rendererDi.override( + windowDi.override( callForHelmChartValuesInjectable, () => callForHelmChartValuesMock, ); - rendererDi.override( + windowDi.override( callForHelmChartValuesInjectable, () => callForHelmChartValuesMock, ); - rendererDi.override( + windowDi.override( callForCreateHelmReleaseInjectable, () => jest.fn(), ); // TODO: Replace store mocking with mock for the actual side-effect (where the namespaces are coming from) - rendererDi.override( + windowDi.override( namespaceStoreInjectable, () => ({ @@ -85,51 +80,51 @@ describe("installing helm chart from previously opened tab", () => { } as unknown as NamespaceStore), ); - rendererDi.override(getRandomInstallChartTabIdInjectable, () => + windowDi.override(getRandomInstallChartTabIdInjectable, () => jest .fn(() => "some-irrelevant-tab-id") .mockReturnValueOnce("some-first-tab-id"), ); }); - - builder.setEnvironmentToClusterFrame(); }); describe("given tab for installing chart was previously opened, when application is started", () => { let rendered: RenderResult; beforeEach(async () => { - const writeJsonFile = rendererDi.inject(writeJsonFileInjectable); + builder.beforeWindowStart(async (windowDi) => { + const writeJsonFile = windowDi.inject(writeJsonFileInjectable); - writeJsonFile( - "/some-directory-for-lens-local-storage/some-cluster-id.json", - { - dock: { - height: 300, - tabs: [ - { - id: "some-first-tab-id", - kind: TabKind.INSTALL_CHART, - title: "Helm Install: some-repository/some-name", - pinned: false, + await writeJsonFile( + "/some-directory-for-lens-local-storage/some-cluster-id.json", + { + dock: { + height: 300, + tabs: [ + { + id: "some-first-tab-id", + kind: TabKind.INSTALL_CHART, + title: "Helm Install: some-repository/some-name", + pinned: false, + }, + ], + + isOpen: true, + }, + + install_charts: { + "some-first-tab-id": { + name: "some-name", + repo: "some-repository", + version: "some-other-version", + values: "some-stored-configuration", + releaseName: "some-stored-custom-name", + namespace: "some-other-namespace", }, - ], - - isOpen: true, - }, - - install_charts: { - "some-first-tab-id": { - name: "some-name", - repo: "some-repository", - version: "some-other-version", - values: "some-stored-configuration", - releaseName: "some-stored-custom-name", - namespace: "some-other-namespace", }, }, - }, - ); + ); + }); rendered = await builder.render(); diff --git a/src/behaviours/helm-charts/installing-chart/opening-dock-tab-for-installing-helm-chart.test.ts b/src/behaviours/helm-charts/installing-chart/opening-dock-tab-for-installing-helm-chart.test.ts index 16c4f236a3..ddc682afd2 100644 --- a/src/behaviours/helm-charts/installing-chart/opening-dock-tab-for-installing-helm-chart.test.ts +++ b/src/behaviours/helm-charts/installing-chart/opening-dock-tab-for-installing-helm-chart.test.ts @@ -19,15 +19,12 @@ import callForHelmChartReadmeInjectable from "../../../renderer/components/+helm import type { CallForHelmChartVersions } from "../../../renderer/components/+helm-charts/details/versions/call-for-helm-chart-versions.injectable"; import callForHelmChartVersionsInjectable from "../../../renderer/components/+helm-charts/details/versions/call-for-helm-chart-versions.injectable"; import { flushPromises } from "../../../common/test-utils/flush-promises"; -import { overrideFsWithFakes } from "../../../test-utils/override-fs-with-fakes"; import directoryForLensLocalStorageInjectable from "../../../common/directory-for-lens-local-storage/directory-for-lens-local-storage.injectable"; import hostedClusterIdInjectable from "../../../renderer/cluster-frame-context/hosted-cluster-id.injectable"; import dockStoreInjectable from "../../../renderer/components/dock/dock/store.injectable"; -import type { DiContainer } from "@ogre-tools/injectable"; describe("opening dock tab for installing helm chart", () => { let builder: ApplicationBuilder; - let rendererDi: DiContainer; let callForHelmChartsMock: AsyncFnMock; let callForHelmChartVersionsMock: AsyncFnMock; let callForHelmChartReadmeMock: AsyncFnMock; @@ -36,49 +33,45 @@ describe("opening dock tab for installing helm chart", () => { beforeEach(() => { builder = getApplicationBuilder(); - rendererDi = builder.dis.rendererDi; - - overrideFsWithFakes(rendererDi); - callForHelmChartsMock = asyncFn(); callForHelmChartVersionsMock = asyncFn(); callForHelmChartReadmeMock = asyncFn(); callForHelmChartValuesMock = jest.fn(); - builder.beforeApplicationStart(({ rendererDi }) => { - rendererDi.override( + builder.beforeWindowStart((windowDi) => { + windowDi.override( directoryForLensLocalStorageInjectable, () => "/some-directory-for-lens-local-storage", ); - rendererDi.override(hostedClusterIdInjectable, () => "some-cluster-id"); + windowDi.override(hostedClusterIdInjectable, () => "some-cluster-id"); - rendererDi.override( + windowDi.override( callForHelmChartsInjectable, () => callForHelmChartsMock, ); - rendererDi.override( + windowDi.override( callForHelmChartVersionsInjectable, () => callForHelmChartVersionsMock, ); - rendererDi.override( + windowDi.override( callForHelmChartReadmeInjectable, () => callForHelmChartReadmeMock, ); - rendererDi.override( + windowDi.override( callForHelmChartValuesInjectable, () => callForHelmChartValuesMock, ); - rendererDi.override( + windowDi.override( callForCreateHelmReleaseInjectable, () => jest.fn(), ); - rendererDi.override(getRandomInstallChartTabIdInjectable, () => + windowDi.override(getRandomInstallChartTabIdInjectable, () => jest .fn(() => "some-irrelevant-tab-id") .mockReturnValueOnce("some-tab-id"), @@ -96,7 +89,9 @@ describe("opening dock tab for installing helm chart", () => { builder.helmCharts.navigate(); - const dockStore = rendererDi.inject(dockStoreInjectable); + const windowDi = builder.applicationWindow.only.di; + + const dockStore = windowDi.inject(dockStoreInjectable); // TODO: Make TerminalWindow unit testable to allow realistic behaviour dockStore.closeTab("terminal"); diff --git a/src/behaviours/helm-charts/listing-active-helm-repositories-in-preferences.test.ts b/src/behaviours/helm-charts/listing-active-helm-repositories-in-preferences.test.ts index d7939e890a..395b4c2c8a 100644 --- a/src/behaviours/helm-charts/listing-active-helm-repositories-in-preferences.test.ts +++ b/src/behaviours/helm-charts/listing-active-helm-repositories-in-preferences.test.ts @@ -18,7 +18,7 @@ import callForPublicHelmRepositoriesInjectable from "../../renderer/components/+ import showErrorNotificationInjectable from "../../renderer/components/notifications/show-error-notification.injectable"; describe("listing active helm repositories in preferences", () => { - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; let rendered: RenderResult; let readYamlFileMock: AsyncFnMock; let execFileMock: AsyncFnMock>; @@ -26,31 +26,33 @@ describe("listing active helm repositories in preferences", () => { let showErrorNotificationMock: jest.Mock; beforeEach(async () => { - applicationBuilder = getApplicationBuilder(); + builder = getApplicationBuilder(); readYamlFileMock = asyncFn(); execFileMock = asyncFn(); + showErrorNotificationMock = jest.fn(); loggerStub = { error: jest.fn() } as unknown as Logger; - applicationBuilder.beforeApplicationStart(({ mainDi, rendererDi }) => { - showErrorNotificationMock = jest.fn(); - - rendererDi.override(showErrorNotificationInjectable, () => showErrorNotificationMock); - rendererDi.override(callForPublicHelmRepositoriesInjectable, () => async () => []); + builder.beforeApplicationStart((mainDi) => { mainDi.override(readYamlFileInjectable, () => readYamlFileMock); mainDi.override(execFileInjectable, () => execFileMock); mainDi.override(helmBinaryPathInjectable, () => "some-helm-binary-path"); mainDi.override(loggerInjectable, () => loggerStub); }); - rendered = await applicationBuilder.render(); + builder.beforeWindowStart((windowDi) => { + windowDi.override(showErrorNotificationInjectable, () => showErrorNotificationMock); + windowDi.override(callForPublicHelmRepositoriesInjectable, () => async () => []); + }); + + rendered = await builder.render(); }); describe("when navigating to preferences containing helm repositories", () => { beforeEach(async () => { - applicationBuilder.preferences.navigate(); - applicationBuilder.preferences.navigation.click("kubernetes"); + builder.preferences.navigate(); + builder.preferences.navigation.click("kubernetes"); }); it("renders", () => { diff --git a/src/behaviours/helm-charts/remove-helm-repository-from-list-of-active-repository-in-preferences.test.ts b/src/behaviours/helm-charts/remove-helm-repository-from-list-of-active-repository-in-preferences.test.ts index ca7ec95b24..1eb6b7b832 100644 --- a/src/behaviours/helm-charts/remove-helm-repository-from-list-of-active-repository-in-preferences.test.ts +++ b/src/behaviours/helm-charts/remove-helm-repository-from-list-of-active-repository-in-preferences.test.ts @@ -16,7 +16,7 @@ import callForPublicHelmRepositoriesInjectable from "../../renderer/components/+ import type { AsyncResult } from "../../common/utils/async-result"; describe("remove helm repository from list of active repositories in preferences", () => { - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; let rendered: RenderResult; let getActiveHelmRepositoriesMock: AsyncFnMock<() => Promise>>; let execFileMock: AsyncFnMock< @@ -24,30 +24,28 @@ describe("remove helm repository from list of active repositories in preferences >; beforeEach(async () => { - applicationBuilder = getApplicationBuilder(); + builder = getApplicationBuilder(); execFileMock = asyncFn(); getActiveHelmRepositoriesMock = asyncFn(); - applicationBuilder.beforeApplicationStart(({ mainDi, rendererDi }) => { - rendererDi.override(callForPublicHelmRepositoriesInjectable, () => async () => []); - - mainDi.override( - getActiveHelmRepositoriesInjectable, - () => getActiveHelmRepositoriesMock, - ); - + builder.beforeApplicationStart((mainDi) => { + mainDi.override(getActiveHelmRepositoriesInjectable, () => getActiveHelmRepositoriesMock); mainDi.override(execFileInjectable, () => execFileMock); mainDi.override(helmBinaryPathInjectable, () => "some-helm-binary-path"); }); - rendered = await applicationBuilder.render(); + builder.beforeWindowStart((windowDi) => { + windowDi.override(callForPublicHelmRepositoriesInjectable, () => async () => []); + }); + + rendered = await builder.render(); }); describe("when navigating to preferences containing helm repositories", () => { beforeEach(async () => { - applicationBuilder.preferences.navigate(); - applicationBuilder.preferences.navigation.click("kubernetes"); + builder.preferences.navigate(); + builder.preferences.navigation.click("kubernetes"); }); it("renders", () => { diff --git a/src/behaviours/helm-releases/showing-details-for-helm-release.test.ts b/src/behaviours/helm-releases/showing-details-for-helm-release.test.ts index a2349302b1..37d9b05fc5 100644 --- a/src/behaviours/helm-releases/showing-details-for-helm-release.test.ts +++ b/src/behaviours/helm-releases/showing-details-for-helm-release.test.ts @@ -48,43 +48,43 @@ describe("showing details for helm release", () => { showSuccessNotificationMock = jest.fn(); showCheckedErrorNotificationMock = jest.fn(); - builder.beforeApplicationStart(({ rendererDi }) => { - rendererDi.override( + builder.beforeWindowStart((windowDi) => { + windowDi.override( getRandomUpgradeChartTabIdInjectable, () => () => "some-tab-id", ); - rendererDi.override( + windowDi.override( showSuccessNotificationInjectable, () => showSuccessNotificationMock, ); - rendererDi.override( + windowDi.override( showCheckedErrorInjectable, () => showCheckedErrorNotificationMock, ); - rendererDi.override( + windowDi.override( callForHelmReleasesInjectable, () => callForHelmReleasesMock, ); - rendererDi.override( + windowDi.override( callForHelmReleaseInjectable, () => callForHelmReleaseMock, ); - rendererDi.override( + windowDi.override( callForHelmReleaseConfigurationInjectable, () => callForHelmReleaseConfigurationMock, ); - rendererDi.override( + windowDi.override( callForHelmReleaseUpdateInjectable, () => callForHelmReleaseUpdateMock, ); - rendererDi.override( + windowDi.override( namespaceStoreInjectable, () => ({ @@ -105,9 +105,9 @@ describe("showing details for helm release", () => { describe("when navigating to helm releases", () => { beforeEach(() => { - const rendererDi = builder.dis.rendererDi; + const windowDi = builder.applicationWindow.only.di; - const navigateToHelmReleases = rendererDi.inject( + const navigateToHelmReleases = windowDi.inject( navigateToHelmReleasesInjectable, ); diff --git a/src/behaviours/navigate-to-extension-page.test.tsx b/src/behaviours/navigate-to-extension-page.test.tsx index f78a8493d8..24f5ec729b 100644 --- a/src/behaviours/navigate-to-extension-page.test.tsx +++ b/src/behaviours/navigate-to-extension-page.test.tsx @@ -2,8 +2,6 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { FakeExtensionData, TestExtension } from "../renderer/components/test-utils/get-renderer-extension-fake"; -import { getRendererExtensionFakeFor } from "../renderer/components/test-utils/get-renderer-extension-fake"; import React from "react"; import type { RenderResult } from "@testing-library/react"; import { fireEvent } from "@testing-library/react"; @@ -12,29 +10,29 @@ import queryParametersInjectable from "../renderer/routes/query-parameters.injec import currentPathInjectable from "../renderer/routes/current-path.injectable"; import type { IComputedValue } from "mobx"; import { getApplicationBuilder } from "../renderer/components/test-utils/get-application-builder"; +import type { FakeExtensionOptions } from "../renderer/components/test-utils/get-extension-fake"; +import type { LensRendererExtension } from "../extensions/lens-renderer-extension"; describe("navigate to extension page", () => { let rendered: RenderResult; - let testExtension: TestExtension; + let testExtension: LensRendererExtension; let queryParameters: IComputedValue; let currentPath: IComputedValue; beforeEach(async () => { - const applicationBuilder = getApplicationBuilder(); - const getRendererExtensionFake = getRendererExtensionFakeFor(applicationBuilder); + const builder = getApplicationBuilder(); - testExtension = getRendererExtensionFake( - extensionWithPagesHavingParameters, - ); + builder.extensions.enable(extensionWithPagesHavingParameters); - applicationBuilder.extensions.renderer.enable(testExtension); + rendered = await builder.render(); - rendered = await applicationBuilder.render(); + const windowDi = builder.applicationWindow.only.di; - const rendererDi = applicationBuilder.dis.rendererDi; + testExtension = + builder.extensions.get("some-extension-id").applicationWindows.only; - queryParameters = rendererDi.inject(queryParametersInjectable); - currentPath = rendererDi.inject(currentPathInjectable); + queryParameters = windowDi.inject(queryParametersInjectable); + currentPath = windowDi.inject(currentPathInjectable); }); it("renders", () => { @@ -125,57 +123,60 @@ describe("navigate to extension page", () => { }); }); -const extensionWithPagesHavingParameters: FakeExtensionData = { +const extensionWithPagesHavingParameters: FakeExtensionOptions = { id: "some-extension-id", name: "some-extension-name", - globalPages: [ - { - components: { - Page: ({ params }) => ( -
-
    -
  • {params.someStringParameter.get()}
  • -
  • {params.someNumberParameter.get()}
  • -
  • {params.someArrayParameter.get().join(",")}
  • -
- -
- ), - }, + rendererOptions: { + globalPages: [ + { + components: { + Page: ({ params }) => ( +
+
    +
  • {params.someStringParameter.get()}
  • +
  • {params.someNumberParameter.get()}
  • +
  • {params.someArrayParameter.get().join(",")}
  • +
- params: { - someStringParameter: "some-string-value", - someNumberParameter: { - defaultValue: 42, - stringify: (value) => value.toString(), - parse: (value) => (value ? Number(value) : undefined), + +
+ ), }, - someArrayParameter: { - defaultValue: ["some-array-value", "some-other-array-value"], - stringify: (value) => value.join(","), - parse: (value: string[]) => (!isEmpty(value) ? value : undefined), + + params: { + someStringParameter: "some-string-value", + someNumberParameter: { + defaultValue: 42, + stringify: (value) => value.toString(), + parse: (value) => (value ? Number(value) : undefined), + }, + someArrayParameter: { + defaultValue: ["some-array-value", "some-other-array-value"], + stringify: (value) => value.join(","), + parse: (value: string[]) => (!isEmpty(value) ? value : undefined), + }, }, }, - }, - { - id: "some-child-page-id", - components: { - Page: () =>
Child page
, + { + id: "some-child-page-id", + components: { + Page: () =>
Child page
, + }, }, - }, - ], + ], + }, }; diff --git a/src/behaviours/navigating-between-routes.test.tsx b/src/behaviours/navigating-between-routes.test.tsx index 4758fb4074..bcff0e2a11 100644 --- a/src/behaviours/navigating-between-routes.test.tsx +++ b/src/behaviours/navigating-between-routes.test.tsx @@ -20,32 +20,34 @@ import { navigateToRouteInjectionToken } from "../common/front-end-routing/navig import routePathParametersInjectable from "../renderer/routes/route-path-parameters.injectable"; describe("navigating between routes", () => { - let rendererDi: DiContainer; let rendered: RenderResult; - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; beforeEach(async () => { - applicationBuilder = getApplicationBuilder(); - rendererDi = applicationBuilder.dis.rendererDi; + builder = getApplicationBuilder(); }); describe("given route without path parameters", () => { + let windowDi: DiContainer; + beforeEach(async () => { - applicationBuilder.beforeApplicationStart(({ rendererDi }) => { - rendererDi.register(testRouteWithoutPathParametersInjectable); - rendererDi.register(testRouteWithoutPathParametersComponentInjectable); + builder.beforeWindowStart((windowDi) => { + windowDi.register(testRouteWithoutPathParametersInjectable); + windowDi.register(testRouteWithoutPathParametersComponentInjectable); }); - rendered = await applicationBuilder.render(); + rendered = await builder.render(); + + windowDi = builder.applicationWindow.only.di; }); describe("when navigating to route", () => { let route: Route; beforeEach(() => { - const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken); + const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken); - route = rendererDi.inject(testRouteWithoutPathParametersInjectable); + route = windowDi.inject(testRouteWithoutPathParametersInjectable); navigateToRoute(route); }); @@ -55,35 +57,35 @@ describe("navigating between routes", () => { }); it("knows current route", () => { - const currentRoute = rendererDi.inject(currentRouteInjectable); + const currentRoute = windowDi.inject(currentRouteInjectable); expect(currentRoute.get()).toBe(route); }); it("knows current path", () => { - const currentPath = rendererDi.inject(currentPathInjectable); + const currentPath = windowDi.inject(currentPathInjectable); expect(currentPath.get()).toBe("/some-path"); }); it("does not have query parameters", () => { - const queryParameters = rendererDi.inject(queryParametersInjectable); + const queryParameters = windowDi.inject(queryParametersInjectable); expect(queryParameters.get()).toEqual({}); }); it("does not have path parameters", () => { - const pathParameters = rendererDi.inject(routePathParametersInjectable, route); + const pathParameters = windowDi.inject(routePathParametersInjectable, route); expect(pathParameters.get()).toEqual({}); }); }); it("when navigating to route with query parameters, knows query parameters", () => { - const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken); - const queryParameters = rendererDi.inject(queryParametersInjectable); + const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken); + const queryParameters = windowDi.inject(queryParametersInjectable); - const route = rendererDi.inject(testRouteWithoutPathParametersInjectable); + const route = windowDi.inject(testRouteWithoutPathParametersInjectable); navigateToRoute(route, { query: { @@ -100,23 +102,26 @@ describe("navigating between routes", () => { }); describe("given route with optional path parameters", () => { + let windowDi: DiContainer; + beforeEach(async () => { - applicationBuilder.beforeApplicationStart(({ rendererDi }) => { - rendererDi.register(routeWithOptionalPathParametersInjectable); - rendererDi.register(routeWithOptionalPathParametersComponentInjectable); + builder.beforeWindowStart((windowDi) => { + windowDi.register(routeWithOptionalPathParametersInjectable); + windowDi.register(routeWithOptionalPathParametersComponentInjectable); }); + rendered = await builder.render(); - rendered = await applicationBuilder.render(); + windowDi = builder.applicationWindow.only.di; }); describe("when navigating to route with path parameters", () => { let route: Route; beforeEach(() => { - route = rendererDi.inject(routeWithOptionalPathParametersInjectable); + route = windowDi.inject(routeWithOptionalPathParametersInjectable); - const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken); + const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken); navigateToRoute(route, { parameters: { @@ -131,13 +136,13 @@ describe("navigating between routes", () => { }); it("knows current route", () => { - const currentRoute = rendererDi.inject(currentRouteInjectable); + const currentRoute = windowDi.inject(currentRouteInjectable); expect(currentRoute.get()).toBe(route); }); it("knows current path", () => { - const currentPath = rendererDi.inject(currentPathInjectable); + const currentPath = windowDi.inject(currentPathInjectable); expect(currentPath.get()).toBe( "/some-path/some-value/some-other-value", @@ -145,7 +150,7 @@ describe("navigating between routes", () => { }); it("knows path parameters", () => { - const pathParameters = rendererDi.inject(routePathParametersInjectable, route); + const pathParameters = windowDi.inject(routePathParametersInjectable, route); expect(pathParameters.get()).toEqual({ someParameter: "some-value", @@ -158,27 +163,27 @@ describe("navigating between routes", () => { let route: Route; beforeEach(() => { - route = rendererDi.inject(routeWithOptionalPathParametersInjectable); + route = windowDi.inject(routeWithOptionalPathParametersInjectable); - const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken); + const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken); navigateToRoute(route); }); it("knows current route", () => { - const currentRoute = rendererDi.inject(currentRouteInjectable); + const currentRoute = windowDi.inject(currentRouteInjectable); expect(currentRoute.get()).toBe(route); }); it("knows current path", () => { - const currentPath = rendererDi.inject(currentPathInjectable); + const currentPath = windowDi.inject(currentPathInjectable); expect(currentPath.get()).toBe("/some-path"); }); it("knows path parameters", () => { - const pathParameters = rendererDi.inject(routePathParametersInjectable, route); + const pathParameters = windowDi.inject(routePathParametersInjectable, route); expect(pathParameters.get()).toEqual({ someParameter: undefined, diff --git a/src/behaviours/preferences/closing-preferences.test.tsx b/src/behaviours/preferences/closing-preferences.test.tsx index dddd7e18dc..f93eaf70ce 100644 --- a/src/behaviours/preferences/closing-preferences.test.tsx +++ b/src/behaviours/preferences/closing-preferences.test.tsx @@ -24,19 +24,19 @@ import navigateToFrontPageInjectable from "../../common/front-end-routing/naviga import { navigateToRouteInjectionToken } from "../../common/front-end-routing/navigate-to-route-injection-token"; describe("preferences - closing-preferences", () => { - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; beforeEach(() => { - applicationBuilder = getApplicationBuilder(); + builder = getApplicationBuilder(); - applicationBuilder.beforeApplicationStart(({ rendererDi }) => { - rendererDi.register(testPreferencesRouteInjectable); - rendererDi.register(testPreferencesRouteComponentInjectable); - rendererDi.register(testFrontPageRouteInjectable); - rendererDi.register(testFrontPageRouteComponentInjectable); - rendererDi.register(testNavigationItemInjectable); + builder.beforeWindowStart((windowDi) => { + windowDi.register(testPreferencesRouteInjectable); + windowDi.register(testPreferencesRouteComponentInjectable); + windowDi.register(testFrontPageRouteInjectable); + windowDi.register(testFrontPageRouteComponentInjectable); + windowDi.register(testNavigationItemInjectable); - rendererDi.override(navigateToFrontPageInjectable, (di) => { + windowDi.override(navigateToFrontPageInjectable, (di) => { const navigateToRoute = di.inject(navigateToRouteInjectionToken); const testFrontPage = di.inject(testFrontPageRouteInjectable); @@ -49,11 +49,11 @@ describe("preferences - closing-preferences", () => { describe("given already in a page and then navigated to preferences", () => { let rendered: RenderResult; - let rendererDi: DiContainer; + let windowDi: DiContainer; beforeEach(async () => { - applicationBuilder.beforeApplicationStart(({ rendererDi }) => { - rendererDi.override(observableHistoryInjectable, () => { + builder.beforeWindowStart((windowDi) => { + windowDi.override(observableHistoryInjectable, () => { const historyFake = createMemoryHistory({ initialEntries: ["/some-test-path"], initialIndex: 0, @@ -65,10 +65,10 @@ describe("preferences - closing-preferences", () => { }); }); - rendered = await applicationBuilder.render(); - rendererDi = applicationBuilder.dis.rendererDi; + rendered = await builder.render(); + windowDi = builder.applicationWindow.only.di; - applicationBuilder.preferences.navigate(); + builder.preferences.navigate(); }); it("renders", () => { @@ -77,7 +77,7 @@ describe("preferences - closing-preferences", () => { describe("when preferences are closed", () => { beforeEach(() => { - applicationBuilder.preferences.close(); + builder.preferences.close(); }); it("renders", () => { @@ -85,7 +85,7 @@ describe("preferences - closing-preferences", () => { }); it("navigates back to the original page", () => { - const currentPath = rendererDi.inject(currentPathInjectable).get(); + const currentPath = windowDi.inject(currentPathInjectable).get(); expect(currentPath).toBe("/some-test-path"); }); @@ -93,7 +93,7 @@ describe("preferences - closing-preferences", () => { describe("when navigating to a tab in preferences", () => { beforeEach(() => { - applicationBuilder.preferences.navigation.click( + builder.preferences.navigation.click( "some-test-preference-navigation-item-id", ); }); @@ -104,7 +104,7 @@ describe("preferences - closing-preferences", () => { describe("when preferences are closed", () => { beforeEach(() => { - applicationBuilder.preferences.close(); + builder.preferences.close(); }); it("renders", () => { @@ -112,7 +112,7 @@ describe("preferences - closing-preferences", () => { }); it("navigates back to the original page", () => { - const currentPath = rendererDi.inject(currentPathInjectable).get(); + const currentPath = windowDi.inject(currentPathInjectable).get(); expect(currentPath).toBe("/some-test-path"); }); @@ -122,11 +122,11 @@ describe("preferences - closing-preferences", () => { describe("given accessing preferences directly", () => { let rendered: RenderResult; - let rendererDi: DiContainer; + let windowDi: DiContainer; beforeEach(async () => { - applicationBuilder.beforeApplicationStart(({ rendererDi }) => { - rendererDi.override(observableHistoryInjectable, () => { + builder.beforeWindowStart((windowDi) => { + windowDi.override(observableHistoryInjectable, () => { const historyFake = createMemoryHistory({ initialEntries: ["/preferences/app"], initialIndex: 0, @@ -138,9 +138,9 @@ describe("preferences - closing-preferences", () => { }); }); - rendered = await applicationBuilder.render(); + rendered = await builder.render(); - rendererDi = applicationBuilder.dis.rendererDi; + windowDi = builder.applicationWindow.only.di; }); it("renders", () => { @@ -149,7 +149,7 @@ describe("preferences - closing-preferences", () => { describe("when preferences are closed", () => { beforeEach(() => { - applicationBuilder.preferences.close(); + builder.preferences.close(); }); it("renders", () => { @@ -157,7 +157,7 @@ describe("preferences - closing-preferences", () => { }); it("navigates back to the front page", () => { - const currentPath = rendererDi.inject(currentPathInjectable).get(); + const currentPath = windowDi.inject(currentPathInjectable).get(); expect(currentPath).toBe("/some-front-page"); }); @@ -165,7 +165,7 @@ describe("preferences - closing-preferences", () => { describe("when navigating to a tab in preferences", () => { beforeEach(() => { - applicationBuilder.preferences.navigation.click( + builder.preferences.navigation.click( "some-test-preference-navigation-item-id", ); }); @@ -176,7 +176,7 @@ describe("preferences - closing-preferences", () => { describe("when preferences are closed", () => { beforeEach(() => { - applicationBuilder.preferences.close(); + builder.preferences.close(); }); it("renders", () => { @@ -184,7 +184,7 @@ describe("preferences - closing-preferences", () => { }); it("navigates back to the front page", () => { - const currentPath = rendererDi.inject(currentPathInjectable).get(); + const currentPath = windowDi.inject(currentPathInjectable).get(); expect(currentPath).toBe("/some-front-page"); }); diff --git a/src/behaviours/preferences/extension-adding-preference-tabs.test.tsx b/src/behaviours/preferences/extension-adding-preference-tabs.test.tsx index b811a5a848..47810df727 100644 --- a/src/behaviours/preferences/extension-adding-preference-tabs.test.tsx +++ b/src/behaviours/preferences/extension-adding-preference-tabs.test.tsx @@ -7,7 +7,6 @@ import type { IObservableValue } from "mobx"; import { runInAction, computed, observable } from "mobx"; import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; -import { getExtensionFakeFor } from "../../renderer/components/test-utils/get-extension-fake"; describe("preferences: extension adding preference tabs", () => { let builder: ApplicationBuilder; @@ -25,11 +24,9 @@ describe("preferences: extension adding preference tabs", () => { builder.preferences.navigate(); - const getExtensionFake = getExtensionFakeFor(builder); - someObservable = observable.box(false); - const testExtension = getExtensionFake({ + const testExtension = { id: "some-extension-id", name: "some-extension", @@ -53,7 +50,7 @@ describe("preferences: extension adding preference tabs", () => { }, ], }, - }); + }; builder.extensions.enable(testExtension); diff --git a/src/behaviours/preferences/navigation-to-application-preferences.test.ts b/src/behaviours/preferences/navigation-to-application-preferences.test.ts index c91f091323..c90a2b3cc5 100644 --- a/src/behaviours/preferences/navigation-to-application-preferences.test.ts +++ b/src/behaviours/preferences/navigation-to-application-preferences.test.ts @@ -8,23 +8,23 @@ import { getApplicationBuilder } from "../../renderer/components/test-utils/get- import navigateToProxyPreferencesInjectable from "../../common/front-end-routing/routes/preferences/proxy/navigate-to-proxy-preferences.injectable"; describe("preferences - navigation to application preferences", () => { - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; beforeEach(() => { - applicationBuilder = getApplicationBuilder(); + builder = getApplicationBuilder(); }); describe("given in some child page of preferences, when rendered", () => { let rendered: RenderResult; beforeEach(async () => { - applicationBuilder.beforeRender(({ rendererDi }) => { - const navigateToProxyPreferences = rendererDi.inject(navigateToProxyPreferencesInjectable); + builder.beforeWindowStart((windowDi) => { + const navigateToProxyPreferences = windowDi.inject(navigateToProxyPreferencesInjectable); navigateToProxyPreferences(); }); - rendered = await applicationBuilder.render(); + rendered = await builder.render(); }); it("renders", () => { @@ -39,7 +39,7 @@ describe("preferences - navigation to application preferences", () => { describe("when navigating to application preferences using navigation", () => { beforeEach(() => { - applicationBuilder.preferences.navigation.click("application"); + builder.preferences.navigation.click("application"); }); it("renders", () => { diff --git a/src/behaviours/preferences/navigation-to-editor-preferences.test.ts b/src/behaviours/preferences/navigation-to-editor-preferences.test.ts index 1b74b94eb4..7a37abbc8c 100644 --- a/src/behaviours/preferences/navigation-to-editor-preferences.test.ts +++ b/src/behaviours/preferences/navigation-to-editor-preferences.test.ts @@ -17,7 +17,7 @@ describe("preferences - navigation to editor preferences", () => { let rendered: RenderResult; beforeEach(async () => { - applicationBuilder.beforeRender(() => { + applicationBuilder.beforeWindowStart(() => { applicationBuilder.preferences.navigate(); }); diff --git a/src/behaviours/preferences/navigation-to-extension-specific-preferences.test.tsx b/src/behaviours/preferences/navigation-to-extension-specific-preferences.test.tsx index 876ce98004..cb44c1770c 100644 --- a/src/behaviours/preferences/navigation-to-extension-specific-preferences.test.tsx +++ b/src/behaviours/preferences/navigation-to-extension-specific-preferences.test.tsx @@ -7,29 +7,25 @@ import type { ApplicationBuilder } from "../../renderer/components/test-utils/ge import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import React from "react"; import "@testing-library/jest-dom/extend-expect"; -import type { FakeExtensionData, TestExtension } from "../../renderer/components/test-utils/get-renderer-extension-fake"; -import { getRendererExtensionFakeFor } from "../../renderer/components/test-utils/get-renderer-extension-fake"; -import type { DiContainer } from "@ogre-tools/injectable"; -import { getDiForUnitTesting } from "../../renderer/getDiForUnitTesting"; import extensionPreferencesRouteInjectable from "../../common/front-end-routing/routes/preferences/extension/extension-preferences-route.injectable"; - +import type { FakeExtensionOptions } from "../../renderer/components/test-utils/get-extension-fake"; describe("preferences - navigation to extension specific preferences", () => { - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; beforeEach(() => { - applicationBuilder = getApplicationBuilder(); + builder = getApplicationBuilder(); }); describe("given in preferences, when rendered", () => { let rendered: RenderResult; beforeEach(async () => { - applicationBuilder.beforeRender(() => { - applicationBuilder.preferences.navigate(); + builder.beforeWindowStart(() => { + builder.preferences.navigate(); }); - rendered = await applicationBuilder.render(); + rendered = await builder.render(); }); it("renders", () => { @@ -49,13 +45,15 @@ describe("preferences - navigation to extension specific preferences", () => { }); describe("given multiple extensions with specific preferences, when navigating to extension specific preferences page", () => { - beforeEach(async () => { - const getRendererExtensionFake = getRendererExtensionFakeFor(applicationBuilder); - const someTestExtension = getRendererExtensionFake(extensionStubWithExtensionSpecificPreferenceItems); - const someOtherTestExtension = getRendererExtensionFake(someOtherExtensionStubWithExtensionSpecificPreferenceItems); + beforeEach(() => { + builder.extensions.enable( + extensionStubWithExtensionSpecificPreferenceItems, + someOtherExtensionStubWithExtensionSpecificPreferenceItems, + ); - await applicationBuilder.extensions.renderer.enable(someTestExtension, someOtherTestExtension); - applicationBuilder.preferences.navigation.click("extension-some-test-extension-id"); + builder.preferences.navigation.click( + "extension-some-test-extension-id", + ); }); it("renders", () => { @@ -76,13 +74,12 @@ describe("preferences - navigation to extension specific preferences", () => { }); describe("given multiple extensions with and without specific preferences", () => { - beforeEach(async () => { - const getRendererExtensionFake = getRendererExtensionFakeFor(applicationBuilder); - const someTestExtension = getRendererExtensionFake(extensionStubWithExtensionSpecificPreferenceItems); - const extensionWithoutPreferences = getRendererExtensionFake(extensionStubWithoutPreferences); - const extensionWithSpecificTab = getRendererExtensionFake(extensionStubWithShowInPreferencesTab); - - await applicationBuilder.extensions.renderer.enable(someTestExtension, extensionWithoutPreferences, extensionWithSpecificTab); + beforeEach(() => { + builder.extensions.enable( + extensionStubWithExtensionSpecificPreferenceItems, + extensionStubWithoutPreferences, + extensionStubWithShowInPreferencesTab, + ); }); it("doesn't show link for extension without preferences", () => { @@ -99,16 +96,8 @@ describe("preferences - navigation to extension specific preferences", () => { }); describe("when extension with specific preferences is enabled", () => { - let testExtension: TestExtension; - beforeEach(() => { - const getRendererExtensionFake = getRendererExtensionFakeFor(applicationBuilder); - - testExtension = getRendererExtensionFake( - extensionStubWithExtensionSpecificPreferenceItems, - ); - - applicationBuilder.extensions.renderer.enable(testExtension); + builder.extensions.enable(extensionStubWithExtensionSpecificPreferenceItems); }); it("renders", () => { @@ -129,7 +118,7 @@ describe("preferences - navigation to extension specific preferences", () => { describe("when navigating to extension preferences using navigation", () => { beforeEach(() => { - applicationBuilder.preferences.navigation.click("extension-some-test-extension-id"); + builder.preferences.navigation.click("extension-some-test-extension-id"); }); it("renders", () => { @@ -168,7 +157,7 @@ describe("preferences - navigation to extension specific preferences", () => { describe("when extension is disabled", () => { beforeEach(() => { - applicationBuilder.extensions.renderer.disable(testExtension); + builder.extensions.disable(extensionStubWithExtensionSpecificPreferenceItems); }); it("renders", () => { @@ -180,7 +169,7 @@ describe("preferences - navigation to extension specific preferences", () => { }); it("when extension is enabled again, does not show the error message anymore", () => { - applicationBuilder.extensions.renderer.enable(testExtension); + builder.extensions.enable(extensionStubWithExtensionSpecificPreferenceItems); expect(rendered.queryByTestId("error-for-extension-not-being-present")).not.toBeInTheDocument(); }); @@ -189,11 +178,8 @@ describe("preferences - navigation to extension specific preferences", () => { }); describe("given extension with registered tab", () => { - beforeEach(async () => { - const getRendererExtensionFake = getRendererExtensionFakeFor(applicationBuilder); - const extension = getRendererExtensionFake(extensionStubWithWithRegisteredTab); - - await applicationBuilder.extensions.renderer.enable(extension); + beforeEach(() => { + builder.extensions.enable(extensionStubWithWithRegisteredTab); }); it("shows extension tab in general area", () => { @@ -210,7 +196,7 @@ describe("preferences - navigation to extension specific preferences", () => { describe("when navigating to specific extension tab", () => { beforeEach(() => { - applicationBuilder.preferences.navigation.click("extension-registered-tab-page-id-nav-item-metrics-extension-tab"); + builder.preferences.navigation.click("extension-registered-tab-page-id-nav-item-metrics-extension-tab"); }); it("renders", () => { expect(rendered.container).toMatchSnapshot(); @@ -232,7 +218,7 @@ describe("preferences - navigation to extension specific preferences", () => { }); it("shows page title same as tab title", () => { const pageTitle = rendered.queryByTestId("extension-preferences-page-title"); - const tabs = extensionStubWithWithRegisteredTab.appPreferenceTabs; + const tabs = extensionStubWithWithRegisteredTab.rendererOptions?.appPreferenceTabs; const tabTitle = tabs && tabs[0].title; expect(pageTitle?.innerHTML).toBe(tabTitle); @@ -246,11 +232,8 @@ describe("preferences - navigation to extension specific preferences", () => { "tab-link-for-extension-hello-world-tab-page-id-nav-item-logs-extension-tab", ]; - beforeEach(async () => { - const getRendererExtensionFake = getRendererExtensionFakeFor(applicationBuilder); - const extension = getRendererExtensionFake(extensionStubWithWithRegisteredTabs); - - await applicationBuilder.extensions.renderer.enable(extension); + beforeEach(() => { + builder.extensions.enable(extensionStubWithWithRegisteredTabs); }); it.each(tabs)("shows '%s' tab in general area", (tab) => { @@ -261,12 +244,8 @@ describe("preferences - navigation to extension specific preferences", () => { }); describe("given extensions with tabs having same id", () => { - beforeEach(async () => { - const getRendererExtensionFake = getRendererExtensionFakeFor(applicationBuilder); - const extension = getRendererExtensionFake(extensionStubWithWithRegisteredTab); - const otherExtension = getRendererExtensionFake(extensionStubWithWithSameRegisteredTab); - - await applicationBuilder.extensions.renderer.enable(extension, otherExtension); + beforeEach(() => { + builder.extensions.enable(extensionStubWithWithRegisteredTab, extensionStubWithWithSameRegisteredTab); }); it("shows tab from the first extension", () => { @@ -283,7 +262,7 @@ describe("preferences - navigation to extension specific preferences", () => { describe("when navigating to first extension tab", () => { beforeEach(() => { - applicationBuilder.preferences.navigation.click("extension-registered-tab-page-id-nav-item-metrics-extension-tab"); + builder.preferences.navigation.click("extension-registered-tab-page-id-nav-item-metrics-extension-tab"); }); it("renders", () => { @@ -305,7 +284,7 @@ describe("preferences - navigation to extension specific preferences", () => { describe("when navigating to second extension tab", () => { beforeEach(() => { - applicationBuilder.preferences.navigation.click("extension-duplicated-tab-page-id-nav-item-metrics-extension-tab"); + builder.preferences.navigation.click("extension-duplicated-tab-page-id-nav-item-metrics-extension-tab"); }); it("renders", () => { @@ -329,27 +308,21 @@ describe("preferences - navigation to extension specific preferences", () => { describe("when navigating to extension specific tab", () => { let rendered: RenderResult; - let di: DiContainer; beforeEach(async () => { - di = getDiForUnitTesting({ doGeneralOverrides: true }); + builder.beforeWindowStart((windowDi) => { + const extensionRoute = windowDi.inject(extensionPreferencesRouteInjectable); - const getRendererExtensionFake = getRendererExtensionFakeFor(applicationBuilder); - const extension = getRendererExtensionFake(extensionStubWithWithSameRegisteredTab); - const otherExtension = getRendererExtensionFake(extensionUsingSomeoneElseTab); - - applicationBuilder.beforeRender(() => { - const extensionRoute = di.inject(extensionPreferencesRouteInjectable); const params = { parameters: { extensionId: "duplicated-tab-page-id", tabId: "metrics-extension-tab", }}; - applicationBuilder.preferences.navigateTo(extensionRoute, params); + builder.preferences.navigateTo(extensionRoute, params); }); - await applicationBuilder.extensions.renderer.enable(extension, otherExtension); - rendered = await applicationBuilder.render(); + builder.extensions.enable(extensionStubWithWithSameRegisteredTab, extensionUsingSomeoneElseTab); + rendered = await builder.render(); }); it("renders", () => { @@ -367,27 +340,20 @@ describe("preferences - navigation to extension specific preferences", () => { describe("when navigating to someone else extension specific tab", () => { let rendered: RenderResult; - let di: DiContainer; beforeEach(async () => { - di = getDiForUnitTesting({ doGeneralOverrides: true }); - - const getRendererExtensionFake = getRendererExtensionFakeFor(applicationBuilder); - const extension = getRendererExtensionFake(extensionStubWithWithSameRegisteredTab); - const extensionUsingOtherTab = getRendererExtensionFake(extensionUsingSomeoneElseTab); - - applicationBuilder.beforeRender(() => { - const extensionRoute = di.inject(extensionPreferencesRouteInjectable); + builder.beforeWindowStart((windowDi) => { + const extensionRoute = windowDi.inject(extensionPreferencesRouteInjectable); const params = { parameters: { extensionId: "extension-using-someone-else-tab-id", tabId: "metrics-extension-tab", }}; - applicationBuilder.preferences.navigateTo(extensionRoute, params); + builder.preferences.navigateTo(extensionRoute, params); }); - await applicationBuilder.extensions.renderer.enable(extension, extensionUsingOtherTab); - rendered = await applicationBuilder.render(); + builder.extensions.enable(extensionStubWithWithSameRegisteredTab, extensionUsingSomeoneElseTab); + rendered = await builder.render(); }); it("renders", () => { @@ -396,193 +362,208 @@ describe("preferences - navigation to extension specific preferences", () => { }); }); -const extensionStubWithExtensionSpecificPreferenceItems: FakeExtensionData = { +const extensionStubWithExtensionSpecificPreferenceItems: FakeExtensionOptions = { id: "some-test-extension-id", name: "some-test-extension-id", - appPreferences: [ - { - title: "Some preference item", - id: "some-preference-item-id", - components: { - Hint: () =>
, - Input: () =>
, + rendererOptions: { + appPreferences: [ + { + title: "Some preference item", + id: "some-preference-item-id", + + components: { + Hint: () =>
, + Input: () =>
, + }, }, - }, - { - title: "irrelevant", - id: "some-unrelated-preference-item-id", - showInPreferencesTab: "some-tab", + { + title: "irrelevant", + id: "some-unrelated-preference-item-id", + showInPreferencesTab: "some-tab", - components: { - Hint: () =>
, - Input: () =>
, + components: { + Hint: () =>
, + Input: () =>
, + }, }, - }, - ], + ], + }, }; -const someOtherExtensionStubWithExtensionSpecificPreferenceItems: FakeExtensionData = { +const someOtherExtensionStubWithExtensionSpecificPreferenceItems: FakeExtensionOptions = { id: "some-other-test-extension-id", name: "some-other-test-extension-id", - appPreferences: [ - { - title: "Test preference item", - id: "some-other-preference-item-id", + rendererOptions: { + appPreferences: [ + { + title: "Test preference item", + id: "some-other-preference-item-id", - components: { - Hint: () =>
, - Input: () =>
, + components: { + Hint: () =>
, + Input: () =>
, + }, }, - }, - ], + ], + }, }; -const extensionStubWithoutPreferences: FakeExtensionData = { +const extensionStubWithoutPreferences: FakeExtensionOptions = { id: "without-preferences-id", name: "without-preferences-id", }; -const extensionStubWithShowInPreferencesTab: FakeExtensionData = { +const extensionStubWithShowInPreferencesTab: FakeExtensionOptions = { id: "specified-preferences-page-id", name: "specified-preferences-page-name", - appPreferences: [ - { - title: "Test preference item", - id: "very-other-preference-item-id", - showInPreferencesTab: "some-tab", + rendererOptions: { + appPreferences: [ + { + title: "Test preference item", + id: "very-other-preference-item-id", + showInPreferencesTab: "some-tab", - components: { - Hint: () =>
, - Input: () =>
, + components: { + Hint: () =>
, + Input: () =>
, + }, }, - }, - ], + ], + }, }; -const extensionStubWithWithRegisteredTab: FakeExtensionData = { +const extensionStubWithWithRegisteredTab: FakeExtensionOptions = { id: "registered-tab-page-id", name: "registered-tab-page-id", - appPreferences: [ - { - title: "License item", - id: "metrics-preference-item-id", - showInPreferencesTab: "metrics-extension-tab", + rendererOptions: { + appPreferences: [ + { + title: "License item", + id: "metrics-preference-item-id", + showInPreferencesTab: "metrics-extension-tab", - components: { - Hint: () =>
, - Input: () =>
, + components: { + Hint: () =>
, + Input: () =>
, + }, }, - }, - { - title: "Menu item", - id: "menu-preference-item-id", - showInPreferencesTab: "menu-extension-tab", + { + title: "Menu item", + id: "menu-preference-item-id", + showInPreferencesTab: "menu-extension-tab", - components: { - Hint: () =>
, - Input: () =>
, + components: { + Hint: () =>
, + Input: () =>
, + }, }, - }, - { - title: "Survey item", - id: "survey-preference-item-id", - showInPreferencesTab: "survey-extension-tab", + { + title: "Survey item", + id: "survey-preference-item-id", + showInPreferencesTab: "survey-extension-tab", - components: { - Hint: () =>
, - Input: () =>
, + components: { + Hint: () =>
, + Input: () =>
, + }, }, - }, - ], + ], - appPreferenceTabs: [{ - title: "Metrics tab", - id: "metrics-extension-tab", - orderNumber: 100, - }], + appPreferenceTabs: [{ + title: "Metrics tab", + id: "metrics-extension-tab", + orderNumber: 100, + }], + }, }; -const extensionStubWithWithRegisteredTabs: FakeExtensionData = { +const extensionStubWithWithRegisteredTabs: FakeExtensionOptions = { id: "hello-world-tab-page-id", name: "hello-world-tab-page-id", - appPreferences: [ - { - title: "Hello world", - id: "hello-preference-item-id", - showInPreferencesTab: "hello-extension-tab", + rendererOptions: { + appPreferences: [ + { + title: "Hello world", + id: "hello-preference-item-id", + showInPreferencesTab: "hello-extension-tab", - components: { - Hint: () =>
, - Input: () =>
, + components: { + Hint: () =>
, + Input: () =>
, + }, }, - }, - { - title: "Logs", - id: "logs-preference-item-id", - showInPreferencesTab: "logs-extension-tab", + { + title: "Logs", + id: "logs-preference-item-id", + showInPreferencesTab: "logs-extension-tab", - components: { - Hint: () =>
, - Input: () =>
, + components: { + Hint: () =>
, + Input: () =>
, + }, }, - }, - ], + ], - appPreferenceTabs: [{ - title: "Metrics tab", - id: "hello-extension-tab", - orderNumber: 100, - }, { - title: "Logs tab", - id: "logs-extension-tab", - orderNumber: 200, - }], + appPreferenceTabs: [{ + title: "Metrics tab", + id: "hello-extension-tab", + orderNumber: 100, + }, { + title: "Logs tab", + id: "logs-extension-tab", + orderNumber: 200, + }], + }, }; -const extensionStubWithWithSameRegisteredTab: FakeExtensionData = { +const extensionStubWithWithSameRegisteredTab: FakeExtensionOptions = { id: "duplicated-tab-page-id", name: "duplicated-tab-page-id", - appPreferences: [ - { - title: "Another metrics", - id: "another-metrics-preference-item-id", - showInPreferencesTab: "metrics-extension-tab", + rendererOptions: { + appPreferences: [ + { + title: "Another metrics", + id: "another-metrics-preference-item-id", + showInPreferencesTab: "metrics-extension-tab", - components: { - Hint: () =>
, - Input: () =>
, + components: { + Hint: () =>
, + Input: () =>
, + }, }, - }, - ], + ], - appPreferenceTabs: [{ - title: "Metrics tab", - id: "metrics-extension-tab", - orderNumber: 100, - }], + appPreferenceTabs: [{ + title: "Metrics tab", + id: "metrics-extension-tab", + orderNumber: 100, + }], + }, }; -const extensionUsingSomeoneElseTab: FakeExtensionData = { +const extensionUsingSomeoneElseTab: FakeExtensionOptions = { id: "extension-using-someone-else-tab-id", name: "extension-using-someone-else-tab-id", - appPreferences: [ - { - title: "My preferences", - id: "my-preferences-item-id", - showInPreferencesTab: "metrics-extension-tab", + rendererOptions: { + appPreferences: [ + { + title: "My preferences", + id: "my-preferences-item-id", + showInPreferencesTab: "metrics-extension-tab", - components: { - Hint: () =>
, - Input: () =>
, + components: { + Hint: () =>
, + Input: () =>
, + }, }, - }, - ], + ], + }, }; diff --git a/src/behaviours/preferences/navigation-to-kubernetes-preferences.test.ts b/src/behaviours/preferences/navigation-to-kubernetes-preferences.test.ts index 75b4585c21..3bdf1c611b 100644 --- a/src/behaviours/preferences/navigation-to-kubernetes-preferences.test.ts +++ b/src/behaviours/preferences/navigation-to-kubernetes-preferences.test.ts @@ -9,30 +9,32 @@ import callForPublicHelmRepositoriesInjectable from "../../renderer/components/+ import getActiveHelmRepositoriesInjectable from "../../main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories.injectable"; describe("preferences - navigation to kubernetes preferences", () => { - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; beforeEach(() => { - applicationBuilder = getApplicationBuilder(); + builder = getApplicationBuilder(); }); describe("given in preferences, when rendered", () => { let rendered: RenderResult; beforeEach(async () => { - applicationBuilder.beforeApplicationStart(({ rendererDi, mainDi }) => { - rendererDi.override(callForPublicHelmRepositoriesInjectable, () => async () => []); - + builder.beforeApplicationStart((mainDi) => { mainDi.override( getActiveHelmRepositoriesInjectable, () => async () => ({ callWasSuccessful: true, response: [] }), ); }); - applicationBuilder.beforeRender(() => { - applicationBuilder.preferences.navigate(); + builder.beforeWindowStart((windowDi) => { + windowDi.override(callForPublicHelmRepositoriesInjectable, () => async () => []); }); - rendered = await applicationBuilder.render(); + builder.beforeWindowStart(() => { + builder.preferences.navigate(); + }); + + rendered = await builder.render(); }); it("renders", () => { @@ -47,7 +49,7 @@ describe("preferences - navigation to kubernetes preferences", () => { describe("when navigating to kubernetes preferences using navigation", () => { beforeEach(() => { - applicationBuilder.preferences.navigation.click("kubernetes"); + builder.preferences.navigation.click("kubernetes"); }); it("renders", () => { diff --git a/src/behaviours/preferences/navigation-to-proxy-preferences.test.ts b/src/behaviours/preferences/navigation-to-proxy-preferences.test.ts index 3d2c8d6d2c..976e9058ef 100644 --- a/src/behaviours/preferences/navigation-to-proxy-preferences.test.ts +++ b/src/behaviours/preferences/navigation-to-proxy-preferences.test.ts @@ -17,7 +17,7 @@ describe("preferences - navigation to proxy preferences", () => { let rendered: RenderResult; beforeEach(async () => { - applicationBuilder.beforeRender(() => { + applicationBuilder.beforeWindowStart(() => { applicationBuilder.preferences.navigate(); }); diff --git a/src/behaviours/preferences/navigation-to-telemetry-preferences.test.tsx b/src/behaviours/preferences/navigation-to-telemetry-preferences.test.tsx index 42ea181ddc..c4a76bed81 100644 --- a/src/behaviours/preferences/navigation-to-telemetry-preferences.test.tsx +++ b/src/behaviours/preferences/navigation-to-telemetry-preferences.test.tsx @@ -6,27 +6,26 @@ import type { RenderResult } from "@testing-library/react"; import React from "react"; import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; -import type { FakeExtensionData } from "../../renderer/components/test-utils/get-renderer-extension-fake"; -import { getRendererExtensionFakeFor } from "../../renderer/components/test-utils/get-renderer-extension-fake"; import navigateToTelemetryPreferencesInjectable from "../../common/front-end-routing/routes/preferences/telemetry/navigate-to-telemetry-preferences.injectable"; import sentryDnsUrlInjectable from "../../renderer/components/+preferences/sentry-dns-url.injectable"; +import type { FakeExtensionOptions } from "../../renderer/components/test-utils/get-extension-fake"; describe("preferences - navigation to telemetry preferences", () => { - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; beforeEach(() => { - applicationBuilder = getApplicationBuilder(); + builder = getApplicationBuilder(); }); describe("given in preferences, when rendered", () => { let rendered: RenderResult; beforeEach(async () => { - applicationBuilder.beforeRender(() => { - applicationBuilder.preferences.navigate(); + builder.beforeWindowStart(() => { + builder.preferences.navigate(); }); - rendered = await applicationBuilder.render(); + rendered = await builder.render(); }); it("renders", () => { @@ -47,11 +46,8 @@ describe("preferences - navigation to telemetry preferences", () => { describe("when extension with telemetry preference items gets enabled", () => { beforeEach(() => { - const getRendererExtensionFake = getRendererExtensionFakeFor(applicationBuilder); - const testExtensionWithTelemetryPreferenceItems = getRendererExtensionFake(extensionStubWithTelemetryPreferenceItems); - - applicationBuilder.extensions.renderer.enable( - testExtensionWithTelemetryPreferenceItems, + builder.extensions.enable( + extensionStubWithTelemetryPreferenceItems, ); }); @@ -67,7 +63,7 @@ describe("preferences - navigation to telemetry preferences", () => { describe("when clicking link to telemetry preferences from navigation", () => { beforeEach(() => { - applicationBuilder.preferences.navigation.click("telemetry"); + builder.preferences.navigation.click("telemetry"); }); it("renders", () => { @@ -91,23 +87,21 @@ describe("preferences - navigation to telemetry preferences", () => { }); it("given extensions but no telemetry preference items, does not show link for telemetry preferences", () => { - const getRendererExtensionFake = getRendererExtensionFakeFor(applicationBuilder); - const testExtensionWithTelemetryPreferenceItems = getRendererExtensionFake({ + builder.extensions.enable({ id: "some-test-extension-id", name: "some-test-extension-name", - appPreferences: [ - { - title: "irrelevant", - id: "irrelevant", - showInPreferencesTab: "not-telemetry", - components: { Hint: () =>
, Input: () =>
}, - }, - ], - }); - applicationBuilder.extensions.renderer.enable( - testExtensionWithTelemetryPreferenceItems, - ); + rendererOptions: { + appPreferences: [ + { + title: "irrelevant", + id: "irrelevant", + showInPreferencesTab: "not-telemetry", + components: { Hint: () =>
, Input: () =>
}, + }, + ], + }, + }); const actual = rendered.queryByTestId("tab-link-for-telemetry"); @@ -119,18 +113,18 @@ describe("preferences - navigation to telemetry preferences", () => { let rendered: RenderResult; beforeEach(async () => { - applicationBuilder.beforeApplicationStart(({ rendererDi }) => { - rendererDi.override(sentryDnsUrlInjectable, () => "some-sentry-dns-url"); + builder.beforeWindowStart((windowDi) => { + windowDi.override(sentryDnsUrlInjectable, () => "some-sentry-dns-url"); }); - rendered = await applicationBuilder.render(); + rendered = await builder.render(); - applicationBuilder.preferences.navigate(); + builder.preferences.navigate(); }); describe("when navigating to telemetry preferences", () => { beforeEach(() => { - applicationBuilder.preferences.navigation.click("telemetry"); + builder.preferences.navigation.click("telemetry"); }); it("renders", () => { @@ -149,13 +143,15 @@ describe("preferences - navigation to telemetry preferences", () => { let rendered: RenderResult; beforeEach(async () => { - applicationBuilder.beforeApplicationStart(({ rendererDi }) => { - rendererDi.override(sentryDnsUrlInjectable, () => null); + builder.beforeWindowStart((windowDi) => { + windowDi.override(sentryDnsUrlInjectable, () => null); }); - rendered = await applicationBuilder.render(); + rendered = await builder.render(); - const navigateToTelemetryPreferences = applicationBuilder.dis.rendererDi.inject(navigateToTelemetryPreferencesInjectable); + const windowDi = builder.applicationWindow.only.di; + + const navigateToTelemetryPreferences = windowDi.inject(navigateToTelemetryPreferencesInjectable); navigateToTelemetryPreferences(); }); @@ -172,19 +168,22 @@ describe("preferences - navigation to telemetry preferences", () => { }); }); -const extensionStubWithTelemetryPreferenceItems: FakeExtensionData = { +const extensionStubWithTelemetryPreferenceItems: FakeExtensionOptions = { id: "some-test-extension-id", name: "some-test-extension-name", - appPreferences: [ - { - title: "Some telemetry-preference item", - id: "some-telemetry-preference-item-id", - showInPreferencesTab: "telemetry", - components: { - Hint: () =>
, - Input: () =>
, + rendererOptions: { + appPreferences: [ + { + title: "Some telemetry-preference item", + id: "some-telemetry-preference-item-id", + showInPreferencesTab: "telemetry", + + components: { + Hint: () =>
, + Input: () =>
, + }, }, - }, - ], + ], + }, }; diff --git a/src/behaviours/preferences/navigation-to-terminal-preferences.test.ts b/src/behaviours/preferences/navigation-to-terminal-preferences.test.ts index 73eff39006..e7fbb9c4b9 100644 --- a/src/behaviours/preferences/navigation-to-terminal-preferences.test.ts +++ b/src/behaviours/preferences/navigation-to-terminal-preferences.test.ts @@ -17,7 +17,7 @@ describe("preferences - navigation to terminal preferences", () => { let rendered: RenderResult; beforeEach(async () => { - applicationBuilder.beforeRender(() => { + applicationBuilder.beforeWindowStart(() => { applicationBuilder.preferences.navigate(); }); diff --git a/src/behaviours/quitting-and-restarting-the-app/opening-application-window-using-tray.test.ts b/src/behaviours/quitting-and-restarting-the-app/opening-application-window-using-tray.test.ts index dedbb33e28..f9ced472dd 100644 --- a/src/behaviours/quitting-and-restarting-the-app/opening-application-window-using-tray.test.ts +++ b/src/behaviours/quitting-and-restarting-the-app/opening-application-window-using-tray.test.ts @@ -5,19 +5,18 @@ import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; -import { lensWindowInjectionToken } from "../../main/start-main-application/lens-window/application-window/lens-window-injection-token"; -import applicationWindowInjectable from "../../main/start-main-application/lens-window/application-window/application-window.injectable"; -import createElectronWindowForInjectable from "../../main/start-main-application/lens-window/application-window/create-electron-window.injectable"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; -import type { ElectronWindow, LensWindowConfiguration } from "../../main/start-main-application/lens-window/application-window/create-lens-window.injectable"; -import type { DiContainer } from "@ogre-tools/injectable"; +import type { LensWindow } from "../../main/start-main-application/lens-window/application-window/create-lens-window.injectable"; import lensResourcesDirInjectable from "../../common/vars/lens-resources-dir.injectable"; import focusApplicationInjectable from "../../main/electron-app/features/focus-application.injectable"; +import type { CreateElectronWindow } from "../../main/start-main-application/lens-window/application-window/create-electron-window.injectable"; +import createElectronWindowInjectable from "../../main/start-main-application/lens-window/application-window/create-electron-window.injectable"; +import splashWindowInjectable from "../../main/start-main-application/lens-window/splash-window/splash-window.injectable"; describe("opening application window using tray", () => { describe("given application has started", () => { - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; let createElectronWindowMock: jest.Mock; let expectWindowsToBeOpen: (windowIds: string[]) => void; let callForSplashWindowHtmlMock: AsyncFnMock<() => Promise>; @@ -30,71 +29,66 @@ describe("opening application window using tray", () => { focusApplicationMock = jest.fn(); - applicationBuilder = getApplicationBuilder().beforeApplicationStart( - ({ mainDi }) => { - mainDi.override(focusApplicationInjectable, () => focusApplicationMock); + builder = getApplicationBuilder(); - mainDi.override(lensResourcesDirInjectable, () => "some-lens-resources-directory"); + builder.beforeApplicationStart((mainDi) => { + mainDi.override(focusApplicationInjectable, () => focusApplicationMock); - const loadFileMock = jest - .fn(callForSplashWindowHtmlMock) - .mockImplementationOnce(() => Promise.resolve()); + mainDi.override( + lensResourcesDirInjectable, + () => "some-lens-resources-directory", + ); - const loadUrlMock = jest - .fn(callForApplicationWindowHtmlMock) - .mockImplementationOnce(() => Promise.resolve()); + const loadFileMock = jest + .fn(callForSplashWindowHtmlMock) + .mockImplementationOnce(() => Promise.resolve()); - createElectronWindowMock = jest.fn((configuration: LensWindowConfiguration) => - ({ - splash: { - send: () => {}, - close: () => {}, - show: () => {}, - loadFile: loadFileMock, - loadUrl: () => { throw new Error("Should never come here"); }, - }, + const loadUrlMock = jest + .fn(callForApplicationWindowHtmlMock) + .mockImplementationOnce(() => Promise.resolve()); - "only-application-window": { - send: () => {}, - close: () => {}, - show: () => {}, - loadFile: () => { throw new Error("Should never come here"); }, - loadUrl: loadUrlMock, - }, - }[configuration.id] as ElectronWindow)); + createElectronWindowMock = jest.fn((toBeDecorated): CreateElectronWindow => (configuration) => { + const browserWindow = toBeDecorated(configuration); - mainDi.override( - createElectronWindowForInjectable, + if (configuration.id === "splash") { + return { ...browserWindow, loadFile: loadFileMock }; + } - () => createElectronWindowMock, - ); + if (configuration.id === "first-application-window") { + return { ...browserWindow, loadUrl: loadUrlMock }; + } - expectWindowsToBeOpen = expectWindowsToBeOpenFor(mainDi); - }, - ); + return browserWindow; + }); - await applicationBuilder.render(); + (mainDi as any).decorateFunction( + createElectronWindowInjectable, + createElectronWindowMock, + ); + + expectWindowsToBeOpen = expectWindowsToBeOpenFor(builder); + }); + + await builder.render(); }); - it("only an application window is open", () => { - expectWindowsToBeOpen(["only-application-window"]); + it("only the first application window is open", () => { + expectWindowsToBeOpen(["first-application-window"]); }); describe("when an attempt to reopen the already started application is made using tray", () => { beforeEach(() => { - applicationBuilder.tray.click("open-app"); + builder.tray.click("open-app"); }); it("still shows only the application window", () => { - expectWindowsToBeOpen(["only-application-window"]); + expectWindowsToBeOpen(["first-application-window"]); }); }); - describe("when the application window is closed", () => { + describe("when the first application window is closed", () => { beforeEach(() => { - const applicationWindow = applicationBuilder.dis.mainDi.inject( - applicationWindowInjectable, - ); + const applicationWindow = builder.applicationWindow.only; applicationWindow.close(); }); @@ -110,7 +104,7 @@ describe("opening application window using tray", () => { callForSplashWindowHtmlMock.mockClear(); callForApplicationWindowHtmlMock.mockClear(); - applicationBuilder.tray.click("open-app"); + builder.tray.click("open-app"); }); it("focuses the application", () => { @@ -143,7 +137,7 @@ describe("opening application window using tray", () => { callForApplicationWindowHtmlMock.mockClear(); callForSplashWindowHtmlMock.mockClear(); - applicationBuilder.tray.click("open-app"); + builder.tray.click("open-app"); }); it("does not load contents of splash window again", () => { @@ -155,7 +149,7 @@ describe("opening application window using tray", () => { }); it("shows just the blank application window to permit developer tool access", () => { - expectWindowsToBeOpen(["only-application-window"]); + expectWindowsToBeOpen(["first-application-window"]); }); }); @@ -165,7 +159,7 @@ describe("opening application window using tray", () => { }); it("shows just the application window", () => { - expectWindowsToBeOpen(["only-application-window"]); + expectWindowsToBeOpen(["first-application-window"]); }); describe("when reopening the application using tray", () => { @@ -173,11 +167,11 @@ describe("opening application window using tray", () => { callForSplashWindowHtmlMock.mockClear(); callForApplicationWindowHtmlMock.mockClear(); - applicationBuilder.tray.click("open-app"); + builder.tray.click("open-app"); }); it("still shows just the application window", () => { - expectWindowsToBeOpen(["only-application-window"]); + expectWindowsToBeOpen(["first-application-window"]); }); it("does not load HTML for splash window again", () => { @@ -195,7 +189,7 @@ describe("opening application window using tray", () => { beforeEach(() => { createElectronWindowMock.mockClear(); - applicationBuilder.tray.click("open-app"); + builder.tray.click("open-app"); }); it("does not open any new windows", () => { @@ -215,14 +209,14 @@ describe("opening application window using tray", () => { it("when opening of application window finishes, only an application window is open", async () => { await callForApplicationWindowHtmlMock.resolve(); - expectWindowsToBeOpen(["only-application-window"]); + expectWindowsToBeOpen(["first-application-window"]); }); describe("given opening of application window has not finished yet, but another attempt to open the application is made", () => { beforeEach(() => { createElectronWindowMock.mockClear(); - applicationBuilder.tray.click("open-app"); + builder.tray.click("open-app"); }); it("does not open any new windows", () => { @@ -232,7 +226,7 @@ describe("opening application window using tray", () => { it("when opening finishes, only an application window is open", async () => { await callForApplicationWindowHtmlMock.resolve(); - expectWindowsToBeOpen(["only-application-window"]); + expectWindowsToBeOpen(["first-application-window"]); }); }); }); @@ -241,10 +235,14 @@ describe("opening application window using tray", () => { }); }); -const expectWindowsToBeOpenFor = (di: DiContainer) => (windowIds: string[]) => { - const windows = di.injectMany(lensWindowInjectionToken); +const expectWindowsToBeOpenFor = + (builder: ApplicationBuilder) => (windowIds: string[]) => { + const windows: LensWindow[] = [ + builder.mainDi.inject(splashWindowInjectable), + ...builder.applicationWindow.getAll(), + ]; - expect( - windows.filter((window) => window.isVisible).map((window) => window.id), - ).toEqual(windowIds); -}; + expect( + windows.filter((window) => window.isVisible).map((window) => window.id), + ).toEqual(windowIds); + }; diff --git a/src/behaviours/quitting-and-restarting-the-app/quitting-the-app-using-application-menu.test.ts b/src/behaviours/quitting-and-restarting-the-app/quitting-the-app-using-application-menu.test.ts index 19360d77bd..fe903f93f3 100644 --- a/src/behaviours/quitting-and-restarting-the-app/quitting-the-app-using-application-menu.test.ts +++ b/src/behaviours/quitting-and-restarting-the-app/quitting-the-app-using-application-menu.test.ts @@ -6,7 +6,6 @@ import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import type { ClusterManager } from "../../main/cluster-manager"; -import { lensWindowInjectionToken } from "../../main/start-main-application/lens-window/application-window/lens-window-injection-token"; import exitAppInjectable from "../../main/electron-app/features/exit-app.injectable"; import clusterManagerInjectable from "../../main/cluster-manager.injectable"; import stopServicesAndExitAppInjectable from "../../main/stop-services-and-exit-app.injectable"; @@ -14,15 +13,17 @@ import { advanceFakeTime, useFakeTime } from "../../common/test-utils/use-fake-t describe("quitting the app using application menu", () => { describe("given application has started", () => { - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; let clusterManagerStub: ClusterManager; let exitAppMock: jest.Mock; beforeEach(async () => { useFakeTime("2015-10-21T07:28:00Z"); - applicationBuilder = getApplicationBuilder().beforeApplicationStart( - ({ mainDi }) => { + builder = getApplicationBuilder(); + + builder.beforeApplicationStart( + (mainDi) => { mainDi.unoverride(stopServicesAndExitAppInjectable); clusterManagerStub = { stop: jest.fn() } as unknown as ClusterManager; @@ -33,38 +34,24 @@ describe("quitting the app using application menu", () => { }, ); - await applicationBuilder.render(); + await builder.render(); }); - it("only an application window is open", () => { - const windows = applicationBuilder.dis.mainDi.injectMany( - lensWindowInjectionToken, - ); + it("first application window is open", () => { + const windows = builder.applicationWindow.getAll(); - expect( - windows.map((window) => ({ id: window.id, visible: window.isVisible })), - ).toEqual([ - { id: "only-application-window", visible: true }, - { id: "splash", visible: false }, - ]); + expect(windows.map((window) => window.id)).toEqual(["first-application-window"]); }); describe("when application is quit", () => { beforeEach(() => { - applicationBuilder.applicationMenu.click("root.quit"); + builder.applicationMenu.click("root.quit"); }); it("closes all windows", () => { - const windows = applicationBuilder.dis.mainDi.injectMany( - lensWindowInjectionToken, - ); + const windows = builder.applicationWindow.getAll(); - expect( - windows.map((window) => ({ id: window.id, visible: window.isVisible })), - ).toEqual([ - { id: "only-application-window", visible: false }, - { id: "splash", visible: false }, - ]); + expect(windows).toEqual([]); }); it("disconnects all clusters", () => { diff --git a/src/behaviours/resolve-system-proxy/resolve-system-proxy.test.ts b/src/behaviours/resolve-system-proxy/resolve-system-proxy.test.ts index a78aa0dd68..d2e021ef98 100644 --- a/src/behaviours/resolve-system-proxy/resolve-system-proxy.test.ts +++ b/src/behaviours/resolve-system-proxy/resolve-system-proxy.test.ts @@ -12,28 +12,28 @@ import resolveSystemProxyFromElectronInjectable from "../../main/utils/resolve-s import { getPromiseStatus } from "../../common/test-utils/get-promise-status"; describe("resolve-system-proxy", () => { - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; let actualPromise: Promise; let resolveSystemProxyFromElectronMock: AsyncFnMock; beforeEach(async () => { - applicationBuilder = getApplicationBuilder(); + builder = getApplicationBuilder(); resolveSystemProxyFromElectronMock = asyncFn(); - applicationBuilder.beforeApplicationStart(({ mainDi }) => { + builder.beforeApplicationStart((mainDi) => { mainDi.override( resolveSystemProxyFromElectronInjectable, () => resolveSystemProxyFromElectronMock, ); }); - await applicationBuilder.render(); + await builder.render(); }); describe("given in main, when called with URL", () => { beforeEach(async () => { - const resolveSystemProxyInMain = applicationBuilder.dis.mainDi.inject( + const resolveSystemProxyInMain = builder.mainDi.inject( resolveSystemProxyInjectionToken, ); @@ -59,7 +59,9 @@ describe("resolve-system-proxy", () => { describe("given in renderer, when called with URL", () => { beforeEach(async () => { - const resolveSystemProxyInRenderer = applicationBuilder.dis.rendererDi.inject( + const windowDi = builder.applicationWindow.only.di; + + const resolveSystemProxyInRenderer = windowDi.inject( resolveSystemProxyInjectionToken, ); diff --git a/src/behaviours/routes/extension-api/reactively-disable-global-pages.test.tsx b/src/behaviours/routes/extension-api/reactively-disable-global-pages.test.tsx index 523a56cf79..deb4015480 100644 --- a/src/behaviours/routes/extension-api/reactively-disable-global-pages.test.tsx +++ b/src/behaviours/routes/extension-api/reactively-disable-global-pages.test.tsx @@ -9,7 +9,6 @@ import React from "react"; import type { TestExtensionRenderer } from "../../../renderer/components/test-utils/get-extension-fake"; import type { ApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; -import { getExtensionFakeFor } from "../../../renderer/components/test-utils/get-extension-fake"; describe("reactively disable global pages", () => { let builder: ApplicationBuilder; @@ -20,11 +19,9 @@ describe("reactively disable global pages", () => { beforeEach(async () => { builder = getApplicationBuilder(); - const getExtensionFake = getExtensionFakeFor(builder); - someObservable = observable.box(false); - const testExtension = getExtensionFake({ + const testExtension = { id: "test-extension-id", name: "test-extension", @@ -37,13 +34,13 @@ describe("reactively disable global pages", () => { enabled: computed(() => someObservable.get()), }], }, - }); + }; rendered = await builder.render(); builder.extensions.enable(testExtension); - rendererTestExtension = testExtension.renderer; + rendererTestExtension = builder.extensions.get("test-extension-id").applicationWindows.only; }); it("when navigating to the page, does not show the page", () => { diff --git a/src/behaviours/status-bar/status-bar-items-originating-from-extensions.test.tsx b/src/behaviours/status-bar/status-bar-items-originating-from-extensions.test.tsx index 998a8d7281..8d81720a7a 100644 --- a/src/behaviours/status-bar/status-bar-items-originating-from-extensions.test.tsx +++ b/src/behaviours/status-bar/status-bar-items-originating-from-extensions.test.tsx @@ -4,11 +4,10 @@ */ import type { RenderResult } from "@testing-library/react"; import React from "react"; -import type { GetRendererExtensionFake, TestExtension } from "../../renderer/components/test-utils/get-renderer-extension-fake"; -import { getRendererExtensionFakeFor } from "../../renderer/components/test-utils/get-renderer-extension-fake"; import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import getRandomIdInjectable from "../../common/utils/get-random-id.injectable"; +import type { FakeExtensionOptions } from "../../renderer/components/test-utils/get-extension-fake"; describe("status-bar-items-originating-from-extensions", () => { let applicationBuilder: ApplicationBuilder; @@ -16,50 +15,53 @@ describe("status-bar-items-originating-from-extensions", () => { beforeEach(() => { applicationBuilder = getApplicationBuilder(); - applicationBuilder.beforeApplicationStart(({ rendererDi }) => { - rendererDi.unoverride(getRandomIdInjectable); - rendererDi.permitSideEffects(getRandomIdInjectable); + applicationBuilder.beforeWindowStart((windowDi) => { + windowDi.unoverride(getRandomIdInjectable); + windowDi.permitSideEffects(getRandomIdInjectable); }); }); describe("when application starts", () => { let rendered: RenderResult; - let getRendererExtensionFake: GetRendererExtensionFake; beforeEach(async () => { rendered = await applicationBuilder.render(); - getRendererExtensionFake = getRendererExtensionFakeFor(applicationBuilder); }); it("when multiple extensions with status bar items are loaded, shows items in correct order", () => { - const testExtension1 = getRendererExtensionFake({ + const testExtension1 = { id: "some-id", name: "some-name", - statusBarItems: [ - { - components: { - Item: () =>
extension1
, - position: "right", + rendererOptions: { + statusBarItems: [ + { + components: { + Item: () =>
extension1
, + position: "right" as const, + }, }, - }, - ], - }); + ], + }, + }; - const testExtension2 = getRendererExtensionFake({ + const testExtension2 = { id: "some-other-id", name: "some-other-name", - statusBarItems: [ - { - components: { - Item: () =>
extension2
, - position: "right", - }, - }, - ], - }); - applicationBuilder.extensions.renderer.enable(testExtension1, testExtension2); + rendererOptions: { + statusBarItems: [ + { + components: { + Item: () =>
extension2
, + position: "right" as const, + }, + }, + ], + }, + }; + + applicationBuilder.extensions.enable(testExtension1, testExtension2); const rightSide = rendered.getByTestId("status-bar-right"); @@ -72,41 +74,44 @@ describe("status-bar-items-originating-from-extensions", () => { }); describe("when extension with status bar items is loaded", () => { - let testExtension: TestExtension; + let testExtensionOptions: FakeExtensionOptions; beforeEach(() => { - testExtension = getRendererExtensionFake({ + testExtensionOptions = { id: "some-id", name: "some-name", - statusBarItems: [ - { - item: () => right1, - }, - { - item: () => right2, - }, - { - components: { - Item: () =>
right3
, - position: "right", - }, - }, - { - components: { - Item: () =>
left1
, - position: "left", - }, - }, - { - components: { - Item: () =>
left2
, - position: "left", - }, - }, - ], - }); - applicationBuilder.extensions.renderer.enable(testExtension); + rendererOptions: { + statusBarItems: [ + { + item: () => right1, + }, + { + item: () => right2, + }, + { + components: { + Item: () =>
right3
, + position: "right" as const, + }, + }, + { + components: { + Item: () =>
left1
, + position: "left" as const, + }, + }, + { + components: { + Item: () =>
left2
, + position: "left" as const, + }, + }, + ], + }, + }; + + applicationBuilder.extensions.enable(testExtensionOptions); }); it("renders", () => { @@ -134,7 +139,7 @@ describe("status-bar-items-originating-from-extensions", () => { }); it("when the extension is removed, shows there are no extension status bar items", () => { - applicationBuilder.extensions.renderer.disable(testExtension); + applicationBuilder.extensions.disable(testExtensionOptions); const actual = rendered.queryAllByTestId("some-testId"); diff --git a/src/behaviours/tray/clicking-tray-menu-item-originating-from-extension.test.ts b/src/behaviours/tray/clicking-tray-menu-item-originating-from-extension.test.ts index 006760f902..667671a927 100644 --- a/src/behaviours/tray/clicking-tray-menu-item-originating-from-extension.test.ts +++ b/src/behaviours/tray/clicking-tray-menu-item-originating-from-extension.test.ts @@ -2,47 +2,49 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { LensMainExtension } from "../../extensions/lens-main-extension"; -import type { TrayMenuRegistration } from "../../main/tray/tray-menu-registration"; import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import loggerInjectable from "../../common/logger.injectable"; import type { Logger } from "../../common/logger"; +import type { FakeExtensionOptions } from "../../renderer/components/test-utils/get-extension-fake"; describe("clicking tray menu item originating from extension", () => { - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; let logErrorMock: jest.Mock; beforeEach(async () => { - applicationBuilder = getApplicationBuilder(); + builder = getApplicationBuilder(); - applicationBuilder.beforeApplicationStart(({ mainDi }) => { + builder.beforeApplicationStart((mainDi) => { logErrorMock = jest.fn(); mainDi.override(loggerInjectable, () => ({ error: logErrorMock }) as unknown as Logger); }); - await applicationBuilder.render(); + await builder.render(); }); describe("when extension is enabled", () => { - let someExtension: SomeTestExtension; + let someExtension: FakeExtensionOptions; let clickMock: jest.Mock; beforeEach(() => { clickMock = jest.fn(); - someExtension = new SomeTestExtension({ + someExtension = { id: "some-extension-id", - trayMenus: [{ label: "some-label", click: clickMock }], - }); + name: "some-extension-name", + mainOptions: { + trayMenus: [{ label: "some-label", click: clickMock }], + }, + }; - applicationBuilder.extensions.main.enable(someExtension); + builder.extensions.enable(someExtension); }); it("when item is clicked, triggers the click handler", () => { - applicationBuilder.tray.click( - "some-label-tray-menu-item-for-extension-some-extension-id", + builder.tray.click( + "some-label-tray-menu-item-for-extension-some-extension-name", ); expect(clickMock).toHaveBeenCalled(); @@ -54,14 +56,14 @@ describe("clicking tray menu item originating from extension", () => { throw new Error("some-error"); }); - applicationBuilder.tray.click( - "some-label-tray-menu-item-for-extension-some-extension-id", + builder.tray.click( + "some-label-tray-menu-item-for-extension-some-extension-name", ); }); it("logs the error", () => { expect(logErrorMock).toHaveBeenCalledWith( - '[TRAY]: Clicking of tray item "some-label" from extension "some-extension-id" failed.', + '[TRAY]: Clicking of tray item "some-label" from extension "some-extension-name" failed.', expect.any(Error), ); }); @@ -71,14 +73,14 @@ describe("clicking tray menu item originating from extension", () => { beforeEach(() => { clickMock.mockImplementation(() => Promise.reject("some-rejection")); - applicationBuilder.tray.click( - "some-label-tray-menu-item-for-extension-some-extension-id", + builder.tray.click( + "some-label-tray-menu-item-for-extension-some-extension-name", ); }); it("logs the error", () => { expect(logErrorMock).toHaveBeenCalledWith( - '[TRAY]: Clicking of tray item "some-label" from extension "some-extension-id" failed.', + '[TRAY]: Clicking of tray item "some-label" from extension "some-extension-name" failed.', "some-rejection", ); }); @@ -86,47 +88,27 @@ describe("clicking tray menu item originating from extension", () => { describe("when extension is disabled", () => { beforeEach(() => { - applicationBuilder.extensions.main.disable(someExtension); + builder.extensions.disable(someExtension); }); it("does not have the tray menu item from extension", () => { expect( - applicationBuilder.tray.get( - "some-label-tray-menu-item-for-extension-some-extension-id", + builder.tray.get( + "some-label-tray-menu-item-for-extension-some-extension-name", ), ).toBeNull(); }); // Note: Motivation here is to make sure that enabling same extension does not throw it("when extension is re-enabled, has the tray menu item from extension", async () => { - await applicationBuilder.extensions.main.enable(someExtension); + await builder.extensions.enable(someExtension); expect( - applicationBuilder.tray.get( - "some-label-tray-menu-item-for-extension-some-extension-id", + builder.tray.get( + "some-label-tray-menu-item-for-extension-some-extension-name", ), ).not.toBeNull(); }); }); - }); }); - -class SomeTestExtension extends LensMainExtension { - constructor({ id, trayMenus }: { - id: string; - trayMenus: TrayMenuRegistration[]; - }) { - super({ - id, - absolutePath: "irrelevant", - isBundled: false, - isCompatible: false, - isEnabled: false, - manifest: { name: id, version: "some-version", engines: { lens: "^5.5.0" }}, - manifestPath: "irrelevant", - }); - - this.trayMenus = trayMenus; - } -} diff --git a/src/behaviours/tray/extension-adding-tray-items.test.tsx b/src/behaviours/tray/extension-adding-tray-items.test.tsx index 35e09e0f76..0860cb5d00 100644 --- a/src/behaviours/tray/extension-adding-tray-items.test.tsx +++ b/src/behaviours/tray/extension-adding-tray-items.test.tsx @@ -6,7 +6,6 @@ import type { IObservableValue } from "mobx"; import { computed, runInAction, observable } from "mobx"; import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; -import { getExtensionFakeFor } from "../../renderer/components/test-utils/get-extension-fake"; describe("preferences: extension adding tray items", () => { describe("when extension with tray items is enabled", () => { @@ -21,12 +20,10 @@ describe("preferences: extension adding tray items", () => { builder.preferences.navigate(); - const getExtensionFake = getExtensionFakeFor(builder); - someObservableForVisibility = observable.box(false); someObservableForEnabled = observable.box(false); - const testExtension = getExtensionFake({ + const testExtension = { id: "some-extension-id", name: "some-extension", @@ -67,7 +64,7 @@ describe("preferences: extension adding tray items", () => { }, ], }, - }); + }; builder.extensions.enable(testExtension); }); diff --git a/src/behaviours/tray/multiple-separators-originating-from-extension.test.ts b/src/behaviours/tray/multiple-separators-originating-from-extension.test.ts index 96b9f18198..fd21d78bae 100644 --- a/src/behaviours/tray/multiple-separators-originating-from-extension.test.ts +++ b/src/behaviours/tray/multiple-separators-originating-from-extension.test.ts @@ -2,53 +2,36 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { LensMainExtension } from "../../extensions/lens-main-extension"; -import type { TrayMenuRegistration } from "../../main/tray/tray-menu-registration"; import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import getRandomIdInjectable from "../../common/utils/get-random-id.injectable"; describe("multiple separators originating from extension", () => { - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; beforeEach(async () => { - applicationBuilder = getApplicationBuilder(); + builder = getApplicationBuilder(); - applicationBuilder.beforeApplicationStart(({ mainDi }) => { + builder.beforeApplicationStart((mainDi) => { mainDi.unoverride(getRandomIdInjectable); mainDi.permitSideEffects(getRandomIdInjectable); }); - await applicationBuilder.render(); + await builder.render(); }); it("given extension with multiple separators, when extension is enabled, does not throw", () => { - const someExtension = new SomeTestExtension({ + const someExtension = { id: "some-extension-id", - trayMenus: [{ type: "separator" }, { type: "separator" } ], - }); + name: "some-extension", + + mainOptions: { + trayMenus: [{ type: "separator" as const }, { type: "separator" as const } ], + }, + }; expect(() => { - applicationBuilder.extensions.main.enable(someExtension); + builder.extensions.enable(someExtension); }).not.toThrow(); }); }); - -class SomeTestExtension extends LensMainExtension { - constructor({ id, trayMenus }: { - id: string; - trayMenus: TrayMenuRegistration[]; - }) { - super({ - id, - absolutePath: "irrelevant", - isBundled: false, - isCompatible: false, - isEnabled: false, - manifest: { name: id, version: "some-version", engines: { lens: "^5.5.0" }}, - manifestPath: "irrelevant", - }); - - this.trayMenus = trayMenus; - } -} diff --git a/src/common/app-paths/app-paths.test.ts b/src/common/app-paths/app-paths.test.ts index 5793295e0e..b5ec33059c 100644 --- a/src/common/app-paths/app-paths.test.ts +++ b/src/common/app-paths/app-paths.test.ts @@ -14,15 +14,10 @@ import { getApplicationBuilder } from "../../renderer/components/test-utils/get- import type { DiContainer } from "@ogre-tools/injectable"; describe("app-paths", () => { - let applicationBuilder: ApplicationBuilder; - let rendererDi: DiContainer; - let mainDi: DiContainer; + let builder: ApplicationBuilder; beforeEach(() => { - applicationBuilder = getApplicationBuilder(); - - rendererDi = applicationBuilder.dis.rendererDi; - mainDi = applicationBuilder.dis.mainDi; + builder = getApplicationBuilder(); const defaultAppPathsStub: AppPaths = { appData: "some-app-data", @@ -43,7 +38,7 @@ describe("app-paths", () => { userData: "some-irrelevant-user-data", }; - applicationBuilder.beforeApplicationStart(({ mainDi }) => { + builder.beforeApplicationStart((mainDi) => { mainDi.override( getElectronAppPathInjectable, () => @@ -64,12 +59,18 @@ describe("app-paths", () => { }); describe("normally", () => { + let windowDi: DiContainer; + let mainDi: DiContainer; + beforeEach(async () => { - await applicationBuilder.render(); + await builder.render(); + + windowDi = builder.applicationWindow.only.di; + mainDi = builder.mainDi; }); it("given in renderer, when injecting app paths, returns application specific app paths", () => { - const actual = rendererDi.inject(appPathsInjectionToken); + const actual = windowDi.inject(appPathsInjectionToken); expect(actual).toEqual({ appData: "some-app-data", @@ -116,19 +117,23 @@ describe("app-paths", () => { }); describe("when running integration tests", () => { + let windowDi: DiContainer; + beforeEach(async () => { - applicationBuilder.beforeApplicationStart(({ mainDi }) => { + builder.beforeApplicationStart((mainDi) => { mainDi.override( directoryForIntegrationTestingInjectable, () => "some-integration-testing-app-data", ); }); - await applicationBuilder.render(); + await builder.render(); + + windowDi = builder.applicationWindow.only.di; }); it("given in renderer, when injecting path for app data, has integration specific app data path", () => { - const { appData, userData } = rendererDi.inject(appPathsInjectionToken); + const { appData, userData } = windowDi.inject(appPathsInjectionToken); expect({ appData, userData }).toEqual({ appData: "some-integration-testing-app-data", @@ -137,7 +142,7 @@ describe("app-paths", () => { }); it("given in main, when injecting path for app data, has integration specific app data path", () => { - const { appData, userData } = rendererDi.inject(appPathsInjectionToken); + const { appData, userData } = windowDi.inject(appPathsInjectionToken); expect({ appData, userData }).toEqual({ appData: "some-integration-testing-app-data", diff --git a/src/common/cluster-store/cluster-store.global-override-for-injectable.ts b/src/common/cluster-store/cluster-store.global-override-for-injectable.ts new file mode 100644 index 0000000000..32a1ee62a1 --- /dev/null +++ b/src/common/cluster-store/cluster-store.global-override-for-injectable.ts @@ -0,0 +1,17 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getGlobalOverride } from "../test-utils/get-global-override"; +import clusterStoreInjectable from "./cluster-store.injectable"; +import type { Cluster } from "../cluster/cluster"; +import type { ClusterStore } from "./cluster-store"; + +export default getGlobalOverride( + clusterStoreInjectable, + () => + ({ + provideInitialFromMain: () => {}, + getById: (id) => (void id, {}) as Cluster, + } as ClusterStore), +); diff --git a/src/common/utils/channel/channel.test.ts b/src/common/utils/channel/channel.test.ts index 84c1366f35..a3d6a805e2 100644 --- a/src/common/utils/channel/channel.test.ts +++ b/src/common/utils/channel/channel.test.ts @@ -4,13 +4,11 @@ */ import type { DiContainer } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable"; -import type { LensWindow } from "../../../main/start-main-application/lens-window/application-window/lens-window-injection-token"; -import { lensWindowInjectionToken } from "../../../main/start-main-application/lens-window/application-window/lens-window-injection-token"; import type { MessageToChannel } from "./message-to-channel-injection-token"; import { messageToChannelInjectionToken } from "./message-to-channel-injection-token"; +import type { ApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; -import createLensWindowInjectable from "../../../main/start-main-application/lens-window/application-window/create-lens-window.injectable"; -import closeAllWindowsInjectable from "../../../main/start-main-application/lens-window/hide-all-windows/close-all-windows.injectable"; +import type { LensWindow } from "../../../main/start-main-application/lens-window/application-window/create-lens-window.injectable"; import { messageChannelListenerInjectionToken } from "./message-channel-listener-injection-token"; import type { MessageChannel } from "./message-channel-injection-token"; import type { RequestFromChannel } from "./request-from-channel-injection-token"; @@ -30,12 +28,10 @@ describe("channel", () => { let messageListenerInWindowMock: jest.Mock; let mainDi: DiContainer; let messageToChannel: MessageToChannel; + let builder: ApplicationBuilder; beforeEach(async () => { - const applicationBuilder = getApplicationBuilder(); - - mainDi = applicationBuilder.dis.mainDi; - const rendererDi = applicationBuilder.dis.rendererDi; + builder = getApplicationBuilder(); messageListenerInWindowMock = jest.fn(); @@ -44,37 +40,34 @@ describe("channel", () => { instantiate: (di) => ({ channel: di.inject(testMessageChannelInjectable), - handler: messageListenerInWindowMock, }), injectionToken: messageChannelListenerInjectionToken, }); - rendererDi.register(testChannelListenerInTestWindowInjectable); + builder.beforeApplicationStart((mainDi) => { + mainDi.register(testMessageChannelInjectable); + }); - // Notice how test channel has presence in both DIs, being from common - mainDi.register(testMessageChannelInjectable); - rendererDi.register(testMessageChannelInjectable); + builder.beforeWindowStart((windowDi) => { + windowDi.register(testChannelListenerInTestWindowInjectable); + windowDi.register(testMessageChannelInjectable); + }); + + mainDi = builder.mainDi; + + await builder.startHidden(); testMessageChannel = mainDi.inject(testMessageChannelInjectable); - - messageToChannel = mainDi.inject( - messageToChannelInjectionToken, - ); - - await applicationBuilder.render(); - - const closeAllWindows = mainDi.inject(closeAllWindowsInjectable); - - closeAllWindows(); + messageToChannel = mainDi.inject(messageToChannelInjectionToken); }); describe("given window is started", () => { let someWindowFake: LensWindow; beforeEach(async () => { - someWindowFake = createTestWindow(mainDi, "some-window"); + someWindowFake = builder.applicationWindow.create("some-window"); await someWindowFake.start(); }); @@ -95,8 +88,8 @@ describe("channel", () => { }); it("given multiple started windows, when sending message, triggers listeners in all windows", async () => { - const someWindowFake = createTestWindow(mainDi, "some-window"); - const someOtherWindowFake = createTestWindow(mainDi, "some-other-window"); + const someWindowFake = builder.applicationWindow.create("some-window"); + const someOtherWindowFake = builder.applicationWindow.create("some-other-window"); await someWindowFake.start(); await someOtherWindowFake.start(); @@ -113,16 +106,11 @@ describe("channel", () => { describe("messaging from renderer to main, given listener for channel in a main and application has started", () => { let testMessageChannel: TestMessageChannel; let messageListenerInMainMock: jest.Mock; - let rendererDi: DiContainer; - let mainDi: DiContainer; let messageToChannel: MessageToChannel; beforeEach(async () => { const applicationBuilder = getApplicationBuilder(); - mainDi = applicationBuilder.dis.mainDi; - rendererDi = applicationBuilder.dis.rendererDi; - messageListenerInMainMock = jest.fn(); const testChannelListenerInMainInjectable = getInjectable({ @@ -137,19 +125,21 @@ describe("channel", () => { injectionToken: messageChannelListenerInjectionToken, }); - mainDi.register(testChannelListenerInMainInjectable); + applicationBuilder.beforeApplicationStart((mainDi) => { + mainDi.register(testChannelListenerInMainInjectable); + mainDi.register(testMessageChannelInjectable); + }); - // Notice how test channel has presence in both DIs, being from common - mainDi.register(testMessageChannelInjectable); - rendererDi.register(testMessageChannelInjectable); - - testMessageChannel = rendererDi.inject(testMessageChannelInjectable); - - messageToChannel = rendererDi.inject( - messageToChannelInjectionToken, - ); + applicationBuilder.beforeWindowStart((windowDi) => { + windowDi.register(testMessageChannelInjectable); + }); await applicationBuilder.render(); + + const windowDi = applicationBuilder.applicationWindow.only.di; + + testMessageChannel = windowDi.inject(testMessageChannelInjectable); + messageToChannel = windowDi.inject(messageToChannelInjectionToken); }); it("when sending message, triggers listener in main", () => { @@ -162,16 +152,11 @@ describe("channel", () => { describe("requesting from main in renderer, given listener for channel in a main and application has started", () => { let testRequestChannel: TestRequestChannel; let requestListenerInMainMock: AsyncFnMock<(arg: string) => string>; - let rendererDi: DiContainer; - let mainDi: DiContainer; let requestFromChannel: RequestFromChannel; beforeEach(async () => { const applicationBuilder = getApplicationBuilder(); - mainDi = applicationBuilder.dis.mainDi; - rendererDi = applicationBuilder.dis.rendererDi; - requestListenerInMainMock = asyncFn(); const testChannelListenerInMainInjectable = getInjectable({ @@ -186,19 +171,24 @@ describe("channel", () => { injectionToken: requestChannelListenerInjectionToken, }); - mainDi.register(testChannelListenerInMainInjectable); + applicationBuilder.beforeApplicationStart((mainDi) => { + mainDi.register(testChannelListenerInMainInjectable); + mainDi.register(testRequestChannelInjectable); + }); - // Notice how test channel has presence in both DIs, being from common - mainDi.register(testRequestChannelInjectable); - rendererDi.register(testRequestChannelInjectable); - - testRequestChannel = rendererDi.inject(testRequestChannelInjectable); - - requestFromChannel = rendererDi.inject( - requestFromChannelInjectionToken, - ); + applicationBuilder.beforeWindowStart((windowDi) => { + windowDi.register(testRequestChannelInjectable); + }); await applicationBuilder.render(); + + const windowDi = applicationBuilder.applicationWindow.only.di; + + testRequestChannel = windowDi.inject(testRequestChannelInjectable); + + requestFromChannel = windowDi.inject( + requestFromChannelInjectionToken, + ); }); describe("when requesting from channel", () => { @@ -245,29 +235,3 @@ const testRequestChannelInjectable = getInjectable({ }), }); -const createTestWindow = (di: DiContainer, id: string) => { - const testWindowInjectable = getInjectable({ - id, - - instantiate: (di) => { - const createLensWindow = di.inject(createLensWindowInjectable); - - return createLensWindow({ - id, - title: "Some test window", - defaultHeight: 42, - defaultWidth: 42, - getContentSource: () => ({ url: "some-content-url" }), - resizable: true, - windowFrameUtilitiesAreShown: false, - centered: false, - }); - }, - - injectionToken: lensWindowInjectionToken, - }); - - di.register(testWindowInjectable); - - return di.inject(testWindowInjectable); -}; diff --git a/src/common/utils/sync-box/sync-box.test.ts b/src/common/utils/sync-box/sync-box.test.ts index 2dccbd87a5..cfb8954802 100644 --- a/src/common/utils/sync-box/sync-box.test.ts +++ b/src/common/utils/sync-box/sync-box.test.ts @@ -2,13 +2,14 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ +import type { DiContainer } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable"; import { observe, runInAction } from "mobx"; import type { ApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; import createSyncBoxInjectable from "./create-sync-box.injectable"; -import { flushPromises } from "../../test-utils/flush-promises"; import type { SyncBox } from "./sync-box-injection-token"; +import { syncBoxInjectionToken } from "./sync-box-injection-token"; describe("sync-box", () => { let applicationBuilder: ApplicationBuilder; @@ -16,19 +17,23 @@ describe("sync-box", () => { beforeEach(() => { applicationBuilder = getApplicationBuilder(); - applicationBuilder.dis.mainDi.register(someInjectable); - applicationBuilder.dis.rendererDi.register(someInjectable); + applicationBuilder.beforeApplicationStart(mainDi => { + mainDi.register(someInjectable); + }); + + applicationBuilder.beforeWindowStart((windowDi) => { + windowDi.register(someInjectable); + }); }); - // TODO: Separate starting for main application and starting of window in application builder - xdescribe("given application is started, when value is set in main", () => { + describe("given application is started, when value is set in main", () => { let valueInMain: string; let syncBoxInMain: SyncBox; beforeEach(async () => { - syncBoxInMain = applicationBuilder.dis.mainDi.inject(someInjectable); + await applicationBuilder.startHidden(); - // await applicationBuilder.start(); + syncBoxInMain = applicationBuilder.mainDi.inject(someInjectable); observe(syncBoxInMain.value, ({ newValue }) => { valueInMain = newValue as string; @@ -46,48 +51,28 @@ describe("sync-box", () => { describe("when window starts", () => { let valueInRenderer: string; let syncBoxInRenderer: SyncBox; + let rendererDi: DiContainer; - beforeEach(() => { - // applicationBuilder.renderWindow() + beforeEach(async () => { + const applicationWindow = + applicationBuilder.applicationWindow.create("some-window-id"); - syncBoxInRenderer = applicationBuilder.dis.rendererDi.inject(someInjectable); + await applicationWindow.start(); + + rendererDi = applicationWindow.di; + + syncBoxInRenderer = rendererDi.inject(someInjectable); observe(syncBoxInRenderer.value, ({ newValue }) => { valueInRenderer = newValue as string; }, true); }); - it("does not have the initial value yet", () => { - expect(valueInRenderer).toBe(undefined); + it("has the value from main", () => { + expect(valueInRenderer).toBe("some-value-from-main"); }); - describe("when getting initial value resolves", () => { - beforeEach(async () => { - await flushPromises(); - }); - - it("has value in renderer", () => { - expect(valueInRenderer).toBe("some-value-from-main"); - }); - - describe("when value is set from renderer", () => { - beforeEach(() => { - runInAction(() => { - syncBoxInRenderer.set("some-value-from-renderer"); - }); - }); - - it("has value in main", () => { - expect(valueInMain).toBe("some-value-from-renderer"); - }); - - it("has value in renderer", () => { - expect(valueInRenderer).toBe("some-value-from-renderer"); - }); - }); - }); - - describe("when value is set from renderer before getting initial value from main resolves", () => { + describe("when value is set from renderer", () => { beforeEach(() => { runInAction(() => { syncBoxInRenderer.set("some-value-from-renderer"); @@ -112,11 +97,13 @@ describe("sync-box", () => { let syncBoxInRenderer: SyncBox; beforeEach(async () => { - syncBoxInMain = applicationBuilder.dis.mainDi.inject(someInjectable); - syncBoxInRenderer = applicationBuilder.dis.rendererDi.inject(someInjectable); - await applicationBuilder.render(); + const applicationWindow = applicationBuilder.applicationWindow.only; + + syncBoxInMain = applicationBuilder.mainDi.inject(someInjectable); + syncBoxInRenderer = applicationWindow.di.inject(someInjectable); + observe(syncBoxInRenderer.value, ({ newValue }) => { valueInRenderer = newValue as string; }, true); @@ -176,4 +163,6 @@ const someInjectable = getInjectable({ return createSyncBox("some-sync-box", "some-initial-value"); }, + + injectionToken: syncBoxInjectionToken, }); diff --git a/src/main/getDiForUnitTesting.ts b/src/main/getDiForUnitTesting.ts index 9c5a3ab741..08be89004d 100644 --- a/src/main/getDiForUnitTesting.ts +++ b/src/main/getDiForUnitTesting.ts @@ -18,9 +18,6 @@ import extensionsStoreInjectable from "../extensions/extensions-store/extensions import type { ExtensionsStore } from "../extensions/extensions-store/extensions-store"; import fileSystemProvisionerStoreInjectable from "../extensions/extension-loader/file-system-provisioner-store/file-system-provisioner-store.injectable"; import type { FileSystemProvisionerStore } from "../extensions/extension-loader/file-system-provisioner-store/file-system-provisioner-store"; -import clusterStoreInjectable from "../common/cluster-store/cluster-store.injectable"; -import type { ClusterStore } from "../common/cluster-store/cluster-store"; -import type { Cluster } from "../common/cluster/cluster"; import userStoreInjectable from "../common/user-store/user-store.injectable"; import type { UserStore } from "../common/user-store"; import getAbsolutePathInjectable from "../common/path/get-absolute-path.injectable"; @@ -63,9 +60,7 @@ import { observable } from "mobx"; import waitForElectronToBeReadyInjectable from "./electron-app/features/wait-for-electron-to-be-ready.injectable"; import setupListenerForCurrentClusterFrameInjectable from "./start-main-application/lens-window/current-cluster-frame/setup-listener-for-current-cluster-frame.injectable"; import ipcMainInjectable from "./utils/channel/ipc-main/ipc-main.injectable"; -import createElectronWindowForInjectable from "./start-main-application/lens-window/application-window/create-electron-window.injectable"; import setupRunnablesAfterWindowIsOpenedInjectable from "./electron-app/runnables/setup-runnables-after-window-is-opened.injectable"; -import sendToChannelInElectronBrowserWindowInjectable from "./start-main-application/lens-window/application-window/send-to-channel-in-electron-browser-window.injectable"; import broadcastMessageInjectable from "../common/ipc/broadcast-message.injectable"; import getElectronThemeInjectable from "./electron-app/features/get-electron-theme.injectable"; import syncThemeFromOperatingSystemInjectable from "./electron-app/features/sync-theme-from-operating-system.injectable"; @@ -146,7 +141,6 @@ export function getDiForUnitTesting(opts: { doGeneralOverrides?: boolean } = {}) di.override(userStoreInjectable, () => ({ startMainReactions: () => {}, extensionRegistryUrl: { customUrl: "some-custom-url" }}) as UserStore); di.override(extensionsStoreInjectable, () => ({ isEnabled: (opts) => (void opts, false) }) as ExtensionsStore); - di.override(clusterStoreInjectable, () => ({ provideInitialFromMain: () => {}, getById: (id) => (void id, {}) as Cluster }) as ClusterStore); di.override(fileSystemProvisionerStoreInjectable, () => ({}) as FileSystemProvisionerStore); overrideOperatingSystem(di); @@ -286,21 +280,6 @@ const overrideElectronFeatures = (di: DiContainer) => { throw new Error("Tried to check for platform updates without explicit override."); }); - di.override(createElectronWindowForInjectable, () => () => ({ - show: () => {}, - - close: () => {}, - - send: (arg) => { - const sendFake = di.inject(sendToChannelInElectronBrowserWindowInjectable) as any; - - sendFake(null, arg); - }, - - loadFile: async () => {}, - loadUrl: async () => {}, - })); - di.override( getElectronAppPathInjectable, () => (name: string) => `some-electron-app-path-for-${kebabCase(name)}`, diff --git a/src/main/utils/channel/message-to-channel.test.ts b/src/main/utils/channel/message-to-channel.test.ts index 67a407de55..6d5e83a548 100644 --- a/src/main/utils/channel/message-to-channel.test.ts +++ b/src/main/utils/channel/message-to-channel.test.ts @@ -5,15 +5,10 @@ import type { MessageToChannel } from "../../../common/utils/channel/message-to-channel-injection-token"; import { messageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; -import closeAllWindowsInjectable from "../../start-main-application/lens-window/hide-all-windows/close-all-windows.injectable"; import type { MessageChannel } from "../../../common/utils/channel/message-channel-injection-token"; -import { getDiForUnitTesting } from "../../getDiForUnitTesting"; -import createLensWindowInjectable from "../../start-main-application/lens-window/application-window/create-lens-window.injectable"; -import type { LensWindow } from "../../start-main-application/lens-window/application-window/lens-window-injection-token"; -import { lensWindowInjectionToken } from "../../start-main-application/lens-window/application-window/lens-window-injection-token"; -import type { DiContainer } from "@ogre-tools/injectable"; -import { getInjectable } from "@ogre-tools/injectable"; +import type { LensWindow } from "../../start-main-application/lens-window/application-window/create-lens-window.injectable"; import sendToChannelInElectronBrowserWindowInjectable from "../../start-main-application/lens-window/application-window/send-to-channel-in-electron-browser-window.injectable"; +import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; describe("message to channel from main", () => { let messageToChannel: MessageToChannel; @@ -21,20 +16,21 @@ describe("message to channel from main", () => { let someOtherTestWindow: LensWindow; let sendToChannelInBrowserMock: jest.Mock; - beforeEach(() => { - const di = getDiForUnitTesting({ doGeneralOverrides: true }); + beforeEach(async () => { + const builder = getApplicationBuilder(); sendToChannelInBrowserMock = jest.fn(); - di.override(sendToChannelInElectronBrowserWindowInjectable, () => sendToChannelInBrowserMock); - someTestWindow = createTestWindow(di, "some-test-window-id"); - someOtherTestWindow = createTestWindow(di, "some-other-test-window-id"); + builder.beforeApplicationStart(mainDi => { + mainDi.override(sendToChannelInElectronBrowserWindowInjectable, () => sendToChannelInBrowserMock); + }); - messageToChannel = di.inject(messageToChannelInjectionToken); + await builder.startHidden(); - const closeAllWindows = di.inject(closeAllWindowsInjectable); + someTestWindow = builder.applicationWindow.create("some-test-window-id"); + someOtherTestWindow = builder.applicationWindow.create("some-other-test-window-id"); - closeAllWindows(); + messageToChannel = builder.mainDi.inject(messageToChannelInjectionToken); }); it("given no visible windows, when messaging to channel, does not message to any window", () => { @@ -53,6 +49,8 @@ describe("message to channel from main", () => { expect(sendToChannelInBrowserMock.mock.calls).toEqual([ [ + "some-test-window-id", + null, { @@ -68,6 +66,8 @@ describe("message to channel from main", () => { expect(sendToChannelInBrowserMock.mock.calls).toEqual([ [ + "some-test-window-id", + null, { @@ -83,6 +83,8 @@ describe("message to channel from main", () => { expect(sendToChannelInBrowserMock.mock.calls).toEqual([ [ + "some-test-window-id", + null, { @@ -98,6 +100,8 @@ describe("message to channel from main", () => { expect(sendToChannelInBrowserMock.mock.calls).toEqual([ [ + "some-test-window-id", + null, { @@ -117,6 +121,8 @@ describe("message to channel from main", () => { expect(sendToChannelInBrowserMock.mock.calls).toEqual([ [ + "some-test-window-id", + null, { @@ -126,6 +132,8 @@ describe("message to channel from main", () => { ], [ + "some-other-test-window-id", + null, { @@ -138,30 +146,3 @@ describe("message to channel from main", () => { }); const someChannel: MessageChannel = { id: "some-channel" }; - -const createTestWindow = (di: DiContainer, id: string) => { - const testWindowInjectable = getInjectable({ - id, - - instantiate: (di) => { - const createLensWindow = di.inject(createLensWindowInjectable); - - return createLensWindow({ - id, - title: "Some test window", - defaultHeight: 42, - defaultWidth: 42, - getContentSource: () => ({ url: "some-content-url" }), - resizable: true, - windowFrameUtilitiesAreShown: false, - centered: false, - }); - }, - - injectionToken: lensWindowInjectionToken, - }); - - di.register(testWindowInjectable); - - return di.inject(testWindowInjectable); -}; diff --git a/src/renderer/components/+preferences/preferences-navigation/__tests__/preferences-navigation.test.tsx b/src/renderer/components/+preferences/preferences-navigation/__tests__/preferences-navigation.test.tsx index 0d4547ae6a..81244bcd24 100644 --- a/src/renderer/components/+preferences/preferences-navigation/__tests__/preferences-navigation.test.tsx +++ b/src/renderer/components/+preferences/preferences-navigation/__tests__/preferences-navigation.test.tsx @@ -13,10 +13,10 @@ import type { PreferenceNavigationItem } from "../preference-navigation-items.in import preferenceNavigationItemsInjectable from "../preference-navigation-items.injectable"; describe.only("preferences - navigation block with links", () => { - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; beforeEach(() => { - applicationBuilder = getApplicationBuilder(); + builder = getApplicationBuilder(); }); describe("given in preferences, when rendered", () => { @@ -24,17 +24,15 @@ describe.only("preferences - navigation block with links", () => { describe("when general navigation items passed", () => { beforeEach(async () => { - applicationBuilder.beforeApplicationStart(({ rendererDi }) => { - rendererDi.override(preferenceNavigationItemsInjectable, () => + builder.beforeWindowStart((windowDi) => { + windowDi.override(preferenceNavigationItemsInjectable, () => computed(() => generalNavItems), ); + + builder.preferences.navigate(); }); - applicationBuilder.beforeRender(() => { - applicationBuilder.preferences.navigate(); - }); - - renderer = await applicationBuilder.render(); + renderer = await builder.render(); }); const links = ["General", "Proxy"]; @@ -52,17 +50,15 @@ describe.only("preferences - navigation block with links", () => { describe("when general + extension navigation items passed", () => { beforeEach(async () => { - applicationBuilder.beforeApplicationStart(({ rendererDi }) => { - rendererDi.override(preferenceNavigationItemsInjectable, () => + builder.beforeWindowStart((windowDi) => { + windowDi.override(preferenceNavigationItemsInjectable, () => computed(() => [...generalNavItems, ...extensionNavItems]), ); + + builder.preferences.navigate(); }); - applicationBuilder.beforeRender(() => { - applicationBuilder.preferences.navigate(); - }); - - renderer = await applicationBuilder.render(); + renderer = await builder.render(); }); const generalLinks = ["General", "Proxy"]; diff --git a/src/renderer/components/delete-cluster-dialog/__tests__/delete-cluster-dialog.test.tsx b/src/renderer/components/delete-cluster-dialog/__tests__/delete-cluster-dialog.test.tsx index 8978e00b5b..ad810ef2dd 100644 --- a/src/renderer/components/delete-cluster-dialog/__tests__/delete-cluster-dialog.test.tsx +++ b/src/renderer/components/delete-cluster-dialog/__tests__/delete-cluster-dialog.test.tsx @@ -6,13 +6,10 @@ import "@testing-library/jest-dom/extend-expect"; import { KubeConfig } from "@kubernetes/client-node"; import { fireEvent } from "@testing-library/react"; import type { RenderResult } from "@testing-library/react"; -import mockFs from "mock-fs"; import * as selectEvent from "react-select-event"; import type { CreateCluster } from "../../../../common/cluster/create-cluster-injection-token"; import { createClusterInjectionToken } from "../../../../common/cluster/create-cluster-injection-token"; import createContextHandlerInjectable from "../../../../main/context-handler/create-context-handler.injectable"; -import type { OpenDeleteClusterDialog } from "../open.injectable"; -import openDeleteClusterDialogInjectable from "../open.injectable"; import storesAndApisCanBeCreatedInjectable from "../../../stores-apis-can-be-created.injectable"; import createKubeconfigManagerInjectable from "../../../../main/kubeconfig-manager/create-kubeconfig-manager.injectable"; import type { ApplicationBuilder } from "../../test-utils/get-application-builder"; @@ -20,22 +17,8 @@ import { getApplicationBuilder } from "../../test-utils/get-application-builder" import normalizedPlatformInjectable from "../../../../common/vars/normalized-platform.injectable"; import kubectlBinaryNameInjectable from "../../../../main/kubectl/binary-name.injectable"; import kubectlDownloadingNormalizedArchInjectable from "../../../../main/kubectl/normalized-arch.injectable"; - -jest.mock("electron", () => ({ - app: { - getVersion: () => "99.99.99", - getName: () => "lens", - setName: jest.fn(), - setPath: jest.fn(), - getPath: () => "tmp", - getLocale: () => "en", - setLoginItemSettings: jest.fn(), - }, - ipcMain: { - on: jest.fn(), - handle: jest.fn(), - }, -})); +import type { OpenDeleteClusterDialog } from "../open.injectable"; +import openDeleteClusterDialogInjectable from "../open.injectable"; const currentClusterServerUrl = "https://localhost"; const nonCurrentClusterServerUrl = "http://localhost"; @@ -87,65 +70,50 @@ users: token: kubeconfig-user-q4lm4:xxxyyyy `; -let config: KubeConfig; - describe("", () => { - let applicationBuilder: ApplicationBuilder; - let createCluster: CreateCluster; - let openDeleteClusterDialog: OpenDeleteClusterDialog; + let builder: ApplicationBuilder; - beforeEach(async () => { - applicationBuilder = getApplicationBuilder(); + beforeEach(() => { + builder = getApplicationBuilder(); - applicationBuilder.beforeApplicationStart(({ mainDi, rendererDi }) => { + builder.beforeApplicationStart((mainDi) => { mainDi.override(createContextHandlerInjectable, () => () => undefined as never); mainDi.override(createKubeconfigManagerInjectable, () => () => undefined as never); mainDi.override(kubectlBinaryNameInjectable, () => "kubectl"); mainDi.override(kubectlDownloadingNormalizedArchInjectable, () => "amd64"); mainDi.override(normalizedPlatformInjectable, () => "darwin"); - rendererDi.override(storesAndApisCanBeCreatedInjectable, () => true); }); - mockFs(); - - applicationBuilder.beforeRender(({ rendererDi }) => { - openDeleteClusterDialog = rendererDi.inject(openDeleteClusterDialogInjectable); - createCluster = rendererDi.inject(createClusterInjectionToken); + builder.beforeWindowStart((windowDi) => { + windowDi.override(storesAndApisCanBeCreatedInjectable, () => true); }); }); - afterEach(() => { - mockFs.restore(); - }); - it("shows context switcher when deleting current cluster", async () => { - const mockOpts = { - "temp-kube-config": multiClusterConfig, - }; + const config = new KubeConfig(); - mockFs(mockOpts); - - config = new KubeConfig(); config.loadFromString(multiClusterConfig); - applicationBuilder.beforeRender(({ rendererDi }) => { - const createCluster = rendererDi.inject(createClusterInjectionToken); + const rendered = await builder.render(); - const cluster = createCluster({ - id: "some-current-context-cluster", - contextName: "some-current-context", - preferences: { - clusterName: "some-current-context-cluster", - }, - kubeConfigPath: "./temp-kube-config", - }, { - clusterServerUrl: currentClusterServerUrl, - }); + const windowDi = builder.applicationWindow.only.di; - openDeleteClusterDialog({ cluster, config }); + const createCluster = windowDi.inject(createClusterInjectionToken); + + const cluster = createCluster({ + id: "some-current-context-cluster", + contextName: "some-current-context", + preferences: { + clusterName: "some-current-context-cluster", + }, + kubeConfigPath: "./temp-kube-config", + }, { + clusterServerUrl: currentClusterServerUrl, }); - const rendered = await applicationBuilder.render(); + const openDeleteClusterDialog = windowDi.inject(openDeleteClusterDialogInjectable); + + openDeleteClusterDialog({ cluster, config }); const { getByText } = rendered; @@ -158,21 +126,23 @@ describe("", () => { expect(getByText("some-non-current-context")).toBeInTheDocument(); }); - describe("Kubeconfig with different clusters", () => { let rendered: RenderResult; + let openDeleteClusterDialog: OpenDeleteClusterDialog; + let createCluster: CreateCluster; + let config: KubeConfig; beforeEach(async () => { - const mockOpts = { - "temp-kube-config": multiClusterConfig, - }; - - mockFs(mockOpts); - config = new KubeConfig(); + config.loadFromString(multiClusterConfig); - rendered = await applicationBuilder.render(); + rendered = await builder.render(); + + const windowDi = builder.applicationWindow.only.di; + + openDeleteClusterDialog = windowDi.inject(openDeleteClusterDialogInjectable); + createCluster = windowDi.inject(createClusterInjectionToken); }); it("renders w/o errors", () => { @@ -268,18 +238,21 @@ describe("", () => { describe("Kubeconfig with single cluster", () => { let rendered: RenderResult; + let openDeleteClusterDialog: OpenDeleteClusterDialog; + let createCluster: CreateCluster; + let config: KubeConfig; beforeEach(async () => { - const mockOpts = { - "temp-kube-config": singleClusterConfig, - }; - - mockFs(mockOpts); - config = new KubeConfig(); + config.loadFromString(singleClusterConfig); - rendered = await applicationBuilder.render(); + rendered = await builder.render(); + + const windowDi = builder.applicationWindow.only.di; + + openDeleteClusterDialog = windowDi.inject(openDeleteClusterDialogInjectable); + createCluster = windowDi.inject(createClusterInjectionToken); }); it("shows warning if no other contexts left", () => { diff --git a/src/renderer/components/status-bar/status-bar.test.tsx b/src/renderer/components/status-bar/status-bar.test.tsx index 322b37dc85..8aaf40b9c4 100644 --- a/src/renderer/components/status-bar/status-bar.test.tsx +++ b/src/renderer/components/status-bar/status-bar.test.tsx @@ -7,55 +7,40 @@ import React from "react"; import "@testing-library/jest-dom/extend-expect"; import type { IObservableArray } from "mobx"; import { computed, observable } from "mobx"; -import type { DiContainer } from "@ogre-tools/injectable"; import type { StatusBarItems } from "./status-bar-items.injectable"; import statusBarItemsInjectable from "./status-bar-items.injectable"; -import { LensRendererExtension } from "../../../extensions/lens-renderer-extension"; import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; import type { ApplicationBuilder } from "../test-utils/get-application-builder"; import { getApplicationBuilder } from "../test-utils/get-application-builder"; import getRandomIdInjectable from "../../../common/utils/get-random-id.injectable"; -class SomeTestExtension extends LensRendererExtension { - constructor(statusBarItems: IObservableArray) { - super({ - id: "some-id", - absolutePath: "irrelevant", - isBundled: false, - isCompatible: false, - isEnabled: false, - manifest: { name: "some-id", version: "some-version", engines: { lens: "^5.5.0" }}, - manifestPath: "irrelevant", - }); - - this.statusBarItems = statusBarItems; - } -} - describe("", () => { - let di: DiContainer; let statusBarItems: IObservableArray; - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; beforeEach(async () => { statusBarItems = observable.array([]); - applicationBuilder = getApplicationBuilder(); + builder = getApplicationBuilder(); - applicationBuilder.beforeApplicationStart(({ rendererDi }) => { - rendererDi.unoverride(getRandomIdInjectable); - rendererDi.permitSideEffects(getRandomIdInjectable); + builder.beforeWindowStart((windowDi) => { + windowDi.unoverride(getRandomIdInjectable); + windowDi.permitSideEffects(getRandomIdInjectable); + windowDi.override(directoryForUserDataInjectable, () => "some-directory-for-user-data"); }); - applicationBuilder.extensions.renderer.enable(new SomeTestExtension(statusBarItems)); - - di = applicationBuilder.dis.rendererDi; + builder.extensions.enable({ + id: "some-id", + name: "some-name", - di.override(directoryForUserDataInjectable, () => "some-directory-for-user-data"); + rendererOptions: { + statusBarItems, + }, + }); }); it("renders w/o errors", async () => { - const { container } = await applicationBuilder.render(); + const { container } = await builder.render(); expect(container).toBeInstanceOf(HTMLElement); }); @@ -71,19 +56,21 @@ describe("", () => { ])("renders w/o errors when registrations are not type compliant (%p)", async val => { statusBarItems.replace([val]); - await expect(applicationBuilder.render()).resolves.toBeTruthy(); + await expect(builder.render()).resolves.toBeTruthy(); }); it("renders items [{item: React.ReactNode}] (4.0.0-rc.1)", async () => { const testId = "testId"; const text = "heee"; - di.override(statusBarItemsInjectable, () => computed(() => ({ - right: [ () => {text} ], - left: [], - }) as StatusBarItems)); + builder.beforeWindowStart((windowDi) => { + windowDi.override(statusBarItemsInjectable, () => computed(() => ({ + right: [ () => {text} ], + left: [], + }) as StatusBarItems)); + }); - const { getByTestId } = await applicationBuilder.render(); + const { getByTestId } = await builder.render(); expect(getByTestId(testId)).toHaveTextContent(text); }); @@ -96,7 +83,7 @@ describe("", () => { item: () => {text}, }]); - const { getByTestId } = await applicationBuilder.render(); + const { getByTestId } = await builder.render(); expect(getByTestId(testId)).toHaveTextContent(text); }); @@ -129,7 +116,7 @@ describe("", () => { }, ]); - const { getAllByTestId } = await applicationBuilder.render(); + const { getAllByTestId } = await builder.render(); const elems = getAllByTestId("sortedElem"); const positions = elems.map(elem => elem.textContent); diff --git a/src/renderer/components/test-utils/get-application-builder.tsx b/src/renderer/components/test-utils/get-application-builder.tsx index da07584816..55e3a4817d 100644 --- a/src/renderer/components/test-utils/get-application-builder.tsx +++ b/src/renderer/components/test-utils/get-application-builder.tsx @@ -5,27 +5,24 @@ import type { LensRendererExtension } from "../../../extensions/lens-renderer-extension"; import rendererExtensionsInjectable from "../../../extensions/renderer-extensions.injectable"; import currentlyInClusterFrameInjectable from "../../routes/currently-in-cluster-frame.injectable"; -import type { ObservableSet } from "mobx"; +import type { IComputedValue, ObservableMap } from "mobx"; import { computed, observable, runInAction } from "mobx"; import React from "react"; import { Router } from "react-router"; -import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.injectable"; import allowedResourcesInjectable from "../../cluster-frame-context/allowed-resources.injectable"; import type { RenderResult } from "@testing-library/react"; -import { queryByText, fireEvent } from "@testing-library/react"; +import { fireEvent, queryByText } from "@testing-library/react"; import type { KubeResource } from "../../../common/rbac"; -import type { DiContainer } from "@ogre-tools/injectable"; -import clusterStoreInjectable from "../../../common/cluster-store/cluster-store.injectable"; -import type { ClusterStore } from "../../../common/cluster-store/cluster-store"; +import type { DiContainer, Injectable } from "@ogre-tools/injectable"; +import { getInjectable } from "@ogre-tools/injectable"; import mainExtensionsInjectable from "../../../extensions/main-extensions.injectable"; import { pipeline } from "@ogre-tools/fp"; -import { flatMap, compact, join, get, filter, map, matches, last } from "lodash/fp"; +import { compact, filter, first, flatMap, get, join, last, map, matches } from "lodash/fp"; import preferenceNavigationItemsInjectable from "../+preferences/preferences-navigation/preference-navigation-items.injectable"; import navigateToPreferencesInjectable from "../../../common/front-end-routing/routes/preferences/navigate-to-preferences.injectable"; import type { MenuItemOpts } from "../../../main/menu/application-menu-items.injectable"; import applicationMenuItemsInjectable from "../../../main/menu/application-menu-items.injectable"; -import type { MenuItemConstructorOptions, MenuItem } from "electron"; -import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable"; +import type { MenuItem, MenuItemConstructorOptions } from "electron"; import type { NavigateToHelmCharts } from "../../../common/front-end-routing/routes/cluster/helm/charts/navigate-to-helm-charts.injectable"; import navigateToHelmChartsInjectable from "../../../common/front-end-routing/routes/cluster/helm/charts/navigate-to-helm-charts.injectable"; import hostedClusterInjectable from "../../cluster-frame-context/hosted-cluster.injectable"; @@ -39,7 +36,6 @@ import type { NamespaceStore } from "../+namespaces/store"; import historyInjectable from "../../navigation/history.injectable"; import type { MinimalTrayMenuItem } from "../../../main/tray/electron-tray/electron-tray.injectable"; 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 { getDiForUnitTesting as getRendererDi } from "../../getDiForUnitTesting"; import { getDiForUnitTesting as getMainDi } from "../../../main/getDiForUnitTesting"; import { overrideChannels } from "../../../test-utils/channel-fakes/override-channels"; @@ -52,7 +48,6 @@ import type { NavigateToRouteOptions } from "../../../common/front-end-routing/n import { navigateToRouteInjectionToken } from "../../../common/front-end-routing/navigate-to-route-injection-token"; import type { LensMainExtension } from "../../../extensions/lens-main-extension"; import type { LensExtension } from "../../../extensions/lens-extension"; - import extensionInjectable from "../../../extensions/extension-loader/extension/extension.injectable"; import { renderFor } from "./renderFor"; import { RootFrame } from "../../frames/root-frame/root-frame"; @@ -62,34 +57,50 @@ import activeKubernetesClusterInjectable from "../../cluster-frame-context/activ import { catalogEntityFromCluster } from "../../../main/cluster-manager"; import namespaceStoreInjectable from "../+namespaces/store.injectable"; import { isAllowedResource } from "../../../common/cluster/is-allowed-resource"; +import createApplicationWindowInjectable from "../../../main/start-main-application/lens-window/application-window/create-application-window.injectable"; +import type { CreateElectronWindow } from "../../../main/start-main-application/lens-window/application-window/create-electron-window.injectable"; +import createElectronWindowInjectable from "../../../main/start-main-application/lens-window/application-window/create-electron-window.injectable"; +import { applicationWindowInjectionToken } from "../../../main/start-main-application/lens-window/application-window/application-window-injection-token"; +import sendToChannelInElectronBrowserWindowInjectable from "../../../main/start-main-application/lens-window/application-window/send-to-channel-in-electron-browser-window.injectable"; +import closeAllWindowsInjectable from "../../../main/start-main-application/lens-window/hide-all-windows/close-all-windows.injectable"; +import type { LensWindow } from "../../../main/start-main-application/lens-window/application-window/create-lens-window.injectable"; +import type { FakeExtensionOptions } from "./get-extension-fake"; +import { getExtensionFakeForMain, getExtensionFakeForRenderer } from "./get-extension-fake"; -type Callback = (dis: DiContainers) => void | Promise; +type Callback = (di: DiContainer) => void | Promise; -type EnableExtensions = (...extensions: T[]) => void; -type DisableExtensions = (...extensions: T[]) => void; +type LensWindowWithHelpers = LensWindow & { rendered: RenderResult; di: DiContainer }; export interface ApplicationBuilder { - dis: DiContainers; + mainDi: DiContainer; setEnvironmentToClusterFrame: () => ApplicationBuilder; extensions: { - renderer: { - enable: EnableExtensions; - disable: DisableExtensions; - }; + enable: (...extensions: FakeExtensionOptions[]) => void; + disable: (...extensions: FakeExtensionOptions[]) => void; - main: { - enable: EnableExtensions; - disable: DisableExtensions; - }; + get: (id: string) => { + main: LensMainExtension; - enable: (...extensions: { renderer: LensRendererExtension; main: LensMainExtension }[]) => void; - disable: (...extensions: { renderer: LensRendererExtension; main: LensMainExtension }[]) => void; + applicationWindows: Record & { + only: LensRendererExtension; + }; + }; + }; + + applicationWindow: { + closeAll: () => void; + only: LensWindowWithHelpers; + get: (id: string) => LensWindowWithHelpers; + getAll: () => LensWindowWithHelpers[]; + create: (id: string) => LensWindowWithHelpers; }; allowKubeResource: (resourceName: KubeResource) => ApplicationBuilder; beforeApplicationStart: (callback: Callback) => ApplicationBuilder; - beforeRender: (callback: Callback) => ApplicationBuilder; + beforeWindowStart: (callback: Callback) => ApplicationBuilder; + + startHidden: () => Promise; render: () => Promise; tray: { @@ -116,17 +127,12 @@ export interface ApplicationBuilder { }; select: { - openMenu: (id: string) => ({ selectOption: (labelText: string) => void }); + openMenu: (id: string) => { selectOption: (labelText: string) => void }; selectOption: (menuId: string, labelText: string) => void; getValue: (menuId: string) => string; }; } -interface DiContainers { - rendererDi: DiContainer; - mainDi: DiContainer; -} - interface Environment { RootComponent: React.ElementType; onAllowKubeResource: () => void; @@ -137,64 +143,22 @@ export const getApplicationBuilder = () => { doGeneralOverrides: true, }); + mainDi.register(mainExtensionsStateInjectable); + const overrideChannelsForWindow = overrideChannels(mainDi); - const rendererDi = getRendererDi({ - doGeneralOverrides: true, - }); - - overrideChannelsForWindow(rendererDi); - - const dis = { rendererDi, mainDi }; - - const clusterStoreStub = { - provideInitialFromMain: () => {}, - getById: (): null => null, - } as unknown as ClusterStore; - - rendererDi.override(clusterStoreInjectable, () => clusterStoreStub); - rendererDi.override(storesAndApisCanBeCreatedInjectable, () => true); - mainDi.override(clusterStoreInjectable, () => clusterStoreStub); - const beforeApplicationStartCallbacks: Callback[] = []; - const beforeRenderCallbacks: Callback[] = []; - - const rendererExtensionsState = observable.set(); - const mainExtensionsState = observable.set(); - - rendererDi.override(subscribeStoresInjectable, () => () => () => {}); - - const environments = { - application: { - RootComponent: RootFrame, - - onAllowKubeResource: () => { - throw new Error( - "Tried to allow kube resource when environment is not cluster frame.", - ); - }, - } as Environment, - - clusterFrame: { - RootComponent: ClusterFrame, - onAllowKubeResource: () => {}, - } as Environment, - }; + const beforeWindowStartCallbacks: Callback[] = []; let environment = environments.application; - rendererDi.override( - currentlyInClusterFrameInjectable, - () => environment === environments.clusterFrame, - ); + mainDi.override(mainExtensionsInjectable, (di) => { + const mainExtensionsState = di.inject(mainExtensionsStateInjectable); - rendererDi.override(rendererExtensionsInjectable, () => - computed(() => [...rendererExtensionsState]), - ); - - mainDi.override(mainExtensionsInjectable, () => - computed(() => [...mainExtensionsState]), - ); + return computed(() => + [...mainExtensionsState.values()], + ); + }); let trayMenuIconPath: string; @@ -209,60 +173,135 @@ export const getApplicationBuilder = () => { }, })); - let allowedResourcesState: KubeResource[]; - let rendered: RenderResult; + const allowedResourcesState = observable.array(); - const enableExtensionsFor = ( - extensionState: T, - di: DiContainer, - ) => { - const getExtension = (extension: LensExtension) => - di.inject(extensionInjectable, extension); + const windowHelpers = new Map RenderResult }>(); - return (...extensionInstances: LensExtension[]) => { - const addAndEnableExtensions = () => { - extensionInstances.forEach(instance => { - const extension = getExtension(instance); + const createElectronWindowFake: CreateElectronWindow = (configuration) => { + const windowId = configuration.id; - extension.register(); - }); + const windowDi = getRendererDi({ doGeneralOverrides: true }); - runInAction(() => { - extensionInstances.forEach((extension) => { - extensionState.add(extension); - }); - }); - }; + overrideChannelsForWindow(windowDi, windowId); - if (rendered) { - addAndEnableExtensions(); - } else { - builder.beforeRender(addAndEnableExtensions); - } + windowDi.register(rendererExtensionsStateInjectable); + + windowDi.override( + currentlyInClusterFrameInjectable, + () => environment === environments.clusterFrame, + ); + + windowDi.override(rendererExtensionsInjectable, (di) => { + const rendererExtensionState = di.inject(rendererExtensionsStateInjectable); + + return computed(() => [...rendererExtensionState.values()]); + }); + + let rendered: RenderResult; + + windowHelpers.set(windowId, { di: windowDi, getRendered: () => rendered }); + + return { + show: () => {}, + close: () => {}, + loadFile: async () => {}, + loadUrl: async () => { + for (const callback of beforeWindowStartCallbacks) { + await callback(windowDi); + } + + const startFrame = windowDi.inject(startFrameInjectable); + + await startFrame(); + + const history = windowDi.inject(historyInjectable); + + const render = renderFor(windowDi); + + rendered = render( + + + , + ); + }, + + send: (arg) => { + const sendFake = mainDi.inject(sendToChannelInElectronBrowserWindowInjectable) as any; + + sendFake(windowId, null, arg); + }, + + reload: () => { + throw new Error("Tried to reload application window which is not implemented yet."); + }, }; }; - const enableRendererExtension = enableExtensionsFor(rendererExtensionsState, rendererDi); - const enableMainExtension = enableExtensionsFor(mainExtensionsState, mainDi); - const disableRendererExtension = disableExtensionsFor(rendererExtensionsState, rendererDi); - const disableMainExtension = disableExtensionsFor(mainExtensionsState, mainDi); + mainDi.override(createElectronWindowInjectable, () => createElectronWindowFake); - const selectOptionFor = (menuId: string) => (labelText: string) => { - const menuOptions = rendered.baseElement.querySelector( - `.${menuId}-options`, - ); - - assert(menuOptions, `Could not find select options for menu with ID "${menuId}"`); - - const option = queryByText(menuOptions, labelText); - - assert(option, `Could not find select option with label "${labelText}" for menu with ID "${menuId}"`); - - userEvent.click(option); - }; + let applicationHasStarted = false; const builder: ApplicationBuilder = { - dis, + mainDi, + + applicationWindow: { + closeAll: () => { + const closeAll = mainDi.inject(closeAllWindowsInjectable); + + closeAll(); + + document.documentElement.innerHTML = ""; + }, + + get only() { + const applicationWindows = builder.applicationWindow.getAll(); + + if (applicationWindows.length > 1) { + throw new Error( + "Tried to get only application window when there are multiple windows.", + ); + } + + const applicationWindow = first(applicationWindows); + + if (!applicationWindow) { + throw new Error( + "Tried to get only application window when there are no windows.", + ); + } + + return applicationWindow; + }, + + getAll: () => + mainDi + .injectMany(applicationWindowInjectionToken) + .map(toWindowWithHelpersFor(windowHelpers)), + + get: (id) => { + const applicationWindows = builder.applicationWindow.getAll(); + + const applicationWindow = applicationWindows.find( + (window) => window.id === id, + ); + + if (!applicationWindow) { + throw new Error(`Tried to get application window with ID "${id}" but it was not found.`); + } + + return applicationWindow; + }, + + create: (id) => { + const createApplicationWindow = mainDi.inject( + createApplicationWindowInjectable, + ); + + createApplicationWindow(id); + + return builder.applicationWindow.get(id); + }, + }, applicationMenu: { click: (path: string) => { @@ -340,29 +379,39 @@ export const getApplicationBuilder = () => { preferences: { close: () => { + const rendered = builder.applicationWindow.only.rendered; + const link = rendered.getByTestId("close-preferences"); fireEvent.click(link); }, navigate: () => { - const navigateToPreferences = rendererDi.inject(navigateToPreferencesInjectable); + const windowDi = builder.applicationWindow.only.di; + + const navigateToPreferences = windowDi.inject( + navigateToPreferencesInjectable, + ); navigateToPreferences(); }, navigateTo: (route: Route, params: Partial>) => { - const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken); + const windowDi = builder.applicationWindow.only.di; + + const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken); navigateToRoute(route, params); }, navigation: { click: (id: string) => { + const { di: windowDi, rendered } = builder.applicationWindow.only; + const link = rendered.queryByTestId(`tab-link-for-${id}`); if (!link) { - const preferencesNavigationItems = rendererDi.inject( + const preferencesNavigationItems = windowDi.inject( preferenceNavigationItemsInjectable, ); @@ -382,7 +431,11 @@ export const getApplicationBuilder = () => { helmCharts: { navigate: (parameters) => { - const navigateToHelmCharts = rendererDi.inject(navigateToHelmChartsInjectable); + const windowDi = builder.applicationWindow.only.di; + + const navigateToHelmCharts = windowDi.inject( + navigateToHelmChartsInjectable, + ); navigateToHelmCharts(parameters); }, @@ -391,81 +444,129 @@ export const getApplicationBuilder = () => { setEnvironmentToClusterFrame: () => { environment = environments.clusterFrame; - allowedResourcesState = observable.array(); + builder.beforeWindowStart((windowDi) => { + windowDi.override(allowedResourcesInjectable, () => + computed(() => new Set([...allowedResourcesState])), + ); - rendererDi.override(allowedResourcesInjectable, () => - computed(() => new Set([...allowedResourcesState])), - ); + const clusterStub = { + accessibleNamespaces: [], + isAllowedResource: isAllowedResource(allowedResourcesState), + } as unknown as Cluster; - const clusterStub = { - accessibleNamespaces: [], - isAllowedResource: isAllowedResource(allowedResourcesState), - } as unknown as Cluster; + windowDi.override(activeKubernetesClusterInjectable, () => + computed(() => catalogEntityFromCluster(clusterStub)), + ); - rendererDi.override(activeKubernetesClusterInjectable, () => - computed(() => catalogEntityFromCluster(clusterStub)), - ); + // TODO: Figure out a way to remove this stub. + const namespaceStoreStub = { + isLoaded: true, + contextNamespaces: [], + contextItems: [], + api: { + kind: "Namespace", + }, + items: [], + selectNamespaces: () => {}, + getByPath: () => undefined, + pickOnlySelected: () => [], + isSelectedAll: () => false, + getTotalCount: () => 0, + } as unknown as NamespaceStore; - // TODO: Figure out a way to remove this stub. - const namespaceStoreStub = { - isLoaded: true, - contextNamespaces: [], - contextItems: [], - api: { - kind: "Namespace", - }, - items: [], - selectNamespaces: () => {}, - getByPath: () => undefined, - pickOnlySelected: () => [], - isSelectedAll: () => false, - getTotalCount: () => 0, - } as unknown as NamespaceStore; + const clusterFrameContextFake = new ClusterFrameContext( + clusterStub, - const clusterFrameContextFake = new ClusterFrameContext( - clusterStub, + { + namespaceStore: namespaceStoreStub, + }, + ); - { - namespaceStore: namespaceStoreStub, - }, - ); + windowDi.override(namespaceStoreInjectable, () => namespaceStoreStub); + windowDi.override(hostedClusterInjectable, () => clusterStub); + windowDi.override(hostedClusterIdInjectable, () => "irrelevant-hosted-cluster-id"); + windowDi.override(clusterFrameContextInjectable, () => clusterFrameContextFake); - rendererDi.override(namespaceStoreInjectable, () => namespaceStoreStub); - rendererDi.override(hostedClusterInjectable, () => clusterStub); - rendererDi.override(hostedClusterIdInjectable, () => "irrelevant-hosted-cluster-id"); - rendererDi.override(clusterFrameContextInjectable, () => clusterFrameContextFake); - - // Todo: get rid of global state. - KubeObjectStore.defaultContext.set(clusterFrameContextFake); + // Todo: get rid of global state. + KubeObjectStore.defaultContext.set(clusterFrameContextFake); + }); return builder; }, extensions: { - renderer: { - enable: enableRendererExtension, - disable: disableRendererExtension, - }, + get: (id: string) => { + const windowInstances = pipeline( + builder.applicationWindow.getAll(), - main: { - enable: enableMainExtension, - disable: disableMainExtension, + map((window): [string, LensRendererExtension] => [ + window.id, + findExtensionInstance(window.di, rendererExtensionsInjectable, id), + ]), + + items => Object.fromEntries(items), + ); + + return { + main: findExtensionInstance(mainDi, mainExtensionsInjectable, id), + + applicationWindows: { + get only() { + return findExtensionInstance( + builder.applicationWindow.only.di, + rendererExtensionsInjectable, + id, + ); + }, + + ...windowInstances, + }, + }; }, enable: (...extensions) => { - const rendererExtensions = extensions.map(extension => extension.renderer); - const mainExtensions = extensions.map(extension => extension.main); + builder.beforeWindowStart((windowDi) => { + const rendererExtensionInstances = extensions.map((options) => + getExtensionFakeForRenderer( + windowDi, + options.id, + options.name, + options.rendererOptions || {}, + ), + ); - enableRendererExtension(...rendererExtensions); - enableMainExtension(...mainExtensions); + rendererExtensionInstances.forEach( + enableExtensionFor(windowDi, rendererExtensionsStateInjectable), + ); + }); + + builder.beforeApplicationStart((mainDi) => { + const mainExtensionInstances = extensions.map((extension) => + getExtensionFakeForMain(mainDi, extension.id, extension.name, extension.mainOptions || {}), + ); + + mainExtensionInstances.forEach( + enableExtensionFor(mainDi, mainExtensionsStateInjectable), + ); + }); }, disable: (...extensions) => { - const rendererExtensions = extensions.map(extension => extension.renderer); - const mainExtensions = extensions.map(extension => extension.main); + builder.beforeWindowStart(windowDi => { + extensions + .map((ext) => ext.id) + .forEach( + disableExtensionFor(windowDi, rendererExtensionsStateInjectable), + ); + }); - disableRendererExtension(...rendererExtensions); - disableMainExtension(...mainExtensions); + builder.beforeApplicationStart(mainDi => { + extensions + .map((ext) => ext.id) + .forEach( + disableExtensionFor(mainDi, mainExtensionsStateInjectable), + ); + }); }, }, @@ -479,56 +580,72 @@ export const getApplicationBuilder = () => { return builder; }, - beforeApplicationStart(callback: (dis: DiContainers) => void) { + beforeApplicationStart(callback) { + if (applicationHasStarted) { + callback(mainDi); + } + beforeApplicationStartCallbacks.push(callback); return builder; }, - beforeRender(callback: (dis: DiContainers) => void) { - beforeRenderCallbacks.push(callback); + beforeWindowStart(callback) { + const alreadyRenderedWindows = builder.applicationWindow.getAll(); + + alreadyRenderedWindows.forEach((window) => { + callback(window.di); + }); + + beforeWindowStartCallbacks.push(callback); return builder; }, + startHidden: async () => { + mainDi.inject(lensProxyPortInjectable).set(42); + + for (const callback of beforeApplicationStartCallbacks) { + await callback(mainDi); + } + + const startMainApplication = mainDi.inject( + startMainApplicationInjectable, + ); + + await startMainApplication(false); + + applicationHasStarted = true; + }, + async render() { mainDi.inject(lensProxyPortInjectable).set(42); for (const callback of beforeApplicationStartCallbacks) { - await callback(dis); + await callback(mainDi); } - const startMainApplication = mainDi.inject(startMainApplicationInjectable); - - await startMainApplication(); - - const applicationWindow = mainDi.inject(applicationWindowInjectable); - - await applicationWindow.start(); - - const startFrame = rendererDi.inject(startFrameInjectable); - - await startFrame(); - - for (const callback of beforeRenderCallbacks) { - await callback(dis); - } - - const history = rendererDi.inject(historyInjectable); - - const render = renderFor(rendererDi); - - rendered = render( - - - , + const startMainApplication = mainDi.inject( + startMainApplicationInjectable, ); - return rendered; + await startMainApplication(true); + + applicationHasStarted = true; + + const applicationWindow = builder.applicationWindow.get( + "first-application-window", + ); + + assert(applicationWindow); + + return applicationWindow.rendered; }, select: { openMenu: (menuId) => { + const rendered = builder.applicationWindow.only.rendered; + const select = rendered.baseElement.querySelector( `#${menuId}`, ); @@ -538,13 +655,15 @@ export const getApplicationBuilder = () => { openMenu(select); return { - selectOption: selectOptionFor(menuId), + selectOption: selectOptionFor(builder, menuId), }; }, - selectOption: (menuId, labelText) => selectOptionFor(menuId)(labelText), + selectOption: (menuId, labelText) => selectOptionFor(builder, menuId)(labelText), getValue: (menuId) => { + const rendered = builder.applicationWindow.only.rendered; + const select = rendered.baseElement.querySelector( `#${menuId}`, ); @@ -582,22 +701,134 @@ function toFlatChildren(parentId: string | null | undefined): ToFlatChildren { ]; } -const disableExtensionsFor = ( - extensionState: T, +export const rendererExtensionsStateInjectable = getInjectable({ + id: "renderer-extensions-state", + instantiate: () => observable.map(), +}); + +const mainExtensionsStateInjectable = getInjectable({ + id: "main-extensions-state", + instantiate: () => observable.map(), +}); + +const findExtensionInstance = (di: DiContainer, injectable: Injectable, any, any>, id: string) => { + const instance = di.inject(injectable).get().find(ext => ext.id === id); + + if (!instance) { + throw new Error(`Tried to get extension with ID ${id}, but it didn't exist`); + } + + return instance; +}; + +type ApplicationWindowHelpers = Map RenderResult }>; + +const toWindowWithHelpersFor = + (windowHelpers: ApplicationWindowHelpers) => (applicationWindow: LensWindow) => ({ + ...applicationWindow, + + get rendered() { + const helpers = windowHelpers.get(applicationWindow.id); + + if (!helpers) { + throw new Error( + `Tried to get rendered for application window "${applicationWindow.id}" before it was started.`, + ); + } + + return helpers.getRendered(); + }, + + get di() { + const helpers = windowHelpers.get(applicationWindow.id); + + if (!helpers) { + throw new Error( + `Tried to get di for application window "${applicationWindow.id}" before it was started.`, + ); + } + + return helpers.di; + }, + }); + +const environments = { + application: { + RootComponent: RootFrame, + + onAllowKubeResource: () => { + throw new Error( + "Tried to allow kube resource when environment is not cluster frame.", + ); + }, + } as Environment, + + clusterFrame: { + RootComponent: ClusterFrame, + onAllowKubeResource: () => {}, + } as Environment, +}; + +const selectOptionFor = (builder: ApplicationBuilder, menuId: string) => (labelText: string) => { + const rendered = builder.applicationWindow.only.rendered; + + const menuOptions = rendered.baseElement.querySelector( + `.${menuId}-options`, + ); + + assert(menuOptions, `Could not find select options for menu with ID "${menuId}"`); + + const option = queryByText(menuOptions, labelText); + + assert(option, `Could not find select option with label "${labelText}" for menu with ID "${menuId}"`); + + userEvent.click(option); +}; + +const enableExtensionFor = ( di: DiContainer, + stateInjectable: Injectable, any, any>, ) => { - const getExtension = (instance: LensExtension) => - di.inject(extensionInjectable, instance); + const extensionState = di.inject(stateInjectable); - return (...extensionInstances: LensExtension[]) => { - extensionInstances.forEach((instance) => { - const extension = getExtension(instance); + const getExtension = (extension: LensExtension) => + di.inject(extensionInjectable, extension); - runInAction(() => { - extension.deregister(); + return (extensionInstance: LensExtension) => { + const extension = getExtension(extensionInstance); - extensionState.delete(instance); - }); + runInAction(() => { + extension.register(); + extensionState.set(extensionInstance.id, extensionInstance); }); }; }; + +const disableExtensionFor = + ( + di: DiContainer, + stateInjectable: Injectable, unknown, void>, + ) => + (id: string) => { + const getExtension = (extension: LensExtension) => + di.inject(extensionInjectable, extension); + + const extensionsState = di.inject(stateInjectable); + + const instance = extensionsState.get(id); + + if (!instance) { + throw new Error( + `Tried to disable extension with ID "${id}", but it wasn't enabled`, + ); + } + + const injectable = getExtension(instance); + + runInAction(() => { + injectable.deregister(); + + extensionsState.delete(id); + }); + }; + diff --git a/src/renderer/components/test-utils/get-extension-fake.ts b/src/renderer/components/test-utils/get-extension-fake.ts index 6237f2a83f..6dd8dcacab 100644 --- a/src/renderer/components/test-utils/get-extension-fake.ts +++ b/src/renderer/components/test-utils/get-extension-fake.ts @@ -5,7 +5,6 @@ import type { Mutable } from "type-fest"; import fileSystemProvisionerStoreInjectable from "../../../extensions/extension-loader/file-system-provisioner-store/file-system-provisioner-store.injectable"; import { lensExtensionDependencies } from "../../../extensions/lens-extension"; -import type { ApplicationBuilder } from "./get-application-builder"; import { LensMainExtension } from "../../../extensions/lens-main-extension"; import navigateForExtensionInjectable from "../../../main/start-main-application/lens-window/navigate-for-extension.injectable"; import { LensRendererExtension } from "../../../extensions/lens-renderer-extension"; @@ -27,21 +26,7 @@ export interface FakeExtensionOptions { mainOptions?: Partial; } -export type GetExtensionFake = (arg: FakeExtensionOptions) => { - main: TestExtensionMain; - renderer: TestExtensionRenderer; -}; - -export const getExtensionFakeFor = - (builder: ApplicationBuilder): GetExtensionFake => - ({ id, name, mainOptions = {}, rendererOptions = {}}) => { - const mainInstance = getExtensionFakeForMain(builder.dis.mainDi, id, name, mainOptions); - const rendererInstance = getExtensionFakeForRenderer(builder.dis.rendererDi, id, name, rendererOptions); - - return { main: mainInstance, renderer: rendererInstance }; - }; - -const getExtensionFakeForMain = (di: DiContainer, id: string, name: string, options: Partial) => { +export const getExtensionFakeForMain = (di: DiContainer, id: string, name: string, options: Partial) => { const instance = new TestExtensionMain({ id, absolutePath: "irrelevant", @@ -71,7 +56,7 @@ const getExtensionFakeForMain = (di: DiContainer, id: string, name: string, opti return instance; }; -const getExtensionFakeForRenderer = (di: DiContainer, id: string, name: string, options: Partial) => { +export const getExtensionFakeForRenderer = (di: DiContainer, id: string, name: string, options: Partial) => { const instance = new TestExtensionRenderer({ id, absolutePath: "irrelevant", diff --git a/src/renderer/components/test-utils/get-renderer-extension-fake.ts b/src/renderer/components/test-utils/get-renderer-extension-fake.ts deleted file mode 100644 index 685d2c3c8a..0000000000 --- a/src/renderer/components/test-utils/get-renderer-extension-fake.ts +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import type { SetRequired } from "type-fest"; -import { LensRendererExtension } from "../../../extensions/lens-renderer-extension"; -import type { ApplicationBuilder } from "./get-application-builder"; -import { getExtensionFakeFor } from "./get-extension-fake"; - -export class TestExtension extends LensRendererExtension {} - -export type FakeExtensionData = SetRequired, "id" | "name">; - -export type GetRendererExtensionFake = (fakeExtensionData: FakeExtensionData) => TestExtension; - -export const getRendererExtensionFakeFor = ( - builder: ApplicationBuilder, -): GetRendererExtensionFake => { - const getExtensionFake = getExtensionFakeFor(builder); - - return ({ id, name, ...rest }) => - getExtensionFake({ - id, - name, - rendererOptions: rest, - }).renderer; -}; - diff --git a/src/renderer/getDiForUnitTesting.tsx b/src/renderer/getDiForUnitTesting.tsx index 4b8a69c090..c291356edc 100644 --- a/src/renderer/getDiForUnitTesting.tsx +++ b/src/renderer/getDiForUnitTesting.tsx @@ -19,9 +19,6 @@ import extensionsStoreInjectable from "../extensions/extensions-store/extensions import type { ExtensionsStore } from "../extensions/extensions-store/extensions-store"; import fileSystemProvisionerStoreInjectable from "../extensions/extension-loader/file-system-provisioner-store/file-system-provisioner-store.injectable"; import type { FileSystemProvisionerStore } from "../extensions/extension-loader/file-system-provisioner-store/file-system-provisioner-store"; -import clusterStoreInjectable from "../common/cluster-store/cluster-store.injectable"; -import type { ClusterStore } from "../common/cluster-store/cluster-store"; -import type { Cluster } from "../common/cluster/cluster"; import userStoreInjectable from "../common/user-store/user-store.injectable"; import type { UserStore } from "../common/user-store"; import getAbsolutePathInjectable from "../common/path/get-absolute-path.injectable"; @@ -42,7 +39,6 @@ import setupOnApiErrorListenersInjectable from "./api/setup-on-api-errors.inject import { observable, computed } from "mobx"; import defaultShellInjectable from "./components/+preferences/default-shell.injectable"; import appVersionInjectable from "../common/vars/app-version.injectable"; -import provideInitialValuesForSyncBoxesInjectable from "./utils/sync-box/provide-initial-values-for-sync-boxes.injectable"; import requestAnimationFrameInjectable from "./components/animate/request-animation-frame.injectable"; import getRandomIdInjectable from "../common/utils/get-random-id.injectable"; import getFilePathsInjectable from "./components/+preferences/kubernetes/helm-charts/adding-of-custom-helm-repository/helm-file-input/get-file-paths.injectable"; @@ -191,12 +187,8 @@ export const getDiForUnitTesting = (opts: { doGeneralOverrides?: boolean } = {}) di.override(fileSystemProvisionerStoreInjectable, () => ({}) as FileSystemProvisionerStore); - // eslint-disable-next-line unused-imports/no-unused-vars-ts - di.override(clusterStoreInjectable, () => ({ getById: (id): Cluster => ({}) as Cluster }) as ClusterStore); - di.override(setupSystemCaInjectable, () => ({ run: () => {} })); di.override(setupOnApiErrorListenersInjectable, () => ({ run: () => {} })); - di.override(provideInitialValuesForSyncBoxesInjectable, () => ({ run: () => {} })); di.override(defaultShellInjectable, () => "some-default-shell"); diff --git a/src/renderer/kube-watch-api/subscribe-stores.global-override-for-injectable.ts b/src/renderer/kube-watch-api/subscribe-stores.global-override-for-injectable.ts new file mode 100644 index 0000000000..711e9caa17 --- /dev/null +++ b/src/renderer/kube-watch-api/subscribe-stores.global-override-for-injectable.ts @@ -0,0 +1,11 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getGlobalOverride } from "../../common/test-utils/get-global-override"; +import subscribeStoresInjectable from "./subscribe-stores.injectable"; + +export default getGlobalOverride( + subscribeStoresInjectable, + () => () => () => {}, +); diff --git a/src/test-utils/channel-fakes/override-channels.ts b/src/test-utils/channel-fakes/override-channels.ts index 4d7a337e04..7d3a20cd75 100644 --- a/src/test-utils/channel-fakes/override-channels.ts +++ b/src/test-utils/channel-fakes/override-channels.ts @@ -12,8 +12,8 @@ export const overrideChannels = (mainDi: DiContainer) => { const overrideMessagingFromWindowToForWindow = overrideMessagingFromWindowToMain(mainDi); const overrideRequestingFromWindowToMainForWindow = overrideRequestingFromWindowToMain(mainDi); - return (windowDi: DiContainer) => { - overrideMessagingFromMainToWindowForWindow(windowDi); + return (windowDi: DiContainer, windowId: string) => { + overrideMessagingFromMainToWindowForWindow(windowDi, windowId); overrideMessagingFromWindowToForWindow(windowDi); overrideRequestingFromWindowToMainForWindow(windowDi); }; diff --git a/src/test-utils/channel-fakes/override-messaging-from-main-to-window.ts b/src/test-utils/channel-fakes/override-messaging-from-main-to-window.ts index 6ade9b7f0d..852b2cfb0b 100644 --- a/src/test-utils/channel-fakes/override-messaging-from-main-to-window.ts +++ b/src/test-utils/channel-fakes/override-messaging-from-main-to-window.ts @@ -3,30 +3,44 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import type { MessageChannelListener } from "../../common/utils/channel/message-channel-listener-injection-token"; -import type { MessageChannel } from "../../common/utils/channel/message-channel-injection-token"; import sendToChannelInElectronBrowserWindowInjectable from "../../main/start-main-application/lens-window/application-window/send-to-channel-in-electron-browser-window.injectable"; -import type { SendToViewArgs } from "../../main/start-main-application/lens-window/application-window/lens-window-injection-token"; +import type { SendToViewArgs } from "../../main/start-main-application/lens-window/application-window/create-lens-window.injectable"; import enlistMessageChannelListenerInjectableInRenderer from "../../renderer/utils/channel/channel-listeners/enlist-message-channel-listener.injectable"; import type { DiContainer } from "@ogre-tools/injectable"; -import assert from "assert"; import { tentativeParseJson } from "../../common/utils/tentative-parse-json"; +import { getOrInsert } from "../../common/utils"; + +type ListenerSet = Set>; +type WindowListenerMap = Map; +type ListenerFakeMap = Map; export const overrideMessagingFromMainToWindow = (mainDi: DiContainer) => { - const messageChannelListenerFakesForRenderer = new Map< - string, - Set>> - >(); + const messageChannelListenerFakesForRenderer: ListenerFakeMap = new Map(); + + const getWindowListeners = (channelId: string, windowId: string) => { + const channelListeners = getOrInsert( + messageChannelListenerFakesForRenderer, + channelId, + new Map(), + ); + + return getOrInsert( + channelListeners, + windowId, + new Set(), + ); + }; mainDi.override( sendToChannelInElectronBrowserWindowInjectable, () => ( + windowId: string, browserWindow, { channel: channelId, frameInfo, data = [] }: SendToViewArgs, ) => { - const listeners = - messageChannelListenerFakesForRenderer.get(channelId) || new Set(); + const windowListeners = getWindowListeners(channelId, windowId); if (frameInfo) { throw new Error( @@ -40,7 +54,7 @@ export const overrideMessagingFromMainToWindow = (mainDi: DiContainer) => { ); } - if (listeners.size === 0) { + if (windowListeners.size === 0) { throw new Error( `Tried to send message to channel "${channelId}" but there where no listeners. Current channels with listeners: "${[ ...messageChannelListenerFakesForRenderer.keys(), @@ -50,40 +64,26 @@ export const overrideMessagingFromMainToWindow = (mainDi: DiContainer) => { const message = tentativeParseJson(data[0]); - listeners.forEach((listener) => listener.handler(message)); + windowListeners.forEach((listener) => + listener.handler(message), + ); }, ); - return (windowDi: DiContainer) => { + return (windowDi: DiContainer, windowId: string) => { windowDi.override( enlistMessageChannelListenerInjectableInRenderer, () => (listener) => { - if (!messageChannelListenerFakesForRenderer.has(listener.channel.id)) { - messageChannelListenerFakesForRenderer.set( - listener.channel.id, - new Set(), - ); - } - - const listeners = messageChannelListenerFakesForRenderer.get( + const windowListeners = getWindowListeners( listener.channel.id, + windowId, ); - assert(listeners); - - // TODO: Figure out typing - listeners.add( - listener as unknown as MessageChannelListener>, - ); + windowListeners.add(listener); return () => { - // TODO: Figure out typing - listeners.delete( - listener as unknown as MessageChannelListener< - MessageChannel - >, - ); + windowListeners.delete(listener); }; }, );