1+ import { faUser } from '@fortawesome/free-solid-svg-icons' ;
2+ import { render , screen } from '@testing-library/react' ;
3+ import SecondaryCard from 'components/SecondaryCard' ;
4+
5+ describe ( 'SecondaryCard Component' , ( ) => {
6+ const defaultProps = {
7+ title : 'Test Title' ,
8+ icon : faUser ,
9+ children : < p > Test children</ p > ,
10+ className : 'custom-class' ,
11+ } ;
12+
13+ describe ( 'Renders successfully with minimal required props' , ( ) => {
14+ it ( 'renders successfully with only a title' , ( ) => {
15+ render ( < SecondaryCard title = { defaultProps . title } /> ) ;
16+ expect ( screen . getByText ( defaultProps . title ) ) . toBeInTheDocument ( ) ;
17+ } ) ;
18+
19+ it ( 'renders successfully with only children' , ( ) => {
20+ render ( < SecondaryCard > { defaultProps . children } </ SecondaryCard > ) ;
21+ expect ( screen . getByText ( 'Test children' ) ) . toBeInTheDocument ( ) ;
22+ } ) ;
23+
24+ it ( 'renders successfully with no props at all' , ( ) => {
25+ const { container } = render ( < SecondaryCard /> ) ;
26+ expect ( container . querySelector ( '.mb-8' ) ) . toBeInTheDocument ( ) ;
27+ } ) ;
28+ } ) ;
29+
30+ describe ( 'Conditional rendering logic' , ( ) => {
31+ it ( 'does not render the h2 title element when title prop is not provided' , ( ) => {
32+ render ( < SecondaryCard /> ) ;
33+ const titleElement = screen . queryByRole ( 'heading' ) ;
34+ expect ( titleElement ) . not . toBeInTheDocument ( ) ;
35+ } ) ;
36+
37+ it ( 'renders the h2 title element when title prop is provided' , ( ) => {
38+ render ( < SecondaryCard title = { defaultProps . title } /> ) ;
39+ const titleElement = screen . getByRole ( 'heading' , { name : 'Test Title' } ) ;
40+ expect ( titleElement ) . toBeInTheDocument ( ) ;
41+ } ) ;
42+
43+ it ( 'does not render the icon when icon prop is not provided' , ( ) => {
44+ const { container } = render ( < SecondaryCard title = { defaultProps . title } /> ) ;
45+ const iconElement = container . querySelector ( 'svg' ) ;
46+ expect ( iconElement ) . not . toBeInTheDocument ( ) ;
47+ } ) ;
48+ } ) ;
49+
50+ describe ( 'Prop-based behavior - different props affect output' , ( ) => {
51+ it ( 'renders a title and an icon when both are provided' , ( ) => {
52+ render ( < SecondaryCard title = { defaultProps . title } icon = { defaultProps . icon } /> ) ;
53+ expect ( screen . getByText ( defaultProps . title ) ) . toBeInTheDocument ( ) ;
54+ expect ( screen . getByRole ( 'img' , { hidden : true } ) ) . toBeInTheDocument ( ) ;
55+ } ) ;
56+
57+ it ( 'renders children content correctly' , ( ) => {
58+ render ( < SecondaryCard > { defaultProps . children } </ SecondaryCard > ) ;
59+ expect ( screen . getByText ( 'Test children' ) ) . toBeInTheDocument ( ) ;
60+ } ) ;
61+ } ) ;
62+
63+ describe ( 'Text and content rendering' , ( ) => {
64+ it ( 'displays the correct text for the title' , ( ) => {
65+ const customTitle = 'My Custom Title' ;
66+ render ( < SecondaryCard title = { customTitle } /> ) ;
67+ expect ( screen . getByText ( customTitle ) ) . toBeInTheDocument ( ) ;
68+ } ) ;
69+
70+ it ( 'renders complex children nodes' , ( ) => {
71+ const complexChildren = (
72+ < div >
73+ < span > Nested Content</ span >
74+ < button > Click Me</ button >
75+ </ div >
76+ ) ;
77+ render ( < SecondaryCard > { complexChildren } </ SecondaryCard > ) ;
78+ expect ( screen . getByText ( 'Nested Content' ) ) . toBeInTheDocument ( ) ;
79+ expect ( screen . getByRole ( 'button' , { name : 'Click Me' } ) ) . toBeInTheDocument ( ) ;
80+ } ) ;
81+ } ) ;
82+
83+ describe ( 'Handles edge cases and invalid inputs' , ( ) => {
84+ it ( 'handles an empty string for the title prop by not rendering the title element' , ( ) => {
85+ render ( < SecondaryCard title = "" /> ) ;
86+ const titleElement = screen . queryByRole ( 'heading' ) ;
87+ expect ( titleElement ) . not . toBeInTheDocument ( ) ;
88+ } ) ;
89+
90+ it ( 'handles null children gracefully by rendering nothing for the children' , ( ) => {
91+ const { container } = render (
92+ < SecondaryCard title = "Title" > { null } </ SecondaryCard >
93+ ) ;
94+ const cardElement = container . firstChild ;
95+ const titleElement = screen . getByRole ( 'heading' , { name : 'Title' } ) ;
96+ expect ( titleElement ) . toBeInTheDocument ( ) ;
97+ expect ( cardElement . childNodes . length ) . toBe ( 1 ) ;
98+ } ) ;
99+ } ) ;
100+
101+ describe ( 'Accessibility roles and labels' , ( ) => {
102+ it ( 'renders the title within an h2 tag for proper heading structure' , ( ) => {
103+ render ( < SecondaryCard title = { defaultProps . title } /> ) ;
104+ const heading = screen . getByRole ( 'heading' , { level : 2 , name : defaultProps . title } ) ;
105+ expect ( heading ) . toBeInTheDocument ( ) ;
106+ } ) ;
107+ } ) ;
108+
109+ describe ( 'DOM structure / classNames / styles' , ( ) => {
110+ it ( 'applies the base and custom classNames to the root div' , ( ) => {
111+ const { container } = render ( < SecondaryCard className = { defaultProps . className } /> ) ;
112+ const cardElement = container . firstChild ;
113+ expect ( cardElement ) . toHaveClass ( 'mb-8' , 'rounded-lg' , 'bg-gray-100' , 'p-6' , 'shadow-md' , 'dark:bg-gray-800' ) ;
114+ expect ( cardElement ) . toHaveClass ( defaultProps . className ) ;
115+ } ) ;
116+
117+ it ( 'has the correct classNames for the h2 title element' , ( ) => {
118+ render ( < SecondaryCard title = { defaultProps . title } /> ) ;
119+ const titleElement = screen . getByText ( defaultProps . title ) ;
120+ expect ( titleElement ) . toHaveClass ( 'mb-4' , 'flex' , 'flex-row' , 'items-center' , 'gap-2' , 'text-2xl' , 'font-semibold' ) ;
121+ } ) ;
122+
123+ it ( 'has the correct className for the icon' , ( ) => {
124+ render ( < SecondaryCard title = { defaultProps . title } icon = { defaultProps . icon } /> ) ;
125+ const iconElement = screen . getByRole ( 'img' , { hidden : true } ) ;
126+ expect ( iconElement ) . toHaveClass ( 'h-5' , 'w-5' ) ;
127+ } ) ;
128+ } ) ;
129+ } ) ;
0 commit comments