diff --git a/src/extensions/registries/__tests__/page-registry.test.ts b/src/extensions/registries/__tests__/page-registry.test.ts index 2910c874c9..6f0d333681 100644 --- a/src/extensions/registries/__tests__/page-registry.test.ts +++ b/src/extensions/registries/__tests__/page-registry.test.ts @@ -1,4 +1,4 @@ -import { getExtensionPageUrl, globalPageRegistry } from "../page-registry"; +import { getExtensionPageUrl, globalPageRegistry, PageTargetParams } from "../page-registry"; import { LensExtension } from "../../lens-extension"; import React from "react"; @@ -17,6 +17,16 @@ describe("getPageUrl", () => { isBundled: false, isEnabled: true }); + globalPageRegistry.add({ + id: "page-with-params", + components: { + Page: () => React.createElement("Page with params") + }, + params: { + test1: "test1-default", + test2: "" // no default value, just declaration + }, + }, ext); }); it("returns a page url for extension", () => { @@ -34,6 +44,24 @@ describe("getPageUrl", () => { it("adds / prefix", () => { expect(getExtensionPageUrl({ extensionId: ext.name, pageId: "test" })).toBe("/extension/foo-bar/test"); }); + + it("normalize possible multi-slashes in page.id", () => { + expect(getExtensionPageUrl({ extensionId: ext.name, pageId: "//test/" })).toBe("/extension/foo-bar/test"); + }); + + it("gets page url with custom params", () => { + const params: PageTargetParams = { test1: "one", test2: "2" }; + const searchParams = new URLSearchParams(params); + const pageUrl = getExtensionPageUrl({ extensionId: ext.name, pageId: "page-with-params", params }); + + expect(pageUrl).toBe(`/extension/foo-bar/page-with-params?${searchParams}`); + }); + + it("gets page url with default custom params", () => { + const defaultPageUrl = getExtensionPageUrl({ extensionId: ext.name, pageId: "page-with-params", }); + + expect(defaultPageUrl).toBe(`/extension/foo-bar/page-with-params?test1=test1-default`); + }); }); describe("globalPageRegistry", () => { diff --git a/src/extensions/registries/page-registry.ts b/src/extensions/registries/page-registry.ts index ee6804c8ca..52e95db882 100644 --- a/src/extensions/registries/page-registry.ts +++ b/src/extensions/registries/page-registry.ts @@ -41,22 +41,29 @@ export interface RegisteredPage extends PageRegistration { } export function getExtensionPageUrl(target: PageTarget): string { - const { extensionId, pageId = "", params: targetPageParams = {} } = target; + const { extensionId, pageId = "", params: targetParams = {} } = target; + + const pagePath = ["/extension", sanitizeExtensionName(extensionId), pageId] + .filter(Boolean) + .join("/").replace(/\/+/g, "/").replace(/\/$/, ""); // normalize multi-slashes (e.g. coming from page.id) - const pagePath = ["/extension", sanitizeExtensionName(extensionId), pageId].join("/"); const pageUrl = new URL(pagePath, `http://localhost`); // stringify params to matched target page - const targetPage = globalPageRegistry.getByPageTarget(target) || clusterPageRegistry.getByPageTarget(target); + const registeredPage = globalPageRegistry.getByPageTarget(target) || clusterPageRegistry.getByPageTarget(target); - if (targetPage?.params) { - Object.entries(targetPage.params).forEach(([name, param]) => { - const paramValue = targetPageParams[name]; + if (registeredPage?.params) { + Object.entries(registeredPage.params).forEach(([name, param]) => { + const targetParamValue = targetParams[name]; if (param instanceof UrlParam) { - pageUrl.searchParams.set(name, param.stringify(paramValue)); + pageUrl.searchParams.set(name, param.stringify(targetParamValue)); } else { - pageUrl.searchParams.set(name, String(paramValue ?? param)); + const value = String(targetParamValue ?? param); + + if (value) { + pageUrl.searchParams.set(name, value); + } } }); }