Skip to content

Commit b163cec

Browse files
committed
chore: update component tests for improved accuracy and consistency
1 parent 1b374ef commit b163cec

8 files changed

Lines changed: 137 additions & 83 deletions

File tree

packages/lib/src/components/Contact/Contact.test.tsx

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -60,17 +60,8 @@ describe('Contact', () => {
6060
})
6161

6262
it('renders Contact component with correct layout', () => {
63-
const grid = screen.getByRole('grid')
64-
expect(grid).toBeDefined()
65-
66-
const gridCols = within(grid).getAllByRole('gridcell')
67-
expect(gridCols).toHaveLength(2)
68-
69-
const contactPersonCard = within(gridCols[0])
70-
expect(contactPersonCard).toBeDefined()
71-
72-
const contactForm = within(gridCols[1])
73-
expect(contactForm).toBeDefined()
63+
expect(screen.getByRole('complementary')).toBeDefined()
64+
expect(screen.getByRole('form')).toBeDefined()
7465
})
7566

7667
describe('ContactPersonCard', () => {
@@ -87,15 +78,18 @@ describe('Contact', () => {
8778
const name = within(card).getByRole('heading', { level: 5 })
8879
expect(name).toBeDefined()
8980

81+
const phone = within(card).getByLabelText(
82+
'contactView.contactPersonCard.contactPerson.ariaLabel',
83+
)
84+
9085
const information = within(card).getAllByLabelText('Contact info')
91-
expect(information).toHaveLength(4)
86+
expect(information).toHaveLength(3)
9287

93-
const phone = information[0]
94-
const mail = information[1]
95-
const location = information[2]
96-
const socialIcons = information[3]
88+
const mail = information[0]
89+
const location = information[1]
90+
const socialIcons = information[2]
9791

98-
expect(within(phone).getByText(/1(123) 456-7890/)).toBeDefined()
92+
expect(within(phone).getByText('1(123) 456-7890')).toBeDefined()
9993
expect(within(mail).getByText(/jane.doe@example.com/)).toBeDefined()
10094
expect(
10195
within(location).getByText(/123 Maple Street. Anytown, PA 17101/),
@@ -114,12 +108,6 @@ describe('Contact', () => {
114108
const title = within(form).getByRole('heading', { level: 3 })
115109
expect(title).toBeDefined()
116110

117-
const emailInput = within(form).getByLabelText(/email/i)
118-
expect(emailInput).toBeDefined()
119-
120-
const nameInput = within(form).getByLabelText(/name/i)
121-
expect(nameInput).toBeDefined()
122-
123111
const subjectInput = within(form).getByLabelText(/subject/i)
124112
expect(subjectInput).toBeDefined()
125113

packages/lib/src/components/FeedbackWidget/FeedbackWidget.test.tsx

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,13 @@
1818
*/
1919

2020
import { AppShell, MantineProvider } from '@mantine/core'
21-
import { fireEvent, render, screen } from '@testing-library/react'
22-
import { beforeAll, describe, expect, it, vi } from 'vitest'
21+
import {
22+
cleanup,
23+
fireEvent,
24+
render,
25+
screen,
26+
} from '@testing-library/react'
27+
import { afterEach, beforeAll, describe, expect, it, vi } from 'vitest'
2328

2429
import { FeedbackWidget } from './FeedbackWidget'
2530

@@ -37,6 +42,24 @@ vi.mock('@mantine/core', async () => {
3742
}
3843
})
3944

45+
vi.mock('@mantine/hooks', async () => {
46+
const mantineHooks = (await vi.importActual('@mantine/hooks')) as Record<
47+
string,
48+
unknown
49+
>
50+
51+
return {
52+
...mantineHooks,
53+
useDisclosure: () => [
54+
true,
55+
{
56+
toggle: vi.fn(),
57+
close: vi.fn(),
58+
},
59+
],
60+
}
61+
})
62+
4063
const mockedProps = {
4164
spyFunctions: {
4265
createFeedback: vi.fn(),
@@ -74,6 +97,10 @@ const mockedProps = {
7497
}
7598

7699
describe('FeedbackWidget', () => {
100+
afterEach(() => {
101+
cleanup()
102+
})
103+
77104
beforeAll(() => {
78105
vi.mock('next/router', () => ({
79106
useRouter: () => ({
@@ -106,18 +133,25 @@ describe('FeedbackWidget', () => {
106133

107134
fireEvent.click(openButton)
108135

109-
expect(screen.getByText('feedbackWidget.title')).toBeDefined()
110-
111136
expect(
112-
screen.getAllByRole('button', { name: 'feedbackWidget.issue' })[0],
137+
screen.getAllByRole('button', {
138+
name: 'feedbackWidget.issue',
139+
hidden: true,
140+
})[0],
113141
).toBeDefined()
114142

115143
expect(
116-
screen.getAllByRole('button', { name: 'feedbackWidget.idea' })[0],
144+
screen.getAllByRole('button', {
145+
name: 'feedbackWidget.idea',
146+
hidden: true,
147+
})[0],
117148
).toBeDefined()
118149

119150
expect(
120-
screen.getAllByRole('button', { name: 'feedbackWidget.other' })[0],
151+
screen.getAllByRole('button', {
152+
name: 'feedbackWidget.other',
153+
hidden: true,
154+
})[0],
121155
).toBeDefined()
122156

123157
component.unmount()
@@ -148,8 +182,9 @@ describe('FeedbackWidget', () => {
148182
fireEvent.click(openButton)
149183

150184
const issueButton = screen.getAllByRole('button', {
151-
name: '',
152-
})[1]
185+
name: 'feedbackWidget.issue',
186+
hidden: true,
187+
})[0]
153188

154189
fireEvent.click(issueButton)
155190

@@ -203,8 +238,9 @@ describe('FeedbackWidget', () => {
203238
fireEvent.click(openButton)
204239

205240
const issueButton = screen.getAllByRole('button', {
206-
name: '',
207-
})[1]
241+
name: 'feedbackWidget.issue',
242+
hidden: true,
243+
})[0]
208244

209245
fireEvent.click(issueButton)
210246

@@ -240,8 +276,9 @@ describe('FeedbackWidget', () => {
240276
fireEvent.click(openButton)
241277

242278
const issueButton = screen.getAllByRole('button', {
243-
name: '',
244-
})[1]
279+
name: 'feedbackWidget.issue',
280+
hidden: true,
281+
})[0]
245282

246283
fireEvent.click(issueButton)
247284

packages/lib/src/components/Header/Header.test.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,11 @@ describe('Header.tsx', () => {
8080
})
8181

8282
it('should render the spotlight search bar', () => {
83-
expect(HeaderMounted.getByRole('searchbox')).toBeDefined()
83+
expect(
84+
HeaderMounted.getByRole('button', {
85+
name: 'header.spotlight.placeholder',
86+
}),
87+
).toBeDefined()
8488
})
8589

8690
it('should render the theme selector', () => {

packages/lib/src/components/Home/Home.test.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import { AppShell, MantineProvider } from '@mantine/core'
2121
import * as MantineSpotlight from '@mantine/spotlight'
2222
import { fireEvent, render, screen } from '@testing-library/react'
23-
import mockRouter from 'next-router-mock'
2423
import { beforeAll, describe, expect, it, vi } from 'vitest'
2524

2625
import { Home } from './Home'
@@ -53,11 +52,13 @@ vi.mock('@mantine/spotlight', async () => {
5352
})
5453

5554
describe('Home', () => {
55+
const onClickButton = vi.fn()
56+
5657
beforeAll(() => {
5758
render(
5859
<MantineProvider>
5960
<AppShell>
60-
<Home onClickButton={() => {}} showUsersPageButton />
61+
<Home onClickButton={onClickButton} showUsersPageButton />
6162
</AppShell>
6263
</MantineProvider>,
6364
)
@@ -82,13 +83,13 @@ describe('Home', () => {
8283
expect(openSpotlightSpy).toHaveBeenCalledOnce()
8384
})
8485

85-
it('should navigate to corresponding routes', () => {
86+
it('should call onClickButton with corresponding routes', () => {
8687
const usersButton = screen.getByText('homeView.action.users')
8788
fireEvent.click(usersButton)
88-
expect(mockRouter.pathname).toEqual('/admin/users')
89+
expect(onClickButton).toHaveBeenCalledWith('/admin/users')
8990

9091
const profileButton = screen.getByText('homeView.action.profile')
9192
fireEvent.click(profileButton)
92-
expect(mockRouter.pathname).toEqual('/profile')
93+
expect(onClickButton).toHaveBeenCalledWith('/profile')
9394
})
9495
})

packages/lib/src/components/NavBar/NavBar.test.tsx

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,36 @@ import {
2626
IconUsers,
2727
IconUserStar,
2828
} from '@tabler/icons-react'
29-
import { fireEvent, render, screen } from '@testing-library/react'
29+
import { cleanup, fireEvent, render, screen } from '@testing-library/react'
3030
import { type JSX, ReactNode } from 'react'
31-
import { beforeAll, describe, expect, it, vi } from 'vitest'
31+
import { afterEach, beforeAll, describe, expect, it, vi } from 'vitest'
3232

3333
import { NavBar } from './NavBar'
3434

3535
const BASE_PATH = 'http://localhost:3000'
3636

37+
vi.mock('react-i18next', async () => {
38+
const reactI18next = (await vi.importActual('react-i18next')) as Record<
39+
string,
40+
unknown
41+
>
42+
43+
return {
44+
...reactI18next,
45+
getI18n: () => ({ language: 'en' }),
46+
}
47+
})
48+
49+
vi.mock('next/navigation', () => ({
50+
usePathname: () => '/en/admin/users',
51+
}))
52+
3753
describe('NavBar', () => {
54+
afterEach(() => {
55+
cleanup()
56+
vi.clearAllMocks()
57+
})
58+
3859
const NAV_LINKS: NavLink[] = [
3960
{
4061
icon: <IconHome />,
@@ -150,19 +171,19 @@ describe('NavBar', () => {
150171

151172
expect(
152173
screen.getByText('navigation.users.label').closest('a'),
153-
).toHaveProperty('href', `${BASE_PATH}/admin/users`)
174+
).toHaveProperty('href', `${BASE_PATH}/users`)
154175

155176
expect(
156177
screen.getByText('navigation.roles.label').closest('a'),
157-
).toHaveProperty('href', `${BASE_PATH}/admin/roles`)
178+
).toHaveProperty('href', `${BASE_PATH}/roles`)
158179

159180
expect(
160181
screen.getByText('navigation.rights.label').closest('a'),
161-
).toHaveProperty('href', `${BASE_PATH}/admin/rights`)
182+
).toHaveProperty('href', `${BASE_PATH}/rights`)
162183

163184
expect(
164185
screen.getByText('navigation.translations.label').closest('a'),
165-
).toHaveProperty('href', `${BASE_PATH}/admin/translations`)
186+
).toHaveProperty('href', `${BASE_PATH}/translations`)
166187

167188
renderedComponent.unmount()
168189
})
@@ -178,15 +199,15 @@ describe('NavBar', () => {
178199

179200
expect(
180201
screen.getByText('navigation.users.label').closest('a'),
181-
).toHaveProperty('href', `${BASE_PATH}/admin/users`)
202+
).toHaveProperty('href', `${BASE_PATH}/users`)
182203

183204
expect(
184205
screen.getByText('navigation.roles.label').closest('a'),
185-
).toHaveProperty('href', `${BASE_PATH}/admin/roles`)
206+
).toHaveProperty('href', `${BASE_PATH}/roles`)
186207

187208
expect(
188209
screen.getByText('navigation.rights.label').closest('a'),
189-
).toHaveProperty('href', `${BASE_PATH}/admin/rights`)
210+
).toHaveProperty('href', `${BASE_PATH}/rights`)
190211

191212
expect(screen.queryByText('navigation.translations.label')).toBeNull()
192213

packages/lib/src/components/Notification/HttpNotification.test.tsx

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
* along with Essencium Frontend. If not, see <http://www.gnu.org/licenses/>.
1818
*/
1919

20+
import { MantineProvider } from '@mantine/core'
2021
import { render, RenderResult, screen } from '@testing-library/react'
21-
import ReactDOM from 'react-dom'
2222
import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
2323

2424
import { HttpNotification } from './HttpNotification'
@@ -27,14 +27,9 @@ describe('HttpNotification', () => {
2727
let mountedHttpNotificaton: RenderResult
2828

2929
beforeAll(() => {
30-
vi.mock('react-dom', async (): Promise<Awaited<typeof ReactDOM>> => {
31-
const actual = await vi.importActual<typeof ReactDOM>('react-dom')
32-
33-
return {
34-
...actual,
35-
createPortal: vi.fn().mockImplementation(children => children),
36-
}
37-
})
30+
const notificationDiv = document.createElement('div')
31+
notificationDiv.setAttribute('id', 'notification')
32+
document.body.appendChild(notificationDiv)
3833
})
3934

4035
beforeEach(() => {
@@ -45,20 +40,24 @@ describe('HttpNotification', () => {
4540

4641
it('returns nothing if no truthy loading or error state', () => {
4742
mountedHttpNotificaton = render(
48-
<HttpNotification isLoading={false} isError={false} />,
43+
<MantineProvider>
44+
<HttpNotification isLoading={false} isError={false} />
45+
</MantineProvider>,
4946
)
5047

5148
expect(screen.queryByRole('alert')).toBeNull()
5249
})
5350

5451
it('returns loading state if loading property is true', () => {
5552
mountedHttpNotificaton = render(
56-
<HttpNotification
57-
isLoading
58-
isError={false}
59-
loadingTitle="Loading..."
60-
loadingMessage="Retrieving data from the server"
61-
/>,
53+
<MantineProvider>
54+
<HttpNotification
55+
isLoading
56+
isError={false}
57+
loadingTitle="Loading..."
58+
loadingMessage="Retrieving data from the server"
59+
/>
60+
</MantineProvider>,
6261
)
6362

6463
expect(screen.queryByRole('alert')).toBeDefined()
@@ -68,12 +67,14 @@ describe('HttpNotification', () => {
6867

6968
it('returns error state if error property is true', () => {
7069
mountedHttpNotificaton = render(
71-
<HttpNotification
72-
isLoading={false}
73-
isError
74-
errorTitle="Error"
75-
errorMessage="Unable to fetch data"
76-
/>,
70+
<MantineProvider>
71+
<HttpNotification
72+
isLoading={false}
73+
isError
74+
errorTitle="Error"
75+
errorMessage="Unable to fetch data"
76+
/>
77+
</MantineProvider>,
7778
)
7879

7980
expect(screen.queryByRole('alert')).toBeDefined()

0 commit comments

Comments
 (0)