# Testing Strategy for CommunityRule ## Overview This document outlines our comprehensive testing strategy that properly separates unit testing from responsive behavior testing, following best practices for JSDOM limitations and real browser testing. ## Current Test Status - **184 total tests** across the project - **176 tests passing** (95.7% success rate) - **8 tests failing** (all related to multiple element instances) - **13 test files** covering all major components ## Testing Philosophy ### The Problem with JSDOM and Responsive Testing **Short take: Unit tests in JSDOM can't truly "switch breakpoints."** JSDOM doesn't evaluate CSS media queries, so Tailwind's `hidden sm:block …` won't change visibility when you "resize" the window. ### Solution: Proper Test Separation - **Unit / component tests (Vitest + RTL):** assert **structure and classes**, not responsive visibility. - **Responsive behavior:** verify with **browser-based tests** (Playwright) or **visual tests** (Chromatic/Storybook) at real viewport widths. ## Test Categories ### 1. Unit Tests (Vitest + React Testing Library) **Purpose:** Test component structure, accessibility, and configuration data. **What to test:** - DOM roles/labels exist: `role="banner"`, nav landmark, menu items - The right **Tailwind classes** are present on wrappers (`block sm:hidden`, `hidden md:block`, etc.) - Data-driven bits produce the expected count/order (e.g., `navigationItems`, `avatarImages`, `logoConfig`) - Component configuration and exported data structures **Example:** ```javascript // tests/unit/Header.structure.test.js test("logo wrappers include breakpoint classes", () => { render(
); const logoWrappers = screen.getAllByTestId("logo-wrapper"); // Check first logo variant (xs only) expect(logoWrappers[0]).toHaveClass("block", "sm:hidden"); // Check second logo variant (sm only) expect(logoWrappers[1]).toHaveClass("hidden", "sm:block", "md:hidden"); }); ``` ### 2. Browser-Based Tests (Playwright) **Purpose:** Test real responsive behavior at actual viewport widths. **What to test:** - **Visibility** at real breakpoints - **Layout changes** between breakpoints - **Interactive behavior** at different screen sizes - **Accessibility** across viewports **Example:** ```javascript // tests/e2e/header.responsive.spec.js const breakpoints = [ { name: "xs", width: 360, height: 700 }, { name: "sm", width: 640, height: 700 }, { name: "md", width: 768, height: 700 }, { name: "lg", width: 1024, height: 700 }, { name: "xl", width: 1280, height: 700 }, ]; for (const bp of breakpoints) { test(`header layout at ${bp.name}`, async ({ page }) => { await page.setViewportSize({ width: bp.width, height: bp.height }); await page.goto("/"); const nav = page.getByRole("navigation", { name: /main navigation/i }); await expect(nav).toBeVisible(); }); } ``` ### 3. Visual Tests (Storybook + Chromatic) **Purpose:** Visual regression testing and design system validation. **What to test:** - **Visual diffs** per breakpoint - **Design consistency** across viewports - **Component variations** and states **Example:** ```javascript // stories/Header.responsive.stories.js export default { parameters: { chromatic: { viewports: [360, 640, 768, 1024, 1280], delay: 100, }, }, }; ``` ## Component Improvements ### Header Component Enhancements 1. **Added Test IDs** for easier testing: ```jsx
{renderLogo(config.size, config.showText)}
``` 2. **Exported Configuration** for testing: ```javascript export const navigationItems = [...]; export const avatarImages = [...]; export const logoConfig = [...]; ``` 3. **Structured Breakpoint Containers**: ```jsx
``` ## Test File Structure ``` tests/ ├── unit/ # Unit tests (Vitest + RTL) │ ├── Header.test.jsx # CONSOLIDATED: Comprehensive Header tests │ ├── Footer.test.jsx │ ├── Layout.test.jsx │ └── Page.test.jsx ├── integration/ # Integration tests │ └── ContentLockup.integration.test.jsx ├── e2e/ # Browser tests (Playwright) │ └── header.responsive.spec.js # NEW: Responsive behavior tests └── stories/ # Storybook stories └── Header.responsive.stories.js # NEW: Visual testing ``` ## Best Practices ### Unit Testing (JSDOM) 1. **Test structure, not visibility**: ```javascript // ✅ Good: Test classes exist expect(element).toHaveClass("block", "sm:hidden"); // ❌ Bad: Test visibility (doesn't work in JSDOM) expect(element).toBeVisible(); ``` 2. **Use test IDs for containers**: ```javascript // ✅ Good: Test specific containers const logoWrapper = screen.getByTestId("logo-wrapper"); // ❌ Bad: Query by complex class strings const logoWrapper = document.querySelector(".block.sm\\:hidden"); ``` 3. **Test configuration data**: ```javascript // ✅ Good: Test exported configuration expect(navigationItems).toHaveLength(3); expect(logoConfig).toHaveLength(5); ``` ### Browser Testing (Playwright) 1. **Test real viewport sizes**: ```javascript await page.setViewportSize({ width: 640, height: 700 }); ``` 2. **Test visibility at breakpoints**: ```javascript if (bp.name === "xs") { await expect(page.getByTestId("auth-xs")).toBeVisible(); } ``` 3. **Test accessibility across viewports**: ```javascript const interactiveElements = [ page.getByRole("link", { name: /use cases/i }), page.getByRole("button", { name: /create rule/i }), ]; for (const element of interactiveElements) { await expect(element).toBeVisible(); await expect(element).toBeEnabled(); } ``` ## Running Tests ### Unit Tests ```bash npm test # Run all unit tests npm test tests/unit/ # Run only unit tests npm test Header.structure # Run specific test file ``` ### Browser Tests ```bash npx playwright test # Run all browser tests npx playwright test header.responsive.spec.js # Run specific test ``` ### Visual Tests ```bash npm run storybook # Start Storybook npx chromatic --project-token=xxx # Run visual tests ``` ## Future Improvements 1. **Add more Playwright tests** for other components 2. **Set up Chromatic** for visual regression testing 3. **Add performance tests** for responsive behavior 4. **Create component-specific test utilities** 5. **Add accessibility testing** with axe-core ## Key Takeaways 1. **JSDOM limitations** require separating structure tests from visibility tests 2. **Test IDs** make testing more reliable and maintainable 3. **Exported configuration** enables better data structure testing 4. **Real browser testing** is essential for responsive behavior 5. **Visual testing** catches design regressions across breakpoints This strategy provides comprehensive coverage while respecting the limitations of different testing environments.