@@ -2,6 +2,7 @@ import { render, screen, fireEvent } from '@testing-library/react';
22import '@testing-library/jest-dom/vitest' ;
33import { describe , expect , it , vi , beforeEach } from 'vitest' ;
44import { FeatureCard , FeatureCardsSection } from './FeatureCards' ;
5+ import gsap from 'gsap' ;
56
67// Mock GSAP
78const mockTimeline = {
@@ -74,24 +75,80 @@ describe('FeatureCards Component Suite', () => {
7475 // The bottom accent line has class "absolute bottom-0 left-0"
7576 const accentLine = container . querySelector ( '.absolute.bottom-0.left-0' ) as HTMLElement ;
7677 expect ( accentLine ) . toBeInTheDocument ( ) ;
77- expect ( accentLine . style . background ) . toMatch ( / r g b \ (1 6 , 1 8 5 , 1 2 9 \) | # 1 0 b 9 8 1 / ) ;
78+ expect ( accentLine . style . background ) . toContain ( ' rgb(16, 185, 129)' ) ;
7879 } ) ;
7980
80- it ( 'triggers mouse movement and hover hover -effects to activate magnetic spotlight' , ( ) => {
81+ it ( 'triggers mouse movement and hover-effects to activate magnetic spotlight' , ( ) => {
8182 const { container } = render ( < FeatureCard { ...defaultProps } /> ) ;
8283 const card = container . firstChild as HTMLDivElement ;
8384
8485 // Mouse enter triggers hover state
8586 fireEvent . mouseEnter ( card ) ;
87+ expect ( gsap . to ) . toHaveBeenCalled ( ) ;
88+
89+ vi . clearAllMocks ( ) ;
8690
8791 // Mouse move triggers magnetic movement recalculations
8892 fireEvent . mouseMove ( card , { clientX : 100 , clientY : 100 } ) ;
93+ expect ( gsap . to ) . toHaveBeenCalled ( ) ;
94+
95+ vi . clearAllMocks ( ) ;
8996
9097 // Mouse leave resets magnetic coordinates
9198 fireEvent . mouseLeave ( card ) ;
99+ expect ( gsap . to ) . toHaveBeenCalled ( ) ;
92100 } ) ;
93101 } ) ;
94102
103+ it ( 'renders all 3 feature cards matching the defined list length' , ( ) => {
104+ render (
105+ < FeatureCardsSection >
106+ < FeatureCard
107+ icon = { < span > ⚡</ span > }
108+ accent = "text-white"
109+ accentColor = "#10b981"
110+ index = { 0 }
111+ title = "Real-time Sync"
112+ desc = "Pulled directly from GitHub GraphQL API. Your streak updates as fast as your code pushes."
113+ />
114+ < FeatureCard
115+ icon = { < span > 📋</ span > }
116+ accent = "text-white"
117+ accentColor = "#8b5cf6"
118+ index = { 1 }
119+ title = "Theme Engine"
120+ desc = "Switch between Neon, Dracula, or custom HEX modes via simple URL management."
121+ />
122+ < FeatureCard
123+ icon = { < span > 📦</ span > }
124+ accent = "text-white"
125+ accentColor = "#06b6d4"
126+ index = { 2 }
127+ title = "Isometric Math"
128+ desc = "Sophisticated 3D projection formulas turn 2D data into digital architecture."
129+ />
130+ </ FeatureCardsSection >
131+ ) ;
132+
133+ const headings = screen . getAllByRole ( 'heading' , { level : 3 } ) ;
134+ expect ( headings ) . toHaveLength ( 3 ) ;
135+
136+ expect ( screen . getByText ( 'Real-time Sync' ) ) . toBeInTheDocument ( ) ;
137+ expect ( screen . getByText ( 'Theme Engine' ) ) . toBeInTheDocument ( ) ;
138+ expect ( screen . getByText ( 'Isometric Math' ) ) . toBeInTheDocument ( ) ;
139+ } ) ;
140+
141+ it ( 'applies responsive grid layout classes to the card grid' , ( ) => {
142+ const { container } = render (
143+ < FeatureCardsSection >
144+ < div />
145+ </ FeatureCardsSection >
146+ ) ;
147+ const grid = container . querySelector ( '.grid' ) ;
148+ expect ( grid ) . toHaveClass ( 'md:grid-cols-3' ) ;
149+ expect ( grid ) . toHaveClass ( 'gap-6' ) ;
150+ } ) ;
151+
95152 describe ( 'FeatureCardsSection Wrapper Component' , ( ) => {
96153 it ( 'renders children components and Why CommitPulse heading correctly' , ( ) => {
97154 render (
0 commit comments