diff --git a/package.json b/package.json index 8a800221d9..f159778b09 100644 --- a/package.json +++ b/package.json @@ -218,11 +218,11 @@ "@hapi/subtext": "^7.0.4", "@kubernetes/client-node": "^0.17.0", "@material-ui/styles": "^4.11.5", - "@ogre-tools/fp": "9.0.3", - "@ogre-tools/injectable": "9.0.3", - "@ogre-tools/injectable-extension-for-auto-registration": "9.0.3", - "@ogre-tools/injectable-extension-for-mobx": "9.0.3", - "@ogre-tools/injectable-react": "9.0.3", + "@ogre-tools/fp": "10.1.0", + "@ogre-tools/injectable": "10.1.0", + "@ogre-tools/injectable-extension-for-auto-registration": "10.1.0", + "@ogre-tools/injectable-extension-for-mobx": "10.1.0", + "@ogre-tools/injectable-react": "10.1.0", "@sentry/electron": "^3.0.7", "@sentry/integrations": "^6.19.3", "@side/jest-runtime": "^1.0.1", diff --git a/src/common/app-event-bus/app-event-bus.global-override-for-injectable.ts b/src/common/app-event-bus/app-event-bus.global-override-for-injectable.ts new file mode 100644 index 0000000000..2cdd21c919 --- /dev/null +++ b/src/common/app-event-bus/app-event-bus.global-override-for-injectable.ts @@ -0,0 +1,8 @@ +/** + * 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 emitEventInjectable from "./emit-event.injectable"; + +export default getGlobalOverride(emitEventInjectable, () => () => {}); diff --git a/src/common/app-event-bus/app-event-bus.injectable.ts b/src/common/app-event-bus/app-event-bus.injectable.ts index 31ed3dd3a1..d707ec9fc3 100644 --- a/src/common/app-event-bus/app-event-bus.injectable.ts +++ b/src/common/app-event-bus/app-event-bus.injectable.ts @@ -9,6 +9,7 @@ const appEventBusInjectable = getInjectable({ id: "app-event-bus", instantiate: () => appEventBus, causesSideEffects: true, + decorable: false, }); export default appEventBusInjectable; diff --git a/src/common/app-event-bus/emit-event.injectable.ts b/src/common/app-event-bus/emit-event.injectable.ts index 47bf2ca691..d5aaafe37b 100644 --- a/src/common/app-event-bus/emit-event.injectable.ts +++ b/src/common/app-event-bus/emit-event.injectable.ts @@ -8,6 +8,7 @@ import appEventBusInjectable from "./app-event-bus.injectable"; const emitEventInjectable = getInjectable({ id: "emit-event", instantiate: (di) => di.inject(appEventBusInjectable).emit, + decorable: false, }); export default emitEventInjectable; diff --git a/src/common/catalog-entities/__tests__/kubernetes-cluster.test.ts b/src/common/catalog-entities/__tests__/kubernetes-cluster.test.ts index d681713a80..b2814f9785 100644 --- a/src/common/catalog-entities/__tests__/kubernetes-cluster.test.ts +++ b/src/common/catalog-entities/__tests__/kubernetes-cluster.test.ts @@ -12,7 +12,7 @@ describe("kubernetesClusterCategory", () => { let kubernetesClusterCategory: KubernetesClusterCategory; beforeEach(() => { - const di = getDiForUnitTesting(); + const di = getDiForUnitTesting({ doGeneralOverrides: true }); kubernetesClusterCategory = di.inject(kubernetesClusterCategoryInjectable); }); diff --git a/src/common/utils/channel/channel.test.ts b/src/common/utils/channel/channel.test.ts index a3d6a805e2..c5f52c0874 100644 --- a/src/common/utils/channel/channel.test.ts +++ b/src/common/utils/channel/channel.test.ts @@ -18,6 +18,7 @@ import { requestChannelListenerInjectionToken } from "./request-channel-listener import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; import { getPromiseStatus } from "../../test-utils/get-promise-status"; +import { runInAction } from "mobx"; type TestMessageChannel = MessageChannel; type TestRequestChannel = RequestChannel; @@ -47,12 +48,16 @@ describe("channel", () => { }); builder.beforeApplicationStart((mainDi) => { - mainDi.register(testMessageChannelInjectable); + runInAction(() => { + mainDi.register(testMessageChannelInjectable); + }); }); builder.beforeWindowStart((windowDi) => { - windowDi.register(testChannelListenerInTestWindowInjectable); - windowDi.register(testMessageChannelInjectable); + runInAction(() => { + windowDi.register(testChannelListenerInTestWindowInjectable); + windowDi.register(testMessageChannelInjectable); + }); }); mainDi = builder.mainDi; @@ -126,12 +131,16 @@ describe("channel", () => { }); applicationBuilder.beforeApplicationStart((mainDi) => { - mainDi.register(testChannelListenerInMainInjectable); - mainDi.register(testMessageChannelInjectable); + runInAction(() => { + mainDi.register(testChannelListenerInMainInjectable); + mainDi.register(testMessageChannelInjectable); + }); }); applicationBuilder.beforeWindowStart((windowDi) => { - windowDi.register(testMessageChannelInjectable); + runInAction(() => { + windowDi.register(testMessageChannelInjectable); + }); }); await applicationBuilder.render(); @@ -172,12 +181,16 @@ describe("channel", () => { }); applicationBuilder.beforeApplicationStart((mainDi) => { - mainDi.register(testChannelListenerInMainInjectable); - mainDi.register(testRequestChannelInjectable); + runInAction(() => { + mainDi.register(testChannelListenerInMainInjectable); + mainDi.register(testRequestChannelInjectable); + }); }); applicationBuilder.beforeWindowStart((windowDi) => { - windowDi.register(testRequestChannelInjectable); + runInAction(() => { + windowDi.register(testRequestChannelInjectable); + }); }); await applicationBuilder.render(); diff --git a/src/common/utils/sync-box/sync-box.test.ts b/src/common/utils/sync-box/sync-box.test.ts index cfb8954802..95f139a8cd 100644 --- a/src/common/utils/sync-box/sync-box.test.ts +++ b/src/common/utils/sync-box/sync-box.test.ts @@ -18,11 +18,15 @@ describe("sync-box", () => { applicationBuilder = getApplicationBuilder(); applicationBuilder.beforeApplicationStart(mainDi => { - mainDi.register(someInjectable); + runInAction(() => { + mainDi.register(someInjectable); + }); }); applicationBuilder.beforeWindowStart((windowDi) => { - windowDi.register(someInjectable); + runInAction(() => { + windowDi.register(someInjectable); + }); }); }); diff --git a/src/common/utils/with-error-logging/with-error-logging.test.ts b/src/common/utils/with-error-logging/with-error-logging.test.ts index 05526c64c9..b14b7278e9 100644 --- a/src/common/utils/with-error-logging/with-error-logging.test.ts +++ b/src/common/utils/with-error-logging/with-error-logging.test.ts @@ -19,7 +19,7 @@ describe("with-error-logging", () => { let decorated: (a: string, b: string) => number | undefined; beforeEach(() => { - const di = getDiForUnitTesting(); + const di = getDiForUnitTesting({ doGeneralOverrides: true }); loggerStub = { error: jest.fn(), @@ -119,7 +119,7 @@ describe("with-error-logging", () => { let toBeDecorated: AsyncFnMock; beforeEach(() => { - const di = getDiForUnitTesting(); + const di = getDiForUnitTesting({ doGeneralOverrides: true }); loggerStub = { error: jest.fn(), diff --git a/src/extensions/extension-loader/extension/extension.injectable.ts b/src/extensions/extension-loader/extension/extension.injectable.ts index ba1bb6aea8..7ed23a3dfa 100644 --- a/src/extensions/extension-loader/extension/extension.injectable.ts +++ b/src/extensions/extension-loader/extension/extension.injectable.ts @@ -3,6 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import { runInAction } from "mobx"; import type { LensExtension } from "../../lens-extension"; import { extensionRegistratorInjectionToken } from "../extension-registrator-injection-token"; @@ -27,17 +28,23 @@ const extensionInjectable = getInjectable({ getInjectablesOfExtension(instance), ); - childDi.register(...injectables); + runInAction(() => { + childDi.register(...injectables); + }); }, deregister: () => { - parentDi.deregister(extensionInjectable); + runInAction(() => { + parentDi.deregister(extensionInjectable); + }); }, }; }, }); - parentDi.register(extensionInjectable); + runInAction(() => { + parentDi.register(extensionInjectable); + }); return parentDi.inject(extensionInjectable); }, diff --git a/src/features/application-update/analytics-for-installing-update.test.ts b/src/features/application-update/analytics-for-installing-update.test.ts index 7f451b0076..60523c5e49 100644 --- a/src/features/application-update/analytics-for-installing-update.test.ts +++ b/src/features/application-update/analytics-for-installing-update.test.ts @@ -19,6 +19,7 @@ import quitAndInstallUpdateInjectable from "../../main/application-update/quit-a import appVersionInjectable from "../../common/vars/app-version.injectable"; import periodicalCheckForUpdatesInjectable from "../../main/application-update/periodical-check-for-updates/periodical-check-for-updates.injectable"; import { advanceFakeTime, useFakeTime } from "../../common/test-utils/use-fake-time"; +import emitEventInjectable from "../../common/app-event-bus/emit-event.injectable"; describe("analytics for installing update", () => { let builder: ApplicationBuilder; @@ -51,6 +52,8 @@ describe("analytics for installing update", () => { mainDi.override(publishIsConfiguredInjectable, () => true); + mainDi.unoverride(emitEventInjectable); + const eventBus = mainDi.inject(appEventBusInjectable); eventBus.addListener(analyticsListenerMock); @@ -65,7 +68,6 @@ describe("analytics for installing update", () => { mainDi.permitSideEffects(periodicalCheckForUpdatesInjectable); await builder.render(); - }); it("sends event to analytics for being checked periodically", () => { diff --git a/src/features/cluster/kube-object-details/extension-api/disable-kube-object-detail-items-when-cluster-is-not-relevant.test.tsx b/src/features/cluster/kube-object-details/extension-api/disable-kube-object-detail-items-when-cluster-is-not-relevant.test.tsx index 90660f980f..5c1f27b8ca 100644 --- a/src/features/cluster/kube-object-details/extension-api/disable-kube-object-detail-items-when-cluster-is-not-relevant.test.tsx +++ b/src/features/cluster/kube-object-details/extension-api/disable-kube-object-detail-items-when-cluster-is-not-relevant.test.tsx @@ -10,7 +10,7 @@ import type { KubernetesCluster } from "../../../../common/catalog-entities"; import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder"; import { getInjectable } from "@ogre-tools/injectable"; import { frontEndRouteInjectionToken } from "../../../../common/front-end-routing/front-end-route-injection-token"; -import { computed } from "mobx"; +import { computed, runInAction } from "mobx"; import React from "react"; import { navigateToRouteInjectionToken } from "../../../../common/front-end-routing/navigate-to-route-injection-token"; import { routeSpecificComponentInjectionToken } from "../../../../renderer/routes/route-specific-component-injection-token"; @@ -45,7 +45,9 @@ describe("disable kube object detail items when cluster is not relevant", () => windowDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable); - windowDi.register(testRouteInjectable, testRouteComponentInjectable); + runInAction(() => { + windowDi.register(testRouteInjectable, testRouteComponentInjectable); + }); }); isEnabledForClusterMock = asyncFn(); diff --git a/src/features/cluster/kube-object-details/extension-api/reactively-hide-kube-object-detail-item.test.tsx b/src/features/cluster/kube-object-details/extension-api/reactively-hide-kube-object-detail-item.test.tsx index 5ca5961778..a2dbee433e 100644 --- a/src/features/cluster/kube-object-details/extension-api/reactively-hide-kube-object-detail-item.test.tsx +++ b/src/features/cluster/kube-object-details/extension-api/reactively-hide-kube-object-detail-item.test.tsx @@ -39,7 +39,9 @@ describe("reactively hide kube object detail item", () => { } as unknown as ApiManager), ); - windowDi.register(testRouteInjectable, testRouteComponentInjectable); + runInAction(() => { + windowDi.register(testRouteInjectable, testRouteComponentInjectable); + }); }); someObservable = observable.box(false); diff --git a/src/features/cluster/kube-object-menu/extension-api/disable-kube-object-menu-items-when-cluster-is-not-relevant.test.tsx b/src/features/cluster/kube-object-menu/extension-api/disable-kube-object-menu-items-when-cluster-is-not-relevant.test.tsx index 94bd91681f..75df0f9359 100644 --- a/src/features/cluster/kube-object-menu/extension-api/disable-kube-object-menu-items-when-cluster-is-not-relevant.test.tsx +++ b/src/features/cluster/kube-object-menu/extension-api/disable-kube-object-menu-items-when-cluster-is-not-relevant.test.tsx @@ -10,7 +10,7 @@ import type { KubernetesCluster } from "../../../../common/catalog-entities"; import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder"; import { getInjectable } from "@ogre-tools/injectable"; import { frontEndRouteInjectionToken } from "../../../../common/front-end-routing/front-end-route-injection-token"; -import { computed } from "mobx"; +import { computed, runInAction } from "mobx"; import React from "react"; import { navigateToRouteInjectionToken } from "../../../../common/front-end-routing/navigate-to-route-injection-token"; import { routeSpecificComponentInjectionToken } from "../../../../renderer/routes/route-specific-component-injection-token"; @@ -32,7 +32,10 @@ describe("disable kube object menu items when cluster is not relevant", () => { builder.beforeWindowStart((windowDi) => { windowDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable); - windowDi.register(testRouteInjectable, testRouteComponentInjectable); + + runInAction(() => { + windowDi.register(testRouteInjectable, testRouteComponentInjectable); + }); }); isEnabledForClusterMock = asyncFn(); diff --git a/src/features/cluster/kube-object-menu/extension-api/reactively-hide-kube-object-menu-item.test.tsx b/src/features/cluster/kube-object-menu/extension-api/reactively-hide-kube-object-menu-item.test.tsx index 61a5fe6e90..be8cc96ed9 100644 --- a/src/features/cluster/kube-object-menu/extension-api/reactively-hide-kube-object-menu-item.test.tsx +++ b/src/features/cluster/kube-object-menu/extension-api/reactively-hide-kube-object-menu-item.test.tsx @@ -26,7 +26,9 @@ describe("reactively hide kube object menu item", () => { builder.setEnvironmentToClusterFrame(); builder.beforeWindowStart((windowDi) => { - windowDi.register(testRouteInjectable, testRouteComponentInjectable); + runInAction(() => { + windowDi.register(testRouteInjectable, testRouteComponentInjectable); + }); }); someObservable = observable.box(false); diff --git a/src/features/cluster/kube-object-status-icon/extension-api/disable-kube-object-statuses-when-cluster-is-not-relevant.test.tsx b/src/features/cluster/kube-object-status-icon/extension-api/disable-kube-object-statuses-when-cluster-is-not-relevant.test.tsx index 7a459c258d..b3bc2b3716 100644 --- a/src/features/cluster/kube-object-status-icon/extension-api/disable-kube-object-statuses-when-cluster-is-not-relevant.test.tsx +++ b/src/features/cluster/kube-object-status-icon/extension-api/disable-kube-object-statuses-when-cluster-is-not-relevant.test.tsx @@ -10,7 +10,7 @@ import type { KubernetesCluster } from "../../../../common/catalog-entities"; import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder"; import { getInjectable } from "@ogre-tools/injectable"; import { frontEndRouteInjectionToken } from "../../../../common/front-end-routing/front-end-route-injection-token"; -import { computed } from "mobx"; +import { computed, runInAction } from "mobx"; import React from "react"; import { navigateToRouteInjectionToken } from "../../../../common/front-end-routing/navigate-to-route-injection-token"; import { routeSpecificComponentInjectionToken } from "../../../../renderer/routes/route-specific-component-injection-token"; @@ -33,7 +33,10 @@ describe("disable kube object statuses when cluster is not relevant", () => { builder.beforeWindowStart((windowDi) => { windowDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable); - windowDi.register(testRouteInjectable, testRouteComponentInjectable); + + runInAction(() => { + windowDi.register(testRouteInjectable, testRouteComponentInjectable); + }); }); isEnabledForClusterMock = asyncFn(); diff --git a/src/features/cluster/kube-object-status-icon/extension-api/reactively-hide-kube-object-status.test.tsx b/src/features/cluster/kube-object-status-icon/extension-api/reactively-hide-kube-object-status.test.tsx index 7dd45803a2..8e197f3f30 100644 --- a/src/features/cluster/kube-object-status-icon/extension-api/reactively-hide-kube-object-status.test.tsx +++ b/src/features/cluster/kube-object-status-icon/extension-api/reactively-hide-kube-object-status.test.tsx @@ -29,7 +29,10 @@ describe("reactively hide kube object status", () => { builder.beforeWindowStart((windowDi) => { windowDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable); - windowDi.register(testRouteInjectable, testRouteComponentInjectable); + + runInAction(() => { + windowDi.register(testRouteInjectable, testRouteComponentInjectable); + }); }); someObservable = observable.box(false); diff --git a/src/features/cluster/kube-object-status-icon/show-status-for-a-kube-object.test.tsx b/src/features/cluster/kube-object-status-icon/show-status-for-a-kube-object.test.tsx index eba681ef47..95d508351d 100644 --- a/src/features/cluster/kube-object-status-icon/show-status-for-a-kube-object.test.tsx +++ b/src/features/cluster/kube-object-status-icon/show-status-for-a-kube-object.test.tsx @@ -9,7 +9,7 @@ import { useFakeTime } from "../../../common/test-utils/use-fake-time"; import type { DiContainer } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable"; import type { IAtom } from "mobx"; -import { createAtom, computed } from "mobx"; +import { runInAction, createAtom, computed } from "mobx"; import { frontEndRouteInjectionToken } from "../../../common/front-end-routing/front-end-route-injection-token"; import { routeSpecificComponentInjectionToken } from "../../../renderer/routes/route-specific-component-injection-token"; import type { ApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; @@ -94,14 +94,17 @@ describe("show status for a kube object", () => { }); builder.beforeWindowStart((windowDi) => { - windowDi.register( - testRouteInjectable, - testRouteComponentInjectable, - infoStatusInjectable, - warningStatusInjectable, - criticalStatusInjectable, - someAtomInjectable, - ); + runInAction(() => { + windowDi.register( + testRouteInjectable, + testRouteComponentInjectable, + infoStatusInjectable, + warningStatusInjectable, + criticalStatusInjectable, + someAtomInjectable, + ); + + }); }); builder.setEnvironmentToClusterFrame(); @@ -141,7 +144,9 @@ describe("show status for a kube object", () => { describe("when status for irrelevant kube object kind emerges", () => { beforeEach(() => { - windowDi.register(statusForIrrelevantKubeObjectKindInjectable); + runInAction(() => { + windowDi.register(statusForIrrelevantKubeObjectKindInjectable); + }); rerenderParent(); }); @@ -161,7 +166,9 @@ describe("show status for a kube object", () => { describe("when status for irrelevant kube object api version emerges", () => { beforeEach(() => { - windowDi.register(statusForIrrelevantKubeObjectApiVersionInjectable); + runInAction(() => { + windowDi.register(statusForIrrelevantKubeObjectApiVersionInjectable); + }); rerenderParent(); }); diff --git a/src/features/cluster/order-of-sidebar-items.test.tsx b/src/features/cluster/order-of-sidebar-items.test.tsx index 718d267e70..449fb838c1 100644 --- a/src/features/cluster/order-of-sidebar-items.test.tsx +++ b/src/features/cluster/order-of-sidebar-items.test.tsx @@ -7,7 +7,7 @@ import type { RenderResult } from "@testing-library/react"; import { fireEvent } from "@testing-library/react"; import type { SidebarItemRegistration } from "../../renderer/components/layout/sidebar-items.injectable"; import { sidebarItemsInjectionToken } from "../../renderer/components/layout/sidebar-items.injectable"; -import { computed } from "mobx"; +import { computed, runInAction } from "mobx"; import { noop } from "lodash/fp"; import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; @@ -22,7 +22,9 @@ describe("cluster - order of sidebar items", () => { builder.setEnvironmentToClusterFrame(); builder.beforeWindowStart((windowDi) => { - windowDi.register(testSidebarItemsInjectable); + runInAction(() => { + windowDi.register(testSidebarItemsInjectable); + }); }); }); diff --git a/src/features/cluster/sidebar-and-tab-navigation-for-core.test.tsx b/src/features/cluster/sidebar-and-tab-navigation-for-core.test.tsx index caa9873208..2272fc0db6 100644 --- a/src/features/cluster/sidebar-and-tab-navigation-for-core.test.tsx +++ b/src/features/cluster/sidebar-and-tab-navigation-for-core.test.tsx @@ -11,7 +11,7 @@ import directoryForLensLocalStorageInjectable from "../../common/directory-for-l import { routeSpecificComponentInjectionToken } from "../../renderer/routes/route-specific-component-injection-token"; import type { SidebarItemRegistration } from "../../renderer/components/layout/sidebar-items.injectable"; import { sidebarItemsInjectionToken } from "../../renderer/components/layout/sidebar-items.injectable"; -import { computed } from "mobx"; +import { computed, runInAction } from "mobx"; import { noop } from "lodash/fp"; import routeIsActiveInjectable from "../../renderer/routes/route-is-active.injectable"; import { frontEndRouteInjectionToken } from "../../common/front-end-routing/front-end-route-injection-token"; @@ -51,9 +51,11 @@ describe("cluster - sidebar and tab navigation for core", () => { describe("given core registrations", () => { beforeEach(() => { builder.beforeWindowStart((windowDi) => { - windowDi.register(testRouteInjectable); - windowDi.register(testRouteComponentInjectable); - windowDi.register(testSidebarItemsInjectable); + runInAction(() => { + windowDi.register(testRouteInjectable); + windowDi.register(testRouteComponentInjectable); + windowDi.register(testSidebarItemsInjectable); + }); }); }); diff --git a/src/features/cluster/visibility-of-sidebar-items.test.tsx b/src/features/cluster/visibility-of-sidebar-items.test.tsx index 52224b7cd1..0e09f0efa8 100644 --- a/src/features/cluster/visibility-of-sidebar-items.test.tsx +++ b/src/features/cluster/visibility-of-sidebar-items.test.tsx @@ -6,7 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { RenderResult } from "@testing-library/react"; import type { SidebarItemRegistration } from "../../renderer/components/layout/sidebar-items.injectable"; import { sidebarItemsInjectionToken } from "../../renderer/components/layout/sidebar-items.injectable"; -import { computed } from "mobx"; +import { computed, runInAction } from "mobx"; import { routeSpecificComponentInjectionToken } from "../../renderer/routes/route-specific-component-injection-token"; import React from "react"; import isAllowedResourceInjectable from "../../common/utils/is-allowed-resource.injectable"; @@ -25,9 +25,11 @@ describe("cluster - visibility of sidebar items", () => { builder.setEnvironmentToClusterFrame(); builder.beforeWindowStart((windowDi) => { - windowDi.register(testRouteInjectable); - windowDi.register(testRouteComponentInjectable); - windowDi.register(testSidebarItemsInjectable); + runInAction(() => { + windowDi.register(testRouteInjectable); + windowDi.register(testRouteComponentInjectable); + windowDi.register(testSidebarItemsInjectable); + }); }); }); diff --git a/src/features/cluster/workloads/overview/extension-api/order-of-workload-overview-details.test.tsx b/src/features/cluster/workloads/overview/extension-api/order-of-workload-overview-details.test.tsx index 70d9983f2b..620b2cabb1 100644 --- a/src/features/cluster/workloads/overview/extension-api/order-of-workload-overview-details.test.tsx +++ b/src/features/cluster/workloads/overview/extension-api/order-of-workload-overview-details.test.tsx @@ -8,7 +8,7 @@ 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"; import { getInjectable } from "@ogre-tools/injectable"; -import { computed } from "mobx"; +import { computed, runInAction } from "mobx"; describe("order of workload overview details", () => { let rendered: RenderResult; @@ -20,11 +20,13 @@ describe("order of workload overview details", () => { windowDi.unoverride(getRandomIdInjectable); windowDi.permitSideEffects(getRandomIdInjectable); - windowDi.register( - someCoreItemWithLowOrderNumberInjectable, - someCoreItemWithHighOrderNumberInjectable, - someCoreItemWithDefaultOrderNumberInjectable, - ); + runInAction(() => { + windowDi.register( + someCoreItemWithLowOrderNumberInjectable, + someCoreItemWithHighOrderNumberInjectable, + someCoreItemWithDefaultOrderNumberInjectable, + ); + }); }); builder.setEnvironmentToClusterFrame(); diff --git a/src/features/navigating-between-routes.test.tsx b/src/features/navigating-between-routes.test.tsx index bcff0e2a11..cf2dda5cc1 100644 --- a/src/features/navigating-between-routes.test.tsx +++ b/src/features/navigating-between-routes.test.tsx @@ -5,7 +5,7 @@ import type { DiContainer } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable"; import React from "react"; -import { computed } from "mobx"; +import { computed, runInAction } from "mobx"; import type { RenderResult } from "@testing-library/react"; import { routeSpecificComponentInjectionToken } from "../renderer/routes/route-specific-component-injection-token"; import { observer } from "mobx-react"; @@ -32,8 +32,10 @@ describe("navigating between routes", () => { beforeEach(async () => { builder.beforeWindowStart((windowDi) => { - windowDi.register(testRouteWithoutPathParametersInjectable); - windowDi.register(testRouteWithoutPathParametersComponentInjectable); + runInAction(() => { + windowDi.register(testRouteWithoutPathParametersInjectable); + windowDi.register(testRouteWithoutPathParametersComponentInjectable); + }); }); rendered = await builder.render(); @@ -106,8 +108,10 @@ describe("navigating between routes", () => { beforeEach(async () => { builder.beforeWindowStart((windowDi) => { - windowDi.register(routeWithOptionalPathParametersInjectable); - windowDi.register(routeWithOptionalPathParametersComponentInjectable); + runInAction(() => { + windowDi.register(routeWithOptionalPathParametersInjectable); + windowDi.register(routeWithOptionalPathParametersComponentInjectable); + }); }); rendered = await builder.render(); diff --git a/src/features/preferences/closing-preferences.test.tsx b/src/features/preferences/closing-preferences.test.tsx index f93eaf70ce..5363e6e76f 100644 --- a/src/features/preferences/closing-preferences.test.tsx +++ b/src/features/preferences/closing-preferences.test.tsx @@ -9,7 +9,7 @@ import type { ApplicationBuilder } from "../../renderer/components/test-utils/ge import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import currentPathInjectable from "../../renderer/routes/current-path.injectable"; import { frontEndRouteInjectionToken } from "../../common/front-end-routing/front-end-route-injection-token"; -import { computed } from "mobx"; +import { computed, runInAction } from "mobx"; import { preferenceNavigationItemInjectionToken } from "../../renderer/components/+preferences/preferences-navigation/preference-navigation-items.injectable"; import routeIsActiveInjectable from "../../renderer/routes/route-is-active.injectable"; import { Preferences } from "../../renderer/components/+preferences"; @@ -30,11 +30,13 @@ describe("preferences - closing-preferences", () => { builder = getApplicationBuilder(); builder.beforeWindowStart((windowDi) => { - windowDi.register(testPreferencesRouteInjectable); - windowDi.register(testPreferencesRouteComponentInjectable); - windowDi.register(testFrontPageRouteInjectable); - windowDi.register(testFrontPageRouteComponentInjectable); - windowDi.register(testNavigationItemInjectable); + runInAction(() => { + windowDi.register(testPreferencesRouteInjectable); + windowDi.register(testPreferencesRouteComponentInjectable); + windowDi.register(testFrontPageRouteInjectable); + windowDi.register(testFrontPageRouteComponentInjectable); + windowDi.register(testNavigationItemInjectable); + }); windowDi.override(navigateToFrontPageInjectable, (di) => { const navigateToRoute = di.inject(navigateToRouteInjectionToken); diff --git a/src/features/quitting-and-restarting-the-app/opening-application-window-using-tray.test.ts b/src/features/quitting-and-restarting-the-app/opening-application-window-using-tray.test.ts index f9ced472dd..86f0a6b83a 100644 --- a/src/features/quitting-and-restarting-the-app/opening-application-window-using-tray.test.ts +++ b/src/features/quitting-and-restarting-the-app/opening-application-window-using-tray.test.ts @@ -13,6 +13,7 @@ import focusApplicationInjectable from "../../main/electron-app/features/focus-a 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"; +import { runInAction } from "mobx"; describe("opening application window using tray", () => { describe("given application has started", () => { @@ -61,10 +62,12 @@ describe("opening application window using tray", () => { return browserWindow; }); - (mainDi as any).decorateFunction( - createElectronWindowInjectable, - createElectronWindowMock, - ); + runInAction(() => { + (mainDi as any).decorateFunction( + createElectronWindowInjectable, + createElectronWindowMock, + ); + }); expectWindowsToBeOpen = expectWindowsToBeOpenFor(builder); }); diff --git a/src/features/telemetry/emit-telemetry-from-specific-function-calls.test.ts b/src/features/telemetry/emit-telemetry-from-specific-function-calls.test.ts new file mode 100644 index 0000000000..961647fa29 --- /dev/null +++ b/src/features/telemetry/emit-telemetry-from-specific-function-calls.test.ts @@ -0,0 +1,146 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { computed, runInAction } from "mobx"; +import type { DiContainer } from "@ogre-tools/injectable"; +import { getInjectable } from "@ogre-tools/injectable"; +import { getDiForUnitTesting } from "../../renderer/getDiForUnitTesting"; +import telemetryWhiteListForFunctionsInjectable from "./renderer/telemetry-white-list-for-functions.injectable"; +import emitEventInjectable from "../../common/app-event-bus/emit-event.injectable"; + +describe("emit-telemetry-from-specific-function-calls", () => { + let di: DiContainer; + + beforeEach(() => { + di = getDiForUnitTesting({ doGeneralOverrides: true }); + }); + + describe("given a telemetry white-list for injectables which instantiate a function", () => { + let emitEventMock: jest.Mock; + + beforeEach(() => { + di.override(telemetryWhiteListForFunctionsInjectable, () => [ + "some-white-listed-function", + ]); + + emitEventMock = jest.fn(); + di.override(emitEventInjectable, () => emitEventMock); + }); + + describe("given instances of white-listed, non-white-listed and tagged functions", () => { + let whiteListedFunctionMock: jest.Mock; + let nonWhiteListedFunctionMock: jest.Mock; + let taggedFunctionMock: jest.Mock; + let injectedWhiteListedFunction: jest.Mock; + let injectedNonWhiteListedFunction: jest.Mock; + let injectedTaggedFunction: jest.Mock; + + beforeEach(() => { + whiteListedFunctionMock = jest.fn(); + nonWhiteListedFunctionMock = jest.fn(); + taggedFunctionMock = jest.fn(); + + const whiteListedInjectable = getInjectable({ + id: "some-white-listed-function", + instantiate: () => whiteListedFunctionMock, + }); + + const nonWhiteListedInjectable = getInjectable({ + id: "some-non-white-listed-function", + instantiate: () => nonWhiteListedFunctionMock, + }); + + const taggedInjectable = getInjectable({ + id: "some-tagged-function", + instantiate: () => taggedFunctionMock, + tags: ["emit-telemetry"], + }); + + runInAction(() => { + di.register(whiteListedInjectable); + di.register(nonWhiteListedInjectable); + di.register(taggedInjectable); + }); + + injectedWhiteListedFunction = di.inject(whiteListedInjectable); + injectedNonWhiteListedFunction = di.inject(nonWhiteListedInjectable); + injectedTaggedFunction = di.inject(taggedInjectable); + }); + + it("telemetry is not emitted yet", () => { + expect(emitEventMock).not.toHaveBeenCalled(); + }); + + describe("when the white-listed function is called", () => { + beforeEach(() => { + injectedWhiteListedFunction("some-arg", "some-other-arg"); + }); + + it("telemetry is emitted in event bus", () => { + expect(emitEventMock).toHaveBeenCalledWith({ + destination: "auto-capture", + action: "telemetry-from-business-action", + name: "some-white-listed-function", + params: { args: ["some-arg", "some-other-arg"] }, + }); + }); + }); + + describe("when the white-listed function is called with MobX reactive content", () => { + beforeEach(() => { + const someComputedProperty = computed(() => "some-computed-value"); + + const someObservable = { + someStaticProperty: "some-static-value", + someComputedProperty, + }; + + injectedWhiteListedFunction(someObservable); + }); + + it("telemetry is emitted in event bus without MobX internals or computeds", () => { + expect(emitEventMock).toHaveBeenCalledWith({ + destination: "auto-capture", + action: "telemetry-from-business-action", + name: "some-white-listed-function", + + params: { + args: [ + { + someStaticProperty: "some-static-value", + someComputedProperty: "some-computed-value", + }, + ], + }, + }); + }); + }); + + describe("when the non-white-listed function is called", () => { + beforeEach(() => { + injectedNonWhiteListedFunction(); + }); + + it("telemetry is not emitted", () => { + expect(emitEventMock).not.toHaveBeenCalled(); + }); + }); + + describe("when the tagged, but not white-listed function is called", () => { + beforeEach(() => { + injectedTaggedFunction("some-arg", "some-other-arg"); + }); + + it("telemetry is emitted in event bus", () => { + expect(emitEventMock).toHaveBeenCalledWith({ + destination: "auto-capture", + action: "telemetry-from-business-action", + name: "some-tagged-function", + params: { args: ["some-arg", "some-other-arg"] }, + }); + }); + }); + }); + }); +}); diff --git a/src/features/telemetry/renderer/emit-telemetry.injectable.ts b/src/features/telemetry/renderer/emit-telemetry.injectable.ts new file mode 100644 index 0000000000..f543daf843 --- /dev/null +++ b/src/features/telemetry/renderer/emit-telemetry.injectable.ts @@ -0,0 +1,28 @@ +/** + * 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 emitEventInjectable from "../../../common/app-event-bus/emit-event.injectable"; +import { toJS, observable } from "mobx"; + +const emitTelemetryInjectable = getInjectable({ + id: "emit-telemetry", + + instantiate: (di) => { + const emitEvent = di.inject(emitEventInjectable); + + return ({ action, args }: { action: string; args: any[] }) => { + emitEvent({ + destination: "auto-capture", + action: "telemetry-from-business-action", + name: action, + params: { args: toJS(observable(args)) }, + }); + }; + }, + + decorable: false, +}); + +export default emitTelemetryInjectable; diff --git a/src/features/telemetry/renderer/telemetry-decorator.injectable.ts b/src/features/telemetry/renderer/telemetry-decorator.injectable.ts new file mode 100644 index 0000000000..e1a614660c --- /dev/null +++ b/src/features/telemetry/renderer/telemetry-decorator.injectable.ts @@ -0,0 +1,69 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { + DiContainerForInjection, + Injectable, +} from "@ogre-tools/injectable"; + +import { + lifecycleEnum, + getInjectable, + instantiationDecoratorToken, +} from "@ogre-tools/injectable"; +import assert from "assert"; + +import { isFunction } from "lodash/fp"; +import emitTelemetryInjectable from "./emit-telemetry.injectable"; +import telemetryWhiteListForFunctionsInjectable from "./telemetry-white-list-for-functions.injectable"; + +const telemetryDecoratorInjectable = getInjectable({ + id: "telemetry-decorator", + + instantiate: (diForDecorator) => { + const emitTelemetry = diForDecorator.inject(emitTelemetryInjectable); + + const whiteList = diForDecorator.inject( + telemetryWhiteListForFunctionsInjectable, + ); + + const shouldEmitTelemetry = shouldEmitTelemetryFor(whiteList); + + return { + decorate: + (instantiateToBeDecorated: any) => + (di: DiContainerForInjection, instantiationParameter: any) => { + const instance = instantiateToBeDecorated(di, instantiationParameter); + + if (isFunction(instance)) { + return (...args: any[]) => { + const currentContext = di.context.at(-1); + + assert(currentContext); + + if (shouldEmitTelemetry(currentContext.injectable)) { + emitTelemetry({ action: currentContext.injectable.id, args }); + } + + return instance(...args); + }; + } + + return instance; + }, + }; + }, + + decorable: false, + // Todo: this is required because of imperfect typing in injectable. + lifecycle: lifecycleEnum.singleton, + injectionToken: instantiationDecoratorToken, +}); + +const shouldEmitTelemetryFor = + (whiteList: string[]) => (injectable: Injectable) => + injectable.tags?.includes("emit-telemetry") || + whiteList.includes(injectable.id); + +export default telemetryDecoratorInjectable; diff --git a/src/features/telemetry/renderer/telemetry-white-list-for-functions.injectable.ts b/src/features/telemetry/renderer/telemetry-white-list-for-functions.injectable.ts new file mode 100644 index 0000000000..3c7ac58336 --- /dev/null +++ b/src/features/telemetry/renderer/telemetry-white-list-for-functions.injectable.ts @@ -0,0 +1,13 @@ +/** + * 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"; + +const telemetryWhiteListForFunctionsInjectable = getInjectable({ + id: "telemetry-white-list-for-functions", + instantiate: () => ["some-placeholder-injectable-id"], + decorable: false, +}); + +export default telemetryWhiteListForFunctionsInjectable; diff --git a/src/main/getDi.ts b/src/main/getDi.ts index ded33e9e0f..17d9cc36b7 100644 --- a/src/main/getDi.ts +++ b/src/main/getDi.ts @@ -5,24 +5,27 @@ import { createContainer } from "@ogre-tools/injectable"; import { autoRegister } from "@ogre-tools/injectable-extension-for-auto-registration"; import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx"; +import { runInAction } from "mobx"; import { Environments, setLegacyGlobalDiForExtensionApi } from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; export const getDi = () => { const di = createContainer("main"); - registerMobX(di); - - autoRegister({ - di, - requireContexts: [ - require.context("./", true, /\.injectable\.(ts|tsx)$/), - require.context("../extensions", true, /\.injectable\.(ts|tsx)$/), - require.context("../common", true, /\.injectable\.(ts|tsx)$/), - require.context("../features", true, /.*\/(main|common)\/.*\.injectable\.(ts|tsx)$/), - ], - }); - setLegacyGlobalDiForExtensionApi(di, Environments.main); + runInAction(() => { + registerMobX(di); + + autoRegister({ + di, + requireContexts: [ + require.context("./", true, /\.injectable\.(ts|tsx)$/), + require.context("../extensions", true, /\.injectable\.(ts|tsx)$/), + require.context("../common", true, /\.injectable\.(ts|tsx)$/), + require.context("../features", true, /.*\/(main|common)\/.*\.injectable\.(ts|tsx)$/), + ], + }); + }); + return di; }; diff --git a/src/main/getDiForUnitTesting.ts b/src/main/getDiForUnitTesting.ts index af891b1412..b7a5bf2431 100644 --- a/src/main/getDiForUnitTesting.ts +++ b/src/main/getDiForUnitTesting.ts @@ -55,7 +55,7 @@ import setupRunnablesBeforeClosingOfApplicationInjectable from "./electron-app/r import showMessagePopupInjectable from "./electron-app/features/show-message-popup.injectable"; import clusterFramesInjectable from "../common/cluster-frames.injectable"; import type { ClusterFrameInfo } from "../common/cluster-frames"; -import { observable } from "mobx"; +import { observable, runInAction } 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 setupRunnablesAfterWindowIsOpenedInjectable from "./electron-app/runnables/setup-runnables-after-window-is-opened.injectable"; @@ -103,19 +103,21 @@ export function getDiForUnitTesting(opts: { doGeneralOverrides?: boolean } = {}) const di = createContainer("main"); - registerMobX(di); - setLegacyGlobalDiForExtensionApi(di, Environments.main); + di.preventSideEffects(); + const injectables: Injectable[] = (global as any).mainInjectablePaths.map( (filePath: string) => require(filePath).default, ); - chunk(100)(injectables).forEach(chunkInjectables => { - di.register(...chunkInjectables); - }); + runInAction(() => { + registerMobX(di); - di.preventSideEffects(); + chunk(100)(injectables).forEach(chunkInjectables => { + di.register(...chunkInjectables); + }); + }); if (doGeneralOverrides) { const globalOverrides: GlobalOverride[] = (global as any).mainGlobalOverridePaths.map( diff --git a/src/main/router/router.test.ts b/src/main/router/router.test.ts index a8467df3f2..a487104c72 100644 --- a/src/main/router/router.test.ts +++ b/src/main/router/router.test.ts @@ -20,6 +20,7 @@ import type { SetRequired } from "type-fest"; import normalizedPlatformInjectable from "../../common/vars/normalized-platform.injectable"; import kubectlBinaryNameInjectable from "../kubectl/binary-name.injectable"; import kubectlDownloadingNormalizedArchInjectable from "../kubectl/normalized-arch.injectable"; +import { runInAction } from "mobx"; describe("router", () => { let router: Router; @@ -53,7 +54,9 @@ describe("router", () => { injectionToken: routeInjectionToken, }); - di.register(injectable); + runInAction(() => { + di.register(injectable); + }); router = di.inject(routerInjectable); }); diff --git a/src/main/start-main-application/lens-window/application-window/create-application-window.injectable.ts b/src/main/start-main-application/lens-window/application-window/create-application-window.injectable.ts index 91975c314d..1652b67f9b 100644 --- a/src/main/start-main-application/lens-window/application-window/create-application-window.injectable.ts +++ b/src/main/start-main-application/lens-window/application-window/create-application-window.injectable.ts @@ -10,6 +10,7 @@ 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"; +import { runInAction } from "mobx"; const createApplicationWindowInjectable = getInjectable({ id: "create-application-window", @@ -49,7 +50,9 @@ const createApplicationWindowInjectable = getInjectable({ }, onClose: () => { - parentDi.deregister(windowInjectable); + runInAction(() => { + parentDi.deregister(windowInjectable); + }); }, beforeOpen: waitUntilBundledExtensionsAreLoaded, @@ -59,7 +62,9 @@ const createApplicationWindowInjectable = getInjectable({ injectionToken: applicationWindowInjectionToken, }); - parentDi.register(windowInjectable); + runInAction(() => { + parentDi.register(windowInjectable); + }); return parentDi.inject(windowInjectable); }, diff --git a/src/main/utils/resolve-system-proxy/resolve-system-proxy-from-electron.test.ts b/src/main/utils/resolve-system-proxy/resolve-system-proxy-from-electron.test.ts index 9c395dca5b..a80a05a7cf 100644 --- a/src/main/utils/resolve-system-proxy/resolve-system-proxy-from-electron.test.ts +++ b/src/main/utils/resolve-system-proxy/resolve-system-proxy-from-electron.test.ts @@ -20,7 +20,7 @@ describe("technical: resolve-system-proxy-from-electron", () => { let actualPromise: Promise; beforeEach(() => { - di = getDiForUnitTesting(); + di = getDiForUnitTesting({ doGeneralOverrides: true }); logErrorMock = jest.fn(); di.override(logErrorInjectable, () => logErrorMock); diff --git a/src/renderer/api/__tests__/catalog-entity-registry.test.ts b/src/renderer/api/__tests__/catalog-entity-registry.test.ts index 08dacb8f5a..7092650e5a 100644 --- a/src/renderer/api/__tests__/catalog-entity-registry.test.ts +++ b/src/renderer/api/__tests__/catalog-entity-registry.test.ts @@ -80,7 +80,7 @@ describe("CatalogEntityRegistry", () => { let catalogCategoryRegistry: CatalogCategoryRegistry; beforeEach(() => { - const di = getDiForUnitTesting(); + const di = getDiForUnitTesting({ doGeneralOverrides: true }); entityRegistry = di.inject(catalogEntityRegistryInjectable); catalogCategoryRegistry = di.inject(catalogCategoryRegistryInjectable); diff --git a/src/renderer/components/+catalog/__tests__/custom-columns.test.ts b/src/renderer/components/+catalog/__tests__/custom-columns.test.ts index 83b564566b..d689e8f812 100644 --- a/src/renderer/components/+catalog/__tests__/custom-columns.test.ts +++ b/src/renderer/components/+catalog/__tests__/custom-columns.test.ts @@ -43,7 +43,7 @@ describe("Custom Category Columns", () => { let di: DiContainer; beforeEach(() => { - di = getDiForUnitTesting(); + di = getDiForUnitTesting({ doGeneralOverrides: true }); di.override(hotbarStoreInjectable, () => ({})); }); diff --git a/src/renderer/components/+catalog/__tests__/custom-views.test.ts b/src/renderer/components/+catalog/__tests__/custom-views.test.ts index 8bd996505e..8a8f7fa39d 100644 --- a/src/renderer/components/+catalog/__tests__/custom-views.test.ts +++ b/src/renderer/components/+catalog/__tests__/custom-views.test.ts @@ -16,7 +16,7 @@ describe("Custom Category Views", () => { let di: DiContainer; beforeEach(() => { - di = getDiForUnitTesting(); + di = getDiForUnitTesting({ doGeneralOverrides: true }); }); it("should order items correctly over all extensions", () => { diff --git a/src/renderer/components/kube-object-menu/kube-object-menu.test.tsx b/src/renderer/components/kube-object-menu/kube-object-menu.test.tsx index 80a783c19a..b435d2b6b6 100644 --- a/src/renderer/components/kube-object-menu/kube-object-menu.test.tsx +++ b/src/renderer/components/kube-object-menu/kube-object-menu.test.tsx @@ -14,7 +14,7 @@ import { ConfirmDialog } from "../confirm-dialog"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; import { getDiForUnitTesting } from "../../getDiForUnitTesting"; -import { computed } from "mobx"; +import { computed, runInAction } from "mobx"; import clusterInjectable from "./dependencies/cluster.injectable"; import type { DiRender } from "../test-utils/renderFor"; import { renderFor } from "../test-utils/renderFor"; @@ -34,11 +34,13 @@ describe("kube-object-menu", () => { beforeEach(() => { di = getDiForUnitTesting({ doGeneralOverrides: true }); - di.register( - someMenuItemInjectable, - someOtherMenuItemInjectable, - someAnotherMenuItemInjectable, - ); + runInAction(() => { + di.register( + someMenuItemInjectable, + someOtherMenuItemInjectable, + someAnotherMenuItemInjectable, + ); + }); render = renderFor(di); diff --git a/src/renderer/components/test-utils/get-application-builder.tsx b/src/renderer/components/test-utils/get-application-builder.tsx index 5ca3c5975f..9f9ab7d903 100644 --- a/src/renderer/components/test-utils/get-application-builder.tsx +++ b/src/renderer/components/test-utils/get-application-builder.tsx @@ -143,7 +143,9 @@ export const getApplicationBuilder = () => { doGeneralOverrides: true, }); - mainDi.register(mainExtensionsStateInjectable); + runInAction(() => { + mainDi.register(mainExtensionsStateInjectable); + }); const overrideChannelsForWindow = overrideChannels(mainDi); @@ -184,7 +186,9 @@ export const getApplicationBuilder = () => { overrideChannelsForWindow(windowDi, windowId); - windowDi.register(rendererExtensionsStateInjectable); + runInAction(() => { + windowDi.register(rendererExtensionsStateInjectable); + }); windowDi.override( currentlyInClusterFrameInjectable, @@ -552,9 +556,11 @@ export const getApplicationBuilder = () => { getExtensionFakeForMain(mainDi, extension.id, extension.name, extension.mainOptions || {}), ); - mainExtensionInstances.forEach( - enableExtensionFor(mainDi, mainExtensionsStateInjectable), - ); + runInAction(() => { + mainExtensionInstances.forEach( + enableExtensionFor(mainDi, mainExtensionsStateInjectable), + ); + }); }); }, diff --git a/src/renderer/getDi.tsx b/src/renderer/getDi.tsx index 632b651547..348c5e369b 100644 --- a/src/renderer/getDi.tsx +++ b/src/renderer/getDi.tsx @@ -6,24 +6,27 @@ import { createContainer } from "@ogre-tools/injectable"; import { autoRegister } from "@ogre-tools/injectable-extension-for-auto-registration"; import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx"; +import { runInAction } from "mobx"; import { Environments, setLegacyGlobalDiForExtensionApi } from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; export const getDi = () => { const di = createContainer("renderer"); - registerMobX(di); - - autoRegister({ - di, - requireContexts: [ - require.context("./", true, /\.injectable\.(ts|tsx)$/), - require.context("../common", true, /\.injectable\.(ts|tsx)$/), - require.context("../extensions", true, /\.injectable\.(ts|tsx)$/), - require.context("../features", true, /.*\/(renderer|common)\/.*\.injectable\.(ts|tsx)$/), - ], - }); - setLegacyGlobalDiForExtensionApi(di, Environments.renderer); + runInAction(() => { + registerMobX(di); + + autoRegister({ + di, + requireContexts: [ + require.context("./", true, /\.injectable\.(ts|tsx)$/), + require.context("../common", true, /\.injectable\.(ts|tsx)$/), + require.context("../extensions", true, /\.injectable\.(ts|tsx)$/), + require.context("../features", true, /.*\/(renderer|common)\/.*\.injectable\.(ts|tsx)$/), + ], + }); + }); + return di; }; diff --git a/src/renderer/getDiForUnitTesting.tsx b/src/renderer/getDiForUnitTesting.tsx index ddd560674f..469de713b0 100644 --- a/src/renderer/getDiForUnitTesting.tsx +++ b/src/renderer/getDiForUnitTesting.tsx @@ -33,7 +33,7 @@ import lensResourcesDirInjectable from "../common/vars/lens-resources-dir.inject import broadcastMessageInjectable from "../common/ipc/broadcast-message.injectable"; import apiManagerInjectable from "../common/k8s-api/api-manager/manager.injectable"; import setupOnApiErrorListenersInjectable from "./api/setup-on-api-errors.injectable"; -import { observable, computed } from "mobx"; +import { observable, computed, runInAction } from "mobx"; import defaultShellInjectable from "./components/+preferences/default-shell.injectable"; import appVersionInjectable from "../common/vars/app-version.injectable"; import requestAnimationFrameInjectable from "./components/animate/request-animation-frame.injectable"; @@ -68,26 +68,30 @@ import getEntitySettingCommandsInjectable from "./components/command-palette/reg import storageSaveDelayInjectable from "./utils/create-storage/storage-save-delay.injectable"; import type { GlobalOverride } from "../common/test-utils/get-global-override"; -export const getDiForUnitTesting = (opts: { doGeneralOverrides?: boolean } = {}) => { - const { - doGeneralOverrides = false, - } = opts; +export const getDiForUnitTesting = ( + opts: { doGeneralOverrides?: boolean } = {}, +) => { + const { doGeneralOverrides = false } = opts; const di = createContainer("renderer"); - registerMobX(di); + di.preventSideEffects(); setLegacyGlobalDiForExtensionApi(di, Environments.renderer); - const injectables: Injectable[] = (global as any).rendererInjectablePaths.map( + const injectables: Injectable[] = ( + global as any + ).rendererInjectablePaths.map( (filePath: string) => require(filePath).default, ); - chunk(100)(injectables).forEach(chunkInjectables => { - di.register(...chunkInjectables); - }); + runInAction(() => { + registerMobX(di); - di.preventSideEffects(); + chunk(100)(injectables).forEach((chunkInjectables) => { + di.register(...chunkInjectables); + }); + }); if (doGeneralOverrides) { const globalOverrides: GlobalOverride[] = (global as any).rendererGlobalOverridePaths.map( diff --git a/src/renderer/routes/navigate-to-route.injectable.ts b/src/renderer/routes/navigate-to-route.injectable.ts index 8b57a02613..1207841c7a 100644 --- a/src/renderer/routes/navigate-to-route.injectable.ts +++ b/src/renderer/routes/navigate-to-route.injectable.ts @@ -33,6 +33,8 @@ const navigateToRouteInjectable = getInjectable({ }; }, + tags: ["emit-telemetry"], + injectionToken: navigateToRouteInjectionToken, }); diff --git a/src/renderer/utils/create-storage/storages-are-ready.ts b/src/renderer/utils/create-storage/storages-are-ready.ts index 04f2595472..8489138d1d 100644 --- a/src/renderer/utils/create-storage/storages-are-ready.ts +++ b/src/renderer/utils/create-storage/storages-are-ready.ts @@ -3,6 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import type { DiContainer } from "@ogre-tools/injectable"; +import { runInAction } from "mobx"; import type { CreateStorage } from "./create-storage"; import createStorageInjectable from "./create-storage.injectable"; @@ -19,8 +20,10 @@ export const controlWhenStoragesAreReady = (di: DiContainer) => { return storage; }; - // TODO: Remove when typing is added to the library - (di as any).decorateFunction(createStorageInjectable, decorated); + runInAction(() => { + // TODO: Remove when typing is added to the library + (di as any).decorateFunction(createStorageInjectable, decorated); + }); return async () => { await Promise.all(storagesAreReady); diff --git a/yarn.lock b/yarn.lock index e119733ecf..3b4a659484 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1240,46 +1240,46 @@ mkdirp "^1.0.4" rimraf "^3.0.2" -"@ogre-tools/fp@9.0.3", "@ogre-tools/fp@^9.0.3": - version "9.0.3" - resolved "https://registry.yarnpkg.com/@ogre-tools/fp/-/fp-9.0.3.tgz#f8c9a3316b688c4782309e050c86aa04bebfc293" - integrity sha512-j5TQAxiz6ncEfYFBcqnWXeLZY89Qd+dZ9UlfonBdw/C9okxjNeFL+2bmt+b/Vxscz1cOLGZ1F6nmlhQdTtHzPw== +"@ogre-tools/fp@10.1.0", "@ogre-tools/fp@^10.1.0": + version "10.1.0" + resolved "https://registry.yarnpkg.com/@ogre-tools/fp/-/fp-10.1.0.tgz#e83c4dad97416c62d89913c0c0a34e734ae06b8b" + integrity sha512-ZqGQXytucSWbSoNjrdyHAiIWO0LotxBU+aI5hCcqedWg9TzNzf78YKD6ngHXxVEwT/JYsslxXMxzE4LNdo8Cbg== dependencies: lodash "^4.17.21" -"@ogre-tools/injectable-extension-for-auto-registration@9.0.3": - version "9.0.3" - resolved "https://registry.yarnpkg.com/@ogre-tools/injectable-extension-for-auto-registration/-/injectable-extension-for-auto-registration-9.0.3.tgz#a26d2a39e24ec3a0800fe21141c0f4f0e7d5504d" - integrity sha512-0zjt4w1ACBX9a3FyhTD+/AAqk/xov2bw+Cnbte7NMOVWAbHDfQpmbdiKJlMnFcMUd8vdwOEMm1Z4ogT1VkUeqg== +"@ogre-tools/injectable-extension-for-auto-registration@10.1.0": + version "10.1.0" + resolved "https://registry.yarnpkg.com/@ogre-tools/injectable-extension-for-auto-registration/-/injectable-extension-for-auto-registration-10.1.0.tgz#a46d23cf5cf880e416a46238ecb54e7f933f9d89" + integrity sha512-G9UKcaYr4DHViXHIKigzy6jI2ZhQC+K6idc1M4W/l4IazaV26Gwj1MSI5nrJ6Z4aRAzILFKM4dzkvZNFjkyGrw== dependencies: - "@ogre-tools/fp" "^9.0.3" - "@ogre-tools/injectable" "^9.0.3" + "@ogre-tools/fp" "^10.1.0" + "@ogre-tools/injectable" "^10.1.0" lodash "^4.17.21" -"@ogre-tools/injectable-extension-for-mobx@9.0.3": - version "9.0.3" - resolved "https://registry.yarnpkg.com/@ogre-tools/injectable-extension-for-mobx/-/injectable-extension-for-mobx-9.0.3.tgz#24a14b940f51cae8b07645a2376d804b826c659e" - integrity sha512-DgCbAIqMPKgeNETY/8nxz6llAk8fAihGcbs/fkKINe4N9zFgOBKsuk/w67Sx0rTE7l35L6HQenbo7nJhIqbCWA== +"@ogre-tools/injectable-extension-for-mobx@10.1.0": + version "10.1.0" + resolved "https://registry.yarnpkg.com/@ogre-tools/injectable-extension-for-mobx/-/injectable-extension-for-mobx-10.1.0.tgz#b1efaafb048f2ceb5588daad708dbeffbd2ec7d1" + integrity sha512-G5A6FSgBMTlD6Qdd6xzeuVzcyHGS+tTUW7DCBbYLJqZ3Y8/PprSomhunrNrrcuZdM0K16BpQT8o6OHw4Z/Kqiw== dependencies: - "@ogre-tools/fp" "^9.0.3" - "@ogre-tools/injectable" "^9.0.3" + "@ogre-tools/fp" "^10.1.0" + "@ogre-tools/injectable" "^10.1.0" lodash "^4.17.21" -"@ogre-tools/injectable-react@9.0.3": - version "9.0.3" - resolved "https://registry.yarnpkg.com/@ogre-tools/injectable-react/-/injectable-react-9.0.3.tgz#bc125ef906b171c8894f711f8b61f38d49e81dd0" - integrity sha512-6O9vr19Mcy0uUekZhRyjsM5nw8pgFXhbNvZ8JOnBQg6Lp1CqdasIFhJ0Hdxb8w8P9Zs+pd8pfevRVotq0ouV2Q== +"@ogre-tools/injectable-react@10.1.0": + version "10.1.0" + resolved "https://registry.yarnpkg.com/@ogre-tools/injectable-react/-/injectable-react-10.1.0.tgz#5c9b4b5eb9e5843cc966629131104055180ba18c" + integrity sha512-4ReLJm8QcruCEm4KFhbsXLki3YiKRwlg3Mg7C2d8KyUfg+MUA5VdvgQSn3HthnyejiXlYCinqJLw83IryX/GNA== dependencies: - "@ogre-tools/fp" "^9.0.3" - "@ogre-tools/injectable" "^9.0.3" + "@ogre-tools/fp" "^10.1.0" + "@ogre-tools/injectable" "^10.1.0" lodash "^4.17.21" -"@ogre-tools/injectable@9.0.3", "@ogre-tools/injectable@^9.0.3": - version "9.0.3" - resolved "https://registry.yarnpkg.com/@ogre-tools/injectable/-/injectable-9.0.3.tgz#6d9e01a5be7e7c96e7bcbc727f928faad5e11884" - integrity sha512-KCmqcMEl/1Jjwg6XzNve+JVaW/OtiJUOKBucTJx2ZKBlAQaKz1/VUP7IB4UoQ4RWVa0+mUKLTxBTQFBQfp05RA== +"@ogre-tools/injectable@10.1.0", "@ogre-tools/injectable@^10.1.0": + version "10.1.0" + resolved "https://registry.yarnpkg.com/@ogre-tools/injectable/-/injectable-10.1.0.tgz#5051cc6a673576028e00439fc3e3f053ecdda030" + integrity sha512-7h7P5nfAFqnSny341FFT6cbJCmXVlGqA4zwTOpwKsGyC1h90NWtQZ+PUxY5MKl7rFWW/wpXgAKQqtf27Vy41Qw== dependencies: - "@ogre-tools/fp" "^9.0.3" + "@ogre-tools/fp" "^10.1.0" lodash "^4.17.21" "@pmmmwh/react-refresh-webpack-plugin@^0.5.7":