mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Consolidate code for application window
Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
parent
5ac9b2aa87
commit
55d1471c10
@ -35,8 +35,8 @@ describe("add-cluster - navigation using application menu", () => {
|
||||
});
|
||||
|
||||
describe("when navigating to add cluster using application menu", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.applicationMenu.click("file.add-cluster");
|
||||
beforeEach(async () => {
|
||||
await applicationBuilder.applicationMenu.click("file.add-cluster");
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
|
||||
@ -46,8 +46,8 @@ describe("extensions - navigation using application menu", () => {
|
||||
});
|
||||
|
||||
describe("when navigating to extensions using application menu", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.applicationMenu.click("root.extensions");
|
||||
beforeEach(async () => {
|
||||
await applicationBuilder.applicationMenu.click("root.extensions");
|
||||
});
|
||||
|
||||
it("focuses the window", () => {
|
||||
|
||||
@ -18,7 +18,6 @@ describe("preferences - navigation using application menu", () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
|
||||
applicationBuilder.beforeSetups(({ rendererDi, mainDi }) => {
|
||||
mainDi.override(isAutoUpdateEnabledInjectable, () => () => false);
|
||||
|
||||
@ -47,8 +46,8 @@ describe("preferences - navigation using application menu", () => {
|
||||
});
|
||||
|
||||
describe("when navigating to preferences using application menu", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.applicationMenu.click("root.preferences");
|
||||
beforeEach(async () => {
|
||||
await applicationBuilder.applicationMenu.click("root.preferences");
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
|
||||
@ -31,8 +31,8 @@ describe("welcome - navigation using application menu", () => {
|
||||
});
|
||||
|
||||
describe("when navigating to welcome using application menu", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.applicationMenu.click("help.welcome");
|
||||
beforeEach(async () => {
|
||||
await applicationBuilder.applicationMenu.click("help.welcome");
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
|
||||
@ -14,17 +14,13 @@ import { stdout, stderr } from "process";
|
||||
import getCustomKubeConfigDirectoryInjectable from "../app-paths/get-custom-kube-config-directory/get-custom-kube-config-directory.injectable";
|
||||
import clusterStoreInjectable from "../cluster-store/cluster-store.injectable";
|
||||
import type { ClusterModel } from "../cluster-types";
|
||||
import type {
|
||||
DiContainer,
|
||||
} from "@ogre-tools/injectable";
|
||||
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import { createClusterInjectionToken } from "../cluster/create-cluster-injection-token";
|
||||
|
||||
import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
import { getDiForUnitTesting } from "../../main/getDiForUnitTesting";
|
||||
import getConfigurationFileModelInjectable from "../get-configuration-file-model/get-configuration-file-model.injectable";
|
||||
import appVersionInjectable from "../get-configuration-file-model/app-version/app-version.injectable";
|
||||
import { runSetups } from "../setupable-injection-token/run-setups";
|
||||
import directoryForTempInjectable from "../app-paths/directory-for-temp/directory-for-temp.injectable";
|
||||
|
||||
console = new Console(stdout, stderr);
|
||||
|
||||
@ -86,12 +82,12 @@ describe("cluster-store", () => {
|
||||
mockFs();
|
||||
|
||||
mainDi.override(directoryForUserDataInjectable, () => "some-directory-for-user-data");
|
||||
mainDi.override(directoryForTempInjectable, () => "some-temp-directory");
|
||||
|
||||
mainDi.permitSideEffects(getConfigurationFileModelInjectable);
|
||||
mainDi.permitSideEffects(appVersionInjectable);
|
||||
mainDi.permitSideEffects(clusterStoreInjectable);
|
||||
|
||||
// @ts-ignore
|
||||
mainDi.unoverride(clusterStoreInjectable);
|
||||
});
|
||||
|
||||
@ -115,8 +111,6 @@ describe("cluster-store", () => {
|
||||
|
||||
mockFs(mockOpts);
|
||||
|
||||
await runSetups(mainDi);
|
||||
|
||||
createCluster = mainDi.inject(createClusterInjectionToken);
|
||||
|
||||
clusterStore = mainDi.inject(clusterStoreInjectable);
|
||||
@ -239,8 +233,6 @@ describe("cluster-store", () => {
|
||||
|
||||
mockFs(mockOpts);
|
||||
|
||||
await runSetups(mainDi);
|
||||
|
||||
createCluster = mainDi.inject(createClusterInjectionToken);
|
||||
|
||||
clusterStore = mainDi.inject(clusterStoreInjectable);
|
||||
@ -325,8 +317,6 @@ users:
|
||||
|
||||
mockFs(mockOpts);
|
||||
|
||||
await runSetups(mainDi);
|
||||
|
||||
createCluster = mainDi.inject(createClusterInjectionToken);
|
||||
|
||||
clusterStore = mainDi.inject(clusterStoreInjectable);
|
||||
@ -371,8 +361,6 @@ users:
|
||||
|
||||
mockFs(mockOpts);
|
||||
|
||||
await runSetups(mainDi);
|
||||
|
||||
createCluster = mainDi.inject(createClusterInjectionToken);
|
||||
|
||||
clusterStore = mainDi.inject(clusterStoreInjectable);
|
||||
|
||||
@ -12,11 +12,10 @@ import getConfigurationFileModelInjectable from "../get-configuration-file-model
|
||||
import appVersionInjectable from "../get-configuration-file-model/app-version/app-version.injectable";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import hotbarStoreInjectable from "../hotbar-store.injectable";
|
||||
import { HotbarStore } from "../hotbar-store";
|
||||
import catalogCatalogEntityInjectable from "../catalog-entities/general-catalog-entities/implementations/catalog-catalog-entity.injectable";
|
||||
import { runSetups } from "../setupable-injection-token/run-setups";
|
||||
import type { HotbarStore } from "../hotbar-store";
|
||||
import catalogEntityRegistryInjectable from "../../main/catalog/catalog-entity-registry.injectable";
|
||||
|
||||
import directoryForUserDataInjectable
|
||||
from "../app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
|
||||
function getMockCatalogEntity(data: Partial<CatalogEntityData> & CatalogEntityKindData): CatalogEntity {
|
||||
return {
|
||||
@ -82,6 +81,9 @@ describe("HotbarStore", () => {
|
||||
di.permitSideEffects(getConfigurationFileModelInjectable);
|
||||
di.permitSideEffects(appVersionInjectable);
|
||||
|
||||
di.permitSideEffects(hotbarStoreInjectable);
|
||||
di.unoverride(hotbarStoreInjectable);
|
||||
|
||||
di.override(catalogEntityRegistryInjectable, () => ({
|
||||
addComputedSource: (id, source) => {},
|
||||
items: [
|
||||
@ -135,13 +137,7 @@ describe("HotbarStore", () => {
|
||||
],
|
||||
}));
|
||||
|
||||
di.override(hotbarStoreInjectable, () => {
|
||||
HotbarStore.resetInstance();
|
||||
|
||||
return HotbarStore.createInstance({
|
||||
catalogCatalogEntity: di.inject(catalogCatalogEntityInjectable),
|
||||
});
|
||||
});
|
||||
di.override(directoryForUserDataInjectable, () => "some-directory-for-user-data");
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@ -152,9 +148,9 @@ describe("HotbarStore", () => {
|
||||
beforeEach(async () => {
|
||||
mockFs();
|
||||
|
||||
await runSetups(di);
|
||||
|
||||
hotbarStore = di.inject(hotbarStoreInjectable);
|
||||
|
||||
hotbarStore.load();
|
||||
});
|
||||
|
||||
describe("load", () => {
|
||||
@ -320,7 +316,7 @@ describe("HotbarStore", () => {
|
||||
describe("given pre beta-5 configurations", () => {
|
||||
beforeEach(async () => {
|
||||
const configurationToBeMigrated = {
|
||||
"some-electron-app-path-for-user-data": {
|
||||
"some-directory-for-user-data": {
|
||||
"lens-hotbar-store.json": JSON.stringify({
|
||||
__internal__: {
|
||||
migrations: {
|
||||
@ -383,9 +379,9 @@ describe("HotbarStore", () => {
|
||||
|
||||
mockFs(configurationToBeMigrated);
|
||||
|
||||
await runSetups(di);
|
||||
|
||||
hotbarStore = di.inject(hotbarStoreInjectable);
|
||||
|
||||
hotbarStore.load();
|
||||
});
|
||||
|
||||
it("allows to retrieve a hotbar", () => {
|
||||
|
||||
@ -2,27 +2,27 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import type { AppPaths } from "./app-path-injection-token";
|
||||
import { appPathsInjectionToken } from "./app-path-injection-token";
|
||||
import getElectronAppPathInjectable from "../../main/app-paths/get-electron-app-path/get-electron-app-path.injectable";
|
||||
import { getDisForUnitTesting } from "../../test-utils/get-dis-for-unit-testing";
|
||||
import type { PathName } from "./app-path-names";
|
||||
import setElectronAppPathInjectable from "../../main/app-paths/set-electron-app-path/set-electron-app-path.injectable";
|
||||
import appNameInjectable from "../../main/app-paths/app-name/app-name.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 { DiContainer } from "@ogre-tools/injectable";
|
||||
|
||||
describe("app-paths", () => {
|
||||
let mainDi: DiContainer;
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let rendererDi: DiContainer;
|
||||
let runSetups: () => Promise<void[]>;
|
||||
let mainDi: DiContainer;
|
||||
|
||||
beforeEach(() => {
|
||||
const dis = getDisForUnitTesting({ doGeneralOverrides: true });
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
|
||||
mainDi = dis.mainDi;
|
||||
rendererDi = dis.rendererDi;
|
||||
runSetups = dis.runSetups;
|
||||
rendererDi = applicationBuilder.dis.rendererDi;
|
||||
mainDi = applicationBuilder.dis.mainDi;
|
||||
|
||||
const defaultAppPathsStub: AppPaths = {
|
||||
appData: "some-app-data",
|
||||
@ -43,27 +43,29 @@ describe("app-paths", () => {
|
||||
userData: "some-irrelevant-user-data",
|
||||
};
|
||||
|
||||
mainDi.override(
|
||||
getElectronAppPathInjectable,
|
||||
() =>
|
||||
(key: PathName): string | null =>
|
||||
defaultAppPathsStub[key],
|
||||
);
|
||||
applicationBuilder.beforeSetups(({ mainDi }) => {
|
||||
mainDi.override(
|
||||
getElectronAppPathInjectable,
|
||||
() =>
|
||||
(key: PathName): string | null =>
|
||||
defaultAppPathsStub[key],
|
||||
);
|
||||
|
||||
mainDi.override(
|
||||
setElectronAppPathInjectable,
|
||||
() =>
|
||||
(key: PathName, path: string): void => {
|
||||
defaultAppPathsStub[key] = path;
|
||||
},
|
||||
);
|
||||
mainDi.override(
|
||||
setElectronAppPathInjectable,
|
||||
() =>
|
||||
(key: PathName, path: string): void => {
|
||||
defaultAppPathsStub[key] = path;
|
||||
},
|
||||
);
|
||||
|
||||
mainDi.override(appNameInjectable, () => "some-app-name");
|
||||
mainDi.override(appNameInjectable, () => "some-app-name");
|
||||
});
|
||||
});
|
||||
|
||||
describe("normally", () => {
|
||||
beforeEach(async () => {
|
||||
await runSetups();
|
||||
await applicationBuilder.render();
|
||||
});
|
||||
|
||||
it("given in renderer, when injecting app paths, returns application specific app paths", () => {
|
||||
@ -115,12 +117,14 @@ describe("app-paths", () => {
|
||||
|
||||
describe("when running integration tests", () => {
|
||||
beforeEach(async () => {
|
||||
mainDi.override(
|
||||
directoryForIntegrationTestingInjectable,
|
||||
() => "some-integration-testing-app-data",
|
||||
);
|
||||
applicationBuilder.beforeSetups(({ mainDi }) => {
|
||||
mainDi.override(
|
||||
directoryForIntegrationTestingInjectable,
|
||||
() => "some-integration-testing-app-data",
|
||||
);
|
||||
});
|
||||
|
||||
await runSetups();
|
||||
await applicationBuilder.render();
|
||||
});
|
||||
|
||||
it("given in renderer, when injecting path for app data, has integration specific app data path", () => {
|
||||
|
||||
14
src/common/ipc/broadcast-message.injectable.ts
Normal file
14
src/common/ipc/broadcast-message.injectable.ts
Normal file
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { broadcastMessage } from "./ipc";
|
||||
|
||||
const broadcastMessageInjectable = getInjectable({
|
||||
id: "broadcast-message",
|
||||
instantiate: () => broadcastMessage,
|
||||
// causesSideEffects: true,
|
||||
});
|
||||
|
||||
export default broadcastMessageInjectable;
|
||||
@ -1,21 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import { beforeElectronIsReadyInjectionToken } from "../../main/start-main-application/before-electron-is-ready/before-electron-is-ready-injection-token";
|
||||
import { afterApplicationIsReadyInjectionToken } from "../../main/start-main-application/after-application-is-ready/after-application-is-ready-injection-token";
|
||||
|
||||
export const runSetups = async (di: DiContainer) => {
|
||||
await Promise.all(
|
||||
di
|
||||
.injectMany(beforeElectronIsReadyInjectionToken)
|
||||
.map((setupable) => setupable.run()),
|
||||
);
|
||||
|
||||
await Promise.all(
|
||||
di
|
||||
.injectMany(afterApplicationIsReadyInjectionToken)
|
||||
.map((setupable) => setupable.run()),
|
||||
);
|
||||
};
|
||||
@ -9,8 +9,8 @@ import { stdout, stderr } from "process";
|
||||
import extensionLoaderInjectable from "../extension-loader/extension-loader.injectable";
|
||||
import { runInAction } from "mobx";
|
||||
import updateExtensionsStateInjectable from "../extension-loader/update-extensions-state/update-extensions-state.injectable";
|
||||
import { getDisForUnitTesting } from "../../test-utils/get-dis-for-unit-testing";
|
||||
import mockFs from "mock-fs";
|
||||
import { getDiForUnitTesting } from "../../main/getDiForUnitTesting";
|
||||
|
||||
console = new Console(stdout, stderr);
|
||||
|
||||
@ -110,15 +110,15 @@ describe("ExtensionLoader", () => {
|
||||
let updateExtensionStateMock: jest.Mock;
|
||||
|
||||
beforeEach(() => {
|
||||
const dis = getDisForUnitTesting({ doGeneralOverrides: true });
|
||||
const di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||
|
||||
mockFs();
|
||||
|
||||
updateExtensionStateMock = jest.fn();
|
||||
|
||||
dis.mainDi.override(updateExtensionsStateInjectable, () => updateExtensionStateMock);
|
||||
di.override(updateExtensionsStateInjectable, () => updateExtensionStateMock);
|
||||
|
||||
extensionLoader = dis.mainDi.inject(extensionLoaderInjectable);
|
||||
extensionLoader = di.inject(extensionLoaderInjectable);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
||||
@ -2,7 +2,8 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { runSetups } from "../../common/setupable-injection-token/run-setups";
|
||||
import directoryForTempInjectable
|
||||
from "../../common/app-paths/directory-for-temp/directory-for-temp.injectable";
|
||||
|
||||
const logger = {
|
||||
silly: jest.fn(),
|
||||
@ -44,6 +45,8 @@ import { createClusterInjectionToken } from "../../common/cluster/create-cluster
|
||||
import authorizationReviewInjectable from "../../common/cluster/authorization-review.injectable";
|
||||
import listNamespacesInjectable from "../../common/cluster/list-namespaces.injectable";
|
||||
import createContextHandlerInjectable from "../context-handler/create-context-handler.injectable";
|
||||
import directoryForUserDataInjectable
|
||||
from "../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
|
||||
console = new Console(process.stdout, process.stderr); // fix mockFS
|
||||
|
||||
@ -80,14 +83,14 @@ describe("create clusters", () => {
|
||||
}),
|
||||
});
|
||||
|
||||
di.override(directoryForUserDataInjectable, () => "some-directory-for-user-data");
|
||||
di.override(directoryForTempInjectable, () => "some-directory-for-temp");
|
||||
di.override(authorizationReviewInjectable, () => () => () => Promise.resolve(true));
|
||||
di.override(listNamespacesInjectable, () => () => () => Promise.resolve([ "default" ]));
|
||||
di.override(createContextHandlerInjectable, () => () => {
|
||||
throw new Error("you should never come here");
|
||||
});
|
||||
|
||||
await runSetups(di);
|
||||
|
||||
createCluster = di.inject(createClusterInjectionToken);
|
||||
|
||||
jest.spyOn(Kubectl.prototype, "ensureKubectl").mockReturnValue(Promise.resolve(true));
|
||||
|
||||
@ -57,7 +57,10 @@ import path from "path";
|
||||
import spawnInjectable from "../child-process/spawn.injectable";
|
||||
import getConfigurationFileModelInjectable from "../../common/get-configuration-file-model/get-configuration-file-model.injectable";
|
||||
import appVersionInjectable from "../../common/get-configuration-file-model/app-version/app-version.injectable";
|
||||
import { runSetups } from "../../common/setupable-injection-token/run-setups";
|
||||
import directoryForUserDataInjectable
|
||||
from "../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
import directoryForTempInjectable
|
||||
from "../../common/app-paths/directory-for-temp/directory-for-temp.injectable";
|
||||
|
||||
console = new Console(stdout, stderr);
|
||||
|
||||
@ -100,6 +103,9 @@ describe("kube auth proxy tests", () => {
|
||||
|
||||
const di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||
|
||||
di.override(directoryForUserDataInjectable, () => "some-directory-for-user-data");
|
||||
di.override(directoryForTempInjectable, () => "some-directory-for-temp");
|
||||
|
||||
di.override(spawnInjectable, () => mockSpawn);
|
||||
|
||||
di.permitSideEffects(getConfigurationFileModelInjectable);
|
||||
@ -107,8 +113,6 @@ describe("kube auth proxy tests", () => {
|
||||
|
||||
mockFs(mockMinikubeConfig);
|
||||
|
||||
await runSetups(di);
|
||||
|
||||
createCluster = di.inject(createClusterInjectionToken);
|
||||
|
||||
createKubeAuthProxy = di.inject(createKubeAuthProxyInjectable);
|
||||
|
||||
@ -2,8 +2,13 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { runSetups } from "../../common/setupable-injection-token/run-setups";
|
||||
import directoryForUserDataInjectable
|
||||
from "../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
const logger = {
|
||||
silly: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
@ -57,6 +62,8 @@ describe("kubeconfig manager tests", () => {
|
||||
di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||
|
||||
di.override(directoryForTempInjectable, () => "some-directory-for-temp");
|
||||
di.override(directoryForUserDataInjectable, () => "some-directory-for-user-data");
|
||||
|
||||
|
||||
mockFs({
|
||||
"minikube-config.yml": JSON.stringify({
|
||||
@ -86,8 +93,6 @@ describe("kubeconfig manager tests", () => {
|
||||
throw new Error("you should never come here");
|
||||
});
|
||||
|
||||
await runSetups(di);
|
||||
|
||||
const createCluster = di.inject(createClusterInjectionToken);
|
||||
|
||||
createKubeconfigManager = di.inject(createKubeconfigManagerInjectable);
|
||||
|
||||
@ -17,8 +17,9 @@ import directoryForKubeConfigsInjectable from "../../../common/app-paths/directo
|
||||
import { ClusterStore } from "../../../common/cluster-store/cluster-store";
|
||||
import getConfigurationFileModelInjectable from "../../../common/get-configuration-file-model/get-configuration-file-model.injectable";
|
||||
import appVersionInjectable from "../../../common/get-configuration-file-model/app-version/app-version.injectable";
|
||||
import { runSetups } from "../../../common/setupable-injection-token/run-setups";
|
||||
import clusterManagerInjectable from "../../cluster-manager.injectable";
|
||||
import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
import directoryForTempInjectable from "../../../common/app-paths/directory-for-temp/directory-for-temp.injectable";
|
||||
|
||||
jest.mock("electron", () => ({
|
||||
app: {
|
||||
@ -44,6 +45,9 @@ describe("kubeconfig-sync.source tests", () => {
|
||||
|
||||
mockFs();
|
||||
|
||||
di.override(directoryForUserDataInjectable, () => "some-directory-for-user-data");
|
||||
di.override(directoryForTempInjectable, () => "some-directory-for-temp");
|
||||
|
||||
di.override(clusterStoreInjectable, () =>
|
||||
ClusterStore.createInstance({ createCluster: () => null }),
|
||||
);
|
||||
@ -51,8 +55,6 @@ describe("kubeconfig-sync.source tests", () => {
|
||||
di.permitSideEffects(getConfigurationFileModelInjectable);
|
||||
di.permitSideEffects(appVersionInjectable);
|
||||
|
||||
await runSetups(di);
|
||||
|
||||
computeDiff = computeDiffFor({
|
||||
directoryForKubeConfigs: di.inject(directoryForKubeConfigsInjectable),
|
||||
createCluster: di.inject(createClusterInjectionToken),
|
||||
|
||||
@ -10,7 +10,8 @@ import commandLineArgumentsInjectable from "../../utils/command-line-arguments.i
|
||||
import { pipeline } from "@ogre-tools/fp";
|
||||
import { find, startsWith, toLower, map } from "lodash/fp";
|
||||
import { whenApplicationIsLoadingInjectionToken } from "../../start-main-application/when-application-is-loading/when-application-is-loading-injection-token";
|
||||
import applicationWindowInjectable from "../../start-main-application/lens-window/application-window/application-window.injectable";
|
||||
import showApplicationWindowInjectable
|
||||
from "../../start-main-application/lens-window/show-application-window.injectable";
|
||||
|
||||
const setupDeepLinkingInjectable = getInjectable({
|
||||
id: "setup-deep-linking",
|
||||
@ -19,7 +20,7 @@ const setupDeepLinkingInjectable = getInjectable({
|
||||
const app = di.inject(electronAppInjectable);
|
||||
const logger = di.inject(loggerInjectable);
|
||||
const openDeepLinkForUrl = di.inject(openDeepLinkInjectable);
|
||||
const applicationWindow = di.inject(applicationWindowInjectable);
|
||||
const showApplicationWindow = di.inject(showApplicationWindowInjectable);
|
||||
|
||||
const firstInstanceCommandLineArguments = di.inject(
|
||||
commandLineArgumentsInjectable,
|
||||
@ -53,7 +54,7 @@ const setupDeepLinkingInjectable = getInjectable({
|
||||
async (_, secondInstanceCommandLineArguments) => {
|
||||
const url = getDeepLinkUrl(secondInstanceCommandLineArguments);
|
||||
|
||||
await applicationWindow.show();
|
||||
await showApplicationWindow();
|
||||
|
||||
if (url) {
|
||||
await openDeepLinkForUrl(url);
|
||||
|
||||
@ -6,14 +6,14 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import electronAppInjectable from "../electron-app.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import { whenApplicationIsLoadingInjectionToken } from "../../start-main-application/when-application-is-loading/when-application-is-loading-injection-token";
|
||||
import applicationWindowInjectable from "../../start-main-application/lens-window/application-window/application-window.injectable";
|
||||
import showApplicationWindowInjectable from "../../start-main-application/lens-window/show-application-window.injectable";
|
||||
|
||||
const setupMainWindowVisibilityAfterActivationInjectable = getInjectable({
|
||||
id: "setup-main-window-visibility-after-activation",
|
||||
|
||||
instantiate: (di) => {
|
||||
const app = di.inject(electronAppInjectable);
|
||||
const applicationWindow = di.inject(applicationWindowInjectable);
|
||||
const showApplicationWindow = di.inject(showApplicationWindowInjectable);
|
||||
const logger = di.inject(loggerInjectable);
|
||||
|
||||
return {
|
||||
@ -22,7 +22,7 @@ const setupMainWindowVisibilityAfterActivationInjectable = getInjectable({
|
||||
logger.info("APP:ACTIVATE", { hasVisibleWindows: windowIsVisible });
|
||||
|
||||
if (!windowIsVisible) {
|
||||
await applicationWindow.show();
|
||||
await showApplicationWindow();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { beforeElectronIsReadyInjectionToken } from "../../start-main-application/before-electron-is-ready/before-electron-is-ready-injection-token";
|
||||
import electronAppInjectable from "../electron-app.injectable";
|
||||
import { runManyFor } from "../../../common/runnable/run-many-for";
|
||||
import { afterWindowIsOpenedInjectionToken } from "../../start-main-application/after-window-is-opened/after-window-is-opened-injection-token";
|
||||
|
||||
const setupRunnablesAfterWindowIsOpenedInjectable = getInjectable({
|
||||
id: "setup-runnables-after-window-is-opened",
|
||||
|
||||
instantiate: (di) => {
|
||||
const afterWindowIsOpened = runManyFor(di)(afterWindowIsOpenedInjectionToken);
|
||||
|
||||
return {
|
||||
run: () => {
|
||||
const app = di.inject(electronAppInjectable);
|
||||
|
||||
app.on("browser-window-created", async () => {
|
||||
await afterWindowIsOpened();
|
||||
});
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
injectionToken: beforeElectronIsReadyInjectionToken,
|
||||
});
|
||||
|
||||
export default setupRunnablesAfterWindowIsOpenedInjectable;
|
||||
@ -9,7 +9,7 @@ import { beforeQuitOfBackEndInjectionToken } from "../../start-main-application/
|
||||
import electronAppInjectable from "../electron-app.injectable";
|
||||
import isIntegrationTestingInjectable from "../../../common/vars/is-integration-testing.injectable";
|
||||
import autoUpdaterInjectable from "../features/auto-updater.injectable";
|
||||
import { runManySyncFor } from "../../start-main-application/run-many-sync-for";
|
||||
import { runManySyncFor } from "../../../common/runnable/run-many-sync-for";
|
||||
|
||||
const setupRunnablesBeforeClosingOfApplicationInjectable = getInjectable({
|
||||
id: "setup-closing-of-application",
|
||||
|
||||
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { beforeQuitOfFrontEndInjectionToken } from "../../start-main-application/before-quit-of-front-end/before-quit-of-front-end-injection-token";
|
||||
import electronAppInjectable from "../electron-app.injectable";
|
||||
import { lensWindowInjectionToken } from "../../start-main-application/lens-window/application-window/lens-window-injection-token";
|
||||
import { pipeline } from "@ogre-tools/fp";
|
||||
import { filter, isEmpty } from "lodash/fp";
|
||||
|
||||
const hideDockForLastClosedWindowInjectable = getInjectable({
|
||||
id: "hide-dock-when-there-are-no-windows",
|
||||
|
||||
instantiate: (di) => {
|
||||
const app = di.inject(electronAppInjectable);
|
||||
const getLensWindows = () => di.injectMany(lensWindowInjectionToken);
|
||||
|
||||
return {
|
||||
run: () => {
|
||||
const visibleWindows = pipeline(
|
||||
getLensWindows(),
|
||||
filter(window => !!window.visible),
|
||||
);
|
||||
|
||||
if (isEmpty(visibleWindows)) {
|
||||
app.dock?.hide();
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
injectionToken: beforeQuitOfFrontEndInjectionToken,
|
||||
});
|
||||
|
||||
export default hideDockForLastClosedWindowInjectable;
|
||||
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import electronAppInjectable from "../electron-app.injectable";
|
||||
import { afterWindowIsOpenedInjectionToken } from "../../start-main-application/after-window-is-opened/after-window-is-opened-injection-token";
|
||||
|
||||
const showDockForFirstOpenedWindowInjectable = getInjectable({
|
||||
id: "show-dock-for-first-opened-window",
|
||||
|
||||
instantiate: (di) => {
|
||||
const app = di.inject(electronAppInjectable);
|
||||
|
||||
return {
|
||||
run: () => {
|
||||
app.dock?.show();
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
injectionToken: afterWindowIsOpenedInjectionToken,
|
||||
});
|
||||
|
||||
export default showDockForFirstOpenedWindowInjectable;
|
||||
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import electronAppInjectable from "../electron-app.injectable";
|
||||
|
||||
const waitForElectronToBeReadyInjectable = getInjectable({
|
||||
id: "wait-for-electron-to-be-ready",
|
||||
|
||||
instantiate: (di) => () => di.inject(electronAppInjectable).whenReady(),
|
||||
});
|
||||
|
||||
export default waitForElectronToBeReadyInjectable;
|
||||
@ -72,8 +72,21 @@ import showMessagePopupInjectable from "./electron-app/features/show-message-pop
|
||||
import clusterFramesInjectable from "../common/cluster-frames.injectable";
|
||||
import type { ClusterFrameInfo } from "../common/cluster-frames";
|
||||
import { observable } from "mobx";
|
||||
import createBrowserWindowInjectable from "./start-main-application/lens-window/application-window/create-browser-window.injectable";
|
||||
import type { BrowserWindow } from "electron";
|
||||
// import createBrowserWindowInjectable from "./start-main-application/lens-window/application-window/create-browser-window.injectable";
|
||||
import waitForElectronToBeReadyInjectable from "./electron-app/features/wait-for-electron-to-be-ready.injectable";
|
||||
|
||||
|
||||
import setupListenerForCurrentClusterFrameInjectable
|
||||
from "./start-main-application/lens-window/current-cluster-frame/setup-listener-for-current-cluster-frame.injectable";
|
||||
import ipcMainInjectable from "./app-paths/register-channel/ipc-main/ipc-main.injectable";
|
||||
import createElectronWindowForInjectable
|
||||
from "./start-main-application/lens-window/application-window/create-electron-window-for.injectable";
|
||||
import setupRunnablesAfterWindowIsOpenedInjectable
|
||||
from "./electron-app/before-application-is-ready/setup-runnables-after-window-is-opened.injectable";
|
||||
import sendToChannelInElectronBrowserWindowInjectable
|
||||
from "./start-main-application/lens-window/application-window/send-to-channel-in-electron-browser-window.injectable";
|
||||
|
||||
|
||||
|
||||
export const getDiForUnitTesting = (
|
||||
{ doGeneralOverrides } = { doGeneralOverrides: false },
|
||||
@ -180,6 +193,8 @@ const overrideRunnablesHavingSideEffects = (di: DiContainer) => {
|
||||
setupShellInjectable,
|
||||
setupSyncingOfWeblinksInjectable,
|
||||
setupSystemCaInjectable,
|
||||
setupListenerForCurrentClusterFrameInjectable,
|
||||
setupRunnablesAfterWindowIsOpenedInjectable,
|
||||
].forEach((injectable) => {
|
||||
di.override(injectable, () => ({ run: () => {} }));
|
||||
});
|
||||
@ -211,11 +226,20 @@ const overrideElectronFeatures = (di: DiContainer) => {
|
||||
di.override(disableHardwareAccelerationInjectable, () => () => {});
|
||||
di.override(shouldStartHiddenInjectable, () => true);
|
||||
di.override(showMessagePopupInjectable, () => () => {});
|
||||
di.override(waitForElectronToBeReadyInjectable, () => () => Promise.resolve());
|
||||
di.override(ipcMainInjectable, () => ({}));
|
||||
|
||||
di.override(createBrowserWindowInjectable, () => async () => ({
|
||||
di.override(createElectronWindowForInjectable, () => () => async () => ({
|
||||
show: () => {},
|
||||
hide: () => {},
|
||||
}) as unknown as BrowserWindow);
|
||||
|
||||
close: () => {},
|
||||
|
||||
send: (arg) => {
|
||||
const sendFake = di.inject(sendToChannelInElectronBrowserWindowInjectable);
|
||||
|
||||
sendFake(null, arg);
|
||||
},
|
||||
}));
|
||||
|
||||
di.override(
|
||||
getElectronAppPathInjectable,
|
||||
|
||||
@ -24,6 +24,8 @@ import { computed } from "mobx";
|
||||
import showAboutInjectable from "./show-about.injectable";
|
||||
import applicationWindowInjectable from "../start-main-application/lens-window/application-window/application-window.injectable";
|
||||
import reloadWindowInjectable from "../start-main-application/lens-window/reload-window.injectable";
|
||||
import showApplicationWindowInjectable
|
||||
from "../start-main-application/lens-window/show-application-window.injectable";
|
||||
|
||||
function ignoreIf(check: boolean, menuItems: MenuItemConstructorOptions[]) {
|
||||
return check ? [] : menuItems;
|
||||
@ -44,6 +46,7 @@ const applicationMenuItemsInjectable = getInjectable({
|
||||
const electronMenuItems = di.inject(electronMenuItemsInjectable);
|
||||
const showAbout = di.inject(showAboutInjectable);
|
||||
const applicationWindow = di.inject(applicationWindowInjectable);
|
||||
const showApplicationWindow = di.inject(showApplicationWindowInjectable);
|
||||
const reloadApplicationWindow = di.inject(reloadWindowInjectable, applicationWindow);
|
||||
|
||||
return computed((): MenuItemOpts[] => {
|
||||
@ -76,7 +79,7 @@ const applicationMenuItemsInjectable = getInjectable({
|
||||
{
|
||||
label: "Check for updates",
|
||||
click() {
|
||||
checkForUpdates().then(() => applicationWindow.show());
|
||||
checkForUpdates().then(() => showApplicationWindow());
|
||||
},
|
||||
},
|
||||
]),
|
||||
@ -294,7 +297,7 @@ const applicationMenuItemsInjectable = getInjectable({
|
||||
label: "Check for updates",
|
||||
click() {
|
||||
checkForUpdates().then(() =>
|
||||
applicationWindow.show(),
|
||||
showApplicationWindow(),
|
||||
);
|
||||
},
|
||||
},
|
||||
|
||||
@ -13,7 +13,7 @@ const navigateToRouteInjectable = getInjectable({
|
||||
instantiate: (di) => {
|
||||
const navigateToUrl = di.inject(navigateToUrlInjectionToken);
|
||||
|
||||
return (route, options) => {
|
||||
return async (route, options) => {
|
||||
const url = buildURL(route.path, {
|
||||
// TODO: enhance typing
|
||||
params: options?.parameters as any,
|
||||
@ -21,7 +21,7 @@ const navigateToRouteInjectable = getInjectable({
|
||||
fragment: options?.fragment,
|
||||
});
|
||||
|
||||
navigateToUrl(url, options);
|
||||
await navigateToUrl(url, options);
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
@ -12,8 +12,8 @@ const navigateToUrlInjectable = getInjectable({
|
||||
instantiate: (di) => {
|
||||
const navigate = di.inject(navigateInjectable);
|
||||
|
||||
return (url) => {
|
||||
navigate(url);
|
||||
return async (url) => {
|
||||
await navigate(url);
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
@ -18,7 +18,9 @@ import lensProtocolRouterMainInjectable from "../lens-protocol-router-main/lens-
|
||||
import extensionsStoreInjectable from "../../../extensions/extensions-store/extensions-store.injectable";
|
||||
import getConfigurationFileModelInjectable from "../../../common/get-configuration-file-model/get-configuration-file-model.injectable";
|
||||
import appVersionInjectable from "../../../common/get-configuration-file-model/app-version/app-version.injectable";
|
||||
import { runSetups } from "../../../common/setupable-injection-token/run-setups";
|
||||
import directoryForUserDataInjectable
|
||||
from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
|
||||
|
||||
jest.mock("../../../common/ipc");
|
||||
|
||||
@ -47,7 +49,7 @@ describe("protocol router tests", () => {
|
||||
di.permitSideEffects(getConfigurationFileModelInjectable);
|
||||
di.permitSideEffects(appVersionInjectable);
|
||||
|
||||
await runSetups(di);
|
||||
di.override(directoryForUserDataInjectable, () => "some-directory-for-user-data");
|
||||
|
||||
extensionLoader = di.inject(extensionLoaderInjectable);
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import extensionLoaderInjectable from "../../../extensions/extension-loader/extension-loader.injectable";
|
||||
import { LensProtocolRouterMain } from "./lens-protocol-router-main";
|
||||
import extensionsStoreInjectable from "../../../extensions/extensions-store/extensions-store.injectable";
|
||||
import applicationWindowInjectable from "../../start-main-application/lens-window/application-window/application-window.injectable";
|
||||
import showApplicationWindowInjectable from "../../start-main-application/lens-window/show-application-window.injectable";
|
||||
|
||||
const lensProtocolRouterMainInjectable = getInjectable({
|
||||
id: "lens-protocol-router-main",
|
||||
@ -15,7 +15,7 @@ const lensProtocolRouterMainInjectable = getInjectable({
|
||||
new LensProtocolRouterMain({
|
||||
extensionLoader: di.inject(extensionLoaderInjectable),
|
||||
extensionsStore: di.inject(extensionsStoreInjectable),
|
||||
applicationWindow: di.inject(applicationWindowInjectable),
|
||||
showApplicationWindow: di.inject(showApplicationWindowInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@ -14,9 +14,6 @@ import { ProtocolHandlerInvalid } from "../../../common/protocol-handler";
|
||||
import { disposer, noop } from "../../../common/utils";
|
||||
import type { ExtensionLoader } from "../../../extensions/extension-loader";
|
||||
import type { ExtensionsStore } from "../../../extensions/extensions-store/extensions-store";
|
||||
import type {
|
||||
LensWindow,
|
||||
} from "../../start-main-application/lens-window/application-window/lens-window-injection-token";
|
||||
|
||||
export interface FallbackHandler {
|
||||
(name: string): Promise<boolean>;
|
||||
@ -42,7 +39,7 @@ function checkHost<Query>(url: URLParse<Query>): boolean {
|
||||
interface Dependencies {
|
||||
extensionLoader: ExtensionLoader;
|
||||
extensionsStore: ExtensionsStore;
|
||||
applicationWindow: LensWindow;
|
||||
showApplicationWindow: () => Promise<void>;
|
||||
}
|
||||
|
||||
export class LensProtocolRouterMain extends proto.LensProtocolRouter {
|
||||
@ -79,7 +76,7 @@ export class LensProtocolRouterMain extends proto.LensProtocolRouter {
|
||||
throw new proto.RoutingError(proto.RoutingErrorType.INVALID_PROTOCOL, url);
|
||||
}
|
||||
|
||||
this.dependencies.applicationWindow.show().catch(noop);
|
||||
this.dependencies.showApplicationWindow().catch(noop);
|
||||
const routeInternally = checkHost(url);
|
||||
|
||||
logger.info(`${proto.LensProtocolRouter.LoggingPrefix}: routing ${url.toString()}`);
|
||||
|
||||
@ -14,7 +14,9 @@ import asyncFn from "@async-fn/jest";
|
||||
import parseRequestInjectable from "./parse-request.injectable";
|
||||
import { contentTypes } from "./router-content-types";
|
||||
import mockFs from "mock-fs";
|
||||
import { runSetups } from "../../common/setupable-injection-token/run-setups";
|
||||
import directoryForUserDataInjectable
|
||||
from "../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
|
||||
|
||||
describe("router", () => {
|
||||
let router: Router;
|
||||
@ -28,6 +30,7 @@ describe("router", () => {
|
||||
mockFs();
|
||||
|
||||
di.override(parseRequestInjectable, () => () => Promise.resolve({ payload: "some-payload" }));
|
||||
di.override(directoryForUserDataInjectable, () => "some-directory-for-user-data");
|
||||
|
||||
const injectable = getInjectable({
|
||||
id: "some-route",
|
||||
@ -43,8 +46,6 @@ describe("router", () => {
|
||||
|
||||
di.register(injectable);
|
||||
|
||||
await runSetups(di);
|
||||
|
||||
router = di.inject(routerInjectable);
|
||||
});
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { Runnable } from "../run-many-for";
|
||||
import type { Runnable } from "../../../common/runnable/run-many-for";
|
||||
|
||||
export const afterApplicationIsLoadedInjectionToken = getInjectionToken<Runnable>({
|
||||
id: "after-application-is-loaded",
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { Runnable } from "../run-many-for";
|
||||
import type { Runnable } from "../../../common/runnable/run-many-for";
|
||||
|
||||
export const afterRootFrameIsReadyInjectionToken = getInjectionToken<Runnable>({
|
||||
id: "after-root-frame-is-ready",
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { Runnable } from "../../../common/runnable/run-many-for";
|
||||
|
||||
export const afterWindowIsOpenedInjectionToken = getInjectionToken<Runnable>({
|
||||
id: "after-window-is-opened",
|
||||
});
|
||||
@ -3,7 +3,7 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { Runnable } from "../run-many-for";
|
||||
import type { Runnable } from "../../../common/runnable/run-many-for";
|
||||
|
||||
export const beforeApplicationIsLoadingInjectionToken = getInjectionToken<Runnable>({
|
||||
id: "before-application-is-loading",
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { RunnableSync } from "../run-many-sync-for";
|
||||
import type { RunnableSync } from "../../../common/runnable/run-many-sync-for";
|
||||
|
||||
export const beforeElectronIsReadyInjectionToken =
|
||||
getInjectionToken<RunnableSync>({
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { RunnableSync } from "../run-many-sync-for";
|
||||
import type { RunnableSync } from "../../../common/runnable/run-many-sync-for";
|
||||
|
||||
export const beforeQuitOfBackEndInjectionToken =
|
||||
getInjectionToken<RunnableSync>({
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { RunnableSync } from "../run-many-sync-for";
|
||||
import type { RunnableSync } from "../../../common/runnable/run-many-sync-for";
|
||||
|
||||
export const beforeQuitOfFrontEndInjectionToken =
|
||||
getInjectionToken<RunnableSync>({
|
||||
|
||||
@ -3,86 +3,28 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { BrowserWindow } from "electron";
|
||||
import type {
|
||||
SendToViewArgs,
|
||||
} from "../application-window/lens-window-injection-token";
|
||||
import {
|
||||
lensWindowInjectionToken,
|
||||
} from "../application-window/lens-window-injection-token";
|
||||
import { lensWindowInjectionToken } from "../application-window/lens-window-injection-token";
|
||||
import createLensWindowInjectable from "../application-window/create-lens-window.injectable";
|
||||
|
||||
const applicationIsLoadingWindowInjectable = getInjectable({
|
||||
id: "application-is-loading-window",
|
||||
|
||||
instantiate: () => {
|
||||
let loadingWindow: BrowserWindow;
|
||||
instantiate: (di) => {
|
||||
const createLensWindow = di.inject(createLensWindowInjectable);
|
||||
|
||||
const hideWindow = () => {
|
||||
loadingWindow?.hide();
|
||||
};
|
||||
|
||||
return {
|
||||
show: async () => {
|
||||
if (!loadingWindow) {
|
||||
loadingWindow = await createLoadingWindow();
|
||||
}
|
||||
|
||||
loadingWindow.show();
|
||||
},
|
||||
|
||||
hide: hideWindow,
|
||||
|
||||
close: () => {
|
||||
hideWindow();
|
||||
|
||||
loadingWindow = null;
|
||||
},
|
||||
|
||||
send: async ({ channel, frameInfo, data = [] }: SendToViewArgs) => {
|
||||
if (!loadingWindow) {
|
||||
loadingWindow = await createLoadingWindow();
|
||||
}
|
||||
|
||||
if (frameInfo) {
|
||||
loadingWindow.webContents.sendToFrame(
|
||||
[frameInfo.processId, frameInfo.frameId],
|
||||
channel,
|
||||
...data,
|
||||
);
|
||||
|
||||
} else {
|
||||
loadingWindow.webContents.send(channel, ...data);
|
||||
}
|
||||
},
|
||||
};
|
||||
return createLensWindow({
|
||||
id: "splash",
|
||||
title: "Loading",
|
||||
getContentUrl: () => "static://splash.html",
|
||||
defaultWidth: 500,
|
||||
defaultHeight: 300,
|
||||
resizable: false,
|
||||
windowFrameUtilitiesAreShown: false,
|
||||
centered: true,
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: lensWindowInjectionToken,
|
||||
|
||||
causesSideEffects: true,
|
||||
});
|
||||
|
||||
export default applicationIsLoadingWindowInjectable;
|
||||
|
||||
const createLoadingWindow = async () => {
|
||||
const loadingWindow = new BrowserWindow({
|
||||
width: 500,
|
||||
height: 300,
|
||||
backgroundColor: "#1e2124",
|
||||
center: true,
|
||||
frame: false,
|
||||
resizable: false,
|
||||
show: false,
|
||||
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
contextIsolation: false,
|
||||
nodeIntegrationInSubFrames: true,
|
||||
nativeWindowOpen: true,
|
||||
},
|
||||
});
|
||||
|
||||
await loadingWindow.loadURL("static://splash.html");
|
||||
|
||||
return loadingWindow;
|
||||
};
|
||||
|
||||
@ -2,20 +2,31 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
|
||||
import windowStateKeeper from "electron-window-state";
|
||||
|
||||
interface WindowStateConfiguration {
|
||||
id: string;
|
||||
defaultHeight: number;
|
||||
defaultWidth: number;
|
||||
}
|
||||
|
||||
const applicationWindowStateInjectable = getInjectable({
|
||||
id: "application-window-state",
|
||||
|
||||
instantiate: () => {
|
||||
console.log("asdasd");
|
||||
instantiate: (
|
||||
di,
|
||||
{ id, defaultHeight, defaultWidth }: WindowStateConfiguration,
|
||||
) =>
|
||||
windowStateKeeper({
|
||||
defaultHeight,
|
||||
defaultWidth,
|
||||
file: `window-state-for-${id}.json`,
|
||||
}),
|
||||
|
||||
return windowStateKeeper({
|
||||
defaultHeight: 900,
|
||||
defaultWidth: 1440,
|
||||
});
|
||||
},
|
||||
lifecycle: lifecycleEnum.keyedSingleton({
|
||||
getInstanceKey: (di, { id }: WindowStateConfiguration) => id,
|
||||
}),
|
||||
});
|
||||
|
||||
export default applicationWindowStateInjectable;
|
||||
|
||||
@ -3,56 +3,63 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import createBrowserWindowInjectable from "./create-browser-window.injectable";
|
||||
import type {
|
||||
SendToViewArgs } from "./lens-window-injection-token";
|
||||
import {
|
||||
lensWindowInjectionToken,
|
||||
} from "./lens-window-injection-token";
|
||||
import type { BrowserWindow } from "electron";
|
||||
import sendToChannelInElectronBrowserWindowInjectable from "./send-to-channel-in-electron-browser-window.injectable";
|
||||
import { lensWindowInjectionToken } from "./lens-window-injection-token";
|
||||
import createLensWindowInjectable from "./create-lens-window.injectable";
|
||||
import lensProxyPortNumberStateInjectable from "../../../lens-proxy-port-number-state.injectable";
|
||||
import isMacInjectable from "../../../../common/vars/is-mac.injectable";
|
||||
import appNameInjectable from "../../../app-paths/app-name/app-name.injectable";
|
||||
import appEventBusInjectable from "../../../../common/app-event-bus/app-event-bus.injectable";
|
||||
import { delay } from "../../../../common/utils";
|
||||
import { bundledExtensionsLoaded } from "../../../../common/ipc/extension-handling";
|
||||
import ipcMainInjectable from "../../../app-paths/register-channel/ipc-main/ipc-main.injectable";
|
||||
|
||||
const applicationWindowInjectable = getInjectable({
|
||||
id: "application-window",
|
||||
|
||||
instantiate: (di) => {
|
||||
const createBrowserWindow = di.inject(createBrowserWindowInjectable);
|
||||
const createLensWindow = di.inject(createLensWindowInjectable);
|
||||
const isMac = di.inject(isMacInjectable);
|
||||
const applicationName = di.inject(appNameInjectable);
|
||||
const appEventBus = di.inject(appEventBusInjectable);
|
||||
const ipcMain = di.inject(ipcMainInjectable);
|
||||
|
||||
let browserWindow: BrowserWindow = null;
|
||||
|
||||
const hideWindow = () => {
|
||||
browserWindow?.hide();
|
||||
};
|
||||
|
||||
const sendToChannelInLensWindow = di.inject(
|
||||
sendToChannelInElectronBrowserWindowInjectable,
|
||||
const lensProxyPortNumberState = di.inject(
|
||||
lensProxyPortNumberStateInjectable,
|
||||
);
|
||||
|
||||
return {
|
||||
show: async () => {
|
||||
if (!browserWindow) {
|
||||
browserWindow = await createBrowserWindow("only-application-window");
|
||||
}
|
||||
const getContentUrl = () => `http://localhost:${lensProxyPortNumberState.get()}`;
|
||||
|
||||
browserWindow.show();
|
||||
return createLensWindow({
|
||||
id: "only-application-window",
|
||||
title: applicationName,
|
||||
defaultHeight: 900,
|
||||
defaultWidth: 1440,
|
||||
getContentUrl,
|
||||
resizable: true,
|
||||
windowFrameUtilitiesAreShown: isMac,
|
||||
centered: false,
|
||||
|
||||
onFocus: () => {
|
||||
appEventBus.emit({ name: "app", action: "focus" });
|
||||
},
|
||||
|
||||
hide: hideWindow,
|
||||
|
||||
close: () => {
|
||||
hideWindow();
|
||||
|
||||
browserWindow = null;
|
||||
onBlur: () => {
|
||||
appEventBus.emit({ name: "app", action: "blur" });
|
||||
},
|
||||
|
||||
send: async (args: SendToViewArgs) => {
|
||||
if (!browserWindow) {
|
||||
browserWindow = await createBrowserWindow("only-application-window");
|
||||
}
|
||||
|
||||
return sendToChannelInLensWindow(browserWindow, args);
|
||||
onDomReady: () => {
|
||||
appEventBus.emit({ name: "app", action: "dom-ready" });
|
||||
},
|
||||
};
|
||||
|
||||
beforeOpen: async () => {
|
||||
const viewHasLoaded = new Promise<void>((resolve) => {
|
||||
ipcMain.once(bundledExtensionsLoaded, () => resolve());
|
||||
});
|
||||
|
||||
await viewHasLoaded;
|
||||
await delay(50); // wait just a bit longer to let the first round of rendering happen
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: lensWindowInjectionToken,
|
||||
|
||||
@ -4,32 +4,51 @@
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import loggerInjectable from "../../../../common/logger.injectable";
|
||||
import appNameInjectable from "../../../app-paths/app-name/app-name.injectable";
|
||||
import applicationWindowStateInjectable from "./application-window-state.injectable";
|
||||
import lensProxyPortNumberStateInjectable from "../../../lens-proxy-port-number-state.injectable";
|
||||
import isMacInjectable from "../../../../common/vars/is-mac.injectable";
|
||||
import { BrowserWindow, ipcMain } from "electron";
|
||||
import { delay, openBrowser } from "../../../../common/utils";
|
||||
import { bundledExtensionsLoaded } from "../../../../common/ipc/extension-handling";
|
||||
import electronAppInjectable from "../../../electron-app/electron-app.injectable";
|
||||
import appEventBusInjectable from "../../../../common/app-event-bus/app-event-bus.injectable";
|
||||
import { BrowserWindow } from "electron";
|
||||
import { openBrowser } from "../../../../common/utils";
|
||||
import type { SendToViewArgs } from "./lens-window-injection-token";
|
||||
import sendToChannelInElectronBrowserWindowInjectable from "./send-to-channel-in-electron-browser-window.injectable";
|
||||
import type { LensWindow } from "./create-lens-window.injectable";
|
||||
|
||||
const createBrowserWindowInjectable = getInjectable({
|
||||
id: "create-browser-window",
|
||||
interface ElectronWindowConfiguration {
|
||||
id: string;
|
||||
title: string;
|
||||
defaultHeight: number;
|
||||
defaultWidth: number;
|
||||
getContentUrl: () => string;
|
||||
resizable: boolean;
|
||||
windowFrameUtilitiesAreShown: boolean;
|
||||
centered: boolean;
|
||||
|
||||
beforeOpen?: () => Promise<void>;
|
||||
onClose: () => void;
|
||||
onFocus?: () => void;
|
||||
onBlur?: () => void;
|
||||
onDomReady?: () => void;
|
||||
}
|
||||
|
||||
const createElectronWindowFor = getInjectable({
|
||||
id: "create-electron-window-for",
|
||||
|
||||
instantiate: (di) => {
|
||||
const logger = di.inject(loggerInjectable);
|
||||
const applicationName = di.inject(appNameInjectable);
|
||||
const isMac = di.inject(isMacInjectable);
|
||||
const appEventBus = di.inject(appEventBusInjectable);
|
||||
|
||||
const lensProxyPortNumberState = di.inject(
|
||||
lensProxyPortNumberStateInjectable,
|
||||
const sendToChannelInLensWindow = di.inject(
|
||||
sendToChannelInElectronBrowserWindowInjectable,
|
||||
);
|
||||
|
||||
return async (id: string) => {
|
||||
const applicationWindowState = di.inject(applicationWindowStateInjectable);
|
||||
const app = di.inject(electronAppInjectable);
|
||||
return (configuration: ElectronWindowConfiguration) => async (): Promise<LensWindow> => {
|
||||
const applicationWindowState = di.inject(
|
||||
applicationWindowStateInjectable,
|
||||
{
|
||||
id: configuration.id,
|
||||
defaultHeight: configuration.defaultHeight,
|
||||
defaultWidth: configuration.defaultWidth,
|
||||
},
|
||||
);
|
||||
|
||||
const { width, height, x, y } = applicationWindowState;
|
||||
|
||||
@ -38,13 +57,16 @@ const createBrowserWindowInjectable = getInjectable({
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
title: applicationName,
|
||||
title: configuration.title,
|
||||
resizable: configuration.resizable,
|
||||
center: configuration.centered,
|
||||
frame: configuration.windowFrameUtilitiesAreShown,
|
||||
show: false,
|
||||
minWidth: 700, // accommodate 800 x 600 display minimum
|
||||
minHeight: 500, // accommodate 800 x 600 display minimum
|
||||
titleBarStyle: isMac ? "hiddenInset" : "hidden",
|
||||
frame: isMac,
|
||||
backgroundColor: "#1e2124",
|
||||
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
nodeIntegrationInSubFrames: true,
|
||||
@ -56,48 +78,51 @@ const createBrowserWindowInjectable = getInjectable({
|
||||
|
||||
applicationWindowState.manage(browserWindow);
|
||||
|
||||
// open external links in default browser (target=_blank, window.open)
|
||||
browserWindow
|
||||
.on("focus", () => {
|
||||
appEventBus.emit({ name: "app", action: "focus" });
|
||||
configuration.onFocus?.();
|
||||
})
|
||||
|
||||
.on("blur", () => {
|
||||
appEventBus.emit({ name: "app", action: "blur" });
|
||||
configuration.onBlur?.();
|
||||
})
|
||||
|
||||
.on("closed", () => {
|
||||
// clean up
|
||||
configuration.onClose();
|
||||
applicationWindowState.unmanage();
|
||||
// this.mainWindow = null;
|
||||
// this.splashWindow = null;
|
||||
app.dock?.hide(); // hide icon in dock (mac-os)
|
||||
})
|
||||
|
||||
.webContents.on("dom-ready", () => {
|
||||
appEventBus.emit({ name: "app", action: "dom-ready" });
|
||||
configuration.onDomReady?.();
|
||||
})
|
||||
|
||||
.on("did-fail-load", (_event, code, desc) => {
|
||||
logger.error(`[WINDOW-MANAGER]: Failed to load Main window`, {
|
||||
code,
|
||||
desc,
|
||||
});
|
||||
logger.error(
|
||||
`[CREATE-ELECTRON-WINDOW]: Failed to load window "${configuration.id}"`,
|
||||
{
|
||||
code,
|
||||
desc,
|
||||
},
|
||||
);
|
||||
})
|
||||
|
||||
.on("did-finish-load", () => {
|
||||
logger.info("[WINDOW-MANAGER]: Main window loaded");
|
||||
logger.info(
|
||||
`[CREATE-ELECTRON-WINDOW]: Window "${configuration.id}" loaded`,
|
||||
);
|
||||
})
|
||||
|
||||
.on("will-attach-webview", (event, webPreferences, params) => {
|
||||
logger.debug("[WINDOW-MANAGER]: Attaching webview");
|
||||
logger.debug(
|
||||
`[CREATE-ELECTRON-WINDOW]: Attaching webview to window "${configuration.id}"`,
|
||||
);
|
||||
// Following is security recommendations because we allow webview tag (webviewTag: true)
|
||||
// suggested by https://www.electronjs.org/docs/tutorial/security#11-verify-webview-options-before-creation
|
||||
// and https://www.electronjs.org/docs/tutorial/security#10-do-not-use-allowpopups
|
||||
|
||||
if (webPreferences.preload) {
|
||||
logger.warn(
|
||||
"[WINDOW-MANAGER]: Strip away preload scripts of webview",
|
||||
"[CREATE-ELECTRON-WINDOW]: Strip away preload scripts of webview",
|
||||
);
|
||||
delete webPreferences.preload;
|
||||
}
|
||||
@ -105,14 +130,14 @@ const createBrowserWindowInjectable = getInjectable({
|
||||
// @ts-expect-error some electron version uses webPreferences.preloadURL/webPreferences.preload
|
||||
if (webPreferences.preloadURL) {
|
||||
logger.warn(
|
||||
"[WINDOW-MANAGER]: Strip away preload scripts of webview",
|
||||
"[CREATE-ELECTRON-WINDOW]: Strip away preload scripts of webview",
|
||||
);
|
||||
delete webPreferences.preload;
|
||||
}
|
||||
|
||||
if (params.allowpopups) {
|
||||
logger.warn(
|
||||
"[WINDOW-MANAGER]: We do not allow allowpopups props, stop webview from renderer",
|
||||
"[CREATE-ELECTRON-WINDOW]: We do not allow allowpopups props, stop webview from renderer",
|
||||
);
|
||||
|
||||
// event.preventDefault() will destroy the guest page.
|
||||
@ -127,32 +152,35 @@ const createBrowserWindowInjectable = getInjectable({
|
||||
|
||||
.setWindowOpenHandler((details) => {
|
||||
openBrowser(details.url).catch((error) => {
|
||||
logger.error("[WINDOW-MANAGER]: failed to open browser", { error });
|
||||
logger.error("[CREATE-ELECTRON-WINDOW]: failed to open browser", {
|
||||
error,
|
||||
});
|
||||
});
|
||||
|
||||
return { action: "deny" };
|
||||
});
|
||||
|
||||
const contentUrl = `http://localhost:${lensProxyPortNumberState.get()}`;
|
||||
const contentUrl = configuration.getContentUrl();
|
||||
|
||||
logger.info(
|
||||
`[WINDOW-MANAGER]: Loading Main window from url: ${contentUrl} ...`,
|
||||
`[CREATE-ELECTRON-WINDOW]: Loading content for window "${configuration.id}" from url: ${contentUrl}...`,
|
||||
);
|
||||
|
||||
await browserWindow.loadURL(contentUrl);
|
||||
|
||||
const viewHasLoaded = new Promise<void>((resolve) => {
|
||||
ipcMain.once(bundledExtensionsLoaded, () => resolve());
|
||||
});
|
||||
await configuration.beforeOpen?.();
|
||||
|
||||
await viewHasLoaded;
|
||||
await delay(50); // wait just a bit longer to let the first round of rendering happen
|
||||
return {
|
||||
show: () => browserWindow.show(),
|
||||
close: () => browserWindow.close(),
|
||||
|
||||
return browserWindow;
|
||||
send: (args: SendToViewArgs) =>
|
||||
sendToChannelInLensWindow(browserWindow, args),
|
||||
};
|
||||
};
|
||||
},
|
||||
|
||||
causesSideEffects: true,
|
||||
});
|
||||
|
||||
export default createBrowserWindowInjectable;
|
||||
export default createElectronWindowFor;
|
||||
@ -0,0 +1,89 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { SendToViewArgs } from "./lens-window-injection-token";
|
||||
import createElectronWindowForInjectable from "./create-electron-window-for.injectable";
|
||||
|
||||
export interface LensWindow {
|
||||
show: () => void;
|
||||
close: () => void;
|
||||
send: (args: SendToViewArgs) => void;
|
||||
}
|
||||
|
||||
interface LensWindowConfiguration {
|
||||
id: string;
|
||||
title: string;
|
||||
defaultHeight: number;
|
||||
defaultWidth: number;
|
||||
getContentUrl: () => string;
|
||||
resizable: boolean;
|
||||
windowFrameUtilitiesAreShown: boolean;
|
||||
centered: boolean;
|
||||
|
||||
beforeOpen?: () => Promise<void>;
|
||||
onFocus?: () => void;
|
||||
onBlur?: () => void;
|
||||
onDomReady?: () => void;
|
||||
}
|
||||
|
||||
const createLensWindowInjectable = getInjectable({
|
||||
id: "create-lens-window",
|
||||
|
||||
instantiate:
|
||||
(di) =>
|
||||
(configuration: LensWindowConfiguration) => {
|
||||
let browserWindow: LensWindow = null;
|
||||
|
||||
const createElectronWindow = di.inject(createElectronWindowForInjectable)(
|
||||
{
|
||||
id: configuration.id,
|
||||
title: configuration.title,
|
||||
defaultHeight: configuration.defaultHeight,
|
||||
defaultWidth: configuration.defaultWidth,
|
||||
getContentUrl: configuration.getContentUrl,
|
||||
resizable: configuration.resizable,
|
||||
windowFrameUtilitiesAreShown: configuration.windowFrameUtilitiesAreShown,
|
||||
centered: configuration.centered,
|
||||
onFocus: configuration.onFocus,
|
||||
onBlur: configuration.onBlur,
|
||||
onDomReady: configuration.onDomReady,
|
||||
beforeOpen: configuration.beforeOpen,
|
||||
|
||||
onClose: () => {
|
||||
browserWindow = null;
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
get visible() {
|
||||
return !!this.browserWindow;
|
||||
},
|
||||
|
||||
show: async () => {
|
||||
if (!browserWindow) {
|
||||
browserWindow = await createElectronWindow();
|
||||
}
|
||||
|
||||
browserWindow.show();
|
||||
},
|
||||
|
||||
close: () => {
|
||||
browserWindow?.close();
|
||||
browserWindow = null;
|
||||
},
|
||||
|
||||
send: async (args: SendToViewArgs) => {
|
||||
if (!browserWindow) {
|
||||
browserWindow = await createElectronWindow();
|
||||
}
|
||||
|
||||
return browserWindow.send(args);
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default createLensWindowInjectable;
|
||||
@ -13,9 +13,9 @@ export interface SendToViewArgs {
|
||||
|
||||
export interface LensWindow {
|
||||
show: () => Promise<void>;
|
||||
hide: () => void;
|
||||
close: () => void;
|
||||
send: (args: SendToViewArgs) => Promise<void>;
|
||||
visible: boolean;
|
||||
}
|
||||
|
||||
export const lensWindowInjectionToken = getInjectionToken<LensWindow>({
|
||||
|
||||
@ -11,7 +11,7 @@ const sendToChannelInElectronBrowserWindowInjectable = getInjectable({
|
||||
|
||||
instantiate:
|
||||
() =>
|
||||
async (
|
||||
(
|
||||
browserWindow: BrowserWindow,
|
||||
{ channel, frameInfo, data = [] }: SendToViewArgs,
|
||||
) => {
|
||||
|
||||
@ -26,6 +26,8 @@ const setupListenerForCurrentClusterFrameInjectable = getInjectable({
|
||||
},
|
||||
}),
|
||||
|
||||
causesSideEffects: true,
|
||||
|
||||
injectionToken: whenApplicationIsLoadingInjectionToken,
|
||||
});
|
||||
|
||||
|
||||
@ -5,16 +5,16 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { lensWindowInjectionToken } from "../application-window/lens-window-injection-token";
|
||||
|
||||
const hideAllWindowsInjectable = getInjectable({
|
||||
id: "hide-all-windows",
|
||||
const closeAllWindowsInjectable = getInjectable({
|
||||
id: "close-all-windows",
|
||||
|
||||
instantiate: (di) => () => {
|
||||
const lensWindows = di.injectMany(lensWindowInjectionToken);
|
||||
|
||||
lensWindows.forEach((lensWindow) => {
|
||||
lensWindow.hide();
|
||||
lensWindow.close();
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
export default hideAllWindowsInjectable;
|
||||
export default closeAllWindowsInjectable;
|
||||
@ -4,8 +4,9 @@
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { iter } from "../../../common/utils";
|
||||
import applicationWindowInjectable from "./application-window/application-window.injectable";
|
||||
import clusterFramesInjectable from "../../../common/cluster-frames.injectable";
|
||||
import showApplicationWindowInjectable from "./show-application-window.injectable";
|
||||
import applicationWindowInjectable from "./application-window/application-window.injectable";
|
||||
|
||||
const navigateForExtensionInjectable = getInjectable({
|
||||
id: "navigate-for-extension",
|
||||
@ -13,6 +14,7 @@ const navigateForExtensionInjectable = getInjectable({
|
||||
instantiate: (di) => {
|
||||
const applicationWindow = di.inject(applicationWindowInjectable);
|
||||
const clusterFrames = di.inject(clusterFramesInjectable);
|
||||
const showApplicationWindow = di.inject(showApplicationWindowInjectable);
|
||||
|
||||
return async (
|
||||
extId: string,
|
||||
@ -20,7 +22,7 @@ const navigateForExtensionInjectable = getInjectable({
|
||||
params?: Record<string, any>,
|
||||
frameId?: number,
|
||||
) => {
|
||||
await applicationWindow.show();
|
||||
await showApplicationWindow();
|
||||
|
||||
const frameInfo = iter.find(
|
||||
clusterFrames.values(),
|
||||
|
||||
@ -7,16 +7,18 @@ import { iter } from "../../../common/utils";
|
||||
import applicationWindowInjectable from "./application-window/application-window.injectable";
|
||||
import clusterFramesInjectable from "../../../common/cluster-frames.injectable";
|
||||
import { IpcRendererNavigationEvents } from "../../../renderer/navigation/events";
|
||||
import showApplicationWindowInjectable from "./show-application-window.injectable";
|
||||
|
||||
const navigateInjectable = getInjectable({
|
||||
id: "navigate",
|
||||
|
||||
instantiate: (di) => {
|
||||
const applicationWindow = di.inject(applicationWindowInjectable);
|
||||
const showApplicationWindow = di.inject(showApplicationWindowInjectable);
|
||||
const clusterFrames = di.inject(clusterFramesInjectable);
|
||||
|
||||
return async (url: string, frameId?: number) => {
|
||||
await applicationWindow.show();
|
||||
await showApplicationWindow();
|
||||
|
||||
const frameInfo = iter.find(
|
||||
clusterFrames.values(),
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import applicationIsLoadingWindowInjectable
|
||||
from "./application-is-loading-window/application-is-loading-window.injectable";
|
||||
import applicationWindowInjectable from "./application-window/application-window.injectable";
|
||||
|
||||
const showApplicationWindowInjectable = getInjectable({
|
||||
id: "show-application-window",
|
||||
|
||||
instantiate: (di) => {
|
||||
const applicationWindow = di.inject(applicationWindowInjectable);
|
||||
|
||||
const applicationIsLoadingWindow = di.inject(
|
||||
applicationIsLoadingWindowInjectable,
|
||||
);
|
||||
|
||||
return async () => {
|
||||
if (applicationWindow.visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
await applicationIsLoadingWindow.show();
|
||||
|
||||
await applicationWindow.show();
|
||||
|
||||
applicationIsLoadingWindow.close();
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default showApplicationWindowInjectable;
|
||||
@ -4,9 +4,8 @@
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
|
||||
import electronAppInjectable from "../electron-app/electron-app.injectable";
|
||||
import { runManyFor } from "./run-many-for";
|
||||
import { runManySyncFor } from "./run-many-sync-for";
|
||||
import { runManyFor } from "../../common/runnable/run-many-for";
|
||||
import { runManySyncFor } from "../../common/runnable/run-many-sync-for";
|
||||
import { beforeElectronIsReadyInjectionToken } from "./before-electron-is-ready/before-electron-is-ready-injection-token";
|
||||
import { beforeApplicationIsLoadingInjectionToken } from "./before-application-is-loading/before-application-is-loading-injection-token";
|
||||
import { whenApplicationIsLoadingInjectionToken } from "./when-application-is-loading/when-application-is-loading-injection-token";
|
||||
@ -19,6 +18,7 @@ import openDeepLinkInjectable from "../protocol-handler/lens-protocol-router-mai
|
||||
import { pipeline } from "@ogre-tools/fp";
|
||||
import { find, map, startsWith, toLower } from "lodash/fp";
|
||||
import commandLineArgumentsInjectable from "../utils/command-line-arguments.injectable";
|
||||
import waitForElectronToBeReadyInjectable from "../electron-app/features/wait-for-electron-to-be-ready.injectable";
|
||||
|
||||
const startMainApplicationInjectable = getInjectable({
|
||||
id: "start-main-application",
|
||||
@ -26,7 +26,7 @@ const startMainApplicationInjectable = getInjectable({
|
||||
instantiate: (di) => {
|
||||
const runMany = runManyFor(di);
|
||||
const runManySync = runManySyncFor(di);
|
||||
const electronApp = di.inject(electronAppInjectable);
|
||||
const waitForElectronToBeReady = di.inject(waitForElectronToBeReadyInjectable);
|
||||
const applicationWindow = di.inject(applicationWindowInjectable);
|
||||
const applicationIsLoadingWindow = di.inject(applicationIsLoadingWindowInjectable);
|
||||
const shouldStartHidden = di.inject(shouldStartHiddenInjectable);
|
||||
@ -43,7 +43,7 @@ const startMainApplicationInjectable = getInjectable({
|
||||
// https://github.com/electron/electron/issues/21370
|
||||
beforeElectronIsReady();
|
||||
|
||||
await electronApp.whenReady();
|
||||
await waitForElectronToBeReady();
|
||||
|
||||
await beforeApplicationIsLoading();
|
||||
|
||||
@ -54,10 +54,10 @@ const startMainApplicationInjectable = getInjectable({
|
||||
await whenApplicationIsLoading();
|
||||
|
||||
if (!shouldStartHidden) {
|
||||
const url = getDeepLinkUrl(commandLineArguments);
|
||||
const deepLinkUrl = getDeepLinkUrl(commandLineArguments);
|
||||
|
||||
if (url) {
|
||||
await openDeepLink(url);
|
||||
if (deepLinkUrl) {
|
||||
await openDeepLink(deepLinkUrl);
|
||||
} else {
|
||||
await applicationWindow.show();
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { ipcMainOn } from "../../../../common/ipc";
|
||||
import { IpcRendererNavigationEvents } from "../../../../renderer/navigation/events";
|
||||
import { afterRootFrameIsReadyInjectionToken } from "../../after-root-frame-is-ready/after-root-frame-is-ready-injection-token";
|
||||
import { runManyFor } from "../../run-many-for";
|
||||
import { runManyFor } from "../../../../common/runnable/run-many-for";
|
||||
import { whenApplicationIsLoadingInjectionToken } from "../when-application-is-loading-injection-token";
|
||||
|
||||
const setupRunnablesForAfterRootFrameIsReadyInjectable = getInjectable({
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { Runnable } from "../run-many-for";
|
||||
import type { Runnable } from "../../../common/runnable/run-many-for";
|
||||
|
||||
export const whenApplicationIsLoadingInjectionToken = getInjectionToken<Runnable>({
|
||||
id: "when-application-is-loading",
|
||||
|
||||
@ -7,7 +7,7 @@ import exitAppInjectable from "./electron-app/features/exit-app.injectable";
|
||||
import clusterManagerInjectable from "./cluster-manager.injectable";
|
||||
import appEventBusInjectable from "../common/app-event-bus/app-event-bus.injectable";
|
||||
import loggerInjectable from "../common/logger.injectable";
|
||||
import hideAllWindowsInjectable from "./start-main-application/lens-window/hide-all-windows/hide-all-windows.injectable";
|
||||
import closeAllWindowsInjectable from "./start-main-application/lens-window/hide-all-windows/close-all-windows.injectable";
|
||||
|
||||
const stopServicesAndExitAppInjectable = getInjectable({
|
||||
id: "stop-services-and-exit-app",
|
||||
@ -17,11 +17,11 @@ const stopServicesAndExitAppInjectable = getInjectable({
|
||||
const clusterManager = di.inject(clusterManagerInjectable);
|
||||
const appEventBus = di.inject(appEventBusInjectable);
|
||||
const logger = di.inject(loggerInjectable);
|
||||
const hideAllWindows = di.inject(hideAllWindowsInjectable);
|
||||
const closeAllWindows = di.inject(closeAllWindowsInjectable);
|
||||
|
||||
return () => {
|
||||
appEventBus.emit({ name: "service", action: "close" });
|
||||
hideAllWindows();
|
||||
closeAllWindows();
|
||||
clusterManager.stop();
|
||||
logger.info("SERVICE:QUIT");
|
||||
setTimeout(exitApp, 1000);
|
||||
|
||||
@ -10,8 +10,9 @@ import stopServicesAndExitAppInjectable from "../stop-services-and-exit-app.inje
|
||||
import { getStartableStoppable } from "../../common/utils/get-startable-stoppable";
|
||||
import isAutoUpdateEnabledInjectable from "../is-auto-update-enabled.injectable";
|
||||
import trayIconPathInjectable from "./tray-icon-path.injectable";
|
||||
import applicationWindowInjectable from "../start-main-application/lens-window/application-window/application-window.injectable";
|
||||
import showAboutInjectable from "../menu/show-about.injectable";
|
||||
import showApplicationWindowInjectable
|
||||
from "../start-main-application/lens-window/show-application-window.injectable";
|
||||
|
||||
const trayInjectable = getInjectable({
|
||||
id: "tray",
|
||||
@ -22,7 +23,7 @@ const trayInjectable = getInjectable({
|
||||
const stopServicesAndExitApp = di.inject(stopServicesAndExitAppInjectable);
|
||||
const isAutoUpdateEnabled = di.inject(isAutoUpdateEnabledInjectable);
|
||||
const trayIconPath = di.inject(trayIconPathInjectable);
|
||||
const applicationWindow = di.inject(applicationWindowInjectable);
|
||||
const showApplicationWindow = di.inject(showApplicationWindowInjectable);
|
||||
const showAboutPopup = di.inject(showAboutInjectable);
|
||||
|
||||
return getStartableStoppable("build-of-tray", () =>
|
||||
@ -32,7 +33,7 @@ const trayInjectable = getInjectable({
|
||||
stopServicesAndExitApp,
|
||||
isAutoUpdateEnabled,
|
||||
trayIconPath,
|
||||
applicationWindow,
|
||||
showApplicationWindow,
|
||||
showAboutPopup,
|
||||
),
|
||||
);
|
||||
|
||||
@ -14,7 +14,6 @@ import type { Disposer } from "../../common/utils";
|
||||
import { disposer, toJS } from "../../common/utils";
|
||||
import type { TrayMenuRegistration } from "./tray-menu-registration";
|
||||
import path from "path";
|
||||
import type { LensWindow } from "../start-main-application/lens-window/application-window/lens-window-injection-token";
|
||||
|
||||
const TRAY_LOG_PREFIX = "[TRAY]";
|
||||
|
||||
@ -34,7 +33,7 @@ export function initTray(
|
||||
navigateToPreferences: () => void,
|
||||
stopServicesAndExitApp: () => void,
|
||||
isAutoUpdateEnabled: () => boolean,
|
||||
applicationWindow: LensWindow,
|
||||
showApplicationWindow: () => Promise<void>,
|
||||
showAbout: () => void,
|
||||
): Disposer {
|
||||
const icon = getTrayIconPath();
|
||||
@ -45,7 +44,7 @@ export function initTray(
|
||||
|
||||
if (isWindows) {
|
||||
tray.on("click", () => {
|
||||
applicationWindow.show()
|
||||
showApplicationWindow()
|
||||
.catch(error => logger.error(`${TRAY_LOG_PREFIX}: Failed to open lens`, { error }));
|
||||
});
|
||||
}
|
||||
@ -53,7 +52,7 @@ export function initTray(
|
||||
return disposer(
|
||||
autorun(() => {
|
||||
try {
|
||||
const menu = createTrayMenu(toJS(trayMenuItems.get()), navigateToPreferences, stopServicesAndExitApp, isAutoUpdateEnabled, applicationWindow, showAbout);
|
||||
const menu = createTrayMenu(toJS(trayMenuItems.get()), navigateToPreferences, stopServicesAndExitApp, isAutoUpdateEnabled, showApplicationWindow, showAbout);
|
||||
|
||||
tray.setContextMenu(menu);
|
||||
} catch (error) {
|
||||
@ -82,14 +81,14 @@ function createTrayMenu(
|
||||
navigateToPreferences: () => void,
|
||||
stopServicesAndExitApp: () => void,
|
||||
isAutoUpdateEnabled: () => boolean,
|
||||
applicationWindow: LensWindow,
|
||||
showApplicationWindow: () => Promise<void>,
|
||||
showAbout: () => void,
|
||||
): Menu {
|
||||
let template: Electron.MenuItemConstructorOptions[] = [
|
||||
{
|
||||
label: `Open ${productName}`,
|
||||
click() {
|
||||
applicationWindow.show().catch(error => logger.error(`${TRAY_LOG_PREFIX}: Failed to open lens`, { error }));
|
||||
showApplicationWindow().catch(error => logger.error(`${TRAY_LOG_PREFIX}: Failed to open lens`, { error }));
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -105,7 +104,7 @@ function createTrayMenu(
|
||||
label: "Check for updates",
|
||||
click() {
|
||||
checkForUpdates()
|
||||
.then(() => applicationWindow.show());
|
||||
.then(() => showApplicationWindow());
|
||||
},
|
||||
});
|
||||
}
|
||||
@ -116,7 +115,7 @@ function createTrayMenu(
|
||||
{
|
||||
label: `About ${productName}`,
|
||||
click() {
|
||||
applicationWindow.show()
|
||||
showApplicationWindow()
|
||||
.then(showAbout)
|
||||
.catch(error => logger.error(`${TRAY_LOG_PREFIX}: Failed to show Lens About view`, { error }));
|
||||
},
|
||||
|
||||
@ -3,10 +3,11 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { AppPaths, appPathsIpcChannel } from "../../common/app-paths/app-path-injection-token";
|
||||
import type { AppPaths } from "../../common/app-paths/app-path-injection-token";
|
||||
import { appPathsIpcChannel } from "../../common/app-paths/app-path-injection-token";
|
||||
import getValueFromRegisteredChannelInjectable from "./get-value-from-registered-channel/get-value-from-registered-channel.injectable";
|
||||
import appPathsStateInjectable from "../../common/app-paths/app-paths-state.injectable";
|
||||
import { afterApplicationIsReadyInjectionToken } from "../../main/start-main-application/after-application-is-ready/after-application-is-ready-injection-token";
|
||||
import { beforeFrameStartsInjectionToken } from "../before-frame-starts/before-frame-starts-injection-token";
|
||||
|
||||
let syncAppPaths: AppPaths;
|
||||
|
||||
@ -27,7 +28,7 @@ const setupAppPathsInjectable = getInjectable({
|
||||
},
|
||||
}),
|
||||
|
||||
injectionToken: afterApplicationIsReadyInjectionToken,
|
||||
injectionToken: beforeFrameStartsInjectionToken,
|
||||
});
|
||||
|
||||
export default setupAppPathsInjectable;
|
||||
|
||||
@ -3,8 +3,8 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { Runnable } from "../run-many-for";
|
||||
import type { Runnable } from "../../common/runnable/run-many-for";
|
||||
|
||||
export const afterApplicationIsReadyInjectionToken = getInjectionToken<Runnable>({
|
||||
id: "after-application-is-ready",
|
||||
export const beforeFrameStartsInjectionToken = getInjectionToken<Runnable>({
|
||||
id: "before-frame-starts",
|
||||
});
|
||||
@ -43,7 +43,10 @@ import hotbarStoreInjectable from "../common/hotbar-store.injectable";
|
||||
import { bindEvents } from "./navigation/events";
|
||||
import deleteClusterDialogModelInjectable from "./components/delete-cluster-dialog/delete-cluster-dialog-model/delete-cluster-dialog-model.injectable";
|
||||
import { init } from "@sentry/electron/renderer";
|
||||
import { runSetups } from "../common/setupable-injection-token/run-setups";
|
||||
import {
|
||||
beforeFrameStartsInjectionToken,
|
||||
} from "./before-frame-starts/before-frame-starts-injection-token";
|
||||
import { runManyFor } from "../common/runnable/run-many-for";
|
||||
|
||||
configurePackages(); // global packages
|
||||
registerCustomThemes(); // monaco editor themes
|
||||
@ -64,7 +67,9 @@ export async function bootstrap(di: DiContainer) {
|
||||
initializeSentryReporting(init);
|
||||
}
|
||||
|
||||
await runSetups(di);
|
||||
const beforeFrameStarts = runManyFor(di)(beforeFrameStartsInjectionToken);
|
||||
|
||||
await beforeFrameStarts();
|
||||
|
||||
// TODO: Consolidate import time side-effect to setup time
|
||||
bindEvents();
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
*/
|
||||
import "@testing-library/jest-dom/extend-expect";
|
||||
import { KubeConfig } from "@kubernetes/client-node";
|
||||
import type { RenderResult } from "@testing-library/react";
|
||||
import { fireEvent } from "@testing-library/react";
|
||||
import mockFs from "mock-fs";
|
||||
import React from "react";
|
||||
@ -13,14 +14,25 @@ import type { Cluster } from "../../../../common/cluster/cluster";
|
||||
import { DeleteClusterDialog } from "../delete-cluster-dialog";
|
||||
|
||||
import type { ClusterModel } from "../../../../common/cluster-types";
|
||||
import { getDisForUnitTesting } from "../../../../test-utils/get-dis-for-unit-testing";
|
||||
import { createClusterInjectionToken } from "../../../../common/cluster/create-cluster-injection-token";
|
||||
import createContextHandlerInjectable from "../../../../main/context-handler/create-context-handler.injectable";
|
||||
import deleteClusterDialogModelInjectable from "../delete-cluster-dialog-model/delete-cluster-dialog-model.injectable";
|
||||
import type { DeleteClusterDialogModel } from "../delete-cluster-dialog-model/delete-cluster-dialog-model";
|
||||
import type { DiRender } from "../../test-utils/renderFor";
|
||||
import { renderFor } from "../../test-utils/renderFor";
|
||||
import hotbarStoreInjectable from "../../../../common/hotbar-store.injectable";
|
||||
import type {
|
||||
ApplicationBuilder } from "../../test-utils/get-application-builder";
|
||||
import {
|
||||
getApplicationBuilder,
|
||||
} from "../../test-utils/get-application-builder";
|
||||
import { routeInjectionToken } from "../../../../common/front-end-routing/route-injection-token";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { computed } from "mobx";
|
||||
import {
|
||||
routeSpecificComponentInjectionToken,
|
||||
} from "../../../routes/route-specific-component-injection-token";
|
||||
import {
|
||||
navigateToRouteInjectionToken,
|
||||
} from "../../../../common/front-end-routing/navigate-to-route-injection-token";
|
||||
|
||||
jest.mock("electron", () => ({
|
||||
app: {
|
||||
@ -92,25 +104,50 @@ users:
|
||||
let config: KubeConfig;
|
||||
|
||||
describe("<DeleteClusterDialog />", () => {
|
||||
let createCluster: (model: ClusterModel) => Cluster;
|
||||
let deleteClusterDialogModel: DeleteClusterDialogModel;
|
||||
let render: DiRender;
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
|
||||
beforeEach(async () => {
|
||||
const { mainDi, rendererDi, runSetups } = getDisForUnitTesting({ doGeneralOverrides: true });
|
||||
|
||||
render = renderFor(rendererDi);
|
||||
|
||||
mainDi.override(createContextHandlerInjectable, () => () => undefined);
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
|
||||
mockFs();
|
||||
|
||||
rendererDi.override(hotbarStoreInjectable, () => ({}));
|
||||
applicationBuilder.beforeSetups(({ mainDi, rendererDi }) => {
|
||||
mainDi.override(createContextHandlerInjectable, () => () => undefined);
|
||||
|
||||
await runSetups();
|
||||
rendererDi.override(hotbarStoreInjectable, () => ({}));
|
||||
|
||||
deleteClusterDialogModel = rendererDi.inject(deleteClusterDialogModelInjectable);
|
||||
createCluster = mainDi.inject(createClusterInjectionToken);
|
||||
const testRouteInjectable = getInjectable({
|
||||
id: "some-test-route",
|
||||
|
||||
instantiate: () => ({
|
||||
path: "/some-test-path",
|
||||
clusterFrame: false,
|
||||
isEnabled: computed(() => true),
|
||||
}),
|
||||
|
||||
injectionToken: routeInjectionToken,
|
||||
});
|
||||
|
||||
const testRouteComponent = getInjectable({
|
||||
id: "some-test-component",
|
||||
|
||||
instantiate: (di) => ({
|
||||
route: di.inject(testRouteInjectable),
|
||||
Component: () => <DeleteClusterDialog />,
|
||||
}),
|
||||
|
||||
injectionToken: routeSpecificComponentInjectionToken,
|
||||
});
|
||||
|
||||
applicationBuilder.beforeRender(({ rendererDi }) => {
|
||||
const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken);
|
||||
const testRoute = rendererDi.inject(testRouteInjectable);
|
||||
|
||||
navigateToRoute(testRoute);
|
||||
});
|
||||
|
||||
rendererDi.register(testRouteInjectable, testRouteComponent);
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@ -118,6 +155,10 @@ describe("<DeleteClusterDialog />", () => {
|
||||
});
|
||||
|
||||
describe("Kubeconfig with different clusters", () => {
|
||||
let rendered: RenderResult;
|
||||
let createCluster: (model: ClusterModel) => Cluster;
|
||||
let deleteClusterDialogModel: DeleteClusterDialogModel;
|
||||
|
||||
beforeEach(async () => {
|
||||
const mockOpts = {
|
||||
"temp-kube-config": kubeconfig,
|
||||
@ -127,6 +168,11 @@ describe("<DeleteClusterDialog />", () => {
|
||||
|
||||
config = new KubeConfig();
|
||||
config.loadFromString(kubeconfig);
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
|
||||
deleteClusterDialogModel = applicationBuilder.dis.rendererDi.inject(deleteClusterDialogModelInjectable);
|
||||
createCluster = applicationBuilder.dis.mainDi.inject(createClusterInjectionToken);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@ -134,9 +180,7 @@ describe("<DeleteClusterDialog />", () => {
|
||||
});
|
||||
|
||||
it("renders w/o errors", () => {
|
||||
const { container } = render(<DeleteClusterDialog />);
|
||||
|
||||
expect(container).toBeInstanceOf(HTMLElement);
|
||||
expect(rendered.container).toBeInstanceOf(HTMLElement);
|
||||
});
|
||||
|
||||
it("shows warning when deleting non-current-context cluster", () => {
|
||||
@ -150,11 +194,10 @@ describe("<DeleteClusterDialog />", () => {
|
||||
});
|
||||
|
||||
deleteClusterDialogModel.open({ cluster, config });
|
||||
const { getByText } = render(<DeleteClusterDialog />);
|
||||
|
||||
const message = "The contents of kubeconfig file will be changed!";
|
||||
|
||||
expect(getByText(message)).toBeInstanceOf(HTMLElement);
|
||||
expect(rendered.getByText(message)).toBeInstanceOf(HTMLElement);
|
||||
});
|
||||
|
||||
it("shows warning when deleting current-context cluster", () => {
|
||||
@ -169,9 +212,7 @@ describe("<DeleteClusterDialog />", () => {
|
||||
|
||||
deleteClusterDialogModel.open({ cluster, config });
|
||||
|
||||
const { getByTestId } = render(<DeleteClusterDialog />);
|
||||
|
||||
expect(getByTestId("current-context-warning")).toBeInstanceOf(HTMLElement);
|
||||
expect(rendered.getByTestId("current-context-warning")).toBeInstanceOf(HTMLElement);
|
||||
});
|
||||
|
||||
it("shows context switcher when deleting current cluster", async () => {
|
||||
@ -186,7 +227,7 @@ describe("<DeleteClusterDialog />", () => {
|
||||
|
||||
deleteClusterDialogModel.open({ cluster, config });
|
||||
|
||||
const { getByText } = render(<DeleteClusterDialog />);
|
||||
const { getByText } = rendered;
|
||||
|
||||
expect(getByText("Select...")).toBeInTheDocument();
|
||||
selectEvent.openMenu(getByText("Select..."));
|
||||
@ -207,7 +248,7 @@ describe("<DeleteClusterDialog />", () => {
|
||||
|
||||
deleteClusterDialogModel.open({ cluster, config });
|
||||
|
||||
const { getByText, getByTestId } = render(<DeleteClusterDialog />);
|
||||
const { getByText, getByTestId } = rendered;
|
||||
const link = getByTestId("context-switch");
|
||||
|
||||
expect(link).toBeInstanceOf(HTMLElement);
|
||||
@ -234,15 +275,17 @@ describe("<DeleteClusterDialog />", () => {
|
||||
|
||||
deleteClusterDialogModel.open({ cluster, config });
|
||||
|
||||
const { getByTestId } = render(<DeleteClusterDialog />);
|
||||
|
||||
expect(getByTestId("internal-kubeconfig-warning")).toBeInstanceOf(HTMLElement);
|
||||
expect(rendered.getByTestId("internal-kubeconfig-warning")).toBeInstanceOf(HTMLElement);
|
||||
|
||||
spy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
describe("Kubeconfig with single cluster", () => {
|
||||
let rendered: RenderResult;
|
||||
let createCluster: (model: ClusterModel) => Cluster;
|
||||
let deleteClusterDialogModel: DeleteClusterDialogModel;
|
||||
|
||||
beforeEach(async () => {
|
||||
const mockOpts = {
|
||||
"temp-kube-config": singleClusterConfig,
|
||||
@ -252,6 +295,11 @@ describe("<DeleteClusterDialog />", () => {
|
||||
|
||||
config = new KubeConfig();
|
||||
config.loadFromString(singleClusterConfig);
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
|
||||
deleteClusterDialogModel = applicationBuilder.dis.rendererDi.inject(deleteClusterDialogModelInjectable);
|
||||
createCluster = applicationBuilder.dis.mainDi.inject(createClusterInjectionToken);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@ -270,9 +318,7 @@ describe("<DeleteClusterDialog />", () => {
|
||||
|
||||
deleteClusterDialogModel.open({ cluster, config });
|
||||
|
||||
const { getByTestId } = render(<DeleteClusterDialog />);
|
||||
|
||||
expect(getByTestId("no-more-contexts-warning")).toBeInstanceOf(HTMLElement);
|
||||
expect(rendered.getByTestId("no-more-contexts-warning")).toBeInstanceOf(HTMLElement);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -40,6 +40,8 @@ import type { NamespaceStore } from "../+namespaces/namespace-store/namespace.st
|
||||
import { KubeObjectStore } from "../../../common/k8s-api/kube-object.store";
|
||||
import namespaceStoreInjectable from "../+namespaces/namespace-store/namespace-store.injectable";
|
||||
import clusterFrameContextInjectable from "../../cluster-frame-context/cluster-frame-context.injectable";
|
||||
import startMainApplicationInjectable from "../../../main/start-main-application/start-main-application.injectable";
|
||||
import startFrameInjectable from "../../start-frame/start-frame.injectable";
|
||||
|
||||
type Callback = (dis: DiContainers) => void | Promise<void>;
|
||||
|
||||
@ -55,7 +57,7 @@ export interface ApplicationBuilder {
|
||||
render: () => Promise<RenderResult>;
|
||||
|
||||
applicationMenu: {
|
||||
click: (path: string) => void;
|
||||
click: (path: string) => Promise<void>;
|
||||
};
|
||||
|
||||
preferences: {
|
||||
@ -82,7 +84,7 @@ interface Environment {
|
||||
}
|
||||
|
||||
export const getApplicationBuilder = () => {
|
||||
const { rendererDi, mainDi, runSetups } = getDisForUnitTesting({
|
||||
const { rendererDi, mainDi } = getDisForUnitTesting({
|
||||
doGeneralOverrides: true,
|
||||
});
|
||||
|
||||
@ -142,7 +144,7 @@ export const getApplicationBuilder = () => {
|
||||
dis,
|
||||
|
||||
applicationMenu: {
|
||||
click: (path: string) => {
|
||||
click: async (path: string) => {
|
||||
const applicationMenuItems = mainDi.inject(
|
||||
applicationMenuItemsInjectable,
|
||||
);
|
||||
@ -164,6 +166,10 @@ export const getApplicationBuilder = () => {
|
||||
}
|
||||
|
||||
menuItem.click(undefined, undefined, undefined);
|
||||
|
||||
const flushPromises = () => new Promise(setImmediate);
|
||||
|
||||
await flushPromises();
|
||||
},
|
||||
},
|
||||
|
||||
@ -301,7 +307,13 @@ export const getApplicationBuilder = () => {
|
||||
await callback(dis);
|
||||
}
|
||||
|
||||
await runSetups();
|
||||
const startMainApplication = mainDi.inject(startMainApplicationInjectable);
|
||||
|
||||
await startMainApplication();
|
||||
|
||||
const startFrame = rendererDi.inject(startFrameInjectable);
|
||||
|
||||
await startFrame();
|
||||
|
||||
const render = renderFor(rendererDi);
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { ipcChannelListenerInjectionToken } from "./ipc-channel-listener-injection-token";
|
||||
import registerIpcChannelListenerInjectable from "../app-paths/get-value-from-registered-channel/register-ipc-channel-listener.injectable";
|
||||
import { afterApplicationIsReadyInjectionToken } from "../../main/start-main-application/after-application-is-ready/after-application-is-ready-injection-token";
|
||||
import { beforeFrameStartsInjectionToken } from "../before-frame-starts/before-frame-starts-injection-token";
|
||||
|
||||
const registerIpcChannelListenersInjectable = getInjectable({
|
||||
id: "register-ipc-channel-listeners",
|
||||
@ -22,7 +22,7 @@ const registerIpcChannelListenersInjectable = getInjectable({
|
||||
},
|
||||
}),
|
||||
|
||||
injectionToken: afterApplicationIsReadyInjectionToken,
|
||||
injectionToken: beforeFrameStartsInjectionToken,
|
||||
});
|
||||
|
||||
export default registerIpcChannelListenersInjectable;
|
||||
|
||||
@ -6,14 +6,15 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import observableHistoryInjectable from "../navigation/observable-history.injectable";
|
||||
import { runInAction } from "mobx";
|
||||
import { navigateToUrlInjectionToken } from "../../common/front-end-routing/navigate-to-url-injection-token";
|
||||
import { broadcastMessage } from "../../common/ipc";
|
||||
import { IpcRendererNavigationEvents } from "../navigation/events";
|
||||
import broadcastMessageInjectable from "../../common/ipc/broadcast-message.injectable";
|
||||
|
||||
const navigateToUrlInjectable = getInjectable({
|
||||
id: "navigate-to-url",
|
||||
|
||||
instantiate: (di) => {
|
||||
const observableHistory = di.inject(observableHistoryInjectable);
|
||||
const broadcastMessage = di.inject(broadcastMessageInjectable);
|
||||
|
||||
return (url, options = {}) => {
|
||||
if (options.forceRootFrame) {
|
||||
|
||||
20
src/renderer/start-frame/start-frame.injectable.ts
Normal file
20
src/renderer/start-frame/start-frame.injectable.ts
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { runManyFor } from "../../common/runnable/run-many-for";
|
||||
import { beforeFrameStartsInjectionToken } from "../before-frame-starts/before-frame-starts-injection-token";
|
||||
|
||||
const startFrameInjectable = getInjectable({
|
||||
id: "start-frame",
|
||||
|
||||
// TODO: Consolidate contents of bootstrap.tsx here
|
||||
instantiate: (di) => async () => {
|
||||
const beforeFrameStarts = runManyFor(di)(beforeFrameStartsInjectionToken);
|
||||
|
||||
await beforeFrameStarts();
|
||||
},
|
||||
});
|
||||
|
||||
export default startFrameInjectable;
|
||||
@ -5,7 +5,6 @@
|
||||
import { getDiForUnitTesting as getRendererDi } from "../renderer/getDiForUnitTesting";
|
||||
import { getDiForUnitTesting as getMainDi } from "../main/getDiForUnitTesting";
|
||||
import { overrideIpcBridge } from "./override-ipc-bridge";
|
||||
import { runSetups } from "../common/setupable-injection-token/run-setups";
|
||||
|
||||
export const getDisForUnitTesting = (
|
||||
{ doGeneralOverrides } = { doGeneralOverrides: false },
|
||||
@ -18,8 +17,5 @@ export const getDisForUnitTesting = (
|
||||
return {
|
||||
rendererDi,
|
||||
mainDi,
|
||||
|
||||
runSetups: () =>
|
||||
Promise.all([runSetups(rendererDi), runSetups(mainDi)]),
|
||||
};
|
||||
};
|
||||
|
||||
@ -10,6 +10,7 @@ import asyncFn from "@async-fn/jest";
|
||||
import registerIpcChannelListenerInjectable from "../renderer/app-paths/get-value-from-registered-channel/register-ipc-channel-listener.injectable";
|
||||
import type { SendToViewArgs } from "../main/start-main-application/lens-window/application-window/lens-window-injection-token";
|
||||
import sendToChannelInElectronBrowserWindowInjectable from "../main/start-main-application/lens-window/application-window/send-to-channel-in-electron-browser-window.injectable";
|
||||
import { isEmpty } from "lodash/fp";
|
||||
|
||||
|
||||
export const overrideIpcBridge = ({
|
||||
@ -89,9 +90,15 @@ export const overrideIpcBridge = ({
|
||||
(browserWindow, { channel: channelName, data }: SendToViewArgs) => {
|
||||
const handles = rendererIpcFakeHandles.get(channelName);
|
||||
|
||||
handles.forEach((handle) => handle(...data));
|
||||
if (isEmpty(handles)) {
|
||||
throw new Error(
|
||||
`Tried to send message to channel "${channelName}" but there where no listeners. Current channels with listeners: "${[
|
||||
...rendererIpcFakeHandles.keys(),
|
||||
].join('", "')}"`,
|
||||
);
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
handles.forEach((handle) => handle(...data));
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user