diff --git a/src/common/app-paths/app-paths.test.ts b/src/common/app-paths/app-paths.test.ts index 095973344f..8fbcb0d318 100644 --- a/src/common/app-paths/app-paths.test.ts +++ b/src/common/app-paths/app-paths.test.ts @@ -7,17 +7,17 @@ import getElectronAppPathInjectable from "../../main/app-paths/get-electron-app- import type { PathName } from "./app-path-names"; import setElectronAppPathInjectable from "../../main/app-paths/set-electron-app-path/set-electron-app-path.injectable"; import directoryForIntegrationTestingInjectable from "../../main/app-paths/directory-for-integration-testing/directory-for-integration-testing.injectable"; -import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; -import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import type { ApplicationBuilder } from "../../features/test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../../features/test-utils/application-builder"; import type { DiContainer } from "@ogre-tools/injectable"; import appPathsInjectable from "./app-paths.injectable"; describe("app-paths", () => { let builder: ApplicationBuilder; - beforeEach(() => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(() => { const defaultAppPathsStub: AppPaths = { currentApp: "/some-current-app", appData: "/some-app-data", @@ -56,10 +56,6 @@ describe("app-paths", () => { }); }); - afterEach(() => { - builder.quit(); - }); - describe("normally", () => { let windowDi: DiContainer; let mainDi: DiContainer; diff --git a/src/common/utils/channel/channel.test.ts b/src/common/utils/channel/channel.test.ts index 1cd5df2264..265a43a5e3 100644 --- a/src/common/utils/channel/channel.test.ts +++ b/src/common/utils/channel/channel.test.ts @@ -6,8 +6,8 @@ import type { DiContainer } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable"; import type { SendMessageToChannel } from "./message-to-channel-injection-token"; import { sendMessageToChannelInjectionToken } 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 type { ApplicationBuilder } from "../../../features/test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../../../features/test-utils/application-builder"; import type { LensWindow } from "../../../main/start-main-application/lens-window/application-window/create-lens-window.injectable"; import type { MessageChannel } from "./message-channel-listener-injection-token"; import { messageChannelListenerInjectionToken } from "./message-channel-listener-injection-token"; @@ -25,15 +25,16 @@ type TestMessageChannel = MessageChannel; type TestRequestChannel = RequestChannel; describe("channel", () => { + let builder: ApplicationBuilder; + + setupInitializingApplicationBuilder(b => builder = b); + describe("messaging from main to renderer, given listener for channel in a window and application has started", () => { let messageListenerInWindowMock: jest.Mock; let mainDi: DiContainer; let messageToChannel: SendMessageToChannel; - let builder: ApplicationBuilder; beforeEach(async () => { - builder = getApplicationBuilder(); - messageListenerInWindowMock = jest.fn(); const testChannelListenerInTestWindowInjectable = getInjectable({ @@ -60,10 +61,6 @@ describe("channel", () => { messageToChannel = mainDi.inject(sendMessageToChannelInjectionToken); }); - afterEach(() => { - builder.quit(); - }); - describe("given window is started", () => { let someWindowFake: LensWindow; @@ -107,10 +104,8 @@ describe("channel", () => { describe("messaging from renderer to main, given listener for channel in a main and application has started", () => { let messageListenerInMainMock: jest.Mock; let messageToChannel: SendMessageToChannel; - let builder: ApplicationBuilder; beforeEach(async () => { - builder = getApplicationBuilder(); messageListenerInMainMock = jest.fn(); const testChannelListenerInMainInjectable = getInjectable({ @@ -137,10 +132,6 @@ describe("channel", () => { messageToChannel = windowDi.inject(sendMessageToChannelInjectionToken); }); - afterEach(() => { - builder.quit(); - }); - it("when sending message, triggers listener in main", () => { messageToChannel(testMessageChannel, "some-message"); @@ -151,10 +142,8 @@ describe("channel", () => { describe("requesting from main in renderer, given listener for channel in a main and application has started", () => { let requestListenerInMainMock: AsyncFnMock>; let requestFromChannel: RequestFromChannel; - let builder: ApplicationBuilder; beforeEach(async () => { - builder = getApplicationBuilder(); requestListenerInMainMock = asyncFn(); const testChannelListenerInMainInjectable = getRequestChannelListenerInjectable({ @@ -175,10 +164,6 @@ describe("channel", () => { requestFromChannel = windowDi.inject(requestFromChannelInjectable); }); - afterEach(() => { - builder.quit(); - }); - describe("when requesting from channel", () => { let actualPromise: Promise; @@ -207,11 +192,7 @@ describe("channel", () => { }); describe("when registering multiple handlers for the same channel", () => { - let builder: ApplicationBuilder; - beforeEach(() => { - builder = getApplicationBuilder(); - const testChannelListenerInMainInjectable = getRequestChannelListenerInjectable({ channel: testRequestChannel, handler: () => () => "some-value", @@ -231,10 +212,6 @@ describe("channel", () => { }); }); - afterEach(() => { - builder.quit(); - }); - it("throws on startup", async () => { await expect(builder.render()).rejects.toThrow('Tried to register a multiple channel handlers for "some-request-channel-id", only one handler is supported for a request channel.'); }); diff --git a/src/common/utils/sync-box/sync-box.test.ts b/src/common/utils/sync-box/sync-box.test.ts index 48e420a43e..755805287a 100644 --- a/src/common/utils/sync-box/sync-box.test.ts +++ b/src/common/utils/sync-box/sync-box.test.ts @@ -5,8 +5,8 @@ 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 type { ApplicationBuilder } from "../../../features/test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../../../features/test-utils/application-builder"; import createSyncBoxInjectable from "./create-sync-box.injectable"; import type { SyncBox } from "./sync-box-injection-token"; import { syncBoxInjectionToken } from "./sync-box-injection-token"; @@ -14,9 +14,9 @@ import { syncBoxInjectionToken } from "./sync-box-injection-token"; describe("sync-box", () => { let builder: ApplicationBuilder; - beforeEach(() => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(() => { builder.beforeApplicationStart(mainDi => { runInAction(() => { mainDi.register(someInjectable); @@ -30,10 +30,6 @@ describe("sync-box", () => { }); }); - afterEach(() => { - builder.quit(); - }); - describe("given application is started, when value is set in main", () => { let valueInMain: string; let syncBoxInMain: SyncBox; diff --git a/src/features/add-cluster/navigation-using-application-menu.test.tsx b/src/features/add-cluster/navigation-using-application-menu.test.tsx index 725015c8e2..2a7e47b98f 100644 --- a/src/features/add-cluster/navigation-using-application-menu.test.tsx +++ b/src/features/add-cluster/navigation-using-application-menu.test.tsx @@ -4,23 +4,19 @@ */ 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 { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; describe("add-cluster - navigation using application menu", () => { let builder: ApplicationBuilder; let rendered: RenderResult; + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { - builder = getApplicationBuilder(); - rendered = await builder.render(); }); - afterEach(() => { - builder.quit(); - }); - it("renders", () => { expect(rendered.container).toMatchSnapshot(); }); diff --git a/src/features/application-menu/application-menu-in-legacy-extension-api.test.ts b/src/features/application-menu/application-menu-in-legacy-extension-api.test.ts index 888f89f251..d8baf617d0 100644 --- a/src/features/application-menu/application-menu-in-legacy-extension-api.test.ts +++ b/src/features/application-menu/application-menu-in-legacy-extension-api.test.ts @@ -5,8 +5,8 @@ import { getInjectable } from "@ogre-tools/injectable"; import { noop } from "lodash/fp"; import { 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 type { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import type { FakeExtensionOptions } from "../../renderer/components/test-utils/get-extension-fake"; import applicationMenuItemInjectionToken from "./main/menu-items/application-menu-item-injection-token"; import logErrorInjectable from "../../common/log-error.injectable"; @@ -15,9 +15,9 @@ describe("application-menu-in-legacy-extension-api", () => { let builder: ApplicationBuilder; let logErrorMock: jest.Mock; - beforeEach(async () => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { builder.beforeApplicationStart( (mainDi) => { runInAction(() => { diff --git a/src/features/application-menu/application-menu.test.ts b/src/features/application-menu/application-menu.test.ts index 0db35db744..bad701f40f 100644 --- a/src/features/application-menu/application-menu.test.ts +++ b/src/features/application-menu/application-menu.test.ts @@ -2,8 +2,8 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; -import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import type { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import populateApplicationMenuInjectable from "./main/populate-application-menu.injectable"; import { advanceFakeTime, testUsingFakeTime } from "../../common/test-utils/use-fake-time"; import { getCompositePaths } from "../../common/utils/composite/get-composite-paths/get-composite-paths"; @@ -13,13 +13,13 @@ describe.each(allPlatforms)("application-menu, given platform is '%s'", (platfor let builder: ApplicationBuilder; let populateApplicationMenuMock: jest.Mock; + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { testUsingFakeTime(); populateApplicationMenuMock = jest.fn(); - builder = getApplicationBuilder(); - builder.beforeApplicationStart((mainDi) => { mainDi.override(platformInjectable, () => platform); diff --git a/src/features/application-menu/handling-of-orphan-application-menu-items.test.ts b/src/features/application-menu/handling-of-orphan-application-menu-items.test.ts index 7f35861a45..ca5e45358d 100644 --- a/src/features/application-menu/handling-of-orphan-application-menu-items.test.ts +++ b/src/features/application-menu/handling-of-orphan-application-menu-items.test.ts @@ -2,8 +2,8 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; -import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import type { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import populateApplicationMenuInjectable from "./main/populate-application-menu.injectable"; import { advanceFakeTime, testUsingFakeTime } from "../../common/test-utils/use-fake-time"; import { getCompositePaths } from "../../common/utils/composite/get-composite-paths/get-composite-paths"; @@ -17,14 +17,14 @@ describe("handling-of-orphan-application-menu-items, given orphan menu item", () let populateApplicationMenuMock: jest.Mock; let logErrorMock: jest.Mock; + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { testUsingFakeTime(); populateApplicationMenuMock = jest.fn(); logErrorMock = jest.fn(); - builder = getApplicationBuilder(); - builder.beforeApplicationStart((mainDi) => { const someOrphanMenuItemInjectable = getInjectable({ id: "some-orphan-menu-item", diff --git a/src/features/application-update/analytics-for-installing-update.test.ts b/src/features/application-update/analytics-for-installing-update.test.ts index ae95051a4a..1c48cb244b 100644 --- a/src/features/application-update/analytics-for-installing-update.test.ts +++ b/src/features/application-update/analytics-for-installing-update.test.ts @@ -2,8 +2,8 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; -import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import type { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import electronUpdaterIsActiveInjectable from "../../main/electron-app/features/electron-updater-is-active.injectable"; import publishIsConfiguredInjectable from "./main/updating-is-enabled/publish-is-configured/publish-is-configured.injectable"; import type { AsyncFnMock } from "@async-fn/jest"; @@ -28,11 +28,11 @@ describe("analytics for installing update", () => { let analyticsListenerMock: jest.Mock; let mainDi: DiContainer; + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { testUsingFakeTime("2015-10-21T07:28:00Z"); - builder = getApplicationBuilder(); - analyticsListenerMock = jest.fn(); builder.beforeApplicationStart(mainDi => { @@ -62,10 +62,6 @@ describe("analytics for installing update", () => { mainDi = builder.mainDi; }); - afterEach(() => { - builder.quit(); - }); - describe("given application is started and checking updates periodically", () => { beforeEach(async () => { mainDi.unoverride(periodicalCheckForUpdatesInjectable); diff --git a/src/features/application-update/child-features/application-update-using-top-bar/installing-update-using-topbar-button.test.tsx b/src/features/application-update/child-features/application-update-using-top-bar/installing-update-using-topbar-button.test.tsx index b7d37a8cd6..59f04578ee 100644 --- a/src/features/application-update/child-features/application-update-using-top-bar/installing-update-using-topbar-button.test.tsx +++ b/src/features/application-update/child-features/application-update-using-top-bar/installing-update-using-topbar-button.test.tsx @@ -12,8 +12,8 @@ import type { DownloadPlatformUpdate } from "../../main/download-update/download import downloadPlatformUpdateInjectable from "../../main/download-update/download-platform-update/download-platform-update.injectable"; import publishIsConfiguredInjectable from "../../main/updating-is-enabled/publish-is-configured/publish-is-configured.injectable"; import electronUpdaterIsActiveInjectable from "../../../../main/electron-app/features/electron-updater-is-active.injectable"; -import type { ApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder"; -import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder"; +import type { ApplicationBuilder } from "../../../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../../../test-utils/application-builder"; import processCheckingForUpdatesInjectable from "../../main/process-checking-for-updates.injectable"; import quitAndInstallUpdateInjectable from "../../main/quit-and-install-update.injectable"; import { advanceFakeTime, testUsingFakeTime } from "../../../../common/test-utils/use-fake-time"; @@ -28,11 +28,11 @@ describe("encourage user to update when sufficient time passed since update was let downloadPlatformUpdateMock: AsyncFnMock; let quitAndInstallUpdateMock: jest.MockedFunction<() => void>; + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(() => { testUsingFakeTime("2015-10-21T07:28:00Z"); - builder = getApplicationBuilder(); - builder.beforeApplicationStart((mainDi) => { checkForPlatformUpdatesMock = asyncFn(); downloadPlatformUpdateMock = asyncFn(); @@ -55,10 +55,6 @@ describe("encourage user to update when sufficient time passed since update was }); }); - afterEach(() => { - builder.quit(); - }); - describe("when started", () => { let rendered: RenderResult; diff --git a/src/features/application-update/child-features/application-update-using-tray/installing-update-using-tray.test.ts b/src/features/application-update/child-features/application-update-using-tray/installing-update-using-tray.test.ts index ad1d20cb53..66a95aa454 100644 --- a/src/features/application-update/child-features/application-update-using-tray/installing-update-using-tray.test.ts +++ b/src/features/application-update/child-features/application-update-using-tray/installing-update-using-tray.test.ts @@ -2,8 +2,8 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { ApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder"; -import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder"; +import type { ApplicationBuilder } from "../../../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../../../test-utils/application-builder"; import type { RenderResult } from "@testing-library/react"; import electronUpdaterIsActiveInjectable from "../../../../main/electron-app/features/electron-updater-is-active.injectable"; import publishIsConfiguredInjectable from "../../main/updating-is-enabled/publish-is-configured/publish-is-configured.injectable"; @@ -21,9 +21,9 @@ describe("installing update using tray", () => { let checkForPlatformUpdatesMock: AsyncFnMock; let downloadPlatformUpdateMock: AsyncFnMock; - beforeEach(() => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(() => { builder.beforeApplicationStart((mainDi) => { checkForPlatformUpdatesMock = asyncFn(); downloadPlatformUpdateMock = asyncFn(); @@ -43,10 +43,6 @@ describe("installing update using tray", () => { }); }); - afterEach(() => { - builder.quit(); - }); - describe("when started", () => { let rendered: RenderResult; diff --git a/src/features/application-update/child-features/force-user-to-update-when-too-long-time-since-update-was-downloaded/force-user-to-update-when-too-long-time-since-update-was-downloaded.test.ts b/src/features/application-update/child-features/force-user-to-update-when-too-long-time-since-update-was-downloaded/force-user-to-update-when-too-long-time-since-update-was-downloaded.test.ts index 73fa30d293..6707bc0018 100644 --- a/src/features/application-update/child-features/force-user-to-update-when-too-long-time-since-update-was-downloaded/force-user-to-update-when-too-long-time-since-update-was-downloaded.test.ts +++ b/src/features/application-update/child-features/force-user-to-update-when-too-long-time-since-update-was-downloaded/force-user-to-update-when-too-long-time-since-update-was-downloaded.test.ts @@ -2,8 +2,8 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { ApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder"; -import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder"; +import type { ApplicationBuilder } from "../../../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../../../test-utils/application-builder"; import type { CheckForPlatformUpdates } from "../../main/check-for-updates/check-for-platform-updates/check-for-platform-updates.injectable"; import checkForPlatformUpdatesInjectable from "../../main/check-for-updates/check-for-platform-updates/check-for-platform-updates.injectable"; import type { DownloadPlatformUpdate } from "../../main/download-update/download-platform-update/download-platform-update.injectable"; @@ -30,11 +30,11 @@ describe("force user to update when too long since update was downloaded", () => let mainDi: DiContainer; let quitAndInstallUpdateMock: jest.Mock; + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(() => { testUsingFakeTime("2015-10-21T07:28:00Z"); - builder = getApplicationBuilder(); - builder.beforeApplicationStart(mainDi => { checkForPlatformUpdatesMock = asyncFn(); @@ -60,10 +60,6 @@ describe("force user to update when too long since update was downloaded", () => mainDi = builder.mainDi; }); - afterEach(() => { - builder.quit(); - }); - describe("when application is started", () => { let rendered: RenderResult; diff --git a/src/features/application-update/child-features/periodical-checking-of-updates/periodical-checking-of-updates.test.ts b/src/features/application-update/child-features/periodical-checking-of-updates/periodical-checking-of-updates.test.ts index 6961538d4c..9b281174ce 100644 --- a/src/features/application-update/child-features/periodical-checking-of-updates/periodical-checking-of-updates.test.ts +++ b/src/features/application-update/child-features/periodical-checking-of-updates/periodical-checking-of-updates.test.ts @@ -2,8 +2,8 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { ApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder"; -import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder"; +import type { ApplicationBuilder } from "../../../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../../../test-utils/application-builder"; import type { RenderResult } from "@testing-library/react"; import electronUpdaterIsActiveInjectable from "../../../../main/electron-app/features/electron-updater-is-active.injectable"; import publishIsConfiguredInjectable from "../../main/updating-is-enabled/publish-is-configured/publish-is-configured.injectable"; @@ -17,11 +17,11 @@ describe("periodical checking of updates", () => { let builder: ApplicationBuilder; let processCheckingForUpdatesMock: jest.Mock; + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(() => { testUsingFakeTime("2015-10-21T07:28:00Z"); - builder = getApplicationBuilder(); - builder.beforeApplicationStart((mainDi) => { mainDi.unoverride(periodicalCheckForUpdatesInjectable); mainDi.permitSideEffects(periodicalCheckForUpdatesInjectable); @@ -35,10 +35,6 @@ describe("periodical checking of updates", () => { }); }); - afterEach(() => { - builder.quit(); - }); - describe("given updater is enabled and configuration exists, when started", () => { let rendered: RenderResult; diff --git a/src/features/application-update/child-features/selection-of-update-stability/selection-of-update-stability.test.ts b/src/features/application-update/child-features/selection-of-update-stability/selection-of-update-stability.test.ts index 7e864085df..c297190052 100644 --- a/src/features/application-update/child-features/selection-of-update-stability/selection-of-update-stability.test.ts +++ b/src/features/application-update/child-features/selection-of-update-stability/selection-of-update-stability.test.ts @@ -2,8 +2,8 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { ApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder"; -import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder"; +import type { ApplicationBuilder } from "../../../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../../../test-utils/application-builder"; import quitAndInstallUpdateInjectable from "../../main/quit-and-install-update.injectable"; import type { RenderResult } from "@testing-library/react"; import electronUpdaterIsActiveInjectable from "../../../../main/electron-app/features/electron-updater-is-active.injectable"; @@ -22,8 +22,7 @@ import setUpdateOnQuitInjectable from "../../../../main/electron-app/features/se import showInfoNotificationInjectable from "../../../../renderer/components/notifications/show-info-notification.injectable"; import processCheckingForUpdatesInjectable from "../../main/process-checking-for-updates.injectable"; import type { DiContainer } from "@ogre-tools/injectable"; -import getBuildVersionInjectable - from "../../../../main/vars/build-version/get-build-version.injectable"; +import getBuildVersionInjectable from "../../../../main/vars/build-version/get-build-version.injectable"; describe("selection of update stability", () => { let builder: ApplicationBuilder; @@ -34,9 +33,9 @@ describe("selection of update stability", () => { let showInfoNotificationMock: jest.Mock; let mainDi: DiContainer; - beforeEach(() => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(() => { builder.beforeApplicationStart((mainDi) => { quitAndInstallUpdateMock = jest.fn(); checkForPlatformUpdatesMock = asyncFn(); @@ -73,10 +72,6 @@ describe("selection of update stability", () => { mainDi = builder.mainDi; }); - afterEach(() => { - builder.quit(); - }); - describe("when started", () => { let rendered: RenderResult; let processCheckingForUpdates: (source: string) => Promise<{ updateIsReadyToBeInstalled: boolean }>; diff --git a/src/features/application-update/downgrading-version-update.test.ts b/src/features/application-update/downgrading-version-update.test.ts index f0ad80d099..93d322946f 100644 --- a/src/features/application-update/downgrading-version-update.test.ts +++ b/src/features/application-update/downgrading-version-update.test.ts @@ -2,8 +2,8 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; -import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import type { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import electronUpdaterIsActiveInjectable from "../../main/electron-app/features/electron-updater-is-active.injectable"; import publishIsConfiguredInjectable from "./main/updating-is-enabled/publish-is-configured/publish-is-configured.injectable"; import type { AsyncFnMock } from "@async-fn/jest"; @@ -21,9 +21,9 @@ describe("downgrading version update", () => { let checkForPlatformUpdatesMock: AsyncFnMock; let mainDi: DiContainer; - beforeEach(() => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(() => { builder.beforeApplicationStart(mainDi => { checkForPlatformUpdatesMock = asyncFn(); @@ -39,10 +39,6 @@ describe("downgrading version update", () => { mainDi = builder.mainDi; }); - afterEach(() => { - builder.quit(); - }); - [ { updateChannel: updateChannels.latest, diff --git a/src/features/application-update/installing-update.test.ts b/src/features/application-update/installing-update.test.ts index cf5d79965b..fc210e3d44 100644 --- a/src/features/application-update/installing-update.test.ts +++ b/src/features/application-update/installing-update.test.ts @@ -2,8 +2,8 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; -import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import type { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import quitAndInstallUpdateInjectable from "./main/quit-and-install-update.injectable"; import type { RenderResult } from "@testing-library/react"; import electronUpdaterIsActiveInjectable from "../../main/electron-app/features/electron-updater-is-active.injectable"; @@ -26,11 +26,11 @@ describe("installing update", () => { let downloadPlatformUpdateMock: AsyncFnMock; let setUpdateOnQuitMock: jest.Mock; + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(() => { testUsingFakeTime("2015-10-21T07:28:00Z"); - builder = getApplicationBuilder(); - builder.beforeApplicationStart((mainDi) => { quitAndInstallUpdateMock = jest.fn(); checkForPlatformUpdatesMock = asyncFn(); @@ -61,10 +61,6 @@ describe("installing update", () => { }); }); - afterEach(() => { - builder.quit(); - }); - describe("when started", () => { let rendered: RenderResult; let processCheckingForUpdates: (source: string) => Promise<{ updateIsReadyToBeInstalled: boolean }>; diff --git a/src/features/cluster/delete-dialog/delete-cluster-dialog.test.tsx b/src/features/cluster/delete-dialog/delete-cluster-dialog.test.tsx index ac6b59adef..3730b27311 100644 --- a/src/features/cluster/delete-dialog/delete-cluster-dialog.test.tsx +++ b/src/features/cluster/delete-dialog/delete-cluster-dialog.test.tsx @@ -13,7 +13,7 @@ import normalizedPlatformInjectable from "../../../common/vars/normalized-platfo import kubectlBinaryNameInjectable from "../../../main/kubectl/binary-name.injectable"; import kubectlDownloadingNormalizedArchInjectable from "../../../main/kubectl/normalized-arch.injectable"; import openDeleteClusterDialogInjectable, { type OpenDeleteClusterDialog } from "../../../renderer/components/delete-cluster-dialog/open.injectable"; -import { type ApplicationBuilder, getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; +import { type ApplicationBuilder, setupInitializingApplicationBuilder } from "../../test-utils/application-builder"; import type { Cluster } from "../../../common/cluster/cluster"; import navigateToCatalogInjectable from "../../../common/front-end-routing/routes/catalog/navigate-to-catalog.injectable"; import directoryForKubeConfigsInjectable from "../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable"; @@ -77,10 +77,10 @@ describe("Deleting a cluster", () => { let rendered: RenderResult; let config: KubeConfig; + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { config = new KubeConfig(); - builder = getApplicationBuilder(); - builder.beforeApplicationStart((mainDi) => { mainDi.override(createContextHandlerInjectable, () => () => undefined as never); mainDi.override(createKubeconfigManagerInjectable, () => () => undefined as never); @@ -104,10 +104,6 @@ describe("Deleting a cluster", () => { rendered = await builder.render(); }); - afterEach(() => { - builder.quit(); - }); - describe("when the kubeconfig has multiple clusters", () => { let currentCluster: Cluster; let nonCurrentCluster: Cluster; diff --git a/src/features/cluster/extension-api/disable-cluster-pages-when-cluster-is-not-relevant.test.tsx b/src/features/cluster/extension-api/disable-cluster-pages-when-cluster-is-not-relevant.test.tsx index aceeb31cfa..24cd1ed417 100644 --- a/src/features/cluster/extension-api/disable-cluster-pages-when-cluster-is-not-relevant.test.tsx +++ b/src/features/cluster/extension-api/disable-cluster-pages-when-cluster-is-not-relevant.test.tsx @@ -5,8 +5,8 @@ import type { AsyncFnMock } from "@async-fn/jest"; 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 type { ApplicationBuilder } from "../../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../../test-utils/application-builder"; import type { TestExtensionRenderer } from "../../../renderer/components/test-utils/get-extension-fake"; import type { KubernetesCluster } from "../../../common/catalog-entities"; import React from "react"; @@ -17,9 +17,9 @@ describe("disable-cluster-pages-when-cluster-is-not-relevant", () => { let rendererTestExtension: TestExtensionRenderer; let isEnabledForClusterMock: AsyncFnMock<(cluster: KubernetesCluster) => Promise>; - beforeEach(async () => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { builder.setEnvironmentToClusterFrame(); isEnabledForClusterMock = asyncFn(); @@ -47,10 +47,6 @@ describe("disable-cluster-pages-when-cluster-is-not-relevant", () => { builder.extensions.get("test-extension-id").applicationWindows.only; }); - afterEach(() => { - builder.quit(); - }); - describe("given not yet known if extension should be enabled for the cluster, when navigating", () => { beforeEach(() => { rendererTestExtension.navigate(); diff --git a/src/features/cluster/extension-api/disable-sidebar-items-when-cluster-is-not-relevant.test.tsx b/src/features/cluster/extension-api/disable-sidebar-items-when-cluster-is-not-relevant.test.tsx index 739de9c65f..c71187a018 100644 --- a/src/features/cluster/extension-api/disable-sidebar-items-when-cluster-is-not-relevant.test.tsx +++ b/src/features/cluster/extension-api/disable-sidebar-items-when-cluster-is-not-relevant.test.tsx @@ -5,8 +5,8 @@ import type { AsyncFnMock } from "@async-fn/jest"; 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 type { ApplicationBuilder } from "../../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../../test-utils/application-builder"; import type { KubernetesCluster } from "../../../common/catalog-entities"; import React from "react"; @@ -15,9 +15,9 @@ describe("disable sidebar items when cluster is not relevant", () => { let rendered: RenderResult; let isEnabledForClusterMock: AsyncFnMock<(cluster: KubernetesCluster) => Promise>; - beforeEach(async () => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { builder.setEnvironmentToClusterFrame(); isEnabledForClusterMock = asyncFn(); @@ -53,10 +53,6 @@ describe("disable sidebar items when cluster is not relevant", () => { builder.extensions.enable(testExtension); }); - afterEach(() => { - builder.quit(); - }); - describe("given not yet known if extension should be enabled for the cluster", () => { it("renders", () => { expect(rendered.baseElement).toMatchSnapshot(); diff --git a/src/features/cluster/extension-api/reactively-disable-cluster-pages.test.tsx b/src/features/cluster/extension-api/reactively-disable-cluster-pages.test.tsx index 8323767b37..4dbdcef6cf 100644 --- a/src/features/cluster/extension-api/reactively-disable-cluster-pages.test.tsx +++ b/src/features/cluster/extension-api/reactively-disable-cluster-pages.test.tsx @@ -7,8 +7,8 @@ import type { IObservableValue } from "mobx"; import { observable, runInAction, computed } from "mobx"; 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 type { ApplicationBuilder } from "../../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../../test-utils/application-builder"; describe("reactively disable cluster pages", () => { let builder: ApplicationBuilder; @@ -16,9 +16,9 @@ describe("reactively disable cluster pages", () => { let someObservable: IObservableValue; let testExtensionInstance: TestExtensionRenderer; - beforeEach(async () => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { builder.setEnvironmentToClusterFrame(); someObservable = observable.box(false); @@ -46,10 +46,6 @@ describe("reactively disable cluster pages", () => { builder.extensions.get("test-extension-id").applicationWindows.only; }); - afterEach(() => { - builder.quit(); - }); - it("when navigating to the page, does not show the page", () => { testExtensionInstance.navigate(); diff --git a/src/features/cluster/kube-object-details/extension-api/disable-kube-object-detail-items-when-cluster-is-not-relevant.test.tsx b/src/features/cluster/kube-object-details/extension-api/disable-kube-object-detail-items-when-cluster-is-not-relevant.test.tsx index a29d07bb14..a2bb4497f7 100644 --- a/src/features/cluster/kube-object-details/extension-api/disable-kube-object-detail-items-when-cluster-is-not-relevant.test.tsx +++ b/src/features/cluster/kube-object-details/extension-api/disable-kube-object-detail-items-when-cluster-is-not-relevant.test.tsx @@ -5,9 +5,9 @@ import type { AsyncFnMock } from "@async-fn/jest"; 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 type { ApplicationBuilder } from "../../../test-utils/application-builder"; import type { KubernetesCluster } from "../../../../common/catalog-entities"; -import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder"; +import { setupInitializingApplicationBuilder } from "../../../test-utils/application-builder"; import React from "react"; import { KubeObject } from "../../../../common/k8s-api/kube-object"; import apiManagerInjectable from "../../../../common/k8s-api/api-manager/manager.injectable"; @@ -22,8 +22,9 @@ describe("disable kube object detail items when cluster is not relevant", () => (cluster: KubernetesCluster) => Promise >; + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { - builder = getApplicationBuilder(); builder.setEnvironmentToClusterFrame(); builder.afterWindowStart((windowDi) => { @@ -75,10 +76,6 @@ describe("disable kube object detail items when cluster is not relevant", () => builder.extensions.enable(testExtension); }); - afterEach(() => { - builder.quit(); - }); - describe("given not yet known if extension should be enabled for the cluster", () => { it("renders", () => { expect(rendered.baseElement).toMatchSnapshot(); diff --git a/src/features/cluster/kube-object-details/extension-api/reactively-hide-kube-object-detail-item.test.tsx b/src/features/cluster/kube-object-details/extension-api/reactively-hide-kube-object-detail-item.test.tsx index f374a115ff..1a5f9ad177 100644 --- a/src/features/cluster/kube-object-details/extension-api/reactively-hide-kube-object-detail-item.test.tsx +++ b/src/features/cluster/kube-object-details/extension-api/reactively-hide-kube-object-detail-item.test.tsx @@ -3,8 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ 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 { ApplicationBuilder } from "../../../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../../../test-utils/application-builder"; import type { IObservableValue } from "mobx"; import { runInAction, computed, observable } from "mobx"; import React from "react"; @@ -19,9 +19,9 @@ describe("reactively hide kube object detail item", () => { let rendered: RenderResult; let someObservable: IObservableValue; - beforeEach(async () => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { builder.setEnvironmentToClusterFrame(); builder.afterWindowStart((windowDi) => { @@ -74,11 +74,6 @@ describe("reactively hide kube object detail item", () => { builder.extensions.enable(testExtension); }); - - afterEach(() => { - builder.quit(); - }); - it("renders", () => { expect(rendered.baseElement).toMatchSnapshot(); }); diff --git a/src/features/cluster/kube-object-menu/extension-api/disable-kube-object-menu-items-when-cluster-is-not-relevant.test.tsx b/src/features/cluster/kube-object-menu/extension-api/disable-kube-object-menu-items-when-cluster-is-not-relevant.test.tsx index 343ee461bf..e65894a3f4 100644 --- a/src/features/cluster/kube-object-menu/extension-api/disable-kube-object-menu-items-when-cluster-is-not-relevant.test.tsx +++ b/src/features/cluster/kube-object-menu/extension-api/disable-kube-object-menu-items-when-cluster-is-not-relevant.test.tsx @@ -5,9 +5,9 @@ import type { AsyncFnMock } from "@async-fn/jest"; 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 type { ApplicationBuilder } from "../../../test-utils/application-builder"; import type { KubernetesCluster } from "../../../../common/catalog-entities"; -import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder"; +import { setupInitializingApplicationBuilder } from "../../../test-utils/application-builder"; import { getInjectable } from "@ogre-tools/injectable"; import { frontEndRouteInjectionToken } from "../../../../common/front-end-routing/front-end-route-injection-token"; import { computed, runInAction } from "mobx"; @@ -24,9 +24,9 @@ describe("disable kube object menu items when cluster is not relevant", () => { (cluster: KubernetesCluster) => Promise >; - beforeEach(async () => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { builder.setEnvironmentToClusterFrame(); builder.beforeWindowStart((windowDi) => { @@ -70,10 +70,6 @@ describe("disable kube object menu items when cluster is not relevant", () => { builder.extensions.enable(testExtension); }); - afterEach(() => { - builder.quit(); - }); - describe("given not yet known if extension should be enabled for the cluster", () => { it("renders", () => { expect(rendered.baseElement).toMatchSnapshot(); diff --git a/src/features/cluster/kube-object-menu/extension-api/reactively-hide-kube-object-menu-item.test.tsx b/src/features/cluster/kube-object-menu/extension-api/reactively-hide-kube-object-menu-item.test.tsx index b7a6ccb31c..fc4b840fcd 100644 --- a/src/features/cluster/kube-object-menu/extension-api/reactively-hide-kube-object-menu-item.test.tsx +++ b/src/features/cluster/kube-object-menu/extension-api/reactively-hide-kube-object-menu-item.test.tsx @@ -3,8 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ 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 { ApplicationBuilder } from "../../../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../../../test-utils/application-builder"; import { getInjectable } from "@ogre-tools/injectable"; import { frontEndRouteInjectionToken } from "../../../../common/front-end-routing/front-end-route-injection-token"; import type { IObservableValue } from "mobx"; @@ -20,9 +20,9 @@ describe("reactively hide kube object menu item", () => { let rendered: RenderResult; let someObservable: IObservableValue; - beforeEach(async () => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { builder.setEnvironmentToClusterFrame(); builder.beforeWindowStart((windowDi) => { @@ -66,10 +66,6 @@ describe("reactively hide kube object menu item", () => { builder.extensions.enable(testExtension); }); - afterEach(() => { - builder.quit(); - }); - it("does not show the kube object menu item", () => { const actual = rendered.queryByTestId("some-kube-object-menu-item"); diff --git a/src/features/cluster/kube-object-status-icon/extension-api/disable-kube-object-statuses-when-cluster-is-not-relevant.test.tsx b/src/features/cluster/kube-object-status-icon/extension-api/disable-kube-object-statuses-when-cluster-is-not-relevant.test.tsx index e14373548f..6900a211f3 100644 --- a/src/features/cluster/kube-object-status-icon/extension-api/disable-kube-object-statuses-when-cluster-is-not-relevant.test.tsx +++ b/src/features/cluster/kube-object-status-icon/extension-api/disable-kube-object-statuses-when-cluster-is-not-relevant.test.tsx @@ -5,9 +5,9 @@ import type { AsyncFnMock } from "@async-fn/jest"; 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 type { ApplicationBuilder } from "../../../test-utils/application-builder"; import type { KubernetesCluster } from "../../../../common/catalog-entities"; -import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder"; +import { setupInitializingApplicationBuilder } from "../../../test-utils/application-builder"; import { getInjectable } from "@ogre-tools/injectable"; import { frontEndRouteInjectionToken } from "../../../../common/front-end-routing/front-end-route-injection-token"; import { computed, runInAction } from "mobx"; @@ -25,9 +25,9 @@ describe("disable kube object statuses when cluster is not relevant", () => { (cluster: KubernetesCluster) => Promise >; - beforeEach(async () => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { builder.setEnvironmentToClusterFrame(); builder.beforeWindowStart((windowDi) => { @@ -71,10 +71,6 @@ describe("disable kube object statuses when cluster is not relevant", () => { builder.extensions.enable(testExtension); }); - afterEach(() => { - builder.quit(); - }); - describe("given not yet known if extension should be enabled for the cluster", () => { it("renders", () => { expect(rendered.baseElement).toMatchSnapshot(); diff --git a/src/features/cluster/kube-object-status-icon/extension-api/reactively-hide-kube-object-status.test.tsx b/src/features/cluster/kube-object-status-icon/extension-api/reactively-hide-kube-object-status.test.tsx index e01e1b1353..5347082260 100644 --- a/src/features/cluster/kube-object-status-icon/extension-api/reactively-hide-kube-object-status.test.tsx +++ b/src/features/cluster/kube-object-status-icon/extension-api/reactively-hide-kube-object-status.test.tsx @@ -4,8 +4,8 @@ */ import type { RenderResult } from "@testing-library/react"; import { waitFor } 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 { ApplicationBuilder } from "../../../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../../../test-utils/application-builder"; import { getInjectable } from "@ogre-tools/injectable"; import { frontEndRouteInjectionToken } from "../../../../common/front-end-routing/front-end-route-injection-token"; import type { IObservableValue } from "mobx"; @@ -22,9 +22,9 @@ describe("reactively hide kube object status", () => { let rendered: RenderResult; let someObservable: IObservableValue; - beforeEach(async () => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { builder.setEnvironmentToClusterFrame(); builder.beforeWindowStart((windowDi) => { @@ -68,10 +68,6 @@ describe("reactively hide kube object status", () => { builder.extensions.enable(testExtension); }); - afterEach(() => { - builder.quit(); - }); - it("does not show the kube object status", async () => { await waitFor(() => expect(rendered.baseElement.querySelectorAll(".KubeObjectStatusIcon")).toHaveLength(0)); }); diff --git a/src/features/cluster/kube-object-status-icon/show-status-for-a-kube-object.test.tsx b/src/features/cluster/kube-object-status-icon/show-status-for-a-kube-object.test.tsx index 997eb1f3ea..19d84c7924 100644 --- a/src/features/cluster/kube-object-status-icon/show-status-for-a-kube-object.test.tsx +++ b/src/features/cluster/kube-object-status-icon/show-status-for-a-kube-object.test.tsx @@ -12,8 +12,8 @@ import type { IAtom } from "mobx"; import { runInAction, createAtom, computed } from "mobx"; import { frontEndRouteInjectionToken } from "../../../common/front-end-routing/front-end-route-injection-token"; import { routeSpecificComponentInjectionToken } from "../../../renderer/routes/route-specific-component-injection-token"; -import type { ApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; -import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; +import type { ApplicationBuilder } from "../../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../../test-utils/application-builder"; import { navigateToRouteInjectionToken } from "../../../common/front-end-routing/navigate-to-route-injection-token"; import type { RenderResult } from "@testing-library/react"; import { act } from "@testing-library/react"; @@ -27,11 +27,11 @@ describe("show status for a kube object", () => { let warningStatusIsShown: boolean; let criticalStatusIsShown: boolean; + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(() => { testUsingFakeTime("2015-10-21T07:28:00Z"); - builder = getApplicationBuilder(); - infoStatusIsShown = false; const infoStatusInjectable = getInjectable({ @@ -110,10 +110,6 @@ describe("show status for a kube object", () => { builder.setEnvironmentToClusterFrame(); }); - afterEach(() => { - builder.quit(); - }); - describe("given application starts and in test page", () => { let windowDi: DiContainer; let rendered: RenderResult; diff --git a/src/features/cluster/legacy-extension-adding-cluster-frame-components.test.tsx b/src/features/cluster/legacy-extension-adding-cluster-frame-components.test.tsx index f837550f7a..8c22ffd3b9 100644 --- a/src/features/cluster/legacy-extension-adding-cluster-frame-components.test.tsx +++ b/src/features/cluster/legacy-extension-adding-cluster-frame-components.test.tsx @@ -7,15 +7,16 @@ import { act } from "@testing-library/react"; import type { IObservableValue } from "mobx"; import { computed, observable, runInAction } from "mobx"; 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 { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; describe("legacy extension adding cluster frame components", () => { let builder: ApplicationBuilder; let rendered: RenderResult; + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(() => { - builder = getApplicationBuilder(); builder.setEnvironmentToClusterFrame(); }); diff --git a/src/features/cluster/namespaces/edit-namespace-from-new-tab.test.tsx b/src/features/cluster/namespaces/edit-namespace-from-new-tab.test.tsx index df316f8562..cb33c4dad3 100644 --- a/src/features/cluster/namespaces/edit-namespace-from-new-tab.test.tsx +++ b/src/features/cluster/namespaces/edit-namespace-from-new-tab.test.tsx @@ -5,8 +5,8 @@ import type { DiContainer } from "@ogre-tools/injectable"; import type { RenderResult } from "@testing-library/react"; import { fireEvent } 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 { ApplicationBuilder } from "../../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../../test-utils/application-builder"; import navigateToNamespacesInjectable from "../../../common/front-end-routing/routes/cluster/namespaces/navigate-to-namespaces.injectable"; import createEditResourceTabInjectable from "../../../renderer/components/dock/edit-resource/edit-resource-tab.injectable"; import getRandomIdForEditResourceTabInjectable from "../../../renderer/components/dock/edit-resource/get-random-id-for-edit-resource-tab.injectable"; @@ -31,9 +31,9 @@ describe("cluster/namespaces - edit namespace from new tab", () => { let showSuccessNotificationMock: jest.Mock; let showErrorNotificationMock: jest.Mock; - beforeEach(() => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(() => { builder.setEnvironmentToClusterFrame(); builder.beforeWindowStart((windowDi) => { @@ -70,10 +70,6 @@ describe("cluster/namespaces - edit namespace from new tab", () => { }); }); - afterEach(() => { - builder.quit(); - }); - describe("when navigating to namespaces", () => { let rendered: RenderResult; let windowDi: DiContainer; diff --git a/src/features/cluster/namespaces/edit-namespace-from-previously-opened-tab.test.tsx b/src/features/cluster/namespaces/edit-namespace-from-previously-opened-tab.test.tsx index 1ad5dcaf3e..3202f2783d 100644 --- a/src/features/cluster/namespaces/edit-namespace-from-previously-opened-tab.test.tsx +++ b/src/features/cluster/namespaces/edit-namespace-from-previously-opened-tab.test.tsx @@ -4,8 +4,8 @@ */ import type { RenderResult } from "@testing-library/react"; import { act } 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 { ApplicationBuilder } from "../../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../../test-utils/application-builder"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; import type { CallForResource } from "../../../renderer/components/dock/edit-resource/edit-resource-model/call-for-resource/call-for-resource.injectable"; @@ -19,9 +19,9 @@ describe("cluster/namespaces - edit namespaces from previously opened tab", () = let builder: ApplicationBuilder; let callForNamespaceMock: AsyncFnMock; - beforeEach(() => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(() => { builder.setEnvironmentToClusterFrame(); callForNamespaceMock = asyncFn(); @@ -41,10 +41,6 @@ describe("cluster/namespaces - edit namespaces from previously opened tab", () = }); }); - afterEach(() => { - builder.quit(); - }); - describe("given tab was previously opened, when application is started", () => { let rendered: RenderResult; diff --git a/src/features/cluster/order-of-sidebar-items.test.tsx b/src/features/cluster/order-of-sidebar-items.test.tsx index bd1454c3a0..b5c0553622 100644 --- a/src/features/cluster/order-of-sidebar-items.test.tsx +++ b/src/features/cluster/order-of-sidebar-items.test.tsx @@ -9,16 +9,16 @@ import type { SidebarItemRegistration } from "../../renderer/components/layout/s import { sidebarItemsInjectionToken } from "../../renderer/components/layout/sidebar-items.injectable"; import { computed, runInAction } from "mobx"; import { noop } from "lodash/fp"; -import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; -import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import type { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; describe("cluster - order of sidebar items", () => { let rendered: RenderResult; let builder: ApplicationBuilder; - beforeEach(() => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(() => { builder.setEnvironmentToClusterFrame(); builder.beforeWindowStart((windowDi) => { @@ -28,10 +28,6 @@ describe("cluster - order of sidebar items", () => { }); }); - afterEach(() => { - builder.quit(); - }); - describe("when rendered", () => { beforeEach(async () => { rendered = await builder.render(); diff --git a/src/features/cluster/sidebar-and-tab-navigation-for-core.test.tsx b/src/features/cluster/sidebar-and-tab-navigation-for-core.test.tsx index 6f28ce1b1e..fc315a83ff 100644 --- a/src/features/cluster/sidebar-and-tab-navigation-for-core.test.tsx +++ b/src/features/cluster/sidebar-and-tab-navigation-for-core.test.tsx @@ -14,8 +14,8 @@ import { computed, runInAction } from "mobx"; import { noop } from "lodash/fp"; import routeIsActiveInjectable from "../../renderer/routes/route-is-active.injectable"; import { frontEndRouteInjectionToken } from "../../common/front-end-routing/front-end-route-injection-token"; -import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; -import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import type { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; 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"; @@ -28,11 +28,11 @@ describe("cluster - sidebar and tab navigation for core", () => { let builder: ApplicationBuilder; let rendered: RenderResult; + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(() => { testUsingFakeTime("2015-10-21T07:28:00Z"); - builder = getApplicationBuilder(); - builder.setEnvironmentToClusterFrame(); builder.beforeWindowStart((windowDi) => { @@ -40,10 +40,6 @@ describe("cluster - sidebar and tab navigation for core", () => { }); }); - afterEach(() => { - builder.quit(); - }); - describe("given core registrations", () => { beforeEach(() => { builder.beforeWindowStart((windowDi) => { diff --git a/src/features/cluster/sidebar-and-tab-navigation-for-extensions.test.tsx b/src/features/cluster/sidebar-and-tab-navigation-for-extensions.test.tsx index 37c17efa90..d38ee2ce98 100644 --- a/src/features/cluster/sidebar-and-tab-navigation-for-extensions.test.tsx +++ b/src/features/cluster/sidebar-and-tab-navigation-for-extensions.test.tsx @@ -8,8 +8,8 @@ import { fireEvent } from "@testing-library/react"; import directoryForLensLocalStorageInjectable from "../../common/directory-for-lens-local-storage/directory-for-lens-local-storage.injectable"; import routesInjectable from "../../renderer/routes/routes.injectable"; import { matches } from "lodash/fp"; -import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; -import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import type { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; 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"; @@ -26,11 +26,11 @@ describe("cluster - sidebar and tab navigation for extensions", () => { let builder: ApplicationBuilder; let rendered: RenderResult; + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(() => { testUsingFakeTime("2015-10-21T07:28:00Z"); - builder = getApplicationBuilder(); - builder.setEnvironmentToClusterFrame(); builder.beforeWindowStart((windowDi) => { @@ -43,10 +43,6 @@ describe("cluster - sidebar and tab navigation for extensions", () => { }); }); - afterEach(() => { - builder.quit(); - }); - describe("given extension with cluster pages and cluster page menus", () => { let someObservable: IObservableValue; diff --git a/src/features/cluster/visibility-of-sidebar-items.test.tsx b/src/features/cluster/visibility-of-sidebar-items.test.tsx index b4abf0a655..f2241b4235 100644 --- a/src/features/cluster/visibility-of-sidebar-items.test.tsx +++ b/src/features/cluster/visibility-of-sidebar-items.test.tsx @@ -10,8 +10,8 @@ import { computed, runInAction } from "mobx"; import { routeSpecificComponentInjectionToken } from "../../renderer/routes/route-specific-component-injection-token"; import React from "react"; import { frontEndRouteInjectionToken } from "../../common/front-end-routing/front-end-route-injection-token"; -import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; -import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import type { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import { navigateToRouteInjectionToken } from "../../common/front-end-routing/navigate-to-route-injection-token"; import { shouldShowResourceInjectionToken } from "../../common/cluster-store/allowed-resources-injection-token"; @@ -19,9 +19,9 @@ describe("cluster - visibility of sidebar items", () => { let builder: ApplicationBuilder; let rendered: RenderResult; - beforeEach(() => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(() => { builder.setEnvironmentToClusterFrame(); builder.beforeWindowStart((windowDi) => { @@ -33,10 +33,6 @@ describe("cluster - visibility of sidebar items", () => { }); }); - afterEach(() => { - builder.quit(); - }); - describe("given kube resource for route is not allowed", () => { beforeEach(async () => { rendered = await builder.render(); diff --git a/src/features/cluster/workload-overview.test.tsx b/src/features/cluster/workload-overview.test.tsx index 205c837b47..1bcc1f5072 100644 --- a/src/features/cluster/workload-overview.test.tsx +++ b/src/features/cluster/workload-overview.test.tsx @@ -5,24 +5,26 @@ import type { RenderResult } from "@testing-library/react"; import navigateToWorkloadsOverviewInjectable from "../../common/front-end-routing/routes/cluster/workloads/overview/navigate-to-workloads-overview.injectable"; -import { type ApplicationBuilder, getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import { type ApplicationBuilder, setupInitializingApplicationBuilder } from "../test-utils/application-builder"; describe("workload overview", () => { let rendered: RenderResult; - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; + + setupInitializingApplicationBuilder(b => builder = b); beforeEach(async () => { - applicationBuilder = getApplicationBuilder().setEnvironmentToClusterFrame(); - applicationBuilder.allowKubeResource({ + builder.setEnvironmentToClusterFrame(); + builder.allowKubeResource({ apiName: "pods", group: "v1", }); - rendered = await applicationBuilder.render(); + rendered = await builder.render(); }); describe("when navigating to workload overview", () => { beforeEach(() => { - applicationBuilder.navigateWith(navigateToWorkloadsOverviewInjectable); + builder.navigateWith(navigateToWorkloadsOverviewInjectable); }); it("renders", () => { diff --git a/src/features/cluster/workloads/overview/extension-api/disable-workloads-overview-details-when-cluster-is-not-relevant.test.tsx b/src/features/cluster/workloads/overview/extension-api/disable-workloads-overview-details-when-cluster-is-not-relevant.test.tsx index de3f8e8303..705ff82d89 100644 --- a/src/features/cluster/workloads/overview/extension-api/disable-workloads-overview-details-when-cluster-is-not-relevant.test.tsx +++ b/src/features/cluster/workloads/overview/extension-api/disable-workloads-overview-details-when-cluster-is-not-relevant.test.tsx @@ -5,9 +5,9 @@ import type { AsyncFnMock } from "@async-fn/jest"; 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 type { ApplicationBuilder } from "../../../../test-utils/application-builder"; import type { KubernetesCluster } from "../../../../../common/catalog-entities"; -import { getApplicationBuilder } from "../../../../../renderer/components/test-utils/get-application-builder"; +import { setupInitializingApplicationBuilder } from "../../../../test-utils/application-builder"; import navigateToWorkloadsOverviewInjectable from "../../../../../common/front-end-routing/routes/cluster/workloads/overview/navigate-to-workloads-overview.injectable"; import React from "react"; @@ -18,9 +18,9 @@ describe("disable workloads overview details when cluster is not relevant", () = (cluster: KubernetesCluster) => Promise >; - beforeEach(async () => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { builder.setEnvironmentToClusterFrame(); isEnabledForClusterMock = asyncFn(); @@ -57,10 +57,6 @@ describe("disable workloads overview details when cluster is not relevant", () = builder.extensions.enable(testExtension); }); - afterEach(() => { - builder.quit(); - }); - describe("given not yet known if extension should be enabled for the cluster", () => { it("renders", () => { expect(rendered.baseElement).toMatchSnapshot(); diff --git a/src/features/cluster/workloads/overview/extension-api/order-of-workload-overview-details.test.tsx b/src/features/cluster/workloads/overview/extension-api/order-of-workload-overview-details.test.tsx index 70bcb6204e..e7781cd566 100644 --- a/src/features/cluster/workloads/overview/extension-api/order-of-workload-overview-details.test.tsx +++ b/src/features/cluster/workloads/overview/extension-api/order-of-workload-overview-details.test.tsx @@ -3,8 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ 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 { ApplicationBuilder } from "../../../../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../../../../test-utils/application-builder"; 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"; @@ -15,9 +15,9 @@ describe("order of workload overview details", () => { let rendered: RenderResult; let builder: ApplicationBuilder; - beforeEach(async () => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { builder.beforeWindowStart((windowDi) => { windowDi.unoverride(getRandomIdInjectable); windowDi.permitSideEffects(getRandomIdInjectable); @@ -80,10 +80,6 @@ describe("order of workload overview details", () => { builder.extensions.enable(testExtension); }); - afterEach(() => { - builder.quit(); - }); - it("shows items in correct order", () => { const actual = rendered.queryAllByTestId("workload-overview-detail").map(x => x.id); diff --git a/src/features/cluster/workloads/overview/extension-api/reactively-hide-workloads-overview-details-item.test.tsx b/src/features/cluster/workloads/overview/extension-api/reactively-hide-workloads-overview-details-item.test.tsx index ac62c021fc..359ab47005 100644 --- a/src/features/cluster/workloads/overview/extension-api/reactively-hide-workloads-overview-details-item.test.tsx +++ b/src/features/cluster/workloads/overview/extension-api/reactively-hide-workloads-overview-details-item.test.tsx @@ -7,17 +7,17 @@ import type { IObservableValue } from "mobx"; import { computed, observable, runInAction } from "mobx"; 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 type { ApplicationBuilder } from "../../../../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../../../../test-utils/application-builder"; describe("reactively hide workloads overview details item", () => { let builder: ApplicationBuilder; let rendered: RenderResult; let someObservable: IObservableValue; - beforeEach(async () => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { builder.setEnvironmentToClusterFrame(); someObservable = observable.box(false); @@ -54,10 +54,6 @@ describe("reactively hide workloads overview details item", () => { builder.extensions.enable(testExtension); }); - afterEach(() => { - builder.quit(); - }); - it("does not show the workload overview detail item", () => { const actual = rendered.queryByTestId("some-workload-overview-detail-item"); diff --git a/src/features/command-pallet/keyboard-shortcuts.test.tsx b/src/features/command-pallet/keyboard-shortcuts.test.tsx index 5419e98f69..188ed4e449 100644 --- a/src/features/command-pallet/keyboard-shortcuts.test.tsx +++ b/src/features/command-pallet/keyboard-shortcuts.test.tsx @@ -6,19 +6,13 @@ import type { RenderResult } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import platformInjectable from "../../common/vars/platform.injectable"; -import { type ApplicationBuilder, getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import { type ApplicationBuilder, setupInitializingApplicationBuilder } from "../test-utils/application-builder"; describe("Command Pallet: keyboard shortcut tests", () => { let builder: ApplicationBuilder; let rendered: RenderResult; - beforeEach(async () => { - builder = getApplicationBuilder(); - }); - - afterEach(() => { - builder.quit(); - }); + setupInitializingApplicationBuilder(b => builder = b); describe("when on macOS", () => { beforeEach(async () => { diff --git a/src/features/extension-special-characters-in-page-registrations.test.tsx b/src/features/extension-special-characters-in-page-registrations.test.tsx index 756bf8249c..7b6cf691da 100644 --- a/src/features/extension-special-characters-in-page-registrations.test.tsx +++ b/src/features/extension-special-characters-in-page-registrations.test.tsx @@ -5,8 +5,8 @@ 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 { ApplicationBuilder } from "./test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "./test-utils/application-builder"; import type { DiContainer } from "@ogre-tools/injectable"; import type { FakeExtensionOptions } from "../renderer/components/test-utils/get-extension-fake"; @@ -15,9 +15,9 @@ describe("extension special characters in page registrations", () => { let rendered: RenderResult; let windowDi: DiContainer; - beforeEach(async () => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { rendered = await builder.render(); builder.extensions.enable(extensionWithPagesHavingSpecialCharacters); @@ -25,10 +25,6 @@ describe("extension special characters in page registrations", () => { windowDi = builder.applicationWindow.only.di; }); - afterEach(() => { - builder.quit(); - }); - it("renders", () => { expect(rendered.container).toMatchSnapshot(); }); diff --git a/src/features/extensions/navigation-using-application-menu.test.ts b/src/features/extensions/navigation-using-application-menu.test.ts index 8e7d67c42d..749e84e69f 100644 --- a/src/features/extensions/navigation-using-application-menu.test.ts +++ b/src/features/extensions/navigation-using-application-menu.test.ts @@ -4,8 +4,8 @@ */ 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 { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import focusWindowInjectable from "../../renderer/navigation/focus-window.injectable"; // TODO: Make components free of side effects by making them deterministic @@ -16,9 +16,9 @@ describe("extensions - navigation using application menu", () => { let rendered: RenderResult; let focusWindowMock: jest.Mock; - beforeEach(async () => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { builder.beforeWindowStart((windowDi) => { focusWindowMock = jest.fn(); @@ -28,10 +28,6 @@ describe("extensions - navigation using application menu", () => { rendered = await builder.render(); }); - afterEach(() => { - builder.quit(); - }); - it("renders", () => { expect(rendered.container).toMatchSnapshot(); }); diff --git a/src/features/helm-charts/add-custom-helm-repository-in-preferences.test.ts b/src/features/helm-charts/add-custom-helm-repository-in-preferences.test.ts index 451b6228bd..af60dac99a 100644 --- a/src/features/helm-charts/add-custom-helm-repository-in-preferences.test.ts +++ b/src/features/helm-charts/add-custom-helm-repository-in-preferences.test.ts @@ -4,8 +4,8 @@ */ import type { RenderResult } from "@testing-library/react"; import { fireEvent } 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 { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; import type { ExecFile } from "../../common/fs/exec-file.injectable"; @@ -28,11 +28,9 @@ describe("add custom helm repository in preferences", () => { let execFileMock: AsyncFnMock; let getActiveHelmRepositoriesMock: AsyncFnMock<() => Promise>>; + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { - jest.useFakeTimers(); - - builder = getApplicationBuilder(); - testUsingFakeTime("2021-01-01 12:00:00"); execFileMock = asyncFn(); @@ -58,10 +56,6 @@ describe("add custom helm repository in preferences", () => { rendered = await builder.render(); }); - afterEach(() => { - builder.quit(); - }); - describe("when navigating to preferences containing helm repositories", () => { beforeEach(async () => { builder.preferences.navigate(); diff --git a/src/features/helm-charts/add-helm-repository-from-list-in-preferences.test.ts b/src/features/helm-charts/add-helm-repository-from-list-in-preferences.test.ts index 07bb53b420..d632b0995b 100644 --- a/src/features/helm-charts/add-helm-repository-from-list-in-preferences.test.ts +++ b/src/features/helm-charts/add-helm-repository-from-list-in-preferences.test.ts @@ -3,8 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ 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 { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; import type { ExecFile } from "../../common/fs/exec-file.injectable"; @@ -26,9 +26,9 @@ describe("add helm repository from list in preferences", () => { let getActiveHelmRepositoriesMock: AsyncFnMock<() => Promise>>; let callForPublicHelmRepositoriesMock: AsyncFnMock<() => Promise>; - beforeEach(async () => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { execFileMock = asyncFn(); getActiveHelmRepositoriesMock = asyncFn(); callForPublicHelmRepositoriesMock = asyncFn(); @@ -50,10 +50,6 @@ describe("add helm repository from list in preferences", () => { rendered = await builder.render(); }); - afterEach(() => { - builder.quit(); - }); - describe("when navigating to preferences containing helm repositories", () => { beforeEach(() => { builder.preferences.navigate(); diff --git a/src/features/helm-charts/installing-chart/installing-helm-chart-from-new-tab.test.ts b/src/features/helm-charts/installing-chart/installing-helm-chart-from-new-tab.test.ts index 112d07d2cb..c0b4ef4311 100644 --- a/src/features/helm-charts/installing-chart/installing-helm-chart-from-new-tab.test.ts +++ b/src/features/helm-charts/installing-chart/installing-helm-chart-from-new-tab.test.ts @@ -6,8 +6,8 @@ import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; import type { RenderResult } from "@testing-library/react"; import { fireEvent } 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 { ApplicationBuilder } from "../../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../../test-utils/application-builder"; import { HelmChart } from "../../../common/k8s-api/endpoints/helm-charts.api"; import getRandomInstallChartTabIdInjectable from "../../../renderer/components/dock/install-chart/get-random-install-chart-tab-id.injectable"; import type { RequestCreateHelmRelease } from "../../../common/k8s-api/endpoints/helm-releases.api/request-create.injectable"; @@ -38,9 +38,9 @@ describe("installing helm chart from new tab", () => { let requestHelmChartValuesMock: AsyncFnMock; let requestCreateHelmReleaseMock: AsyncFnMock; - beforeEach(() => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(() => { builder.setEnvironmentToClusterFrame(); requestDetailedHelmReleaseMock = asyncFn(); @@ -71,10 +71,6 @@ describe("installing helm chart from new tab", () => { builder.namespaces.add("some-other-namespace"); }); - afterEach(() => { - builder.quit(); - }); - describe("given tab for installing chart was not previously opened and application is started", () => { let rendered: RenderResult; let windowDi: DiContainer; diff --git a/src/features/helm-charts/installing-chart/installing-helm-chart-from-previously-opened-tab.test.ts b/src/features/helm-charts/installing-chart/installing-helm-chart-from-previously-opened-tab.test.ts index e890e8d557..c61c27e62f 100644 --- a/src/features/helm-charts/installing-chart/installing-helm-chart-from-previously-opened-tab.test.ts +++ b/src/features/helm-charts/installing-chart/installing-helm-chart-from-previously-opened-tab.test.ts @@ -5,8 +5,8 @@ import type { AsyncFnMock } from "@async-fn/jest"; 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 type { ApplicationBuilder } from "../../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../../test-utils/application-builder"; import { HelmChart } from "../../../common/k8s-api/endpoints/helm-charts.api"; import getRandomInstallChartTabIdInjectable from "../../../renderer/components/dock/install-chart/get-random-install-chart-tab-id.injectable"; import writeJsonFileInjectable from "../../../common/fs/write-json-file.injectable"; @@ -23,9 +23,9 @@ describe("installing helm chart from previously opened tab", () => { let requestHelmChartVersionsMock: AsyncFnMock; let requestHelmChartValuesMock: AsyncFnMock; - beforeEach(() => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(() => { builder.setEnvironmentToClusterFrame(); requestHelmChartVersionsMock = asyncFn(); @@ -48,10 +48,6 @@ describe("installing helm chart from previously opened tab", () => { }); }); - afterEach(() => { - builder.quit(); - }); - describe("given tab for installing chart was previously opened, when application is started", () => { let rendered: RenderResult; diff --git a/src/features/helm-charts/installing-chart/opening-dock-tab-for-installing-helm-chart.test.ts b/src/features/helm-charts/installing-chart/opening-dock-tab-for-installing-helm-chart.test.ts index 9de86c8ed9..ee7a93086a 100644 --- a/src/features/helm-charts/installing-chart/opening-dock-tab-for-installing-helm-chart.test.ts +++ b/src/features/helm-charts/installing-chart/opening-dock-tab-for-installing-helm-chart.test.ts @@ -6,8 +6,8 @@ import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; import type { RenderResult } from "@testing-library/react"; import { fireEvent } 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 { ApplicationBuilder } from "../../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../../test-utils/application-builder"; import { HelmChart } from "../../../common/k8s-api/endpoints/helm-charts.api"; import getRandomInstallChartTabIdInjectable from "../../../renderer/components/dock/install-chart/get-random-install-chart-tab-id.injectable"; import requestCreateHelmReleaseInjectable from "../../../common/k8s-api/endpoints/helm-releases.api/request-create.injectable"; @@ -30,9 +30,9 @@ describe("opening dock tab for installing helm chart", () => { let requestHelmChartReadmeMock: AsyncFnMock; let requestHelmChartValuesMock: jest.Mock; - beforeEach(() => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(() => { requestHelmChartsMock = asyncFn(); requestHelmChartVersionsMock = asyncFn(); requestHelmChartReadmeMock = asyncFn(); @@ -56,10 +56,6 @@ describe("opening dock tab for installing helm chart", () => { builder.setEnvironmentToClusterFrame(); }); - afterEach(() => { - builder.quit(); - }); - describe("given application is started, when navigating to helm charts", () => { let rendered: RenderResult; diff --git a/src/features/helm-charts/listing-active-helm-repositories-in-preferences.test.ts b/src/features/helm-charts/listing-active-helm-repositories-in-preferences.test.ts index 9b893ac287..5332799ec5 100644 --- a/src/features/helm-charts/listing-active-helm-repositories-in-preferences.test.ts +++ b/src/features/helm-charts/listing-active-helm-repositories-in-preferences.test.ts @@ -3,8 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ 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 { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import type { ReadYamlFile } from "../../common/fs/read-yaml-file.injectable"; import readYamlFileInjectable from "../../common/fs/read-yaml-file.injectable"; import type { AsyncFnMock } from "@async-fn/jest"; @@ -27,9 +27,9 @@ describe("listing active helm repositories in preferences", () => { let loggerStub: Logger; let showErrorNotificationMock: jest.Mock; - beforeEach(async () => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { readYamlFileMock = asyncFn(); execFileMock = asyncFn(); showErrorNotificationMock = jest.fn(); @@ -57,10 +57,6 @@ describe("listing active helm repositories in preferences", () => { rendered = await builder.render(); }); - afterEach(() => { - builder.quit(); - }); - describe("when navigating to preferences containing helm repositories", () => { beforeEach(async () => { builder.preferences.navigate(); diff --git a/src/features/helm-charts/remove-helm-repository-from-list-of-active-repository-in-preferences.test.ts b/src/features/helm-charts/remove-helm-repository-from-list-of-active-repository-in-preferences.test.ts index ce1de119e0..f795d7b140 100644 --- a/src/features/helm-charts/remove-helm-repository-from-list-of-active-repository-in-preferences.test.ts +++ b/src/features/helm-charts/remove-helm-repository-from-list-of-active-repository-in-preferences.test.ts @@ -4,8 +4,8 @@ */ import type { RenderResult } from "@testing-library/react"; import { fireEvent } 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 { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; import type { ExecFile } from "../../common/fs/exec-file.injectable"; @@ -22,9 +22,9 @@ describe("remove helm repository from list of active repositories in preferences let getActiveHelmRepositoriesMock: AsyncFnMock<() => Promise>>; let execFileMock: AsyncFnMock; - beforeEach(async () => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { execFileMock = asyncFn(); getActiveHelmRepositoriesMock = asyncFn(); @@ -41,10 +41,6 @@ describe("remove helm repository from list of active repositories in preferences rendered = await builder.render(); }); - afterEach(() => { - builder.quit(); - }); - describe("when navigating to preferences containing helm repositories", () => { beforeEach(async () => { builder.preferences.navigate(); diff --git a/src/features/helm-charts/upgrade-chart/upgrade-chart-new-tab.test.ts b/src/features/helm-charts/upgrade-chart/upgrade-chart-new-tab.test.ts index f1b7ada401..d56154b9f0 100644 --- a/src/features/helm-charts/upgrade-chart/upgrade-chart-new-tab.test.ts +++ b/src/features/helm-charts/upgrade-chart/upgrade-chart-new-tab.test.ts @@ -19,8 +19,8 @@ import type { RequestHelmReleases } from "../../../common/k8s-api/endpoints/helm import requestHelmReleasesInjectable from "../../../common/k8s-api/endpoints/helm-releases.api/request-releases.injectable"; import { advanceFakeTime, testUsingFakeTime } from "../../../common/test-utils/use-fake-time"; import dockStoreInjectable from "../../../renderer/components/dock/dock/store.injectable"; -import type { ApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; -import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; +import type { ApplicationBuilder } from "../../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../../test-utils/application-builder"; describe("New Upgrade Helm Chart Dock Tab", () => { let builder: ApplicationBuilder; @@ -31,8 +31,9 @@ describe("New Upgrade Helm Chart Dock Tab", () => { let requestHelmChartVersionsMock: AsyncFnMock; let navigateToHelmReleases: NavigateToHelmReleases; + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { - builder = getApplicationBuilder(); builder.setEnvironmentToClusterFrame(); builder.beforeWindowStart((windowDi) => { @@ -64,10 +65,6 @@ describe("New Upgrade Helm Chart Dock Tab", () => { dockStore.closeTab("terminal"); }); - afterEach(() => { - builder.quit(); - }); - describe("given a namespace is selected", () => { beforeEach(() => { builder.namespaces.select("my-second-namespace"); diff --git a/src/features/helm-releases/showing-details-for-helm-release.test.ts b/src/features/helm-releases/showing-details-for-helm-release.test.ts index 517c3af1bb..c40cfdce4e 100644 --- a/src/features/helm-releases/showing-details-for-helm-release.test.ts +++ b/src/features/helm-releases/showing-details-for-helm-release.test.ts @@ -2,8 +2,8 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; -import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import type { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import navigateToHelmReleasesInjectable from "../../common/front-end-routing/routes/cluster/helm/releases/navigate-to-helm-releases.injectable"; import type { RenderResult } from "@testing-library/react"; import { fireEvent } from "@testing-library/react"; @@ -44,11 +44,11 @@ describe("showing details for helm release", () => { let showSuccessNotificationMock: jest.Mock; let showCheckedErrorNotificationMock: jest.Mock; + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(() => { testUsingFakeTime("2015-10-21T07:28:00Z"); - builder = getApplicationBuilder(); - builder.setEnvironmentToClusterFrame(); requestHelmReleasesMock = asyncFn(); @@ -83,10 +83,6 @@ describe("showing details for helm release", () => { builder.namespaces.select("some-other-namespace"); }); - afterEach(() => { - builder.quit(); - }); - describe("given application is started", () => { let rendered: RenderResult; diff --git a/src/features/navigate-to-extension-page.test.tsx b/src/features/navigate-to-extension-page.test.tsx index f88f02b5b0..0bfdf4ea2c 100644 --- a/src/features/navigate-to-extension-page.test.tsx +++ b/src/features/navigate-to-extension-page.test.tsx @@ -9,8 +9,8 @@ import isEmpty from "lodash/isEmpty"; import queryParametersInjectable from "../renderer/routes/query-parameters.injectable"; import currentPathInjectable from "../renderer/routes/current-path.injectable"; import type { IComputedValue } from "mobx"; -import type { ApplicationBuilder } from "../renderer/components/test-utils/get-application-builder"; -import { getApplicationBuilder } from "../renderer/components/test-utils/get-application-builder"; +import type { ApplicationBuilder } from "./test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "./test-utils/application-builder"; import type { FakeExtensionOptions } from "../renderer/components/test-utils/get-extension-fake"; import type { LensRendererExtension } from "../extensions/lens-renderer-extension"; @@ -21,9 +21,9 @@ describe("navigate to extension page", () => { let currentPath: IComputedValue; let builder: ApplicationBuilder; - beforeEach(async () => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { builder.extensions.enable(extensionWithPagesHavingParameters); rendered = await builder.render(); @@ -37,10 +37,6 @@ describe("navigate to extension page", () => { currentPath = windowDi.inject(currentPathInjectable); }); - afterEach(() => { - builder.quit(); - }); - it("renders", () => { expect(rendered.container).toMatchSnapshot(); }); diff --git a/src/features/navigating-between-routes.test.tsx b/src/features/navigating-between-routes.test.tsx index 6fe047da22..c908c67c65 100644 --- a/src/features/navigating-between-routes.test.tsx +++ b/src/features/navigating-between-routes.test.tsx @@ -11,8 +11,8 @@ import { routeSpecificComponentInjectionToken } from "../renderer/routes/route-s import { observer } from "mobx-react"; import type { Route } from "../common/front-end-routing/front-end-route-injection-token"; import { frontEndRouteInjectionToken } from "../common/front-end-routing/front-end-route-injection-token"; -import type { ApplicationBuilder } from "../renderer/components/test-utils/get-application-builder"; -import { getApplicationBuilder } from "../renderer/components/test-utils/get-application-builder"; +import type { ApplicationBuilder } from "./test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "./test-utils/application-builder"; import currentRouteInjectable from "../renderer/routes/current-route.injectable"; import currentPathInjectable from "../renderer/routes/current-path.injectable"; import queryParametersInjectable from "../renderer/routes/query-parameters.injectable"; @@ -23,13 +23,7 @@ describe("navigating between routes", () => { let rendered: RenderResult; let builder: ApplicationBuilder; - beforeEach(async () => { - builder = getApplicationBuilder(); - }); - - afterEach(() => { - builder.quit(); - }); + setupInitializingApplicationBuilder(b => builder = b); describe("given route without path parameters", () => { let windowDi: DiContainer; diff --git a/src/features/pod-logs/download-logs.test.tsx b/src/features/pod-logs/download-logs.test.tsx index d0c17b6536..bd69616991 100644 --- a/src/features/pod-logs/download-logs.test.tsx +++ b/src/features/pod-logs/download-logs.test.tsx @@ -8,8 +8,8 @@ import { act, waitFor } from "@testing-library/react"; import getPodByIdInjectable from "../../renderer/components/+workloads-pods/get-pod-by-id.injectable"; import getPodsByOwnerIdInjectable from "../../renderer/components/+workloads-pods/get-pods-by-owner-id.injectable"; import openSaveFileDialogInjectable from "../../renderer/utils/save-file.injectable"; -import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; -import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import type { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import dockStoreInjectable from "../../renderer/components/dock/dock/store.injectable"; import areLogsPresentInjectable from "../../renderer/components/dock/logs/are-logs-present.injectable"; import type { CallForLogs } from "../../renderer/components/dock/logs/call-for-logs.injectable"; @@ -46,11 +46,11 @@ describe("download logs options in logs dock tab", () => { image: "docker.io/prom/node-exporter:v1.0.0-rc.0", }; + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(() => { const selectedPod = dockerPod; - builder = getApplicationBuilder(); - builder.setEnvironmentToClusterFrame(); callForLogsMock = jest.fn(); @@ -95,10 +95,6 @@ describe("download logs options in logs dock tab", () => { }); }); - afterEach(() => { - builder.quit(); - }); - describe("opening pod logs", () => { beforeEach(async () => { rendered = await builder.render(); diff --git a/src/features/preferences/closing-preferences.test.tsx b/src/features/preferences/closing-preferences.test.tsx index aa35c2456e..9b9598b3d3 100644 --- a/src/features/preferences/closing-preferences.test.tsx +++ b/src/features/preferences/closing-preferences.test.tsx @@ -5,8 +5,8 @@ import type { DiContainer } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable"; 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 { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import currentPathInjectable from "../../renderer/routes/current-path.injectable"; import { frontEndRouteInjectionToken } from "../../common/front-end-routing/front-end-route-injection-token"; import { computed, runInAction } from "mobx"; @@ -21,9 +21,9 @@ import historyInjectable from "../../renderer/navigation/history.injectable"; describe("preferences - closing-preferences", () => { let builder: ApplicationBuilder; - beforeEach(() => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(() => { builder.beforeWindowStart((windowDi) => { runInAction(() => { windowDi.register( @@ -47,10 +47,6 @@ describe("preferences - closing-preferences", () => { }); }); - afterEach(() => { - builder.quit(); - }); - describe("given already in a page", () => { let rendered: RenderResult; let windowDi: DiContainer; diff --git a/src/features/preferences/extension-adding-preference-tabs.test.tsx b/src/features/preferences/extension-adding-preference-tabs.test.tsx index 8d015c9f2d..de29638c94 100644 --- a/src/features/preferences/extension-adding-preference-tabs.test.tsx +++ b/src/features/preferences/extension-adding-preference-tabs.test.tsx @@ -5,8 +5,8 @@ import type { RenderResult } from "@testing-library/react"; 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 type { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import type { Discover } from "../../renderer/components/test-utils/discovery-of-html-elements"; import { discoverFor } from "../../renderer/components/test-utils/discovery-of-html-elements"; import React from "react"; @@ -14,13 +14,7 @@ import React from "react"; describe("preferences: extension adding preference tabs", () => { let builder: ApplicationBuilder; - beforeEach(() => { - builder = getApplicationBuilder(); - }); - - afterEach(() => { - builder.quit(); - }); + setupInitializingApplicationBuilder(b => builder = b); describe("given in preferences, when extension with preference tabs is enabled", () => { let rendered: RenderResult; diff --git a/src/features/preferences/hiding-of-empty-branches.test.tsx b/src/features/preferences/hiding-of-empty-branches.test.tsx index 0bc2d67d24..c560011f61 100644 --- a/src/features/preferences/hiding-of-empty-branches.test.tsx +++ b/src/features/preferences/hiding-of-empty-branches.test.tsx @@ -7,8 +7,8 @@ import type { DiContainer } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable"; import type { RenderResult } from "@testing-library/react"; import { 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 type { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import { preferenceItemInjectionToken } from "./renderer/preference-items/preference-item-injection-token"; import type { Discover } from "../../renderer/components/test-utils/discovery-of-html-elements"; import { discoverFor } from "../../renderer/components/test-utils/discovery-of-html-elements"; @@ -19,16 +19,14 @@ describe("preferences - hiding-of-empty-branches, given in preferences page", () let windowDi: DiContainer; let discover: Discover; + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { - builder = getApplicationBuilder(); - rendered = await builder.render(); - discover = discoverFor(() => rendered); + windowDi = builder.applicationWindow.only.di; builder.preferences.navigate(); - - windowDi = builder.applicationWindow.only.di; }); describe("given tab group and empty tabs", () => { diff --git a/src/features/preferences/navigation-to-application-preferences.test.tsx b/src/features/preferences/navigation-to-application-preferences.test.tsx index b13de1d93d..1d9ea732fb 100644 --- a/src/features/preferences/navigation-to-application-preferences.test.tsx +++ b/src/features/preferences/navigation-to-application-preferences.test.tsx @@ -4,8 +4,8 @@ */ import React from "react"; 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 { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import navigateToProxyPreferencesInjectable from "./common/navigate-to-proxy-preferences.injectable"; import type { Discover } from "../../renderer/components/test-utils/discovery-of-html-elements"; import { discoverFor } from "../../renderer/components/test-utils/discovery-of-html-elements"; @@ -14,13 +14,7 @@ import type { FakeExtensionOptions } from "../../renderer/components/test-utils/ describe("preferences - navigation to application preferences", () => { let builder: ApplicationBuilder; - beforeEach(() => { - builder = getApplicationBuilder(); - }); - - afterEach(() => { - builder.quit(); - }); + setupInitializingApplicationBuilder(b => builder = b); describe("given in preferences, when rendered", () => { let rendered: RenderResult; diff --git a/src/features/preferences/navigation-to-editor-preferences.test.ts b/src/features/preferences/navigation-to-editor-preferences.test.ts index d478fdd5d0..38b9eeda46 100644 --- a/src/features/preferences/navigation-to-editor-preferences.test.ts +++ b/src/features/preferences/navigation-to-editor-preferences.test.ts @@ -3,8 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ 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 { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import type { Discover } from "../../renderer/components/test-utils/discovery-of-html-elements"; import { discoverFor } from "../../renderer/components/test-utils/discovery-of-html-elements"; @@ -12,13 +12,7 @@ describe("preferences - navigation to editor preferences", () => { let builder: ApplicationBuilder; let discover: Discover; - beforeEach(() => { - builder = getApplicationBuilder(); - }); - - afterEach(() => { - builder.quit(); - }); + setupInitializingApplicationBuilder(b => builder = b); describe("given in preferences, when rendered", () => { let rendered: RenderResult; diff --git a/src/features/preferences/navigation-to-extension-specific-preferences.test.tsx b/src/features/preferences/navigation-to-extension-specific-preferences.test.tsx index 17a03a7a74..8a3b5adc8d 100644 --- a/src/features/preferences/navigation-to-extension-specific-preferences.test.tsx +++ b/src/features/preferences/navigation-to-extension-specific-preferences.test.tsx @@ -3,8 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ 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 { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import React from "react"; import "@testing-library/jest-dom/extend-expect"; import type { FakeExtensionOptions } from "../../renderer/components/test-utils/get-extension-fake"; @@ -15,13 +15,7 @@ import logErrorInjectable from "../../common/log-error.injectable"; describe("preferences - navigation to extension specific preferences", () => { let builder: ApplicationBuilder; - beforeEach(() => { - builder = getApplicationBuilder(); - }); - - afterEach(() => { - builder.quit(); - }); + setupInitializingApplicationBuilder(b => builder = b); describe("given in preferences, when rendered", () => { let rendered: RenderResult; diff --git a/src/features/preferences/navigation-to-kubernetes-preferences.test.ts b/src/features/preferences/navigation-to-kubernetes-preferences.test.ts index d02bc80532..b317521aac 100644 --- a/src/features/preferences/navigation-to-kubernetes-preferences.test.ts +++ b/src/features/preferences/navigation-to-kubernetes-preferences.test.ts @@ -3,8 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ 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 { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import requestPublicHelmRepositoriesInjectable from "../helm-charts/child-features/preferences/renderer/adding-of-public-helm-repository/public-helm-repositories/request-public-helm-repositories.injectable"; import getActiveHelmRepositoriesInjectable from "../../main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories.injectable"; import type { Discover } from "../../renderer/components/test-utils/discovery-of-html-elements"; @@ -13,13 +13,7 @@ import { discoverFor } from "../../renderer/components/test-utils/discovery-of-h describe("preferences - navigation to kubernetes preferences", () => { let builder: ApplicationBuilder; - beforeEach(() => { - builder = getApplicationBuilder(); - }); - - afterEach(() => { - builder.quit(); - }); + setupInitializingApplicationBuilder(b => builder = b); describe("given in preferences, when rendered", () => { let rendered: RenderResult; diff --git a/src/features/preferences/navigation-to-proxy-preferences.test.ts b/src/features/preferences/navigation-to-proxy-preferences.test.ts index 3edec4b9fb..682102566d 100644 --- a/src/features/preferences/navigation-to-proxy-preferences.test.ts +++ b/src/features/preferences/navigation-to-proxy-preferences.test.ts @@ -3,21 +3,15 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ 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 { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import type { Discover } from "../../renderer/components/test-utils/discovery-of-html-elements"; import { discoverFor } from "../../renderer/components/test-utils/discovery-of-html-elements"; describe("preferences - navigation to proxy preferences", () => { let builder: ApplicationBuilder; - beforeEach(() => { - builder = getApplicationBuilder(); - }); - - afterEach(() => { - builder.quit(); - }); + setupInitializingApplicationBuilder(b => builder = b); describe("given in preferences, when rendered", () => { let rendered: RenderResult; diff --git a/src/features/preferences/navigation-to-telemetry-preferences.test.tsx b/src/features/preferences/navigation-to-telemetry-preferences.test.tsx index 2e18785b0c..14fcb99519 100644 --- a/src/features/preferences/navigation-to-telemetry-preferences.test.tsx +++ b/src/features/preferences/navigation-to-telemetry-preferences.test.tsx @@ -4,8 +4,8 @@ */ 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 { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import navigateToTelemetryPreferencesInjectable from "./common/navigate-to-telemetry-preferences.injectable"; import sentryDataSourceNameInjectable from "../../common/vars/sentry-dsn-url.injectable"; import type { FakeExtensionOptions } from "../../renderer/components/test-utils/get-extension-fake"; @@ -15,13 +15,7 @@ import { discoverFor } from "../../renderer/components/test-utils/discovery-of-h describe("preferences - navigation to telemetry preferences", () => { let builder: ApplicationBuilder; - beforeEach(() => { - builder = getApplicationBuilder(); - }); - - afterEach(() => { - builder.quit(); - }); + setupInitializingApplicationBuilder(b => builder = b); describe("given in preferences, when rendered", () => { let rendered: RenderResult; diff --git a/src/features/preferences/navigation-to-terminal-preferences.test.ts b/src/features/preferences/navigation-to-terminal-preferences.test.ts index 5d065555dc..1c3b396038 100644 --- a/src/features/preferences/navigation-to-terminal-preferences.test.ts +++ b/src/features/preferences/navigation-to-terminal-preferences.test.ts @@ -3,21 +3,15 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ 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 { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import type { Discover } from "../../renderer/components/test-utils/discovery-of-html-elements"; import { discoverFor } from "../../renderer/components/test-utils/discovery-of-html-elements"; describe("preferences - navigation to terminal preferences", () => { let builder: ApplicationBuilder; - beforeEach(() => { - builder = getApplicationBuilder(); - }); - - afterEach(() => { - builder.quit(); - }); + setupInitializingApplicationBuilder(b => builder = b); describe("given in preferences, when rendered", () => { let rendered: RenderResult; diff --git a/src/features/preferences/navigation-using-application-menu.test.ts b/src/features/preferences/navigation-using-application-menu.test.ts index c627dc27a6..ea8e67d08e 100644 --- a/src/features/preferences/navigation-using-application-menu.test.ts +++ b/src/features/preferences/navigation-using-application-menu.test.ts @@ -4,8 +4,8 @@ */ 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 { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import type { Discover } from "../../renderer/components/test-utils/discovery-of-html-elements"; import { discoverFor } from "../../renderer/components/test-utils/discovery-of-html-elements"; @@ -13,18 +13,14 @@ describe("preferences - navigation using application menu", () => { let builder: ApplicationBuilder; let rendered: RenderResult; let discover: Discover; + + setupInitializingApplicationBuilder(b => builder = b); beforeEach(async () => { - builder = getApplicationBuilder(); - rendered = await builder.render(); discover = discoverFor(() => rendered); }); - afterEach(() => { - builder.quit(); - }); - it("renders", () => { expect(rendered.container).toMatchSnapshot(); }); diff --git a/src/features/preferences/navigation-using-tray.test.ts b/src/features/preferences/navigation-using-tray.test.ts index 2853ea4c93..9e9a131376 100644 --- a/src/features/preferences/navigation-using-tray.test.ts +++ b/src/features/preferences/navigation-using-tray.test.ts @@ -3,8 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ 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 { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import type { Discover } from "../../renderer/components/test-utils/discovery-of-html-elements"; import { discoverFor } from "../../renderer/components/test-utils/discovery-of-html-elements"; @@ -13,17 +13,13 @@ describe("show-about-using-tray", () => { let rendered: RenderResult; let discover: Discover; - beforeEach(async () => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { rendered = await builder.render(); discover = discoverFor(() => rendered); }); - afterEach(() => { - builder.quit(); - }); - it("renders", () => { expect(rendered.baseElement).toMatchSnapshot(); }); diff --git a/src/features/preferences/urls-of-legacy-extensions.test.tsx b/src/features/preferences/urls-of-legacy-extensions.test.tsx index d58bd52865..71030f9b87 100644 --- a/src/features/preferences/urls-of-legacy-extensions.test.tsx +++ b/src/features/preferences/urls-of-legacy-extensions.test.tsx @@ -3,8 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ 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 { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import type { Discover } from "../../renderer/components/test-utils/discovery-of-html-elements"; import { discoverFor } from "../../renderer/components/test-utils/discovery-of-html-elements"; import React from "react"; @@ -14,13 +14,7 @@ import navigateInjectable from "../../renderer/navigation/navigate.injectable"; describe("preferences: URLs of legacy extensions", () => { let builder: ApplicationBuilder; - beforeEach(() => { - builder = getApplicationBuilder(); - }); - - afterEach(() => { - builder.quit(); - }); + setupInitializingApplicationBuilder(b => builder = b); describe("given extension with custom preferences and a custom preference tab", () => { let rendered: RenderResult; diff --git a/src/features/quitting-and-restarting-the-app/opening-application-window-using-tray.test.ts b/src/features/quitting-and-restarting-the-app/opening-application-window-using-tray.test.ts index 1735c4d6d8..175d8bb037 100644 --- a/src/features/quitting-and-restarting-the-app/opening-application-window-using-tray.test.ts +++ b/src/features/quitting-and-restarting-the-app/opening-application-window-using-tray.test.ts @@ -3,8 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; -import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import type { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; import type { LensWindow } from "../../main/start-main-application/lens-window/application-window/create-lens-window.injectable"; @@ -17,8 +17,11 @@ import staticFilesDirectoryInjectable from "../../common/vars/static-files-direc import { matches } from "jest-mock-extended"; describe("opening application window using tray", () => { + let builder: ApplicationBuilder; + + setupInitializingApplicationBuilder(b => builder = b); + describe("given application has started", () => { - let builder: ApplicationBuilder; let createElectronWindowMock: jest.Mock; let expectWindowsToBeOpen: (windowIds: string[]) => void; let callForSplashWindowHtmlMock: AsyncFnMock<() => Promise>; @@ -31,8 +34,6 @@ describe("opening application window using tray", () => { focusApplicationMock = jest.fn(); - builder = getApplicationBuilder(); - builder.beforeApplicationStart((mainDi) => { mainDi.override(focusApplicationInjectable, () => focusApplicationMock); @@ -76,10 +77,6 @@ describe("opening application window using tray", () => { await builder.render(); }); - afterEach(() => { - builder.quit(); - }); - it("only the first application window is open", () => { expectWindowsToBeOpen(["first-application-window"]); }); diff --git a/src/features/quitting-and-restarting-the-app/quitting-the-app-using-application-menu.test.ts b/src/features/quitting-and-restarting-the-app/quitting-the-app-using-application-menu.test.ts index d43edfb5e6..7132eb088a 100644 --- a/src/features/quitting-and-restarting-the-app/quitting-the-app-using-application-menu.test.ts +++ b/src/features/quitting-and-restarting-the-app/quitting-the-app-using-application-menu.test.ts @@ -3,8 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; -import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import type { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import type { ClusterManager } from "../../main/cluster/manager"; import exitAppInjectable from "../../main/electron-app/features/exit-app.injectable"; import clusterManagerInjectable from "../../main/cluster/manager.injectable"; @@ -12,16 +12,17 @@ import stopServicesAndExitAppInjectable from "../../main/stop-services-and-exit- import { advanceFakeTime, testUsingFakeTime } from "../../common/test-utils/use-fake-time"; describe("quitting the app using application menu", () => { + let builder: ApplicationBuilder; + + setupInitializingApplicationBuilder(b => builder = b); + describe("given application has started", () => { - let builder: ApplicationBuilder; let clusterManagerStub: ClusterManager; let exitAppMock: jest.Mock; beforeEach(async () => { testUsingFakeTime("2015-10-21T07:28:00Z"); - builder = getApplicationBuilder(); - builder.beforeApplicationStart( (mainDi) => { mainDi.unoverride(stopServicesAndExitAppInjectable); @@ -37,10 +38,6 @@ describe("quitting the app using application menu", () => { await builder.render(); }); - afterEach(() => { - builder.quit(); - }); - it("first application window is open", () => { const windows = builder.applicationWindow.getAll(); diff --git a/src/features/resolve-system-proxy/resolve-system-proxy.test.ts b/src/features/resolve-system-proxy/resolve-system-proxy.test.ts index 64e3108ec0..8194f205e1 100644 --- a/src/features/resolve-system-proxy/resolve-system-proxy.test.ts +++ b/src/features/resolve-system-proxy/resolve-system-proxy.test.ts @@ -4,8 +4,8 @@ */ import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; -import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; -import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import type { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import type { ResolveSystemProxy } from "../../common/utils/resolve-system-proxy/resolve-system-proxy-injection-token"; import { resolveSystemProxyInjectionToken } from "../../common/utils/resolve-system-proxy/resolve-system-proxy-injection-token"; import resolveSystemProxyFromElectronInjectable from "../../main/utils/resolve-system-proxy/resolve-system-proxy-from-electron.injectable"; @@ -16,9 +16,9 @@ describe("resolve-system-proxy", () => { let actualPromise: Promise; let resolveSystemProxyFromElectronMock: AsyncFnMock; - beforeEach(async () => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { resolveSystemProxyFromElectronMock = asyncFn(); builder.beforeApplicationStart((mainDi) => { @@ -31,10 +31,6 @@ describe("resolve-system-proxy", () => { await builder.render(); }); - afterEach(() => { - builder.quit(); - }); - describe("given in main, when called with URL", () => { beforeEach(async () => { const resolveSystemProxyInMain = builder.mainDi.inject( diff --git a/src/features/routes/extension-api/reactively-disable-global-pages.test.tsx b/src/features/routes/extension-api/reactively-disable-global-pages.test.tsx index 5772f91b3e..2cdcd57a68 100644 --- a/src/features/routes/extension-api/reactively-disable-global-pages.test.tsx +++ b/src/features/routes/extension-api/reactively-disable-global-pages.test.tsx @@ -7,8 +7,8 @@ import type { IObservableValue } from "mobx"; import { observable, runInAction, computed } from "mobx"; 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 type { ApplicationBuilder } from "../../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../../test-utils/application-builder"; describe("reactively disable global pages", () => { let builder: ApplicationBuilder; @@ -16,9 +16,9 @@ describe("reactively disable global pages", () => { let someObservable: IObservableValue; let rendererTestExtension: TestExtensionRenderer; - beforeEach(async () => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { someObservable = observable.box(false); const testExtension = { @@ -43,10 +43,6 @@ describe("reactively disable global pages", () => { rendererTestExtension = builder.extensions.get("test-extension-id").applicationWindows.only; }); - afterEach(() => { - builder.quit(); - }); - it("when navigating to the page, does not show the page", () => { rendererTestExtension.navigate(); diff --git a/src/features/status-bar/status-bar-items-originating-from-extensions.test.tsx b/src/features/status-bar/status-bar-items-originating-from-extensions.test.tsx index 164973fdd9..c7ac696112 100644 --- a/src/features/status-bar/status-bar-items-originating-from-extensions.test.tsx +++ b/src/features/status-bar/status-bar-items-originating-from-extensions.test.tsx @@ -4,8 +4,8 @@ */ 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 { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import getRandomIdInjectable from "../../common/utils/get-random-id.injectable"; import type { FakeExtensionOptions } from "../../renderer/components/test-utils/get-extension-fake"; import { computed } from "mobx"; @@ -13,19 +13,15 @@ import { computed } from "mobx"; describe("status-bar-items-originating-from-extensions", () => { let builder: ApplicationBuilder; - beforeEach(() => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(() => { builder.beforeWindowStart((windowDi) => { windowDi.unoverride(getRandomIdInjectable); windowDi.permitSideEffects(getRandomIdInjectable); }); }); - afterEach(() => { - builder.quit(); - }); - describe("when application starts", () => { let rendered: RenderResult; diff --git a/src/features/terminal/opening-terminal-tab.test.tsx b/src/features/terminal/opening-terminal-tab.test.tsx index ca4959be35..3f6fb6ce3e 100644 --- a/src/features/terminal/opening-terminal-tab.test.tsx +++ b/src/features/terminal/opening-terminal-tab.test.tsx @@ -14,8 +14,8 @@ import createKubeconfigManagerInjectable from "../../main/kubeconfig-manager/cre import type { KubeconfigManager } from "../../main/kubeconfig-manager/kubeconfig-manager"; import type { SpawnPty } from "../../main/shell-session/spawn-pty.injectable"; import spawnPtyInjectable from "../../main/shell-session/spawn-pty.injectable"; -import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; -import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import type { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import type { FindByTextWithMarkup } from "../../test-utils/findByTextWithMarkup"; import { findByTextWithMarkupFor } from "../../test-utils/findByTextWithMarkup"; @@ -25,6 +25,8 @@ describe("test for opening terminal tab within cluster frame", () => { let findByTextWithMarkup: FindByTextWithMarkup; let spawnPtyMock: jest.MockedFunction; + setupInitializingApplicationBuilder(b => builder = b); + beforeAll(() => { jest.spyOn(window, "requestAnimationFrame").mockImplementation(function IAmAMockRequestAnimationFrame(cb) { return window.setTimeout(() => cb(Date.now())); @@ -32,8 +34,6 @@ describe("test for opening terminal tab within cluster frame", () => { }); beforeEach(async () => { - builder = getApplicationBuilder(); - builder.mainDi.override(createKubeconfigManagerInjectable, () => (cluster) => { return { getPath: async () => `/some-kubeconfig-managed-path-for-${cluster.id}`, @@ -50,10 +50,6 @@ describe("test for opening terminal tab within cluster frame", () => { findByTextWithMarkup = findByTextWithMarkupFor(result); }); - afterEach(() => { - builder.quit(); - }); - describe("when new terminal tab is opened", () => { beforeEach(() => { result.getByTestId("dock-tab-for-terminal").click(); diff --git a/src/features/test-utils/application-builder.tsx b/src/features/test-utils/application-builder.tsx new file mode 100644 index 0000000000..5da3a5b624 --- /dev/null +++ b/src/features/test-utils/application-builder.tsx @@ -0,0 +1,941 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { LensRendererExtension } from "../../extensions/lens-renderer-extension"; +import rendererExtensionsInjectable from "../../extensions/renderer-extensions.injectable"; +import currentlyInClusterFrameInjectable from "../../renderer/routes/currently-in-cluster-frame.injectable"; +import type { IComputedValue, ObservableMap } from "mobx"; +import { action, computed, observable, runInAction } from "mobx"; +import React from "react"; +import { Router } from "react-router"; +import type { RenderResult } from "@testing-library/react"; +import { fireEvent, queryByText } from "@testing-library/react"; +import type { KubeApiResourceDescriptor } from "../../common/rbac"; +import { apiResourceRecord, formatKubeApiResource } from "../../common/rbac"; +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 { filter, first, join, last, map, matches } from "lodash/fp"; +import navigateToPreferencesInjectable from "../preferences/common/navigate-to-preferences.injectable"; +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 type { Cluster } from "../../common/cluster/cluster"; +import startMainApplicationInjectable from "../../main/start-main-application/start-main-application.injectable"; +import startFrameInjectable from "../../renderer/start-frame/start-frame.injectable"; +import type { NamespaceStore } from "../../renderer/components/+namespaces/store"; +import historyInjectable from "../../renderer/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 { getDiForUnitTesting as getRendererDi } from "../../renderer/getDiForUnitTesting"; +import { getDiForUnitTesting as getMainDi } from "../../main/getDiForUnitTesting"; +import { overrideChannels } from "../../test-utils/channel-fakes/override-channels"; +import assert from "assert"; +import { openMenu } from "react-select-event"; +import userEvent from "@testing-library/user-event"; +import type { Route } from "../../common/front-end-routing/front-end-route-injection-token"; +import type { NavigateToRouteOptions } from "../../common/front-end-routing/navigate-to-route-injection-token"; +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 "../../renderer/components/test-utils/renderFor"; +import { RootFrame } from "../../renderer/frames/root-frame/root-frame"; +import { ClusterFrame } from "../../renderer/frames/cluster-frame/cluster-frame"; +import hostedClusterIdInjectable from "../../renderer/cluster-frame-context/hosted-cluster-id.injectable"; +import namespaceStoreInjectable from "../../renderer/components/+namespaces/store.injectable"; +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 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 "../../renderer/components/test-utils/get-extension-fake"; +import { getExtensionFakeForMain, getExtensionFakeForRenderer } from "../../renderer/components/test-utils/get-extension-fake"; +import namespaceApiInjectable from "../../common/k8s-api/endpoints/namespace.api.injectable"; +import { Namespace } from "../../common/k8s-api/endpoints"; +import { getOverrideFsWithFakes } from "../../test-utils/override-fs-with-fakes"; +import applicationMenuItemCompositeInjectable from "../application-menu/main/application-menu-item-composite.injectable"; +import { getCompositePaths } from "../../common/utils/composite/get-composite-paths/get-composite-paths"; +import { discoverFor } from "../../renderer/components/test-utils/discovery-of-html-elements"; +import { findComposite } from "../../common/utils/composite/find-composite/find-composite"; +import shouldStartHiddenInjectable from "../../main/electron-app/features/should-start-hidden.injectable"; +import fsInjectable from "../../common/fs/fs.injectable"; +import joinPathsInjectable from "../../common/path/join-paths.injectable"; +import homeDirectoryPathInjectable from "../../common/os/home-directory-path.injectable"; +import type { ClusterId } from "../../common/cluster-types"; +import getClusterByIdInjectable from "../../common/cluster-store/get-by-id.injectable"; +import createClusterInjectable from "../../main/create-cluster/create-cluster.injectable"; +import { onLoadOfApplicationInjectionToken } from "../../main/start-main-application/runnable-tokens/on-load-of-application-injection-token"; +import currentLocationInjectable from "../../renderer/api/current-location.injectable"; +import lensProxyPortInjectable from "../../main/lens-proxy/lens-proxy-port.injectable"; +import { beforeQuitOfBackEndInjectionToken } from "../../main/start-main-application/runnable-tokens/before-quit-of-back-end-injection-token"; +import { KubernetesCluster, LensKubernetesClusterStatus } from "../../common/catalog-entities"; +import listNamespacesForInjectable from "../../common/cluster/list-namespaces.injectable"; +import requestApiResourcesInjectable from "../../main/cluster/request-api-resources.injectable"; +import requestNamespaceListPermissionsForInjectable from "../../common/cluster/request-namespace-list-permissions.injectable"; +import { beforeQuitOfFrontEndInjectionToken } from "../../main/start-main-application/runnable-tokens/before-quit-of-front-end-injection-token"; +import { runManySyncFor } from "../../common/runnable/run-many-sync-for"; +import type { MemoryHistory } from "history"; +import { object } from "../../common/utils"; +import catalogEntityRegistryInjectable from "../../renderer/api/catalog/entity/registry.injectable"; +import { testUsingFakeTime } from "../../common/test-utils/use-fake-time"; + +type Callback = (di: DiContainer) => void | Promise; + +type LensWindowWithHelpers = LensWindow & { rendered: RenderResult; di: DiContainer }; + +const createNamespacesFor = (namespaces: Set): Namespace[] => ( + Array.from(namespaces, (namespace) => new Namespace({ + apiVersion: "v1", + kind: "Namespace", + metadata: { + name: namespace, + resourceVersion: "1", + selfLink: `/api/v1/namespaces/${namespace}`, + uid: `namespace-${namespace}`, + }, + })) +); + +export interface ApplicationBuilder { + mainDi: DiContainer; + setEnvironmentToClusterFrame: () => ApplicationBuilder; + + extensions: { + enable: (...extensions: FakeExtensionOptions[]) => void; + disable: (...extensions: FakeExtensionOptions[]) => void; + + get: (id: string) => { + main: LensMainExtension; + + applicationWindows: Record & { + only: LensRendererExtension; + }; + }; + }; + + applicationWindow: { + closeAll: () => void; + only: LensWindowWithHelpers; + get: (id: string) => LensWindowWithHelpers; + getAll: () => LensWindowWithHelpers[]; + create: (id: string) => LensWindowWithHelpers; + }; + + allowKubeResource: (resourceName: KubeApiResourceDescriptor) => ApplicationBuilder; + beforeApplicationStart: (callback: Callback) => ApplicationBuilder; + afterApplicationStart: (callback: Callback) => ApplicationBuilder; + beforeWindowStart: (callback: Callback) => ApplicationBuilder; + afterWindowStart: (callback: Callback) => ApplicationBuilder; + + startHidden: () => Promise; + render: () => Promise; + quit: () => void; + + tray: { + click: (id: string) => Promise; + get: (id: string) => MinimalTrayMenuItem | null; + getIconPath: () => string; + }; + + applicationMenu: { + click: (...path: string[]) => void; + items: string[][]; + }; + preferences: { + close: () => void; + navigate: () => void; + navigateTo: (route: Route, params: Partial>) => void; + navigation: { + click: (id: string) => void; + }; + }; + namespaces: { + add: (namespace: string) => void; + select: (namespace: string) => void; + }; + helmCharts: { + navigate: NavigateToHelmCharts; + }; + navigateWith: (token: Injectable<() => void, any, void>) => void; + select: { + openMenu: (id: string) => { selectOption: (labelText: string) => void }; + selectOption: (menuId: string, labelText: string) => void; + getValue: (menuId: string) => string; + }; +} + +interface Environment { + RootComponent: React.ElementType; + onAllowKubeResource: () => void; +} + +export const setupInitializingApplicationBuilder = (init: (builder: ApplicationBuilder) => void): void => { + let builder: ApplicationBuilder; + + beforeEach(() => { + const mainDi = getMainDi({ + doGeneralOverrides: true, + }); + + runInAction(() => { + mainDi.register(mainExtensionsStateInjectable); + }); + + testUsingFakeTime(); + + const { overrideForWindow, sendToWindow } = overrideChannels(mainDi); + + const beforeApplicationStartCallbacks: Callback[] = []; + const afterApplicationStartCallbacks: Callback[] = []; + const beforeWindowStartCallbacks: Callback[] = []; + const afterWindowStartCallbacks: Callback[] = []; + + const overrideFsWithFakes = getOverrideFsWithFakes(); + + overrideFsWithFakes(mainDi); + + // Set up ~/.kube as existing as a folder + { + const { ensureDirSync } = mainDi.inject(fsInjectable); + const joinPaths = mainDi.inject(joinPathsInjectable); + const homeDirectoryPath = mainDi.inject(homeDirectoryPathInjectable); + + ensureDirSync(joinPaths(homeDirectoryPath, ".kube")); + } + + let environment = environments.application; + + mainDi.override(mainExtensionsInjectable, (di) => { + const mainExtensionsState = di.inject(mainExtensionsStateInjectable); + + return computed(() => + [...mainExtensionsState.values()], + ); + }); + + let trayMenuIconPath: string; + + const traySetMenuItemsMock = jest.fn(); + + mainDi.override(electronTrayInjectable, () => ({ + start: () => {}, + stop: () => {}, + setMenuItems: traySetMenuItemsMock, + setIconPath: (path) => { + trayMenuIconPath = path; + }, + })); + + const allowedResourcesState = observable.set(); + const windowHelpers = new Map RenderResult }>(); + + const createElectronWindowFake: CreateElectronWindow = (configuration) => { + const windowId = configuration.id; + + const windowDi = getRendererDi({ doGeneralOverrides: true }); + + overrideForWindow(windowDi, windowId); + overrideFsWithFakes(windowDi); + + runInAction(() => { + 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(); + + for (const callback of afterWindowStartCallbacks) { + await callback(windowDi); + } + + const history = windowDi.inject(historyInjectable); + const render = renderFor(windowDi); + + rendered = render(( + <> +
+ + + + + )); + }, + send: (arg) => { + sendToWindow(windowId, arg); + }, + canGoBack: () => { + const history = windowDi.inject(historyInjectable) as MemoryHistory; + + return history.canGo(-1); + }, + canGoForward: () => { + const history = windowDi.inject(historyInjectable) as MemoryHistory; + + return history.canGo(1); + }, + reload: () => { + throw new Error("Tried to reload application window which is not implemented yet."); + }, + }; + }; + + mainDi.override(createElectronWindowInjectable, () => createElectronWindowFake); + + let applicationHasStarted = false; + + const namespaces = observable.set(); + const namespaceItems = observable.array(); + const selectedNamespaces = observable.set(); + const clusters = observable.map(); + const clusterId = "some-cluster-id"; + const clusterEntity = new KubernetesCluster({ + metadata: { + labels: {}, + name: "some-context-name", + uid: clusterId, + }, + spec: { + kubeconfigContext: "some-context-name", + kubeconfigPath: "/some-kube-config-path", + }, + status: { + phase: LensKubernetesClusterStatus.DISCONNECTED, + }, + }); + const startMainApplication = mainDi.inject(startMainApplicationInjectable); + + const startApplication = async ({ shouldStartHidden }: { shouldStartHidden: boolean }) => { + for (const callback of beforeApplicationStartCallbacks) { + await callback(mainDi); + } + + mainDi.override(shouldStartHiddenInjectable, () => shouldStartHidden); + await startMainApplication(); + + for (const callback of afterApplicationStartCallbacks) { + await callback(mainDi); + } + + applicationHasStarted = true; + }; + + mainDi.override(getClusterByIdInjectable, () => (id) => clusters.get(id)); + + beforeWindowStartCallbacks.push((windowDi) => { + windowDi.override(getClusterByIdInjectable, () => (id) => clusters.get(id)); + windowDi.override(currentLocationInjectable, () => ({ + hostname: "localhost", + port: `${mainDi.inject(lensProxyPortInjectable).get()}`, + protocol: "http", + })); + }); + + afterWindowStartCallbacks.push((windowDi) => { + windowDi.inject(catalogEntityRegistryInjectable).updateItems([clusterEntity]); + }); + + mainDi.override(listNamespacesForInjectable, () => () => async () => [...namespaces]); + mainDi.override(requestApiResourcesInjectable, () => async () => ( + object.entries(apiResourceRecord) + .map(([apiName, data]) => ({ apiName, ...data })) + )); + mainDi.override(requestNamespaceListPermissionsForInjectable, () => () => async () => (resource) => allowedResourcesState.has(formatKubeApiResource(resource))); + + + runInAction(() => { + mainDi.register(getInjectable({ + id: "create-fake-cluster", + instantiate: (di) => ({ + id: "create-fake-cluster", + run: () => { + const createCluster = di.inject(createClusterInjectable); + const cluster = createCluster({ + contextName: "some-context-name", + id: clusterId, + kubeConfigPath: "/some-kube-config-path", + }, { + clusterServerUrl: "https://some-url.com:8797", + }); + + clusters.set(clusterId, cluster); + }, + }), + injectionToken: onLoadOfApplicationInjectionToken, + })); + }); + + builder = { + 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 applicationWindow = builder.applicationWindow + .getAll() + .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); + }, + }, + namespaces: { + add: action((namespace) => { + namespaces.add(namespace); + namespaceItems.replace(createNamespacesFor(namespaces)); + }), + select: action((namespace) => selectedNamespaces.add(namespace)), + }, + applicationMenu: { + get items() { + const composite = mainDi.inject( + applicationMenuItemCompositeInjectable, + ).get(); + + return getCompositePaths(composite); + }, + + click: (...path: string[]) => { + const composite = mainDi.inject( + applicationMenuItemCompositeInjectable, + ).get(); + + const clickableMenuItem = findComposite(...path)(composite).value; + + if(clickableMenuItem.kind === "clickable-menu-item") { + // Todo: prevent leaking of Electron + (clickableMenuItem.onClick as any)(); + } else { + throw new Error(`Tried to trigger clicking of an application menu item, but item at path '${path.join(" -> ")}' isn't clickable.`); + } + }, + }, + + tray: { + get: (id: string) => { + const lastCall = last(traySetMenuItemsMock.mock.calls); + + assert(lastCall); + + return lastCall[0].find(matches({ id })) ?? null; + }, + + getIconPath: () => trayMenuIconPath, + + click: async (id: string) => { + const lastCall = last(traySetMenuItemsMock.mock.calls); + + assert(lastCall); + + const trayMenuItems = lastCall[0]; + + const menuItem = trayMenuItems.find(matches({ id })) ?? null; + + if (!menuItem) { + const availableIds = pipeline( + trayMenuItems, + filter(item => !!item.click), + map(item => item.id), + join(", "), + ); + + throw new Error(`Tried to click tray menu item with ID ${id} which does not exist. Available IDs are: "${availableIds}"`); + } + + if (!menuItem.enabled) { + throw new Error(`Tried to click tray menu item with ID ${id} which is disabled.`); + } + + await menuItem.click?.(); + }, + }, + + preferences: { + close: () => { + const rendered = builder.applicationWindow.only.rendered; + + const link = rendered.getByTestId("close-preferences"); + + fireEvent.click(link); + }, + + navigate: () => { + const windowDi = builder.applicationWindow.only.di; + + const navigateToPreferences = windowDi.inject( + navigateToPreferencesInjectable, + ); + + navigateToPreferences(); + }, + + navigateTo: (route: Route, params: Partial>) => { + const windowDi = builder.applicationWindow.only.di; + + const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken); + + navigateToRoute(route, params); + }, + + navigation: { + click: (pathId: string) => { + const { rendered } = builder.applicationWindow.only; + + const discover = discoverFor(() => rendered); + + const { discovered: link } = discover.getSingleElement( + "preference-tab-link", + pathId, + ); + + fireEvent.click(link); + }, + }, + }, + + helmCharts: { + navigate: (parameters) => { + const windowDi = builder.applicationWindow.only.di; + + const navigateToHelmCharts = windowDi.inject( + navigateToHelmChartsInjectable, + ); + + navigateToHelmCharts(parameters); + }, + }, + + navigateWith: (token) => { + const windowDi = builder.applicationWindow.only.di; + const navigate = windowDi.inject(token); + + navigate(); + }, + + setEnvironmentToClusterFrame: () => { + environment = environments.clusterFrame; + + builder.beforeWindowStart((windowDi) => { + windowDi.override(hostedClusterIdInjectable, () => clusterId); + + // TODO: Figure out a way to remove this stub. + windowDi.override(namespaceStoreInjectable, () => ({ + isLoaded: true, + get contextNamespaces() { + return Array.from(selectedNamespaces); + }, + get allowedNamespaces() { + return Array.from(namespaces); + }, + contextItems: namespaceItems, + api: windowDi.inject(namespaceApiInjectable), + items: namespaceItems, + selectNamespaces: () => {}, + selectSingle: () => {}, + getByPath: () => undefined, + pickOnlySelected: () => [], + isSelectedAll: () => false, + getTotalCount: () => namespaceItems.length, + } as Partial as NamespaceStore)); + }); + + builder.afterWindowStart(windowDi => { + windowDi.inject(catalogEntityRegistryInjectable).activeEntity = clusterEntity; + }); + + return builder; + }, + + extensions: { + get: (id: string) => { + const windowInstances = pipeline( + builder.applicationWindow.getAll(), + + 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) => { + builder.afterWindowStart((windowDi) => { + const enabledExtension = enableExtensionFor(windowDi, rendererExtensionsStateInjectable); + + runInAction(() => { + for (const extension of extensions) { + enabledExtension(getExtensionFakeForRenderer( + windowDi, + extension.id, + extension.name, + extension.rendererOptions ?? {}, + )); + } + }); + }); + + builder.afterApplicationStart((mainDi) => { + const enabledExtension = enableExtensionFor(mainDi, mainExtensionsStateInjectable); + + runInAction(() => { + for (const extension of extensions) { + enabledExtension(getExtensionFakeForMain( + mainDi, + extension.id, + extension.name, + extension.mainOptions ?? {}, + )); + } + }); + }); + }, + + disable: (...extensions) => { + builder.afterWindowStart(windowDi => { + extensions + .map((ext) => ext.id) + .forEach( + disableExtensionFor(windowDi, rendererExtensionsStateInjectable), + ); + }); + + builder.afterApplicationStart(mainDi => { + extensions + .map((ext) => ext.id) + .forEach( + disableExtensionFor(mainDi, mainExtensionsStateInjectable), + ); + }); + }, + }, + + allowKubeResource: (resource) => { + environment.onAllowKubeResource(); + + runInAction(() => { + allowedResourcesState.add(formatKubeApiResource(resource)); + }); + + return builder; + }, + + beforeApplicationStart(callback) { + if (applicationHasStarted) { + callback(mainDi); + } + + beforeApplicationStartCallbacks.push(callback); + + return builder; + }, + + afterApplicationStart(callback) { + if (applicationHasStarted) { + callback(mainDi); + } + + afterApplicationStartCallbacks.push(callback); + + return builder; + }, + + beforeWindowStart(callback) { + const alreadyRenderedWindows = builder.applicationWindow.getAll(); + + alreadyRenderedWindows.forEach((window) => { + callback(window.di); + }); + + beforeWindowStartCallbacks.push(callback); + + return builder; + }, + + afterWindowStart(callback) { + const alreadyRenderedWindows = builder.applicationWindow.getAll(); + + alreadyRenderedWindows.forEach((window) => { + callback(window.di); + }); + + afterWindowStartCallbacks.push(callback); + + return builder; + }, + + startHidden: async () => { + await startApplication({ shouldStartHidden: true }); + }, + + quit() { + const runManySync = runManySyncFor(builder.mainDi); + const beforeQuitOfFrontEnd = runManySync(beforeQuitOfFrontEndInjectionToken); + const beforeQuitOfBackEnd = runManySync(beforeQuitOfBackEndInjectionToken); + + beforeQuitOfFrontEnd(); + beforeQuitOfBackEnd(); + }, + + async render() { + await startApplication({ shouldStartHidden: false }); + + return builder + .applicationWindow + .get("first-application-window") + .rendered; + }, + + select: { + openMenu: (menuId) => { + const rendered = builder.applicationWindow.only.rendered; + + const select = rendered.baseElement.querySelector( + `#${menuId}`, + ); + + assert(select, `Could not find select with ID "${menuId}"`); + + openMenu(select); + + return { + selectOption: selectOptionFor(builder, menuId), + }; + }, + + selectOption: (menuId, labelText) => selectOptionFor(builder, menuId)(labelText), + + getValue: (menuId) => { + const rendered = builder.applicationWindow.only.rendered; + + const select = rendered.baseElement.querySelector( + `#${menuId}`, + ); + + assert(select, `Could not find select with ID "${menuId}"`); + + const controlElement = select.closest(".Select__control"); + + assert(controlElement, `Could not find select value for menu with ID "${menuId}"`); + + return controlElement.textContent || ""; + }, + }, + }; + + init(builder); + }); + + afterEach(() => { + builder.quit(); + }); +}; + +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 extensionState = di.inject(stateInjectable); + + return (extensionInstance: LensExtension) => { + const extension = di.inject(extensionInjectable, extensionInstance); + + runInAction(() => { + extension.register(); + extensionState.set(extensionInstance.id, extensionInstance); + }); + }; +}; + +const disableExtensionFor = + ( + di: DiContainer, + stateInjectable: Injectable, unknown, void>, + ) => + (id: string) => { + 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 extension = di.inject(extensionInjectable, instance); + + runInAction(() => { + extension.deregister(); + extensionsState.delete(id); + }); + }; diff --git a/src/features/top-bar/extension-api/extendability-using-extension-api.test.tsx b/src/features/top-bar/extension-api/extendability-using-extension-api.test.tsx index 70a06574a7..67fdf2b2cb 100644 --- a/src/features/top-bar/extension-api/extendability-using-extension-api.test.tsx +++ b/src/features/top-bar/extension-api/extendability-using-extension-api.test.tsx @@ -5,18 +5,18 @@ import React from "react"; 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 { ApplicationBuilder } from "../../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../../test-utils/application-builder"; import type { FakeExtensionOptions } from "../../../renderer/components/test-utils/get-extension-fake"; describe("extendability-using-extension-api", () => { let rendered: RenderResult; - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; + + setupInitializingApplicationBuilder(b => builder = b); beforeEach(async () => { - applicationBuilder = getApplicationBuilder(); - - rendered = await applicationBuilder.render(); + rendered = await builder.render(); }); it("renders", () => { @@ -48,7 +48,7 @@ describe("extendability-using-extension-api", () => { }, }; - applicationBuilder.extensions.enable(testExtension); + builder.extensions.enable(testExtension); }); it("renders", () => { @@ -61,7 +61,7 @@ describe("extendability-using-extension-api", () => { describe("when the extension is disabled", () => { beforeEach(() => { - applicationBuilder.extensions.disable(testExtension); + builder.extensions.disable(testExtension); }); it("renders", () => { @@ -98,7 +98,7 @@ describe("extendability-using-extension-api", () => { }, }; - applicationBuilder.extensions.enable(testExtension); + builder.extensions.enable(testExtension); }); it("renders without blowing up", () => { diff --git a/src/features/tray/clicking-tray-menu-item-originating-from-extension.test.ts b/src/features/tray/clicking-tray-menu-item-originating-from-extension.test.ts index 9c0010d75e..f4dab45bab 100644 --- a/src/features/tray/clicking-tray-menu-item-originating-from-extension.test.ts +++ b/src/features/tray/clicking-tray-menu-item-originating-from-extension.test.ts @@ -2,8 +2,8 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; -import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import type { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import type { FakeExtensionOptions } from "../../renderer/components/test-utils/get-extension-fake"; import getRandomIdInjectable from "../../common/utils/get-random-id.injectable"; import logErrorInjectable from "../../common/log-error.injectable"; @@ -12,9 +12,9 @@ describe("clicking tray menu item originating from extension", () => { let builder: ApplicationBuilder; let logErrorMock: jest.Mock; - beforeEach(async () => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { builder.beforeApplicationStart((mainDi) => { logErrorMock = jest.fn(); @@ -25,10 +25,6 @@ describe("clicking tray menu item originating from extension", () => { await builder.render(); }); - afterEach(() => { - builder.quit(); - }); - describe("when extension is enabled", () => { let someExtension: FakeExtensionOptions; let clickMock: jest.Mock; diff --git a/src/features/tray/extension-adding-tray-items.test.tsx b/src/features/tray/extension-adding-tray-items.test.tsx index 9a099e1d0f..6fe5b064f0 100644 --- a/src/features/tray/extension-adding-tray-items.test.tsx +++ b/src/features/tray/extension-adding-tray-items.test.tsx @@ -5,19 +5,20 @@ import type { IObservableArray, IObservableValue } from "mobx"; import { computed, runInAction, observable } from "mobx"; 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 type { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; describe("preferences: extension adding tray items", () => { + let builder: ApplicationBuilder; + + setupInitializingApplicationBuilder(b => builder = b); + describe("when extension with tray items are statically defined", () => { - let builder: ApplicationBuilder; let someObservableForVisibility: IObservableValue; let someObservableForEnabled: IObservableValue; let someObservableLabel: IObservableValue; beforeEach(async () => { - builder = getApplicationBuilder(); - await builder.render(); builder.preferences.navigate(); @@ -85,10 +86,6 @@ describe("preferences: extension adding tray items", () => { builder.extensions.enable(testExtension); }); - afterEach(() => { - builder.quit(); - }); - describe("given controlled label", () => { it("has the label", () => { const item = builder.tray.get( @@ -197,12 +194,9 @@ describe("preferences: extension adding tray items", () => { }); describe("when extension with tray items are dynamically defined", () => { - let builder: ApplicationBuilder; let menuItems: IObservableArray; beforeEach(async () => { - builder = getApplicationBuilder(); - await builder.render(); builder.preferences.navigate(); diff --git a/src/features/tray/multiple-separators-originating-from-extension.test.ts b/src/features/tray/multiple-separators-originating-from-extension.test.ts index 8747d61d80..2919a9dada 100644 --- a/src/features/tray/multiple-separators-originating-from-extension.test.ts +++ b/src/features/tray/multiple-separators-originating-from-extension.test.ts @@ -2,16 +2,16 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; -import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import type { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import getRandomIdInjectable from "../../common/utils/get-random-id.injectable"; describe("multiple separators originating from extension", () => { let builder: ApplicationBuilder; - beforeEach(async () => { - builder = getApplicationBuilder(); + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { builder.beforeApplicationStart((mainDi) => { mainDi.unoverride(getRandomIdInjectable); mainDi.permitSideEffects(getRandomIdInjectable); @@ -20,10 +20,6 @@ describe("multiple separators originating from extension", () => { await builder.render(); }); - afterEach(() => { - builder.quit(); - }); - it("given extension with multiple separators, when extension is enabled, does not throw", () => { const someExtension = { id: "some-extension-id", diff --git a/src/features/welcome/navigation-using-application-menu.test.ts b/src/features/welcome/navigation-using-application-menu.test.ts index d5405d1dfe..2eb69499b7 100644 --- a/src/features/welcome/navigation-using-application-menu.test.ts +++ b/src/features/welcome/navigation-using-application-menu.test.ts @@ -4,23 +4,19 @@ */ 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 { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; describe("welcome - navigation using application menu", () => { let builder: ApplicationBuilder; let rendered: RenderResult; + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { - builder = getApplicationBuilder(); - rendered = await builder.render(); }); - afterEach(() => { - builder.quit(); - }); - it("renders", () => { expect(rendered.container).toMatchSnapshot(); }); diff --git a/src/features/welcome/setting-welcome-page.test.tsx b/src/features/welcome/setting-welcome-page.test.tsx index 34e4025e05..6077edd66b 100644 --- a/src/features/welcome/setting-welcome-page.test.tsx +++ b/src/features/welcome/setting-welcome-page.test.tsx @@ -5,8 +5,8 @@ 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 { ApplicationBuilder } from "../test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../test-utils/application-builder"; import type { FakeExtensionOptions } from "../../renderer/components/test-utils/get-extension-fake"; import welcomeRouteConfigInjectable from "../../common/front-end-routing/routes/welcome/welcome-route-config.injectable"; import welcomeRouteInjectable from "../../common/front-end-routing/routes/welcome/welcome-route.injectable"; @@ -18,13 +18,7 @@ describe("setting-welcome-page", () => { let rendered : RenderResult; let welcomeRoute: Route; - beforeEach(() => { - builder = getApplicationBuilder(); - }); - - afterEach(() => { - builder.quit(); - }); + setupInitializingApplicationBuilder(b => builder = b); describe("given configuration of welcome page route is the default", () => { beforeEach(async () => { diff --git a/src/renderer/components/status-bar/status-bar.test.tsx b/src/renderer/components/status-bar/status-bar.test.tsx index 8aef89766c..253081fb77 100644 --- a/src/renderer/components/status-bar/status-bar.test.tsx +++ b/src/renderer/components/status-bar/status-bar.test.tsx @@ -10,19 +10,19 @@ import { computed, observable } from "mobx"; import type { StatusBarItems } from "./status-bar-items.injectable"; import statusBarItemsInjectable from "./status-bar-items.injectable"; 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 type { ApplicationBuilder } from "../../../features/test-utils/application-builder"; +import { setupInitializingApplicationBuilder } from "../../../features/test-utils/application-builder"; import getRandomIdInjectable from "../../../common/utils/get-random-id.injectable"; describe("", () => { let statusBarItems: IObservableArray; let builder: ApplicationBuilder; + setupInitializingApplicationBuilder(b => builder = b); + beforeEach(async () => { statusBarItems = observable.array([]); - builder = getApplicationBuilder(); - builder.beforeWindowStart((windowDi) => { windowDi.unoverride(getRandomIdInjectable); windowDi.permitSideEffects(getRandomIdInjectable); @@ -39,10 +39,6 @@ describe("", () => { }); }); - afterEach(() => { - builder.quit(); - }); - it("renders w/o errors", async () => { const { container } = await builder.render(); diff --git a/src/renderer/components/test-utils/get-application-builder.tsx b/src/renderer/components/test-utils/get-application-builder.tsx deleted file mode 100644 index 4e9134cc4d..0000000000 --- a/src/renderer/components/test-utils/get-application-builder.tsx +++ /dev/null @@ -1,932 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -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 { IComputedValue, ObservableMap } from "mobx"; -import { action, computed, observable, runInAction } from "mobx"; -import React from "react"; -import { Router } from "react-router"; -import type { RenderResult } from "@testing-library/react"; -import { fireEvent, queryByText } from "@testing-library/react"; -import type { KubeApiResourceDescriptor } from "../../../common/rbac"; -import { apiResourceRecord, formatKubeApiResource } from "../../../common/rbac"; -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 { filter, first, join, last, map, matches } from "lodash/fp"; -import navigateToPreferencesInjectable from "../../../features/preferences/common/navigate-to-preferences.injectable"; -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 type { Cluster } from "../../../common/cluster/cluster"; -import startMainApplicationInjectable from "../../../main/start-main-application/start-main-application.injectable"; -import startFrameInjectable from "../../start-frame/start-frame.injectable"; -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 { getDiForUnitTesting as getRendererDi } from "../../getDiForUnitTesting"; -import { getDiForUnitTesting as getMainDi } from "../../../main/getDiForUnitTesting"; -import { overrideChannels } from "../../../test-utils/channel-fakes/override-channels"; -import assert from "assert"; -import { openMenu } from "react-select-event"; -import userEvent from "@testing-library/user-event"; -import type { Route } from "../../../common/front-end-routing/front-end-route-injection-token"; -import type { NavigateToRouteOptions } from "../../../common/front-end-routing/navigate-to-route-injection-token"; -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"; -import { ClusterFrame } from "../../frames/cluster-frame/cluster-frame"; -import hostedClusterIdInjectable from "../../cluster-frame-context/hosted-cluster-id.injectable"; -import namespaceStoreInjectable from "../+namespaces/store.injectable"; -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 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"; -import namespaceApiInjectable from "../../../common/k8s-api/endpoints/namespace.api.injectable"; -import { Namespace } from "../../../common/k8s-api/endpoints"; -import { getOverrideFsWithFakes } from "../../../test-utils/override-fs-with-fakes"; -import applicationMenuItemCompositeInjectable from "../../../features/application-menu/main/application-menu-item-composite.injectable"; -import { getCompositePaths } from "../../../common/utils/composite/get-composite-paths/get-composite-paths"; -import { discoverFor } from "./discovery-of-html-elements"; -import { findComposite } from "../../../common/utils/composite/find-composite/find-composite"; -import shouldStartHiddenInjectable from "../../../main/electron-app/features/should-start-hidden.injectable"; -import fsInjectable from "../../../common/fs/fs.injectable"; -import joinPathsInjectable from "../../../common/path/join-paths.injectable"; -import homeDirectoryPathInjectable from "../../../common/os/home-directory-path.injectable"; -import { testUsingFakeTime } from "../../../common/test-utils/use-fake-time"; -import type { ClusterId } from "../../../common/cluster-types"; -import getClusterByIdInjectable from "../../../common/cluster-store/get-by-id.injectable"; -import createClusterInjectable from "../../../main/create-cluster/create-cluster.injectable"; -import { onLoadOfApplicationInjectionToken } from "../../../main/start-main-application/runnable-tokens/on-load-of-application-injection-token"; -import currentLocationInjectable from "../../api/current-location.injectable"; -import lensProxyPortInjectable from "../../../main/lens-proxy/lens-proxy-port.injectable"; -import { beforeQuitOfBackEndInjectionToken } from "../../../main/start-main-application/runnable-tokens/before-quit-of-back-end-injection-token"; -import catalogEntityRegistryInjectable from "../../api/catalog/entity/registry.injectable"; -import { KubernetesCluster, LensKubernetesClusterStatus } from "../../../common/catalog-entities"; -import listNamespacesForInjectable from "../../../common/cluster/list-namespaces.injectable"; -import requestApiResourcesInjectable from "../../../common/cluster/request-api-resources.injectable"; -import { object } from "../../utils"; -import requestNamespaceListPermissionsForInjectable from "../../../common/cluster/request-namespace-list-permissions.injectable"; -import { beforeQuitOfFrontEndInjectionToken } from "../../../main/start-main-application/runnable-tokens/before-quit-of-front-end-injection-token"; -import { runManySyncFor } from "../../../common/runnable/run-many-sync-for"; -import type { MemoryHistory } from "history"; - -type Callback = (di: DiContainer) => void | Promise; - -type LensWindowWithHelpers = LensWindow & { rendered: RenderResult; di: DiContainer }; - -const createNamespacesFor = (namespaces: Set): Namespace[] => ( - Array.from(namespaces, (namespace) => new Namespace({ - apiVersion: "v1", - kind: "Namespace", - metadata: { - name: namespace, - resourceVersion: "1", - selfLink: `/api/v1/namespaces/${namespace}`, - uid: `namespace-${namespace}`, - }, - })) -); - -export interface ApplicationBuilder { - mainDi: DiContainer; - setEnvironmentToClusterFrame: () => ApplicationBuilder; - - extensions: { - enable: (...extensions: FakeExtensionOptions[]) => void; - disable: (...extensions: FakeExtensionOptions[]) => void; - - get: (id: string) => { - main: LensMainExtension; - - applicationWindows: Record & { - only: LensRendererExtension; - }; - }; - }; - - applicationWindow: { - closeAll: () => void; - only: LensWindowWithHelpers; - get: (id: string) => LensWindowWithHelpers; - getAll: () => LensWindowWithHelpers[]; - create: (id: string) => LensWindowWithHelpers; - }; - - allowKubeResource: (resource: KubeApiResourceDescriptor) => ApplicationBuilder; - beforeApplicationStart: (callback: Callback) => ApplicationBuilder; - afterApplicationStart: (callback: Callback) => ApplicationBuilder; - beforeWindowStart: (callback: Callback) => ApplicationBuilder; - afterWindowStart: (callback: Callback) => ApplicationBuilder; - - startHidden: () => Promise; - render: () => Promise; - quit: () => void; - - tray: { - click: (id: string) => Promise; - get: (id: string) => MinimalTrayMenuItem | null; - getIconPath: () => string; - }; - - applicationMenu: { - click: (...path: string[]) => void; - items: string[][]; - }; - preferences: { - close: () => void; - navigate: () => void; - navigateTo: (route: Route, params: Partial>) => void; - navigation: { - click: (id: string) => void; - }; - }; - namespaces: { - add: (namespace: string) => void; - select: (namespace: string) => void; - }; - helmCharts: { - navigate: NavigateToHelmCharts; - }; - navigateWith: (token: Injectable<() => void, any, void>) => void; - select: { - openMenu: (id: string) => { selectOption: (labelText: string) => void }; - selectOption: (menuId: string, labelText: string) => void; - getValue: (menuId: string) => string; - }; -} - -interface Environment { - RootComponent: React.ElementType; - onAllowKubeResource: () => void; -} - -export const getApplicationBuilder = () => { - const mainDi = getMainDi({ - doGeneralOverrides: true, - }); - - runInAction(() => { - mainDi.register(mainExtensionsStateInjectable); - }); - - testUsingFakeTime(); - - const { overrideForWindow, sendToWindow } = overrideChannels(mainDi); - - const beforeApplicationStartCallbacks: Callback[] = []; - const afterApplicationStartCallbacks: Callback[] = []; - const beforeWindowStartCallbacks: Callback[] = []; - const afterWindowStartCallbacks: Callback[] = []; - - const overrideFsWithFakes = getOverrideFsWithFakes(); - - overrideFsWithFakes(mainDi); - - // Set up ~/.kube as existing as a folder - { - const { ensureDirSync } = mainDi.inject(fsInjectable); - const joinPaths = mainDi.inject(joinPathsInjectable); - const homeDirectoryPath = mainDi.inject(homeDirectoryPathInjectable); - - ensureDirSync(joinPaths(homeDirectoryPath, ".kube")); - } - - let environment = environments.application; - - mainDi.override(mainExtensionsInjectable, (di) => { - const mainExtensionsState = di.inject(mainExtensionsStateInjectable); - - return computed(() => - [...mainExtensionsState.values()], - ); - }); - - let trayMenuIconPath: string; - - const traySetMenuItemsMock = jest.fn(); - - mainDi.override(electronTrayInjectable, () => ({ - start: () => {}, - stop: () => {}, - setMenuItems: traySetMenuItemsMock, - setIconPath: (path) => { - trayMenuIconPath = path; - }, - })); - - const allowedResourcesState = observable.set(); - const windowHelpers = new Map RenderResult }>(); - - const createElectronWindowFake: CreateElectronWindow = (configuration) => { - const windowId = configuration.id; - - const windowDi = getRendererDi({ doGeneralOverrides: true }); - - overrideForWindow(windowDi, windowId); - overrideFsWithFakes(windowDi); - - runInAction(() => { - 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(); - - for (const callback of afterWindowStartCallbacks) { - await callback(windowDi); - } - - const history = windowDi.inject(historyInjectable); - const render = renderFor(windowDi); - - rendered = render(( - <> -
- - - - - )); - }, - send: (arg) => { - sendToWindow(windowId, arg); - }, - canGoBack: () => { - const history = windowDi.inject(historyInjectable) as MemoryHistory; - - return history.canGo(-1); - }, - canGoForward: () => { - const history = windowDi.inject(historyInjectable) as MemoryHistory; - - return history.canGo(1); - }, - reload: () => { - throw new Error("Tried to reload application window which is not implemented yet."); - }, - }; - }; - - mainDi.override(createElectronWindowInjectable, () => createElectronWindowFake); - - let applicationHasStarted = false; - - const namespaces = observable.set(); - const namespaceItems = observable.array(); - const selectedNamespaces = observable.set(); - const clusters = observable.map(); - const clusterId = "some-cluster-id"; - const startMainApplication = mainDi.inject(startMainApplicationInjectable); - - const startApplication = async ({ shouldStartHidden }: { shouldStartHidden: boolean }) => { - for (const callback of beforeApplicationStartCallbacks) { - await callback(mainDi); - } - - mainDi.override(shouldStartHiddenInjectable, () => shouldStartHidden); - await startMainApplication(); - - for (const callback of afterApplicationStartCallbacks) { - await callback(mainDi); - } - - applicationHasStarted = true; - }; - const clusterEntity = new KubernetesCluster({ - metadata: { - labels: {}, - name: "some-context-name", - uid: clusterId, - }, - spec: { - kubeconfigContext: "some-context-name", - kubeconfigPath: "/some-kube-config-path", - }, - status: { - phase: LensKubernetesClusterStatus.DISCONNECTED, - }, - }); - - mainDi.override(getClusterByIdInjectable, () => (id) => clusters.get(id)); - - beforeWindowStartCallbacks.push((windowDi) => { - windowDi.override(getClusterByIdInjectable, () => (id) => clusters.get(id)); - windowDi.override(currentLocationInjectable, () => ({ - hostname: "localhost", - port: `${mainDi.inject(lensProxyPortInjectable).get()}`, - protocol: "http", - })); - }); - - afterWindowStartCallbacks.push((windowDi) => { - windowDi.inject(catalogEntityRegistryInjectable).updateItems([clusterEntity]); - }); - - mainDi.override(listNamespacesForInjectable, () => () => async () => [...namespaces]); - mainDi.override(requestApiResourcesInjectable, () => async () => ( - object.entries(apiResourceRecord) - .map(([apiName, data]) => ({ apiName, ...data })) - )); - mainDi.override(requestNamespaceListPermissionsForInjectable, () => () => async () => (resource) => allowedResourcesState.has(formatKubeApiResource(resource))); - - runInAction(() => { - mainDi.register(getInjectable({ - id: "create-fake-cluster", - instantiate: (di) => ({ - id: "create-fake-cluster", - run: () => { - const createCluster = di.inject(createClusterInjectable); - const cluster = createCluster({ - contextName: "some-context-name", - id: clusterId, - kubeConfigPath: "/some-kube-config-path", - }, { - clusterServerUrl: "https://some-url.com:8797", - }); - - clusters.set(clusterId, cluster); - }, - }), - injectionToken: onLoadOfApplicationInjectionToken, - })); - }); - - const builder: ApplicationBuilder = { - 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 applicationWindow = builder.applicationWindow - .getAll() - .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); - }, - }, - namespaces: { - add: action((namespace) => { - namespaces.add(namespace); - namespaceItems.replace(createNamespacesFor(namespaces)); - }), - select: action((namespace) => selectedNamespaces.add(namespace)), - }, - applicationMenu: { - get items() { - const composite = mainDi.inject( - applicationMenuItemCompositeInjectable, - ).get(); - - return getCompositePaths(composite); - }, - - click: (...path: string[]) => { - const composite = mainDi.inject( - applicationMenuItemCompositeInjectable, - ).get(); - - const clickableMenuItem = findComposite(...path)(composite).value; - - if(clickableMenuItem.kind === "clickable-menu-item") { - // Todo: prevent leaking of Electron - (clickableMenuItem.onClick as any)(); - } else { - throw new Error(`Tried to trigger clicking of an application menu item, but item at path '${path.join(" -> ")}' isn't clickable.`); - } - }, - }, - - tray: { - get: (id: string) => { - const lastCall = last(traySetMenuItemsMock.mock.calls); - - assert(lastCall); - - return lastCall[0].find(matches({ id })) ?? null; - }, - - getIconPath: () => trayMenuIconPath, - - click: async (id: string) => { - const lastCall = last(traySetMenuItemsMock.mock.calls); - - assert(lastCall); - - const trayMenuItems = lastCall[0]; - - const menuItem = trayMenuItems.find(matches({ id })) ?? null; - - if (!menuItem) { - const availableIds = pipeline( - trayMenuItems, - filter(item => !!item.click), - map(item => item.id), - join(", "), - ); - - throw new Error(`Tried to click tray menu item with ID ${id} which does not exist. Available IDs are: "${availableIds}"`); - } - - if (!menuItem.enabled) { - throw new Error(`Tried to click tray menu item with ID ${id} which is disabled.`); - } - - await menuItem.click?.(); - }, - }, - - preferences: { - close: () => { - const rendered = builder.applicationWindow.only.rendered; - - const link = rendered.getByTestId("close-preferences"); - - fireEvent.click(link); - }, - - navigate: () => { - const windowDi = builder.applicationWindow.only.di; - - const navigateToPreferences = windowDi.inject( - navigateToPreferencesInjectable, - ); - - navigateToPreferences(); - }, - - navigateTo: (route: Route, params: Partial>) => { - const windowDi = builder.applicationWindow.only.di; - - const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken); - - navigateToRoute(route, params); - }, - - navigation: { - click: (pathId: string) => { - const { rendered } = builder.applicationWindow.only; - - const discover = discoverFor(() => rendered); - - const { discovered: link } = discover.getSingleElement( - "preference-tab-link", - pathId, - ); - - fireEvent.click(link); - }, - }, - }, - - helmCharts: { - navigate: (parameters) => { - const windowDi = builder.applicationWindow.only.di; - - const navigateToHelmCharts = windowDi.inject( - navigateToHelmChartsInjectable, - ); - - navigateToHelmCharts(parameters); - }, - }, - - navigateWith: (token) => { - const windowDi = builder.applicationWindow.only.di; - const navigate = windowDi.inject(token); - - navigate(); - }, - - setEnvironmentToClusterFrame: () => { - environment = environments.clusterFrame; - - builder.beforeWindowStart((windowDi) => { - windowDi.override(hostedClusterIdInjectable, () => clusterId); - - // TODO: Figure out a way to remove this stub. - windowDi.override(namespaceStoreInjectable, () => ({ - isLoaded: true, - get contextNamespaces() { - return Array.from(selectedNamespaces); - }, - get allowedNamespaces() { - return Array.from(namespaces); - }, - contextItems: namespaceItems, - api: windowDi.inject(namespaceApiInjectable), - items: namespaceItems, - selectNamespaces: () => {}, - selectSingle: () => {}, - getByPath: () => undefined, - pickOnlySelected: () => [], - isSelectedAll: () => false, - getTotalCount: () => namespaceItems.length, - } as Partial as NamespaceStore)); - }); - - builder.afterWindowStart(windowDi => { - windowDi.inject(catalogEntityRegistryInjectable).activeEntity = clusterEntity; - }); - - return builder; - }, - - extensions: { - get: (id: string) => { - const windowInstances = pipeline( - builder.applicationWindow.getAll(), - - 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) => { - builder.afterWindowStart((windowDi) => { - const enabledExtension = enableExtensionFor(windowDi, rendererExtensionsStateInjectable); - - runInAction(() => { - for (const extension of extensions) { - enabledExtension(getExtensionFakeForRenderer( - windowDi, - extension.id, - extension.name, - extension.rendererOptions ?? {}, - )); - } - }); - }); - - builder.afterApplicationStart((mainDi) => { - const enabledExtension = enableExtensionFor(mainDi, mainExtensionsStateInjectable); - - runInAction(() => { - for (const extension of extensions) { - enabledExtension(getExtensionFakeForMain( - mainDi, - extension.id, - extension.name, - extension.mainOptions ?? {}, - )); - } - }); - }); - }, - - disable: (...extensions) => { - builder.afterWindowStart(windowDi => { - extensions - .map((ext) => ext.id) - .forEach( - disableExtensionFor(windowDi, rendererExtensionsStateInjectable), - ); - }); - - builder.afterApplicationStart(mainDi => { - extensions - .map((ext) => ext.id) - .forEach( - disableExtensionFor(mainDi, mainExtensionsStateInjectable), - ); - }); - }, - }, - - allowKubeResource: (resource) => { - environment.onAllowKubeResource(); - - runInAction(() => { - allowedResourcesState.add(formatKubeApiResource(resource)); - }); - - return builder; - }, - - beforeApplicationStart(callback) { - if (applicationHasStarted) { - callback(mainDi); - } - - beforeApplicationStartCallbacks.push(callback); - - return builder; - }, - - afterApplicationStart(callback) { - if (applicationHasStarted) { - callback(mainDi); - } - - afterApplicationStartCallbacks.push(callback); - - return builder; - }, - - beforeWindowStart(callback) { - const alreadyRenderedWindows = builder.applicationWindow.getAll(); - - alreadyRenderedWindows.forEach((window) => { - callback(window.di); - }); - - beforeWindowStartCallbacks.push(callback); - - return builder; - }, - - afterWindowStart(callback) { - const alreadyRenderedWindows = builder.applicationWindow.getAll(); - - alreadyRenderedWindows.forEach((window) => { - callback(window.di); - }); - - afterWindowStartCallbacks.push(callback); - - return builder; - }, - - startHidden: async () => { - await startApplication({ shouldStartHidden: true }); - }, - - quit() { - const runManySync = runManySyncFor(builder.mainDi); - const beforeQuitOfFrontEnd = runManySync(beforeQuitOfFrontEndInjectionToken); - const beforeQuitOfBackEnd = runManySync(beforeQuitOfBackEndInjectionToken); - - beforeQuitOfFrontEnd(); - beforeQuitOfBackEnd(); - }, - - async render() { - await startApplication({ shouldStartHidden: false }); - - return builder - .applicationWindow - .get("first-application-window") - .rendered; - }, - - select: { - openMenu: (menuId) => { - const rendered = builder.applicationWindow.only.rendered; - - const select = rendered.baseElement.querySelector( - `#${menuId}`, - ); - - assert(select, `Could not find select with ID "${menuId}"`); - - openMenu(select); - - return { - selectOption: selectOptionFor(builder, menuId), - }; - }, - - selectOption: (menuId, labelText) => selectOptionFor(builder, menuId)(labelText), - - getValue: (menuId) => { - const rendered = builder.applicationWindow.only.rendered; - - const select = rendered.baseElement.querySelector( - `#${menuId}`, - ); - - assert(select, `Could not find select with ID "${menuId}"`); - - const controlElement = select.closest(".Select__control"); - - assert(controlElement, `Could not find select value for menu with ID "${menuId}"`); - - return controlElement.textContent || ""; - }, - }, - }; - - return builder; -}; - -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 extensionState = di.inject(stateInjectable); - - return (extensionInstance: LensExtension) => { - const extension = di.inject(extensionInjectable, extensionInstance); - - runInAction(() => { - extension.register(); - extensionState.set(extensionInstance.id, extensionInstance); - }); - }; -}; - -const disableExtensionFor = - ( - di: DiContainer, - stateInjectable: Injectable, unknown, void>, - ) => - (id: string) => { - 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 extension = di.inject(extensionInjectable, instance); - - runInAction(() => { - extension.deregister(); - extensionsState.delete(id); - }); - };