From bfb01f64f62c294d468c1bd2528b5d1eb6e4e456 Mon Sep 17 00:00:00 2001 From: Adam Joseph Arling Date: Wed, 10 Jul 2024 11:54:48 -0500 Subject: [PATCH] Add support for mobile tests; remove duplicate Header component from layout --- playwright.config.ts | 16 +-- pnpm-lock.yaml | 15 +- src/app/features/page.tsx | 2 - src/app/getting-started/page.tsx | 2 - src/app/news/page.tsx | 2 - src/app/presentations/page.tsx | 2 - src/components/layout/header.tsx | 17 ++- src/components/layout/nav.tsx | 234 ------------------------------- tests/home.spec.ts | 2 +- tests/layout.spec.ts | 122 +++++++++++----- 10 files changed, 116 insertions(+), 298 deletions(-) delete mode 100644 src/components/layout/nav.tsx diff --git a/playwright.config.ts b/playwright.config.ts index 1c00d74..7b9fbf2 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -51,14 +51,14 @@ export default defineConfig({ }, /* Test against mobile viewports. */ - // { - // name: "Mobile Chrome", - // use: { ...devices["Pixel 5"] }, - // }, - // { - // name: "Mobile Safari", - // use: { ...devices["iPhone 12"] }, - // }, + { + name: "Mobile Chrome", + use: { ...devices["Pixel 5"] }, + }, + { + name: "Mobile Safari", + use: { ...devices["iPhone 12"] }, + }, /* Test against branded browsers. */ // { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 152b05c..2a7d95e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -356,7 +356,7 @@ packages: engines: {node: '>=6.0.0'} dependencies: '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/sourcemap-codec': 1.5.0 '@jridgewell/trace-mapping': 0.3.25 /@jridgewell/resolve-uri@3.1.2: @@ -367,14 +367,14 @@ packages: resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} engines: {node: '>=6.0.0'} - /@jridgewell/sourcemap-codec@1.4.15: - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + /@jridgewell/sourcemap-codec@1.5.0: + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} /@jridgewell/trace-mapping@0.3.25: resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} dependencies: '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/sourcemap-codec': 1.5.0 /@next/env@14.2.4: resolution: {integrity: sha512-3EtkY5VDkuV2+lNmKlbkibIJxcO4oIHEhBWne6PaAp+76J9KoSsGvNikp6ivzAT8dhhBMYrm6op2pS1ApG0Hzg==} @@ -3963,9 +3963,8 @@ packages: dependencies: js-tokens: 4.0.0 - /lru-cache@10.4.2: - resolution: {integrity: sha512-voV4dDrdVZVNz84n39LFKDaRzfwhdzJ7akpyXfTMxCgRUp07U3lcJUXRlhTKP17rgt09sUzLi5iCitpEAr+6ug==} - engines: {node: 14 || 16 || 18 || 20 || >=22} + /lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} /make-dir@3.1.0: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} @@ -4518,7 +4517,7 @@ packages: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} dependencies: - lru-cache: 10.4.2 + lru-cache: 10.4.3 minipass: 7.1.2 /path-type@4.0.0: diff --git a/src/app/features/page.tsx b/src/app/features/page.tsx index 8410fd2..f3ac4a1 100644 --- a/src/app/features/page.tsx +++ b/src/app/features/page.tsx @@ -1,7 +1,6 @@ import BgLayer from "@/components/layout/bg-layer"; import Container from "@/components/layout/container"; import FeatureList from "@/components/features/list"; -import Header from "@/components/layout/header"; import Implementations from "@/components/features/implementations"; import MainWrapper from "@/components/layout/main-wrapper"; import { Metadata } from "next"; @@ -14,7 +13,6 @@ export const metadata: Metadata = { export default async function FeaturesPage() { return (
-
-
-
-
{ const [mobileMenuOpen, setMobileMenuOpen] = useState(false); + const pathname = usePathname(); + + useEffect(() => { + if (mobileMenuOpen) { + setMobileMenuOpen(false); + } + }, [pathname]); return (
@@ -94,9 +102,10 @@ const Header = () => { className="lg:hidden" open={mobileMenuOpen} onClose={setMobileMenuOpen} + data-testid="mobile-menu" >
- + ); diff --git a/src/components/layout/nav.tsx b/src/components/layout/nav.tsx deleted file mode 100644 index 3435a1c..0000000 --- a/src/components/layout/nav.tsx +++ /dev/null @@ -1,234 +0,0 @@ -"use client"; - -import { - ArrowPathIcon, - Bars3Icon, - ChartPieIcon, - CursorArrowRaysIcon, - FingerPrintIcon, - SquaresPlusIcon, - XMarkIcon, -} from "@heroicons/react/24/outline"; -import { - ChevronDownIcon, - PhoneIcon, - PlayCircleIcon, -} from "@heroicons/react/20/solid"; -import { Dialog, Popover, Transition } from "@headlessui/react"; -import { Fragment, useState } from "react"; - -import Image from "next/image"; -import hykuLogo from "../../../public/logo-hyku.png"; - -const callsToAction = [ - { name: "Watch demo", href: "#", icon: PlayCircleIcon }, - { name: "Contact sales", href: "#", icon: PhoneIcon }, -]; -const company = [ - { - name: "About us", - href: "#", - description: - "Learn more about our company values and mission to empower others", - }, - { - name: "Careers", - href: "#", - description: - "Looking for you next career opportunity? See all of our open positions", - }, - { - name: "Support", - href: "#", - description: - "Get in touch with our dedicated support team or reach out on our community forums", - }, - { - name: "Blog", - href: "#", - description: - "Read our latest announcements and get perspectives from our team", - }, -]; - -const nav = [ - { - name: "Features and Implementations", - href: "/features", - }, - { - name: "Getting Started", - href: "/getting-started", - }, - { - name: "News", - href: "/news", - }, - { - name: "Contact", - href: "/contact", - }, -]; - -export default function Nav() { - const [mobileMenuOpen, setMobileMenuOpen] = useState(false); - - return ( -
- - -
- -
-
- - Your Company - - - -
-
-
-
- - Features - - - Marketplace - - - {company.map((item) => ( - - {item.name} - - ))} -
- -
-
-
-
- {callsToAction.map((item) => ( - - {item.name} - - ))} -
-
-
-
- ); -} diff --git a/tests/home.spec.ts b/tests/home.spec.ts index 8ea5e04..47f5e43 100644 --- a/tests/home.spec.ts +++ b/tests/home.spec.ts @@ -15,7 +15,7 @@ test("homepage elements", async ({ page }) => { await expect(page.locator("h1")).toContainText("Getting Started"); await page.goto("/"); - await page.waitForURL("**/"); + await page.waitForURL("/"); await expect(page.getByRole("main")).toContainText("Documentation →"); await expect(page.getByRole("img", { name: "App screenshot" })).toBeVisible(); diff --git a/tests/layout.spec.ts b/tests/layout.spec.ts index 50f567d..c58b3f3 100644 --- a/tests/layout.spec.ts +++ b/tests/layout.spec.ts @@ -8,48 +8,100 @@ const links = [ "Contact", ]; -test("has main heading and top level navigation", async ({ page }) => { +test("has main heading and top level navigation", async ({ + page, +}, testInfo) => { + const isMobile = testInfo.project.name.includes("Mobile"); + await page.goto("/"); + await page.waitForURL("/"); const header = page.getByLabel("Global"); await expect(header).toBeVisible(); await expect(header.getByAltText("Hyku logo")).toBeVisible(); - await page - .getByRole("link", { name: "Features and Implementations" }) - .nth(1) - .click(); - await expect( - page.getByRole("heading", { name: "Features and Implementations" }), - ).toBeVisible(); - - await page.getByRole("link", { name: "Getting Started" }).nth(1).click(); - await expect( - page.getByRole("heading", { name: "Getting Started" }), - ).toBeVisible(); - - await page - .getByRole("link", { name: "Presentations and Demos" }) - .nth(1) - .click(); - await expect( - page.getByRole("heading", { name: "Presentations and Demos" }), - ).toBeVisible(); - - await page.getByRole("link", { name: "News" }).nth(1).click(); - await expect( - page.getByRole("heading", { name: "News and Events" }), - ).toBeVisible(); - - await page.getByRole("link", { name: "Contact" }).nth(1).click(); - await expect( - page.getByRole("heading", { name: "Get in touch" }), - ).toBeVisible(); - - await expect( - page.getByRole("link", { name: "Learn more" }).nth(1), - ).toHaveAttribute("href", "https://github.com/samvera/hyku"); + // Test desktop navigation + if (!isMobile) { + await page + .getByRole("link", { name: "Features and Implementations" }) + .nth(1) + .click(); + await expect( + page.getByRole("heading", { name: "Features and Implementations" }), + ).toBeVisible(); + + await page.getByRole("link", { name: "Getting Started" }).nth(1).click(); + await expect( + page.getByRole("heading", { name: "Getting Started" }), + ).toBeVisible(); + + await page + .getByRole("link", { name: "Presentations and Demos" }) + .nth(1) + .click(); + await page.waitForURL("/presentations"); + await expect( + page.getByRole("heading", { name: "Presentations and Demos" }), + ).toBeVisible(); + + await page.getByRole("link", { name: "News" }).nth(1).click(); + await page.waitForURL("/news"); + await expect( + page.getByRole("heading", { name: "News and Events" }), + ).toBeVisible(); + + await page.getByRole("link", { name: "Contact" }).nth(1).click(); + await page.waitForURL("/contact"); + await expect( + page.getByRole("heading", { name: "Get in touch" }), + ).toBeVisible(); + + await expect( + page.getByRole("link", { name: "Learn more" }).nth(1), + ).toHaveAttribute("href", "https://github.com/samvera/hyku"); + } + + // Test mobile navigation + if (isMobile) { + await page.goto("/"); + + const mobileMenuEl = page.getByTestId("mobile-menu"); + const hamburgerEl = page.getByRole("button", { name: "Open main menu" }); + + await hamburgerEl.click(); + await mobileMenuEl + .getByRole("link", { name: "Features and Implementations" }) + .click(); + + await expect(page.locator("h1")).toContainText( + "Features and Implementations", + ); + + await hamburgerEl.click(); + await mobileMenuEl.getByRole("link", { name: "Getting Started" }).click(); + + await expect(page.locator("h1")).toContainText("Getting Started"); + + await hamburgerEl.click(); + await mobileMenuEl + .getByRole("link", { name: "Presentations and Demos" }) + .click(); + + await expect(page.locator("h1")).toContainText("Presentations and Demos"); + + await hamburgerEl.click(); + await mobileMenuEl.getByRole("link", { name: "News" }).click(); + + await expect(page.locator("h1")).toContainText("News and Events"); + + await hamburgerEl.click(); + await mobileMenuEl.getByRole("link", { name: "Contact" }).click(); + + await expect( + page.getByRole("heading", { name: "Get in touch" }), + ).toBeVisible(); + } }); test("has footer with links to social media", async ({ page }) => {