diff --git a/libs/web-components/src/common/urls.spec.ts b/libs/web-components/src/common/urls.spec.ts
index f7a4919bd..0c9058dc9 100644
--- a/libs/web-components/src/common/urls.spec.ts
+++ b/libs/web-components/src/common/urls.spec.ts
@@ -44,13 +44,13 @@ it("should match urls", async () => {
desc: "empty test url",
windowUrl: new URL("http://localhost/foo"),
testUrl: "",
- weight: 0,
+ weight: -1,
},
{
desc: "root path only match",
windowUrl: new URL("http://localhost"),
testUrl: "/",
- weight: 0,
+ weight: 1,
},
{
desc: "path match",
@@ -121,25 +121,37 @@ it("should match urls", async () => {
];
for (const spec of specs) {
- expect(isUrlMatch(spec.windowUrl, spec.testUrl)).toEqual(spec.weight);
+ try {
+ expect(isUrlMatch(spec.windowUrl, spec.testUrl)).toEqual(spec.weight);
+ } catch (error) {
+ throw new Error(spec.desc);
+ }
+
}
});
-describe("should getMatchedLink", () => {
+interface MenuTest {
+ desc: string;
+ windowUrl: URL;
+ activeMenuHref: string|undefined;
+}
+
+it("should fix bug/1368 getMatchedLink", () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const links: any[] = [
{
- getAttribute: (attr: string) => attr === 'href' ? "#/" : null,
+ getAttribute: (attr: string) => attr === 'href' ? "/" : null,
},
{
- getAttribute: (attr: string) => attr === 'href' ? "#/get-started" : null,
+ getAttribute: (attr: string) => attr === 'href' ? "/get-started" : null,
},
{
- getAttribute: (attr: string) => attr === 'href' ? "#/tabs" : null,
+ getAttribute: (attr: string) => attr === 'href' ? "/accordion" : null,
},
{
getAttribute: (attr: string) => attr === 'href' ? "/patterns" : null,
},
+ // Make sure external link won't be able to highlighted in any case, even it matched
{
getAttribute: (attr: string) => {
if (attr === 'href') return "https://google.com/choose";
@@ -149,54 +161,45 @@ describe("should getMatchedLink", () => {
}
];
+ const specs: MenuTest[] = [
+ {
+ desc: "return home menu / if we navigate to /",
+ windowUrl: new URL("http://localhost/"),
+ activeMenuHref: "/"
+ },
+ {
+ desc: "return Get started menu if we navigate to /get-started",
+ windowUrl: new URL("http://localhost/get-started"),
+ activeMenuHref: "/get-started"
+ },
+ {
+ desc: "return Get started menu if we navigate to /get-started/developers",
+ windowUrl: new URL("http://localhost/get-started/developers"),
+ activeMenuHref: "/get-started"
+ },
+ {
+ desc: "return Accordion if we navigate to /accordion#tab-0",
+ windowUrl: new URL("http://localhost/accordion#tab-0"),
+ activeMenuHref: "/accordion"
+ },
+ {
+ desc: "return patterns menu if we navigate to /patterns#tab-1",
+ windowUrl: new URL("http://localhost/patterns#tab-1"),
+ activeMenuHref: "/patterns"
+ },
+ {
+ desc: "return no menu if we navigate to /profile",
+ windowUrl: new URL("http://localhost/profile"),
+ activeMenuHref: undefined
+ }
+ ];
- it("should return null if we navigate to a home root / (React app)", () => {
- const windowUrl = "/";
- const result = getMatchedLink(links, windowUrl);
- expect(result).toBeNull();
- })
-
- it("should return Home menu if we navigate to a root #/ (Angular app)", () => {
- const windowUrl = "/ui-components/#/";
- const result = getMatchedLink(links, windowUrl);
- expect(result?.getAttribute("href")).toEqual("#/");
- });
-
- it("should return get-started if we navigate to /get-started", () => {
- const windowUrl = "/ui-components/#/get-started";
- const result = getMatchedLink(links, windowUrl);
- expect(result?.getAttribute("href")).toEqual("#/get-started");
- });
-
- it("should return get-started if we navigate to /get-started/developers", () => {
- const windowUrl = "/ui-components/#/get-started/developers";
- const result = getMatchedLink(links, windowUrl)
- expect(result?.getAttribute("href")).toEqual("#/get-started");
- });
-
- it("should return tabs if we navigate to /tabs#tab-0", () => {
- const windowUrl = "/ui-components/#/tabs#tab-0";
- const result = getMatchedLink(links, windowUrl);
- expect(result?.getAttribute("href")).toEqual("#/tabs");
- });
-
- it("should return null if we navigate to /accordion", () => {
- const windowUrl = "/ui-components/#/accordion";
- const result = getMatchedLink(links, windowUrl);
- console.log(result?.getAttribute("href"));
- expect(result).toBeNull();
- });
-
- it("should return patterns menu if we navigate to /patterns", () => {
- const windowUrl = "/patterns#tab-0";
- const result = getMatchedLink(links, windowUrl);
- expect(result?.getAttribute("href")).toEqual("/patterns");
- });
-
- it("should return patterns menu if we navigate to /patterns/complex-form", () => {
- const windowUrl = "/patterns/complex-form";
- const result = getMatchedLink(links, windowUrl);
- expect(result?.getAttribute("href")).toEqual("/patterns");
- });
-
+ for (const spec of specs) {
+ const matchedLink = getMatchedLink(links, spec.windowUrl);
+ try {
+ expect(matchedLink?.getAttribute("href")).toEqual(spec.activeMenuHref);
+ } catch (error) {
+ throw new Error(spec.desc);
+ }
+ }
})
diff --git a/libs/web-components/src/common/urls.ts b/libs/web-components/src/common/urls.ts
index 2bde32db0..6a412adb9 100644
--- a/libs/web-components/src/common/urls.ts
+++ b/libs/web-components/src/common/urls.ts
@@ -14,17 +14,14 @@ export function isUrlMatch(windowUrl: URL | Location, testUrl: string): number {
return 1;
}
- // root url
- if (urlParts.length === 1 && urlParts[0] === "") {
- return 0;
- }
-
let weight = -1;
let index = 0;
- for (const part of windowUrlParts) {
- if (urlParts[index] !== part) {
- break;
+ for (const part of urlParts) {
+ if (windowUrlParts[index] !== part) {
+ // Ex: windowURl: /get-started/designers should match to a menu "/#/get-started, but not match to "/get-started/developers
+ // So if we check by menu (linkParts) and have anything not matched, it should return -1 (not matched), otherwise menu /get-started/developers & menu /get-started/ will have the same weight
+ return -1;
}
weight += 1;
index++;
@@ -34,54 +31,12 @@ export function isUrlMatch(windowUrl: URL | Location, testUrl: string): number {
return weight >= 0 ? weight + 1 : weight;
}
-function findMaxIndexMatchedToWindowUrlParts(windowUrlParts: string[], urlParts: string[]) {
-
- for (let urlPartsIndex = 0; urlPartsIndex < urlParts.length; urlPartsIndex++) {
- for (let windowUrlPartsIndex = 0; windowUrlPartsIndex < windowUrlParts.length; windowUrlPartsIndex++) {
- const cleanedWindowUrlPart = windowUrlParts[windowUrlPartsIndex].split("#")[0];
- const cleanedUrlPart = urlParts[urlPartsIndex].split("#")[0];
- if (cleanedUrlPart === cleanedWindowUrlPart) {
- return windowUrlPartsIndex;
- }
- }
- }
- return -1;
-}
-
-function getUrlWeight(windowUrl: string, linkHref: string) {
- const windowParts = decodeURIComponent(windowUrl).replace(/^\/#?/, "").split("/");
- const linkParts = decodeURIComponent(linkHref).replace(/^\//, "").split("/");
-
-
-
- let startIndex = findMaxIndexMatchedToWindowUrlParts(windowParts, linkParts);
- if (startIndex === -1) {
- return -1;
- }
- // Weight should start with matched index on windowUrl. Ex: window.pathname="/ui-components/#/", linkHref="#/", Home menu should have higher weight than the rest
- let weight = startIndex;
-
- for (let i = 0; i < linkParts.length && startIndex < windowParts.length; i++) {
- const cleanedWindowPartStr = windowParts[startIndex].split("#")[0];
- const cleanedLinkPartStr = linkParts[i].split("#")[0];
- if (cleanedWindowPartStr === cleanedLinkPartStr) {
- // Increase weight for each matching segment
- weight += 1;
- } else {
- // Break loop on first non-match
- break;
- }
- startIndex++;
- }
-
- return weight;
-}
-export function getMatchedLink(links: Element[], windowUrl: string) {
+export function getMatchedLink(links: Element[], windowUrl: URL | Location) {
const weights = links.map((link) => {
if (link.getAttribute("target")) return -1;
- return getUrlWeight(
- windowUrl,
+ return isUrlMatch(
+ windowUrl,
(link as HTMLLinkElement).getAttribute("href") || "",
)
}
diff --git a/libs/web-components/src/components/app-header-menu/AppHeaderMenu.svelte b/libs/web-components/src/components/app-header-menu/AppHeaderMenu.svelte
index 34a7d3e54..8813f994c 100644
--- a/libs/web-components/src/components/app-header-menu/AppHeaderMenu.svelte
+++ b/libs/web-components/src/components/app-header-menu/AppHeaderMenu.svelte
@@ -1,14 +1,14 @@
+
+
+ Get started
+ Overview
+ UX designers
+
+ Overview
+ Setup
+
+
diff --git a/libs/web-components/src/components/side-menu/side-menu.spec.ts b/libs/web-components/src/components/side-menu/side-menu.spec.ts
index 2a6389383..b4aafafbc 100644
--- a/libs/web-components/src/components/side-menu/side-menu.spec.ts
+++ b/libs/web-components/src/components/side-menu/side-menu.spec.ts
@@ -1,5 +1,22 @@
-// import SideMenu from "./SideMenu.svelte";
-// import { render } from "@testing-library/svelte";
import { it } from "vitest";
+import { render } from "@testing-library/svelte";
+import SideMenuWrapper from './SideMenuWrapper.test.svelte';
-it.skip("test", async () => { /* do nothing */ });
+describe.skip("SideMenu should render with children and set highlighted menu item correctly", () => {
+ it("should render", async() => {
+ // Mock window.location
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-expect-error
+ delete window.location;
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-expect-error
+ window.location = new URL('http://localhost/get-started');
+ const {container} = render(SideMenuWrapper);
+
+ const links = container.querySelectorAll("a");
+ expect(links.length).toBe(4);
+ const currentLink = container.querySelector("a.current");
+ expect(currentLink).toBeTruthy();
+ expect(currentLink?.getAttribute("href")).toBe("get-started");
+ })
+})
diff --git a/libs/web-components/src/components/tabs/Tabs.svelte b/libs/web-components/src/components/tabs/Tabs.svelte
index 89c8046f9..55c57377c 100644
--- a/libs/web-components/src/components/tabs/Tabs.svelte
+++ b/libs/web-components/src/components/tabs/Tabs.svelte
@@ -50,7 +50,7 @@
}
function bindChildren() {
- const path = window.location.href;
+ const path = window.location.pathname;
// create buttons (tabs) for each of the tab contents elements
_tabProps.forEach((tabProps, index) => {