diff --git a/app/components/HeroSection.accessibility.test.tsx b/app/components/HeroSection.accessibility.test.tsx new file mode 100644 index 000000000..7acd3adbd --- /dev/null +++ b/app/components/HeroSection.accessibility.test.tsx @@ -0,0 +1,58 @@ +import { render, screen } from '@testing-library/react'; +import '@testing-library/jest-dom/vitest'; +import { describe, it, expect, vi } from 'vitest'; +import { HeroSection } from './HeroSection'; + +type MockMotionProps = { + children?: React.ReactNode; + className?: string; + [key: string]: unknown; +}; + +vi.mock('framer-motion', () => ({ + motion: { + div: ({ children, ...props }: MockMotionProps) =>
{children}
, + p: ({ children, ...props }: MockMotionProps) =>

{children}

, + }, +})); + +describe('HeroSection — Accessibility & Screen Reader Compliance', () => { + it('renders primary h1 heading with correct text for screen reader hierarchy', () => { + render(); + + const heading = screen.getByRole('heading', { level: 1 }); + expect(heading).toBeInTheDocument(); + expect(heading).toHaveTextContent('Elevate Your Contribution Story.'); + }); + + it('renders search landmark with descriptive aria-label for the input form', () => { + render(); + + const searchRegion = screen.getByRole('search', { + name: 'Generate your GitHub streak badge', + }); + expect(searchRegion).toBeInTheDocument(); + }); + + it('renders username input with aria-label for screen reader announcement', () => { + render(); + + const input = screen.getByRole('textbox', { name: 'GitHub username' }); + expect(input).toBeInTheDocument(); + }); + + it('renders both buttons with meaningful visible text for screen readers', () => { + render(); + + expect(screen.getByRole('button', { name: /copy link/i })).toBeInTheDocument(); + + expect(screen.getByRole('button', { name: /watch dashboard/i })).toBeInTheDocument(); + }); + + it('hides decorative background elements from screen readers via aria-hidden', () => { + const { container } = render(); + + const hiddenElements = container.querySelectorAll('[aria-hidden="true"]'); + expect(hiddenElements.length).toBeGreaterThanOrEqual(2); + }); +}); diff --git a/app/components/HeroSection.tsx b/app/components/HeroSection.tsx index e735a2982..725affb0b 100644 --- a/app/components/HeroSection.tsx +++ b/app/components/HeroSection.tsx @@ -5,12 +5,25 @@ import { Copy } from 'lucide-react'; export function HeroSection() { return ( -
-
+
+