Skip to content

Commit 1f46216

Browse files
Add unit tests for Kitchen and Inventory Portal
Test Login component and update header rendering for Kitchen and Inventory Portal. Add titles for Kitchen and Inventory routes in App component.
1 parent 9df9d9e commit 1f46216

2 files changed

Lines changed: 235 additions & 0 deletions

File tree

src/components/App.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ function UpdateDocumentTitle() {
107107
{ pattern: /^\/Logout$/, title: 'Logout' },
108108
{ pattern: /^\/forcePasswordUpdate\/[^/]+$/, title: 'Force Password Update' },
109109
{ pattern: /^\/$/, title: `Dashboard - ${fullName}` },
110+
{ pattern: /^\/kitchenandinventory\/login$/, title: 'Kitchen and Inventory Login' },
111+
{ pattern: /^\/kitchenandinventory$/, title: 'Kitchen and Inventory Dashboard' },
110112
{ pattern: /.*/, title: 'HGN APP' }, // Default case
111113
{
112114
pattern: /^\/communityportal\/activity\/activityid\/feedback$/,
Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
2+
import '@testing-library/jest-dom/extend-expect';
3+
import { useDispatch, Provider } from 'react-redux';
4+
import thunk from 'redux-thunk';
5+
import { configureStore } from 'redux-mock-store';
6+
import { BrowserRouter as Router } from 'react-router-dom';
7+
import axios from 'axios';
8+
import KitchenandInventoryLogin from '../KitchenandInventoryLogin';
9+
10+
const mockStore = configureStore([thunk]);
11+
let store;
12+
13+
beforeEach(() => {
14+
store = mockStore({
15+
auth: {
16+
isAuthenticated: true,
17+
user: {
18+
permissions: {
19+
frontPermissions: [],
20+
backPermissions: [],
21+
},
22+
role: 'Owner',
23+
},
24+
permissions: {
25+
frontPermissions: [],
26+
backPermissions: [],
27+
},
28+
},
29+
});
30+
});
31+
32+
vi.mock('axios');
33+
34+
vi.mock('jwt-decode', () => ({
35+
default: vi.fn(() => ({ decodedPayload: 'mocked_decoded_payload' })),
36+
}));
37+
const history = {
38+
push: vi.fn(),
39+
location: { pathname: '/' },
40+
};
41+
42+
const renderComponent = testStore => {
43+
function LoginWrapper() {
44+
const dispatch = useDispatch();
45+
const location = {};
46+
47+
return <KitchenandInventoryLogin dispatch={dispatch} history={history} location={location} />;
48+
}
49+
return render(
50+
<Provider store={testStore}>
51+
<Router>
52+
<LoginWrapper />
53+
</Router>
54+
</Provider>,
55+
);
56+
};
57+
58+
describe('KitchenandInventoryLogin component', () => {
59+
it('renders without crashing', () => {
60+
renderComponent(store);
61+
});
62+
it('check if login elements get displayed when isAuthenticated is true', () => {
63+
renderComponent(store);
64+
expect(screen.getByText('Log In To Kitchen and Inventory Portal')).toBeInTheDocument();
65+
});
66+
it('check if login elements does not get displayed when isAuthenticated is false', () => {
67+
const testStore = mockStore({
68+
auth: {
69+
isAuthenticated: false,
70+
user: {
71+
permissions: {
72+
frontPermissions: [],
73+
backPermissions: [],
74+
},
75+
role: 'Owner',
76+
},
77+
permissions: {
78+
frontPermissions: [],
79+
backPermissions: [],
80+
},
81+
},
82+
});
83+
renderComponent(testStore);
84+
expect(screen.queryByText('Log In To Kitchen and Inventory Portal')).not.toBeInTheDocument();
85+
});
86+
it('check if Enter your current user credentials to access the Kitchen and Inventory Portal Dashboard header displays as expected', () => {
87+
renderComponent(store);
88+
expect(
89+
screen.getByText(
90+
'Enter your current user credentials to access the Kitchen and Inventory Portal Dashboard',
91+
),
92+
).toBeInTheDocument();
93+
});
94+
it('check if Note: You must use your Production/Main credentials for this login. header displays as expected', () => {
95+
renderComponent(store);
96+
expect(
97+
screen.getByText('Note: You must use your Production/Main credentials for this login.'),
98+
).toBeInTheDocument();
99+
});
100+
it('check if email label is displaying as expected', () => {
101+
renderComponent(store);
102+
expect(screen.getByText('Email')).toBeInTheDocument();
103+
});
104+
it('check if password label is displaying as expected', () => {
105+
renderComponent(store);
106+
expect(screen.getByText('Password')).toBeInTheDocument();
107+
});
108+
it('check if submit button is disabled when either email or password is not entered', () => {
109+
renderComponent(store);
110+
const buttonElement = screen.getByText('Submit');
111+
expect(buttonElement).toBeDisabled();
112+
});
113+
it('check if validation for invalid email id works as expected', () => {
114+
const { container } = renderComponent(store);
115+
const emailElement = screen.getByRole('textbox', { name: /email/i });
116+
fireEvent.change(emailElement, { target: { value: 'test' } });
117+
118+
const passwordElement = screen.getByLabelText(/password/i);
119+
fireEvent.change(passwordElement, { target: { value: '12' } });
120+
121+
const submitElement = screen.getByText('Submit');
122+
fireEvent.click(submitElement);
123+
124+
expect(emailElement).toBeInvalid();
125+
expect(screen.getByText('"email" must be a valid email')).toBeInTheDocument();
126+
});
127+
it('check if validation for password works as expected', () => {
128+
const { container } = renderComponent(store);
129+
const emailElement = screen.getByRole('textbox', { name: /email/i });
130+
fireEvent.change(emailElement, { target: { value: 'test@gmail.com' } });
131+
132+
const passwordElement = screen.getByLabelText(/password/i);
133+
fireEvent.change(passwordElement, { target: { value: '12' } });
134+
135+
const submitElement = screen.getByText('Submit');
136+
fireEvent.click(submitElement);
137+
138+
expect(passwordElement).toBeInvalid();
139+
expect(
140+
screen.getByText('"password" length must be at least 8 characters long'),
141+
).toBeInTheDocument();
142+
});
143+
it('check if entering the right email and password logs in as expected', async () => {
144+
axios.post.mockResolvedValue({
145+
statusText: 'OK',
146+
data: { token: '1234' },
147+
});
148+
149+
const { container } = renderComponent(store);
150+
151+
const emailElement = screen.getByRole('textbox', { name: /email/i });
152+
const passwordElement = screen.getByLabelText(/password/i);
153+
const submitElement = screen.getByText('Submit');
154+
155+
fireEvent.change(emailElement, { target: { value: 'test@gmail.com' } });
156+
fireEvent.change(passwordElement, { target: { value: 'Test12345' } });
157+
fireEvent.click(submitElement);
158+
159+
// Wait for validation to pass
160+
await waitFor(() => {
161+
expect(emailElement).not.toBeInvalid();
162+
});
163+
expect(passwordElement).not.toBeInvalid();
164+
expect(screen.queryByText('"email" must be a valid email')).not.toBeInTheDocument();
165+
expect(
166+
screen.queryByText('"password" length must be at least 8 characters long'),
167+
).not.toBeInTheDocument();
168+
169+
// Wait for redirect to be triggered
170+
await waitFor(() => {
171+
expect(history.push).toHaveBeenCalledWith('/kitchenandinventory');
172+
});
173+
});
174+
it("check if statusText in response is not 'OK' and status is 422 and displays validation error", async () => {
175+
axios.post.mockResolvedValue({
176+
statusText: 'ERROR',
177+
status: 422,
178+
data: { token: '1234', label: 'email', message: 'User not found' },
179+
});
180+
const { container } = renderComponent(store);
181+
182+
const emailElement = screen.getByRole('textbox', { name: /email/i });
183+
fireEvent.change(emailElement, { target: { value: 'test@gmail.com' } });
184+
185+
const passwordElement = screen.getByLabelText(/password/i);
186+
fireEvent.change(passwordElement, { target: { value: 'Test12345' } });
187+
188+
const submitElement = screen.getByText('Submit');
189+
fireEvent.click(submitElement);
190+
191+
await waitFor(() => {
192+
expect(screen.getByText('User not found')).toBeInTheDocument();
193+
});
194+
});
195+
it("check if statusText in response is not 'OK' and status is not 422 and does not display any validation error", async () => {
196+
axios.post.mockResolvedValue({
197+
statusText: 'ERROR',
198+
status: 500,
199+
data: { token: '1234' },
200+
});
201+
const { container } = renderComponent(store);
202+
203+
const emailElement = screen.getByRole('textbox', { name: /email/i });
204+
fireEvent.change(emailElement, { target: { value: 'test@gmail.com' } });
205+
206+
const passwordElement = screen.getByLabelText(/password/i);
207+
fireEvent.change(passwordElement, { target: { value: 'Test12345' } });
208+
209+
const submitElement = screen.getByText('Submit');
210+
fireEvent.click(submitElement);
211+
212+
await waitFor(() => {
213+
expect(passwordElement).not.toBeInvalid();
214+
});
215+
});
216+
it('check failed post request does not display any validation error', async () => {
217+
axios.post.mockRejectedValue({ response: 'server error' });
218+
const { container } = renderComponent(store);
219+
220+
const emailElement = screen.getByRole('textbox', { name: /email/i });
221+
fireEvent.change(emailElement, { target: { value: 'test@gmail.com' } });
222+
223+
const passwordElement = screen.getByLabelText(/password/i);
224+
fireEvent.change(passwordElement, { target: { value: 'Test12345' } });
225+
226+
const submitElement = screen.getByText('Submit');
227+
fireEvent.click(submitElement);
228+
229+
await waitFor(() => {
230+
expect(passwordElement).not.toBeInvalid();
231+
});
232+
});
233+
});

0 commit comments

Comments
 (0)