import { SELECTORS } from "../../fixtures/selectors"; import { expect, test } from "../../fixtures/test"; import { getStickyPosition, ViewportSize } from "../../fixtures/viewports"; test.describe("Sticky Header Behavior @smoke", () => { test.beforeEach(async ({ gotoApp, waitForAppReady }) => { await gotoApp(); await waitForAppReady(); }); test("header is sticky on scroll", async ({ page }) => { const header = page.locator(SELECTORS.header.root); // Check initial position const initialPosition = await getStickyPosition( page, SELECTORS.header.root, ); expect(initialPosition.isSticky).toBe(true); // Scroll down await page.evaluate(() => window.scrollTo(0, 500)); await page.waitForTimeout(500); // Header should still be at top const scrolledPosition = await getStickyPosition( page, SELECTORS.header.root, ); expect(scrolledPosition.top).toBeLessThanOrEqual(10); // Allow small offset expect(scrolledPosition.isSticky).toBe(true); }); test("header shrinks on scroll", async ({ page }) => { const header = page.locator(SELECTORS.header.root); const headerContainer = header.locator("> div"); // Get initial height const initialHeight = await headerContainer.evaluate( (el) => el.offsetHeight, ); // Scroll down await page.evaluate(() => window.scrollTo(0, 300)); await page.waitForTimeout(500); // Get scrolled height const scrolledHeight = await headerContainer.evaluate( (el) => el.offsetHeight, ); // Header should shrink (or stay same, but not grow) expect(scrolledHeight).toBeLessThanOrEqual(initialHeight); }); test("header maintains glass effect on scroll", async ({ page }) => { // Scroll down await page.evaluate(() => window.scrollTo(0, 500)); await page.waitForTimeout(500); // Check header has backdrop blur const hasBlur = await page.evaluate(() => { const header = document.querySelector("header"); if (!header) return false; const style = window.getComputedStyle(header); return style.backdropFilter.includes("blur"); }); expect(hasBlur).toBe(true); }); }); test.describe("Sticky Footer Behavior", () => { test.beforeEach(async ({ gotoApp, waitForAppReady }) => { await gotoApp(); await waitForAppReady(); }); test("footer is sticky at bottom", async ({ page }) => { const footer = page.locator(SELECTORS.footer.root); // Check footer is visible await expect(footer).toBeVisible(); // Check footer position const footerBox = await footer.boundingBox(); const viewportHeight = await page.evaluate(() => window.innerHeight); // Footer should be at bottom of viewport expect(footerBox!.y + footerBox!.height).toBeGreaterThanOrEqual( viewportHeight - 10, ); }); test("footer does not overlap main content", async ({ page }) => { const footer = page.locator(SELECTORS.footer.root); const mainContent = page.locator("main"); // Get bounding boxes const footerBox = await footer.boundingBox(); const mainBox = await mainContent.boundingBox(); // Main content should have padding at bottom to account for footer const bodyPadding = await page.evaluate(() => { const body = document.body; const style = window.getComputedStyle(body); return parseInt(style.paddingBottom || "0"); }); expect(bodyPadding).toBeGreaterThan(0); }); }); test.describe("Back to Top Behavior @smoke", () => { test.beforeEach(async ({ gotoApp, waitForAppReady }) => { await gotoApp(); await waitForAppReady(); }); test("back to top is hidden initially", async ({ page }) => { const backToTop = page.locator(SELECTORS.backToTop.root); // Should not be visible at top of page const isVisible = await backToTop.isVisible().catch(() => false); expect(isVisible).toBe(false); }); test("back to top appears on scroll", async ({ page }) => { // Scroll down await page.evaluate(() => window.scrollTo(0, 800)); await page.waitForTimeout(500); const backToTop = page.locator(SELECTORS.backToTop.root); // Should be visible after scroll await expect(backToTop).toBeVisible(); }); test("back to top scrolls to top when clicked", async ({ page }) => { // Scroll down await page.evaluate(() => window.scrollTo(0, 1000)); await page.waitForTimeout(500); // Click back to top const backToTop = page.locator(SELECTORS.backToTop.root); await backToTop.click(); // Wait for scroll animation await page.waitForTimeout(1000); // Should be at top const scrollPosition = await page.evaluate(() => window.scrollY); expect(scrollPosition).toBeLessThanOrEqual(50); }); test("back to top is accessible", async ({ page }) => { // Scroll down to make visible await page.evaluate(() => window.scrollTo(0, 800)); await page.waitForTimeout(500); const backToTop = page.locator(SELECTORS.backToTop.root); // Should have aria-label await expect(backToTop).toHaveAttribute("aria-label"); // Should be keyboard focusable await backToTop.focus(); await expect(backToTop).toBeFocused(); }); }); test.describe("Sticky Behavior Across Breakpoints", () => { test("header and footer work on mobile", async ({ gotoApp, waitForAppReady, setViewport, page, }) => { await setViewport("mobile"); await gotoApp(); await waitForAppReady(); // Check header is sticky const header = page.locator(SELECTORS.header.root); await expect(header).toBeVisible(); // Scroll down await page.evaluate(() => window.scrollTo(0, 500)); await page.waitForTimeout(500); // Header should still be visible await expect(header).toBeVisible(); // Footer should be visible const footer = page.locator(SELECTORS.footer.root); await expect(footer).toBeVisible(); }); test("header and footer work on tablet", async ({ gotoApp, waitForAppReady, setViewport, page, }) => { await setViewport("tablet"); await gotoApp(); await waitForAppReady(); // Check header is sticky const header = page.locator(SELECTORS.header.root); await expect(header).toBeVisible(); // Scroll down await page.evaluate(() => window.scrollTo(0, 500)); await page.waitForTimeout(500); // Header should still be visible await expect(header).toBeVisible(); // Footer should be visible const footer = page.locator(SELECTORS.footer.root); await expect(footer).toBeVisible(); }); test("header and footer work on desktop", async ({ gotoApp, waitForAppReady, setViewport, page, }) => { await setViewport("desktop"); await gotoApp(); await waitForAppReady(); // Check header is sticky const header = page.locator(SELECTORS.header.root); await expect(header).toBeVisible(); // Scroll down await page.evaluate(() => window.scrollTo(0, 500)); await page.waitForTimeout(500); // Header should still be visible await expect(header).toBeVisible(); // Footer should be visible const footer = page.locator(SELECTORS.footer.root); await expect(footer).toBeVisible(); }); });