diff --git a/src/common/protocol-handler/router.ts b/src/common/protocol-handler/router.ts index 476c992582..804f70c80b 100644 --- a/src/common/protocol-handler/router.ts +++ b/src/common/protocol-handler/router.ts @@ -63,9 +63,9 @@ export function foldAttemptResults(mainAttempt: RouteAttempt, rendererAttempt: R } } -interface Dependencies { - extensionLoader: ExtensionLoader; - extensionsStore: ExtensionsStore; +export interface LensProtocolRouterDependencies { + readonly extensionLoader: ExtensionLoader; + readonly extensionsStore: ExtensionsStore; } export abstract class LensProtocolRouter { @@ -76,7 +76,7 @@ export abstract class LensProtocolRouter { static readonly ExtensionUrlSchema = `/:${EXTENSION_PUBLISHER_MATCH}(@[A-Za-z0-9_]+)?/:${EXTENSION_NAME_MATCH}`; - constructor(protected dependencies: Dependencies) {} + constructor(protected readonly dependencies: LensProtocolRouterDependencies) {} /** * Attempts to route the given URL to all internal routes that have been registered diff --git a/src/extensions/extensions-store/extensions-store.ts b/src/extensions/extensions-store/extensions-store.ts index c1345bfec9..2ec1c8fd55 100644 --- a/src/extensions/extensions-store/extensions-store.ts +++ b/src/extensions/extensions-store/extensions-store.ts @@ -17,6 +17,11 @@ export interface LensExtensionState { name: string; } +export interface IsEnabledExtensionDescriptor { + id: string; + isBundled: boolean; +} + export class ExtensionsStore extends BaseStore { readonly displayName = "ExtensionsStore"; constructor() { @@ -36,7 +41,7 @@ export class ExtensionsStore extends BaseStore { protected state = observable.map(); - isEnabled({ id, isBundled }: { id: string; isBundled: boolean }): boolean { + isEnabled({ id, isBundled }: IsEnabledExtensionDescriptor): boolean { // By default false, so that copied extensions are disabled by default. // If user installs the extension from the UI, the Extensions component will specifically enable it. return isBundled || Boolean(this.state.get(id)?.enabled); diff --git a/src/main/protocol-handler/__test__/router.test.ts b/src/main/protocol-handler/__test__/router.test.ts index 05c8f8a7d9..545f8cc7eb 100644 --- a/src/main/protocol-handler/__test__/router.test.ts +++ b/src/main/protocol-handler/__test__/router.test.ts @@ -6,11 +6,10 @@ import * as uuid from "uuid"; import { broadcastMessage } from "../../../common/ipc"; -import { ProtocolHandlerExtension, ProtocolHandlerInternal } from "../../../common/protocol-handler"; +import { ProtocolHandlerExtension, ProtocolHandlerInternal, ProtocolHandlerInvalid } from "../../../common/protocol-handler"; import { delay, noop } from "../../../common/utils"; -import { ExtensionsStore } from "../../../extensions/extensions-store/extensions-store"; +import type { ExtensionsStore, IsEnabledExtensionDescriptor } from "../../../extensions/extensions-store/extensions-store"; import type { LensProtocolRouterMain } from "../lens-protocol-router-main/lens-protocol-router-main"; -import mockFs from "mock-fs"; import { getDiForUnitTesting } from "../../getDiForUnitTesting"; import lensProtocolRouterMainInjectable from "../lens-protocol-router-main/lens-protocol-router-main.injectable"; import extensionsStoreInjectable from "../../../extensions/extensions-store/extensions-store.injectable"; @@ -33,16 +32,16 @@ function throwIfDefined(val: any): void { describe("protocol router tests", () => { let extensionInstances: ObservableMap; let lpr: LensProtocolRouterMain; - let extensionsStore: ExtensionsStore; + let enabledExtensions: Set; beforeEach(async () => { const di = getDiForUnitTesting({ doGeneralOverrides: true }); - mockFs({ - "tmp": {}, - }); + enabledExtensions = new Set(); - di.override(extensionsStoreInjectable, () => ExtensionsStore.createInstance()); + di.override(extensionsStoreInjectable, () => ({ + isEnabled: ({ id, isBundled }: IsEnabledExtensionDescriptor) => isBundled || enabledExtensions.has(id), + } as unknown as ExtensionsStore)); di.permitSideEffects(getConfigurationFileModelInjectable); di.permitSideEffects(appVersionInjectable); @@ -50,24 +49,19 @@ describe("protocol router tests", () => { di.override(directoryForUserDataInjectable, () => "some-directory-for-user-data"); extensionInstances = di.inject(extensionInstancesInjectable); - extensionsStore = di.inject(extensionsStoreInjectable); lpr = di.inject(lensProtocolRouterMainInjectable); lpr.rendererLoaded = true; }); - afterEach(() => { - jest.clearAllMocks(); - - mockFs.restore(); - }); - it("should throw on non-lens URLS", async () => { - expect(lpr.route("https://google.ca")).rejects.toBeDefined(); + await lpr.route("https://google.ca"); + expect(broadcastMessage).toBeCalledWith(ProtocolHandlerInvalid, "invalid protocol", "https://google.ca"); }); it("should throw when host not internal or extension", async () => { - expect(lpr.route("lens://foobar")).rejects.toBeDefined(); + await lpr.route("lens://foobar"); + expect(broadcastMessage).toBeCalledWith(ProtocolHandlerInvalid, "invalid host", "lens://foobar"); }); it("should not throw when has valid host", async () => { @@ -92,7 +86,7 @@ describe("protocol router tests", () => { }); extensionInstances.set(extId, ext); - extensionsStore.mergeState([[extId, { enabled: true, name: "@mirantis/minikube" }]]); + enabledExtensions.add(extId); lpr.addInternalHandler("/", noop); @@ -172,7 +166,7 @@ describe("protocol router tests", () => { }); extensionInstances.set(extId, ext); - extensionsStore.mergeState([[extId, { enabled: true, name: "@foobar/icecream" }]]); + enabledExtensions.add(extId); try { expect(await lpr.route("lens://extension/@foobar/icecream/page/foob")).toBeUndefined(); @@ -211,7 +205,7 @@ describe("protocol router tests", () => { }); extensionInstances.set(extId, ext); - extensionsStore.mergeState([[extId, { enabled: true, name: "@foobar/icecream" }]]); + enabledExtensions.add(extId); } { @@ -237,13 +231,11 @@ describe("protocol router tests", () => { }); extensionInstances.set(extId, ext); - extensionsStore.mergeState([[extId, { enabled: true, name: "icecream" }]]); + enabledExtensions.add(extId); } - extensionsStore.mergeState([ - ["@foobar/icecream", { enabled: true, name: "@foobar/icecream" }], - ["icecream", { enabled: true, name: "icecream" }], - ]); + enabledExtensions.add("@foobar/icecream"); + enabledExtensions.add("icecream"); try { expect(await lpr.route("lens://extension/icecream/page")).toBeUndefined(); diff --git a/src/main/protocol-handler/lens-protocol-router-main/lens-protocol-router-main.ts b/src/main/protocol-handler/lens-protocol-router-main/lens-protocol-router-main.ts index 56270ac6b2..14b8fa3347 100644 --- a/src/main/protocol-handler/lens-protocol-router-main/lens-protocol-router-main.ts +++ b/src/main/protocol-handler/lens-protocol-router-main/lens-protocol-router-main.ts @@ -9,11 +9,9 @@ import URLParse from "url-parse"; import type { LensExtension } from "../../../extensions/lens-extension"; import { broadcastMessage } from "../../../common/ipc"; import { observable, when, makeObservable } from "mobx"; -import type { RouteAttempt } from "../../../common/protocol-handler"; +import type { LensProtocolRouterDependencies, RouteAttempt } from "../../../common/protocol-handler"; import { ProtocolHandlerInvalid } from "../../../common/protocol-handler"; import { disposer, noop } from "../../../common/utils"; -import type { ExtensionLoader } from "../../../extensions/extension-loader"; -import type { ExtensionsStore } from "../../../extensions/extensions-store/extensions-store"; export interface FallbackHandler { (name: string): Promise; @@ -36,9 +34,7 @@ function checkHost(url: URLParse): boolean { } } -interface Dependencies { - extensionLoader: ExtensionLoader; - extensionsStore: ExtensionsStore; +export interface LensProtocolRouterMainDependencies extends LensProtocolRouterDependencies { showApplicationWindow: () => Promise; } @@ -50,7 +46,7 @@ export class LensProtocolRouterMain extends proto.LensProtocolRouter { protected disposers = disposer(); - constructor(protected dependencies: Dependencies) { + constructor(protected readonly dependencies: LensProtocolRouterMainDependencies) { super(dependencies); makeObservable(this);