Skip to content

Commit bb4dd30

Browse files
rasesh-herekasya
authored andcommitted
Fix OWASP#1912: Added test for SecondaryCard component (OWASP#2069)
* Fix OWASP#1912: Added test for SecondaryCard component * Added newline at end of SecondaryCard.test.tsx * Fix make check --------- Co-authored-by: Kate Golovanova <[email protected]>
1 parent 3849ea6 commit bb4dd30

File tree

1 file changed

+142
-0
lines changed

1 file changed

+142
-0
lines changed
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
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(<SecondaryCard title="Title">{null}</SecondaryCard>)
92+
const cardElement = container.firstChild
93+
const titleElement = screen.getByRole('heading', { name: 'Title' })
94+
expect(titleElement).toBeInTheDocument()
95+
expect(cardElement.childNodes.length).toBe(1)
96+
})
97+
})
98+
99+
describe('Accessibility roles and labels', () => {
100+
it('renders the title within an h2 tag for proper heading structure', () => {
101+
render(<SecondaryCard title={defaultProps.title} />)
102+
const heading = screen.getByRole('heading', { level: 2, name: defaultProps.title })
103+
expect(heading).toBeInTheDocument()
104+
})
105+
})
106+
107+
describe('DOM structure / classNames / styles', () => {
108+
it('applies the base and custom classNames to the root div', () => {
109+
const { container } = render(<SecondaryCard className={defaultProps.className} />)
110+
const cardElement = container.firstChild
111+
expect(cardElement).toHaveClass(
112+
'mb-8',
113+
'rounded-lg',
114+
'bg-gray-100',
115+
'p-6',
116+
'shadow-md',
117+
'dark:bg-gray-800'
118+
)
119+
expect(cardElement).toHaveClass(defaultProps.className)
120+
})
121+
122+
it('has the correct classNames for the h2 title element', () => {
123+
render(<SecondaryCard title={defaultProps.title} />)
124+
const titleElement = screen.getByText(defaultProps.title)
125+
expect(titleElement).toHaveClass(
126+
'mb-4',
127+
'flex',
128+
'flex-row',
129+
'items-center',
130+
'gap-2',
131+
'text-2xl',
132+
'font-semibold'
133+
)
134+
})
135+
136+
it('has the correct className for the icon', () => {
137+
render(<SecondaryCard title={defaultProps.title} icon={defaultProps.icon} />)
138+
const iconElement = screen.getByRole('img', { hidden: true })
139+
expect(iconElement).toHaveClass('h-5', 'w-5')
140+
})
141+
})
142+
})

0 commit comments

Comments
 (0)