Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 19 additions & 13 deletions frontend/src/components/app-layout/NavBar.test.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,37 @@
import { screen } from "@testing-library/react";
import { render, screen } from "@testing-library/react";
import { describe, it, expect } from "vitest";
import NavBar from "./NavBar";
import { renderWithProviders } from "../../tests/test-utils";

describe("NavBar", () => {
it("renders an explicit homepage link", () => {
renderWithProviders(<NavBar />);
it("renders Working Groups link with correct URL", () => {
render(<NavBar />);

const homeLink = screen.getByRole("link", {
name: /gpu mode home/i,
const workingGroupsLink = screen.getByRole("link", {

Check failure on line 9 in frontend/src/components/app-layout/NavBar.test.tsx

View workflow job for this annotation

GitHub Actions / test

src/components/app-layout/NavBar.test.tsx > NavBar > renders Working Groups link with correct URL

TestingLibraryElementError: Unable to find an accessible element with the role "link" and name `/working groups/i` Here are the accessible roles: banner: Name "": <header class="MuiPaper-root MuiPaper-elevation MuiPaper-elevation4 MuiAppBar-root MuiAppBar-colorPrimary MuiAppBar-positionFixed mui-fixed css-ndnlem-MuiPaper-root-MuiAppBar-root" style="--Paper-shadow: 0px 2px 4px -1px rgba(0,0,0,0.2),0px 4px 5px 0px rgba(0,0,0,0.14),0px 1px 10px 0px rgba(0,0,0,0.12);" /> -------------------------------------------------- link: Name "GPU MODE": <a class="MuiTypography-root MuiTypography-inherit MuiLink-root MuiLink-underlineNone css-6b04s2-MuiTypography-root-MuiLink-root" href="/" /> Name "News": <a class="MuiTypography-root MuiTypography-inherit MuiLink-root MuiLink-underlineNone css-opw7is-MuiTypography-root-MuiLink-root" href="/news" /> Name "Events": <a class="MuiTypography-root MuiTypography-inherit MuiLink-root MuiLink-underlineNone css-opw7is-MuiTypography-root-MuiLink-root" href="/events" /> Name "Projects": <a class="MuiTypography-root MuiTypography-inherit MuiLink-root MuiLink-underlineNone css-opw7is-MuiTypography-root-MuiLink-root" href="/working-groups" /> Name "Login": <a aria-label="Login" class="MuiButtonBase-root MuiButton-root MuiButton-outlined MuiButton-outlinedPrimary MuiButton-sizeSmall MuiButton-outlinedSizeSmall MuiButton-colorPrimary MuiButton-root MuiButton-outlined MuiButton-outlinedPrimary MuiButton-sizeSmall MuiButton-outlinedSizeSmall MuiButton-colorPrimary css-14ra4zo-MuiButtonBase-root-MuiButton-root" data-mui-internal-clone-element="true" data-testid="login-btn" href="/login" tabindex="0" /> -------------------------------------------------- img: Name "GPU MODE": <img alt="GPU MODE" class="MuiBox-root css-1cwcwxp" src="/gpu-mode-logo/black-cropped.svg" /> -------------------------------------------------- button: Name "Switch to light mode": <button aria-label="Switch to light mode" class="MuiButtonBase-root MuiIconButton-root MuiIconButton-colorInherit MuiIconButton-sizeSmall css-38cjb0-MuiButtonBase-root-MuiIconButton-root" data-mui-internal-clone-element="true" tabindex="0" type="button" /> -------------------------------------------------- Ignored nodes: comments, script, style <body> <div> <header class="MuiPaper-root MuiPaper-elevation MuiPaper-elevation4 MuiAppBar-root MuiAppBar-colorPrimary MuiAppBar-positionFixed mui-fixed css-ndnlem-MuiPaper-root-MuiAppBar-root" style="--Paper-shadow: 0px 2px 4px -1px rgba(0,0,0,0.2),0px 4px 5px 0px rgba(0,0,0,0.14),0px 1px 10px 0px rgba(0,0,0,0.12);" > <div class="MuiBox-root css-1hzmvx4" > <div class="MuiToolbar-root MuiToolbar-gutters MuiToolbar-regular css-h6ref9-MuiToolbar-root" > <div class="MuiBox-root css-u60zxe" > <a class="MuiTypography-root MuiTypography-inherit MuiLink-root MuiLink-underlineNone css-6b04s2-MuiTypography-root-MuiLink-root" href="/" > <div class="MuiBox-root css-171onha" > <img alt="GPU MODE" class="MuiBox-root css-1cwcwxp" src="/gpu-mode-logo/black-cropped.svg" /> </div> </a> </div> <div class="MuiBox-root css-mubuwc" > <a class="MuiTypography-root MuiTypography-inherit MuiLink-root MuiLink-underlineNone css-opw7is-MuiTypography-root-MuiLink-root" href="/news" > <div class="MuiBox-root css-1drdzif" > News </div> </a> <a class="MuiTypography-root MuiTypography-inherit MuiLink-root MuiLink-underlineNone css-opw7is-MuiTypography-root-MuiLink-root"
name: /working groups/i,
});

expect(homeLink).toHaveAttribute("href", "/home");
expect(homeLink).toHaveTextContent("Home");
expect(workingGroupsLink).toBeInTheDocument();
expect(workingGroupsLink).toHaveAttribute("href", "/working-groups");
// Internal link should not have target="_blank" or rel="noopener"
expect(workingGroupsLink).not.toHaveAttribute("target", "_blank");
expect(workingGroupsLink).not.toHaveAttribute("rel", "noopener");
});

it("renders all expected navigation links in correct order", () => {
renderWithProviders(<NavBar />);
render(<NavBar />);

const links = screen.getAllByRole("link");
const navigationLinks = links.filter((link) =>
["News", "Events", "Projects"].includes(link.textContent || ""),
["News", "Working Groups", "Events", "Resources", "Docs"].includes(
link.textContent || "",
),
);

expect(navigationLinks).toHaveLength(3);
expect(navigationLinks).toHaveLength(5);

Check failure on line 30 in frontend/src/components/app-layout/NavBar.test.tsx

View workflow job for this annotation

GitHub Actions / test

src/components/app-layout/NavBar.test.tsx > NavBar > renders all expected navigation links in correct order

AssertionError: expected [ <a …(2)>…(1)</a>, <a …(2)>…(1)</a> ] to have a length of 5 but got 2 - Expected + Received - 5 + 2 ❯ src/components/app-layout/NavBar.test.tsx:30:29
expect(navigationLinks[0]).toHaveTextContent("News");
expect(navigationLinks[1]).toHaveTextContent("Events");
expect(navigationLinks[2]).toHaveTextContent("Projects");
expect(navigationLinks[1]).toHaveTextContent("Working Groups");
expect(navigationLinks[2]).toHaveTextContent("Events");
expect(navigationLinks[3]).toHaveTextContent("Resources");
expect(navigationLinks[4]).toHaveTextContent("Docs");
});
});
49 changes: 7 additions & 42 deletions frontend/src/components/app-layout/NavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import ArrowOutwardIcon from "@mui/icons-material/ArrowOutward";
import LightModeIcon from "@mui/icons-material/LightMode";
import DarkModeIcon from "@mui/icons-material/DarkMode";
import SettingsBrightnessIcon from "@mui/icons-material/SettingsBrightness";
import HomeRoundedIcon from "@mui/icons-material/HomeRounded";
import { useTheme } from "@mui/material/styles";
import {
flexRowCenter,
Expand Down Expand Up @@ -61,42 +60,15 @@ export default function NavBar() {
];

const Brand = () => (
<Box
sx={{
...brandStyle,
position: { xs: "sticky", sm: "static" },
left: 0,
zIndex: 1,
bgcolor: "background.paper",
}}
>
<Link
href="/home"
aria-label="GPU MODE home"
underline="none"
color="inherit"
sx={{ display: "block" }}
>
<Box
sx={{
...flexRowCenter,
display: { xs: "flex", sm: "none" },
minHeight: 44,
px: 0.5,
fontSize: "1rem",
fontWeight: 600,
}}
>
<HomeRoundedIcon sx={{ fontSize: 22 }} />
Home
</Box>
<Box sx={{ display: { xs: "none", sm: "flex" } }}>
<Box sx={brandStyle}>
<Link href="/" underline="none" color="inherit">
<Box sx={{ ...flexRowCenter }}>
<Box
component="img"
src={logoSrc}
alt=""
alt="GPU MODE"
sx={{
height: 32,
height: { xs: 24, sm: 32 },
maxWidth: "100%",
}}
/>
Expand All @@ -108,19 +80,12 @@ export default function NavBar() {
return (
<AppBar position="fixed" sx={appBarStyle}>
<ConstrainedContainer>
<Toolbar sx={{ px: 0, gap: { xs: 1, sm: 2 }, overflowX: "auto" }}>
<Toolbar sx={{ px: 0, gap: 2, overflowX: "auto" }}>
{/* Left: Brand */}
<Brand />

{/* Middle: Links */}
<Box
sx={{
...flexRowCenterMediumGap,
gap: { xs: 2.5, sm: 5 },
ml: { xs: 0, sm: 3 },
flexShrink: 0,
}}
>
<Box sx={{ ...flexRowCenterMediumGap, ml: 3, flexShrink: 0 }}>
{links.map(({ label, href, external }) => (
<Link
key={label}
Expand Down
5 changes: 2 additions & 3 deletions frontend/src/components/app-layout/styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@ export const brandStyle: SxProps<Theme> = {
...flexRowCenter,
...mediumText,
fontWeight: "bold",
flexShrink: 0,
ml: { xs: 0, sm: -2 }, // Keep the mobile home control fully visible
ml: -2, // Negative left margin to reduce space from left edge
mr: {
xs: 1, // margin on extra-small screens
xs: 2, // margin on extra-small screens
sm: 4, // margin on small screens
md: 8, // margin on medium screens
lg: 16, // margin on large screens
Expand Down
Loading