mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Replace static application window with ability to create many (#5979)
* Replace static application window with ability to create as many as you wish Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Adapt tests for replacing static application window with ability to create as many as you wish and separate starting of main and window in behaviours Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Make first render of application smaller in test that proves to be hard for CI Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Remove redundant code Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Simplify code Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
parent
299922c8a7
commit
63d5a34379
@ -14,15 +14,10 @@ import { getApplicationBuilder } from "../../renderer/components/test-utils/get-
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
|
||||
describe("app-paths", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let rendererDi: DiContainer;
|
||||
let mainDi: DiContainer;
|
||||
let builder: ApplicationBuilder;
|
||||
|
||||
beforeEach(() => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
|
||||
rendererDi = applicationBuilder.dis.rendererDi;
|
||||
mainDi = applicationBuilder.dis.mainDi;
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
const defaultAppPathsStub: AppPaths = {
|
||||
appData: "some-app-data",
|
||||
@ -43,7 +38,7 @@ describe("app-paths", () => {
|
||||
userData: "some-irrelevant-user-data",
|
||||
};
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
mainDi.override(
|
||||
getElectronAppPathInjectable,
|
||||
() =>
|
||||
@ -64,12 +59,18 @@ describe("app-paths", () => {
|
||||
});
|
||||
|
||||
describe("normally", () => {
|
||||
let windowDi: DiContainer;
|
||||
let mainDi: DiContainer;
|
||||
|
||||
beforeEach(async () => {
|
||||
await applicationBuilder.render();
|
||||
await builder.render();
|
||||
|
||||
windowDi = builder.applicationWindow.only.di;
|
||||
mainDi = builder.mainDi;
|
||||
});
|
||||
|
||||
it("given in renderer, when injecting app paths, returns application specific app paths", () => {
|
||||
const actual = rendererDi.inject(appPathsInjectionToken);
|
||||
const actual = windowDi.inject(appPathsInjectionToken);
|
||||
|
||||
expect(actual).toEqual({
|
||||
appData: "some-app-data",
|
||||
@ -116,19 +117,23 @@ describe("app-paths", () => {
|
||||
});
|
||||
|
||||
describe("when running integration tests", () => {
|
||||
let windowDi: DiContainer;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
mainDi.override(
|
||||
directoryForIntegrationTestingInjectable,
|
||||
() => "some-integration-testing-app-data",
|
||||
);
|
||||
});
|
||||
|
||||
await applicationBuilder.render();
|
||||
await builder.render();
|
||||
|
||||
windowDi = builder.applicationWindow.only.di;
|
||||
});
|
||||
|
||||
it("given in renderer, when injecting path for app data, has integration specific app data path", () => {
|
||||
const { appData, userData } = rendererDi.inject(appPathsInjectionToken);
|
||||
const { appData, userData } = windowDi.inject(appPathsInjectionToken);
|
||||
|
||||
expect({ appData, userData }).toEqual({
|
||||
appData: "some-integration-testing-app-data",
|
||||
@ -137,7 +142,7 @@ describe("app-paths", () => {
|
||||
});
|
||||
|
||||
it("given in main, when injecting path for app data, has integration specific app data path", () => {
|
||||
const { appData, userData } = rendererDi.inject(appPathsInjectionToken);
|
||||
const { appData, userData } = windowDi.inject(appPathsInjectionToken);
|
||||
|
||||
expect({ appData, userData }).toEqual({
|
||||
appData: "some-integration-testing-app-data",
|
||||
|
||||
@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getGlobalOverride } from "../test-utils/get-global-override";
|
||||
import clusterStoreInjectable from "./cluster-store.injectable";
|
||||
import type { Cluster } from "../cluster/cluster";
|
||||
import type { ClusterStore } from "./cluster-store";
|
||||
|
||||
export default getGlobalOverride(
|
||||
clusterStoreInjectable,
|
||||
() =>
|
||||
({
|
||||
provideInitialFromMain: () => {},
|
||||
getById: (id) => (void id, {}) as Cluster,
|
||||
} as ClusterStore),
|
||||
);
|
||||
@ -4,13 +4,11 @@
|
||||
*/
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { LensWindow } from "../../../main/start-main-application/lens-window/application-window/lens-window-injection-token";
|
||||
import { lensWindowInjectionToken } from "../../../main/start-main-application/lens-window/application-window/lens-window-injection-token";
|
||||
import type { MessageToChannel } from "./message-to-channel-injection-token";
|
||||
import { messageToChannelInjectionToken } from "./message-to-channel-injection-token";
|
||||
import type { ApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder";
|
||||
import createLensWindowInjectable from "../../../main/start-main-application/lens-window/application-window/create-lens-window.injectable";
|
||||
import closeAllWindowsInjectable from "../../../main/start-main-application/lens-window/hide-all-windows/close-all-windows.injectable";
|
||||
import type { LensWindow } from "../../../main/start-main-application/lens-window/application-window/create-lens-window.injectable";
|
||||
import { messageChannelListenerInjectionToken } from "./message-channel-listener-injection-token";
|
||||
import type { MessageChannel } from "./message-channel-injection-token";
|
||||
import type { RequestFromChannel } from "./request-from-channel-injection-token";
|
||||
@ -30,12 +28,10 @@ describe("channel", () => {
|
||||
let messageListenerInWindowMock: jest.Mock;
|
||||
let mainDi: DiContainer;
|
||||
let messageToChannel: MessageToChannel;
|
||||
let builder: ApplicationBuilder;
|
||||
|
||||
beforeEach(async () => {
|
||||
const applicationBuilder = getApplicationBuilder();
|
||||
|
||||
mainDi = applicationBuilder.dis.mainDi;
|
||||
const rendererDi = applicationBuilder.dis.rendererDi;
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
messageListenerInWindowMock = jest.fn();
|
||||
|
||||
@ -44,37 +40,34 @@ describe("channel", () => {
|
||||
|
||||
instantiate: (di) => ({
|
||||
channel: di.inject(testMessageChannelInjectable),
|
||||
|
||||
handler: messageListenerInWindowMock,
|
||||
}),
|
||||
|
||||
injectionToken: messageChannelListenerInjectionToken,
|
||||
});
|
||||
|
||||
rendererDi.register(testChannelListenerInTestWindowInjectable);
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
mainDi.register(testMessageChannelInjectable);
|
||||
});
|
||||
|
||||
// Notice how test channel has presence in both DIs, being from common
|
||||
mainDi.register(testMessageChannelInjectable);
|
||||
rendererDi.register(testMessageChannelInjectable);
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.register(testChannelListenerInTestWindowInjectable);
|
||||
windowDi.register(testMessageChannelInjectable);
|
||||
});
|
||||
|
||||
mainDi = builder.mainDi;
|
||||
|
||||
await builder.startHidden();
|
||||
|
||||
testMessageChannel = mainDi.inject(testMessageChannelInjectable);
|
||||
|
||||
messageToChannel = mainDi.inject(
|
||||
messageToChannelInjectionToken,
|
||||
);
|
||||
|
||||
await applicationBuilder.render();
|
||||
|
||||
const closeAllWindows = mainDi.inject(closeAllWindowsInjectable);
|
||||
|
||||
closeAllWindows();
|
||||
messageToChannel = mainDi.inject(messageToChannelInjectionToken);
|
||||
});
|
||||
|
||||
describe("given window is started", () => {
|
||||
let someWindowFake: LensWindow;
|
||||
|
||||
beforeEach(async () => {
|
||||
someWindowFake = createTestWindow(mainDi, "some-window");
|
||||
someWindowFake = builder.applicationWindow.create("some-window");
|
||||
|
||||
await someWindowFake.start();
|
||||
});
|
||||
@ -95,8 +88,8 @@ describe("channel", () => {
|
||||
});
|
||||
|
||||
it("given multiple started windows, when sending message, triggers listeners in all windows", async () => {
|
||||
const someWindowFake = createTestWindow(mainDi, "some-window");
|
||||
const someOtherWindowFake = createTestWindow(mainDi, "some-other-window");
|
||||
const someWindowFake = builder.applicationWindow.create("some-window");
|
||||
const someOtherWindowFake = builder.applicationWindow.create("some-other-window");
|
||||
|
||||
await someWindowFake.start();
|
||||
await someOtherWindowFake.start();
|
||||
@ -113,16 +106,11 @@ describe("channel", () => {
|
||||
describe("messaging from renderer to main, given listener for channel in a main and application has started", () => {
|
||||
let testMessageChannel: TestMessageChannel;
|
||||
let messageListenerInMainMock: jest.Mock;
|
||||
let rendererDi: DiContainer;
|
||||
let mainDi: DiContainer;
|
||||
let messageToChannel: MessageToChannel;
|
||||
|
||||
beforeEach(async () => {
|
||||
const applicationBuilder = getApplicationBuilder();
|
||||
|
||||
mainDi = applicationBuilder.dis.mainDi;
|
||||
rendererDi = applicationBuilder.dis.rendererDi;
|
||||
|
||||
messageListenerInMainMock = jest.fn();
|
||||
|
||||
const testChannelListenerInMainInjectable = getInjectable({
|
||||
@ -137,19 +125,21 @@ describe("channel", () => {
|
||||
injectionToken: messageChannelListenerInjectionToken,
|
||||
});
|
||||
|
||||
mainDi.register(testChannelListenerInMainInjectable);
|
||||
applicationBuilder.beforeApplicationStart((mainDi) => {
|
||||
mainDi.register(testChannelListenerInMainInjectable);
|
||||
mainDi.register(testMessageChannelInjectable);
|
||||
});
|
||||
|
||||
// Notice how test channel has presence in both DIs, being from common
|
||||
mainDi.register(testMessageChannelInjectable);
|
||||
rendererDi.register(testMessageChannelInjectable);
|
||||
|
||||
testMessageChannel = rendererDi.inject(testMessageChannelInjectable);
|
||||
|
||||
messageToChannel = rendererDi.inject(
|
||||
messageToChannelInjectionToken,
|
||||
);
|
||||
applicationBuilder.beforeWindowStart((windowDi) => {
|
||||
windowDi.register(testMessageChannelInjectable);
|
||||
});
|
||||
|
||||
await applicationBuilder.render();
|
||||
|
||||
const windowDi = applicationBuilder.applicationWindow.only.di;
|
||||
|
||||
testMessageChannel = windowDi.inject(testMessageChannelInjectable);
|
||||
messageToChannel = windowDi.inject(messageToChannelInjectionToken);
|
||||
});
|
||||
|
||||
it("when sending message, triggers listener in main", () => {
|
||||
@ -162,16 +152,11 @@ describe("channel", () => {
|
||||
describe("requesting from main in renderer, given listener for channel in a main and application has started", () => {
|
||||
let testRequestChannel: TestRequestChannel;
|
||||
let requestListenerInMainMock: AsyncFnMock<(arg: string) => string>;
|
||||
let rendererDi: DiContainer;
|
||||
let mainDi: DiContainer;
|
||||
let requestFromChannel: RequestFromChannel;
|
||||
|
||||
beforeEach(async () => {
|
||||
const applicationBuilder = getApplicationBuilder();
|
||||
|
||||
mainDi = applicationBuilder.dis.mainDi;
|
||||
rendererDi = applicationBuilder.dis.rendererDi;
|
||||
|
||||
requestListenerInMainMock = asyncFn();
|
||||
|
||||
const testChannelListenerInMainInjectable = getInjectable({
|
||||
@ -186,19 +171,24 @@ describe("channel", () => {
|
||||
injectionToken: requestChannelListenerInjectionToken,
|
||||
});
|
||||
|
||||
mainDi.register(testChannelListenerInMainInjectable);
|
||||
applicationBuilder.beforeApplicationStart((mainDi) => {
|
||||
mainDi.register(testChannelListenerInMainInjectable);
|
||||
mainDi.register(testRequestChannelInjectable);
|
||||
});
|
||||
|
||||
// Notice how test channel has presence in both DIs, being from common
|
||||
mainDi.register(testRequestChannelInjectable);
|
||||
rendererDi.register(testRequestChannelInjectable);
|
||||
|
||||
testRequestChannel = rendererDi.inject(testRequestChannelInjectable);
|
||||
|
||||
requestFromChannel = rendererDi.inject(
|
||||
requestFromChannelInjectionToken,
|
||||
);
|
||||
applicationBuilder.beforeWindowStart((windowDi) => {
|
||||
windowDi.register(testRequestChannelInjectable);
|
||||
});
|
||||
|
||||
await applicationBuilder.render();
|
||||
|
||||
const windowDi = applicationBuilder.applicationWindow.only.di;
|
||||
|
||||
testRequestChannel = windowDi.inject(testRequestChannelInjectable);
|
||||
|
||||
requestFromChannel = windowDi.inject(
|
||||
requestFromChannelInjectionToken,
|
||||
);
|
||||
});
|
||||
|
||||
describe("when requesting from channel", () => {
|
||||
@ -245,29 +235,3 @@ const testRequestChannelInjectable = getInjectable({
|
||||
}),
|
||||
});
|
||||
|
||||
const createTestWindow = (di: DiContainer, id: string) => {
|
||||
const testWindowInjectable = getInjectable({
|
||||
id,
|
||||
|
||||
instantiate: (di) => {
|
||||
const createLensWindow = di.inject(createLensWindowInjectable);
|
||||
|
||||
return createLensWindow({
|
||||
id,
|
||||
title: "Some test window",
|
||||
defaultHeight: 42,
|
||||
defaultWidth: 42,
|
||||
getContentSource: () => ({ url: "some-content-url" }),
|
||||
resizable: true,
|
||||
windowFrameUtilitiesAreShown: false,
|
||||
centered: false,
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: lensWindowInjectionToken,
|
||||
});
|
||||
|
||||
di.register(testWindowInjectable);
|
||||
|
||||
return di.inject(testWindowInjectable);
|
||||
};
|
||||
|
||||
@ -2,13 +2,14 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { observe, runInAction } from "mobx";
|
||||
import type { ApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder";
|
||||
import createSyncBoxInjectable from "./create-sync-box.injectable";
|
||||
import { flushPromises } from "../../test-utils/flush-promises";
|
||||
import type { SyncBox } from "./sync-box-injection-token";
|
||||
import { syncBoxInjectionToken } from "./sync-box-injection-token";
|
||||
|
||||
describe("sync-box", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
@ -16,19 +17,23 @@ describe("sync-box", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
|
||||
applicationBuilder.dis.mainDi.register(someInjectable);
|
||||
applicationBuilder.dis.rendererDi.register(someInjectable);
|
||||
applicationBuilder.beforeApplicationStart(mainDi => {
|
||||
mainDi.register(someInjectable);
|
||||
});
|
||||
|
||||
applicationBuilder.beforeWindowStart((windowDi) => {
|
||||
windowDi.register(someInjectable);
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: Separate starting for main application and starting of window in application builder
|
||||
xdescribe("given application is started, when value is set in main", () => {
|
||||
describe("given application is started, when value is set in main", () => {
|
||||
let valueInMain: string;
|
||||
let syncBoxInMain: SyncBox<string>;
|
||||
|
||||
beforeEach(async () => {
|
||||
syncBoxInMain = applicationBuilder.dis.mainDi.inject(someInjectable);
|
||||
await applicationBuilder.startHidden();
|
||||
|
||||
// await applicationBuilder.start();
|
||||
syncBoxInMain = applicationBuilder.mainDi.inject(someInjectable);
|
||||
|
||||
observe(syncBoxInMain.value, ({ newValue }) => {
|
||||
valueInMain = newValue as string;
|
||||
@ -46,48 +51,28 @@ describe("sync-box", () => {
|
||||
describe("when window starts", () => {
|
||||
let valueInRenderer: string;
|
||||
let syncBoxInRenderer: SyncBox<string>;
|
||||
let rendererDi: DiContainer;
|
||||
|
||||
beforeEach(() => {
|
||||
// applicationBuilder.renderWindow()
|
||||
beforeEach(async () => {
|
||||
const applicationWindow =
|
||||
applicationBuilder.applicationWindow.create("some-window-id");
|
||||
|
||||
syncBoxInRenderer = applicationBuilder.dis.rendererDi.inject(someInjectable);
|
||||
await applicationWindow.start();
|
||||
|
||||
rendererDi = applicationWindow.di;
|
||||
|
||||
syncBoxInRenderer = rendererDi.inject(someInjectable);
|
||||
|
||||
observe(syncBoxInRenderer.value, ({ newValue }) => {
|
||||
valueInRenderer = newValue as string;
|
||||
}, true);
|
||||
});
|
||||
|
||||
it("does not have the initial value yet", () => {
|
||||
expect(valueInRenderer).toBe(undefined);
|
||||
it("has the value from main", () => {
|
||||
expect(valueInRenderer).toBe("some-value-from-main");
|
||||
});
|
||||
|
||||
describe("when getting initial value resolves", () => {
|
||||
beforeEach(async () => {
|
||||
await flushPromises();
|
||||
});
|
||||
|
||||
it("has value in renderer", () => {
|
||||
expect(valueInRenderer).toBe("some-value-from-main");
|
||||
});
|
||||
|
||||
describe("when value is set from renderer", () => {
|
||||
beforeEach(() => {
|
||||
runInAction(() => {
|
||||
syncBoxInRenderer.set("some-value-from-renderer");
|
||||
});
|
||||
});
|
||||
|
||||
it("has value in main", () => {
|
||||
expect(valueInMain).toBe("some-value-from-renderer");
|
||||
});
|
||||
|
||||
it("has value in renderer", () => {
|
||||
expect(valueInRenderer).toBe("some-value-from-renderer");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("when value is set from renderer before getting initial value from main resolves", () => {
|
||||
describe("when value is set from renderer", () => {
|
||||
beforeEach(() => {
|
||||
runInAction(() => {
|
||||
syncBoxInRenderer.set("some-value-from-renderer");
|
||||
@ -112,11 +97,13 @@ describe("sync-box", () => {
|
||||
let syncBoxInRenderer: SyncBox<string>;
|
||||
|
||||
beforeEach(async () => {
|
||||
syncBoxInMain = applicationBuilder.dis.mainDi.inject(someInjectable);
|
||||
syncBoxInRenderer = applicationBuilder.dis.rendererDi.inject(someInjectable);
|
||||
|
||||
await applicationBuilder.render();
|
||||
|
||||
const applicationWindow = applicationBuilder.applicationWindow.only;
|
||||
|
||||
syncBoxInMain = applicationBuilder.mainDi.inject(someInjectable);
|
||||
syncBoxInRenderer = applicationWindow.di.inject(someInjectable);
|
||||
|
||||
observe(syncBoxInRenderer.value, ({ newValue }) => {
|
||||
valueInRenderer = newValue as string;
|
||||
}, true);
|
||||
@ -176,4 +163,6 @@ const someInjectable = getInjectable({
|
||||
|
||||
return createSyncBox("some-sync-box", "some-initial-value");
|
||||
},
|
||||
|
||||
injectionToken: syncBoxInjectionToken,
|
||||
});
|
||||
|
||||
@ -21,7 +21,7 @@ import periodicalCheckForUpdatesInjectable from "../../main/application-update/p
|
||||
import { advanceFakeTime, useFakeTime } from "../../common/test-utils/use-fake-time";
|
||||
|
||||
describe("analytics for installing update", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let builder: ApplicationBuilder;
|
||||
let checkForPlatformUpdatesMock: AsyncFnMock<CheckForPlatformUpdates>;
|
||||
let downloadPlatformUpdateMock: AsyncFnMock<DownloadPlatformUpdate>;
|
||||
let analyticsListenerMock: jest.Mock;
|
||||
@ -30,11 +30,11 @@ describe("analytics for installing update", () => {
|
||||
beforeEach(async () => {
|
||||
useFakeTime("2015-10-21T07:28:00Z");
|
||||
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
analyticsListenerMock = jest.fn();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
builder.beforeApplicationStart(mainDi => {
|
||||
mainDi.override(appVersionInjectable, () => "42.0.0");
|
||||
|
||||
checkForPlatformUpdatesMock = asyncFn();
|
||||
@ -56,7 +56,7 @@ describe("analytics for installing update", () => {
|
||||
eventBus.addListener(analyticsListenerMock);
|
||||
});
|
||||
|
||||
mainDi = applicationBuilder.dis.mainDi;
|
||||
mainDi = builder.mainDi;
|
||||
});
|
||||
|
||||
describe("given application is started and checking updates periodically", () => {
|
||||
@ -64,7 +64,7 @@ describe("analytics for installing update", () => {
|
||||
mainDi.unoverride(periodicalCheckForUpdatesInjectable);
|
||||
mainDi.permitSideEffects(periodicalCheckForUpdatesInjectable);
|
||||
|
||||
await applicationBuilder.render();
|
||||
await builder.render();
|
||||
|
||||
});
|
||||
|
||||
@ -101,7 +101,7 @@ describe("analytics for installing update", () => {
|
||||
beforeEach(async () => {
|
||||
analyticsListenerMock.mockClear();
|
||||
|
||||
await applicationBuilder.render();
|
||||
await builder.render();
|
||||
});
|
||||
|
||||
it("sends event to analytics about the current version", () => {
|
||||
@ -119,7 +119,7 @@ describe("analytics for installing update", () => {
|
||||
it("when checking for updates using tray, sends event to analytics for being checked from tray", async () => {
|
||||
analyticsListenerMock.mockClear();
|
||||
|
||||
applicationBuilder.tray.click("check-for-updates");
|
||||
builder.tray.click("check-for-updates");
|
||||
|
||||
expect(analyticsListenerMock.mock.calls).toEqual([
|
||||
[
|
||||
@ -140,7 +140,7 @@ describe("analytics for installing update", () => {
|
||||
it("when checking for updates using application menu, sends event to analytics for being checked from application menu", async () => {
|
||||
analyticsListenerMock.mockClear();
|
||||
|
||||
applicationBuilder.applicationMenu.click("root.check-for-updates");
|
||||
builder.applicationMenu.click("root.check-for-updates");
|
||||
|
||||
expect(analyticsListenerMock.mock.calls).toEqual([
|
||||
[
|
||||
|
||||
@ -24,7 +24,7 @@ describe("downgrading version update", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
applicationBuilder.beforeApplicationStart(mainDi => {
|
||||
checkForPlatformUpdatesMock = asyncFn();
|
||||
|
||||
mainDi.override(
|
||||
@ -36,7 +36,7 @@ describe("downgrading version update", () => {
|
||||
mainDi.override(publishIsConfiguredInjectable, () => true);
|
||||
});
|
||||
|
||||
mainDi = applicationBuilder.dis.mainDi;
|
||||
mainDi = applicationBuilder.mainDi;
|
||||
});
|
||||
|
||||
[
|
||||
|
||||
@ -35,10 +35,7 @@ describe("force user to update when too long since update was downloaded", () =>
|
||||
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi, rendererDi }) => {
|
||||
rendererDi.unoverride(forceUpdateModalRootFrameComponentInjectable);
|
||||
rendererDi.permitSideEffects(forceUpdateModalRootFrameComponentInjectable);
|
||||
|
||||
applicationBuilder.beforeApplicationStart(mainDi => {
|
||||
checkForPlatformUpdatesMock = asyncFn();
|
||||
|
||||
mainDi.override(checkForPlatformUpdatesInjectable, () => checkForPlatformUpdatesMock);
|
||||
@ -50,13 +47,17 @@ describe("force user to update when too long since update was downloaded", () =>
|
||||
quitAndInstallUpdateMock = jest.fn();
|
||||
|
||||
mainDi.override(quitAndInstallUpdateInjectable, () => quitAndInstallUpdateMock);
|
||||
|
||||
rendererDi.override(timeAfterUpdateMustBeInstalledInjectable, () => TIME_AFTER_UPDATE_MUST_BE_INSTALLED);
|
||||
|
||||
rendererDi.override(secondsAfterInstallStartsInjectable, () => TIME_AFTER_INSTALL_STARTS / 1000);
|
||||
});
|
||||
|
||||
mainDi = applicationBuilder.dis.mainDi;
|
||||
applicationBuilder.beforeWindowStart(windowDi => {
|
||||
windowDi.unoverride(forceUpdateModalRootFrameComponentInjectable);
|
||||
windowDi.permitSideEffects(forceUpdateModalRootFrameComponentInjectable);
|
||||
|
||||
windowDi.override(timeAfterUpdateMustBeInstalledInjectable, () => TIME_AFTER_UPDATE_MUST_BE_INSTALLED);
|
||||
windowDi.override(secondsAfterInstallStartsInjectable, () => TIME_AFTER_INSTALL_STARTS / 1000);
|
||||
});
|
||||
|
||||
mainDi = applicationBuilder.mainDi;
|
||||
});
|
||||
|
||||
describe("when application is started", () => {
|
||||
|
||||
@ -33,7 +33,7 @@ describe("encourage user to update when sufficient time passed since update was
|
||||
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
applicationBuilder.beforeApplicationStart((mainDi) => {
|
||||
checkForPlatformUpdatesMock = asyncFn();
|
||||
downloadPlatformUpdateMock = asyncFn();
|
||||
|
||||
@ -76,7 +76,7 @@ describe("encourage user to update when sufficient time passed since update was
|
||||
let processCheckingForUpdates: (source: string) => Promise<{ updateIsReadyToBeInstalled: boolean }>;
|
||||
|
||||
beforeEach(async () => {
|
||||
processCheckingForUpdates = applicationBuilder.dis.mainDi.inject(
|
||||
processCheckingForUpdates = applicationBuilder.mainDi.inject(
|
||||
processCheckingForUpdatesInjectable,
|
||||
);
|
||||
|
||||
@ -105,8 +105,15 @@ describe("encourage user to update when sufficient time passed since update was
|
||||
expect(button).toHaveAttribute("data-warning-level", "light");
|
||||
});
|
||||
|
||||
// TODO: Implement after starting main and renderer is separated in ApplicationBuilder
|
||||
xit("given closing the application window, when starting the application window again, still shows the button", () => {
|
||||
it("given closing the application window, when starting the application window again, still shows the button", async () => {
|
||||
applicationBuilder.applicationWindow.closeAll();
|
||||
|
||||
const window = applicationBuilder.applicationWindow.create("some-window-id");
|
||||
|
||||
await window.start();
|
||||
|
||||
const button = window.rendered.queryByTestId("update-button");
|
||||
|
||||
expect(button).toBeInTheDocument();
|
||||
});
|
||||
|
||||
|
||||
@ -13,19 +13,18 @@ import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import type { DownloadPlatformUpdate } from "../../main/application-update/download-platform-update/download-platform-update.injectable";
|
||||
import downloadPlatformUpdateInjectable from "../../main/application-update/download-platform-update/download-platform-update.injectable";
|
||||
import closeAllWindowsInjectable from "../../main/start-main-application/lens-window/hide-all-windows/close-all-windows.injectable";
|
||||
import applicationWindowInjectable from "../../main/start-main-application/lens-window/application-window/application-window.injectable";
|
||||
import type { LensWindow } from "../../main/start-main-application/lens-window/application-window/lens-window-injection-token";
|
||||
import type { LensWindow } from "../../main/start-main-application/lens-window/application-window/create-lens-window.injectable";
|
||||
import getCurrentApplicationWindowInjectable from "../../main/start-main-application/lens-window/application-window/get-current-application-window.injectable";
|
||||
|
||||
describe("installing update using tray", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let builder: ApplicationBuilder;
|
||||
let checkForPlatformUpdatesMock: AsyncFnMock<CheckForPlatformUpdates>;
|
||||
let downloadPlatformUpdateMock: AsyncFnMock<DownloadPlatformUpdate>;
|
||||
|
||||
beforeEach(() => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
checkForPlatformUpdatesMock = asyncFn();
|
||||
downloadPlatformUpdateMock = asyncFn();
|
||||
|
||||
@ -48,7 +47,7 @@ describe("installing update using tray", () => {
|
||||
let rendered: RenderResult;
|
||||
|
||||
beforeEach(async () => {
|
||||
rendered = await applicationBuilder.render();
|
||||
rendered = await builder.render();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -56,23 +55,20 @@ describe("installing update using tray", () => {
|
||||
});
|
||||
|
||||
it("user cannot install update yet", () => {
|
||||
expect(applicationBuilder.tray.get("install-update")).toBeNull();
|
||||
expect(builder.tray.get("install-update")).toBeNull();
|
||||
});
|
||||
|
||||
describe("given all application windows are closed, when checking for updates", () => {
|
||||
let applicationWindow: LensWindow;
|
||||
let closeAllWindows: () => void;
|
||||
let getCurrentApplicationWindow: () => LensWindow | undefined;
|
||||
|
||||
beforeEach(() => {
|
||||
const mainDi = applicationBuilder.dis.mainDi;
|
||||
getCurrentApplicationWindow = builder.mainDi.inject(
|
||||
getCurrentApplicationWindowInjectable,
|
||||
);
|
||||
|
||||
closeAllWindows = mainDi.inject(closeAllWindowsInjectable);
|
||||
builder.applicationWindow.closeAll();
|
||||
|
||||
applicationWindow = mainDi.inject(applicationWindowInjectable);
|
||||
|
||||
closeAllWindows();
|
||||
|
||||
applicationBuilder.tray.click("check-for-updates");
|
||||
builder.tray.click("check-for-updates");
|
||||
});
|
||||
|
||||
describe("when check for update resolves with new update", () => {
|
||||
@ -84,37 +80,44 @@ describe("installing update using tray", () => {
|
||||
});
|
||||
|
||||
it("does not show application window yet", () => {
|
||||
expect(applicationWindow.isVisible).toBe(false);
|
||||
const actual = getCurrentApplicationWindow();
|
||||
|
||||
expect(actual).toBeUndefined();
|
||||
});
|
||||
|
||||
describe("when download of update resolves with success", () => {
|
||||
beforeEach(async () => {
|
||||
|
||||
await downloadPlatformUpdateMock.resolve({ downloadWasSuccessful: true });
|
||||
});
|
||||
|
||||
it("shows the application window", () => {
|
||||
expect(applicationWindow.isVisible).toBe(true);
|
||||
const actual = getCurrentApplicationWindow();
|
||||
|
||||
expect(actual).not.toBeUndefined();
|
||||
});
|
||||
|
||||
it("given closing application window again and checking for updates again using tray, when check resolves with same version that was earlier downloaded, shows the application window", async () => {
|
||||
closeAllWindows();
|
||||
builder.applicationWindow.closeAll();
|
||||
|
||||
applicationBuilder.tray.click("check-for-updates");
|
||||
builder.tray.click("check-for-updates");
|
||||
|
||||
await checkForPlatformUpdatesMock.resolve({
|
||||
updateWasDiscovered: true,
|
||||
version: "some-version",
|
||||
});
|
||||
|
||||
expect(applicationWindow.isVisible).toBe(true);
|
||||
const actual = getCurrentApplicationWindow();
|
||||
|
||||
expect(actual).not.toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
it("when download of update resolves with failure, does not show the application window", async () => {
|
||||
await downloadPlatformUpdateMock.resolve({ downloadWasSuccessful: false });
|
||||
|
||||
expect(applicationWindow.isVisible).toBe(false);
|
||||
const actual = getCurrentApplicationWindow();
|
||||
|
||||
expect(actual).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
@ -123,29 +126,31 @@ describe("installing update using tray", () => {
|
||||
updateWasDiscovered: false,
|
||||
});
|
||||
|
||||
expect(applicationWindow.isVisible).toBe(false);
|
||||
const actual = getCurrentApplicationWindow();
|
||||
|
||||
expect(actual).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("when user checks for updates using tray", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.tray.click("check-for-updates");
|
||||
builder.tray.click("check-for-updates");
|
||||
});
|
||||
|
||||
it("user cannot check for updates again", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.enabled,
|
||||
builder.tray.get("check-for-updates")?.enabled,
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("name of tray item for checking updates indicates that checking is happening", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.label,
|
||||
builder.tray.get("check-for-updates")?.label,
|
||||
).toBe("Checking for updates...");
|
||||
});
|
||||
|
||||
it("user cannot install update yet", () => {
|
||||
expect(applicationBuilder.tray.get("install-update")).toBeNull();
|
||||
expect(builder.tray.get("install-update")).toBeNull();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -160,18 +165,18 @@ describe("installing update using tray", () => {
|
||||
});
|
||||
|
||||
it("user cannot install update", () => {
|
||||
expect(applicationBuilder.tray.get("install-update")).toBeNull();
|
||||
expect(builder.tray.get("install-update")).toBeNull();
|
||||
});
|
||||
|
||||
it("user can check for updates again", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.enabled,
|
||||
builder.tray.get("check-for-updates")?.enabled,
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("name of tray item for checking updates no longer indicates that checking is happening", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.label,
|
||||
builder.tray.get("check-for-updates")?.label,
|
||||
).toBe("Check for updates");
|
||||
});
|
||||
|
||||
@ -190,13 +195,13 @@ describe("installing update using tray", () => {
|
||||
|
||||
it("user cannot check for updates again yet", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.enabled,
|
||||
builder.tray.get("check-for-updates")?.enabled,
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("name of tray item for checking updates indicates that downloading is happening", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.label,
|
||||
builder.tray.get("check-for-updates")?.label,
|
||||
).toBe("Downloading update some-version (0%)...");
|
||||
});
|
||||
|
||||
@ -204,12 +209,12 @@ describe("installing update using tray", () => {
|
||||
downloadPlatformUpdateMock.mock.calls[0][0]({ percentage: 42.424242 });
|
||||
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.label,
|
||||
builder.tray.get("check-for-updates")?.label,
|
||||
).toBe("Downloading update some-version (42%)...");
|
||||
});
|
||||
|
||||
it("user still cannot install update", () => {
|
||||
expect(applicationBuilder.tray.get("install-update")).toBeNull();
|
||||
expect(builder.tray.get("install-update")).toBeNull();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -223,19 +228,19 @@ describe("installing update using tray", () => {
|
||||
|
||||
it("user cannot install update", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("install-update"),
|
||||
builder.tray.get("install-update"),
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it("user can check for updates again", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.enabled,
|
||||
builder.tray.get("check-for-updates")?.enabled,
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("name of tray item for checking updates no longer indicates that downloading is happening", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.label,
|
||||
builder.tray.get("check-for-updates")?.label,
|
||||
).toBe("Check for updates");
|
||||
});
|
||||
|
||||
@ -251,19 +256,19 @@ describe("installing update using tray", () => {
|
||||
|
||||
it("user can install update", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("install-update")?.label,
|
||||
builder.tray.get("install-update")?.label,
|
||||
).toBe("Install update some-version");
|
||||
});
|
||||
|
||||
it("user can check for updates again", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.enabled,
|
||||
builder.tray.get("check-for-updates")?.enabled,
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("name of tray item for checking updates no longer indicates that downloading is happening", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get("check-for-updates")?.label,
|
||||
builder.tray.get("check-for-updates")?.label,
|
||||
).toBe("Check for updates");
|
||||
});
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ import { useFakeTime } from "../../common/test-utils/use-fake-time";
|
||||
import staticFilesDirectoryInjectable from "../../common/vars/static-files-directory.injectable";
|
||||
|
||||
describe("installing update", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let builder: ApplicationBuilder;
|
||||
let quitAndInstallUpdateMock: jest.Mock;
|
||||
let checkForPlatformUpdatesMock: AsyncFnMock<CheckForPlatformUpdates>;
|
||||
let downloadPlatformUpdateMock: AsyncFnMock<DownloadPlatformUpdate>;
|
||||
@ -29,9 +29,9 @@ describe("installing update", () => {
|
||||
beforeEach(() => {
|
||||
useFakeTime("2015-10-21T07:28:00Z");
|
||||
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
quitAndInstallUpdateMock = jest.fn();
|
||||
checkForPlatformUpdatesMock = asyncFn();
|
||||
downloadPlatformUpdateMock = asyncFn();
|
||||
@ -66,9 +66,9 @@ describe("installing update", () => {
|
||||
let processCheckingForUpdates: (source: string) => Promise<{ updateIsReadyToBeInstalled: boolean }>;
|
||||
|
||||
beforeEach(async () => {
|
||||
rendered = await applicationBuilder.render();
|
||||
rendered = await builder.render();
|
||||
|
||||
processCheckingForUpdates = applicationBuilder.dis.mainDi.inject(
|
||||
processCheckingForUpdates = builder.mainDi.inject(
|
||||
processCheckingForUpdatesInjectable,
|
||||
);
|
||||
});
|
||||
@ -78,7 +78,7 @@ describe("installing update", () => {
|
||||
});
|
||||
|
||||
it("shows normal tray icon", () => {
|
||||
expect(applicationBuilder.tray.getIconPath()).toBe(
|
||||
expect(builder.tray.getIconPath()).toBe(
|
||||
"/some-static-files-directory/icons/trayIconTemplate.png",
|
||||
);
|
||||
});
|
||||
@ -96,7 +96,7 @@ describe("installing update", () => {
|
||||
});
|
||||
|
||||
it("shows tray icon for checking for updates", () => {
|
||||
expect(applicationBuilder.tray.getIconPath()).toBe(
|
||||
expect(builder.tray.getIconPath()).toBe(
|
||||
"/some-static-files-directory/icons/trayIconCheckingForUpdatesTemplate.png",
|
||||
);
|
||||
});
|
||||
@ -113,7 +113,7 @@ describe("installing update", () => {
|
||||
});
|
||||
|
||||
it("shows tray icon for normal", () => {
|
||||
expect(applicationBuilder.tray.getIconPath()).toBe(
|
||||
expect(builder.tray.getIconPath()).toBe(
|
||||
"/some-static-files-directory/icons/trayIconTemplate.png",
|
||||
);
|
||||
});
|
||||
@ -140,7 +140,7 @@ describe("installing update", () => {
|
||||
});
|
||||
|
||||
it("still shows tray icon for downloading", () => {
|
||||
expect(applicationBuilder.tray.getIconPath()).toBe(
|
||||
expect(builder.tray.getIconPath()).toBe(
|
||||
"/some-static-files-directory/icons/trayIconCheckingForUpdatesTemplate.png",
|
||||
);
|
||||
});
|
||||
@ -159,7 +159,7 @@ describe("installing update", () => {
|
||||
});
|
||||
|
||||
it("still shows normal tray icon", () => {
|
||||
expect(applicationBuilder.tray.getIconPath()).toBe(
|
||||
expect(builder.tray.getIconPath()).toBe(
|
||||
"/some-static-files-directory/icons/trayIconTemplate.png",
|
||||
);
|
||||
});
|
||||
@ -179,7 +179,7 @@ describe("installing update", () => {
|
||||
});
|
||||
|
||||
it("shows tray icon for update being available", () => {
|
||||
expect(applicationBuilder.tray.getIconPath()).toBe(
|
||||
expect(builder.tray.getIconPath()).toBe(
|
||||
"/some-static-files-directory/icons/trayIconUpdateAvailableTemplate.png",
|
||||
);
|
||||
});
|
||||
@ -196,7 +196,7 @@ describe("installing update", () => {
|
||||
});
|
||||
|
||||
it("shows tray icon for checking for updates", () => {
|
||||
expect(applicationBuilder.tray.getIconPath()).toBe(
|
||||
expect(builder.tray.getIconPath()).toBe(
|
||||
"/some-static-files-directory/icons/trayIconCheckingForUpdatesTemplate.png",
|
||||
);
|
||||
});
|
||||
@ -214,7 +214,7 @@ describe("installing update", () => {
|
||||
});
|
||||
|
||||
it("shows tray icon for update being available", () => {
|
||||
expect(applicationBuilder.tray.getIconPath()).toBe(
|
||||
expect(builder.tray.getIconPath()).toBe(
|
||||
"/some-static-files-directory/icons/trayIconUpdateAvailableTemplate.png",
|
||||
);
|
||||
});
|
||||
@ -233,7 +233,7 @@ describe("installing update", () => {
|
||||
});
|
||||
|
||||
it("shows tray icon for downloading update", () => {
|
||||
expect(applicationBuilder.tray.getIconPath()).toBe(
|
||||
expect(builder.tray.getIconPath()).toBe(
|
||||
"/some-static-files-directory/icons/trayIconCheckingForUpdatesTemplate.png",
|
||||
);
|
||||
});
|
||||
|
||||
@ -14,15 +14,15 @@ import { advanceFakeTime, useFakeTime } from "../../common/test-utils/use-fake-t
|
||||
const ENOUGH_TIME = 1000 * 60 * 60 * 2;
|
||||
|
||||
describe("periodical checking of updates", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let builder: ApplicationBuilder;
|
||||
let processCheckingForUpdatesMock: jest.Mock;
|
||||
|
||||
beforeEach(() => {
|
||||
useFakeTime("2015-10-21T07:28:00Z");
|
||||
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
mainDi.unoverride(periodicalCheckForUpdatesInjectable);
|
||||
mainDi.permitSideEffects(periodicalCheckForUpdatesInjectable);
|
||||
|
||||
@ -39,12 +39,12 @@ describe("periodical checking of updates", () => {
|
||||
let rendered: RenderResult;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
mainDi.override(electronUpdaterIsActiveInjectable, () => true);
|
||||
mainDi.override(publishIsConfiguredInjectable, () => true);
|
||||
});
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
rendered = await builder.render();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -74,12 +74,12 @@ describe("periodical checking of updates", () => {
|
||||
|
||||
describe("given updater is enabled but no configuration exist, when started", () => {
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
mainDi.override(electronUpdaterIsActiveInjectable, () => true);
|
||||
mainDi.override(publishIsConfiguredInjectable, () => false);
|
||||
});
|
||||
|
||||
await applicationBuilder.render();
|
||||
await builder.render();
|
||||
});
|
||||
|
||||
it("does not check for updates", () => {
|
||||
@ -95,12 +95,12 @@ describe("periodical checking of updates", () => {
|
||||
|
||||
describe("given updater is not enabled but and configuration exist, when started", () => {
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
mainDi.override(electronUpdaterIsActiveInjectable, () => false);
|
||||
mainDi.override(publishIsConfiguredInjectable, () => true);
|
||||
});
|
||||
|
||||
await applicationBuilder.render();
|
||||
await builder.render();
|
||||
});
|
||||
|
||||
it("does not check for updates", () => {
|
||||
|
||||
@ -22,26 +22,25 @@ import setUpdateOnQuitInjectable from "../../main/electron-app/features/set-upda
|
||||
import showInfoNotificationInjectable from "../../renderer/components/notifications/show-info-notification.injectable";
|
||||
import processCheckingForUpdatesInjectable from "../../main/application-update/check-for-updates/process-checking-for-updates.injectable";
|
||||
import appVersionInjectable from "../../common/vars/app-version.injectable";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
|
||||
describe("selection of update stability", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let builder: ApplicationBuilder;
|
||||
let quitAndInstallUpdateMock: jest.Mock;
|
||||
let checkForPlatformUpdatesMock: AsyncFnMock<CheckForPlatformUpdates>;
|
||||
let downloadPlatformUpdateMock: AsyncFnMock<DownloadPlatformUpdate>;
|
||||
let setUpdateOnQuitMock: jest.Mock;
|
||||
let showInfoNotificationMock: jest.Mock;
|
||||
let mainDi: DiContainer;
|
||||
|
||||
beforeEach(() => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi, rendererDi }) => {
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
quitAndInstallUpdateMock = jest.fn();
|
||||
checkForPlatformUpdatesMock = asyncFn();
|
||||
downloadPlatformUpdateMock = asyncFn();
|
||||
setUpdateOnQuitMock = jest.fn();
|
||||
showInfoNotificationMock = jest.fn(() => () => {});
|
||||
|
||||
rendererDi.override(showInfoNotificationInjectable, () => showInfoNotificationMock);
|
||||
|
||||
mainDi.override(setUpdateOnQuitInjectable, () => setUpdateOnQuitMock);
|
||||
|
||||
@ -63,6 +62,14 @@ describe("selection of update stability", () => {
|
||||
mainDi.override(electronUpdaterIsActiveInjectable, () => true);
|
||||
mainDi.override(publishIsConfiguredInjectable, () => true);
|
||||
});
|
||||
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
showInfoNotificationMock = jest.fn(() => () => {});
|
||||
|
||||
windowDi.override(showInfoNotificationInjectable, () => showInfoNotificationMock);
|
||||
});
|
||||
|
||||
mainDi = builder.mainDi;
|
||||
});
|
||||
|
||||
describe("when started", () => {
|
||||
@ -70,9 +77,9 @@ describe("selection of update stability", () => {
|
||||
let processCheckingForUpdates: (source: string) => Promise<{ updateIsReadyToBeInstalled: boolean }>;
|
||||
|
||||
beforeEach(async () => {
|
||||
rendered = await applicationBuilder.render();
|
||||
rendered = await builder.render();
|
||||
|
||||
processCheckingForUpdates = applicationBuilder.dis.mainDi.inject(processCheckingForUpdatesInjectable);
|
||||
processCheckingForUpdates = mainDi.inject(processCheckingForUpdatesInjectable);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -86,7 +93,7 @@ describe("selection of update stability", () => {
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
selectedUpdateChannel = applicationBuilder.dis.mainDi.inject(
|
||||
selectedUpdateChannel = mainDi.inject(
|
||||
selectedUpdateChannelInjectable,
|
||||
);
|
||||
|
||||
@ -177,7 +184,7 @@ describe("selection of update stability", () => {
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
selectedUpdateChannel = applicationBuilder.dis.mainDi.inject(
|
||||
selectedUpdateChannel = mainDi.inject(
|
||||
selectedUpdateChannelInjectable,
|
||||
);
|
||||
|
||||
@ -224,7 +231,7 @@ describe("selection of update stability", () => {
|
||||
});
|
||||
|
||||
it("given valid update channel selection is stored, when checking for updates, checks for updates from the update channel", async () => {
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
// TODO: Switch to more natural way of setting initial value
|
||||
// TODO: UserStore is currently responsible for getting and setting initial value
|
||||
const selectedUpdateChannel = mainDi.inject(selectedUpdateChannelInjectable);
|
||||
@ -232,9 +239,9 @@ describe("selection of update stability", () => {
|
||||
selectedUpdateChannel.setValue(updateChannels.beta.id);
|
||||
});
|
||||
|
||||
await applicationBuilder.render();
|
||||
await builder.render();
|
||||
|
||||
const processCheckingForUpdates = applicationBuilder.dis.mainDi.inject(processCheckingForUpdatesInjectable);
|
||||
const processCheckingForUpdates = mainDi.inject(processCheckingForUpdatesInjectable);
|
||||
|
||||
processCheckingForUpdates("irrelevant");
|
||||
|
||||
@ -242,7 +249,7 @@ describe("selection of update stability", () => {
|
||||
});
|
||||
|
||||
it("given invalid update channel selection is stored, when checking for updates, checks for updates from the update channel", async () => {
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
// TODO: Switch to more natural way of setting initial value
|
||||
// TODO: UserStore is currently responsible for getting and setting initial value
|
||||
const selectedUpdateChannel = mainDi.inject(selectedUpdateChannelInjectable);
|
||||
@ -250,9 +257,9 @@ describe("selection of update stability", () => {
|
||||
selectedUpdateChannel.setValue("something-invalid" as UpdateChannelId);
|
||||
});
|
||||
|
||||
await applicationBuilder.render();
|
||||
await builder.render();
|
||||
|
||||
const processCheckingForUpdates = applicationBuilder.dis.mainDi.inject(processCheckingForUpdatesInjectable);
|
||||
const processCheckingForUpdates = mainDi.inject(processCheckingForUpdatesInjectable);
|
||||
|
||||
processCheckingForUpdates("irrelevant");
|
||||
|
||||
@ -260,13 +267,13 @@ describe("selection of update stability", () => {
|
||||
});
|
||||
|
||||
it('given no update channel selection is stored and currently using stable release, when user checks for updates, checks for updates from "latest" update channel by default', async () => {
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
mainDi.override(appVersionInjectable, () => "1.0.0");
|
||||
});
|
||||
|
||||
await applicationBuilder.render();
|
||||
await builder.render();
|
||||
|
||||
const processCheckingForUpdates = applicationBuilder.dis.mainDi.inject(processCheckingForUpdatesInjectable);
|
||||
const processCheckingForUpdates = mainDi.inject(processCheckingForUpdatesInjectable);
|
||||
|
||||
processCheckingForUpdates("irrelevant");
|
||||
|
||||
@ -277,13 +284,13 @@ describe("selection of update stability", () => {
|
||||
});
|
||||
|
||||
it('given no update channel selection is stored and currently using alpha release, when checking for updates, checks for updates from "alpha" channel', async () => {
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
mainDi.override(appVersionInjectable, () => "1.0.0-alpha");
|
||||
});
|
||||
|
||||
await applicationBuilder.render();
|
||||
await builder.render();
|
||||
|
||||
const processCheckingForUpdates = applicationBuilder.dis.mainDi.inject(processCheckingForUpdatesInjectable);
|
||||
const processCheckingForUpdates = mainDi.inject(processCheckingForUpdatesInjectable);
|
||||
|
||||
processCheckingForUpdates("irrelevant");
|
||||
|
||||
@ -291,13 +298,13 @@ describe("selection of update stability", () => {
|
||||
});
|
||||
|
||||
it('given no update channel selection is stored and currently using beta release, when checking for updates, checks for updates from "beta" channel', async () => {
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
mainDi.override(appVersionInjectable, () => "1.0.0-beta");
|
||||
});
|
||||
|
||||
await applicationBuilder.render();
|
||||
await builder.render();
|
||||
|
||||
const processCheckingForUpdates = applicationBuilder.dis.mainDi.inject(processCheckingForUpdatesInjectable);
|
||||
const processCheckingForUpdates = mainDi.inject(processCheckingForUpdatesInjectable);
|
||||
|
||||
processCheckingForUpdates("irrelevant");
|
||||
|
||||
@ -305,7 +312,7 @@ describe("selection of update stability", () => {
|
||||
});
|
||||
|
||||
it("given update channel selection is stored and currently using prerelease, when checking for updates, checks for updates from stored channel", async () => {
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
mainDi.override(appVersionInjectable, () => "1.0.0-alpha");
|
||||
|
||||
// TODO: Switch to more natural way of setting initial value
|
||||
@ -315,9 +322,9 @@ describe("selection of update stability", () => {
|
||||
selectedUpdateChannel.setValue(updateChannels.beta.id);
|
||||
});
|
||||
|
||||
await applicationBuilder.render();
|
||||
await builder.render();
|
||||
|
||||
const processCheckingForUpdates = applicationBuilder.dis.mainDi.inject(processCheckingForUpdatesInjectable);
|
||||
const processCheckingForUpdates = mainDi.inject(processCheckingForUpdatesInjectable);
|
||||
|
||||
processCheckingForUpdates("irrelevant");
|
||||
|
||||
|
||||
@ -8,7 +8,6 @@ import type { RenderResult } from "@testing-library/react";
|
||||
import type { ApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder";
|
||||
import type { TestExtensionRenderer } from "../../../renderer/components/test-utils/get-extension-fake";
|
||||
import { getExtensionFakeFor } from "../../../renderer/components/test-utils/get-extension-fake";
|
||||
import type { KubernetesCluster } from "../../../common/catalog-entities";
|
||||
import React from "react";
|
||||
import extensionShouldBeEnabledForClusterFrameInjectable from "../../../renderer/extension-loader/extension-should-be-enabled-for-cluster-frame.injectable";
|
||||
@ -24,13 +23,13 @@ describe("disable-cluster-pages-when-cluster-is-not-relevant", () => {
|
||||
|
||||
builder.setEnvironmentToClusterFrame();
|
||||
|
||||
builder.dis.rendererDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable);
|
||||
|
||||
const getExtensionFake = getExtensionFakeFor(builder);
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable);
|
||||
});
|
||||
|
||||
isEnabledForClusterMock = asyncFn();
|
||||
|
||||
const testExtension = getExtensionFake({
|
||||
const testExtension = {
|
||||
id: "test-extension-id",
|
||||
name: "test-extension",
|
||||
|
||||
@ -43,13 +42,14 @@ describe("disable-cluster-pages-when-cluster-is-not-relevant", () => {
|
||||
},
|
||||
}],
|
||||
},
|
||||
});
|
||||
|
||||
rendererTestExtension = testExtension.renderer;
|
||||
};
|
||||
|
||||
rendered = await builder.render();
|
||||
|
||||
builder.extensions.enable(testExtension);
|
||||
|
||||
rendererTestExtension =
|
||||
builder.extensions.get("test-extension-id").applicationWindows.only;
|
||||
});
|
||||
|
||||
describe("given not yet known if extension should be enabled for the cluster, when navigating", () => {
|
||||
|
||||
@ -7,7 +7,6 @@ import asyncFn from "@async-fn/jest";
|
||||
import type { RenderResult } from "@testing-library/react";
|
||||
import type { ApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getExtensionFakeFor } from "../../../renderer/components/test-utils/get-extension-fake";
|
||||
import type { KubernetesCluster } from "../../../common/catalog-entities";
|
||||
import React from "react";
|
||||
import extensionShouldBeEnabledForClusterFrameInjectable from "../../../renderer/extension-loader/extension-should-be-enabled-for-cluster-frame.injectable";
|
||||
@ -22,13 +21,13 @@ describe("disable sidebar items when cluster is not relevant", () => {
|
||||
|
||||
builder.setEnvironmentToClusterFrame();
|
||||
|
||||
builder.dis.rendererDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable);
|
||||
|
||||
const getExtensionFake = getExtensionFakeFor(builder);
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable);
|
||||
});
|
||||
|
||||
isEnabledForClusterMock = asyncFn();
|
||||
|
||||
const testExtension = getExtensionFake({
|
||||
const testExtension = {
|
||||
id: "test-extension-id",
|
||||
name: "test-extension",
|
||||
|
||||
@ -52,7 +51,7 @@ describe("disable sidebar items when cluster is not relevant", () => {
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
rendered = await builder.render();
|
||||
|
||||
|
||||
@ -9,24 +9,21 @@ import React from "react";
|
||||
import type { TestExtensionRenderer } from "../../../renderer/components/test-utils/get-extension-fake";
|
||||
import type { ApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getExtensionFakeFor } from "../../../renderer/components/test-utils/get-extension-fake";
|
||||
|
||||
describe("reactively disable cluster pages", () => {
|
||||
let builder: ApplicationBuilder;
|
||||
let rendered: RenderResult;
|
||||
let someObservable: IObservableValue<boolean>;
|
||||
let rendererTestExtension: TestExtensionRenderer;
|
||||
let testExtensionInstance: TestExtensionRenderer;
|
||||
|
||||
beforeEach(async () => {
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
builder.setEnvironmentToClusterFrame();
|
||||
|
||||
const getExtensionFake = getExtensionFakeFor(builder);
|
||||
|
||||
someObservable = observable.box(false);
|
||||
|
||||
const testExtension = getExtensionFake({
|
||||
const testExtensionOptions = {
|
||||
id: "test-extension-id",
|
||||
name: "test-extension",
|
||||
|
||||
@ -39,17 +36,18 @@ describe("reactively disable cluster pages", () => {
|
||||
enabled: computed(() => someObservable.get()),
|
||||
}],
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
rendered = await builder.render();
|
||||
|
||||
builder.extensions.enable(testExtension);
|
||||
builder.extensions.enable(testExtensionOptions);
|
||||
|
||||
rendererTestExtension = testExtension.renderer;
|
||||
testExtensionInstance =
|
||||
builder.extensions.get("test-extension-id").applicationWindows.only;
|
||||
});
|
||||
|
||||
it("when navigating to the page, does not show the page", () => {
|
||||
rendererTestExtension.navigate();
|
||||
testExtensionInstance.navigate();
|
||||
|
||||
const actual = rendered.queryByTestId("some-test-page");
|
||||
|
||||
@ -61,7 +59,7 @@ describe("reactively disable cluster pages", () => {
|
||||
someObservable.set(true);
|
||||
});
|
||||
|
||||
rendererTestExtension.navigate();
|
||||
testExtensionInstance.navigate();
|
||||
|
||||
const actual = rendered.queryByTestId("some-test-page");
|
||||
|
||||
|
||||
@ -8,7 +8,6 @@ import type { RenderResult } from "@testing-library/react";
|
||||
import type { ApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder";
|
||||
import type { KubernetesCluster } from "../../../../common/catalog-entities";
|
||||
import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getExtensionFakeFor } from "../../../../renderer/components/test-utils/get-extension-fake";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { frontEndRouteInjectionToken } from "../../../../common/front-end-routing/front-end-route-injection-token";
|
||||
import { computed } from "mobx";
|
||||
@ -30,9 +29,10 @@ describe("disable kube object detail items when cluster is not relevant", () =>
|
||||
|
||||
beforeEach(async () => {
|
||||
builder = getApplicationBuilder();
|
||||
builder.setEnvironmentToClusterFrame();
|
||||
|
||||
builder.beforeApplicationStart(({ rendererDi }) => {
|
||||
rendererDi.override(
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.override(
|
||||
apiManagerInjectable,
|
||||
() =>
|
||||
({
|
||||
@ -42,21 +42,15 @@ describe("disable kube object detail items when cluster is not relevant", () =>
|
||||
}),
|
||||
} as unknown as ApiManager),
|
||||
);
|
||||
|
||||
windowDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable);
|
||||
|
||||
windowDi.register(testRouteInjectable, testRouteComponentInjectable);
|
||||
});
|
||||
|
||||
const rendererDi = builder.dis.rendererDi;
|
||||
|
||||
rendererDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable);
|
||||
|
||||
rendererDi.register(testRouteInjectable, testRouteComponentInjectable);
|
||||
|
||||
builder.setEnvironmentToClusterFrame();
|
||||
|
||||
const getExtensionFake = getExtensionFakeFor(builder);
|
||||
|
||||
isEnabledForClusterMock = asyncFn();
|
||||
|
||||
const testExtension = getExtensionFake({
|
||||
const testExtension = {
|
||||
id: "test-extension-id",
|
||||
name: "test-extension",
|
||||
|
||||
@ -77,12 +71,14 @@ describe("disable kube object detail items when cluster is not relevant", () =>
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
rendered = await builder.render();
|
||||
|
||||
const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken);
|
||||
const testRoute = rendererDi.inject(testRouteInjectable);
|
||||
const windowDi = builder.applicationWindow.only.di;
|
||||
|
||||
const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken);
|
||||
const testRoute = windowDi.inject(testRouteInjectable);
|
||||
|
||||
navigateToRoute(testRoute);
|
||||
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
import type { RenderResult } from "@testing-library/react";
|
||||
import type { ApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getExtensionFakeFor } from "../../../../renderer/components/test-utils/get-extension-fake";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { frontEndRouteInjectionToken } from "../../../../common/front-end-routing/front-end-route-injection-token";
|
||||
import type { IObservableValue } from "mobx";
|
||||
@ -26,8 +25,10 @@ describe("reactively hide kube object detail item", () => {
|
||||
beforeEach(async () => {
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
builder.beforeApplicationStart(({ rendererDi }) => {
|
||||
rendererDi.override(
|
||||
builder.setEnvironmentToClusterFrame();
|
||||
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.override(
|
||||
apiManagerInjectable,
|
||||
() =>
|
||||
({
|
||||
@ -37,19 +38,13 @@ describe("reactively hide kube object detail item", () => {
|
||||
}),
|
||||
} as unknown as ApiManager),
|
||||
);
|
||||
|
||||
windowDi.register(testRouteInjectable, testRouteComponentInjectable);
|
||||
});
|
||||
|
||||
const rendererDi = builder.dis.rendererDi;
|
||||
|
||||
rendererDi.register(testRouteInjectable, testRouteComponentInjectable);
|
||||
|
||||
builder.setEnvironmentToClusterFrame();
|
||||
|
||||
const getExtensionFake = getExtensionFakeFor(builder);
|
||||
|
||||
someObservable = observable.box(false);
|
||||
|
||||
const testExtension = getExtensionFake({
|
||||
const testExtension = {
|
||||
id: "test-extension-id",
|
||||
name: "test-extension",
|
||||
|
||||
@ -71,12 +66,14 @@ describe("reactively hide kube object detail item", () => {
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
rendered = await builder.render();
|
||||
|
||||
const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken);
|
||||
const testRoute = rendererDi.inject(testRouteInjectable);
|
||||
const windowDi = builder.applicationWindow.only.di;
|
||||
|
||||
const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken);
|
||||
const testRoute = windowDi.inject(testRouteInjectable);
|
||||
|
||||
navigateToRoute(testRoute);
|
||||
|
||||
|
||||
@ -8,7 +8,6 @@ import type { RenderResult } from "@testing-library/react";
|
||||
import type { ApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder";
|
||||
import type { KubernetesCluster } from "../../../../common/catalog-entities";
|
||||
import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getExtensionFakeFor } from "../../../../renderer/components/test-utils/get-extension-fake";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { frontEndRouteInjectionToken } from "../../../../common/front-end-routing/front-end-route-injection-token";
|
||||
import { computed } from "mobx";
|
||||
@ -29,19 +28,16 @@ describe("disable kube object menu items when cluster is not relevant", () => {
|
||||
beforeEach(async () => {
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
const rendererDi = builder.dis.rendererDi;
|
||||
|
||||
rendererDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable);
|
||||
|
||||
rendererDi.register(testRouteInjectable, testRouteComponentInjectable);
|
||||
|
||||
builder.setEnvironmentToClusterFrame();
|
||||
|
||||
const getExtensionFake = getExtensionFakeFor(builder);
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable);
|
||||
windowDi.register(testRouteInjectable, testRouteComponentInjectable);
|
||||
});
|
||||
|
||||
isEnabledForClusterMock = asyncFn();
|
||||
|
||||
const testExtension = getExtensionFake({
|
||||
const testExtension = {
|
||||
id: "test-extension-id",
|
||||
name: "test-extension",
|
||||
|
||||
@ -60,12 +56,14 @@ describe("disable kube object menu items when cluster is not relevant", () => {
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
rendered = await builder.render();
|
||||
|
||||
const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken);
|
||||
const testRoute = rendererDi.inject(testRouteInjectable);
|
||||
const windowDi = builder.applicationWindow.only.di;
|
||||
|
||||
const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken);
|
||||
const testRoute = windowDi.inject(testRouteInjectable);
|
||||
|
||||
navigateToRoute(testRoute);
|
||||
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
import type { RenderResult } from "@testing-library/react";
|
||||
import type { ApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getExtensionFakeFor } from "../../../../renderer/components/test-utils/get-extension-fake";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { frontEndRouteInjectionToken } from "../../../../common/front-end-routing/front-end-route-injection-token";
|
||||
import type { IObservableValue } from "mobx";
|
||||
@ -24,17 +23,15 @@ describe("reactively hide kube object menu item", () => {
|
||||
beforeEach(async () => {
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
const rendererDi = builder.dis.rendererDi;
|
||||
|
||||
rendererDi.register(testRouteInjectable, testRouteComponentInjectable);
|
||||
|
||||
builder.setEnvironmentToClusterFrame();
|
||||
|
||||
const getExtensionFake = getExtensionFakeFor(builder);
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.register(testRouteInjectable, testRouteComponentInjectable);
|
||||
});
|
||||
|
||||
someObservable = observable.box(false);
|
||||
|
||||
const testExtension = getExtensionFake({
|
||||
const testExtension = {
|
||||
id: "test-extension-id",
|
||||
name: "test-extension",
|
||||
|
||||
@ -53,12 +50,14 @@ describe("reactively hide kube object menu item", () => {
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
rendered = await builder.render();
|
||||
|
||||
const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken);
|
||||
const testRoute = rendererDi.inject(testRouteInjectable);
|
||||
const windowDi = builder.applicationWindow.only.di;
|
||||
|
||||
const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken);
|
||||
const testRoute = windowDi.inject(testRouteInjectable);
|
||||
|
||||
navigateToRoute(testRoute);
|
||||
|
||||
|
||||
@ -8,7 +8,6 @@ import type { RenderResult } from "@testing-library/react";
|
||||
import type { ApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder";
|
||||
import type { KubernetesCluster } from "../../../../common/catalog-entities";
|
||||
import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getExtensionFakeFor } from "../../../../renderer/components/test-utils/get-extension-fake";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { frontEndRouteInjectionToken } from "../../../../common/front-end-routing/front-end-route-injection-token";
|
||||
import { computed } from "mobx";
|
||||
@ -30,19 +29,16 @@ describe("disable kube object statuses when cluster is not relevant", () => {
|
||||
beforeEach(async () => {
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
const rendererDi = builder.dis.rendererDi;
|
||||
|
||||
rendererDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable);
|
||||
|
||||
rendererDi.register(testRouteInjectable, testRouteComponentInjectable);
|
||||
|
||||
builder.setEnvironmentToClusterFrame();
|
||||
|
||||
const getExtensionFake = getExtensionFakeFor(builder);
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable);
|
||||
windowDi.register(testRouteInjectable, testRouteComponentInjectable);
|
||||
});
|
||||
|
||||
isEnabledForClusterMock = asyncFn();
|
||||
|
||||
const testExtension = getExtensionFake({
|
||||
const testExtension = {
|
||||
id: "test-extension-id",
|
||||
name: "test-extension",
|
||||
|
||||
@ -61,12 +57,14 @@ describe("disable kube object statuses when cluster is not relevant", () => {
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
rendered = await builder.render();
|
||||
|
||||
const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken);
|
||||
const testRoute = rendererDi.inject(testRouteInjectable);
|
||||
const windowDi = builder.applicationWindow.only.di;
|
||||
|
||||
const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken);
|
||||
const testRoute = windowDi.inject(testRouteInjectable);
|
||||
|
||||
navigateToRoute(testRoute);
|
||||
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
import type { RenderResult } from "@testing-library/react";
|
||||
import type { ApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getExtensionFakeFor } from "../../../../renderer/components/test-utils/get-extension-fake";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { frontEndRouteInjectionToken } from "../../../../common/front-end-routing/front-end-route-injection-token";
|
||||
import type { IObservableValue } from "mobx";
|
||||
@ -26,19 +25,16 @@ describe("reactively hide kube object status", () => {
|
||||
beforeEach(async () => {
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
const rendererDi = builder.dis.rendererDi;
|
||||
|
||||
rendererDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable);
|
||||
|
||||
rendererDi.register(testRouteInjectable, testRouteComponentInjectable);
|
||||
|
||||
builder.setEnvironmentToClusterFrame();
|
||||
|
||||
const getExtensionFake = getExtensionFakeFor(builder);
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable);
|
||||
windowDi.register(testRouteInjectable, testRouteComponentInjectable);
|
||||
});
|
||||
|
||||
someObservable = observable.box(false);
|
||||
|
||||
const testExtension = getExtensionFake({
|
||||
const testExtension = {
|
||||
id: "test-extension-id",
|
||||
name: "test-extension",
|
||||
|
||||
@ -57,12 +53,14 @@ describe("reactively hide kube object status", () => {
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
rendered = await builder.render();
|
||||
|
||||
const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken);
|
||||
const testRoute = rendererDi.inject(testRouteInjectable);
|
||||
const windowDi = builder.applicationWindow.only.di;
|
||||
|
||||
const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken);
|
||||
const testRoute = windowDi.inject(testRouteInjectable);
|
||||
|
||||
navigateToRoute(testRoute);
|
||||
|
||||
|
||||
@ -32,8 +32,6 @@ describe("show status for a kube object", () => {
|
||||
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
const rendererDi = builder.dis.rendererDi;
|
||||
|
||||
infoStatusIsShown = false;
|
||||
|
||||
const infoStatusInjectable = getInjectable({
|
||||
@ -95,34 +93,36 @@ describe("show status for a kube object", () => {
|
||||
}),
|
||||
});
|
||||
|
||||
rendererDi.register(
|
||||
testRouteInjectable,
|
||||
testRouteComponentInjectable,
|
||||
infoStatusInjectable,
|
||||
warningStatusInjectable,
|
||||
criticalStatusInjectable,
|
||||
someAtomInjectable,
|
||||
);
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.register(
|
||||
testRouteInjectable,
|
||||
testRouteComponentInjectable,
|
||||
infoStatusInjectable,
|
||||
warningStatusInjectable,
|
||||
criticalStatusInjectable,
|
||||
someAtomInjectable,
|
||||
);
|
||||
});
|
||||
|
||||
builder.setEnvironmentToClusterFrame();
|
||||
});
|
||||
|
||||
describe("given application starts and in test page", () => {
|
||||
let rendererDi: DiContainer;
|
||||
let windowDi: DiContainer;
|
||||
let rendered: RenderResult;
|
||||
let rerenderParent: () => void;
|
||||
|
||||
beforeEach(async () => {
|
||||
rendered = await builder.render();
|
||||
|
||||
rendererDi = builder.dis.rendererDi;
|
||||
windowDi = builder.applicationWindow.only.di;
|
||||
|
||||
const someAtom = rendererDi.inject(someAtomInjectable);
|
||||
const someAtom = windowDi.inject(someAtomInjectable);
|
||||
|
||||
rerenderParent = rerenderParentFor(someAtom);
|
||||
|
||||
const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken);
|
||||
const testRoute = rendererDi.inject(testRouteInjectable);
|
||||
const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken);
|
||||
const testRoute = windowDi.inject(testRouteInjectable);
|
||||
|
||||
navigateToRoute(testRoute);
|
||||
});
|
||||
@ -141,7 +141,7 @@ describe("show status for a kube object", () => {
|
||||
|
||||
describe("when status for irrelevant kube object kind emerges", () => {
|
||||
beforeEach(() => {
|
||||
rendererDi.register(statusForIrrelevantKubeObjectKindInjectable);
|
||||
windowDi.register(statusForIrrelevantKubeObjectKindInjectable);
|
||||
|
||||
rerenderParent();
|
||||
});
|
||||
@ -161,7 +161,7 @@ describe("show status for a kube object", () => {
|
||||
|
||||
describe("when status for irrelevant kube object api version emerges", () => {
|
||||
beforeEach(() => {
|
||||
rendererDi.register(statusForIrrelevantKubeObjectApiVersionInjectable);
|
||||
windowDi.register(statusForIrrelevantKubeObjectApiVersionInjectable);
|
||||
|
||||
rerenderParent();
|
||||
});
|
||||
|
||||
@ -44,34 +44,34 @@ describe("cluster/namespaces - edit namespace from new tab", () => {
|
||||
showSuccessNotificationMock = jest.fn();
|
||||
showErrorNotificationMock = jest.fn();
|
||||
|
||||
builder.beforeApplicationStart(({ rendererDi }) => {
|
||||
rendererDi.override(
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.override(
|
||||
directoryForLensLocalStorageInjectable,
|
||||
() => "/some-directory-for-lens-local-storage",
|
||||
);
|
||||
|
||||
rendererDi.override(hostedClusterIdInjectable, () => "some-cluster-id");
|
||||
windowDi.override(hostedClusterIdInjectable, () => "some-cluster-id");
|
||||
|
||||
storagesAreReady = controlWhenStoragesAreReady(rendererDi);
|
||||
storagesAreReady = controlWhenStoragesAreReady(windowDi);
|
||||
|
||||
rendererDi.override(
|
||||
windowDi.override(
|
||||
showSuccessNotificationInjectable,
|
||||
() => showSuccessNotificationMock,
|
||||
);
|
||||
|
||||
rendererDi.override(
|
||||
windowDi.override(
|
||||
showErrorNotificationInjectable,
|
||||
() => showErrorNotificationMock,
|
||||
);
|
||||
|
||||
rendererDi.override(getRandomIdForEditResourceTabInjectable, () =>
|
||||
windowDi.override(getRandomIdForEditResourceTabInjectable, () =>
|
||||
jest
|
||||
.fn(() => "some-irrelevant-random-id")
|
||||
.mockReturnValueOnce("some-first-tab-id")
|
||||
.mockReturnValueOnce("some-second-tab-id"),
|
||||
);
|
||||
|
||||
rendererDi.override(callForResourceInjectable, () => async (selfLink: string) => {
|
||||
windowDi.override(callForResourceInjectable, () => async (selfLink: string) => {
|
||||
if (
|
||||
[
|
||||
"/apis/some-api-version/namespaces/some-uid",
|
||||
@ -84,7 +84,7 @@ describe("cluster/namespaces - edit namespace from new tab", () => {
|
||||
return undefined;
|
||||
});
|
||||
|
||||
rendererDi.override(callForPatchResourceInjectable, () => async (namespace, ...args) => {
|
||||
windowDi.override(callForPatchResourceInjectable, () => async (namespace, ...args) => {
|
||||
if (
|
||||
[
|
||||
"/apis/some-api-version/namespaces/some-uid",
|
||||
@ -103,22 +103,22 @@ describe("cluster/namespaces - edit namespace from new tab", () => {
|
||||
|
||||
describe("when navigating to namespaces", () => {
|
||||
let rendered: RenderResult;
|
||||
let rendererDi: DiContainer;
|
||||
let windowDi: DiContainer;
|
||||
|
||||
beforeEach(async () => {
|
||||
rendered = await builder.render();
|
||||
|
||||
await storagesAreReady();
|
||||
|
||||
rendererDi = builder.dis.rendererDi;
|
||||
windowDi = builder.applicationWindow.only.di;
|
||||
|
||||
const navigateToNamespaces = rendererDi.inject(
|
||||
const navigateToNamespaces = windowDi.inject(
|
||||
navigateToNamespacesInjectable,
|
||||
);
|
||||
|
||||
navigateToNamespaces();
|
||||
|
||||
const dockStore = rendererDi.inject(dockStoreInjectable);
|
||||
const dockStore = windowDi.inject(dockStoreInjectable);
|
||||
|
||||
// TODO: Make TerminalWindow unit testable to allow realistic behaviour
|
||||
dockStore.closeTab("terminal");
|
||||
@ -168,7 +168,7 @@ describe("cluster/namespaces - edit namespace from new tab", () => {
|
||||
// TODO: Make implementation match the description (tests above)
|
||||
const namespaceStub = new Namespace(someNamespaceDataStub);
|
||||
|
||||
const createEditResourceTab = rendererDi.inject(createEditResourceTabInjectable);
|
||||
const createEditResourceTab = windowDi.inject(createEditResourceTabInjectable);
|
||||
|
||||
createEditResourceTab(namespaceStub);
|
||||
});
|
||||
@ -510,7 +510,7 @@ metadata:
|
||||
});
|
||||
|
||||
it("stores the changed configuration", async () => {
|
||||
const readJsonFile = rendererDi.inject(
|
||||
const readJsonFile = windowDi.inject(
|
||||
readJsonFileInjectable,
|
||||
);
|
||||
|
||||
@ -719,7 +719,7 @@ metadata:
|
||||
// TODO: Make implementation match the description
|
||||
const namespaceStub = new Namespace(someOtherNamespaceDataStub);
|
||||
|
||||
const createEditResourceTab = rendererDi.inject(createEditResourceTabInjectable);
|
||||
const createEditResourceTab = windowDi.inject(createEditResourceTabInjectable);
|
||||
|
||||
createEditResourceTab(namespaceStub);
|
||||
});
|
||||
|
||||
@ -29,17 +29,17 @@ describe("cluster/namespaces - edit namespaces from previously opened tab", () =
|
||||
|
||||
callForNamespaceMock = asyncFn();
|
||||
|
||||
builder.beforeApplicationStart(({ rendererDi }) => {
|
||||
rendererDi.override(
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.override(
|
||||
directoryForLensLocalStorageInjectable,
|
||||
() => "/some-directory-for-lens-local-storage",
|
||||
);
|
||||
|
||||
rendererDi.override(hostedClusterIdInjectable, () => "some-cluster-id");
|
||||
windowDi.override(hostedClusterIdInjectable, () => "some-cluster-id");
|
||||
|
||||
storagesAreReady = controlWhenStoragesAreReady(rendererDi);
|
||||
storagesAreReady = controlWhenStoragesAreReady(windowDi);
|
||||
|
||||
rendererDi.override(callForResourceInjectable, () => callForNamespaceMock);
|
||||
windowDi.override(callForResourceInjectable, () => callForNamespaceMock);
|
||||
});
|
||||
|
||||
builder.allowKubeResource("namespaces");
|
||||
@ -49,33 +49,35 @@ describe("cluster/namespaces - edit namespaces from previously opened tab", () =
|
||||
let rendered: RenderResult;
|
||||
|
||||
beforeEach(async () => {
|
||||
const writeJsonFile = builder.dis.rendererDi.inject(writeJsonFileInjectable);
|
||||
builder.beforeWindowStart(async (windowDi) => {
|
||||
const writeJsonFile = windowDi.inject(writeJsonFileInjectable);
|
||||
|
||||
await writeJsonFile(
|
||||
"/some-directory-for-lens-local-storage/some-cluster-id.json",
|
||||
{
|
||||
dock: {
|
||||
height: 300,
|
||||
tabs: [
|
||||
{
|
||||
id: "some-first-tab-id",
|
||||
kind: TabKind.EDIT_RESOURCE,
|
||||
title: "Namespace: some-namespace",
|
||||
pinned: false,
|
||||
await writeJsonFile(
|
||||
"/some-directory-for-lens-local-storage/some-cluster-id.json",
|
||||
{
|
||||
dock: {
|
||||
height: 300,
|
||||
tabs: [
|
||||
{
|
||||
id: "some-first-tab-id",
|
||||
kind: TabKind.EDIT_RESOURCE,
|
||||
title: "Namespace: some-namespace",
|
||||
pinned: false,
|
||||
},
|
||||
],
|
||||
|
||||
isOpen: true,
|
||||
},
|
||||
|
||||
edit_resource_store: {
|
||||
"some-first-tab-id": {
|
||||
resource: "/apis/some-api-version/namespaces/some-uid",
|
||||
draft: "some-saved-configuration",
|
||||
},
|
||||
],
|
||||
|
||||
isOpen: true,
|
||||
},
|
||||
|
||||
edit_resource_store: {
|
||||
"some-first-tab-id": {
|
||||
resource: "/apis/some-api-version/namespaces/some-uid",
|
||||
draft: "some-saved-configuration",
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
rendered = await builder.render();
|
||||
|
||||
|
||||
@ -14,19 +14,21 @@ import { getApplicationBuilder } from "../../renderer/components/test-utils/get-
|
||||
|
||||
describe("cluster - order of sidebar items", () => {
|
||||
let rendered: RenderResult;
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let builder: ApplicationBuilder;
|
||||
|
||||
beforeEach(() => {
|
||||
applicationBuilder = getApplicationBuilder().setEnvironmentToClusterFrame();
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ rendererDi }) => {
|
||||
rendererDi.register(testSidebarItemsInjectable);
|
||||
builder.setEnvironmentToClusterFrame();
|
||||
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.register(testSidebarItemsInjectable);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when rendered", () => {
|
||||
beforeEach(async () => {
|
||||
rendered = await applicationBuilder.render();
|
||||
rendered = await builder.render();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
|
||||
@ -27,24 +27,21 @@ import { advanceFakeTime, useFakeTime } from "../../common/test-utils/use-fake-t
|
||||
import storageSaveDelayInjectable from "../../renderer/utils/create-storage/storage-save-delay.injectable";
|
||||
|
||||
describe("cluster - sidebar and tab navigation for core", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let rendererDi: DiContainer;
|
||||
let builder: ApplicationBuilder;
|
||||
let rendered: RenderResult;
|
||||
|
||||
beforeEach(() => {
|
||||
useFakeTime("2015-10-21T07:28:00Z");
|
||||
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
rendererDi = applicationBuilder.dis.rendererDi;
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
applicationBuilder.setEnvironmentToClusterFrame();
|
||||
builder.setEnvironmentToClusterFrame();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ rendererDi }) => {
|
||||
rendererDi.override(hostedClusterIdInjectable, () => "some-hosted-cluster-id");
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.override(hostedClusterIdInjectable, () => "some-hosted-cluster-id");
|
||||
windowDi.override(storageSaveDelayInjectable, () => 250);
|
||||
|
||||
rendererDi.override(storageSaveDelayInjectable, () => 250);
|
||||
|
||||
rendererDi.override(
|
||||
windowDi.override(
|
||||
directoryForLensLocalStorageInjectable,
|
||||
() => "/some-directory-for-lens-local-storage",
|
||||
);
|
||||
@ -53,24 +50,23 @@ describe("cluster - sidebar and tab navigation for core", () => {
|
||||
|
||||
describe("given core registrations", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.beforeApplicationStart(({ rendererDi }) => {
|
||||
rendererDi.register(testRouteInjectable);
|
||||
rendererDi.register(testRouteComponentInjectable);
|
||||
rendererDi.register(testSidebarItemsInjectable);
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.register(testRouteInjectable);
|
||||
windowDi.register(testRouteComponentInjectable);
|
||||
windowDi.register(testSidebarItemsInjectable);
|
||||
});
|
||||
});
|
||||
|
||||
describe("given no state for expanded sidebar items exists, and navigated to child sidebar item, when rendered", () => {
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeRender(({ rendererDi }) => {
|
||||
const route = rendererDi.inject(testRouteInjectable);
|
||||
rendered = await builder.render();
|
||||
|
||||
const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken);
|
||||
const windowDi = builder.applicationWindow.only.di;
|
||||
|
||||
navigateToRoute(route);
|
||||
});
|
||||
const route = windowDi.inject(testRouteInjectable);
|
||||
const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken);
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
navigateToRoute(route);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -96,8 +92,8 @@ describe("cluster - sidebar and tab navigation for core", () => {
|
||||
|
||||
describe("given state for expanded sidebar items already exists, when rendered", () => {
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeRender(async ({ rendererDi }) => {
|
||||
const writeJsonFileFake = rendererDi.inject(writeJsonFileInjectable);
|
||||
builder.beforeWindowStart(async (windowDi) => {
|
||||
const writeJsonFileFake = windowDi.inject(writeJsonFileInjectable);
|
||||
|
||||
await writeJsonFileFake(
|
||||
"/some-directory-for-lens-local-storage/some-hosted-cluster-id.json",
|
||||
@ -108,15 +104,13 @@ describe("cluster - sidebar and tab navigation for core", () => {
|
||||
},
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
applicationBuilder.beforeRender(async ({ rendererDi }) => {
|
||||
const sidebarStorage = rendererDi.inject(sidebarStorageInjectable);
|
||||
const sidebarStorage = windowDi.inject(sidebarStorageInjectable);
|
||||
|
||||
await sidebarStorage.whenReady;
|
||||
});
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
rendered = await builder.render();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -138,8 +132,8 @@ describe("cluster - sidebar and tab navigation for core", () => {
|
||||
|
||||
describe("given state for expanded unknown sidebar items already exists, when rendered", () => {
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeRender(async ({ rendererDi }) => {
|
||||
const writeJsonFileFake = rendererDi.inject(writeJsonFileInjectable);
|
||||
builder.beforeWindowStart(async (windowDi) => {
|
||||
const writeJsonFileFake = windowDi.inject(writeJsonFileInjectable);
|
||||
|
||||
await writeJsonFileFake(
|
||||
"/some-directory-for-lens-local-storage/some-hosted-cluster-id.json",
|
||||
@ -152,7 +146,7 @@ describe("cluster - sidebar and tab navigation for core", () => {
|
||||
);
|
||||
});
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
rendered = await builder.render();
|
||||
});
|
||||
|
||||
it("renders without errors", () => {
|
||||
@ -168,8 +162,8 @@ describe("cluster - sidebar and tab navigation for core", () => {
|
||||
|
||||
describe("given empty state for expanded sidebar items already exists, when rendered", () => {
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeRender(async ({ rendererDi }) => {
|
||||
const writeJsonFileFake = rendererDi.inject(writeJsonFileInjectable);
|
||||
builder.beforeWindowStart(async (windowDi) => {
|
||||
const writeJsonFileFake = windowDi.inject(writeJsonFileInjectable);
|
||||
|
||||
await writeJsonFileFake(
|
||||
"/some-directory-for-lens-local-storage/some-hosted-cluster-id.json",
|
||||
@ -179,7 +173,7 @@ describe("cluster - sidebar and tab navigation for core", () => {
|
||||
);
|
||||
});
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
rendered = await builder.render();
|
||||
});
|
||||
|
||||
it("renders without errors", () => {
|
||||
@ -194,8 +188,12 @@ describe("cluster - sidebar and tab navigation for core", () => {
|
||||
});
|
||||
|
||||
describe("given no initially persisted state for sidebar items, when rendered", () => {
|
||||
let windowDi: DiContainer;
|
||||
|
||||
beforeEach(async () => {
|
||||
rendered = await applicationBuilder.render();
|
||||
rendered = await builder.render();
|
||||
|
||||
windowDi = builder.applicationWindow.only.di;
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -271,7 +269,7 @@ describe("cluster - sidebar and tab navigation for core", () => {
|
||||
it("when not enough time passes, does not store state for expanded sidebar items to file system yet", async () => {
|
||||
advanceFakeTime(250 - 1);
|
||||
|
||||
const pathExistsFake = rendererDi.inject(pathExistsInjectable);
|
||||
const pathExistsFake = windowDi.inject(pathExistsInjectable);
|
||||
|
||||
const actual = await pathExistsFake(
|
||||
"/some-directory-for-lens-local-storage/some-hosted-cluster-id.json",
|
||||
@ -283,7 +281,7 @@ describe("cluster - sidebar and tab navigation for core", () => {
|
||||
it("when enough time passes, stores state for expanded sidebar items to file system", async () => {
|
||||
advanceFakeTime(250);
|
||||
|
||||
const readJsonFileFake = rendererDi.inject(readJsonFileInjectable);
|
||||
const readJsonFileFake = windowDi.inject(readJsonFileInjectable);
|
||||
|
||||
const actual = await readJsonFileFake(
|
||||
"/some-directory-for-lens-local-storage/some-hosted-cluster-id.json",
|
||||
|
||||
@ -13,35 +13,31 @@ import { getApplicationBuilder } from "../../renderer/components/test-utils/get-
|
||||
import writeJsonFileInjectable from "../../common/fs/write-json-file.injectable";
|
||||
import pathExistsInjectable from "../../common/fs/path-exists.injectable";
|
||||
import readJsonFileInjectable from "../../common/fs/read-json-file.injectable";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import { navigateToRouteInjectionToken } from "../../common/front-end-routing/navigate-to-route-injection-token";
|
||||
import assert from "assert";
|
||||
import hostedClusterIdInjectable from "../../renderer/cluster-frame-context/hosted-cluster-id.injectable";
|
||||
import { advanceFakeTime, useFakeTime } from "../../common/test-utils/use-fake-time";
|
||||
import { getExtensionFakeFor } from "../../renderer/components/test-utils/get-extension-fake";
|
||||
import type { IObservableValue } from "mobx";
|
||||
import { runInAction, computed, observable } from "mobx";
|
||||
import storageSaveDelayInjectable from "../../renderer/utils/create-storage/storage-save-delay.injectable";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
|
||||
describe("cluster - sidebar and tab navigation for extensions", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let rendererDi: DiContainer;
|
||||
let rendered: RenderResult;
|
||||
|
||||
beforeEach(() => {
|
||||
useFakeTime("2015-10-21T07:28:00Z");
|
||||
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
rendererDi = applicationBuilder.dis.rendererDi;
|
||||
|
||||
applicationBuilder.setEnvironmentToClusterFrame();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ rendererDi }) => {
|
||||
rendererDi.override(hostedClusterIdInjectable, () => "some-hosted-cluster-id");
|
||||
applicationBuilder.beforeWindowStart((windowDi) => {
|
||||
windowDi.override(hostedClusterIdInjectable, () => "some-hosted-cluster-id");
|
||||
windowDi.override(storageSaveDelayInjectable, () => 250);
|
||||
|
||||
rendererDi.override(storageSaveDelayInjectable, () => 250);
|
||||
|
||||
rendererDi.override(
|
||||
windowDi.override(
|
||||
directoryForLensLocalStorageInjectable,
|
||||
() => "/some-directory-for-lens-local-storage",
|
||||
);
|
||||
@ -54,9 +50,7 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
|
||||
beforeEach(() => {
|
||||
someObservable = observable.box(false);
|
||||
|
||||
const getExtensionFake = getExtensionFakeFor(applicationBuilder);
|
||||
|
||||
const testExtension = getExtensionFake({
|
||||
const testExtension = {
|
||||
id: "some-extension-id",
|
||||
name: "some-extension-name",
|
||||
|
||||
@ -130,29 +124,31 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
applicationBuilder.extensions.enable(testExtension);
|
||||
});
|
||||
|
||||
describe("given no state for expanded sidebar items exists, and navigated to child sidebar item, when rendered", () => {
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeRender(({ rendererDi }) => {
|
||||
const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken);
|
||||
const route = rendererDi
|
||||
.inject(routesInjectable)
|
||||
.get()
|
||||
.find(
|
||||
matches({
|
||||
path: "/extension/some-extension-name/some-child-page-id",
|
||||
}),
|
||||
);
|
||||
|
||||
assert(route);
|
||||
navigateToRoute(route);
|
||||
});
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
|
||||
const windowDi = applicationBuilder.applicationWindow.only.di;
|
||||
|
||||
const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken);
|
||||
|
||||
const route = windowDi
|
||||
.inject(routesInjectable)
|
||||
.get()
|
||||
.find(
|
||||
matches({
|
||||
path: "/extension/some-extension-name/some-child-page-id",
|
||||
}),
|
||||
);
|
||||
|
||||
assert(route);
|
||||
navigateToRoute(route);
|
||||
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -178,8 +174,8 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
|
||||
|
||||
describe("given state for expanded sidebar items already exists, when rendered", () => {
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeRender(async ({ rendererDi }) => {
|
||||
const writeJsonFileFake = rendererDi.inject(writeJsonFileInjectable);
|
||||
applicationBuilder.beforeWindowStart(async (windowDi) => {
|
||||
const writeJsonFileFake = windowDi.inject(writeJsonFileInjectable);
|
||||
|
||||
await writeJsonFileFake(
|
||||
"/some-directory-for-lens-local-storage/some-hosted-cluster-id.json",
|
||||
@ -214,8 +210,8 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
|
||||
|
||||
describe("given state for expanded unknown sidebar items already exists, when rendered", () => {
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeRender(async ({ rendererDi }) => {
|
||||
const writeJsonFileFake = rendererDi.inject(writeJsonFileInjectable);
|
||||
applicationBuilder.beforeWindowStart(async (windowDi) => {
|
||||
const writeJsonFileFake = windowDi.inject(writeJsonFileInjectable);
|
||||
|
||||
await writeJsonFileFake(
|
||||
"/some-directory-for-lens-local-storage/some-hosted-cluster-id.json",
|
||||
@ -244,8 +240,8 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
|
||||
|
||||
describe("given empty state for expanded sidebar items already exists, when rendered", () => {
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeRender(async ({ rendererDi }) => {
|
||||
const writeJsonFileFake = rendererDi.inject(writeJsonFileInjectable);
|
||||
applicationBuilder.beforeWindowStart(async (windowDi) => {
|
||||
const writeJsonFileFake = windowDi.inject(writeJsonFileInjectable);
|
||||
|
||||
await writeJsonFileFake(
|
||||
"/some-directory-for-lens-local-storage/some-hosted-cluster-id.json",
|
||||
@ -270,8 +266,12 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
|
||||
});
|
||||
|
||||
describe("given no initially persisted state for sidebar items, when rendered", () => {
|
||||
let windowDi: DiContainer;
|
||||
|
||||
beforeEach(async () => {
|
||||
rendered = await applicationBuilder.render();
|
||||
|
||||
windowDi = applicationBuilder.applicationWindow.only.di;
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -387,7 +387,7 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
|
||||
it("when not enough time passes, does not store state for expanded sidebar items to file system yet", async () => {
|
||||
advanceFakeTime(250 - 1);
|
||||
|
||||
const pathExistsFake = rendererDi.inject(pathExistsInjectable);
|
||||
const pathExistsFake = windowDi.inject(pathExistsInjectable);
|
||||
|
||||
const actual = await pathExistsFake(
|
||||
"/some-directory-for-lens-local-storage/some-hosted-cluster-id.json",
|
||||
@ -399,7 +399,7 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
|
||||
it("when enough time passes, stores state for expanded sidebar items to file system", async () => {
|
||||
advanceFakeTime(250);
|
||||
|
||||
const readJsonFileFake = rendererDi.inject(readJsonFileInjectable);
|
||||
const readJsonFileFake = windowDi.inject(readJsonFileInjectable);
|
||||
|
||||
const actual = await readJsonFileFake(
|
||||
"/some-directory-for-lens-local-storage/some-hosted-cluster-id.json",
|
||||
|
||||
@ -16,24 +16,24 @@ import { getApplicationBuilder } from "../../renderer/components/test-utils/get-
|
||||
import { navigateToRouteInjectionToken } from "../../common/front-end-routing/navigate-to-route-injection-token";
|
||||
|
||||
describe("cluster - visibility of sidebar items", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let builder: ApplicationBuilder;
|
||||
let rendered: RenderResult;
|
||||
|
||||
beforeEach(() => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
applicationBuilder.setEnvironmentToClusterFrame();
|
||||
builder.setEnvironmentToClusterFrame();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ rendererDi }) => {
|
||||
rendererDi.register(testRouteInjectable);
|
||||
rendererDi.register(testRouteComponentInjectable);
|
||||
rendererDi.register(testSidebarItemsInjectable);
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.register(testRouteInjectable);
|
||||
windowDi.register(testRouteComponentInjectable);
|
||||
windowDi.register(testSidebarItemsInjectable);
|
||||
});
|
||||
});
|
||||
|
||||
describe("given kube resource for route is not allowed", () => {
|
||||
beforeEach(async () => {
|
||||
rendered = await applicationBuilder.render();
|
||||
rendered = await builder.render();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -48,7 +48,7 @@ describe("cluster - visibility of sidebar items", () => {
|
||||
|
||||
describe("when kube resource becomes allowed", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.allowKubeResource("namespaces");
|
||||
builder.allowKubeResource("namespaces");
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
|
||||
@ -8,7 +8,6 @@ import type { RenderResult } from "@testing-library/react";
|
||||
import type { ApplicationBuilder } from "../../../../../renderer/components/test-utils/get-application-builder";
|
||||
import type { KubernetesCluster } from "../../../../../common/catalog-entities";
|
||||
import { getApplicationBuilder } from "../../../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getExtensionFakeFor } from "../../../../../renderer/components/test-utils/get-extension-fake";
|
||||
import extensionShouldBeEnabledForClusterFrameInjectable from "../../../../../renderer/extension-loader/extension-should-be-enabled-for-cluster-frame.injectable";
|
||||
import apiManagerInjectable from "../../../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import navigateToWorkloadsOverviewInjectable from "../../../../../common/front-end-routing/routes/cluster/workloads/overview/navigate-to-workloads-overview.injectable";
|
||||
@ -24,21 +23,19 @@ describe("disable workloads overview details when cluster is not relevant", () =
|
||||
beforeEach(async () => {
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
builder.beforeApplicationStart(({ mainDi }) => {
|
||||
builder.setEnvironmentToClusterFrame();
|
||||
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
mainDi.override(apiManagerInjectable, () => ({}));
|
||||
});
|
||||
|
||||
const rendererDi = builder.dis.rendererDi;
|
||||
|
||||
rendererDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable);
|
||||
|
||||
builder.setEnvironmentToClusterFrame();
|
||||
|
||||
const getExtensionFake = getExtensionFakeFor(builder);
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable);
|
||||
});
|
||||
|
||||
isEnabledForClusterMock = asyncFn();
|
||||
|
||||
const testExtension = getExtensionFake({
|
||||
const testExtension = {
|
||||
id: "test-extension-id",
|
||||
name: "test-extension",
|
||||
|
||||
@ -55,11 +52,13 @@ describe("disable workloads overview details when cluster is not relevant", () =
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
rendered = await builder.render();
|
||||
|
||||
const navigateToWorkloadsOverview = rendererDi.inject(
|
||||
const windowDi = builder.applicationWindow.only.di;
|
||||
|
||||
const navigateToWorkloadsOverview = windowDi.inject(
|
||||
navigateToWorkloadsOverviewInjectable,
|
||||
);
|
||||
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
*/
|
||||
import type { RenderResult } from "@testing-library/react";
|
||||
import { getApplicationBuilder } from "../../../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getExtensionFakeFor } from "../../../../../renderer/components/test-utils/get-extension-fake";
|
||||
import React from "react";
|
||||
import getRandomIdInjectable from "../../../../../common/utils/get-random-id.injectable";
|
||||
import { workloadOverviewDetailInjectionToken } from "../../../../../renderer/components/+workloads-overview/workload-overview-details/workload-overview-detail-injection-token";
|
||||
@ -17,16 +16,22 @@ describe("order of workload overview details", () => {
|
||||
beforeEach(async () => {
|
||||
const builder = getApplicationBuilder();
|
||||
|
||||
builder.beforeApplicationStart(({ rendererDi }) => {
|
||||
rendererDi.unoverride(getRandomIdInjectable);
|
||||
rendererDi.permitSideEffects(getRandomIdInjectable);
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.unoverride(getRandomIdInjectable);
|
||||
windowDi.permitSideEffects(getRandomIdInjectable);
|
||||
|
||||
windowDi.register(
|
||||
someCoreItemWithLowOrderNumberInjectable,
|
||||
someCoreItemWithHighOrderNumberInjectable,
|
||||
someCoreItemWithDefaultOrderNumberInjectable,
|
||||
);
|
||||
});
|
||||
|
||||
builder.setEnvironmentToClusterFrame();
|
||||
|
||||
rendered = await builder.render();
|
||||
|
||||
const testExtension = getExtensionFakeFor(builder)({
|
||||
const testExtension = {
|
||||
id: "some-extension-id",
|
||||
name: "some-extension",
|
||||
|
||||
@ -66,16 +71,9 @@ describe("order of workload overview details", () => {
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
builder.extensions.enable(testExtension);
|
||||
|
||||
|
||||
builder.dis.rendererDi.register(
|
||||
someCoreItemWithLowOrderNumberInjectable,
|
||||
someCoreItemWithHighOrderNumberInjectable,
|
||||
someCoreItemWithDefaultOrderNumberInjectable,
|
||||
);
|
||||
});
|
||||
|
||||
it("shows items in correct order", () => {
|
||||
|
||||
@ -9,7 +9,6 @@ import React from "react";
|
||||
import navigateToWorkloadsOverviewInjectable from "../../../../../common/front-end-routing/routes/cluster/workloads/overview/navigate-to-workloads-overview.injectable";
|
||||
import type { ApplicationBuilder } from "../../../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getExtensionFakeFor } from "../../../../../renderer/components/test-utils/get-extension-fake";
|
||||
|
||||
describe("reactively hide workloads overview details item", () => {
|
||||
let builder: ApplicationBuilder;
|
||||
@ -19,15 +18,11 @@ describe("reactively hide workloads overview details item", () => {
|
||||
beforeEach(async () => {
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
const rendererDi = builder.dis.rendererDi;
|
||||
|
||||
builder.setEnvironmentToClusterFrame();
|
||||
|
||||
const getExtensionFake = getExtensionFakeFor(builder);
|
||||
|
||||
someObservable = observable.box(false);
|
||||
|
||||
const testExtension = getExtensionFake({
|
||||
const testExtension = {
|
||||
id: "test-extension-id",
|
||||
name: "test-extension",
|
||||
|
||||
@ -44,11 +39,13 @@ describe("reactively hide workloads overview details item", () => {
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
rendered = await builder.render();
|
||||
|
||||
const navigateToWorkloadsOverview = rendererDi.inject(
|
||||
const windowDi = builder.applicationWindow.only.di;
|
||||
|
||||
const navigateToWorkloadsOverview = windowDi.inject(
|
||||
navigateToWorkloadsOverviewInjectable,
|
||||
);
|
||||
|
||||
|
||||
@ -9,17 +9,20 @@ import platformInjectable from "../../common/vars/platform.injectable";
|
||||
import { type ApplicationBuilder, getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
|
||||
describe("Command Pallet: keyboard shortcut tests", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let builder: ApplicationBuilder;
|
||||
let rendered: RenderResult;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
builder = getApplicationBuilder();
|
||||
});
|
||||
|
||||
describe("when on macOS", () => {
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.dis.rendererDi.override(platformInjectable, () => "darwin");
|
||||
rendered = await applicationBuilder.render();
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.override(platformInjectable, () => "darwin");
|
||||
});
|
||||
|
||||
rendered = await builder.render();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -83,8 +86,11 @@ describe("Command Pallet: keyboard shortcut tests", () => {
|
||||
|
||||
describe("when on linux", () => {
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.dis.rendererDi.override(platformInjectable, () => "linux");
|
||||
rendered = await applicationBuilder.render();
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.override(platformInjectable, () => "linux");
|
||||
});
|
||||
|
||||
rendered = await builder.render();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
|
||||
@ -2,30 +2,27 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { FakeExtensionData, TestExtension } from "../renderer/components/test-utils/get-renderer-extension-fake";
|
||||
import { getRendererExtensionFakeFor } from "../renderer/components/test-utils/get-renderer-extension-fake";
|
||||
import React from "react";
|
||||
import type { RenderResult } from "@testing-library/react";
|
||||
import currentPathInjectable from "../renderer/routes/current-path.injectable";
|
||||
import type { ApplicationBuilder } from "../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../renderer/components/test-utils/get-application-builder";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import type { FakeExtensionOptions } from "../renderer/components/test-utils/get-extension-fake";
|
||||
|
||||
describe("extension special characters in page registrations", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let builder: ApplicationBuilder;
|
||||
let rendered: RenderResult;
|
||||
let testExtension: TestExtension;
|
||||
let windowDi: DiContainer;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
const getRendererExtensionFake = getRendererExtensionFakeFor(applicationBuilder);
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
testExtension = getRendererExtensionFake(
|
||||
extensionWithPagesHavingSpecialCharacters,
|
||||
);
|
||||
rendered = await builder.render();
|
||||
|
||||
applicationBuilder.extensions.renderer.enable(testExtension);
|
||||
builder.extensions.enable(extensionWithPagesHavingSpecialCharacters);
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
windowDi = builder.applicationWindow.only.di;
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -34,6 +31,9 @@ describe("extension special characters in page registrations", () => {
|
||||
|
||||
describe("when navigating to route with ID having special characters", () => {
|
||||
beforeEach(() => {
|
||||
const testExtension =
|
||||
builder.extensions.get("some-extension-id").applicationWindows.only;
|
||||
|
||||
testExtension.navigate("/some-page-id/");
|
||||
});
|
||||
|
||||
@ -42,22 +42,25 @@ describe("extension special characters in page registrations", () => {
|
||||
});
|
||||
|
||||
it("knows URL", () => {
|
||||
const currentPath = applicationBuilder.dis.rendererDi.inject(currentPathInjectable);
|
||||
const currentPath = windowDi.inject(currentPathInjectable);
|
||||
|
||||
expect(currentPath.get()).toBe("/extension/some-extension-name--/some-page-id");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const extensionWithPagesHavingSpecialCharacters: FakeExtensionData = {
|
||||
const extensionWithPagesHavingSpecialCharacters: FakeExtensionOptions = {
|
||||
id: "some-extension-id",
|
||||
name: "@some-extension-name/",
|
||||
globalPages: [
|
||||
{
|
||||
id: "/some-page-id/",
|
||||
components: {
|
||||
Page: () => <div>Some page</div>,
|
||||
|
||||
rendererOptions: {
|
||||
globalPages: [
|
||||
{
|
||||
id: "/some-page-id/",
|
||||
components: {
|
||||
Page: () => <div>Some page</div>,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
@ -12,18 +12,20 @@ import focusWindowInjectable from "../../renderer/navigation/focus-window.inject
|
||||
jest.mock("../../renderer/components/input/input");
|
||||
|
||||
describe("extensions - navigation using application menu", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let builder: ApplicationBuilder;
|
||||
let rendered: RenderResult;
|
||||
let focusWindowMock: jest.Mock;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder = getApplicationBuilder().beforeApplicationStart(({ rendererDi }) => {
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
focusWindowMock = jest.fn();
|
||||
|
||||
rendererDi.override(focusWindowInjectable, () => focusWindowMock);
|
||||
windowDi.override(focusWindowInjectable, () => focusWindowMock);
|
||||
});
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
rendered = await builder.render();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -38,7 +40,7 @@ describe("extensions - navigation using application menu", () => {
|
||||
|
||||
describe("when navigating to extensions using application menu", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.applicationMenu.click("root.extensions");
|
||||
builder.applicationMenu.click("root.extensions");
|
||||
});
|
||||
|
||||
it("focuses the window", () => {
|
||||
|
||||
@ -19,7 +19,7 @@ import showErrorNotificationInjectable from "../../renderer/components/notificat
|
||||
import type { AsyncResult } from "../../common/utils/async-result";
|
||||
|
||||
describe("add custom helm repository in preferences", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let builder: ApplicationBuilder;
|
||||
let showSuccessNotificationMock: jest.Mock;
|
||||
let showErrorNotificationMock: jest.Mock;
|
||||
let rendered: RenderResult;
|
||||
@ -31,41 +31,35 @@ describe("add custom helm repository in preferences", () => {
|
||||
beforeEach(async () => {
|
||||
jest.useFakeTimers();
|
||||
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
execFileMock = asyncFn();
|
||||
getActiveHelmRepositoriesMock = asyncFn();
|
||||
showSuccessNotificationMock = jest.fn();
|
||||
showErrorNotificationMock = jest.fn();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi, rendererDi }) => {
|
||||
rendererDi.override(callForPublicHelmRepositoriesInjectable, () => async () => []);
|
||||
|
||||
showSuccessNotificationMock = jest.fn();
|
||||
|
||||
rendererDi.override(showSuccessNotificationInjectable, () => showSuccessNotificationMock);
|
||||
|
||||
showErrorNotificationMock = jest.fn();
|
||||
|
||||
rendererDi.override(showErrorNotificationInjectable, () => showErrorNotificationMock);
|
||||
|
||||
// TODO: Figure out how to make async validators unit testable
|
||||
rendererDi.override(isPathInjectable, () => ({ debounce: 0, validate: async () => {} }));
|
||||
|
||||
mainDi.override(
|
||||
getActiveHelmRepositoriesInjectable,
|
||||
() => getActiveHelmRepositoriesMock,
|
||||
);
|
||||
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
mainDi.override(getActiveHelmRepositoriesInjectable, () => getActiveHelmRepositoriesMock);
|
||||
mainDi.override(execFileInjectable, () => execFileMock);
|
||||
mainDi.override(helmBinaryPathInjectable, () => "some-helm-binary-path");
|
||||
});
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.override(callForPublicHelmRepositoriesInjectable, () => async () => []);
|
||||
windowDi.override(showSuccessNotificationInjectable, () => showSuccessNotificationMock);
|
||||
windowDi.override(showErrorNotificationInjectable, () => showErrorNotificationMock);
|
||||
|
||||
// TODO: Figure out how to make async validators unit testable
|
||||
windowDi.override(isPathInjectable, () => ({ debounce: 0, validate: async () => {} }));
|
||||
});
|
||||
|
||||
rendered = await builder.render();
|
||||
});
|
||||
|
||||
describe("when navigating to preferences containing helm repositories", () => {
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.preferences.navigate();
|
||||
applicationBuilder.preferences.navigation.click("kubernetes");
|
||||
builder.preferences.navigate();
|
||||
builder.preferences.navigation.click("kubernetes");
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
|
||||
@ -17,7 +17,7 @@ import showErrorNotificationInjectable from "../../renderer/components/notificat
|
||||
import type { AsyncResult } from "../../common/utils/async-result";
|
||||
|
||||
describe("add helm repository from list in preferences", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let builder: ApplicationBuilder;
|
||||
let showSuccessNotificationMock: jest.Mock;
|
||||
let showErrorNotificationMock: jest.Mock;
|
||||
let rendered: RenderResult;
|
||||
@ -28,41 +28,33 @@ describe("add helm repository from list in preferences", () => {
|
||||
let callForPublicHelmRepositoriesMock: AsyncFnMock<() => Promise<HelmRepo[]>>;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
execFileMock = asyncFn();
|
||||
getActiveHelmRepositoriesMock = asyncFn();
|
||||
callForPublicHelmRepositoriesMock = asyncFn();
|
||||
showSuccessNotificationMock = jest.fn();
|
||||
showErrorNotificationMock = jest.fn();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi, rendererDi }) => {
|
||||
showSuccessNotificationMock = jest.fn();
|
||||
|
||||
rendererDi.override(showSuccessNotificationInjectable, () => showSuccessNotificationMock);
|
||||
|
||||
showErrorNotificationMock = jest.fn();
|
||||
|
||||
rendererDi.override(showErrorNotificationInjectable, () => showErrorNotificationMock);
|
||||
|
||||
rendererDi.override(
|
||||
callForPublicHelmRepositoriesInjectable,
|
||||
() => callForPublicHelmRepositoriesMock,
|
||||
);
|
||||
|
||||
mainDi.override(
|
||||
getActiveHelmRepositoriesInjectable,
|
||||
() => getActiveHelmRepositoriesMock,
|
||||
);
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
mainDi.override(getActiveHelmRepositoriesInjectable, () => getActiveHelmRepositoriesMock);
|
||||
mainDi.override(execFileInjectable, () => execFileMock);
|
||||
mainDi.override(helmBinaryPathInjectable, () => "some-helm-binary-path");
|
||||
});
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.override(showSuccessNotificationInjectable, () => showSuccessNotificationMock);
|
||||
windowDi.override(showErrorNotificationInjectable, () => showErrorNotificationMock);
|
||||
windowDi.override(callForPublicHelmRepositoriesInjectable, () => callForPublicHelmRepositoriesMock);
|
||||
});
|
||||
|
||||
rendered = await builder.render();
|
||||
});
|
||||
|
||||
describe("when navigating to preferences containing helm repositories", () => {
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.preferences.navigate();
|
||||
applicationBuilder.preferences.navigation.click("kubernetes");
|
||||
beforeEach(() => {
|
||||
builder.preferences.navigate();
|
||||
builder.preferences.navigation.click("kubernetes");
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -100,7 +92,7 @@ describe("add helm repository from list in preferences", () => {
|
||||
|
||||
describe("when select for adding public repositories is clicked", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.select.openMenu(
|
||||
builder.select.openMenu(
|
||||
"selection-of-active-public-helm-repository",
|
||||
);
|
||||
});
|
||||
@ -113,7 +105,7 @@ describe("add helm repository from list in preferences", () => {
|
||||
beforeEach(async () => {
|
||||
getActiveHelmRepositoriesMock.mockClear();
|
||||
|
||||
applicationBuilder.select.selectOption(
|
||||
builder.select.selectOption(
|
||||
"selection-of-active-public-helm-repository",
|
||||
"Some to be added repository",
|
||||
);
|
||||
@ -207,7 +199,7 @@ describe("add helm repository from list in preferences", () => {
|
||||
|
||||
describe("when select for selecting active repositories is clicked", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.select.openMenu(
|
||||
builder.select.openMenu(
|
||||
"selection-of-active-public-helm-repository",
|
||||
);
|
||||
});
|
||||
@ -221,7 +213,7 @@ describe("add helm repository from list in preferences", () => {
|
||||
execFileMock.mockClear();
|
||||
getActiveHelmRepositoriesMock.mockClear();
|
||||
|
||||
applicationBuilder.select.selectOption(
|
||||
builder.select.selectOption(
|
||||
"selection-of-active-public-helm-repository",
|
||||
"Some already active repository",
|
||||
);
|
||||
|
||||
@ -1,6 +1,448 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started, when navigating to helm charts renders 1`] = `
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started renders 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div
|
||||
class="Notifications flex column align-flex-end"
|
||||
/>
|
||||
<div
|
||||
class="mainLayout"
|
||||
style="--sidebar-width: 200px;"
|
||||
>
|
||||
<div
|
||||
class="sidebar"
|
||||
>
|
||||
<div
|
||||
class="flex flex-col"
|
||||
data-testid="cluster-sidebar"
|
||||
>
|
||||
<div
|
||||
class="SidebarCluster"
|
||||
>
|
||||
<div
|
||||
class="Avatar rounded loadingAvatar"
|
||||
style="width: 40px; height: 40px;"
|
||||
>
|
||||
??
|
||||
</div>
|
||||
<div
|
||||
class="loadingClusterName"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="sidebarNav sidebar-active-status"
|
||||
>
|
||||
<div
|
||||
class="SidebarItem"
|
||||
data-is-active-test="true"
|
||||
data-testid="sidebar-item-workloads"
|
||||
>
|
||||
<a
|
||||
aria-current="page"
|
||||
class="nav-item flex gaps align-center expandable active"
|
||||
data-testid="sidebar-item-link-for-workloads"
|
||||
href="/"
|
||||
>
|
||||
<i
|
||||
class="Icon svg focusable"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
/>
|
||||
</i>
|
||||
<span
|
||||
class="link-text box grow"
|
||||
>
|
||||
Workloads
|
||||
</span>
|
||||
<i
|
||||
class="Icon expand-icon box right material focusable"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="keyboard_arrow_down"
|
||||
>
|
||||
keyboard_arrow_down
|
||||
</span>
|
||||
</i>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
class="SidebarItem"
|
||||
data-is-active-test="false"
|
||||
data-testid="sidebar-item-config"
|
||||
>
|
||||
<a
|
||||
class="nav-item flex gaps align-center"
|
||||
data-testid="sidebar-item-link-for-config"
|
||||
href="/"
|
||||
>
|
||||
<i
|
||||
class="Icon material focusable"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="list"
|
||||
>
|
||||
list
|
||||
</span>
|
||||
</i>
|
||||
<span
|
||||
class="link-text box grow"
|
||||
>
|
||||
Config
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
class="SidebarItem"
|
||||
data-is-active-test="false"
|
||||
data-testid="sidebar-item-network"
|
||||
>
|
||||
<a
|
||||
class="nav-item flex gaps align-center expandable"
|
||||
data-testid="sidebar-item-link-for-network"
|
||||
href="/"
|
||||
>
|
||||
<i
|
||||
class="Icon material focusable"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="device_hub"
|
||||
>
|
||||
device_hub
|
||||
</span>
|
||||
</i>
|
||||
<span
|
||||
class="link-text box grow"
|
||||
>
|
||||
Network
|
||||
</span>
|
||||
<i
|
||||
class="Icon expand-icon box right material focusable"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="keyboard_arrow_down"
|
||||
>
|
||||
keyboard_arrow_down
|
||||
</span>
|
||||
</i>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
class="SidebarItem"
|
||||
data-is-active-test="false"
|
||||
data-testid="sidebar-item-storage"
|
||||
>
|
||||
<a
|
||||
class="nav-item flex gaps align-center"
|
||||
data-testid="sidebar-item-link-for-storage"
|
||||
href="/"
|
||||
>
|
||||
<i
|
||||
class="Icon material focusable"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="storage"
|
||||
>
|
||||
storage
|
||||
</span>
|
||||
</i>
|
||||
<span
|
||||
class="link-text box grow"
|
||||
>
|
||||
Storage
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
class="SidebarItem"
|
||||
data-is-active-test="false"
|
||||
data-testid="sidebar-item-helm"
|
||||
>
|
||||
<a
|
||||
class="nav-item flex gaps align-center expandable"
|
||||
data-testid="sidebar-item-link-for-helm"
|
||||
href="/"
|
||||
>
|
||||
<i
|
||||
class="Icon svg focusable"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
/>
|
||||
</i>
|
||||
<span
|
||||
class="link-text box grow"
|
||||
>
|
||||
Helm
|
||||
</span>
|
||||
<i
|
||||
class="Icon expand-icon box right material focusable"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="keyboard_arrow_down"
|
||||
>
|
||||
keyboard_arrow_down
|
||||
</span>
|
||||
</i>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
class="SidebarItem"
|
||||
data-is-active-test="false"
|
||||
data-testid="sidebar-item-user-management"
|
||||
>
|
||||
<a
|
||||
class="nav-item flex gaps align-center"
|
||||
data-testid="sidebar-item-link-for-user-management"
|
||||
href="/"
|
||||
>
|
||||
<i
|
||||
class="Icon material focusable"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="security"
|
||||
>
|
||||
security
|
||||
</span>
|
||||
</i>
|
||||
<span
|
||||
class="link-text box grow"
|
||||
>
|
||||
Access Control
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
class="SidebarItem"
|
||||
data-is-active-test="false"
|
||||
data-testid="sidebar-item-custom-resources"
|
||||
>
|
||||
<a
|
||||
class="nav-item flex gaps align-center expandable"
|
||||
data-testid="sidebar-item-link-for-custom-resources"
|
||||
href="/"
|
||||
>
|
||||
<i
|
||||
class="Icon material focusable"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="extension"
|
||||
>
|
||||
extension
|
||||
</span>
|
||||
</i>
|
||||
<span
|
||||
class="link-text box grow"
|
||||
>
|
||||
Custom Resources
|
||||
</span>
|
||||
<i
|
||||
class="Icon expand-icon box right material focusable"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="keyboard_arrow_down"
|
||||
>
|
||||
keyboard_arrow_down
|
||||
</span>
|
||||
</i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ResizingAnchor horizontal trailing"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="contents"
|
||||
>
|
||||
<div
|
||||
class="TabLayout"
|
||||
data-testid="tab-layout"
|
||||
>
|
||||
<div
|
||||
class="Tabs center scrollable"
|
||||
>
|
||||
<div
|
||||
class="Tab flex gaps align-center active"
|
||||
data-is-active-test="true"
|
||||
data-testid="tab-link-for-overview"
|
||||
role="tab"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="label"
|
||||
>
|
||||
Overview
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<main>
|
||||
<div
|
||||
class="WorkloadsOverview flex column gaps"
|
||||
>
|
||||
<div
|
||||
class="header flex gaps align-center"
|
||||
>
|
||||
<h5
|
||||
class="box grow"
|
||||
>
|
||||
Overview
|
||||
</h5>
|
||||
<div
|
||||
class="NamespaceSelectFilterParent"
|
||||
data-testid="namespace-select-filter"
|
||||
>
|
||||
<div
|
||||
class="Select theme-dark NamespaceSelect NamespaceSelectFilter css-b62m3t-container"
|
||||
>
|
||||
<span
|
||||
class="css-1f43avz-a11yText-A11yText"
|
||||
id="react-select-overview-namespace-select-filter-input-live-region"
|
||||
/>
|
||||
<span
|
||||
aria-atomic="false"
|
||||
aria-live="polite"
|
||||
aria-relevant="additions text"
|
||||
class="css-1f43avz-a11yText-A11yText"
|
||||
/>
|
||||
<div
|
||||
class="Select__control css-1s2u09g-control"
|
||||
>
|
||||
<div
|
||||
class="Select__value-container Select__value-container--is-multi css-319lph-ValueContainer"
|
||||
>
|
||||
<div
|
||||
class="Select__placeholder css-14el2xx-placeholder"
|
||||
id="react-select-overview-namespace-select-filter-input-placeholder"
|
||||
>
|
||||
All namespaces
|
||||
</div>
|
||||
<div
|
||||
class="Select__input-container css-6j8wv5-Input"
|
||||
data-value=""
|
||||
>
|
||||
<input
|
||||
aria-autocomplete="list"
|
||||
aria-describedby="react-select-overview-namespace-select-filter-input-placeholder"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
autocapitalize="none"
|
||||
autocomplete="off"
|
||||
autocorrect="off"
|
||||
class="Select__input"
|
||||
id="overview-namespace-select-filter-input"
|
||||
role="combobox"
|
||||
spellcheck="false"
|
||||
style="opacity: 1; width: 100%; grid-area: 1 / 2; min-width: 2px; border: 0px; margin: 0px; outline: 0; padding: 0px;"
|
||||
tabindex="0"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="Select__indicators css-1hb7zxy-IndicatorsContainer"
|
||||
>
|
||||
<span
|
||||
class="Select__indicator-separator css-1okebmr-indicatorSeparator"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="css-tj5bde-Svg"
|
||||
focusable="false"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
width="20"
|
||||
>
|
||||
<path
|
||||
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="OverviewStatuses"
|
||||
>
|
||||
<div
|
||||
class="workloads"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="footer"
|
||||
>
|
||||
<div
|
||||
class="Dock"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="ResizingAnchor vertical leading disabled"
|
||||
/>
|
||||
<div
|
||||
class="tabs-container flex align-center"
|
||||
>
|
||||
<div
|
||||
class="dockTabs"
|
||||
role="tablist"
|
||||
>
|
||||
<div
|
||||
class="Tabs tabs"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="toolbar flex gaps align-center box grow pl-0"
|
||||
>
|
||||
<div
|
||||
class="dock-menu box grow"
|
||||
>
|
||||
<i
|
||||
class="Icon new-dock-tab material interactive focusable"
|
||||
id="menu-actions-for-dock"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
class="icon"
|
||||
data-icon-name="add"
|
||||
>
|
||||
add
|
||||
</span>
|
||||
</i>
|
||||
<div>
|
||||
New tab
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started when navigating to helm charts renders 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div
|
||||
@ -927,7 +1369,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started, when navigating to helm charts when selecting to install the chart renders 1`] = `
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started when navigating to helm charts when selecting to install the chart renders 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div
|
||||
@ -1696,7 +2138,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started, when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given changing version to be installed renders 1`] = `
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given changing version to be installed renders 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div
|
||||
@ -2709,7 +3151,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started, when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given changing version to be installed when version is selected renders 1`] = `
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given changing version to be installed when version is selected renders 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div
|
||||
@ -3696,7 +4138,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started, when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given changing version to be installed when version is selected when default configuration resolves renders 1`] = `
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given changing version to be installed when version is selected when default configuration resolves renders 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div
|
||||
@ -4678,7 +5120,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started, when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given custom name is inputted renders 1`] = `
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given custom name is inputted renders 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div
|
||||
@ -5660,7 +6102,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started, when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given invalid change in configuration renders 1`] = `
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given invalid change in configuration renders 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div
|
||||
@ -6664,7 +7106,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started, when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given namespace selection is opened renders 1`] = `
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given namespace selection is opened renders 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div
|
||||
@ -7677,7 +8119,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started, when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given namespace selection is opened when namespace is selected renders 1`] = `
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given namespace selection is opened when namespace is selected renders 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div
|
||||
@ -8659,7 +9101,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started, when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given no changes in configuration, when installing the chart renders 1`] = `
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given no changes in configuration, when installing the chart renders 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div
|
||||
@ -9649,7 +10091,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started, when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given no changes in configuration, when installing the chart when installation resolves renders 1`] = `
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given no changes in configuration, when installing the chart when installation resolves renders 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div
|
||||
@ -10498,7 +10940,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started, when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given no changes in configuration, when installing the chart when installation resolves when selected to see the installed release renders 1`] = `
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given no changes in configuration, when installing the chart when installation resolves when selected to see the installed release renders 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div
|
||||
@ -11271,7 +11713,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started, when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given no changes in configuration, when installing the chart when installation resolves when selected to show execution output renders 1`] = `
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given no changes in configuration, when installing the chart when installation resolves when selected to show execution output renders 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div
|
||||
@ -12180,7 +12622,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started, when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given opening details for second chart, when details resolve renders 1`] = `
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given opening details for second chart, when details resolve renders 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div
|
||||
@ -13408,7 +13850,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started, when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given opening details for second chart, when details resolve when selecting to install second chart renders 1`] = `
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given opening details for second chart, when details resolve when selecting to install second chart renders 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div
|
||||
@ -14226,7 +14668,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started, when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given opening details for second chart, when details resolve when selecting to install second chart when configuration and versions resolve renders 1`] = `
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given opening details for second chart, when details resolve when selecting to install second chart when configuration and versions resolve renders 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div
|
||||
@ -15259,7 +15701,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started, when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given opening details for second chart, when details resolve when selecting to install second chart when configuration and versions resolve when selecting the dock tab for installing first chart renders 1`] = `
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given opening details for second chart, when details resolve when selecting to install second chart when configuration and versions resolve when selecting the dock tab for installing first chart renders 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div
|
||||
@ -16290,7 +16732,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started, when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given valid change in configuration renders 1`] = `
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started when navigating to helm charts when selecting to install the chart when default configuration and versions resolve given valid change in configuration renders 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div
|
||||
@ -17272,7 +17714,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started, when navigating to helm charts when selecting to install the chart when default configuration and versions resolve renders 1`] = `
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started when navigating to helm charts when selecting to install the chart when default configuration and versions resolve renders 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div
|
||||
@ -18254,7 +18696,7 @@ exports[`installing helm chart from new tab given tab for installing chart was n
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started, when navigating to helm charts when selecting to install the chart when default configuration and versions resolve when cancelled renders 1`] = `
|
||||
exports[`installing helm chart from new tab given tab for installing chart was not previously opened and application is started when navigating to helm charts when selecting to install the chart when default configuration and versions resolve when cancelled renders 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -15,18 +15,15 @@ import namespaceStoreInjectable from "../../../renderer/components/+namespaces/s
|
||||
import type { NamespaceStore } from "../../../renderer/components/+namespaces/store";
|
||||
import type { CallForHelmChartVersions } from "../../../renderer/components/+helm-charts/details/versions/call-for-helm-chart-versions.injectable";
|
||||
import callForHelmChartVersionsInjectable from "../../../renderer/components/+helm-charts/details/versions/call-for-helm-chart-versions.injectable";
|
||||
import { overrideFsWithFakes } from "../../../test-utils/override-fs-with-fakes";
|
||||
import writeJsonFileInjectable from "../../../common/fs/write-json-file.injectable";
|
||||
import directoryForLensLocalStorageInjectable from "../../../common/directory-for-lens-local-storage/directory-for-lens-local-storage.injectable";
|
||||
import hostedClusterIdInjectable from "../../../renderer/cluster-frame-context/hosted-cluster-id.injectable";
|
||||
import { TabKind } from "../../../renderer/components/dock/dock/store";
|
||||
import { controlWhenStoragesAreReady } from "../../../renderer/utils/create-storage/storages-are-ready";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import callForCreateHelmReleaseInjectable from "../../../renderer/components/+helm-releases/create-release/call-for-create-helm-release.injectable";
|
||||
|
||||
describe("installing helm chart from previously opened tab", () => {
|
||||
let builder: ApplicationBuilder;
|
||||
let rendererDi: DiContainer;
|
||||
let callForHelmChartVersionsMock: AsyncFnMock<CallForHelmChartVersions>;
|
||||
let callForHelmChartValuesMock: AsyncFnMock<CallForHelmChartValues>;
|
||||
let storagesAreReady: () => Promise<void>;
|
||||
@ -34,45 +31,43 @@ describe("installing helm chart from previously opened tab", () => {
|
||||
beforeEach(() => {
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
rendererDi = builder.dis.rendererDi;
|
||||
|
||||
overrideFsWithFakes(rendererDi);
|
||||
builder.setEnvironmentToClusterFrame();
|
||||
|
||||
callForHelmChartVersionsMock = asyncFn();
|
||||
callForHelmChartValuesMock = asyncFn();
|
||||
|
||||
builder.beforeApplicationStart(({ rendererDi }) => {
|
||||
rendererDi.override(
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.override(
|
||||
directoryForLensLocalStorageInjectable,
|
||||
() => "/some-directory-for-lens-local-storage",
|
||||
);
|
||||
|
||||
rendererDi.override(hostedClusterIdInjectable, () => "some-cluster-id");
|
||||
windowDi.override(hostedClusterIdInjectable, () => "some-cluster-id");
|
||||
|
||||
storagesAreReady = controlWhenStoragesAreReady(rendererDi);
|
||||
storagesAreReady = controlWhenStoragesAreReady(windowDi);
|
||||
|
||||
rendererDi.override(
|
||||
windowDi.override(
|
||||
callForHelmChartVersionsInjectable,
|
||||
() => callForHelmChartVersionsMock,
|
||||
);
|
||||
|
||||
rendererDi.override(
|
||||
windowDi.override(
|
||||
callForHelmChartValuesInjectable,
|
||||
() => callForHelmChartValuesMock,
|
||||
);
|
||||
|
||||
rendererDi.override(
|
||||
windowDi.override(
|
||||
callForHelmChartValuesInjectable,
|
||||
() => callForHelmChartValuesMock,
|
||||
);
|
||||
|
||||
rendererDi.override(
|
||||
windowDi.override(
|
||||
callForCreateHelmReleaseInjectable,
|
||||
() => jest.fn(),
|
||||
);
|
||||
|
||||
// TODO: Replace store mocking with mock for the actual side-effect (where the namespaces are coming from)
|
||||
rendererDi.override(
|
||||
windowDi.override(
|
||||
namespaceStoreInjectable,
|
||||
() =>
|
||||
({
|
||||
@ -85,51 +80,51 @@ describe("installing helm chart from previously opened tab", () => {
|
||||
} as unknown as NamespaceStore),
|
||||
);
|
||||
|
||||
rendererDi.override(getRandomInstallChartTabIdInjectable, () =>
|
||||
windowDi.override(getRandomInstallChartTabIdInjectable, () =>
|
||||
jest
|
||||
.fn(() => "some-irrelevant-tab-id")
|
||||
.mockReturnValueOnce("some-first-tab-id"),
|
||||
);
|
||||
});
|
||||
|
||||
builder.setEnvironmentToClusterFrame();
|
||||
});
|
||||
|
||||
describe("given tab for installing chart was previously opened, when application is started", () => {
|
||||
let rendered: RenderResult;
|
||||
|
||||
beforeEach(async () => {
|
||||
const writeJsonFile = rendererDi.inject(writeJsonFileInjectable);
|
||||
builder.beforeWindowStart(async (windowDi) => {
|
||||
const writeJsonFile = windowDi.inject(writeJsonFileInjectable);
|
||||
|
||||
writeJsonFile(
|
||||
"/some-directory-for-lens-local-storage/some-cluster-id.json",
|
||||
{
|
||||
dock: {
|
||||
height: 300,
|
||||
tabs: [
|
||||
{
|
||||
id: "some-first-tab-id",
|
||||
kind: TabKind.INSTALL_CHART,
|
||||
title: "Helm Install: some-repository/some-name",
|
||||
pinned: false,
|
||||
await writeJsonFile(
|
||||
"/some-directory-for-lens-local-storage/some-cluster-id.json",
|
||||
{
|
||||
dock: {
|
||||
height: 300,
|
||||
tabs: [
|
||||
{
|
||||
id: "some-first-tab-id",
|
||||
kind: TabKind.INSTALL_CHART,
|
||||
title: "Helm Install: some-repository/some-name",
|
||||
pinned: false,
|
||||
},
|
||||
],
|
||||
|
||||
isOpen: true,
|
||||
},
|
||||
|
||||
install_charts: {
|
||||
"some-first-tab-id": {
|
||||
name: "some-name",
|
||||
repo: "some-repository",
|
||||
version: "some-other-version",
|
||||
values: "some-stored-configuration",
|
||||
releaseName: "some-stored-custom-name",
|
||||
namespace: "some-other-namespace",
|
||||
},
|
||||
],
|
||||
|
||||
isOpen: true,
|
||||
},
|
||||
|
||||
install_charts: {
|
||||
"some-first-tab-id": {
|
||||
name: "some-name",
|
||||
repo: "some-repository",
|
||||
version: "some-other-version",
|
||||
values: "some-stored-configuration",
|
||||
releaseName: "some-stored-custom-name",
|
||||
namespace: "some-other-namespace",
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
rendered = await builder.render();
|
||||
|
||||
|
||||
@ -19,15 +19,12 @@ import callForHelmChartReadmeInjectable from "../../../renderer/components/+helm
|
||||
import type { CallForHelmChartVersions } from "../../../renderer/components/+helm-charts/details/versions/call-for-helm-chart-versions.injectable";
|
||||
import callForHelmChartVersionsInjectable from "../../../renderer/components/+helm-charts/details/versions/call-for-helm-chart-versions.injectable";
|
||||
import { flushPromises } from "../../../common/test-utils/flush-promises";
|
||||
import { overrideFsWithFakes } from "../../../test-utils/override-fs-with-fakes";
|
||||
import directoryForLensLocalStorageInjectable from "../../../common/directory-for-lens-local-storage/directory-for-lens-local-storage.injectable";
|
||||
import hostedClusterIdInjectable from "../../../renderer/cluster-frame-context/hosted-cluster-id.injectable";
|
||||
import dockStoreInjectable from "../../../renderer/components/dock/dock/store.injectable";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
|
||||
describe("opening dock tab for installing helm chart", () => {
|
||||
let builder: ApplicationBuilder;
|
||||
let rendererDi: DiContainer;
|
||||
let callForHelmChartsMock: AsyncFnMock<CallForHelmCharts>;
|
||||
let callForHelmChartVersionsMock: AsyncFnMock<CallForHelmChartVersions>;
|
||||
let callForHelmChartReadmeMock: AsyncFnMock<CallForHelmChartReadme>;
|
||||
@ -36,49 +33,45 @@ describe("opening dock tab for installing helm chart", () => {
|
||||
beforeEach(() => {
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
rendererDi = builder.dis.rendererDi;
|
||||
|
||||
overrideFsWithFakes(rendererDi);
|
||||
|
||||
callForHelmChartsMock = asyncFn();
|
||||
callForHelmChartVersionsMock = asyncFn();
|
||||
callForHelmChartReadmeMock = asyncFn();
|
||||
callForHelmChartValuesMock = jest.fn();
|
||||
|
||||
builder.beforeApplicationStart(({ rendererDi }) => {
|
||||
rendererDi.override(
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.override(
|
||||
directoryForLensLocalStorageInjectable,
|
||||
() => "/some-directory-for-lens-local-storage",
|
||||
);
|
||||
|
||||
rendererDi.override(hostedClusterIdInjectable, () => "some-cluster-id");
|
||||
windowDi.override(hostedClusterIdInjectable, () => "some-cluster-id");
|
||||
|
||||
rendererDi.override(
|
||||
windowDi.override(
|
||||
callForHelmChartsInjectable,
|
||||
() => callForHelmChartsMock,
|
||||
);
|
||||
|
||||
rendererDi.override(
|
||||
windowDi.override(
|
||||
callForHelmChartVersionsInjectable,
|
||||
() => callForHelmChartVersionsMock,
|
||||
);
|
||||
|
||||
rendererDi.override(
|
||||
windowDi.override(
|
||||
callForHelmChartReadmeInjectable,
|
||||
() => callForHelmChartReadmeMock,
|
||||
);
|
||||
|
||||
rendererDi.override(
|
||||
windowDi.override(
|
||||
callForHelmChartValuesInjectable,
|
||||
() => callForHelmChartValuesMock,
|
||||
);
|
||||
|
||||
rendererDi.override(
|
||||
windowDi.override(
|
||||
callForCreateHelmReleaseInjectable,
|
||||
() => jest.fn(),
|
||||
);
|
||||
|
||||
rendererDi.override(getRandomInstallChartTabIdInjectable, () =>
|
||||
windowDi.override(getRandomInstallChartTabIdInjectable, () =>
|
||||
jest
|
||||
.fn(() => "some-irrelevant-tab-id")
|
||||
.mockReturnValueOnce("some-tab-id"),
|
||||
@ -96,7 +89,9 @@ describe("opening dock tab for installing helm chart", () => {
|
||||
|
||||
builder.helmCharts.navigate();
|
||||
|
||||
const dockStore = rendererDi.inject(dockStoreInjectable);
|
||||
const windowDi = builder.applicationWindow.only.di;
|
||||
|
||||
const dockStore = windowDi.inject(dockStoreInjectable);
|
||||
|
||||
// TODO: Make TerminalWindow unit testable to allow realistic behaviour
|
||||
dockStore.closeTab("terminal");
|
||||
|
||||
@ -18,7 +18,7 @@ import callForPublicHelmRepositoriesInjectable from "../../renderer/components/+
|
||||
import showErrorNotificationInjectable from "../../renderer/components/notifications/show-error-notification.injectable";
|
||||
|
||||
describe("listing active helm repositories in preferences", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let builder: ApplicationBuilder;
|
||||
let rendered: RenderResult;
|
||||
let readYamlFileMock: AsyncFnMock<ReadYamlFile>;
|
||||
let execFileMock: AsyncFnMock<ReturnType<typeof execFileInjectable["instantiate"]>>;
|
||||
@ -26,31 +26,33 @@ describe("listing active helm repositories in preferences", () => {
|
||||
let showErrorNotificationMock: jest.Mock;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
readYamlFileMock = asyncFn();
|
||||
execFileMock = asyncFn();
|
||||
showErrorNotificationMock = jest.fn();
|
||||
|
||||
loggerStub = { error: jest.fn() } as unknown as Logger;
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi, rendererDi }) => {
|
||||
showErrorNotificationMock = jest.fn();
|
||||
|
||||
rendererDi.override(showErrorNotificationInjectable, () => showErrorNotificationMock);
|
||||
rendererDi.override(callForPublicHelmRepositoriesInjectable, () => async () => []);
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
mainDi.override(readYamlFileInjectable, () => readYamlFileMock);
|
||||
mainDi.override(execFileInjectable, () => execFileMock);
|
||||
mainDi.override(helmBinaryPathInjectable, () => "some-helm-binary-path");
|
||||
mainDi.override(loggerInjectable, () => loggerStub);
|
||||
});
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.override(showErrorNotificationInjectable, () => showErrorNotificationMock);
|
||||
windowDi.override(callForPublicHelmRepositoriesInjectable, () => async () => []);
|
||||
});
|
||||
|
||||
rendered = await builder.render();
|
||||
});
|
||||
|
||||
describe("when navigating to preferences containing helm repositories", () => {
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.preferences.navigate();
|
||||
applicationBuilder.preferences.navigation.click("kubernetes");
|
||||
builder.preferences.navigate();
|
||||
builder.preferences.navigation.click("kubernetes");
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
|
||||
@ -16,7 +16,7 @@ import callForPublicHelmRepositoriesInjectable from "../../renderer/components/+
|
||||
import type { AsyncResult } from "../../common/utils/async-result";
|
||||
|
||||
describe("remove helm repository from list of active repositories in preferences", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let builder: ApplicationBuilder;
|
||||
let rendered: RenderResult;
|
||||
let getActiveHelmRepositoriesMock: AsyncFnMock<() => Promise<AsyncResult<HelmRepo[]>>>;
|
||||
let execFileMock: AsyncFnMock<
|
||||
@ -24,30 +24,28 @@ describe("remove helm repository from list of active repositories in preferences
|
||||
>;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
execFileMock = asyncFn();
|
||||
getActiveHelmRepositoriesMock = asyncFn();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi, rendererDi }) => {
|
||||
rendererDi.override(callForPublicHelmRepositoriesInjectable, () => async () => []);
|
||||
|
||||
mainDi.override(
|
||||
getActiveHelmRepositoriesInjectable,
|
||||
() => getActiveHelmRepositoriesMock,
|
||||
);
|
||||
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
mainDi.override(getActiveHelmRepositoriesInjectable, () => getActiveHelmRepositoriesMock);
|
||||
mainDi.override(execFileInjectable, () => execFileMock);
|
||||
mainDi.override(helmBinaryPathInjectable, () => "some-helm-binary-path");
|
||||
});
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.override(callForPublicHelmRepositoriesInjectable, () => async () => []);
|
||||
});
|
||||
|
||||
rendered = await builder.render();
|
||||
});
|
||||
|
||||
describe("when navigating to preferences containing helm repositories", () => {
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.preferences.navigate();
|
||||
applicationBuilder.preferences.navigation.click("kubernetes");
|
||||
builder.preferences.navigate();
|
||||
builder.preferences.navigation.click("kubernetes");
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
|
||||
@ -48,43 +48,43 @@ describe("showing details for helm release", () => {
|
||||
showSuccessNotificationMock = jest.fn();
|
||||
showCheckedErrorNotificationMock = jest.fn();
|
||||
|
||||
builder.beforeApplicationStart(({ rendererDi }) => {
|
||||
rendererDi.override(
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.override(
|
||||
getRandomUpgradeChartTabIdInjectable,
|
||||
() => () => "some-tab-id",
|
||||
);
|
||||
|
||||
rendererDi.override(
|
||||
windowDi.override(
|
||||
showSuccessNotificationInjectable,
|
||||
() => showSuccessNotificationMock,
|
||||
);
|
||||
|
||||
rendererDi.override(
|
||||
windowDi.override(
|
||||
showCheckedErrorInjectable,
|
||||
() => showCheckedErrorNotificationMock,
|
||||
);
|
||||
|
||||
rendererDi.override(
|
||||
windowDi.override(
|
||||
callForHelmReleasesInjectable,
|
||||
() => callForHelmReleasesMock,
|
||||
);
|
||||
|
||||
rendererDi.override(
|
||||
windowDi.override(
|
||||
callForHelmReleaseInjectable,
|
||||
() => callForHelmReleaseMock,
|
||||
);
|
||||
|
||||
rendererDi.override(
|
||||
windowDi.override(
|
||||
callForHelmReleaseConfigurationInjectable,
|
||||
() => callForHelmReleaseConfigurationMock,
|
||||
);
|
||||
|
||||
rendererDi.override(
|
||||
windowDi.override(
|
||||
callForHelmReleaseUpdateInjectable,
|
||||
() => callForHelmReleaseUpdateMock,
|
||||
);
|
||||
|
||||
rendererDi.override(
|
||||
windowDi.override(
|
||||
namespaceStoreInjectable,
|
||||
() =>
|
||||
({
|
||||
@ -105,9 +105,9 @@ describe("showing details for helm release", () => {
|
||||
|
||||
describe("when navigating to helm releases", () => {
|
||||
beforeEach(() => {
|
||||
const rendererDi = builder.dis.rendererDi;
|
||||
const windowDi = builder.applicationWindow.only.di;
|
||||
|
||||
const navigateToHelmReleases = rendererDi.inject(
|
||||
const navigateToHelmReleases = windowDi.inject(
|
||||
navigateToHelmReleasesInjectable,
|
||||
);
|
||||
|
||||
|
||||
@ -2,8 +2,6 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { FakeExtensionData, TestExtension } from "../renderer/components/test-utils/get-renderer-extension-fake";
|
||||
import { getRendererExtensionFakeFor } from "../renderer/components/test-utils/get-renderer-extension-fake";
|
||||
import React from "react";
|
||||
import type { RenderResult } from "@testing-library/react";
|
||||
import { fireEvent } from "@testing-library/react";
|
||||
@ -12,29 +10,29 @@ import queryParametersInjectable from "../renderer/routes/query-parameters.injec
|
||||
import currentPathInjectable from "../renderer/routes/current-path.injectable";
|
||||
import type { IComputedValue } from "mobx";
|
||||
import { getApplicationBuilder } from "../renderer/components/test-utils/get-application-builder";
|
||||
import type { FakeExtensionOptions } from "../renderer/components/test-utils/get-extension-fake";
|
||||
import type { LensRendererExtension } from "../extensions/lens-renderer-extension";
|
||||
|
||||
describe("navigate to extension page", () => {
|
||||
let rendered: RenderResult;
|
||||
let testExtension: TestExtension;
|
||||
let testExtension: LensRendererExtension;
|
||||
let queryParameters: IComputedValue<object>;
|
||||
let currentPath: IComputedValue<string>;
|
||||
|
||||
beforeEach(async () => {
|
||||
const applicationBuilder = getApplicationBuilder();
|
||||
const getRendererExtensionFake = getRendererExtensionFakeFor(applicationBuilder);
|
||||
const builder = getApplicationBuilder();
|
||||
|
||||
testExtension = getRendererExtensionFake(
|
||||
extensionWithPagesHavingParameters,
|
||||
);
|
||||
builder.extensions.enable(extensionWithPagesHavingParameters);
|
||||
|
||||
applicationBuilder.extensions.renderer.enable(testExtension);
|
||||
rendered = await builder.render();
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
const windowDi = builder.applicationWindow.only.di;
|
||||
|
||||
const rendererDi = applicationBuilder.dis.rendererDi;
|
||||
testExtension =
|
||||
builder.extensions.get("some-extension-id").applicationWindows.only;
|
||||
|
||||
queryParameters = rendererDi.inject(queryParametersInjectable);
|
||||
currentPath = rendererDi.inject(currentPathInjectable);
|
||||
queryParameters = windowDi.inject(queryParametersInjectable);
|
||||
currentPath = windowDi.inject(currentPathInjectable);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -125,57 +123,60 @@ describe("navigate to extension page", () => {
|
||||
});
|
||||
});
|
||||
|
||||
const extensionWithPagesHavingParameters: FakeExtensionData = {
|
||||
const extensionWithPagesHavingParameters: FakeExtensionOptions = {
|
||||
id: "some-extension-id",
|
||||
name: "some-extension-name",
|
||||
globalPages: [
|
||||
{
|
||||
components: {
|
||||
Page: ({ params }) => (
|
||||
<div>
|
||||
<ul>
|
||||
<li>{params.someStringParameter.get()}</li>
|
||||
<li>{params.someNumberParameter.get()}</li>
|
||||
<li>{params.someArrayParameter.get().join(",")}</li>
|
||||
</ul>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
data-testid="button-to-change-page-parameters"
|
||||
onClick={() => {
|
||||
params.someStringParameter.set("some-changed-string-value");
|
||||
params.someNumberParameter.set(84);
|
||||
params.someArrayParameter.set([
|
||||
"some-changed-array-value",
|
||||
"some-other-changed-array-value",
|
||||
]);
|
||||
}}
|
||||
>
|
||||
Some button
|
||||
</button>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
rendererOptions: {
|
||||
globalPages: [
|
||||
{
|
||||
components: {
|
||||
Page: ({ params }) => (
|
||||
<div>
|
||||
<ul>
|
||||
<li>{params.someStringParameter.get()}</li>
|
||||
<li>{params.someNumberParameter.get()}</li>
|
||||
<li>{params.someArrayParameter.get().join(",")}</li>
|
||||
</ul>
|
||||
|
||||
params: {
|
||||
someStringParameter: "some-string-value",
|
||||
someNumberParameter: {
|
||||
defaultValue: 42,
|
||||
stringify: (value) => value.toString(),
|
||||
parse: (value) => (value ? Number(value) : undefined),
|
||||
<button
|
||||
type="button"
|
||||
data-testid="button-to-change-page-parameters"
|
||||
onClick={() => {
|
||||
params.someStringParameter.set("some-changed-string-value");
|
||||
params.someNumberParameter.set(84);
|
||||
params.someArrayParameter.set([
|
||||
"some-changed-array-value",
|
||||
"some-other-changed-array-value",
|
||||
]);
|
||||
}}
|
||||
>
|
||||
Some button
|
||||
</button>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
someArrayParameter: {
|
||||
defaultValue: ["some-array-value", "some-other-array-value"],
|
||||
stringify: (value) => value.join(","),
|
||||
parse: (value: string[]) => (!isEmpty(value) ? value : undefined),
|
||||
|
||||
params: {
|
||||
someStringParameter: "some-string-value",
|
||||
someNumberParameter: {
|
||||
defaultValue: 42,
|
||||
stringify: (value) => value.toString(),
|
||||
parse: (value) => (value ? Number(value) : undefined),
|
||||
},
|
||||
someArrayParameter: {
|
||||
defaultValue: ["some-array-value", "some-other-array-value"],
|
||||
stringify: (value) => value.join(","),
|
||||
parse: (value: string[]) => (!isEmpty(value) ? value : undefined),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "some-child-page-id",
|
||||
components: {
|
||||
Page: () => <div>Child page</div>,
|
||||
{
|
||||
id: "some-child-page-id",
|
||||
components: {
|
||||
Page: () => <div>Child page</div>,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
@ -20,32 +20,34 @@ import { navigateToRouteInjectionToken } from "../common/front-end-routing/navig
|
||||
import routePathParametersInjectable from "../renderer/routes/route-path-parameters.injectable";
|
||||
|
||||
describe("navigating between routes", () => {
|
||||
let rendererDi: DiContainer;
|
||||
let rendered: RenderResult;
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let builder: ApplicationBuilder;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
rendererDi = applicationBuilder.dis.rendererDi;
|
||||
builder = getApplicationBuilder();
|
||||
});
|
||||
|
||||
describe("given route without path parameters", () => {
|
||||
let windowDi: DiContainer;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeApplicationStart(({ rendererDi }) => {
|
||||
rendererDi.register(testRouteWithoutPathParametersInjectable);
|
||||
rendererDi.register(testRouteWithoutPathParametersComponentInjectable);
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.register(testRouteWithoutPathParametersInjectable);
|
||||
windowDi.register(testRouteWithoutPathParametersComponentInjectable);
|
||||
});
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
rendered = await builder.render();
|
||||
|
||||
windowDi = builder.applicationWindow.only.di;
|
||||
});
|
||||
|
||||
describe("when navigating to route", () => {
|
||||
let route: Route;
|
||||
|
||||
beforeEach(() => {
|
||||
const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken);
|
||||
const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken);
|
||||
|
||||
route = rendererDi.inject(testRouteWithoutPathParametersInjectable);
|
||||
route = windowDi.inject(testRouteWithoutPathParametersInjectable);
|
||||
|
||||
navigateToRoute(route);
|
||||
});
|
||||
@ -55,35 +57,35 @@ describe("navigating between routes", () => {
|
||||
});
|
||||
|
||||
it("knows current route", () => {
|
||||
const currentRoute = rendererDi.inject(currentRouteInjectable);
|
||||
const currentRoute = windowDi.inject(currentRouteInjectable);
|
||||
|
||||
expect(currentRoute.get()).toBe(route);
|
||||
});
|
||||
|
||||
it("knows current path", () => {
|
||||
const currentPath = rendererDi.inject(currentPathInjectable);
|
||||
const currentPath = windowDi.inject(currentPathInjectable);
|
||||
|
||||
expect(currentPath.get()).toBe("/some-path");
|
||||
});
|
||||
|
||||
it("does not have query parameters", () => {
|
||||
const queryParameters = rendererDi.inject(queryParametersInjectable);
|
||||
const queryParameters = windowDi.inject(queryParametersInjectable);
|
||||
|
||||
expect(queryParameters.get()).toEqual({});
|
||||
});
|
||||
|
||||
it("does not have path parameters", () => {
|
||||
const pathParameters = rendererDi.inject(routePathParametersInjectable, route);
|
||||
const pathParameters = windowDi.inject(routePathParametersInjectable, route);
|
||||
|
||||
expect(pathParameters.get()).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
it("when navigating to route with query parameters, knows query parameters", () => {
|
||||
const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken);
|
||||
const queryParameters = rendererDi.inject(queryParametersInjectable);
|
||||
const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken);
|
||||
const queryParameters = windowDi.inject(queryParametersInjectable);
|
||||
|
||||
const route = rendererDi.inject(testRouteWithoutPathParametersInjectable);
|
||||
const route = windowDi.inject(testRouteWithoutPathParametersInjectable);
|
||||
|
||||
navigateToRoute(route, {
|
||||
query: {
|
||||
@ -100,23 +102,26 @@ describe("navigating between routes", () => {
|
||||
});
|
||||
|
||||
describe("given route with optional path parameters", () => {
|
||||
let windowDi: DiContainer;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeApplicationStart(({ rendererDi }) => {
|
||||
rendererDi.register(routeWithOptionalPathParametersInjectable);
|
||||
rendererDi.register(routeWithOptionalPathParametersComponentInjectable);
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.register(routeWithOptionalPathParametersInjectable);
|
||||
windowDi.register(routeWithOptionalPathParametersComponentInjectable);
|
||||
});
|
||||
|
||||
rendered = await builder.render();
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
windowDi = builder.applicationWindow.only.di;
|
||||
});
|
||||
|
||||
describe("when navigating to route with path parameters", () => {
|
||||
let route: Route<any>;
|
||||
|
||||
beforeEach(() => {
|
||||
route = rendererDi.inject(routeWithOptionalPathParametersInjectable);
|
||||
route = windowDi.inject(routeWithOptionalPathParametersInjectable);
|
||||
|
||||
const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken);
|
||||
const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken);
|
||||
|
||||
navigateToRoute(route, {
|
||||
parameters: {
|
||||
@ -131,13 +136,13 @@ describe("navigating between routes", () => {
|
||||
});
|
||||
|
||||
it("knows current route", () => {
|
||||
const currentRoute = rendererDi.inject(currentRouteInjectable);
|
||||
const currentRoute = windowDi.inject(currentRouteInjectable);
|
||||
|
||||
expect(currentRoute.get()).toBe(route);
|
||||
});
|
||||
|
||||
it("knows current path", () => {
|
||||
const currentPath = rendererDi.inject(currentPathInjectable);
|
||||
const currentPath = windowDi.inject(currentPathInjectable);
|
||||
|
||||
expect(currentPath.get()).toBe(
|
||||
"/some-path/some-value/some-other-value",
|
||||
@ -145,7 +150,7 @@ describe("navigating between routes", () => {
|
||||
});
|
||||
|
||||
it("knows path parameters", () => {
|
||||
const pathParameters = rendererDi.inject(routePathParametersInjectable, route);
|
||||
const pathParameters = windowDi.inject(routePathParametersInjectable, route);
|
||||
|
||||
expect(pathParameters.get()).toEqual({
|
||||
someParameter: "some-value",
|
||||
@ -158,27 +163,27 @@ describe("navigating between routes", () => {
|
||||
let route: Route<any>;
|
||||
|
||||
beforeEach(() => {
|
||||
route = rendererDi.inject(routeWithOptionalPathParametersInjectable);
|
||||
route = windowDi.inject(routeWithOptionalPathParametersInjectable);
|
||||
|
||||
const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken);
|
||||
const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken);
|
||||
|
||||
navigateToRoute(route);
|
||||
});
|
||||
|
||||
it("knows current route", () => {
|
||||
const currentRoute = rendererDi.inject(currentRouteInjectable);
|
||||
const currentRoute = windowDi.inject(currentRouteInjectable);
|
||||
|
||||
expect(currentRoute.get()).toBe(route);
|
||||
});
|
||||
|
||||
it("knows current path", () => {
|
||||
const currentPath = rendererDi.inject(currentPathInjectable);
|
||||
const currentPath = windowDi.inject(currentPathInjectable);
|
||||
|
||||
expect(currentPath.get()).toBe("/some-path");
|
||||
});
|
||||
|
||||
it("knows path parameters", () => {
|
||||
const pathParameters = rendererDi.inject(routePathParametersInjectable, route);
|
||||
const pathParameters = windowDi.inject(routePathParametersInjectable, route);
|
||||
|
||||
expect(pathParameters.get()).toEqual({
|
||||
someParameter: undefined,
|
||||
|
||||
@ -24,19 +24,19 @@ import navigateToFrontPageInjectable from "../../common/front-end-routing/naviga
|
||||
import { navigateToRouteInjectionToken } from "../../common/front-end-routing/navigate-to-route-injection-token";
|
||||
|
||||
describe("preferences - closing-preferences", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let builder: ApplicationBuilder;
|
||||
|
||||
beforeEach(() => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ rendererDi }) => {
|
||||
rendererDi.register(testPreferencesRouteInjectable);
|
||||
rendererDi.register(testPreferencesRouteComponentInjectable);
|
||||
rendererDi.register(testFrontPageRouteInjectable);
|
||||
rendererDi.register(testFrontPageRouteComponentInjectable);
|
||||
rendererDi.register(testNavigationItemInjectable);
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.register(testPreferencesRouteInjectable);
|
||||
windowDi.register(testPreferencesRouteComponentInjectable);
|
||||
windowDi.register(testFrontPageRouteInjectable);
|
||||
windowDi.register(testFrontPageRouteComponentInjectable);
|
||||
windowDi.register(testNavigationItemInjectable);
|
||||
|
||||
rendererDi.override(navigateToFrontPageInjectable, (di) => {
|
||||
windowDi.override(navigateToFrontPageInjectable, (di) => {
|
||||
const navigateToRoute = di.inject(navigateToRouteInjectionToken);
|
||||
const testFrontPage = di.inject(testFrontPageRouteInjectable);
|
||||
|
||||
@ -49,11 +49,11 @@ describe("preferences - closing-preferences", () => {
|
||||
|
||||
describe("given already in a page and then navigated to preferences", () => {
|
||||
let rendered: RenderResult;
|
||||
let rendererDi: DiContainer;
|
||||
let windowDi: DiContainer;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeApplicationStart(({ rendererDi }) => {
|
||||
rendererDi.override(observableHistoryInjectable, () => {
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.override(observableHistoryInjectable, () => {
|
||||
const historyFake = createMemoryHistory({
|
||||
initialEntries: ["/some-test-path"],
|
||||
initialIndex: 0,
|
||||
@ -65,10 +65,10 @@ describe("preferences - closing-preferences", () => {
|
||||
});
|
||||
});
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
rendererDi = applicationBuilder.dis.rendererDi;
|
||||
rendered = await builder.render();
|
||||
windowDi = builder.applicationWindow.only.di;
|
||||
|
||||
applicationBuilder.preferences.navigate();
|
||||
builder.preferences.navigate();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -77,7 +77,7 @@ describe("preferences - closing-preferences", () => {
|
||||
|
||||
describe("when preferences are closed", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.preferences.close();
|
||||
builder.preferences.close();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -85,7 +85,7 @@ describe("preferences - closing-preferences", () => {
|
||||
});
|
||||
|
||||
it("navigates back to the original page", () => {
|
||||
const currentPath = rendererDi.inject(currentPathInjectable).get();
|
||||
const currentPath = windowDi.inject(currentPathInjectable).get();
|
||||
|
||||
expect(currentPath).toBe("/some-test-path");
|
||||
});
|
||||
@ -93,7 +93,7 @@ describe("preferences - closing-preferences", () => {
|
||||
|
||||
describe("when navigating to a tab in preferences", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.preferences.navigation.click(
|
||||
builder.preferences.navigation.click(
|
||||
"some-test-preference-navigation-item-id",
|
||||
);
|
||||
});
|
||||
@ -104,7 +104,7 @@ describe("preferences - closing-preferences", () => {
|
||||
|
||||
describe("when preferences are closed", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.preferences.close();
|
||||
builder.preferences.close();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -112,7 +112,7 @@ describe("preferences - closing-preferences", () => {
|
||||
});
|
||||
|
||||
it("navigates back to the original page", () => {
|
||||
const currentPath = rendererDi.inject(currentPathInjectable).get();
|
||||
const currentPath = windowDi.inject(currentPathInjectable).get();
|
||||
|
||||
expect(currentPath).toBe("/some-test-path");
|
||||
});
|
||||
@ -122,11 +122,11 @@ describe("preferences - closing-preferences", () => {
|
||||
|
||||
describe("given accessing preferences directly", () => {
|
||||
let rendered: RenderResult;
|
||||
let rendererDi: DiContainer;
|
||||
let windowDi: DiContainer;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeApplicationStart(({ rendererDi }) => {
|
||||
rendererDi.override(observableHistoryInjectable, () => {
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.override(observableHistoryInjectable, () => {
|
||||
const historyFake = createMemoryHistory({
|
||||
initialEntries: ["/preferences/app"],
|
||||
initialIndex: 0,
|
||||
@ -138,9 +138,9 @@ describe("preferences - closing-preferences", () => {
|
||||
});
|
||||
});
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
rendered = await builder.render();
|
||||
|
||||
rendererDi = applicationBuilder.dis.rendererDi;
|
||||
windowDi = builder.applicationWindow.only.di;
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -149,7 +149,7 @@ describe("preferences - closing-preferences", () => {
|
||||
|
||||
describe("when preferences are closed", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.preferences.close();
|
||||
builder.preferences.close();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -157,7 +157,7 @@ describe("preferences - closing-preferences", () => {
|
||||
});
|
||||
|
||||
it("navigates back to the front page", () => {
|
||||
const currentPath = rendererDi.inject(currentPathInjectable).get();
|
||||
const currentPath = windowDi.inject(currentPathInjectable).get();
|
||||
|
||||
expect(currentPath).toBe("/some-front-page");
|
||||
});
|
||||
@ -165,7 +165,7 @@ describe("preferences - closing-preferences", () => {
|
||||
|
||||
describe("when navigating to a tab in preferences", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.preferences.navigation.click(
|
||||
builder.preferences.navigation.click(
|
||||
"some-test-preference-navigation-item-id",
|
||||
);
|
||||
});
|
||||
@ -176,7 +176,7 @@ describe("preferences - closing-preferences", () => {
|
||||
|
||||
describe("when preferences are closed", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.preferences.close();
|
||||
builder.preferences.close();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -184,7 +184,7 @@ describe("preferences - closing-preferences", () => {
|
||||
});
|
||||
|
||||
it("navigates back to the front page", () => {
|
||||
const currentPath = rendererDi.inject(currentPathInjectable).get();
|
||||
const currentPath = windowDi.inject(currentPathInjectable).get();
|
||||
|
||||
expect(currentPath).toBe("/some-front-page");
|
||||
});
|
||||
|
||||
@ -7,7 +7,6 @@ import type { IObservableValue } from "mobx";
|
||||
import { runInAction, computed, observable } from "mobx";
|
||||
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { getExtensionFakeFor } from "../../renderer/components/test-utils/get-extension-fake";
|
||||
|
||||
describe("preferences: extension adding preference tabs", () => {
|
||||
let builder: ApplicationBuilder;
|
||||
@ -25,11 +24,9 @@ describe("preferences: extension adding preference tabs", () => {
|
||||
|
||||
builder.preferences.navigate();
|
||||
|
||||
const getExtensionFake = getExtensionFakeFor(builder);
|
||||
|
||||
someObservable = observable.box(false);
|
||||
|
||||
const testExtension = getExtensionFake({
|
||||
const testExtension = {
|
||||
id: "some-extension-id",
|
||||
name: "some-extension",
|
||||
|
||||
@ -53,7 +50,7 @@ describe("preferences: extension adding preference tabs", () => {
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
builder.extensions.enable(testExtension);
|
||||
|
||||
|
||||
@ -8,23 +8,23 @@ import { getApplicationBuilder } from "../../renderer/components/test-utils/get-
|
||||
import navigateToProxyPreferencesInjectable from "../../common/front-end-routing/routes/preferences/proxy/navigate-to-proxy-preferences.injectable";
|
||||
|
||||
describe("preferences - navigation to application preferences", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let builder: ApplicationBuilder;
|
||||
|
||||
beforeEach(() => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
builder = getApplicationBuilder();
|
||||
});
|
||||
|
||||
describe("given in some child page of preferences, when rendered", () => {
|
||||
let rendered: RenderResult;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeRender(({ rendererDi }) => {
|
||||
const navigateToProxyPreferences = rendererDi.inject(navigateToProxyPreferencesInjectable);
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
const navigateToProxyPreferences = windowDi.inject(navigateToProxyPreferencesInjectable);
|
||||
|
||||
navigateToProxyPreferences();
|
||||
});
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
rendered = await builder.render();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -39,7 +39,7 @@ describe("preferences - navigation to application preferences", () => {
|
||||
|
||||
describe("when navigating to application preferences using navigation", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.preferences.navigation.click("application");
|
||||
builder.preferences.navigation.click("application");
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
|
||||
@ -17,7 +17,7 @@ describe("preferences - navigation to editor preferences", () => {
|
||||
let rendered: RenderResult;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeRender(() => {
|
||||
applicationBuilder.beforeWindowStart(() => {
|
||||
applicationBuilder.preferences.navigate();
|
||||
});
|
||||
|
||||
|
||||
@ -7,29 +7,25 @@ import type { ApplicationBuilder } from "../../renderer/components/test-utils/ge
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import React from "react";
|
||||
import "@testing-library/jest-dom/extend-expect";
|
||||
import type { FakeExtensionData, TestExtension } from "../../renderer/components/test-utils/get-renderer-extension-fake";
|
||||
import { getRendererExtensionFakeFor } from "../../renderer/components/test-utils/get-renderer-extension-fake";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import { getDiForUnitTesting } from "../../renderer/getDiForUnitTesting";
|
||||
import extensionPreferencesRouteInjectable from "../../common/front-end-routing/routes/preferences/extension/extension-preferences-route.injectable";
|
||||
|
||||
import type { FakeExtensionOptions } from "../../renderer/components/test-utils/get-extension-fake";
|
||||
|
||||
describe("preferences - navigation to extension specific preferences", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let builder: ApplicationBuilder;
|
||||
|
||||
beforeEach(() => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
builder = getApplicationBuilder();
|
||||
});
|
||||
|
||||
describe("given in preferences, when rendered", () => {
|
||||
let rendered: RenderResult;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeRender(() => {
|
||||
applicationBuilder.preferences.navigate();
|
||||
builder.beforeWindowStart(() => {
|
||||
builder.preferences.navigate();
|
||||
});
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
rendered = await builder.render();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -49,13 +45,15 @@ describe("preferences - navigation to extension specific preferences", () => {
|
||||
});
|
||||
|
||||
describe("given multiple extensions with specific preferences, when navigating to extension specific preferences page", () => {
|
||||
beforeEach(async () => {
|
||||
const getRendererExtensionFake = getRendererExtensionFakeFor(applicationBuilder);
|
||||
const someTestExtension = getRendererExtensionFake(extensionStubWithExtensionSpecificPreferenceItems);
|
||||
const someOtherTestExtension = getRendererExtensionFake(someOtherExtensionStubWithExtensionSpecificPreferenceItems);
|
||||
beforeEach(() => {
|
||||
builder.extensions.enable(
|
||||
extensionStubWithExtensionSpecificPreferenceItems,
|
||||
someOtherExtensionStubWithExtensionSpecificPreferenceItems,
|
||||
);
|
||||
|
||||
await applicationBuilder.extensions.renderer.enable(someTestExtension, someOtherTestExtension);
|
||||
applicationBuilder.preferences.navigation.click("extension-some-test-extension-id");
|
||||
builder.preferences.navigation.click(
|
||||
"extension-some-test-extension-id",
|
||||
);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -76,13 +74,12 @@ describe("preferences - navigation to extension specific preferences", () => {
|
||||
});
|
||||
|
||||
describe("given multiple extensions with and without specific preferences", () => {
|
||||
beforeEach(async () => {
|
||||
const getRendererExtensionFake = getRendererExtensionFakeFor(applicationBuilder);
|
||||
const someTestExtension = getRendererExtensionFake(extensionStubWithExtensionSpecificPreferenceItems);
|
||||
const extensionWithoutPreferences = getRendererExtensionFake(extensionStubWithoutPreferences);
|
||||
const extensionWithSpecificTab = getRendererExtensionFake(extensionStubWithShowInPreferencesTab);
|
||||
|
||||
await applicationBuilder.extensions.renderer.enable(someTestExtension, extensionWithoutPreferences, extensionWithSpecificTab);
|
||||
beforeEach(() => {
|
||||
builder.extensions.enable(
|
||||
extensionStubWithExtensionSpecificPreferenceItems,
|
||||
extensionStubWithoutPreferences,
|
||||
extensionStubWithShowInPreferencesTab,
|
||||
);
|
||||
});
|
||||
|
||||
it("doesn't show link for extension without preferences", () => {
|
||||
@ -99,16 +96,8 @@ describe("preferences - navigation to extension specific preferences", () => {
|
||||
});
|
||||
|
||||
describe("when extension with specific preferences is enabled", () => {
|
||||
let testExtension: TestExtension;
|
||||
|
||||
beforeEach(() => {
|
||||
const getRendererExtensionFake = getRendererExtensionFakeFor(applicationBuilder);
|
||||
|
||||
testExtension = getRendererExtensionFake(
|
||||
extensionStubWithExtensionSpecificPreferenceItems,
|
||||
);
|
||||
|
||||
applicationBuilder.extensions.renderer.enable(testExtension);
|
||||
builder.extensions.enable(extensionStubWithExtensionSpecificPreferenceItems);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -129,7 +118,7 @@ describe("preferences - navigation to extension specific preferences", () => {
|
||||
|
||||
describe("when navigating to extension preferences using navigation", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.preferences.navigation.click("extension-some-test-extension-id");
|
||||
builder.preferences.navigation.click("extension-some-test-extension-id");
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -168,7 +157,7 @@ describe("preferences - navigation to extension specific preferences", () => {
|
||||
|
||||
describe("when extension is disabled", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.extensions.renderer.disable(testExtension);
|
||||
builder.extensions.disable(extensionStubWithExtensionSpecificPreferenceItems);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -180,7 +169,7 @@ describe("preferences - navigation to extension specific preferences", () => {
|
||||
});
|
||||
|
||||
it("when extension is enabled again, does not show the error message anymore", () => {
|
||||
applicationBuilder.extensions.renderer.enable(testExtension);
|
||||
builder.extensions.enable(extensionStubWithExtensionSpecificPreferenceItems);
|
||||
|
||||
expect(rendered.queryByTestId("error-for-extension-not-being-present")).not.toBeInTheDocument();
|
||||
});
|
||||
@ -189,11 +178,8 @@ describe("preferences - navigation to extension specific preferences", () => {
|
||||
});
|
||||
|
||||
describe("given extension with registered tab", () => {
|
||||
beforeEach(async () => {
|
||||
const getRendererExtensionFake = getRendererExtensionFakeFor(applicationBuilder);
|
||||
const extension = getRendererExtensionFake(extensionStubWithWithRegisteredTab);
|
||||
|
||||
await applicationBuilder.extensions.renderer.enable(extension);
|
||||
beforeEach(() => {
|
||||
builder.extensions.enable(extensionStubWithWithRegisteredTab);
|
||||
});
|
||||
|
||||
it("shows extension tab in general area", () => {
|
||||
@ -210,7 +196,7 @@ describe("preferences - navigation to extension specific preferences", () => {
|
||||
|
||||
describe("when navigating to specific extension tab", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.preferences.navigation.click("extension-registered-tab-page-id-nav-item-metrics-extension-tab");
|
||||
builder.preferences.navigation.click("extension-registered-tab-page-id-nav-item-metrics-extension-tab");
|
||||
});
|
||||
it("renders", () => {
|
||||
expect(rendered.container).toMatchSnapshot();
|
||||
@ -232,7 +218,7 @@ describe("preferences - navigation to extension specific preferences", () => {
|
||||
});
|
||||
it("shows page title same as tab title", () => {
|
||||
const pageTitle = rendered.queryByTestId("extension-preferences-page-title");
|
||||
const tabs = extensionStubWithWithRegisteredTab.appPreferenceTabs;
|
||||
const tabs = extensionStubWithWithRegisteredTab.rendererOptions?.appPreferenceTabs;
|
||||
const tabTitle = tabs && tabs[0].title;
|
||||
|
||||
expect(pageTitle?.innerHTML).toBe(tabTitle);
|
||||
@ -246,11 +232,8 @@ describe("preferences - navigation to extension specific preferences", () => {
|
||||
"tab-link-for-extension-hello-world-tab-page-id-nav-item-logs-extension-tab",
|
||||
];
|
||||
|
||||
beforeEach(async () => {
|
||||
const getRendererExtensionFake = getRendererExtensionFakeFor(applicationBuilder);
|
||||
const extension = getRendererExtensionFake(extensionStubWithWithRegisteredTabs);
|
||||
|
||||
await applicationBuilder.extensions.renderer.enable(extension);
|
||||
beforeEach(() => {
|
||||
builder.extensions.enable(extensionStubWithWithRegisteredTabs);
|
||||
});
|
||||
|
||||
it.each(tabs)("shows '%s' tab in general area", (tab) => {
|
||||
@ -261,12 +244,8 @@ describe("preferences - navigation to extension specific preferences", () => {
|
||||
});
|
||||
|
||||
describe("given extensions with tabs having same id", () => {
|
||||
beforeEach(async () => {
|
||||
const getRendererExtensionFake = getRendererExtensionFakeFor(applicationBuilder);
|
||||
const extension = getRendererExtensionFake(extensionStubWithWithRegisteredTab);
|
||||
const otherExtension = getRendererExtensionFake(extensionStubWithWithSameRegisteredTab);
|
||||
|
||||
await applicationBuilder.extensions.renderer.enable(extension, otherExtension);
|
||||
beforeEach(() => {
|
||||
builder.extensions.enable(extensionStubWithWithRegisteredTab, extensionStubWithWithSameRegisteredTab);
|
||||
});
|
||||
|
||||
it("shows tab from the first extension", () => {
|
||||
@ -283,7 +262,7 @@ describe("preferences - navigation to extension specific preferences", () => {
|
||||
|
||||
describe("when navigating to first extension tab", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.preferences.navigation.click("extension-registered-tab-page-id-nav-item-metrics-extension-tab");
|
||||
builder.preferences.navigation.click("extension-registered-tab-page-id-nav-item-metrics-extension-tab");
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -305,7 +284,7 @@ describe("preferences - navigation to extension specific preferences", () => {
|
||||
|
||||
describe("when navigating to second extension tab", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.preferences.navigation.click("extension-duplicated-tab-page-id-nav-item-metrics-extension-tab");
|
||||
builder.preferences.navigation.click("extension-duplicated-tab-page-id-nav-item-metrics-extension-tab");
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -329,27 +308,21 @@ describe("preferences - navigation to extension specific preferences", () => {
|
||||
|
||||
describe("when navigating to extension specific tab", () => {
|
||||
let rendered: RenderResult;
|
||||
let di: DiContainer;
|
||||
|
||||
beforeEach(async () => {
|
||||
di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
const extensionRoute = windowDi.inject(extensionPreferencesRouteInjectable);
|
||||
|
||||
const getRendererExtensionFake = getRendererExtensionFakeFor(applicationBuilder);
|
||||
const extension = getRendererExtensionFake(extensionStubWithWithSameRegisteredTab);
|
||||
const otherExtension = getRendererExtensionFake(extensionUsingSomeoneElseTab);
|
||||
|
||||
applicationBuilder.beforeRender(() => {
|
||||
const extensionRoute = di.inject(extensionPreferencesRouteInjectable);
|
||||
const params = { parameters: {
|
||||
extensionId: "duplicated-tab-page-id",
|
||||
tabId: "metrics-extension-tab",
|
||||
}};
|
||||
|
||||
applicationBuilder.preferences.navigateTo(extensionRoute, params);
|
||||
builder.preferences.navigateTo(extensionRoute, params);
|
||||
});
|
||||
|
||||
await applicationBuilder.extensions.renderer.enable(extension, otherExtension);
|
||||
rendered = await applicationBuilder.render();
|
||||
builder.extensions.enable(extensionStubWithWithSameRegisteredTab, extensionUsingSomeoneElseTab);
|
||||
rendered = await builder.render();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -367,27 +340,20 @@ describe("preferences - navigation to extension specific preferences", () => {
|
||||
|
||||
describe("when navigating to someone else extension specific tab", () => {
|
||||
let rendered: RenderResult;
|
||||
let di: DiContainer;
|
||||
|
||||
beforeEach(async () => {
|
||||
di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||
|
||||
const getRendererExtensionFake = getRendererExtensionFakeFor(applicationBuilder);
|
||||
const extension = getRendererExtensionFake(extensionStubWithWithSameRegisteredTab);
|
||||
const extensionUsingOtherTab = getRendererExtensionFake(extensionUsingSomeoneElseTab);
|
||||
|
||||
applicationBuilder.beforeRender(() => {
|
||||
const extensionRoute = di.inject(extensionPreferencesRouteInjectable);
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
const extensionRoute = windowDi.inject(extensionPreferencesRouteInjectable);
|
||||
const params = { parameters: {
|
||||
extensionId: "extension-using-someone-else-tab-id",
|
||||
tabId: "metrics-extension-tab",
|
||||
}};
|
||||
|
||||
applicationBuilder.preferences.navigateTo(extensionRoute, params);
|
||||
builder.preferences.navigateTo(extensionRoute, params);
|
||||
});
|
||||
|
||||
await applicationBuilder.extensions.renderer.enable(extension, extensionUsingOtherTab);
|
||||
rendered = await applicationBuilder.render();
|
||||
builder.extensions.enable(extensionStubWithWithSameRegisteredTab, extensionUsingSomeoneElseTab);
|
||||
rendered = await builder.render();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -396,193 +362,208 @@ describe("preferences - navigation to extension specific preferences", () => {
|
||||
});
|
||||
});
|
||||
|
||||
const extensionStubWithExtensionSpecificPreferenceItems: FakeExtensionData = {
|
||||
const extensionStubWithExtensionSpecificPreferenceItems: FakeExtensionOptions = {
|
||||
id: "some-test-extension-id",
|
||||
name: "some-test-extension-id",
|
||||
appPreferences: [
|
||||
{
|
||||
title: "Some preference item",
|
||||
id: "some-preference-item-id",
|
||||
|
||||
components: {
|
||||
Hint: () => <div data-testid="some-preference-item-hint" />,
|
||||
Input: () => <div data-testid="some-preference-item-input" />,
|
||||
rendererOptions: {
|
||||
appPreferences: [
|
||||
{
|
||||
title: "Some preference item",
|
||||
id: "some-preference-item-id",
|
||||
|
||||
components: {
|
||||
Hint: () => <div data-testid="some-preference-item-hint" />,
|
||||
Input: () => <div data-testid="some-preference-item-input" />,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
title: "irrelevant",
|
||||
id: "some-unrelated-preference-item-id",
|
||||
showInPreferencesTab: "some-tab",
|
||||
{
|
||||
title: "irrelevant",
|
||||
id: "some-unrelated-preference-item-id",
|
||||
showInPreferencesTab: "some-tab",
|
||||
|
||||
components: {
|
||||
Hint: () => <div />,
|
||||
Input: () => <div />,
|
||||
components: {
|
||||
Hint: () => <div />,
|
||||
Input: () => <div />,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const someOtherExtensionStubWithExtensionSpecificPreferenceItems: FakeExtensionData = {
|
||||
const someOtherExtensionStubWithExtensionSpecificPreferenceItems: FakeExtensionOptions = {
|
||||
id: "some-other-test-extension-id",
|
||||
name: "some-other-test-extension-id",
|
||||
|
||||
appPreferences: [
|
||||
{
|
||||
title: "Test preference item",
|
||||
id: "some-other-preference-item-id",
|
||||
rendererOptions: {
|
||||
appPreferences: [
|
||||
{
|
||||
title: "Test preference item",
|
||||
id: "some-other-preference-item-id",
|
||||
|
||||
components: {
|
||||
Hint: () => <div data-testid="some-other-preference-item-hint" />,
|
||||
Input: () => <div data-testid="some-other-preference-item-input" />,
|
||||
components: {
|
||||
Hint: () => <div data-testid="some-other-preference-item-hint" />,
|
||||
Input: () => <div data-testid="some-other-preference-item-input" />,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const extensionStubWithoutPreferences: FakeExtensionData = {
|
||||
const extensionStubWithoutPreferences: FakeExtensionOptions = {
|
||||
id: "without-preferences-id",
|
||||
name: "without-preferences-id",
|
||||
};
|
||||
|
||||
const extensionStubWithShowInPreferencesTab: FakeExtensionData = {
|
||||
const extensionStubWithShowInPreferencesTab: FakeExtensionOptions = {
|
||||
id: "specified-preferences-page-id",
|
||||
name: "specified-preferences-page-name",
|
||||
|
||||
appPreferences: [
|
||||
{
|
||||
title: "Test preference item",
|
||||
id: "very-other-preference-item-id",
|
||||
showInPreferencesTab: "some-tab",
|
||||
rendererOptions: {
|
||||
appPreferences: [
|
||||
{
|
||||
title: "Test preference item",
|
||||
id: "very-other-preference-item-id",
|
||||
showInPreferencesTab: "some-tab",
|
||||
|
||||
components: {
|
||||
Hint: () => <div data-testid="very-other-preference-item-hint" />,
|
||||
Input: () => <div data-testid="very-other-preference-item-input" />,
|
||||
components: {
|
||||
Hint: () => <div data-testid="very-other-preference-item-hint" />,
|
||||
Input: () => <div data-testid="very-other-preference-item-input" />,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const extensionStubWithWithRegisteredTab: FakeExtensionData = {
|
||||
const extensionStubWithWithRegisteredTab: FakeExtensionOptions = {
|
||||
id: "registered-tab-page-id",
|
||||
name: "registered-tab-page-id",
|
||||
|
||||
appPreferences: [
|
||||
{
|
||||
title: "License item",
|
||||
id: "metrics-preference-item-id",
|
||||
showInPreferencesTab: "metrics-extension-tab",
|
||||
rendererOptions: {
|
||||
appPreferences: [
|
||||
{
|
||||
title: "License item",
|
||||
id: "metrics-preference-item-id",
|
||||
showInPreferencesTab: "metrics-extension-tab",
|
||||
|
||||
components: {
|
||||
Hint: () => <div data-testid="metrics-preference-item-hint" />,
|
||||
Input: () => <div data-testid="metrics-preference-item-input" />,
|
||||
components: {
|
||||
Hint: () => <div data-testid="metrics-preference-item-hint" />,
|
||||
Input: () => <div data-testid="metrics-preference-item-input" />,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Menu item",
|
||||
id: "menu-preference-item-id",
|
||||
showInPreferencesTab: "menu-extension-tab",
|
||||
{
|
||||
title: "Menu item",
|
||||
id: "menu-preference-item-id",
|
||||
showInPreferencesTab: "menu-extension-tab",
|
||||
|
||||
components: {
|
||||
Hint: () => <div data-testid="menu-preference-item-hint" />,
|
||||
Input: () => <div data-testid="menu-preference-item-input" />,
|
||||
components: {
|
||||
Hint: () => <div data-testid="menu-preference-item-hint" />,
|
||||
Input: () => <div data-testid="menu-preference-item-input" />,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Survey item",
|
||||
id: "survey-preference-item-id",
|
||||
showInPreferencesTab: "survey-extension-tab",
|
||||
{
|
||||
title: "Survey item",
|
||||
id: "survey-preference-item-id",
|
||||
showInPreferencesTab: "survey-extension-tab",
|
||||
|
||||
components: {
|
||||
Hint: () => <div data-testid="survey-preference-item-hint" />,
|
||||
Input: () => <div data-testid="survey-preference-item-input" />,
|
||||
components: {
|
||||
Hint: () => <div data-testid="survey-preference-item-hint" />,
|
||||
Input: () => <div data-testid="survey-preference-item-input" />,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
|
||||
appPreferenceTabs: [{
|
||||
title: "Metrics tab",
|
||||
id: "metrics-extension-tab",
|
||||
orderNumber: 100,
|
||||
}],
|
||||
appPreferenceTabs: [{
|
||||
title: "Metrics tab",
|
||||
id: "metrics-extension-tab",
|
||||
orderNumber: 100,
|
||||
}],
|
||||
},
|
||||
};
|
||||
|
||||
const extensionStubWithWithRegisteredTabs: FakeExtensionData = {
|
||||
const extensionStubWithWithRegisteredTabs: FakeExtensionOptions = {
|
||||
id: "hello-world-tab-page-id",
|
||||
name: "hello-world-tab-page-id",
|
||||
|
||||
appPreferences: [
|
||||
{
|
||||
title: "Hello world",
|
||||
id: "hello-preference-item-id",
|
||||
showInPreferencesTab: "hello-extension-tab",
|
||||
rendererOptions: {
|
||||
appPreferences: [
|
||||
{
|
||||
title: "Hello world",
|
||||
id: "hello-preference-item-id",
|
||||
showInPreferencesTab: "hello-extension-tab",
|
||||
|
||||
components: {
|
||||
Hint: () => <div data-testid="hello-preference-item-hint" />,
|
||||
Input: () => <div data-testid="hello-preference-item-input" />,
|
||||
components: {
|
||||
Hint: () => <div data-testid="hello-preference-item-hint" />,
|
||||
Input: () => <div data-testid="hello-preference-item-input" />,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Logs",
|
||||
id: "logs-preference-item-id",
|
||||
showInPreferencesTab: "logs-extension-tab",
|
||||
{
|
||||
title: "Logs",
|
||||
id: "logs-preference-item-id",
|
||||
showInPreferencesTab: "logs-extension-tab",
|
||||
|
||||
components: {
|
||||
Hint: () => <div data-testid="logs-preference-item-hint" />,
|
||||
Input: () => <div data-testid="logs-preference-item-input" />,
|
||||
components: {
|
||||
Hint: () => <div data-testid="logs-preference-item-hint" />,
|
||||
Input: () => <div data-testid="logs-preference-item-input" />,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
|
||||
appPreferenceTabs: [{
|
||||
title: "Metrics tab",
|
||||
id: "hello-extension-tab",
|
||||
orderNumber: 100,
|
||||
}, {
|
||||
title: "Logs tab",
|
||||
id: "logs-extension-tab",
|
||||
orderNumber: 200,
|
||||
}],
|
||||
appPreferenceTabs: [{
|
||||
title: "Metrics tab",
|
||||
id: "hello-extension-tab",
|
||||
orderNumber: 100,
|
||||
}, {
|
||||
title: "Logs tab",
|
||||
id: "logs-extension-tab",
|
||||
orderNumber: 200,
|
||||
}],
|
||||
},
|
||||
};
|
||||
|
||||
const extensionStubWithWithSameRegisteredTab: FakeExtensionData = {
|
||||
const extensionStubWithWithSameRegisteredTab: FakeExtensionOptions = {
|
||||
id: "duplicated-tab-page-id",
|
||||
name: "duplicated-tab-page-id",
|
||||
|
||||
appPreferences: [
|
||||
{
|
||||
title: "Another metrics",
|
||||
id: "another-metrics-preference-item-id",
|
||||
showInPreferencesTab: "metrics-extension-tab",
|
||||
rendererOptions: {
|
||||
appPreferences: [
|
||||
{
|
||||
title: "Another metrics",
|
||||
id: "another-metrics-preference-item-id",
|
||||
showInPreferencesTab: "metrics-extension-tab",
|
||||
|
||||
components: {
|
||||
Hint: () => <div data-testid="another-metrics-preference-item-hint" />,
|
||||
Input: () => <div data-testid="another-metrics-preference-item-input" />,
|
||||
components: {
|
||||
Hint: () => <div data-testid="another-metrics-preference-item-hint" />,
|
||||
Input: () => <div data-testid="another-metrics-preference-item-input" />,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
|
||||
appPreferenceTabs: [{
|
||||
title: "Metrics tab",
|
||||
id: "metrics-extension-tab",
|
||||
orderNumber: 100,
|
||||
}],
|
||||
appPreferenceTabs: [{
|
||||
title: "Metrics tab",
|
||||
id: "metrics-extension-tab",
|
||||
orderNumber: 100,
|
||||
}],
|
||||
},
|
||||
};
|
||||
|
||||
const extensionUsingSomeoneElseTab: FakeExtensionData = {
|
||||
const extensionUsingSomeoneElseTab: FakeExtensionOptions = {
|
||||
id: "extension-using-someone-else-tab-id",
|
||||
name: "extension-using-someone-else-tab-id",
|
||||
|
||||
appPreferences: [
|
||||
{
|
||||
title: "My preferences",
|
||||
id: "my-preferences-item-id",
|
||||
showInPreferencesTab: "metrics-extension-tab",
|
||||
rendererOptions: {
|
||||
appPreferences: [
|
||||
{
|
||||
title: "My preferences",
|
||||
id: "my-preferences-item-id",
|
||||
showInPreferencesTab: "metrics-extension-tab",
|
||||
|
||||
components: {
|
||||
Hint: () => <div data-testid="my-preferences-item-hint" />,
|
||||
Input: () => <div data-testid="my-preferences-item-input" />,
|
||||
components: {
|
||||
Hint: () => <div data-testid="my-preferences-item-hint" />,
|
||||
Input: () => <div data-testid="my-preferences-item-input" />,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
@ -9,30 +9,32 @@ import callForPublicHelmRepositoriesInjectable from "../../renderer/components/+
|
||||
import getActiveHelmRepositoriesInjectable from "../../main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories.injectable";
|
||||
|
||||
describe("preferences - navigation to kubernetes preferences", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let builder: ApplicationBuilder;
|
||||
|
||||
beforeEach(() => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
builder = getApplicationBuilder();
|
||||
});
|
||||
|
||||
describe("given in preferences, when rendered", () => {
|
||||
let rendered: RenderResult;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeApplicationStart(({ rendererDi, mainDi }) => {
|
||||
rendererDi.override(callForPublicHelmRepositoriesInjectable, () => async () => []);
|
||||
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
mainDi.override(
|
||||
getActiveHelmRepositoriesInjectable,
|
||||
() => async () => ({ callWasSuccessful: true, response: [] }),
|
||||
);
|
||||
});
|
||||
|
||||
applicationBuilder.beforeRender(() => {
|
||||
applicationBuilder.preferences.navigate();
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.override(callForPublicHelmRepositoriesInjectable, () => async () => []);
|
||||
});
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
builder.beforeWindowStart(() => {
|
||||
builder.preferences.navigate();
|
||||
});
|
||||
|
||||
rendered = await builder.render();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -47,7 +49,7 @@ describe("preferences - navigation to kubernetes preferences", () => {
|
||||
|
||||
describe("when navigating to kubernetes preferences using navigation", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.preferences.navigation.click("kubernetes");
|
||||
builder.preferences.navigation.click("kubernetes");
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
|
||||
@ -17,7 +17,7 @@ describe("preferences - navigation to proxy preferences", () => {
|
||||
let rendered: RenderResult;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeRender(() => {
|
||||
applicationBuilder.beforeWindowStart(() => {
|
||||
applicationBuilder.preferences.navigate();
|
||||
});
|
||||
|
||||
|
||||
@ -6,27 +6,26 @@ import type { RenderResult } from "@testing-library/react";
|
||||
import React from "react";
|
||||
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import type { FakeExtensionData } from "../../renderer/components/test-utils/get-renderer-extension-fake";
|
||||
import { getRendererExtensionFakeFor } from "../../renderer/components/test-utils/get-renderer-extension-fake";
|
||||
import navigateToTelemetryPreferencesInjectable from "../../common/front-end-routing/routes/preferences/telemetry/navigate-to-telemetry-preferences.injectable";
|
||||
import sentryDnsUrlInjectable from "../../renderer/components/+preferences/sentry-dns-url.injectable";
|
||||
import type { FakeExtensionOptions } from "../../renderer/components/test-utils/get-extension-fake";
|
||||
|
||||
describe("preferences - navigation to telemetry preferences", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let builder: ApplicationBuilder;
|
||||
|
||||
beforeEach(() => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
builder = getApplicationBuilder();
|
||||
});
|
||||
|
||||
describe("given in preferences, when rendered", () => {
|
||||
let rendered: RenderResult;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeRender(() => {
|
||||
applicationBuilder.preferences.navigate();
|
||||
builder.beforeWindowStart(() => {
|
||||
builder.preferences.navigate();
|
||||
});
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
rendered = await builder.render();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -47,11 +46,8 @@ describe("preferences - navigation to telemetry preferences", () => {
|
||||
|
||||
describe("when extension with telemetry preference items gets enabled", () => {
|
||||
beforeEach(() => {
|
||||
const getRendererExtensionFake = getRendererExtensionFakeFor(applicationBuilder);
|
||||
const testExtensionWithTelemetryPreferenceItems = getRendererExtensionFake(extensionStubWithTelemetryPreferenceItems);
|
||||
|
||||
applicationBuilder.extensions.renderer.enable(
|
||||
testExtensionWithTelemetryPreferenceItems,
|
||||
builder.extensions.enable(
|
||||
extensionStubWithTelemetryPreferenceItems,
|
||||
);
|
||||
});
|
||||
|
||||
@ -67,7 +63,7 @@ describe("preferences - navigation to telemetry preferences", () => {
|
||||
|
||||
describe("when clicking link to telemetry preferences from navigation", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.preferences.navigation.click("telemetry");
|
||||
builder.preferences.navigation.click("telemetry");
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -91,23 +87,21 @@ describe("preferences - navigation to telemetry preferences", () => {
|
||||
});
|
||||
|
||||
it("given extensions but no telemetry preference items, does not show link for telemetry preferences", () => {
|
||||
const getRendererExtensionFake = getRendererExtensionFakeFor(applicationBuilder);
|
||||
const testExtensionWithTelemetryPreferenceItems = getRendererExtensionFake({
|
||||
builder.extensions.enable({
|
||||
id: "some-test-extension-id",
|
||||
name: "some-test-extension-name",
|
||||
appPreferences: [
|
||||
{
|
||||
title: "irrelevant",
|
||||
id: "irrelevant",
|
||||
showInPreferencesTab: "not-telemetry",
|
||||
components: { Hint: () => <div />, Input: () => <div /> },
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
applicationBuilder.extensions.renderer.enable(
|
||||
testExtensionWithTelemetryPreferenceItems,
|
||||
);
|
||||
rendererOptions: {
|
||||
appPreferences: [
|
||||
{
|
||||
title: "irrelevant",
|
||||
id: "irrelevant",
|
||||
showInPreferencesTab: "not-telemetry",
|
||||
components: { Hint: () => <div />, Input: () => <div /> },
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const actual = rendered.queryByTestId("tab-link-for-telemetry");
|
||||
|
||||
@ -119,18 +113,18 @@ describe("preferences - navigation to telemetry preferences", () => {
|
||||
let rendered: RenderResult;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeApplicationStart(({ rendererDi }) => {
|
||||
rendererDi.override(sentryDnsUrlInjectable, () => "some-sentry-dns-url");
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.override(sentryDnsUrlInjectable, () => "some-sentry-dns-url");
|
||||
});
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
rendered = await builder.render();
|
||||
|
||||
applicationBuilder.preferences.navigate();
|
||||
builder.preferences.navigate();
|
||||
});
|
||||
|
||||
describe("when navigating to telemetry preferences", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.preferences.navigation.click("telemetry");
|
||||
builder.preferences.navigation.click("telemetry");
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -149,13 +143,15 @@ describe("preferences - navigation to telemetry preferences", () => {
|
||||
let rendered: RenderResult;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeApplicationStart(({ rendererDi }) => {
|
||||
rendererDi.override(sentryDnsUrlInjectable, () => null);
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.override(sentryDnsUrlInjectable, () => null);
|
||||
});
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
rendered = await builder.render();
|
||||
|
||||
const navigateToTelemetryPreferences = applicationBuilder.dis.rendererDi.inject(navigateToTelemetryPreferencesInjectable);
|
||||
const windowDi = builder.applicationWindow.only.di;
|
||||
|
||||
const navigateToTelemetryPreferences = windowDi.inject(navigateToTelemetryPreferencesInjectable);
|
||||
|
||||
navigateToTelemetryPreferences();
|
||||
});
|
||||
@ -172,19 +168,22 @@ describe("preferences - navigation to telemetry preferences", () => {
|
||||
});
|
||||
});
|
||||
|
||||
const extensionStubWithTelemetryPreferenceItems: FakeExtensionData = {
|
||||
const extensionStubWithTelemetryPreferenceItems: FakeExtensionOptions = {
|
||||
id: "some-test-extension-id",
|
||||
name: "some-test-extension-name",
|
||||
appPreferences: [
|
||||
{
|
||||
title: "Some telemetry-preference item",
|
||||
id: "some-telemetry-preference-item-id",
|
||||
showInPreferencesTab: "telemetry",
|
||||
|
||||
components: {
|
||||
Hint: () => <div data-testid="some-preference-item-hint" />,
|
||||
Input: () => <div data-testid="some-preference-item-input" />,
|
||||
rendererOptions: {
|
||||
appPreferences: [
|
||||
{
|
||||
title: "Some telemetry-preference item",
|
||||
id: "some-telemetry-preference-item-id",
|
||||
showInPreferencesTab: "telemetry",
|
||||
|
||||
components: {
|
||||
Hint: () => <div data-testid="some-preference-item-hint" />,
|
||||
Input: () => <div data-testid="some-preference-item-input" />,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
@ -17,7 +17,7 @@ describe("preferences - navigation to terminal preferences", () => {
|
||||
let rendered: RenderResult;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeRender(() => {
|
||||
applicationBuilder.beforeWindowStart(() => {
|
||||
applicationBuilder.preferences.navigate();
|
||||
});
|
||||
|
||||
|
||||
@ -5,19 +5,18 @@
|
||||
|
||||
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { lensWindowInjectionToken } from "../../main/start-main-application/lens-window/application-window/lens-window-injection-token";
|
||||
import applicationWindowInjectable from "../../main/start-main-application/lens-window/application-window/application-window.injectable";
|
||||
import createElectronWindowForInjectable from "../../main/start-main-application/lens-window/application-window/create-electron-window.injectable";
|
||||
import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import type { ElectronWindow, LensWindowConfiguration } from "../../main/start-main-application/lens-window/application-window/create-lens-window.injectable";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import type { LensWindow } from "../../main/start-main-application/lens-window/application-window/create-lens-window.injectable";
|
||||
import lensResourcesDirInjectable from "../../common/vars/lens-resources-dir.injectable";
|
||||
import focusApplicationInjectable from "../../main/electron-app/features/focus-application.injectable";
|
||||
import type { CreateElectronWindow } from "../../main/start-main-application/lens-window/application-window/create-electron-window.injectable";
|
||||
import createElectronWindowInjectable from "../../main/start-main-application/lens-window/application-window/create-electron-window.injectable";
|
||||
import splashWindowInjectable from "../../main/start-main-application/lens-window/splash-window/splash-window.injectable";
|
||||
|
||||
describe("opening application window using tray", () => {
|
||||
describe("given application has started", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let builder: ApplicationBuilder;
|
||||
let createElectronWindowMock: jest.Mock;
|
||||
let expectWindowsToBeOpen: (windowIds: string[]) => void;
|
||||
let callForSplashWindowHtmlMock: AsyncFnMock<() => Promise<void>>;
|
||||
@ -30,71 +29,66 @@ describe("opening application window using tray", () => {
|
||||
|
||||
focusApplicationMock = jest.fn();
|
||||
|
||||
applicationBuilder = getApplicationBuilder().beforeApplicationStart(
|
||||
({ mainDi }) => {
|
||||
mainDi.override(focusApplicationInjectable, () => focusApplicationMock);
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
mainDi.override(lensResourcesDirInjectable, () => "some-lens-resources-directory");
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
mainDi.override(focusApplicationInjectable, () => focusApplicationMock);
|
||||
|
||||
const loadFileMock = jest
|
||||
.fn(callForSplashWindowHtmlMock)
|
||||
.mockImplementationOnce(() => Promise.resolve());
|
||||
mainDi.override(
|
||||
lensResourcesDirInjectable,
|
||||
() => "some-lens-resources-directory",
|
||||
);
|
||||
|
||||
const loadUrlMock = jest
|
||||
.fn(callForApplicationWindowHtmlMock)
|
||||
.mockImplementationOnce(() => Promise.resolve());
|
||||
const loadFileMock = jest
|
||||
.fn(callForSplashWindowHtmlMock)
|
||||
.mockImplementationOnce(() => Promise.resolve());
|
||||
|
||||
createElectronWindowMock = jest.fn((configuration: LensWindowConfiguration) =>
|
||||
({
|
||||
splash: {
|
||||
send: () => {},
|
||||
close: () => {},
|
||||
show: () => {},
|
||||
loadFile: loadFileMock,
|
||||
loadUrl: () => { throw new Error("Should never come here"); },
|
||||
},
|
||||
const loadUrlMock = jest
|
||||
.fn(callForApplicationWindowHtmlMock)
|
||||
.mockImplementationOnce(() => Promise.resolve());
|
||||
|
||||
"only-application-window": {
|
||||
send: () => {},
|
||||
close: () => {},
|
||||
show: () => {},
|
||||
loadFile: () => { throw new Error("Should never come here"); },
|
||||
loadUrl: loadUrlMock,
|
||||
},
|
||||
}[configuration.id] as ElectronWindow));
|
||||
createElectronWindowMock = jest.fn((toBeDecorated): CreateElectronWindow => (configuration) => {
|
||||
const browserWindow = toBeDecorated(configuration);
|
||||
|
||||
mainDi.override(
|
||||
createElectronWindowForInjectable,
|
||||
if (configuration.id === "splash") {
|
||||
return { ...browserWindow, loadFile: loadFileMock };
|
||||
}
|
||||
|
||||
() => createElectronWindowMock,
|
||||
);
|
||||
if (configuration.id === "first-application-window") {
|
||||
return { ...browserWindow, loadUrl: loadUrlMock };
|
||||
}
|
||||
|
||||
expectWindowsToBeOpen = expectWindowsToBeOpenFor(mainDi);
|
||||
},
|
||||
);
|
||||
return browserWindow;
|
||||
});
|
||||
|
||||
await applicationBuilder.render();
|
||||
(mainDi as any).decorateFunction(
|
||||
createElectronWindowInjectable,
|
||||
createElectronWindowMock,
|
||||
);
|
||||
|
||||
expectWindowsToBeOpen = expectWindowsToBeOpenFor(builder);
|
||||
});
|
||||
|
||||
await builder.render();
|
||||
});
|
||||
|
||||
it("only an application window is open", () => {
|
||||
expectWindowsToBeOpen(["only-application-window"]);
|
||||
it("only the first application window is open", () => {
|
||||
expectWindowsToBeOpen(["first-application-window"]);
|
||||
});
|
||||
|
||||
describe("when an attempt to reopen the already started application is made using tray", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.tray.click("open-app");
|
||||
builder.tray.click("open-app");
|
||||
});
|
||||
|
||||
it("still shows only the application window", () => {
|
||||
expectWindowsToBeOpen(["only-application-window"]);
|
||||
expectWindowsToBeOpen(["first-application-window"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when the application window is closed", () => {
|
||||
describe("when the first application window is closed", () => {
|
||||
beforeEach(() => {
|
||||
const applicationWindow = applicationBuilder.dis.mainDi.inject(
|
||||
applicationWindowInjectable,
|
||||
);
|
||||
const applicationWindow = builder.applicationWindow.only;
|
||||
|
||||
applicationWindow.close();
|
||||
});
|
||||
@ -110,7 +104,7 @@ describe("opening application window using tray", () => {
|
||||
callForSplashWindowHtmlMock.mockClear();
|
||||
callForApplicationWindowHtmlMock.mockClear();
|
||||
|
||||
applicationBuilder.tray.click("open-app");
|
||||
builder.tray.click("open-app");
|
||||
});
|
||||
|
||||
it("focuses the application", () => {
|
||||
@ -143,7 +137,7 @@ describe("opening application window using tray", () => {
|
||||
callForApplicationWindowHtmlMock.mockClear();
|
||||
callForSplashWindowHtmlMock.mockClear();
|
||||
|
||||
applicationBuilder.tray.click("open-app");
|
||||
builder.tray.click("open-app");
|
||||
});
|
||||
|
||||
it("does not load contents of splash window again", () => {
|
||||
@ -155,7 +149,7 @@ describe("opening application window using tray", () => {
|
||||
});
|
||||
|
||||
it("shows just the blank application window to permit developer tool access", () => {
|
||||
expectWindowsToBeOpen(["only-application-window"]);
|
||||
expectWindowsToBeOpen(["first-application-window"]);
|
||||
});
|
||||
});
|
||||
|
||||
@ -165,7 +159,7 @@ describe("opening application window using tray", () => {
|
||||
});
|
||||
|
||||
it("shows just the application window", () => {
|
||||
expectWindowsToBeOpen(["only-application-window"]);
|
||||
expectWindowsToBeOpen(["first-application-window"]);
|
||||
});
|
||||
|
||||
describe("when reopening the application using tray", () => {
|
||||
@ -173,11 +167,11 @@ describe("opening application window using tray", () => {
|
||||
callForSplashWindowHtmlMock.mockClear();
|
||||
callForApplicationWindowHtmlMock.mockClear();
|
||||
|
||||
applicationBuilder.tray.click("open-app");
|
||||
builder.tray.click("open-app");
|
||||
});
|
||||
|
||||
it("still shows just the application window", () => {
|
||||
expectWindowsToBeOpen(["only-application-window"]);
|
||||
expectWindowsToBeOpen(["first-application-window"]);
|
||||
});
|
||||
|
||||
it("does not load HTML for splash window again", () => {
|
||||
@ -195,7 +189,7 @@ describe("opening application window using tray", () => {
|
||||
beforeEach(() => {
|
||||
createElectronWindowMock.mockClear();
|
||||
|
||||
applicationBuilder.tray.click("open-app");
|
||||
builder.tray.click("open-app");
|
||||
});
|
||||
|
||||
it("does not open any new windows", () => {
|
||||
@ -215,14 +209,14 @@ describe("opening application window using tray", () => {
|
||||
it("when opening of application window finishes, only an application window is open", async () => {
|
||||
await callForApplicationWindowHtmlMock.resolve();
|
||||
|
||||
expectWindowsToBeOpen(["only-application-window"]);
|
||||
expectWindowsToBeOpen(["first-application-window"]);
|
||||
});
|
||||
|
||||
describe("given opening of application window has not finished yet, but another attempt to open the application is made", () => {
|
||||
beforeEach(() => {
|
||||
createElectronWindowMock.mockClear();
|
||||
|
||||
applicationBuilder.tray.click("open-app");
|
||||
builder.tray.click("open-app");
|
||||
});
|
||||
|
||||
it("does not open any new windows", () => {
|
||||
@ -232,7 +226,7 @@ describe("opening application window using tray", () => {
|
||||
it("when opening finishes, only an application window is open", async () => {
|
||||
await callForApplicationWindowHtmlMock.resolve();
|
||||
|
||||
expectWindowsToBeOpen(["only-application-window"]);
|
||||
expectWindowsToBeOpen(["first-application-window"]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -241,10 +235,14 @@ describe("opening application window using tray", () => {
|
||||
});
|
||||
});
|
||||
|
||||
const expectWindowsToBeOpenFor = (di: DiContainer) => (windowIds: string[]) => {
|
||||
const windows = di.injectMany(lensWindowInjectionToken);
|
||||
const expectWindowsToBeOpenFor =
|
||||
(builder: ApplicationBuilder) => (windowIds: string[]) => {
|
||||
const windows: LensWindow[] = [
|
||||
builder.mainDi.inject(splashWindowInjectable),
|
||||
...builder.applicationWindow.getAll(),
|
||||
];
|
||||
|
||||
expect(
|
||||
windows.filter((window) => window.isVisible).map((window) => window.id),
|
||||
).toEqual(windowIds);
|
||||
};
|
||||
expect(
|
||||
windows.filter((window) => window.isVisible).map((window) => window.id),
|
||||
).toEqual(windowIds);
|
||||
};
|
||||
|
||||
@ -6,7 +6,6 @@
|
||||
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import type { ClusterManager } from "../../main/cluster-manager";
|
||||
import { lensWindowInjectionToken } from "../../main/start-main-application/lens-window/application-window/lens-window-injection-token";
|
||||
import exitAppInjectable from "../../main/electron-app/features/exit-app.injectable";
|
||||
import clusterManagerInjectable from "../../main/cluster-manager.injectable";
|
||||
import stopServicesAndExitAppInjectable from "../../main/stop-services-and-exit-app.injectable";
|
||||
@ -14,15 +13,17 @@ import { advanceFakeTime, useFakeTime } from "../../common/test-utils/use-fake-t
|
||||
|
||||
describe("quitting the app using application menu", () => {
|
||||
describe("given application has started", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let builder: ApplicationBuilder;
|
||||
let clusterManagerStub: ClusterManager;
|
||||
let exitAppMock: jest.Mock;
|
||||
|
||||
beforeEach(async () => {
|
||||
useFakeTime("2015-10-21T07:28:00Z");
|
||||
|
||||
applicationBuilder = getApplicationBuilder().beforeApplicationStart(
|
||||
({ mainDi }) => {
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
builder.beforeApplicationStart(
|
||||
(mainDi) => {
|
||||
mainDi.unoverride(stopServicesAndExitAppInjectable);
|
||||
|
||||
clusterManagerStub = { stop: jest.fn() } as unknown as ClusterManager;
|
||||
@ -33,38 +34,24 @@ describe("quitting the app using application menu", () => {
|
||||
},
|
||||
);
|
||||
|
||||
await applicationBuilder.render();
|
||||
await builder.render();
|
||||
});
|
||||
|
||||
it("only an application window is open", () => {
|
||||
const windows = applicationBuilder.dis.mainDi.injectMany(
|
||||
lensWindowInjectionToken,
|
||||
);
|
||||
it("first application window is open", () => {
|
||||
const windows = builder.applicationWindow.getAll();
|
||||
|
||||
expect(
|
||||
windows.map((window) => ({ id: window.id, visible: window.isVisible })),
|
||||
).toEqual([
|
||||
{ id: "only-application-window", visible: true },
|
||||
{ id: "splash", visible: false },
|
||||
]);
|
||||
expect(windows.map((window) => window.id)).toEqual(["first-application-window"]);
|
||||
});
|
||||
|
||||
describe("when application is quit", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.applicationMenu.click("root.quit");
|
||||
builder.applicationMenu.click("root.quit");
|
||||
});
|
||||
|
||||
it("closes all windows", () => {
|
||||
const windows = applicationBuilder.dis.mainDi.injectMany(
|
||||
lensWindowInjectionToken,
|
||||
);
|
||||
const windows = builder.applicationWindow.getAll();
|
||||
|
||||
expect(
|
||||
windows.map((window) => ({ id: window.id, visible: window.isVisible })),
|
||||
).toEqual([
|
||||
{ id: "only-application-window", visible: false },
|
||||
{ id: "splash", visible: false },
|
||||
]);
|
||||
expect(windows).toEqual([]);
|
||||
});
|
||||
|
||||
it("disconnects all clusters", () => {
|
||||
|
||||
@ -12,28 +12,28 @@ import resolveSystemProxyFromElectronInjectable from "../../main/utils/resolve-s
|
||||
import { getPromiseStatus } from "../../common/test-utils/get-promise-status";
|
||||
|
||||
describe("resolve-system-proxy", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let builder: ApplicationBuilder;
|
||||
let actualPromise: Promise<string>;
|
||||
let resolveSystemProxyFromElectronMock: AsyncFnMock<ResolveSystemProxy>;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
resolveSystemProxyFromElectronMock = asyncFn();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
mainDi.override(
|
||||
resolveSystemProxyFromElectronInjectable,
|
||||
() => resolveSystemProxyFromElectronMock,
|
||||
);
|
||||
});
|
||||
|
||||
await applicationBuilder.render();
|
||||
await builder.render();
|
||||
});
|
||||
|
||||
describe("given in main, when called with URL", () => {
|
||||
beforeEach(async () => {
|
||||
const resolveSystemProxyInMain = applicationBuilder.dis.mainDi.inject(
|
||||
const resolveSystemProxyInMain = builder.mainDi.inject(
|
||||
resolveSystemProxyInjectionToken,
|
||||
);
|
||||
|
||||
@ -59,7 +59,9 @@ describe("resolve-system-proxy", () => {
|
||||
|
||||
describe("given in renderer, when called with URL", () => {
|
||||
beforeEach(async () => {
|
||||
const resolveSystemProxyInRenderer = applicationBuilder.dis.rendererDi.inject(
|
||||
const windowDi = builder.applicationWindow.only.di;
|
||||
|
||||
const resolveSystemProxyInRenderer = windowDi.inject(
|
||||
resolveSystemProxyInjectionToken,
|
||||
);
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ import React from "react";
|
||||
import type { TestExtensionRenderer } from "../../../renderer/components/test-utils/get-extension-fake";
|
||||
import type { ApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getExtensionFakeFor } from "../../../renderer/components/test-utils/get-extension-fake";
|
||||
|
||||
describe("reactively disable global pages", () => {
|
||||
let builder: ApplicationBuilder;
|
||||
@ -20,11 +19,9 @@ describe("reactively disable global pages", () => {
|
||||
beforeEach(async () => {
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
const getExtensionFake = getExtensionFakeFor(builder);
|
||||
|
||||
someObservable = observable.box(false);
|
||||
|
||||
const testExtension = getExtensionFake({
|
||||
const testExtension = {
|
||||
id: "test-extension-id",
|
||||
name: "test-extension",
|
||||
|
||||
@ -37,13 +34,13 @@ describe("reactively disable global pages", () => {
|
||||
enabled: computed(() => someObservable.get()),
|
||||
}],
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
rendered = await builder.render();
|
||||
|
||||
builder.extensions.enable(testExtension);
|
||||
|
||||
rendererTestExtension = testExtension.renderer;
|
||||
rendererTestExtension = builder.extensions.get("test-extension-id").applicationWindows.only;
|
||||
});
|
||||
|
||||
it("when navigating to the page, does not show the page", () => {
|
||||
|
||||
@ -4,11 +4,10 @@
|
||||
*/
|
||||
import type { RenderResult } from "@testing-library/react";
|
||||
import React from "react";
|
||||
import type { GetRendererExtensionFake, TestExtension } from "../../renderer/components/test-utils/get-renderer-extension-fake";
|
||||
import { getRendererExtensionFakeFor } from "../../renderer/components/test-utils/get-renderer-extension-fake";
|
||||
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import getRandomIdInjectable from "../../common/utils/get-random-id.injectable";
|
||||
import type { FakeExtensionOptions } from "../../renderer/components/test-utils/get-extension-fake";
|
||||
|
||||
describe("status-bar-items-originating-from-extensions", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
@ -16,50 +15,53 @@ describe("status-bar-items-originating-from-extensions", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ rendererDi }) => {
|
||||
rendererDi.unoverride(getRandomIdInjectable);
|
||||
rendererDi.permitSideEffects(getRandomIdInjectable);
|
||||
applicationBuilder.beforeWindowStart((windowDi) => {
|
||||
windowDi.unoverride(getRandomIdInjectable);
|
||||
windowDi.permitSideEffects(getRandomIdInjectable);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when application starts", () => {
|
||||
let rendered: RenderResult;
|
||||
let getRendererExtensionFake: GetRendererExtensionFake;
|
||||
|
||||
beforeEach(async () => {
|
||||
rendered = await applicationBuilder.render();
|
||||
getRendererExtensionFake = getRendererExtensionFakeFor(applicationBuilder);
|
||||
});
|
||||
|
||||
it("when multiple extensions with status bar items are loaded, shows items in correct order", () => {
|
||||
const testExtension1 = getRendererExtensionFake({
|
||||
const testExtension1 = {
|
||||
id: "some-id",
|
||||
name: "some-name",
|
||||
|
||||
statusBarItems: [
|
||||
{
|
||||
components: {
|
||||
Item: () => <div data-testid="some-testId">extension1</div>,
|
||||
position: "right",
|
||||
rendererOptions: {
|
||||
statusBarItems: [
|
||||
{
|
||||
components: {
|
||||
Item: () => <div data-testid="some-testId">extension1</div>,
|
||||
position: "right" as const,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const testExtension2 = getRendererExtensionFake({
|
||||
const testExtension2 = {
|
||||
id: "some-other-id",
|
||||
name: "some-other-name",
|
||||
statusBarItems: [
|
||||
{
|
||||
components: {
|
||||
Item: () => <div data-testid="some-testId">extension2</div>,
|
||||
position: "right",
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
applicationBuilder.extensions.renderer.enable(testExtension1, testExtension2);
|
||||
rendererOptions: {
|
||||
statusBarItems: [
|
||||
{
|
||||
components: {
|
||||
Item: () => <div data-testid="some-testId">extension2</div>,
|
||||
position: "right" as const,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
applicationBuilder.extensions.enable(testExtension1, testExtension2);
|
||||
|
||||
const rightSide = rendered.getByTestId("status-bar-right");
|
||||
|
||||
@ -72,41 +74,44 @@ describe("status-bar-items-originating-from-extensions", () => {
|
||||
});
|
||||
|
||||
describe("when extension with status bar items is loaded", () => {
|
||||
let testExtension: TestExtension;
|
||||
let testExtensionOptions: FakeExtensionOptions;
|
||||
|
||||
beforeEach(() => {
|
||||
testExtension = getRendererExtensionFake({
|
||||
testExtensionOptions = {
|
||||
id: "some-id",
|
||||
name: "some-name",
|
||||
statusBarItems: [
|
||||
{
|
||||
item: () => <span data-testid="some-testId">right1</span>,
|
||||
},
|
||||
{
|
||||
item: () => <span data-testid="some-testId">right2</span>,
|
||||
},
|
||||
{
|
||||
components: {
|
||||
Item: () => <div data-testid="some-testId">right3</div>,
|
||||
position: "right",
|
||||
},
|
||||
},
|
||||
{
|
||||
components: {
|
||||
Item: () => <div data-testid="some-testId">left1</div>,
|
||||
position: "left",
|
||||
},
|
||||
},
|
||||
{
|
||||
components: {
|
||||
Item: () => <div data-testid="some-testId">left2</div>,
|
||||
position: "left",
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
applicationBuilder.extensions.renderer.enable(testExtension);
|
||||
rendererOptions: {
|
||||
statusBarItems: [
|
||||
{
|
||||
item: () => <span data-testid="some-testId">right1</span>,
|
||||
},
|
||||
{
|
||||
item: () => <span data-testid="some-testId">right2</span>,
|
||||
},
|
||||
{
|
||||
components: {
|
||||
Item: () => <div data-testid="some-testId">right3</div>,
|
||||
position: "right" as const,
|
||||
},
|
||||
},
|
||||
{
|
||||
components: {
|
||||
Item: () => <div data-testid="some-testId">left1</div>,
|
||||
position: "left" as const,
|
||||
},
|
||||
},
|
||||
{
|
||||
components: {
|
||||
Item: () => <div data-testid="some-testId">left2</div>,
|
||||
position: "left" as const,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
applicationBuilder.extensions.enable(testExtensionOptions);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -134,7 +139,7 @@ describe("status-bar-items-originating-from-extensions", () => {
|
||||
});
|
||||
|
||||
it("when the extension is removed, shows there are no extension status bar items", () => {
|
||||
applicationBuilder.extensions.renderer.disable(testExtension);
|
||||
applicationBuilder.extensions.disable(testExtensionOptions);
|
||||
|
||||
const actual = rendered.queryAllByTestId("some-testId");
|
||||
|
||||
|
||||
@ -2,49 +2,51 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { LensMainExtension } from "../../extensions/lens-main-extension";
|
||||
import type { TrayMenuRegistration } from "../../main/tray/tray-menu-registration";
|
||||
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import loggerInjectable from "../../common/logger.injectable";
|
||||
import type { Logger } from "../../common/logger";
|
||||
import type { FakeExtensionOptions } from "../../renderer/components/test-utils/get-extension-fake";
|
||||
import getRandomIdInjectable from "../../common/utils/get-random-id.injectable";
|
||||
|
||||
describe("clicking tray menu item originating from extension", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let builder: ApplicationBuilder;
|
||||
let logErrorMock: jest.Mock;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
logErrorMock = jest.fn();
|
||||
|
||||
mainDi.override(loggerInjectable, () => ({ error: logErrorMock }) as unknown as Logger);
|
||||
mainDi.override(getRandomIdInjectable, () => () => "some-random-id");
|
||||
});
|
||||
|
||||
await applicationBuilder.render();
|
||||
await builder.render();
|
||||
});
|
||||
|
||||
describe("when extension is enabled", () => {
|
||||
let someExtension: SomeTestExtension;
|
||||
let someExtension: FakeExtensionOptions;
|
||||
let clickMock: jest.Mock;
|
||||
|
||||
beforeEach(() => {
|
||||
clickMock = jest.fn();
|
||||
|
||||
someExtension = new SomeTestExtension({
|
||||
someExtension = {
|
||||
id: "some-extension-id",
|
||||
trayMenus: [{ label: "some-label", click: clickMock }],
|
||||
});
|
||||
name: "some-extension-name",
|
||||
mainOptions: {
|
||||
trayMenus: [{ label: "some-label", click: clickMock }],
|
||||
},
|
||||
};
|
||||
|
||||
applicationBuilder.extensions.main.enable(someExtension);
|
||||
builder.extensions.enable(someExtension);
|
||||
});
|
||||
|
||||
it("when item is clicked, triggers the click handler", () => {
|
||||
applicationBuilder.tray.click(
|
||||
"some-random-id-tray-menu-item-for-extension-some-extension-id",
|
||||
builder.tray.click(
|
||||
"some-random-id-tray-menu-item-for-extension-some-extension-name",
|
||||
);
|
||||
|
||||
expect(clickMock).toHaveBeenCalled();
|
||||
@ -56,14 +58,14 @@ describe("clicking tray menu item originating from extension", () => {
|
||||
throw new Error("some-error");
|
||||
});
|
||||
|
||||
applicationBuilder.tray.click(
|
||||
"some-random-id-tray-menu-item-for-extension-some-extension-id",
|
||||
builder.tray.click(
|
||||
"some-random-id-tray-menu-item-for-extension-some-extension-name",
|
||||
);
|
||||
});
|
||||
|
||||
it("logs the error", () => {
|
||||
expect(logErrorMock).toHaveBeenCalledWith(
|
||||
'[TRAY]: Clicking of tray item "some-random-id" from extension "some-extension-id" failed.',
|
||||
'[TRAY]: Clicking of tray item "some-random-id" from extension "some-extension-name" failed.',
|
||||
expect.any(Error),
|
||||
);
|
||||
});
|
||||
@ -73,14 +75,14 @@ describe("clicking tray menu item originating from extension", () => {
|
||||
beforeEach(() => {
|
||||
clickMock.mockImplementation(() => Promise.reject("some-rejection"));
|
||||
|
||||
applicationBuilder.tray.click(
|
||||
"some-random-id-tray-menu-item-for-extension-some-extension-id",
|
||||
builder.tray.click(
|
||||
"some-random-id-tray-menu-item-for-extension-some-extension-name",
|
||||
);
|
||||
});
|
||||
|
||||
it("logs the error", () => {
|
||||
expect(logErrorMock).toHaveBeenCalledWith(
|
||||
'[TRAY]: Clicking of tray item "some-random-id" from extension "some-extension-id" failed.',
|
||||
'[TRAY]: Clicking of tray item "some-random-id" from extension "some-extension-name" failed.',
|
||||
"some-rejection",
|
||||
);
|
||||
});
|
||||
@ -88,47 +90,27 @@ describe("clicking tray menu item originating from extension", () => {
|
||||
|
||||
describe("when extension is disabled", () => {
|
||||
beforeEach(() => {
|
||||
applicationBuilder.extensions.main.disable(someExtension);
|
||||
builder.extensions.disable(someExtension);
|
||||
});
|
||||
|
||||
it("does not have the tray menu item from extension", () => {
|
||||
expect(
|
||||
applicationBuilder.tray.get(
|
||||
"some-random-id-tray-menu-item-for-extension-some-extension-id",
|
||||
builder.tray.get(
|
||||
"some-random-id-tray-menu-item-for-extension-some-extension-name",
|
||||
),
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
// Note: Motivation here is to make sure that enabling same extension does not throw
|
||||
it("when extension is re-enabled, has the tray menu item from extension", async () => {
|
||||
await applicationBuilder.extensions.main.enable(someExtension);
|
||||
await builder.extensions.enable(someExtension);
|
||||
|
||||
expect(
|
||||
applicationBuilder.tray.get(
|
||||
"some-random-id-tray-menu-item-for-extension-some-extension-id",
|
||||
builder.tray.get(
|
||||
"some-random-id-tray-menu-item-for-extension-some-extension-name",
|
||||
),
|
||||
).not.toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
class SomeTestExtension extends LensMainExtension {
|
||||
constructor({ id, trayMenus }: {
|
||||
id: string;
|
||||
trayMenus: TrayMenuRegistration[];
|
||||
}) {
|
||||
super({
|
||||
id,
|
||||
absolutePath: "irrelevant",
|
||||
isBundled: false,
|
||||
isCompatible: false,
|
||||
isEnabled: false,
|
||||
manifest: { name: id, version: "some-version", engines: { lens: "^5.5.0" }},
|
||||
manifestPath: "irrelevant",
|
||||
});
|
||||
|
||||
this.trayMenus = trayMenus;
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,7 +6,6 @@ import type { IObservableValue } from "mobx";
|
||||
import { computed, runInAction, observable } from "mobx";
|
||||
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { getExtensionFakeFor } from "../../renderer/components/test-utils/get-extension-fake";
|
||||
|
||||
describe("preferences: extension adding tray items", () => {
|
||||
describe("when extension with tray items is enabled", () => {
|
||||
@ -22,13 +21,11 @@ describe("preferences: extension adding tray items", () => {
|
||||
|
||||
builder.preferences.navigate();
|
||||
|
||||
const getExtensionFake = getExtensionFakeFor(builder);
|
||||
|
||||
someObservableForVisibility = observable.box(false);
|
||||
someObservableForEnabled = observable.box(false);
|
||||
someObservableLabel = observable.box("Some label");
|
||||
|
||||
const testExtension = getExtensionFake({
|
||||
const testExtension = {
|
||||
id: "some-extension-id",
|
||||
name: "some-extension",
|
||||
|
||||
@ -82,7 +79,7 @@ describe("preferences: extension adding tray items", () => {
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
builder.extensions.enable(testExtension);
|
||||
});
|
||||
|
||||
@ -2,53 +2,36 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { LensMainExtension } from "../../extensions/lens-main-extension";
|
||||
import type { TrayMenuRegistration } from "../../main/tray/tray-menu-registration";
|
||||
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import getRandomIdInjectable from "../../common/utils/get-random-id.injectable";
|
||||
|
||||
describe("multiple separators originating from extension", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let builder: ApplicationBuilder;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi }) => {
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
mainDi.unoverride(getRandomIdInjectable);
|
||||
mainDi.permitSideEffects(getRandomIdInjectable);
|
||||
});
|
||||
|
||||
await applicationBuilder.render();
|
||||
await builder.render();
|
||||
});
|
||||
|
||||
it("given extension with multiple separators, when extension is enabled, does not throw", () => {
|
||||
const someExtension = new SomeTestExtension({
|
||||
const someExtension = {
|
||||
id: "some-extension-id",
|
||||
trayMenus: [{ type: "separator" }, { type: "separator" } ],
|
||||
});
|
||||
name: "some-extension",
|
||||
|
||||
mainOptions: {
|
||||
trayMenus: [{ type: "separator" as const }, { type: "separator" as const } ],
|
||||
},
|
||||
};
|
||||
|
||||
expect(() => {
|
||||
applicationBuilder.extensions.main.enable(someExtension);
|
||||
builder.extensions.enable(someExtension);
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
class SomeTestExtension extends LensMainExtension {
|
||||
constructor({ id, trayMenus }: {
|
||||
id: string;
|
||||
trayMenus: TrayMenuRegistration[];
|
||||
}) {
|
||||
super({
|
||||
id,
|
||||
absolutePath: "irrelevant",
|
||||
isBundled: false,
|
||||
isCompatible: false,
|
||||
isEnabled: false,
|
||||
manifest: { name: id, version: "some-version", engines: { lens: "^5.5.0" }},
|
||||
manifestPath: "irrelevant",
|
||||
});
|
||||
|
||||
this.trayMenus = trayMenus;
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,9 +17,6 @@ import extensionsStoreInjectable from "../extensions/extensions-store/extensions
|
||||
import type { ExtensionsStore } from "../extensions/extensions-store/extensions-store";
|
||||
import fileSystemProvisionerStoreInjectable from "../extensions/extension-loader/file-system-provisioner-store/file-system-provisioner-store.injectable";
|
||||
import type { FileSystemProvisionerStore } from "../extensions/extension-loader/file-system-provisioner-store/file-system-provisioner-store";
|
||||
import clusterStoreInjectable from "../common/cluster-store/cluster-store.injectable";
|
||||
import type { ClusterStore } from "../common/cluster-store/cluster-store";
|
||||
import type { Cluster } from "../common/cluster/cluster";
|
||||
import userStoreInjectable from "../common/user-store/user-store.injectable";
|
||||
import type { UserStore } from "../common/user-store";
|
||||
import getAbsolutePathInjectable from "../common/path/get-absolute-path.injectable";
|
||||
@ -62,9 +59,7 @@ import { observable } from "mobx";
|
||||
import waitForElectronToBeReadyInjectable from "./electron-app/features/wait-for-electron-to-be-ready.injectable";
|
||||
import setupListenerForCurrentClusterFrameInjectable from "./start-main-application/lens-window/current-cluster-frame/setup-listener-for-current-cluster-frame.injectable";
|
||||
import ipcMainInjectable from "./utils/channel/ipc-main/ipc-main.injectable";
|
||||
import createElectronWindowForInjectable from "./start-main-application/lens-window/application-window/create-electron-window.injectable";
|
||||
import setupRunnablesAfterWindowIsOpenedInjectable from "./electron-app/runnables/setup-runnables-after-window-is-opened.injectable";
|
||||
import sendToChannelInElectronBrowserWindowInjectable from "./start-main-application/lens-window/application-window/send-to-channel-in-electron-browser-window.injectable";
|
||||
import broadcastMessageInjectable from "../common/ipc/broadcast-message.injectable";
|
||||
import getElectronThemeInjectable from "./electron-app/features/get-electron-theme.injectable";
|
||||
import syncThemeFromOperatingSystemInjectable from "./electron-app/features/sync-theme-from-operating-system.injectable";
|
||||
@ -144,7 +139,6 @@ export function getDiForUnitTesting(opts: { doGeneralOverrides?: boolean } = {})
|
||||
|
||||
di.override(userStoreInjectable, () => ({ startMainReactions: () => {}, extensionRegistryUrl: { customUrl: "some-custom-url" }}) as UserStore);
|
||||
di.override(extensionsStoreInjectable, () => ({ isEnabled: (opts) => (void opts, false) }) as ExtensionsStore);
|
||||
di.override(clusterStoreInjectable, () => ({ provideInitialFromMain: () => {}, getById: (id) => (void id, {}) as Cluster }) as ClusterStore);
|
||||
di.override(fileSystemProvisionerStoreInjectable, () => ({}) as FileSystemProvisionerStore);
|
||||
|
||||
overrideOperatingSystem(di);
|
||||
@ -270,21 +264,6 @@ const overrideElectronFeatures = (di: DiContainer) => {
|
||||
throw new Error("Tried to check for platform updates without explicit override.");
|
||||
});
|
||||
|
||||
di.override(createElectronWindowForInjectable, () => () => ({
|
||||
show: () => {},
|
||||
|
||||
close: () => {},
|
||||
|
||||
send: (arg) => {
|
||||
const sendFake = di.inject(sendToChannelInElectronBrowserWindowInjectable) as any;
|
||||
|
||||
sendFake(null, arg);
|
||||
},
|
||||
|
||||
loadFile: async () => {},
|
||||
loadUrl: async () => {},
|
||||
}));
|
||||
|
||||
di.override(
|
||||
getElectronAppPathInjectable,
|
||||
() => (name: string) => `some-electron-app-path-for-${kebabCase(name)}`,
|
||||
|
||||
@ -10,12 +10,15 @@ import * as LensExtensionsCommonApi from "../extensions/common-api";
|
||||
import * as LensExtensionsMainApi from "../extensions/main-api";
|
||||
import { getDi } from "./getDi";
|
||||
import startMainApplicationInjectable from "./start-main-application/start-main-application.injectable";
|
||||
import shouldStartHiddenInjectable from "./electron-app/features/should-start-hidden.injectable";
|
||||
|
||||
const di = getDi();
|
||||
|
||||
const shouldStartHidden = di.inject(shouldStartHiddenInjectable);
|
||||
|
||||
const startApplication = di.inject(startMainApplicationInjectable);
|
||||
|
||||
void startApplication();
|
||||
void startApplication(!shouldStartHidden);
|
||||
|
||||
/**
|
||||
* Exports for virtual package "@k8slens/extensions" for main-process.
|
||||
|
||||
@ -20,8 +20,7 @@ import stopServicesAndExitAppInjectable from "../stop-services-and-exit-app.inje
|
||||
import isMacInjectable from "../../common/vars/is-mac.injectable";
|
||||
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 reloadCurrentApplicationWindowInjectable from "../start-main-application/lens-window/reload-current-application-window.injectable";
|
||||
import showApplicationWindowInjectable from "../start-main-application/lens-window/show-application-window.injectable";
|
||||
import processCheckingForUpdatesInjectable from "../application-update/check-for-updates/process-checking-for-updates.injectable";
|
||||
import openLinkInBrowserInjectable from "../../common/utils/open-link-in-browser.injectable";
|
||||
@ -44,9 +43,8 @@ const applicationMenuItemsInjectable = getInjectable({
|
||||
const updatingIsEnabled = di.inject(updatingIsEnabledInjectable);
|
||||
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);
|
||||
const reloadApplicationWindow = di.inject(reloadCurrentApplicationWindowInjectable);
|
||||
const navigateToPreferences = di.inject(navigateToPreferencesInjectable);
|
||||
const navigateToExtensions = di.inject(navigateToExtensionsInjectable);
|
||||
const navigateToCatalog = di.inject(navigateToCatalogInjectable);
|
||||
|
||||
@ -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 { LensWindow } from "./create-lens-window.injectable";
|
||||
|
||||
export const applicationWindowInjectionToken = getInjectionToken<LensWindow>({
|
||||
id: "application-window-injection-token",
|
||||
});
|
||||
@ -1,53 +0,0 @@
|
||||
/**
|
||||
* 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 { lensWindowInjectionToken } from "./lens-window-injection-token";
|
||||
import createLensWindowInjectable from "./create-lens-window.injectable";
|
||||
import lensProxyPortInjectable from "../../../lens-proxy/lens-proxy-port.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 waitUntilBundledExtensionsAreLoadedInjectable from "./wait-until-bundled-extensions-are-loaded.injectable";
|
||||
|
||||
const applicationWindowInjectable = getInjectable({
|
||||
id: "application-window",
|
||||
|
||||
instantiate: (di) => {
|
||||
const createLensWindow = di.inject(createLensWindowInjectable);
|
||||
const isMac = di.inject(isMacInjectable);
|
||||
const applicationName = di.inject(appNameInjectable);
|
||||
const appEventBus = di.inject(appEventBusInjectable);
|
||||
const waitUntilBundledExtensionsAreLoaded = di.inject(waitUntilBundledExtensionsAreLoadedInjectable);
|
||||
const lensProxyPort = di.inject(lensProxyPortInjectable);
|
||||
|
||||
return createLensWindow({
|
||||
id: "only-application-window",
|
||||
title: applicationName,
|
||||
defaultHeight: 900,
|
||||
defaultWidth: 1440,
|
||||
getContentSource: () => ({
|
||||
url: `http://localhost:${lensProxyPort.get()}`,
|
||||
}),
|
||||
resizable: true,
|
||||
windowFrameUtilitiesAreShown: isMac,
|
||||
titleBarStyle: isMac ? "hiddenInset" : "hidden",
|
||||
centered: false,
|
||||
onFocus: () => {
|
||||
appEventBus.emit({ name: "app", action: "focus" });
|
||||
},
|
||||
onBlur: () => {
|
||||
appEventBus.emit({ name: "app", action: "blur" });
|
||||
},
|
||||
onDomReady: () => {
|
||||
appEventBus.emit({ name: "app", action: "dom-ready" });
|
||||
},
|
||||
beforeOpen: waitUntilBundledExtensionsAreLoaded,
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: lensWindowInjectionToken,
|
||||
});
|
||||
|
||||
export default applicationWindowInjectable;
|
||||
@ -0,0 +1,68 @@
|
||||
/**
|
||||
* 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 createLensWindowInjectable from "./create-lens-window.injectable";
|
||||
import lensProxyPortInjectable from "../../../lens-proxy/lens-proxy-port.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 waitUntilBundledExtensionsAreLoadedInjectable from "./wait-until-bundled-extensions-are-loaded.injectable";
|
||||
import { applicationWindowInjectionToken } from "./application-window-injection-token";
|
||||
|
||||
const createApplicationWindowInjectable = getInjectable({
|
||||
id: "create-application-window",
|
||||
|
||||
instantiate: (parentDi) => (id: string) => {
|
||||
const windowInjectable = getInjectable({
|
||||
id: `application-window-for-${id}`,
|
||||
|
||||
instantiate: (di) => {
|
||||
const createLensWindow = di.inject(createLensWindowInjectable);
|
||||
const isMac = di.inject(isMacInjectable);
|
||||
const applicationName = di.inject(appNameInjectable);
|
||||
const appEventBus = di.inject(appEventBusInjectable);
|
||||
const waitUntilBundledExtensionsAreLoaded = di.inject(waitUntilBundledExtensionsAreLoadedInjectable);
|
||||
const lensProxyPort = di.inject(lensProxyPortInjectable);
|
||||
|
||||
return createLensWindow({
|
||||
id,
|
||||
title: applicationName,
|
||||
defaultHeight: 900,
|
||||
defaultWidth: 1440,
|
||||
getContentSource: () => ({
|
||||
url: `http://localhost:${lensProxyPort.get()}`,
|
||||
}),
|
||||
resizable: true,
|
||||
windowFrameUtilitiesAreShown: isMac,
|
||||
titleBarStyle: isMac ? "hiddenInset" : "hidden",
|
||||
centered: false,
|
||||
onFocus: () => {
|
||||
appEventBus.emit({ name: "app", action: "focus" });
|
||||
},
|
||||
onBlur: () => {
|
||||
appEventBus.emit({ name: "app", action: "blur" });
|
||||
},
|
||||
onDomReady: () => {
|
||||
appEventBus.emit({ name: "app", action: "dom-ready" });
|
||||
},
|
||||
|
||||
onClose: () => {
|
||||
parentDi.deregister(windowInjectable);
|
||||
},
|
||||
|
||||
beforeOpen: waitUntilBundledExtensionsAreLoaded,
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: applicationWindowInjectionToken,
|
||||
});
|
||||
|
||||
parentDi.register(windowInjectable);
|
||||
|
||||
return parentDi.inject(windowInjectable);
|
||||
},
|
||||
});
|
||||
|
||||
export default createApplicationWindowInjectable;
|
||||
@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getGlobalOverride } from "../../../../common/test-utils/get-global-override";
|
||||
import createElectronWindowInjectable from "./create-electron-window.injectable";
|
||||
|
||||
export default getGlobalOverride(createElectronWindowInjectable, () => () => ({
|
||||
loadFile: async () => {},
|
||||
loadUrl: async () => {},
|
||||
show: () => {},
|
||||
close: () => {},
|
||||
send: () => {},
|
||||
reload: () => {},
|
||||
}));
|
||||
@ -140,7 +140,14 @@ const createElectronWindowInjectable = getInjectable({
|
||||
|
||||
show: () => browserWindow.show(),
|
||||
close: () => browserWindow.close(),
|
||||
send: (args) => sendToChannelInLensWindow(browserWindow, args),
|
||||
send: (args) => sendToChannelInLensWindow(configuration.id, browserWindow, args),
|
||||
|
||||
reload: () => {
|
||||
const wc = browserWindow.webContents;
|
||||
|
||||
wc.reload();
|
||||
wc.clearHistory();
|
||||
},
|
||||
};
|
||||
};
|
||||
},
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
/**
|
||||
* 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 createApplicationWindowInjectable from "./create-application-window.injectable";
|
||||
|
||||
// Note: Motivation is to create the window with same ID to use stored dimensions
|
||||
const createFirstApplicationWindowInjectable = getInjectable({
|
||||
id: "create-first-application-window",
|
||||
|
||||
instantiate: (di) => {
|
||||
const createApplicationWindow = di.inject(createApplicationWindowInjectable);
|
||||
|
||||
return () => createApplicationWindow("first-application-window");
|
||||
},
|
||||
});
|
||||
|
||||
export default createFirstApplicationWindowInjectable;
|
||||
@ -3,10 +3,10 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { LensWindow, SendToViewArgs } from "./lens-window-injection-token";
|
||||
import type { ContentSource, ElectronWindowTitleBarStyle } from "./create-electron-window.injectable";
|
||||
import createElectronWindowForInjectable from "./create-electron-window.injectable";
|
||||
import assert from "assert";
|
||||
import type { ClusterFrameInfo } from "../../../../common/cluster-frames";
|
||||
|
||||
export interface ElectronWindow {
|
||||
show: () => void;
|
||||
@ -14,6 +14,24 @@ export interface ElectronWindow {
|
||||
send: (args: SendToViewArgs) => void;
|
||||
loadFile: (filePath: string) => Promise<void>;
|
||||
loadUrl: (url: string) => Promise<void>;
|
||||
reload: () => void;
|
||||
}
|
||||
|
||||
export interface SendToViewArgs {
|
||||
channel: string;
|
||||
frameInfo?: ClusterFrameInfo;
|
||||
data?: unknown[];
|
||||
}
|
||||
|
||||
export interface LensWindow {
|
||||
id: string;
|
||||
start: () => Promise<void>;
|
||||
close: () => void;
|
||||
show: () => void;
|
||||
send: (args: SendToViewArgs) => void;
|
||||
isVisible: boolean;
|
||||
isStarting: boolean;
|
||||
reload: () => void;
|
||||
}
|
||||
|
||||
export interface LensWindowConfiguration {
|
||||
@ -30,6 +48,7 @@ export interface LensWindowConfiguration {
|
||||
onFocus?: () => void;
|
||||
onBlur?: () => void;
|
||||
onDomReady?: () => void;
|
||||
onClose?: () => void;
|
||||
}
|
||||
|
||||
const createLensWindowInjectable = getInjectable({
|
||||
@ -97,6 +116,7 @@ const createLensWindowInjectable = getInjectable({
|
||||
browserWindow?.close();
|
||||
browserWindow = undefined;
|
||||
windowIsShown = false;
|
||||
configuration.onClose?.();
|
||||
},
|
||||
|
||||
send: (args: SendToViewArgs) => {
|
||||
@ -106,6 +126,14 @@ const createLensWindowInjectable = getInjectable({
|
||||
|
||||
return browserWindow.send(args);
|
||||
},
|
||||
|
||||
reload: () => {
|
||||
if (!browserWindow) {
|
||||
throw new Error(`Tried to reload window "${configuration.id}" but the window was closed`);
|
||||
}
|
||||
|
||||
return browserWindow.reload();
|
||||
},
|
||||
};
|
||||
};
|
||||
},
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
/**
|
||||
* 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 { first } from "lodash/fp";
|
||||
import { applicationWindowInjectionToken } from "./application-window-injection-token";
|
||||
|
||||
const getCurrentApplicationWindowInjectable = getInjectable({
|
||||
id: "get-current-application-window",
|
||||
|
||||
instantiate: (di) => () =>
|
||||
first(di.injectMany(applicationWindowInjectionToken)),
|
||||
});
|
||||
|
||||
export default getCurrentApplicationWindowInjectable;
|
||||
@ -1,26 +0,0 @@
|
||||
/**
|
||||
* 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 { ClusterFrameInfo } from "../../../../common/cluster-frames";
|
||||
|
||||
export interface SendToViewArgs {
|
||||
channel: string;
|
||||
frameInfo?: ClusterFrameInfo;
|
||||
data?: unknown[];
|
||||
}
|
||||
|
||||
export interface LensWindow {
|
||||
id: string;
|
||||
start: () => Promise<void>;
|
||||
close: () => void;
|
||||
show: () => void;
|
||||
send: (args: SendToViewArgs) => void;
|
||||
isVisible: boolean;
|
||||
isStarting: boolean;
|
||||
}
|
||||
|
||||
export const lensWindowInjectionToken = getInjectionToken<LensWindow>({
|
||||
id: "lens-window",
|
||||
});
|
||||
@ -4,7 +4,7 @@
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { BrowserWindow } from "electron";
|
||||
import type { SendToViewArgs } from "./lens-window-injection-token";
|
||||
import type { SendToViewArgs } from "./create-lens-window.injectable";
|
||||
|
||||
const sendToChannelInElectronBrowserWindowInjectable = getInjectable({
|
||||
id: "send-to-channel-in-electron-browser-window",
|
||||
@ -12,6 +12,7 @@ const sendToChannelInElectronBrowserWindowInjectable = getInjectable({
|
||||
instantiate:
|
||||
() =>
|
||||
(
|
||||
windowId: string,
|
||||
browserWindow: BrowserWindow,
|
||||
{ channel, frameInfo, data = [] }: SendToViewArgs,
|
||||
) => {
|
||||
|
||||
@ -5,13 +5,13 @@
|
||||
import { pipeline } from "@ogre-tools/fp";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { filter } from "lodash/fp";
|
||||
import { lensWindowInjectionToken } from "./application-window/lens-window-injection-token";
|
||||
import { applicationWindowInjectionToken } from "./application-window/application-window-injection-token";
|
||||
|
||||
const getVisibleWindowsInjectable = getInjectable({
|
||||
id: "get-visible-windows",
|
||||
|
||||
instantiate: (di) => {
|
||||
const getAllLensWindows = () => di.injectMany(lensWindowInjectionToken);
|
||||
const getAllLensWindows = () => di.injectMany(applicationWindowInjectionToken);
|
||||
|
||||
return () =>
|
||||
pipeline(
|
||||
|
||||
@ -3,13 +3,13 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { lensWindowInjectionToken } from "../application-window/lens-window-injection-token";
|
||||
import { applicationWindowInjectionToken } from "../application-window/application-window-injection-token";
|
||||
|
||||
const closeAllWindowsInjectable = getInjectable({
|
||||
id: "close-all-windows",
|
||||
|
||||
instantiate: (di) => () => {
|
||||
const lensWindows = di.injectMany(lensWindowInjectionToken);
|
||||
const lensWindows = di.injectMany(applicationWindowInjectionToken);
|
||||
|
||||
lensWindows.forEach((lensWindow) => {
|
||||
lensWindow.close();
|
||||
|
||||
@ -6,7 +6,8 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { iter } from "../../../common/utils";
|
||||
import clusterFramesInjectable from "../../../common/cluster-frames.injectable";
|
||||
import showApplicationWindowInjectable from "./show-application-window.injectable";
|
||||
import applicationWindowInjectable from "./application-window/application-window.injectable";
|
||||
import getCurrentApplicationWindowInjectable from "./application-window/get-current-application-window.injectable";
|
||||
import assert from "assert";
|
||||
|
||||
export type NavigateForExtension = (
|
||||
extId: string,
|
||||
@ -19,7 +20,7 @@ const navigateForExtensionInjectable = getInjectable({
|
||||
id: "navigate-for-extension",
|
||||
|
||||
instantiate: (di): NavigateForExtension => {
|
||||
const applicationWindow = di.inject(applicationWindowInjectable);
|
||||
const getApplicationWindow = di.inject(getCurrentApplicationWindowInjectable);
|
||||
const clusterFrames = di.inject(clusterFramesInjectable);
|
||||
const showApplicationWindow = di.inject(showApplicationWindowInjectable);
|
||||
|
||||
@ -31,6 +32,10 @@ const navigateForExtensionInjectable = getInjectable({
|
||||
) => {
|
||||
await showApplicationWindow();
|
||||
|
||||
const applicationWindow = getApplicationWindow();
|
||||
|
||||
assert(applicationWindow);
|
||||
|
||||
const frameInfo = iter.find(
|
||||
clusterFrames.values(),
|
||||
(frameInfo) => frameInfo.frameId === frameId,
|
||||
|
||||
@ -4,22 +4,27 @@
|
||||
*/
|
||||
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 { IpcRendererNavigationEvents } from "../../../renderer/navigation/events";
|
||||
import showApplicationWindowInjectable from "./show-application-window.injectable";
|
||||
import getCurrentApplicationWindowInjectable from "./application-window/get-current-application-window.injectable";
|
||||
import assert from "assert";
|
||||
|
||||
const navigateInjectable = getInjectable({
|
||||
id: "navigate",
|
||||
|
||||
instantiate: (di) => {
|
||||
const applicationWindow = di.inject(applicationWindowInjectable);
|
||||
const getApplicationWindow = di.inject(getCurrentApplicationWindowInjectable);
|
||||
const showApplicationWindow = di.inject(showApplicationWindowInjectable);
|
||||
const clusterFrames = di.inject(clusterFramesInjectable);
|
||||
|
||||
return async (url: string, frameId?: number) => {
|
||||
await showApplicationWindow();
|
||||
|
||||
const applicationWindow = getApplicationWindow();
|
||||
|
||||
assert(applicationWindow);
|
||||
|
||||
const frameInfo = iter.find(
|
||||
clusterFrames.values(),
|
||||
(frameInfo) => frameInfo.frameId === frameId,
|
||||
|
||||
@ -1,24 +0,0 @@
|
||||
/**
|
||||
* 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 { webContents } from "electron";
|
||||
|
||||
const reloadAllWindowsInjectable = getInjectable({
|
||||
id: "reload-all-windows",
|
||||
|
||||
instantiate: () => () => {
|
||||
webContents
|
||||
.getAllWebContents()
|
||||
.filter((wc) => wc.getType() === "window")
|
||||
.forEach((wc) => {
|
||||
wc.reload();
|
||||
wc.clearHistory();
|
||||
});
|
||||
},
|
||||
|
||||
causesSideEffects: true,
|
||||
});
|
||||
|
||||
export default reloadAllWindowsInjectable;
|
||||
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* 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 { IpcRendererNavigationEvents } from "../../../renderer/navigation/events";
|
||||
import currentClusterFrameInjectable from "./current-cluster-frame/current-cluster-frame.injectable";
|
||||
import getCurrentApplicationWindowInjectable from "./application-window/get-current-application-window.injectable";
|
||||
|
||||
const reloadCurrentApplicationWindowInjectable = getInjectable({
|
||||
id: "reload-current-application-window",
|
||||
|
||||
instantiate: (di) => {
|
||||
const getCurrentApplicationWindow = di.inject(getCurrentApplicationWindowInjectable);
|
||||
const currentClusterIframe = di.inject(currentClusterFrameInjectable);
|
||||
|
||||
return () => {
|
||||
const lensWindow = getCurrentApplicationWindow();
|
||||
|
||||
if (!lensWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
const frameInfo = currentClusterIframe.get();
|
||||
|
||||
if (frameInfo) {
|
||||
lensWindow.send({
|
||||
channel: IpcRendererNavigationEvents.RELOAD_PAGE,
|
||||
frameInfo,
|
||||
});
|
||||
} else {
|
||||
lensWindow.reload();
|
||||
}
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default reloadCurrentApplicationWindowInjectable;
|
||||
@ -1,33 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
|
||||
import type { LensWindow } from "./application-window/lens-window-injection-token";
|
||||
import { IpcRendererNavigationEvents } from "../../../renderer/navigation/events";
|
||||
import currentClusterFrameInjectable from "./current-cluster-frame/current-cluster-frame.injectable";
|
||||
import reloadAllWindowsInjectable from "./reload-all-windows.injectable";
|
||||
|
||||
const reloadWindowInjectable = getInjectable({
|
||||
id: "reload-window",
|
||||
|
||||
instantiate: (di, lensWindow: LensWindow) => () => {
|
||||
const currentClusterIframe = di.inject(currentClusterFrameInjectable);
|
||||
const reloadAllWindows = di.inject(reloadAllWindowsInjectable);
|
||||
|
||||
const frameInfo = currentClusterIframe.get();
|
||||
|
||||
if (frameInfo) {
|
||||
lensWindow.send({
|
||||
channel: IpcRendererNavigationEvents.RELOAD_PAGE,
|
||||
frameInfo,
|
||||
});
|
||||
} else {
|
||||
reloadAllWindows();
|
||||
}
|
||||
},
|
||||
|
||||
lifecycle: lifecycleEnum.transient,
|
||||
});
|
||||
|
||||
export default reloadWindowInjectable;
|
||||
@ -4,22 +4,26 @@
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import splashWindowInjectable from "./splash-window/splash-window.injectable";
|
||||
import applicationWindowInjectable from "./application-window/application-window.injectable";
|
||||
import { identity, some } from "lodash/fp";
|
||||
import focusApplicationInjectable from "../../electron-app/features/focus-application.injectable";
|
||||
import getCurrentApplicationWindowInjectable from "./application-window/get-current-application-window.injectable";
|
||||
import createFirstApplicationWindowInjectable from "./application-window/create-first-application-window.injectable";
|
||||
const someIsTruthy = some(identity);
|
||||
|
||||
const showApplicationWindowInjectable = getInjectable({
|
||||
id: "show-application-window",
|
||||
|
||||
instantiate: (di) => {
|
||||
const applicationWindow = di.inject(applicationWindowInjectable);
|
||||
const getApplicationWindow = di.inject(getCurrentApplicationWindowInjectable);
|
||||
const createFirstApplicationWindow = di.inject(createFirstApplicationWindowInjectable);
|
||||
const splashWindow = di.inject(splashWindowInjectable);
|
||||
const focusApplication = di.inject(focusApplicationInjectable);
|
||||
|
||||
return async () => {
|
||||
focusApplication();
|
||||
|
||||
const applicationWindow = getApplicationWindow() ?? createFirstApplicationWindow();
|
||||
|
||||
if (applicationWindow.isStarting) {
|
||||
applicationWindow.show();
|
||||
splashWindow.close();
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { lensWindowInjectionToken } from "../application-window/lens-window-injection-token";
|
||||
import createLensWindowInjectable from "../application-window/create-lens-window.injectable";
|
||||
import staticFilesDirectoryInjectable from "../../../../common/vars/static-files-directory.injectable";
|
||||
import getAbsolutePathInjectable from "../../../../common/path/get-absolute-path.injectable";
|
||||
@ -30,8 +29,6 @@ const splashWindowInjectable = getInjectable({
|
||||
centered: true,
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: lensWindowInjectionToken,
|
||||
});
|
||||
|
||||
export default splashWindowInjectable;
|
||||
|
||||
@ -12,13 +12,12 @@ import { onLoadOfApplicationInjectionToken } from "./runnable-tokens/on-load-of-
|
||||
import { afterApplicationIsLoadedInjectionToken } from "./runnable-tokens/after-application-is-loaded-injection-token";
|
||||
import splashWindowInjectable from "./lens-window/splash-window/splash-window.injectable";
|
||||
|
||||
import applicationWindowInjectable from "./lens-window/application-window/application-window.injectable";
|
||||
import shouldStartHiddenInjectable from "../electron-app/features/should-start-hidden.injectable";
|
||||
import openDeepLinkInjectable from "../protocol-handler/lens-protocol-router-main/open-deep-link-for-url/open-deep-link.injectable";
|
||||
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";
|
||||
import createFirstApplicationWindowInjectable from "./lens-window/application-window/create-first-application-window.injectable";
|
||||
|
||||
const startMainApplicationInjectable = getInjectable({
|
||||
id: "start-main-application",
|
||||
@ -27,9 +26,8 @@ const startMainApplicationInjectable = getInjectable({
|
||||
const runMany = runManyFor(di);
|
||||
const runManySync = runManySyncFor(di);
|
||||
const waitForElectronToBeReady = di.inject(waitForElectronToBeReadyInjectable);
|
||||
const applicationWindow = di.inject(applicationWindowInjectable);
|
||||
const createFirstApplicationWindow = di.inject(createFirstApplicationWindowInjectable);
|
||||
const splashWindow = di.inject(splashWindowInjectable);
|
||||
const shouldStartHidden = di.inject(shouldStartHiddenInjectable);
|
||||
const openDeepLink = di.inject(openDeepLinkInjectable);
|
||||
const commandLineArguments = di.inject(commandLineArgumentsInjectable);
|
||||
|
||||
@ -38,7 +36,7 @@ const startMainApplicationInjectable = getInjectable({
|
||||
const onLoadOfApplication = runMany(onLoadOfApplicationInjectionToken);
|
||||
const afterApplicationIsLoaded = runMany(afterApplicationIsLoadedInjectionToken);
|
||||
|
||||
return () => {
|
||||
return (shouldStartWindow: boolean) => {
|
||||
// Stuff happening before application is ready needs to be synchronous because of
|
||||
// https://github.com/electron/electron/issues/21370
|
||||
beforeElectronIsReady();
|
||||
@ -48,18 +46,20 @@ const startMainApplicationInjectable = getInjectable({
|
||||
|
||||
await beforeApplicationIsLoading();
|
||||
|
||||
if (!shouldStartHidden) {
|
||||
if (shouldStartWindow) {
|
||||
await splashWindow.start();
|
||||
}
|
||||
|
||||
await onLoadOfApplication();
|
||||
|
||||
if (!shouldStartHidden) {
|
||||
if (shouldStartWindow) {
|
||||
const deepLinkUrl = getDeepLinkUrl(commandLineArguments);
|
||||
|
||||
if (deepLinkUrl) {
|
||||
await openDeepLink(deepLinkUrl);
|
||||
} else {
|
||||
const applicationWindow = createFirstApplicationWindow();
|
||||
|
||||
await applicationWindow.start();
|
||||
}
|
||||
|
||||
|
||||
@ -5,15 +5,10 @@
|
||||
|
||||
import type { MessageToChannel } from "../../../common/utils/channel/message-to-channel-injection-token";
|
||||
import { messageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token";
|
||||
import closeAllWindowsInjectable from "../../start-main-application/lens-window/hide-all-windows/close-all-windows.injectable";
|
||||
import type { MessageChannel } from "../../../common/utils/channel/message-channel-injection-token";
|
||||
import { getDiForUnitTesting } from "../../getDiForUnitTesting";
|
||||
import createLensWindowInjectable from "../../start-main-application/lens-window/application-window/create-lens-window.injectable";
|
||||
import type { LensWindow } from "../../start-main-application/lens-window/application-window/lens-window-injection-token";
|
||||
import { lensWindowInjectionToken } from "../../start-main-application/lens-window/application-window/lens-window-injection-token";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { LensWindow } from "../../start-main-application/lens-window/application-window/create-lens-window.injectable";
|
||||
import sendToChannelInElectronBrowserWindowInjectable from "../../start-main-application/lens-window/application-window/send-to-channel-in-electron-browser-window.injectable";
|
||||
import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder";
|
||||
|
||||
describe("message to channel from main", () => {
|
||||
let messageToChannel: MessageToChannel;
|
||||
@ -21,20 +16,21 @@ describe("message to channel from main", () => {
|
||||
let someOtherTestWindow: LensWindow;
|
||||
let sendToChannelInBrowserMock: jest.Mock;
|
||||
|
||||
beforeEach(() => {
|
||||
const di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||
beforeEach(async () => {
|
||||
const builder = getApplicationBuilder();
|
||||
|
||||
sendToChannelInBrowserMock = jest.fn();
|
||||
di.override(sendToChannelInElectronBrowserWindowInjectable, () => sendToChannelInBrowserMock);
|
||||
|
||||
someTestWindow = createTestWindow(di, "some-test-window-id");
|
||||
someOtherTestWindow = createTestWindow(di, "some-other-test-window-id");
|
||||
builder.beforeApplicationStart(mainDi => {
|
||||
mainDi.override(sendToChannelInElectronBrowserWindowInjectable, () => sendToChannelInBrowserMock);
|
||||
});
|
||||
|
||||
messageToChannel = di.inject(messageToChannelInjectionToken);
|
||||
await builder.startHidden();
|
||||
|
||||
const closeAllWindows = di.inject(closeAllWindowsInjectable);
|
||||
someTestWindow = builder.applicationWindow.create("some-test-window-id");
|
||||
someOtherTestWindow = builder.applicationWindow.create("some-other-test-window-id");
|
||||
|
||||
closeAllWindows();
|
||||
messageToChannel = builder.mainDi.inject(messageToChannelInjectionToken);
|
||||
});
|
||||
|
||||
it("given no visible windows, when messaging to channel, does not message to any window", () => {
|
||||
@ -53,6 +49,8 @@ describe("message to channel from main", () => {
|
||||
|
||||
expect(sendToChannelInBrowserMock.mock.calls).toEqual([
|
||||
[
|
||||
"some-test-window-id",
|
||||
|
||||
null,
|
||||
|
||||
{
|
||||
@ -68,6 +66,8 @@ describe("message to channel from main", () => {
|
||||
|
||||
expect(sendToChannelInBrowserMock.mock.calls).toEqual([
|
||||
[
|
||||
"some-test-window-id",
|
||||
|
||||
null,
|
||||
|
||||
{
|
||||
@ -83,6 +83,8 @@ describe("message to channel from main", () => {
|
||||
|
||||
expect(sendToChannelInBrowserMock.mock.calls).toEqual([
|
||||
[
|
||||
"some-test-window-id",
|
||||
|
||||
null,
|
||||
|
||||
{
|
||||
@ -98,6 +100,8 @@ describe("message to channel from main", () => {
|
||||
|
||||
expect(sendToChannelInBrowserMock.mock.calls).toEqual([
|
||||
[
|
||||
"some-test-window-id",
|
||||
|
||||
null,
|
||||
|
||||
{
|
||||
@ -117,6 +121,8 @@ describe("message to channel from main", () => {
|
||||
|
||||
expect(sendToChannelInBrowserMock.mock.calls).toEqual([
|
||||
[
|
||||
"some-test-window-id",
|
||||
|
||||
null,
|
||||
|
||||
{
|
||||
@ -126,6 +132,8 @@ describe("message to channel from main", () => {
|
||||
],
|
||||
|
||||
[
|
||||
"some-other-test-window-id",
|
||||
|
||||
null,
|
||||
|
||||
{
|
||||
@ -138,30 +146,3 @@ describe("message to channel from main", () => {
|
||||
});
|
||||
|
||||
const someChannel: MessageChannel<any> = { id: "some-channel" };
|
||||
|
||||
const createTestWindow = (di: DiContainer, id: string) => {
|
||||
const testWindowInjectable = getInjectable({
|
||||
id,
|
||||
|
||||
instantiate: (di) => {
|
||||
const createLensWindow = di.inject(createLensWindowInjectable);
|
||||
|
||||
return createLensWindow({
|
||||
id,
|
||||
title: "Some test window",
|
||||
defaultHeight: 42,
|
||||
defaultWidth: 42,
|
||||
getContentSource: () => ({ url: "some-content-url" }),
|
||||
resizable: true,
|
||||
windowFrameUtilitiesAreShown: false,
|
||||
centered: false,
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: lensWindowInjectionToken,
|
||||
});
|
||||
|
||||
di.register(testWindowInjectable);
|
||||
|
||||
return di.inject(testWindowInjectable);
|
||||
};
|
||||
|
||||
@ -13,10 +13,10 @@ import type { PreferenceNavigationItem } from "../preference-navigation-items.in
|
||||
import preferenceNavigationItemsInjectable from "../preference-navigation-items.injectable";
|
||||
|
||||
describe.only("preferences - navigation block with links", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let builder: ApplicationBuilder;
|
||||
|
||||
beforeEach(() => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
builder = getApplicationBuilder();
|
||||
});
|
||||
|
||||
describe("given in preferences, when rendered", () => {
|
||||
@ -24,17 +24,15 @@ describe.only("preferences - navigation block with links", () => {
|
||||
|
||||
describe("when general navigation items passed", () => {
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeApplicationStart(({ rendererDi }) => {
|
||||
rendererDi.override(preferenceNavigationItemsInjectable, () =>
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.override(preferenceNavigationItemsInjectable, () =>
|
||||
computed(() => generalNavItems),
|
||||
);
|
||||
|
||||
builder.preferences.navigate();
|
||||
});
|
||||
|
||||
applicationBuilder.beforeRender(() => {
|
||||
applicationBuilder.preferences.navigate();
|
||||
});
|
||||
|
||||
renderer = await applicationBuilder.render();
|
||||
renderer = await builder.render();
|
||||
});
|
||||
|
||||
const links = ["General", "Proxy"];
|
||||
@ -52,17 +50,15 @@ describe.only("preferences - navigation block with links", () => {
|
||||
|
||||
describe("when general + extension navigation items passed", () => {
|
||||
beforeEach(async () => {
|
||||
applicationBuilder.beforeApplicationStart(({ rendererDi }) => {
|
||||
rendererDi.override(preferenceNavigationItemsInjectable, () =>
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.override(preferenceNavigationItemsInjectable, () =>
|
||||
computed(() => [...generalNavItems, ...extensionNavItems]),
|
||||
);
|
||||
|
||||
builder.preferences.navigate();
|
||||
});
|
||||
|
||||
applicationBuilder.beforeRender(() => {
|
||||
applicationBuilder.preferences.navigate();
|
||||
});
|
||||
|
||||
renderer = await applicationBuilder.render();
|
||||
renderer = await builder.render();
|
||||
});
|
||||
|
||||
const generalLinks = ["General", "Proxy"];
|
||||
|
||||
@ -6,13 +6,10 @@ import "@testing-library/jest-dom/extend-expect";
|
||||
import { KubeConfig } from "@kubernetes/client-node";
|
||||
import { fireEvent } from "@testing-library/react";
|
||||
import type { RenderResult } from "@testing-library/react";
|
||||
import mockFs from "mock-fs";
|
||||
import * as selectEvent from "react-select-event";
|
||||
import type { CreateCluster } from "../../../../common/cluster/create-cluster-injection-token";
|
||||
import { createClusterInjectionToken } from "../../../../common/cluster/create-cluster-injection-token";
|
||||
import createContextHandlerInjectable from "../../../../main/context-handler/create-context-handler.injectable";
|
||||
import type { OpenDeleteClusterDialog } from "../open.injectable";
|
||||
import openDeleteClusterDialogInjectable from "../open.injectable";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../../stores-apis-can-be-created.injectable";
|
||||
import createKubeconfigManagerInjectable from "../../../../main/kubeconfig-manager/create-kubeconfig-manager.injectable";
|
||||
import type { ApplicationBuilder } from "../../test-utils/get-application-builder";
|
||||
@ -20,22 +17,8 @@ import { getApplicationBuilder } from "../../test-utils/get-application-builder"
|
||||
import normalizedPlatformInjectable from "../../../../common/vars/normalized-platform.injectable";
|
||||
import kubectlBinaryNameInjectable from "../../../../main/kubectl/binary-name.injectable";
|
||||
import kubectlDownloadingNormalizedArchInjectable from "../../../../main/kubectl/normalized-arch.injectable";
|
||||
|
||||
jest.mock("electron", () => ({
|
||||
app: {
|
||||
getVersion: () => "99.99.99",
|
||||
getName: () => "lens",
|
||||
setName: jest.fn(),
|
||||
setPath: jest.fn(),
|
||||
getPath: () => "tmp",
|
||||
getLocale: () => "en",
|
||||
setLoginItemSettings: jest.fn(),
|
||||
},
|
||||
ipcMain: {
|
||||
on: jest.fn(),
|
||||
handle: jest.fn(),
|
||||
},
|
||||
}));
|
||||
import type { OpenDeleteClusterDialog } from "../open.injectable";
|
||||
import openDeleteClusterDialogInjectable from "../open.injectable";
|
||||
|
||||
const currentClusterServerUrl = "https://localhost";
|
||||
const nonCurrentClusterServerUrl = "http://localhost";
|
||||
@ -87,65 +70,50 @@ users:
|
||||
token: kubeconfig-user-q4lm4:xxxyyyy
|
||||
`;
|
||||
|
||||
let config: KubeConfig;
|
||||
|
||||
describe("<DeleteClusterDialog />", () => {
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let createCluster: CreateCluster;
|
||||
let openDeleteClusterDialog: OpenDeleteClusterDialog;
|
||||
let builder: ApplicationBuilder;
|
||||
|
||||
beforeEach(async () => {
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
beforeEach(() => {
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ mainDi, rendererDi }) => {
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
mainDi.override(createContextHandlerInjectable, () => () => undefined as never);
|
||||
mainDi.override(createKubeconfigManagerInjectable, () => () => undefined as never);
|
||||
mainDi.override(kubectlBinaryNameInjectable, () => "kubectl");
|
||||
mainDi.override(kubectlDownloadingNormalizedArchInjectable, () => "amd64");
|
||||
mainDi.override(normalizedPlatformInjectable, () => "darwin");
|
||||
rendererDi.override(storesAndApisCanBeCreatedInjectable, () => true);
|
||||
});
|
||||
|
||||
mockFs();
|
||||
|
||||
applicationBuilder.beforeRender(({ rendererDi }) => {
|
||||
openDeleteClusterDialog = rendererDi.inject(openDeleteClusterDialogInjectable);
|
||||
createCluster = rendererDi.inject(createClusterInjectionToken);
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.override(storesAndApisCanBeCreatedInjectable, () => true);
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
mockFs.restore();
|
||||
});
|
||||
|
||||
it("shows context switcher when deleting current cluster", async () => {
|
||||
const mockOpts = {
|
||||
"temp-kube-config": multiClusterConfig,
|
||||
};
|
||||
const config = new KubeConfig();
|
||||
|
||||
mockFs(mockOpts);
|
||||
|
||||
config = new KubeConfig();
|
||||
config.loadFromString(multiClusterConfig);
|
||||
|
||||
applicationBuilder.beforeRender(({ rendererDi }) => {
|
||||
const createCluster = rendererDi.inject(createClusterInjectionToken);
|
||||
const rendered = await builder.render();
|
||||
|
||||
const cluster = createCluster({
|
||||
id: "some-current-context-cluster",
|
||||
contextName: "some-current-context",
|
||||
preferences: {
|
||||
clusterName: "some-current-context-cluster",
|
||||
},
|
||||
kubeConfigPath: "./temp-kube-config",
|
||||
}, {
|
||||
clusterServerUrl: currentClusterServerUrl,
|
||||
});
|
||||
const windowDi = builder.applicationWindow.only.di;
|
||||
|
||||
openDeleteClusterDialog({ cluster, config });
|
||||
const createCluster = windowDi.inject(createClusterInjectionToken);
|
||||
|
||||
const cluster = createCluster({
|
||||
id: "some-current-context-cluster",
|
||||
contextName: "some-current-context",
|
||||
preferences: {
|
||||
clusterName: "some-current-context-cluster",
|
||||
},
|
||||
kubeConfigPath: "./temp-kube-config",
|
||||
}, {
|
||||
clusterServerUrl: currentClusterServerUrl,
|
||||
});
|
||||
|
||||
const rendered = await applicationBuilder.render();
|
||||
const openDeleteClusterDialog = windowDi.inject(openDeleteClusterDialogInjectable);
|
||||
|
||||
openDeleteClusterDialog({ cluster, config });
|
||||
|
||||
const { getByText } = rendered;
|
||||
|
||||
@ -158,21 +126,23 @@ describe("<DeleteClusterDialog />", () => {
|
||||
expect(getByText("some-non-current-context")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
|
||||
describe("Kubeconfig with different clusters", () => {
|
||||
let rendered: RenderResult;
|
||||
let openDeleteClusterDialog: OpenDeleteClusterDialog;
|
||||
let createCluster: CreateCluster;
|
||||
let config: KubeConfig;
|
||||
|
||||
beforeEach(async () => {
|
||||
const mockOpts = {
|
||||
"temp-kube-config": multiClusterConfig,
|
||||
};
|
||||
|
||||
mockFs(mockOpts);
|
||||
|
||||
config = new KubeConfig();
|
||||
|
||||
config.loadFromString(multiClusterConfig);
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
rendered = await builder.render();
|
||||
|
||||
const windowDi = builder.applicationWindow.only.di;
|
||||
|
||||
openDeleteClusterDialog = windowDi.inject(openDeleteClusterDialogInjectable);
|
||||
createCluster = windowDi.inject(createClusterInjectionToken);
|
||||
});
|
||||
|
||||
it("renders w/o errors", () => {
|
||||
@ -268,18 +238,21 @@ describe("<DeleteClusterDialog />", () => {
|
||||
|
||||
describe("Kubeconfig with single cluster", () => {
|
||||
let rendered: RenderResult;
|
||||
let openDeleteClusterDialog: OpenDeleteClusterDialog;
|
||||
let createCluster: CreateCluster;
|
||||
let config: KubeConfig;
|
||||
|
||||
beforeEach(async () => {
|
||||
const mockOpts = {
|
||||
"temp-kube-config": singleClusterConfig,
|
||||
};
|
||||
|
||||
mockFs(mockOpts);
|
||||
|
||||
config = new KubeConfig();
|
||||
|
||||
config.loadFromString(singleClusterConfig);
|
||||
|
||||
rendered = await applicationBuilder.render();
|
||||
rendered = await builder.render();
|
||||
|
||||
const windowDi = builder.applicationWindow.only.di;
|
||||
|
||||
openDeleteClusterDialog = windowDi.inject(openDeleteClusterDialogInjectable);
|
||||
createCluster = windowDi.inject(createClusterInjectionToken);
|
||||
});
|
||||
|
||||
it("shows warning if no other contexts left", () => {
|
||||
|
||||
@ -14,6 +14,7 @@ import { cssNames, noop, stopPropagation } from "../../utils";
|
||||
import type { ObservableHistory } from "mobx-observable-history";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import observableHistoryInjectable from "../../navigation/observable-history.injectable";
|
||||
import requestAnimationFrameInjectable from "../animate/request-animation-frame.injectable";
|
||||
|
||||
// todo: refactor + handle animation-end in props.onClose()?
|
||||
|
||||
@ -37,6 +38,7 @@ interface DialogState {
|
||||
|
||||
interface Dependencies {
|
||||
navigation: ObservableHistory<unknown>;
|
||||
requestAnimationFrame: (callback: () => void) => void;
|
||||
}
|
||||
|
||||
@observer
|
||||
@ -95,7 +97,7 @@ class NonInjectedDialog extends React.PureComponent<DialogProps & Dependencies &
|
||||
}
|
||||
|
||||
open() {
|
||||
requestAnimationFrame(this.onOpen); // wait for render(), bind close-event to this.elem
|
||||
this.props.requestAnimationFrame(this.onOpen); // wait for render(), bind close-event to this.elem
|
||||
this.setState({ isOpen: true });
|
||||
this.props.open?.();
|
||||
}
|
||||
@ -182,5 +184,6 @@ export const Dialog = withInjectables<Dependencies, DialogProps>((props) => <Non
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
navigation: di.inject(observableHistoryInjectable),
|
||||
requestAnimationFrame: di.inject(requestAnimationFrameInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
@ -7,55 +7,40 @@ import React from "react";
|
||||
import "@testing-library/jest-dom/extend-expect";
|
||||
import type { IObservableArray } from "mobx";
|
||||
import { computed, observable } from "mobx";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import type { StatusBarItems } from "./status-bar-items.injectable";
|
||||
import statusBarItemsInjectable from "./status-bar-items.injectable";
|
||||
import { LensRendererExtension } from "../../../extensions/lens-renderer-extension";
|
||||
import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
import type { ApplicationBuilder } from "../test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../test-utils/get-application-builder";
|
||||
import getRandomIdInjectable from "../../../common/utils/get-random-id.injectable";
|
||||
|
||||
class SomeTestExtension extends LensRendererExtension {
|
||||
constructor(statusBarItems: IObservableArray<any>) {
|
||||
super({
|
||||
id: "some-id",
|
||||
absolutePath: "irrelevant",
|
||||
isBundled: false,
|
||||
isCompatible: false,
|
||||
isEnabled: false,
|
||||
manifest: { name: "some-id", version: "some-version", engines: { lens: "^5.5.0" }},
|
||||
manifestPath: "irrelevant",
|
||||
});
|
||||
|
||||
this.statusBarItems = statusBarItems;
|
||||
}
|
||||
}
|
||||
|
||||
describe("<StatusBar />", () => {
|
||||
let di: DiContainer;
|
||||
let statusBarItems: IObservableArray<any>;
|
||||
let applicationBuilder: ApplicationBuilder;
|
||||
let builder: ApplicationBuilder;
|
||||
|
||||
beforeEach(async () => {
|
||||
statusBarItems = observable.array([]);
|
||||
|
||||
applicationBuilder = getApplicationBuilder();
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
applicationBuilder.beforeApplicationStart(({ rendererDi }) => {
|
||||
rendererDi.unoverride(getRandomIdInjectable);
|
||||
rendererDi.permitSideEffects(getRandomIdInjectable);
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.unoverride(getRandomIdInjectable);
|
||||
windowDi.permitSideEffects(getRandomIdInjectable);
|
||||
windowDi.override(directoryForUserDataInjectable, () => "some-directory-for-user-data");
|
||||
});
|
||||
|
||||
applicationBuilder.extensions.renderer.enable(new SomeTestExtension(statusBarItems));
|
||||
|
||||
di = applicationBuilder.dis.rendererDi;
|
||||
builder.extensions.enable({
|
||||
id: "some-id",
|
||||
name: "some-name",
|
||||
|
||||
di.override(directoryForUserDataInjectable, () => "some-directory-for-user-data");
|
||||
rendererOptions: {
|
||||
statusBarItems,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("renders w/o errors", async () => {
|
||||
const { container } = await applicationBuilder.render();
|
||||
const { container } = await builder.render();
|
||||
|
||||
expect(container).toBeInstanceOf(HTMLElement);
|
||||
});
|
||||
@ -71,19 +56,21 @@ describe("<StatusBar />", () => {
|
||||
])("renders w/o errors when registrations are not type compliant (%p)", async val => {
|
||||
statusBarItems.replace([val]);
|
||||
|
||||
await expect(applicationBuilder.render()).resolves.toBeTruthy();
|
||||
await expect(builder.render()).resolves.toBeTruthy();
|
||||
});
|
||||
|
||||
it("renders items [{item: React.ReactNode}] (4.0.0-rc.1)", async () => {
|
||||
const testId = "testId";
|
||||
const text = "heee";
|
||||
|
||||
di.override(statusBarItemsInjectable, () => computed(() => ({
|
||||
right: [ () => <span data-testid={testId} >{text}</span> ],
|
||||
left: [],
|
||||
}) as StatusBarItems));
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.override(statusBarItemsInjectable, () => computed(() => ({
|
||||
right: [ () => <span data-testid={testId} >{text}</span> ],
|
||||
left: [],
|
||||
}) as StatusBarItems));
|
||||
});
|
||||
|
||||
const { getByTestId } = await applicationBuilder.render();
|
||||
const { getByTestId } = await builder.render();
|
||||
|
||||
expect(getByTestId(testId)).toHaveTextContent(text);
|
||||
});
|
||||
@ -96,7 +83,7 @@ describe("<StatusBar />", () => {
|
||||
item: () => <span data-testid={testId} >{text}</span>,
|
||||
}]);
|
||||
|
||||
const { getByTestId } = await applicationBuilder.render();
|
||||
const { getByTestId } = await builder.render();
|
||||
|
||||
expect(getByTestId(testId)).toHaveTextContent(text);
|
||||
});
|
||||
@ -129,7 +116,7 @@ describe("<StatusBar />", () => {
|
||||
},
|
||||
]);
|
||||
|
||||
const { getAllByTestId } = await applicationBuilder.render();
|
||||
const { getAllByTestId } = await builder.render();
|
||||
const elems = getAllByTestId("sortedElem");
|
||||
const positions = elems.map(elem => elem.textContent);
|
||||
|
||||
|
||||
@ -5,27 +5,24 @@
|
||||
import type { LensRendererExtension } from "../../../extensions/lens-renderer-extension";
|
||||
import rendererExtensionsInjectable from "../../../extensions/renderer-extensions.injectable";
|
||||
import currentlyInClusterFrameInjectable from "../../routes/currently-in-cluster-frame.injectable";
|
||||
import type { ObservableSet } from "mobx";
|
||||
import type { IComputedValue, ObservableMap } from "mobx";
|
||||
import { computed, observable, runInAction } from "mobx";
|
||||
import React from "react";
|
||||
import { Router } from "react-router";
|
||||
import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.injectable";
|
||||
import allowedResourcesInjectable from "../../cluster-frame-context/allowed-resources.injectable";
|
||||
import type { RenderResult } from "@testing-library/react";
|
||||
import { queryByText, fireEvent } from "@testing-library/react";
|
||||
import { fireEvent, queryByText } from "@testing-library/react";
|
||||
import type { KubeResource } from "../../../common/rbac";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import clusterStoreInjectable from "../../../common/cluster-store/cluster-store.injectable";
|
||||
import type { ClusterStore } from "../../../common/cluster-store/cluster-store";
|
||||
import type { DiContainer, Injectable } from "@ogre-tools/injectable";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import mainExtensionsInjectable from "../../../extensions/main-extensions.injectable";
|
||||
import { pipeline } from "@ogre-tools/fp";
|
||||
import { flatMap, compact, join, get, filter, map, matches, last } from "lodash/fp";
|
||||
import { compact, filter, first, flatMap, get, join, last, map, matches } from "lodash/fp";
|
||||
import preferenceNavigationItemsInjectable from "../+preferences/preferences-navigation/preference-navigation-items.injectable";
|
||||
import navigateToPreferencesInjectable from "../../../common/front-end-routing/routes/preferences/navigate-to-preferences.injectable";
|
||||
import type { MenuItemOpts } from "../../../main/menu/application-menu-items.injectable";
|
||||
import applicationMenuItemsInjectable from "../../../main/menu/application-menu-items.injectable";
|
||||
import type { MenuItemConstructorOptions, MenuItem } from "electron";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
|
||||
import type { MenuItem, MenuItemConstructorOptions } from "electron";
|
||||
import type { NavigateToHelmCharts } from "../../../common/front-end-routing/routes/cluster/helm/charts/navigate-to-helm-charts.injectable";
|
||||
import navigateToHelmChartsInjectable from "../../../common/front-end-routing/routes/cluster/helm/charts/navigate-to-helm-charts.injectable";
|
||||
import hostedClusterInjectable from "../../cluster-frame-context/hosted-cluster.injectable";
|
||||
@ -39,7 +36,6 @@ import type { NamespaceStore } from "../+namespaces/store";
|
||||
import historyInjectable from "../../navigation/history.injectable";
|
||||
import type { MinimalTrayMenuItem } from "../../../main/tray/electron-tray/electron-tray.injectable";
|
||||
import electronTrayInjectable from "../../../main/tray/electron-tray/electron-tray.injectable";
|
||||
import applicationWindowInjectable from "../../../main/start-main-application/lens-window/application-window/application-window.injectable";
|
||||
import { getDiForUnitTesting as getRendererDi } from "../../getDiForUnitTesting";
|
||||
import { getDiForUnitTesting as getMainDi } from "../../../main/getDiForUnitTesting";
|
||||
import { overrideChannels } from "../../../test-utils/channel-fakes/override-channels";
|
||||
@ -52,7 +48,6 @@ import type { NavigateToRouteOptions } from "../../../common/front-end-routing/n
|
||||
import { navigateToRouteInjectionToken } from "../../../common/front-end-routing/navigate-to-route-injection-token";
|
||||
import type { LensMainExtension } from "../../../extensions/lens-main-extension";
|
||||
import type { LensExtension } from "../../../extensions/lens-extension";
|
||||
|
||||
import extensionInjectable from "../../../extensions/extension-loader/extension/extension.injectable";
|
||||
import { renderFor } from "./renderFor";
|
||||
import { RootFrame } from "../../frames/root-frame/root-frame";
|
||||
@ -62,34 +57,50 @@ import activeKubernetesClusterInjectable from "../../cluster-frame-context/activ
|
||||
import { catalogEntityFromCluster } from "../../../main/cluster-manager";
|
||||
import namespaceStoreInjectable from "../+namespaces/store.injectable";
|
||||
import { isAllowedResource } from "../../../common/cluster/is-allowed-resource";
|
||||
import createApplicationWindowInjectable from "../../../main/start-main-application/lens-window/application-window/create-application-window.injectable";
|
||||
import type { CreateElectronWindow } from "../../../main/start-main-application/lens-window/application-window/create-electron-window.injectable";
|
||||
import createElectronWindowInjectable from "../../../main/start-main-application/lens-window/application-window/create-electron-window.injectable";
|
||||
import { applicationWindowInjectionToken } from "../../../main/start-main-application/lens-window/application-window/application-window-injection-token";
|
||||
import sendToChannelInElectronBrowserWindowInjectable from "../../../main/start-main-application/lens-window/application-window/send-to-channel-in-electron-browser-window.injectable";
|
||||
import closeAllWindowsInjectable from "../../../main/start-main-application/lens-window/hide-all-windows/close-all-windows.injectable";
|
||||
import type { LensWindow } from "../../../main/start-main-application/lens-window/application-window/create-lens-window.injectable";
|
||||
import type { FakeExtensionOptions } from "./get-extension-fake";
|
||||
import { getExtensionFakeForMain, getExtensionFakeForRenderer } from "./get-extension-fake";
|
||||
|
||||
type Callback = (dis: DiContainers) => void | Promise<void>;
|
||||
type Callback = (di: DiContainer) => void | Promise<void>;
|
||||
|
||||
type EnableExtensions<T> = (...extensions: T[]) => void;
|
||||
type DisableExtensions<T> = (...extensions: T[]) => void;
|
||||
type LensWindowWithHelpers = LensWindow & { rendered: RenderResult; di: DiContainer };
|
||||
|
||||
export interface ApplicationBuilder {
|
||||
dis: DiContainers;
|
||||
mainDi: DiContainer;
|
||||
setEnvironmentToClusterFrame: () => ApplicationBuilder;
|
||||
|
||||
extensions: {
|
||||
renderer: {
|
||||
enable: EnableExtensions<LensRendererExtension>;
|
||||
disable: DisableExtensions<LensRendererExtension>;
|
||||
};
|
||||
enable: (...extensions: FakeExtensionOptions[]) => void;
|
||||
disable: (...extensions: FakeExtensionOptions[]) => void;
|
||||
|
||||
main: {
|
||||
enable: EnableExtensions<LensMainExtension>;
|
||||
disable: DisableExtensions<LensMainExtension>;
|
||||
};
|
||||
get: (id: string) => {
|
||||
main: LensMainExtension;
|
||||
|
||||
enable: (...extensions: { renderer: LensRendererExtension; main: LensMainExtension }[]) => void;
|
||||
disable: (...extensions: { renderer: LensRendererExtension; main: LensMainExtension }[]) => void;
|
||||
applicationWindows: Record<string, LensRendererExtension> & {
|
||||
only: LensRendererExtension;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
applicationWindow: {
|
||||
closeAll: () => void;
|
||||
only: LensWindowWithHelpers;
|
||||
get: (id: string) => LensWindowWithHelpers;
|
||||
getAll: () => LensWindowWithHelpers[];
|
||||
create: (id: string) => LensWindowWithHelpers;
|
||||
};
|
||||
|
||||
allowKubeResource: (resourceName: KubeResource) => ApplicationBuilder;
|
||||
beforeApplicationStart: (callback: Callback) => ApplicationBuilder;
|
||||
beforeRender: (callback: Callback) => ApplicationBuilder;
|
||||
beforeWindowStart: (callback: Callback) => ApplicationBuilder;
|
||||
|
||||
startHidden: () => Promise<void>;
|
||||
render: () => Promise<RenderResult>;
|
||||
|
||||
tray: {
|
||||
@ -116,17 +127,12 @@ export interface ApplicationBuilder {
|
||||
};
|
||||
|
||||
select: {
|
||||
openMenu: (id: string) => ({ selectOption: (labelText: string) => void });
|
||||
openMenu: (id: string) => { selectOption: (labelText: string) => void };
|
||||
selectOption: (menuId: string, labelText: string) => void;
|
||||
getValue: (menuId: string) => string;
|
||||
};
|
||||
}
|
||||
|
||||
interface DiContainers {
|
||||
rendererDi: DiContainer;
|
||||
mainDi: DiContainer;
|
||||
}
|
||||
|
||||
interface Environment {
|
||||
RootComponent: React.ElementType;
|
||||
onAllowKubeResource: () => void;
|
||||
@ -137,64 +143,22 @@ export const getApplicationBuilder = () => {
|
||||
doGeneralOverrides: true,
|
||||
});
|
||||
|
||||
mainDi.register(mainExtensionsStateInjectable);
|
||||
|
||||
const overrideChannelsForWindow = overrideChannels(mainDi);
|
||||
|
||||
const rendererDi = getRendererDi({
|
||||
doGeneralOverrides: true,
|
||||
});
|
||||
|
||||
overrideChannelsForWindow(rendererDi);
|
||||
|
||||
const dis = { rendererDi, mainDi };
|
||||
|
||||
const clusterStoreStub = {
|
||||
provideInitialFromMain: () => {},
|
||||
getById: (): null => null,
|
||||
} as unknown as ClusterStore;
|
||||
|
||||
rendererDi.override(clusterStoreInjectable, () => clusterStoreStub);
|
||||
rendererDi.override(storesAndApisCanBeCreatedInjectable, () => true);
|
||||
mainDi.override(clusterStoreInjectable, () => clusterStoreStub);
|
||||
|
||||
const beforeApplicationStartCallbacks: Callback[] = [];
|
||||
const beforeRenderCallbacks: Callback[] = [];
|
||||
|
||||
const rendererExtensionsState = observable.set<LensRendererExtension>();
|
||||
const mainExtensionsState = observable.set<LensMainExtension>();
|
||||
|
||||
rendererDi.override(subscribeStoresInjectable, () => () => () => {});
|
||||
|
||||
const environments = {
|
||||
application: {
|
||||
RootComponent: RootFrame,
|
||||
|
||||
onAllowKubeResource: () => {
|
||||
throw new Error(
|
||||
"Tried to allow kube resource when environment is not cluster frame.",
|
||||
);
|
||||
},
|
||||
} as Environment,
|
||||
|
||||
clusterFrame: {
|
||||
RootComponent: ClusterFrame,
|
||||
onAllowKubeResource: () => {},
|
||||
} as Environment,
|
||||
};
|
||||
const beforeWindowStartCallbacks: Callback[] = [];
|
||||
|
||||
let environment = environments.application;
|
||||
|
||||
rendererDi.override(
|
||||
currentlyInClusterFrameInjectable,
|
||||
() => environment === environments.clusterFrame,
|
||||
);
|
||||
mainDi.override(mainExtensionsInjectable, (di) => {
|
||||
const mainExtensionsState = di.inject(mainExtensionsStateInjectable);
|
||||
|
||||
rendererDi.override(rendererExtensionsInjectable, () =>
|
||||
computed(() => [...rendererExtensionsState]),
|
||||
);
|
||||
|
||||
mainDi.override(mainExtensionsInjectable, () =>
|
||||
computed(() => [...mainExtensionsState]),
|
||||
);
|
||||
return computed(() =>
|
||||
[...mainExtensionsState.values()],
|
||||
);
|
||||
});
|
||||
|
||||
let trayMenuIconPath: string;
|
||||
|
||||
@ -209,60 +173,135 @@ export const getApplicationBuilder = () => {
|
||||
},
|
||||
}));
|
||||
|
||||
let allowedResourcesState: KubeResource[];
|
||||
let rendered: RenderResult;
|
||||
const allowedResourcesState = observable.array<KubeResource>();
|
||||
|
||||
const enableExtensionsFor = <T extends ObservableSet>(
|
||||
extensionState: T,
|
||||
di: DiContainer,
|
||||
) => {
|
||||
const getExtension = (extension: LensExtension) =>
|
||||
di.inject(extensionInjectable, extension);
|
||||
const windowHelpers = new Map<string, { di: DiContainer; getRendered: () => RenderResult }>();
|
||||
|
||||
return (...extensionInstances: LensExtension[]) => {
|
||||
const addAndEnableExtensions = () => {
|
||||
extensionInstances.forEach(instance => {
|
||||
const extension = getExtension(instance);
|
||||
const createElectronWindowFake: CreateElectronWindow = (configuration) => {
|
||||
const windowId = configuration.id;
|
||||
|
||||
extension.register();
|
||||
});
|
||||
const windowDi = getRendererDi({ doGeneralOverrides: true });
|
||||
|
||||
runInAction(() => {
|
||||
extensionInstances.forEach((extension) => {
|
||||
extensionState.add(extension);
|
||||
});
|
||||
});
|
||||
};
|
||||
overrideChannelsForWindow(windowDi, windowId);
|
||||
|
||||
if (rendered) {
|
||||
addAndEnableExtensions();
|
||||
} else {
|
||||
builder.beforeRender(addAndEnableExtensions);
|
||||
}
|
||||
windowDi.register(rendererExtensionsStateInjectable);
|
||||
|
||||
windowDi.override(
|
||||
currentlyInClusterFrameInjectable,
|
||||
() => environment === environments.clusterFrame,
|
||||
);
|
||||
|
||||
windowDi.override(rendererExtensionsInjectable, (di) => {
|
||||
const rendererExtensionState = di.inject(rendererExtensionsStateInjectable);
|
||||
|
||||
return computed(() => [...rendererExtensionState.values()]);
|
||||
});
|
||||
|
||||
let rendered: RenderResult;
|
||||
|
||||
windowHelpers.set(windowId, { di: windowDi, getRendered: () => rendered });
|
||||
|
||||
return {
|
||||
show: () => {},
|
||||
close: () => {},
|
||||
loadFile: async () => {},
|
||||
loadUrl: async () => {
|
||||
for (const callback of beforeWindowStartCallbacks) {
|
||||
await callback(windowDi);
|
||||
}
|
||||
|
||||
const startFrame = windowDi.inject(startFrameInjectable);
|
||||
|
||||
await startFrame();
|
||||
|
||||
const history = windowDi.inject(historyInjectable);
|
||||
|
||||
const render = renderFor(windowDi);
|
||||
|
||||
rendered = render(
|
||||
<Router history={history}>
|
||||
<environment.RootComponent />
|
||||
</Router>,
|
||||
);
|
||||
},
|
||||
|
||||
send: (arg) => {
|
||||
const sendFake = mainDi.inject(sendToChannelInElectronBrowserWindowInjectable) as any;
|
||||
|
||||
sendFake(windowId, null, arg);
|
||||
},
|
||||
|
||||
reload: () => {
|
||||
throw new Error("Tried to reload application window which is not implemented yet.");
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const enableRendererExtension = enableExtensionsFor(rendererExtensionsState, rendererDi);
|
||||
const enableMainExtension = enableExtensionsFor(mainExtensionsState, mainDi);
|
||||
const disableRendererExtension = disableExtensionsFor(rendererExtensionsState, rendererDi);
|
||||
const disableMainExtension = disableExtensionsFor(mainExtensionsState, mainDi);
|
||||
mainDi.override(createElectronWindowInjectable, () => createElectronWindowFake);
|
||||
|
||||
const selectOptionFor = (menuId: string) => (labelText: string) => {
|
||||
const menuOptions = rendered.baseElement.querySelector<HTMLElement>(
|
||||
`.${menuId}-options`,
|
||||
);
|
||||
|
||||
assert(menuOptions, `Could not find select options for menu with ID "${menuId}"`);
|
||||
|
||||
const option = queryByText(menuOptions, labelText);
|
||||
|
||||
assert(option, `Could not find select option with label "${labelText}" for menu with ID "${menuId}"`);
|
||||
|
||||
userEvent.click(option);
|
||||
};
|
||||
let applicationHasStarted = false;
|
||||
|
||||
const builder: ApplicationBuilder = {
|
||||
dis,
|
||||
mainDi,
|
||||
|
||||
applicationWindow: {
|
||||
closeAll: () => {
|
||||
const closeAll = mainDi.inject(closeAllWindowsInjectable);
|
||||
|
||||
closeAll();
|
||||
|
||||
document.documentElement.innerHTML = "";
|
||||
},
|
||||
|
||||
get only() {
|
||||
const applicationWindows = builder.applicationWindow.getAll();
|
||||
|
||||
if (applicationWindows.length > 1) {
|
||||
throw new Error(
|
||||
"Tried to get only application window when there are multiple windows.",
|
||||
);
|
||||
}
|
||||
|
||||
const applicationWindow = first(applicationWindows);
|
||||
|
||||
if (!applicationWindow) {
|
||||
throw new Error(
|
||||
"Tried to get only application window when there are no windows.",
|
||||
);
|
||||
}
|
||||
|
||||
return applicationWindow;
|
||||
},
|
||||
|
||||
getAll: () =>
|
||||
mainDi
|
||||
.injectMany(applicationWindowInjectionToken)
|
||||
.map(toWindowWithHelpersFor(windowHelpers)),
|
||||
|
||||
get: (id) => {
|
||||
const applicationWindows = builder.applicationWindow.getAll();
|
||||
|
||||
const applicationWindow = applicationWindows.find(
|
||||
(window) => window.id === id,
|
||||
);
|
||||
|
||||
if (!applicationWindow) {
|
||||
throw new Error(`Tried to get application window with ID "${id}" but it was not found.`);
|
||||
}
|
||||
|
||||
return applicationWindow;
|
||||
},
|
||||
|
||||
create: (id) => {
|
||||
const createApplicationWindow = mainDi.inject(
|
||||
createApplicationWindowInjectable,
|
||||
);
|
||||
|
||||
createApplicationWindow(id);
|
||||
|
||||
return builder.applicationWindow.get(id);
|
||||
},
|
||||
},
|
||||
|
||||
applicationMenu: {
|
||||
click: (path: string) => {
|
||||
@ -340,29 +379,39 @@ export const getApplicationBuilder = () => {
|
||||
|
||||
preferences: {
|
||||
close: () => {
|
||||
const rendered = builder.applicationWindow.only.rendered;
|
||||
|
||||
const link = rendered.getByTestId("close-preferences");
|
||||
|
||||
fireEvent.click(link);
|
||||
},
|
||||
|
||||
navigate: () => {
|
||||
const navigateToPreferences = rendererDi.inject(navigateToPreferencesInjectable);
|
||||
const windowDi = builder.applicationWindow.only.di;
|
||||
|
||||
const navigateToPreferences = windowDi.inject(
|
||||
navigateToPreferencesInjectable,
|
||||
);
|
||||
|
||||
navigateToPreferences();
|
||||
},
|
||||
|
||||
navigateTo: (route: Route<any>, params: Partial<NavigateToRouteOptions<any>>) => {
|
||||
const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken);
|
||||
const windowDi = builder.applicationWindow.only.di;
|
||||
|
||||
const navigateToRoute = windowDi.inject(navigateToRouteInjectionToken);
|
||||
|
||||
navigateToRoute(route, params);
|
||||
},
|
||||
|
||||
navigation: {
|
||||
click: (id: string) => {
|
||||
const { di: windowDi, rendered } = builder.applicationWindow.only;
|
||||
|
||||
const link = rendered.queryByTestId(`tab-link-for-${id}`);
|
||||
|
||||
if (!link) {
|
||||
const preferencesNavigationItems = rendererDi.inject(
|
||||
const preferencesNavigationItems = windowDi.inject(
|
||||
preferenceNavigationItemsInjectable,
|
||||
);
|
||||
|
||||
@ -382,7 +431,11 @@ export const getApplicationBuilder = () => {
|
||||
|
||||
helmCharts: {
|
||||
navigate: (parameters) => {
|
||||
const navigateToHelmCharts = rendererDi.inject(navigateToHelmChartsInjectable);
|
||||
const windowDi = builder.applicationWindow.only.di;
|
||||
|
||||
const navigateToHelmCharts = windowDi.inject(
|
||||
navigateToHelmChartsInjectable,
|
||||
);
|
||||
|
||||
navigateToHelmCharts(parameters);
|
||||
},
|
||||
@ -391,81 +444,129 @@ export const getApplicationBuilder = () => {
|
||||
setEnvironmentToClusterFrame: () => {
|
||||
environment = environments.clusterFrame;
|
||||
|
||||
allowedResourcesState = observable.array();
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.override(allowedResourcesInjectable, () =>
|
||||
computed(() => new Set([...allowedResourcesState])),
|
||||
);
|
||||
|
||||
rendererDi.override(allowedResourcesInjectable, () =>
|
||||
computed(() => new Set([...allowedResourcesState])),
|
||||
);
|
||||
const clusterStub = {
|
||||
accessibleNamespaces: [],
|
||||
isAllowedResource: isAllowedResource(allowedResourcesState),
|
||||
} as unknown as Cluster;
|
||||
|
||||
const clusterStub = {
|
||||
accessibleNamespaces: [],
|
||||
isAllowedResource: isAllowedResource(allowedResourcesState),
|
||||
} as unknown as Cluster;
|
||||
windowDi.override(activeKubernetesClusterInjectable, () =>
|
||||
computed(() => catalogEntityFromCluster(clusterStub)),
|
||||
);
|
||||
|
||||
rendererDi.override(activeKubernetesClusterInjectable, () =>
|
||||
computed(() => catalogEntityFromCluster(clusterStub)),
|
||||
);
|
||||
// TODO: Figure out a way to remove this stub.
|
||||
const namespaceStoreStub = {
|
||||
isLoaded: true,
|
||||
contextNamespaces: [],
|
||||
contextItems: [],
|
||||
api: {
|
||||
kind: "Namespace",
|
||||
},
|
||||
items: [],
|
||||
selectNamespaces: () => {},
|
||||
getByPath: () => undefined,
|
||||
pickOnlySelected: () => [],
|
||||
isSelectedAll: () => false,
|
||||
getTotalCount: () => 0,
|
||||
} as unknown as NamespaceStore;
|
||||
|
||||
// TODO: Figure out a way to remove this stub.
|
||||
const namespaceStoreStub = {
|
||||
isLoaded: true,
|
||||
contextNamespaces: [],
|
||||
contextItems: [],
|
||||
api: {
|
||||
kind: "Namespace",
|
||||
},
|
||||
items: [],
|
||||
selectNamespaces: () => {},
|
||||
getByPath: () => undefined,
|
||||
pickOnlySelected: () => [],
|
||||
isSelectedAll: () => false,
|
||||
getTotalCount: () => 0,
|
||||
} as unknown as NamespaceStore;
|
||||
const clusterFrameContextFake = new ClusterFrameContext(
|
||||
clusterStub,
|
||||
|
||||
const clusterFrameContextFake = new ClusterFrameContext(
|
||||
clusterStub,
|
||||
{
|
||||
namespaceStore: namespaceStoreStub,
|
||||
},
|
||||
);
|
||||
|
||||
{
|
||||
namespaceStore: namespaceStoreStub,
|
||||
},
|
||||
);
|
||||
windowDi.override(namespaceStoreInjectable, () => namespaceStoreStub);
|
||||
windowDi.override(hostedClusterInjectable, () => clusterStub);
|
||||
windowDi.override(hostedClusterIdInjectable, () => "irrelevant-hosted-cluster-id");
|
||||
windowDi.override(clusterFrameContextInjectable, () => clusterFrameContextFake);
|
||||
|
||||
rendererDi.override(namespaceStoreInjectable, () => namespaceStoreStub);
|
||||
rendererDi.override(hostedClusterInjectable, () => clusterStub);
|
||||
rendererDi.override(hostedClusterIdInjectable, () => "irrelevant-hosted-cluster-id");
|
||||
rendererDi.override(clusterFrameContextInjectable, () => clusterFrameContextFake);
|
||||
|
||||
// Todo: get rid of global state.
|
||||
KubeObjectStore.defaultContext.set(clusterFrameContextFake);
|
||||
// Todo: get rid of global state.
|
||||
KubeObjectStore.defaultContext.set(clusterFrameContextFake);
|
||||
});
|
||||
|
||||
return builder;
|
||||
},
|
||||
|
||||
extensions: {
|
||||
renderer: {
|
||||
enable: enableRendererExtension,
|
||||
disable: disableRendererExtension,
|
||||
},
|
||||
get: (id: string) => {
|
||||
const windowInstances = pipeline(
|
||||
builder.applicationWindow.getAll(),
|
||||
|
||||
main: {
|
||||
enable: enableMainExtension,
|
||||
disable: disableMainExtension,
|
||||
map((window): [string, LensRendererExtension] => [
|
||||
window.id,
|
||||
findExtensionInstance(window.di, rendererExtensionsInjectable, id),
|
||||
]),
|
||||
|
||||
items => Object.fromEntries(items),
|
||||
);
|
||||
|
||||
return {
|
||||
main: findExtensionInstance(mainDi, mainExtensionsInjectable, id),
|
||||
|
||||
applicationWindows: {
|
||||
get only() {
|
||||
return findExtensionInstance(
|
||||
builder.applicationWindow.only.di,
|
||||
rendererExtensionsInjectable,
|
||||
id,
|
||||
);
|
||||
},
|
||||
|
||||
...windowInstances,
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
enable: (...extensions) => {
|
||||
const rendererExtensions = extensions.map(extension => extension.renderer);
|
||||
const mainExtensions = extensions.map(extension => extension.main);
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
const rendererExtensionInstances = extensions.map((options) =>
|
||||
getExtensionFakeForRenderer(
|
||||
windowDi,
|
||||
options.id,
|
||||
options.name,
|
||||
options.rendererOptions || {},
|
||||
),
|
||||
);
|
||||
|
||||
enableRendererExtension(...rendererExtensions);
|
||||
enableMainExtension(...mainExtensions);
|
||||
rendererExtensionInstances.forEach(
|
||||
enableExtensionFor(windowDi, rendererExtensionsStateInjectable),
|
||||
);
|
||||
});
|
||||
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
const mainExtensionInstances = extensions.map((extension) =>
|
||||
getExtensionFakeForMain(mainDi, extension.id, extension.name, extension.mainOptions || {}),
|
||||
);
|
||||
|
||||
mainExtensionInstances.forEach(
|
||||
enableExtensionFor(mainDi, mainExtensionsStateInjectable),
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
disable: (...extensions) => {
|
||||
const rendererExtensions = extensions.map(extension => extension.renderer);
|
||||
const mainExtensions = extensions.map(extension => extension.main);
|
||||
builder.beforeWindowStart(windowDi => {
|
||||
extensions
|
||||
.map((ext) => ext.id)
|
||||
.forEach(
|
||||
disableExtensionFor(windowDi, rendererExtensionsStateInjectable),
|
||||
);
|
||||
});
|
||||
|
||||
disableRendererExtension(...rendererExtensions);
|
||||
disableMainExtension(...mainExtensions);
|
||||
builder.beforeApplicationStart(mainDi => {
|
||||
extensions
|
||||
.map((ext) => ext.id)
|
||||
.forEach(
|
||||
disableExtensionFor(mainDi, mainExtensionsStateInjectable),
|
||||
);
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
@ -479,56 +580,72 @@ export const getApplicationBuilder = () => {
|
||||
return builder;
|
||||
},
|
||||
|
||||
beforeApplicationStart(callback: (dis: DiContainers) => void) {
|
||||
beforeApplicationStart(callback) {
|
||||
if (applicationHasStarted) {
|
||||
callback(mainDi);
|
||||
}
|
||||
|
||||
beforeApplicationStartCallbacks.push(callback);
|
||||
|
||||
return builder;
|
||||
},
|
||||
|
||||
beforeRender(callback: (dis: DiContainers) => void) {
|
||||
beforeRenderCallbacks.push(callback);
|
||||
beforeWindowStart(callback) {
|
||||
const alreadyRenderedWindows = builder.applicationWindow.getAll();
|
||||
|
||||
alreadyRenderedWindows.forEach((window) => {
|
||||
callback(window.di);
|
||||
});
|
||||
|
||||
beforeWindowStartCallbacks.push(callback);
|
||||
|
||||
return builder;
|
||||
},
|
||||
|
||||
startHidden: async () => {
|
||||
mainDi.inject(lensProxyPortInjectable).set(42);
|
||||
|
||||
for (const callback of beforeApplicationStartCallbacks) {
|
||||
await callback(mainDi);
|
||||
}
|
||||
|
||||
const startMainApplication = mainDi.inject(
|
||||
startMainApplicationInjectable,
|
||||
);
|
||||
|
||||
await startMainApplication(false);
|
||||
|
||||
applicationHasStarted = true;
|
||||
},
|
||||
|
||||
async render() {
|
||||
mainDi.inject(lensProxyPortInjectable).set(42);
|
||||
|
||||
for (const callback of beforeApplicationStartCallbacks) {
|
||||
await callback(dis);
|
||||
await callback(mainDi);
|
||||
}
|
||||
|
||||
const startMainApplication = mainDi.inject(startMainApplicationInjectable);
|
||||
|
||||
await startMainApplication();
|
||||
|
||||
const applicationWindow = mainDi.inject(applicationWindowInjectable);
|
||||
|
||||
await applicationWindow.start();
|
||||
|
||||
const startFrame = rendererDi.inject(startFrameInjectable);
|
||||
|
||||
await startFrame();
|
||||
|
||||
for (const callback of beforeRenderCallbacks) {
|
||||
await callback(dis);
|
||||
}
|
||||
|
||||
const history = rendererDi.inject(historyInjectable);
|
||||
|
||||
const render = renderFor(rendererDi);
|
||||
|
||||
rendered = render(
|
||||
<Router history={history}>
|
||||
<environment.RootComponent />
|
||||
</Router>,
|
||||
const startMainApplication = mainDi.inject(
|
||||
startMainApplicationInjectable,
|
||||
);
|
||||
|
||||
return rendered;
|
||||
await startMainApplication(true);
|
||||
|
||||
applicationHasStarted = true;
|
||||
|
||||
const applicationWindow = builder.applicationWindow.get(
|
||||
"first-application-window",
|
||||
);
|
||||
|
||||
assert(applicationWindow);
|
||||
|
||||
return applicationWindow.rendered;
|
||||
},
|
||||
|
||||
select: {
|
||||
openMenu: (menuId) => {
|
||||
const rendered = builder.applicationWindow.only.rendered;
|
||||
|
||||
const select = rendered.baseElement.querySelector<HTMLElement>(
|
||||
`#${menuId}`,
|
||||
);
|
||||
@ -538,13 +655,15 @@ export const getApplicationBuilder = () => {
|
||||
openMenu(select);
|
||||
|
||||
return {
|
||||
selectOption: selectOptionFor(menuId),
|
||||
selectOption: selectOptionFor(builder, menuId),
|
||||
};
|
||||
},
|
||||
|
||||
selectOption: (menuId, labelText) => selectOptionFor(menuId)(labelText),
|
||||
selectOption: (menuId, labelText) => selectOptionFor(builder, menuId)(labelText),
|
||||
|
||||
getValue: (menuId) => {
|
||||
const rendered = builder.applicationWindow.only.rendered;
|
||||
|
||||
const select = rendered.baseElement.querySelector<HTMLInputElement>(
|
||||
`#${menuId}`,
|
||||
);
|
||||
@ -582,22 +701,134 @@ function toFlatChildren(parentId: string | null | undefined): ToFlatChildren {
|
||||
];
|
||||
}
|
||||
|
||||
const disableExtensionsFor = <T extends ObservableSet>(
|
||||
extensionState: T,
|
||||
export const rendererExtensionsStateInjectable = getInjectable({
|
||||
id: "renderer-extensions-state",
|
||||
instantiate: () => observable.map<string, LensRendererExtension>(),
|
||||
});
|
||||
|
||||
const mainExtensionsStateInjectable = getInjectable({
|
||||
id: "main-extensions-state",
|
||||
instantiate: () => observable.map<string, LensMainExtension>(),
|
||||
});
|
||||
|
||||
const findExtensionInstance = <T extends LensExtension> (di: DiContainer, injectable: Injectable<IComputedValue<T[]>, any, any>, id: string) => {
|
||||
const instance = di.inject(injectable).get().find(ext => ext.id === id);
|
||||
|
||||
if (!instance) {
|
||||
throw new Error(`Tried to get extension with ID ${id}, but it didn't exist`);
|
||||
}
|
||||
|
||||
return instance;
|
||||
};
|
||||
|
||||
type ApplicationWindowHelpers = Map<string, { di: DiContainer; getRendered: () => RenderResult }>;
|
||||
|
||||
const toWindowWithHelpersFor =
|
||||
(windowHelpers: ApplicationWindowHelpers) => (applicationWindow: LensWindow) => ({
|
||||
...applicationWindow,
|
||||
|
||||
get rendered() {
|
||||
const helpers = windowHelpers.get(applicationWindow.id);
|
||||
|
||||
if (!helpers) {
|
||||
throw new Error(
|
||||
`Tried to get rendered for application window "${applicationWindow.id}" before it was started.`,
|
||||
);
|
||||
}
|
||||
|
||||
return helpers.getRendered();
|
||||
},
|
||||
|
||||
get di() {
|
||||
const helpers = windowHelpers.get(applicationWindow.id);
|
||||
|
||||
if (!helpers) {
|
||||
throw new Error(
|
||||
`Tried to get di for application window "${applicationWindow.id}" before it was started.`,
|
||||
);
|
||||
}
|
||||
|
||||
return helpers.di;
|
||||
},
|
||||
});
|
||||
|
||||
const environments = {
|
||||
application: {
|
||||
RootComponent: RootFrame,
|
||||
|
||||
onAllowKubeResource: () => {
|
||||
throw new Error(
|
||||
"Tried to allow kube resource when environment is not cluster frame.",
|
||||
);
|
||||
},
|
||||
} as Environment,
|
||||
|
||||
clusterFrame: {
|
||||
RootComponent: ClusterFrame,
|
||||
onAllowKubeResource: () => {},
|
||||
} as Environment,
|
||||
};
|
||||
|
||||
const selectOptionFor = (builder: ApplicationBuilder, menuId: string) => (labelText: string) => {
|
||||
const rendered = builder.applicationWindow.only.rendered;
|
||||
|
||||
const menuOptions = rendered.baseElement.querySelector<HTMLElement>(
|
||||
`.${menuId}-options`,
|
||||
);
|
||||
|
||||
assert(menuOptions, `Could not find select options for menu with ID "${menuId}"`);
|
||||
|
||||
const option = queryByText(menuOptions, labelText);
|
||||
|
||||
assert(option, `Could not find select option with label "${labelText}" for menu with ID "${menuId}"`);
|
||||
|
||||
userEvent.click(option);
|
||||
};
|
||||
|
||||
const enableExtensionFor = (
|
||||
di: DiContainer,
|
||||
stateInjectable: Injectable<ObservableMap<string, any>, any, any>,
|
||||
) => {
|
||||
const getExtension = (instance: LensExtension) =>
|
||||
di.inject(extensionInjectable, instance);
|
||||
const extensionState = di.inject(stateInjectable);
|
||||
|
||||
return (...extensionInstances: LensExtension[]) => {
|
||||
extensionInstances.forEach((instance) => {
|
||||
const extension = getExtension(instance);
|
||||
const getExtension = (extension: LensExtension) =>
|
||||
di.inject(extensionInjectable, extension);
|
||||
|
||||
runInAction(() => {
|
||||
extension.deregister();
|
||||
return (extensionInstance: LensExtension) => {
|
||||
const extension = getExtension(extensionInstance);
|
||||
|
||||
extensionState.delete(instance);
|
||||
});
|
||||
runInAction(() => {
|
||||
extension.register();
|
||||
extensionState.set(extensionInstance.id, extensionInstance);
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
const disableExtensionFor =
|
||||
(
|
||||
di: DiContainer,
|
||||
stateInjectable: Injectable<ObservableMap<string, any>, unknown, void>,
|
||||
) =>
|
||||
(id: string) => {
|
||||
const getExtension = (extension: LensExtension) =>
|
||||
di.inject(extensionInjectable, extension);
|
||||
|
||||
const extensionsState = di.inject(stateInjectable);
|
||||
|
||||
const instance = extensionsState.get(id);
|
||||
|
||||
if (!instance) {
|
||||
throw new Error(
|
||||
`Tried to disable extension with ID "${id}", but it wasn't enabled`,
|
||||
);
|
||||
}
|
||||
|
||||
const injectable = getExtension(instance);
|
||||
|
||||
runInAction(() => {
|
||||
injectable.deregister();
|
||||
|
||||
extensionsState.delete(id);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
import type { Mutable } from "type-fest";
|
||||
import fileSystemProvisionerStoreInjectable from "../../../extensions/extension-loader/file-system-provisioner-store/file-system-provisioner-store.injectable";
|
||||
import { lensExtensionDependencies } from "../../../extensions/lens-extension";
|
||||
import type { ApplicationBuilder } from "./get-application-builder";
|
||||
import { LensMainExtension } from "../../../extensions/lens-main-extension";
|
||||
import navigateForExtensionInjectable from "../../../main/start-main-application/lens-window/navigate-for-extension.injectable";
|
||||
import { LensRendererExtension } from "../../../extensions/lens-renderer-extension";
|
||||
@ -27,21 +26,7 @@ export interface FakeExtensionOptions {
|
||||
mainOptions?: Partial<LensMainExtension>;
|
||||
}
|
||||
|
||||
export type GetExtensionFake = (arg: FakeExtensionOptions) => {
|
||||
main: TestExtensionMain;
|
||||
renderer: TestExtensionRenderer;
|
||||
};
|
||||
|
||||
export const getExtensionFakeFor =
|
||||
(builder: ApplicationBuilder): GetExtensionFake =>
|
||||
({ id, name, mainOptions = {}, rendererOptions = {}}) => {
|
||||
const mainInstance = getExtensionFakeForMain(builder.dis.mainDi, id, name, mainOptions);
|
||||
const rendererInstance = getExtensionFakeForRenderer(builder.dis.rendererDi, id, name, rendererOptions);
|
||||
|
||||
return { main: mainInstance, renderer: rendererInstance };
|
||||
};
|
||||
|
||||
const getExtensionFakeForMain = (di: DiContainer, id: string, name: string, options: Partial<LensMainExtension>) => {
|
||||
export const getExtensionFakeForMain = (di: DiContainer, id: string, name: string, options: Partial<LensMainExtension>) => {
|
||||
const instance = new TestExtensionMain({
|
||||
id,
|
||||
absolutePath: "irrelevant",
|
||||
@ -71,7 +56,7 @@ const getExtensionFakeForMain = (di: DiContainer, id: string, name: string, opti
|
||||
return instance;
|
||||
};
|
||||
|
||||
const getExtensionFakeForRenderer = (di: DiContainer, id: string, name: string, options: Partial<LensRendererExtension>) => {
|
||||
export const getExtensionFakeForRenderer = (di: DiContainer, id: string, name: string, options: Partial<LensRendererExtension>) => {
|
||||
const instance = new TestExtensionRenderer({
|
||||
id,
|
||||
absolutePath: "irrelevant",
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { SetRequired } from "type-fest";
|
||||
import { LensRendererExtension } from "../../../extensions/lens-renderer-extension";
|
||||
import type { ApplicationBuilder } from "./get-application-builder";
|
||||
import { getExtensionFakeFor } from "./get-extension-fake";
|
||||
|
||||
export class TestExtension extends LensRendererExtension {}
|
||||
|
||||
export type FakeExtensionData = SetRequired<Partial<LensRendererExtension>, "id" | "name">;
|
||||
|
||||
export type GetRendererExtensionFake = (fakeExtensionData: FakeExtensionData) => TestExtension;
|
||||
|
||||
export const getRendererExtensionFakeFor = (
|
||||
builder: ApplicationBuilder,
|
||||
): GetRendererExtensionFake => {
|
||||
const getExtensionFake = getExtensionFakeFor(builder);
|
||||
|
||||
return ({ id, name, ...rest }) =>
|
||||
getExtensionFake({
|
||||
id,
|
||||
name,
|
||||
rendererOptions: rest,
|
||||
}).renderer;
|
||||
};
|
||||
|
||||
@ -18,9 +18,6 @@ import extensionsStoreInjectable from "../extensions/extensions-store/extensions
|
||||
import type { ExtensionsStore } from "../extensions/extensions-store/extensions-store";
|
||||
import fileSystemProvisionerStoreInjectable from "../extensions/extension-loader/file-system-provisioner-store/file-system-provisioner-store.injectable";
|
||||
import type { FileSystemProvisionerStore } from "../extensions/extension-loader/file-system-provisioner-store/file-system-provisioner-store";
|
||||
import clusterStoreInjectable from "../common/cluster-store/cluster-store.injectable";
|
||||
import type { ClusterStore } from "../common/cluster-store/cluster-store";
|
||||
import type { Cluster } from "../common/cluster/cluster";
|
||||
import userStoreInjectable from "../common/user-store/user-store.injectable";
|
||||
import type { UserStore } from "../common/user-store";
|
||||
import getAbsolutePathInjectable from "../common/path/get-absolute-path.injectable";
|
||||
@ -41,7 +38,6 @@ import setupOnApiErrorListenersInjectable from "./api/setup-on-api-errors.inject
|
||||
import { observable, computed } from "mobx";
|
||||
import defaultShellInjectable from "./components/+preferences/default-shell.injectable";
|
||||
import appVersionInjectable from "../common/vars/app-version.injectable";
|
||||
import provideInitialValuesForSyncBoxesInjectable from "./utils/sync-box/provide-initial-values-for-sync-boxes.injectable";
|
||||
import requestAnimationFrameInjectable from "./components/animate/request-animation-frame.injectable";
|
||||
import getRandomIdInjectable from "../common/utils/get-random-id.injectable";
|
||||
import getFilePathsInjectable from "./components/+preferences/kubernetes/helm-charts/adding-of-custom-helm-repository/helm-file-input/get-file-paths.injectable";
|
||||
@ -189,12 +185,8 @@ export const getDiForUnitTesting = (opts: { doGeneralOverrides?: boolean } = {})
|
||||
|
||||
di.override(fileSystemProvisionerStoreInjectable, () => ({}) as FileSystemProvisionerStore);
|
||||
|
||||
// eslint-disable-next-line unused-imports/no-unused-vars-ts
|
||||
di.override(clusterStoreInjectable, () => ({ getById: (id): Cluster => ({}) as Cluster }) as ClusterStore);
|
||||
|
||||
di.override(setupSystemCaInjectable, () => ({ run: () => {} }));
|
||||
di.override(setupOnApiErrorListenersInjectable, () => ({ run: () => {} }));
|
||||
di.override(provideInitialValuesForSyncBoxesInjectable, () => ({ run: () => {} }));
|
||||
|
||||
di.override(defaultShellInjectable, () => "some-default-shell");
|
||||
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getGlobalOverride } from "../../common/test-utils/get-global-override";
|
||||
import subscribeStoresInjectable from "./subscribe-stores.injectable";
|
||||
|
||||
export default getGlobalOverride(
|
||||
subscribeStoresInjectable,
|
||||
() => () => () => {},
|
||||
);
|
||||
@ -4,11 +4,17 @@
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../common/k8s-api/stores-apis-can-be-created.token";
|
||||
import { getClusterIdFromHost } from "./utils";
|
||||
import hostedClusterIdInjectable from "./cluster-frame-context/hosted-cluster-id.injectable";
|
||||
|
||||
const storesAndApisCanBeCreatedInjectable = getInjectable({
|
||||
id: "create-stores-and-apis",
|
||||
instantiate: () => Boolean(getClusterIdFromHost(location.host)),
|
||||
|
||||
instantiate: (di) => {
|
||||
const hostedClusterId = di.inject(hostedClusterIdInjectable);
|
||||
|
||||
return !!hostedClusterId;
|
||||
},
|
||||
|
||||
injectionToken: storesAndApisCanBeCreatedInjectionToken,
|
||||
});
|
||||
|
||||
|
||||
@ -12,8 +12,8 @@ export const overrideChannels = (mainDi: DiContainer) => {
|
||||
const overrideMessagingFromWindowToForWindow = overrideMessagingFromWindowToMain(mainDi);
|
||||
const overrideRequestingFromWindowToMainForWindow = overrideRequestingFromWindowToMain(mainDi);
|
||||
|
||||
return (windowDi: DiContainer) => {
|
||||
overrideMessagingFromMainToWindowForWindow(windowDi);
|
||||
return (windowDi: DiContainer, windowId: string) => {
|
||||
overrideMessagingFromMainToWindowForWindow(windowDi, windowId);
|
||||
overrideMessagingFromWindowToForWindow(windowDi);
|
||||
overrideRequestingFromWindowToMainForWindow(windowDi);
|
||||
};
|
||||
|
||||
@ -3,30 +3,44 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { MessageChannelListener } from "../../common/utils/channel/message-channel-listener-injection-token";
|
||||
import type { MessageChannel } from "../../common/utils/channel/message-channel-injection-token";
|
||||
import sendToChannelInElectronBrowserWindowInjectable from "../../main/start-main-application/lens-window/application-window/send-to-channel-in-electron-browser-window.injectable";
|
||||
import type { SendToViewArgs } from "../../main/start-main-application/lens-window/application-window/lens-window-injection-token";
|
||||
import type { SendToViewArgs } from "../../main/start-main-application/lens-window/application-window/create-lens-window.injectable";
|
||||
import enlistMessageChannelListenerInjectableInRenderer from "../../renderer/utils/channel/channel-listeners/enlist-message-channel-listener.injectable";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import assert from "assert";
|
||||
import { tentativeParseJson } from "../../common/utils/tentative-parse-json";
|
||||
import { getOrInsert } from "../../common/utils";
|
||||
|
||||
type ListenerSet = Set<MessageChannelListener<any>>;
|
||||
type WindowListenerMap = Map<string, ListenerSet>;
|
||||
type ListenerFakeMap = Map<string, WindowListenerMap>;
|
||||
|
||||
export const overrideMessagingFromMainToWindow = (mainDi: DiContainer) => {
|
||||
const messageChannelListenerFakesForRenderer = new Map<
|
||||
string,
|
||||
Set<MessageChannelListener<MessageChannel<any>>>
|
||||
>();
|
||||
const messageChannelListenerFakesForRenderer: ListenerFakeMap = new Map();
|
||||
|
||||
const getWindowListeners = (channelId: string, windowId: string) => {
|
||||
const channelListeners = getOrInsert<string, WindowListenerMap>(
|
||||
messageChannelListenerFakesForRenderer,
|
||||
channelId,
|
||||
new Map(),
|
||||
);
|
||||
|
||||
return getOrInsert<string, ListenerSet>(
|
||||
channelListeners,
|
||||
windowId,
|
||||
new Set(),
|
||||
);
|
||||
};
|
||||
|
||||
mainDi.override(
|
||||
sendToChannelInElectronBrowserWindowInjectable,
|
||||
|
||||
() =>
|
||||
(
|
||||
windowId: string,
|
||||
browserWindow,
|
||||
{ channel: channelId, frameInfo, data = [] }: SendToViewArgs,
|
||||
) => {
|
||||
const listeners =
|
||||
messageChannelListenerFakesForRenderer.get(channelId) || new Set();
|
||||
const windowListeners = getWindowListeners(channelId, windowId);
|
||||
|
||||
if (frameInfo) {
|
||||
throw new Error(
|
||||
@ -40,7 +54,7 @@ export const overrideMessagingFromMainToWindow = (mainDi: DiContainer) => {
|
||||
);
|
||||
}
|
||||
|
||||
if (listeners.size === 0) {
|
||||
if (windowListeners.size === 0) {
|
||||
throw new Error(
|
||||
`Tried to send message to channel "${channelId}" but there where no listeners. Current channels with listeners: "${[
|
||||
...messageChannelListenerFakesForRenderer.keys(),
|
||||
@ -50,40 +64,26 @@ export const overrideMessagingFromMainToWindow = (mainDi: DiContainer) => {
|
||||
|
||||
const message = tentativeParseJson(data[0]);
|
||||
|
||||
listeners.forEach((listener) => listener.handler(message));
|
||||
windowListeners.forEach((listener) =>
|
||||
listener.handler(message),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
return (windowDi: DiContainer) => {
|
||||
return (windowDi: DiContainer, windowId: string) => {
|
||||
windowDi.override(
|
||||
enlistMessageChannelListenerInjectableInRenderer,
|
||||
|
||||
() => (listener) => {
|
||||
if (!messageChannelListenerFakesForRenderer.has(listener.channel.id)) {
|
||||
messageChannelListenerFakesForRenderer.set(
|
||||
listener.channel.id,
|
||||
new Set(),
|
||||
);
|
||||
}
|
||||
|
||||
const listeners = messageChannelListenerFakesForRenderer.get(
|
||||
const windowListeners = getWindowListeners(
|
||||
listener.channel.id,
|
||||
windowId,
|
||||
);
|
||||
|
||||
assert(listeners);
|
||||
|
||||
// TODO: Figure out typing
|
||||
listeners.add(
|
||||
listener as unknown as MessageChannelListener<MessageChannel<any>>,
|
||||
);
|
||||
windowListeners.add(listener);
|
||||
|
||||
return () => {
|
||||
// TODO: Figure out typing
|
||||
listeners.delete(
|
||||
listener as unknown as MessageChannelListener<
|
||||
MessageChannel<any>
|
||||
>,
|
||||
);
|
||||
windowListeners.delete(listener);
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user