Skip to content

Commit a2458f0

Browse files
committed
test(nav): lock mobile navbar visual contracts
1 parent 358e7aa commit a2458f0

1 file changed

Lines changed: 82 additions & 0 deletions

File tree

src/test/Navbar.test.tsx

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,65 @@ describe("Navbar mobile menu", () => {
124124
expect(document.getElementById("mobile-navigation-panel")).not.toBeInTheDocument();
125125
expect(localStorage.getItem("language")).toBe("en");
126126
});
127+
128+
it.each([
129+
{
130+
language: "es",
131+
expectedLabels: [
132+
"Sobre mí",
133+
"Por qué elegirme",
134+
"Servicios",
135+
"Portfolio",
136+
"Contacto",
137+
"FAQ",
138+
],
139+
servicesHref: "/servicios",
140+
},
141+
{
142+
language: "en",
143+
expectedLabels: [
144+
"About me",
145+
"Why choose me",
146+
"Services",
147+
"Portfolio",
148+
"Contact",
149+
"FAQ",
150+
],
151+
servicesHref: "/en/services",
152+
},
153+
] as const)(
154+
"keeps $language desktop, mobile, and no-JavaScript navigation in parity",
155+
async ({ language, expectedLabels, servicesHref }) => {
156+
const user = userEvent.setup();
157+
renderNavbar({ initialEntry: language === "es" ? "/" : "/en", language });
158+
159+
const desktop = getRequiredElement<HTMLElement>("[data-navbar-desktop]");
160+
const trigger = screen.getByRole("button", {
161+
name: language === "es" ? "Abrir menú" : "Open menu",
162+
});
163+
const fallback = getRequiredElement<HTMLElement>("[data-nojs-mobile-nav]");
164+
const fallbackLinks = fallback.firstElementChild?.querySelectorAll("a");
165+
166+
await user.click(trigger);
167+
168+
const panel = getRequiredElement<HTMLElement>("#mobile-navigation-panel");
169+
const desktopLinks = [...desktop.children].filter(
170+
(element): element is HTMLAnchorElement =>
171+
element instanceof HTMLAnchorElement,
172+
);
173+
const mobileLinks = [...panel.children].filter(
174+
(element): element is HTMLAnchorElement =>
175+
element instanceof HTMLAnchorElement,
176+
);
177+
const noJavaScriptLinks = [...(fallbackLinks ?? [])];
178+
179+
for (const links of [desktopLinks, mobileLinks, noJavaScriptLinks]) {
180+
expect(links.map((link) => link.textContent)).toEqual(expectedLabels);
181+
expect(links.filter((link) => link.getAttribute("href") === servicesHref))
182+
.toHaveLength(1);
183+
}
184+
},
185+
);
127186
});
128187

129188
describe("Navbar color tokens", () => {
@@ -156,6 +215,29 @@ describe("Navbar color tokens", () => {
156215
expect(spanishButton).toHaveClass("text-white", "hover:text-primary");
157216
expect(englishButton).toHaveClass("text-primary", "hover:text-primary");
158217
});
218+
219+
it("keeps one approved translucent surface around the mobile panels", async () => {
220+
const user = userEvent.setup();
221+
renderNavbar();
222+
const navbar = getRequiredElement<HTMLElement>("nav[data-nojs-navbar]");
223+
const trigger = screen.getByRole("button", { name: "Abrir menú" });
224+
const fallback = getRequiredElement<HTMLElement>("[data-nojs-mobile-nav]");
225+
226+
expect(navbar).toHaveClass(
227+
"bg-black/70",
228+
"backdrop-blur-xl",
229+
"backdrop-saturate-150",
230+
);
231+
expect(fallback.parentElement).toBe(navbar);
232+
expect(fallback).not.toHaveClass("bg-black/90", "backdrop-blur-sm");
233+
234+
await user.click(trigger);
235+
236+
const panel = getRequiredElement<HTMLElement>("#mobile-navigation-panel");
237+
expect(panel.parentElement).toBe(navbar);
238+
expect(panel).not.toHaveClass("bg-black/90", "backdrop-blur-sm");
239+
expect(navbar.querySelectorAll('[class*="backdrop-blur"]')).toHaveLength(0);
240+
});
159241
});
160242

161243
describe("Navbar no-JavaScript fallback", () => {

0 commit comments

Comments
 (0)