1+ /* @vitest -environment jsdom */
12/* eslint-disable @typescript-eslint/no-explicit-any */
23import { render , screen } from '@testing-library/react' ;
34import { describe , expect , it , vi } from 'vitest' ;
@@ -22,9 +23,9 @@ vi.mock('framer-motion', () => ({
2223 } ,
2324} ) ) ;
2425
25- describe ( 'ComparisonStatsCard' , ( ) => {
26- it ( 'renders correctly with title, labels and values ' , ( ) => {
27- render (
26+ describe ( 'ComparisonStatsCard responsive breakpoints ' , ( ) => {
27+ it ( 'renders the expected card structure and positive growth indicators ' , ( ) => {
28+ const { container } = render (
2829 < ComparisonStatsCard
2930 title = "Developer Score"
3031 valueA = { 85 }
@@ -40,132 +41,25 @@ describe('ComparisonStatsCard', () => {
4041 expect ( screen . getByText ( 'User Two' ) ) . toBeDefined ( ) ;
4142 expect ( screen . getByText ( '85' ) ) . toBeDefined ( ) ;
4243 expect ( screen . getByText ( '72' ) ) . toBeDefined ( ) ;
43- } ) ;
44-
45- it ( 'renders a Winner badge on User One when valueA is greater' , ( ) => {
46- render (
47- < ComparisonStatsCard
48- title = "Developer Score"
49- valueA = { 100 }
50- valueB = { 50 }
51- labelA = "User One"
52- labelB = "User Two"
53- icon = "Award"
54- />
55- ) ;
56-
57- const winnerBadges = screen . getAllByText ( 'Winner' ) ;
58- expect ( winnerBadges . length ) . toBe ( 1 ) ;
59- expect ( screen . getByText ( '100' ) . parentElement ?. innerHTML ) . toContain ( 'Winner' ) ;
60- } ) ;
61-
62- it ( 'renders a Winner badge on User Two when valueB is greater' , ( ) => {
63- render (
64- < ComparisonStatsCard
65- title = "Developer Score"
66- valueA = { 30 }
67- valueB = { 90 }
68- labelA = "User One"
69- labelB = "User Two"
70- icon = "Award"
71- />
72- ) ;
73-
74- const winnerBadges = screen . getAllByText ( 'Winner' ) ;
75- expect ( winnerBadges . length ) . toBe ( 1 ) ;
76- expect ( screen . getByText ( '90' ) . parentElement ?. innerHTML ) . toContain ( 'Winner' ) ;
77- } ) ;
78-
79- it ( 'does not render any Winner badge if values are equal' , ( ) => {
80- render (
81- < ComparisonStatsCard
82- title = "Developer Score"
83- valueA = { 50 }
84- valueB = { 50 }
85- labelA = "User One"
86- labelB = "User Two"
87- icon = "Award"
88- />
89- ) ;
44+ expect ( screen . getByText ( 'Winner' ) ) . toBeDefined ( ) ;
9045
91- expect ( screen . queryByText ( 'Winner' ) ) . toBeNull ( ) ;
92- } ) ;
93- it ( 'renders neutral fallback progress bar when both values are zero' , ( ) => {
94- const { container } = render (
95- < ComparisonStatsCard
96- title = "Developer Score"
97- valueA = { 0 }
98- valueB = { 0 }
99- labelA = "User One"
100- labelB = "User Two"
101- icon = "Award"
102- />
46+ const card = container . firstElementChild ;
47+ const header = container . querySelector ( '.flex.justify-between.items-center.mb-6' ) ;
48+ const comparisonGrid = container . querySelector (
49+ '.grid.grid-cols-2.gap-4.items-center.mb-6.relative'
10350 ) ;
104-
105- const fallbackBar = container . querySelector ( '.bg-gray-700\\/50' ) ;
106-
107- expect ( fallbackBar ) . toBeDefined ( ) ;
51+ const progressBar = container . querySelector ( '.w-full.h-2.bg-gray-100' ) ;
52+ const divider = container . querySelector ( '.hidden.md\\:block' ) ;
53+
54+ expect ( card ?. tagName ) . toBe ( 'DIV' ) ;
55+ expect ( header ?. tagName ) . toBe ( 'DIV' ) ;
56+ expect ( comparisonGrid ?. tagName ) . toBe ( 'DIV' ) ;
57+ expect ( progressBar ?. tagName ) . toBe ( 'DIV' ) ;
58+ expect ( divider ?. tagName ) . toBe ( 'DIV' ) ;
10859 } ) ;
10960
110- it ( 'renders both progress bar segments when total is greater than zero ' , ( ) => {
61+ it ( 'keeps the divider responsive and preserves the negative growth state ' , ( ) => {
11162 const { container } = render (
112- < ComparisonStatsCard
113- title = "Developer Score"
114- valueA = { 75 }
115- valueB = { 25 }
116- labelA = "User One"
117- labelB = "User Two"
118- icon = "Award"
119- />
120- ) ;
121-
122- const userOneSegment = container . querySelector ( '.bg-cyan-400' ) ;
123- const userTwoSegment = container . querySelector ( '.bg-purple-400' ) ;
124-
125- expect ( userOneSegment ) . toBeDefined ( ) ;
126- expect ( userTwoSegment ) . toBeDefined ( ) ;
127- } ) ;
128-
129- it ( 'renders a balanced 50/50 split progress bar without any emerald color highlight when values are equal' , ( ) => {
130- const { container } = render (
131- < ComparisonStatsCard
132- title = "Developer Score"
133- valueA = { 50 }
134- valueB = { 50 }
135- labelA = "User One"
136- labelB = "User Two"
137- icon = "Award"
138- />
139- ) ;
140-
141- const emeraldElement =
142- container . querySelector ( '[className*="emerald"]' ) ||
143- container . querySelector ( '.text-emerald-400' ) ;
144-
145- expect ( emeraldElement ) . toBeNull ( ) ;
146- expect ( screen . queryByText ( 'Winner' ) ) . toBeNull ( ) ;
147- } ) ;
148- } ) ;
149-
150- describe ( 'ComparisonStatsCard responsive rendering and growth trends (Variation 3)' , ( ) => {
151- it ( 'renders positive growth trend with winner badge for higher value' , ( ) => {
152- render (
153- < ComparisonStatsCard
154- title = "Streak"
155- valueA = { 120 }
156- valueB = { 40 }
157- labelA = "Alice"
158- labelB = "Bob"
159- icon = "Flame"
160- />
161- ) ;
162- expect ( screen . getByText ( 'Winner' ) ) . toBeDefined ( ) ;
163- expect ( screen . getByText ( '120' ) ) . toBeDefined ( ) ;
164- expect ( screen . getByText ( '40' ) ) . toBeDefined ( ) ;
165- } ) ;
166-
167- it ( 'renders negative growth indicator — no winner badge for lower value' , ( ) => {
168- render (
16963 < ComparisonStatsCard
17064 title = "Streak"
17165 valueA = { 20 }
@@ -175,29 +69,26 @@ describe('ComparisonStatsCard responsive rendering and growth trends (Variation
17569 icon = "Flame"
17670 />
17771 ) ;
178- const winners = screen . getAllByText ( 'Winner' ) ;
179- expect ( winners . length ) . toBe ( 1 ) ;
180- expect ( screen . getByText ( '20' ) . className ) . not . toMatch ( / e m e r a l d / ) ;
181- } ) ;
18272
183- it ( 'renders title and icon correctly' , ( ) => {
184- render (
185- < ComparisonStatsCard
186- title = "Pull Requests"
187- valueA = { 10 }
188- valueB = { 5 }
189- labelA = "Dev A"
190- labelB = "Dev B"
191- icon = "GitBranch"
192- />
193- ) ;
194- expect ( screen . getByText ( / P u l l R e q u e s t s / i) ) . toBeDefined ( ) ;
195- expect ( screen . getByText ( 'Dev A' ) ) . toBeDefined ( ) ;
196- expect ( screen . getByText ( 'Dev B' ) ) . toBeDefined ( ) ;
73+ const divider = container . querySelector ( '.hidden.md\\:block' ) ;
74+ const winnerBadges = screen . getAllByText ( 'Winner' ) ;
75+
76+ expect ( divider ) . toBeDefined ( ) ;
77+ expect ( winnerBadges . length ) . toBe ( 1 ) ;
78+ expect ( screen . getByText ( 'Alice' ) ) . toBeDefined ( ) ;
79+ expect ( screen . getByText ( 'Bob' ) ) . toBeDefined ( ) ;
80+ expect ( screen . getByText ( '20' ) ) . toBeDefined ( ) ;
81+ expect ( screen . getByText ( '80' ) ) . toBeDefined ( ) ;
82+ expect ( screen . getByTitle ( 'Alice' ) ) . toBeDefined ( ) ;
83+ expect ( screen . getByTitle ( 'Bob' ) ) . toBeDefined ( ) ;
84+
85+ const winnerText = winnerBadges [ 0 ] . textContent ;
86+ expect ( winnerText ) . toBe ( 'Winner' ) ;
87+ expect ( screen . getByText ( '20' ) . className ) . not . toMatch ( / e m e r a l d / ) ;
19788 } ) ;
19889
199- it ( 'renders zero values without crashing ' , ( ) => {
200- render (
90+ it ( 'renders a neutral fallback progress bar when both values are zero ' , ( ) => {
91+ const { container } = render (
20192 < ComparisonStatsCard
20293 title = "Commits"
20394 valueA = { 0 }
@@ -207,21 +98,12 @@ describe('ComparisonStatsCard responsive rendering and growth trends (Variation
20798 icon = "GitCommit"
20899 />
209100 ) ;
210- expect ( screen . queryByText ( 'Winner' ) ) . toBeNull ( ) ;
211- } ) ;
212101
213- it ( 'renders large values correctly' , ( ) => {
214- render (
215- < ComparisonStatsCard
216- title = "Total Contributions"
217- valueA = { 9999 }
218- valueB = { 1 }
219- labelA = "Alice"
220- labelB = "Bob"
221- icon = "TrendingUp"
222- />
223- ) ;
224- expect ( screen . getByText ( '9999' ) ) . toBeDefined ( ) ;
225- expect ( screen . getByText ( 'Winner' ) ) . toBeDefined ( ) ;
102+ const progressBar = container . querySelector ( '.w-full.h-2.bg-gray-100' ) ;
103+ const fallbackBar = container . querySelector ( '.w-full.h-full.bg-zinc-300' ) ;
104+
105+ expect ( progressBar ?. tagName ) . toBe ( 'DIV' ) ;
106+ expect ( fallbackBar ?. tagName ) . toBe ( 'DIV' ) ;
107+ expect ( screen . queryByText ( 'Winner' ) ) . toBeNull ( ) ;
226108 } ) ;
227109} ) ;
0 commit comments