From 702a2e3b746e94c317b2e64a444a1cd4e590b2b4 Mon Sep 17 00:00:00 2001 From: Keith Solomon Date: Sat, 4 Jul 2026 20:35:46 -0500 Subject: [PATCH] test(blog): add blog-page Playwright spec --- tests/blog-page.spec.js | 100 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 tests/blog-page.spec.js diff --git a/tests/blog-page.spec.js b/tests/blog-page.spec.js new file mode 100644 index 0000000..64274f5 --- /dev/null +++ b/tests/blog-page.spec.js @@ -0,0 +1,100 @@ +import { expect, test } from "@playwright/test"; +const AxeBuilder = require("@axe-core/playwright").default; + +const blogUrl = + process.env.TEST_BLOG_URL || + "http://community-works-collaborative.test/blog/"; + +test.describe("blog page", () => { + test("desktop: Blog title, post grid, no inner-page hero, sidebar", async ({ + page, + }) => { + const pageErrors = []; + page.on("pageerror", (err) => pageErrors.push(err.message)); + + await page.setViewportSize({ width: 1280, height: 900 }); + await page.goto(blogUrl); + + // No inner-page hero. + expect(await page.locator(".page-hero").count()).toBe(0); + + // Page title is "Blog". + const heading = page.locator(".post-list__h1").first(); + await expect(heading).toBeVisible(); + await expect(heading).toHaveText("Blog"); + + // Post grid renders at least one card. + const posts = page.locator(".post-list__post"); + const postCount = await posts.count(); + expect(postCount).toBeGreaterThanOrEqual(1); + + // First card: image, title link, byline. + const firstCard = posts.first(); + await expect(firstCard.locator(".post-list__img img")).toBeVisible(); + await expect(firstCard.locator(".post-list__title")).toBeVisible(); + await expect(firstCard.locator(".post-list__byline")).toBeVisible(); + + // First card does NOT have a categories row or an excerpt. + expect(await firstCard.locator(".post-list__cats").count()).toBe(0); + expect(await firstCard.locator(".post-list__excerpt").count()).toBe(0); + + // Sidebar renders. + await expect(page.locator("#secondary, .sidebar, aside").first()).toBeAttached(); + + // No JS errors. + expect(pageErrors).toEqual([]); + }); + + test("mobile 402: single-column grid, no horizontal overflow", async ({ + page, + }) => { + await page.setViewportSize({ width: 402, height: 874 }); + await page.goto(blogUrl); + + const heading = page.locator(".post-list__h1").first(); + await expect(heading).toBeVisible(); + + const headingBox = await heading.boundingBox(); + const block = page.locator(".post-list").first(); + const blockBox = await block.boundingBox(); + + expect(headingBox).not.toBeNull(); + expect(blockBox).not.toBeNull(); + expect(headingBox.x + headingBox.width).toBeLessThanOrEqual(402 + 3); + expect(blockBox.x + blockBox.width).toBeLessThanOrEqual(402 + 3); + }); + + test("mobile 320: nothing clips horizontally", async ({ page }) => { + await page.setViewportSize({ width: 320, height: 800 }); + await page.goto(blogUrl); + + const block = page.locator(".post-list").first(); + await expect(block).toBeVisible(); + + const blockBox = await block.boundingBox(); + expect(blockBox.x + blockBox.width).toBeLessThanOrEqual(320 + 3); + }); + + test("axe: no violations", async ({ page }, testInfo) => { + await page.setViewportSize({ width: 1280, height: 900 }); + await page.goto(blogUrl); + + const results = await new AxeBuilder({ page }) + .withTags([ + "wcag2a", + "wcag2aa", + "wcag21a", + "wcag21aa", + "wcag22a", + "wcag22aa", + ]) + .analyze(); + + await testInfo.attach("accessibility-scan-results", { + body: JSON.stringify(results, null, 2), + contentType: "application/json", + }); + + expect(results.violations).toEqual([]); + }); +});