Skip to content

Commit

Permalink
(feat) O3-4221: Use react hook form and zod in the queue service form (
Browse files Browse the repository at this point in the history
…#1416)

* (refactor) 03-4221 refactored the form by the reacthooks and zod

* (refactor) 03-4221 refactored the form by the reacthooks and zod

* (refactor) 03-4221 refactored the form by the reacthooks and zod

* (refactor) 03-4221 refactored the form by the reacthooks and zod

* (refactor) 03-4221 refactored the form by the reacthooks and zod

* changed Missing queue name to  Queue name is required

* improved zod validation

* improved the zodvalidaiton

* updated the zod validation

* changed back test

* modified yarn file

* removed InlineNotification and modified the validation

* modified test file

* changed import  from i18next to  react-i18next

* Final tweaks

---------

Co-authored-by: Dennis Kigen <kigen.work@gmail.com>
  • Loading branch information
Muppasanipraneeth and denniskigen authored Dec 23, 2024
1 parent aeab2cf commit 1689ede
Show file tree
Hide file tree
Showing 7 changed files with 353 additions and 266 deletions.
5 changes: 4 additions & 1 deletion packages/esm-service-queues-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@
},
"dependencies": {
"@carbon/react": "^1.71.0",
"lodash-es": "^4.17.15"
"@hookform/resolvers": "^3.9.1",
"lodash-es": "^4.17.15",
"react-hook-form": "^7.54.0",
"zod": "^3.24.1"
},
"peerDependencies": {
"@openmrs/esm-framework": "6.x",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const MetricsHeader = () => {
menuAlignment="bottom-end"
onClick={navigateToQueueScreen}
size={isDesktop(layout) ? 'sm' : 'lg'}
tooltipAlignment="top-end">
tooltipAlignment="left">
<UserHasAccess privilege="Emr: View Legacy Interface">
<MenuItem
label={t('addNewService', 'Add new service')}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import React from 'react';
import userEvent from '@testing-library/user-event';
import { render, screen } from '@testing-library/react';
import { useLayoutType } from '@openmrs/esm-framework';
import { showSnackbar, useLayoutType } from '@openmrs/esm-framework';
import { saveQueue } from './queue-service.resource';
import QueueServiceForm from './queue-service-form.workspace';

const defaultProps = {
closeWorkspace: jest.fn(),
promptBeforeClosing: jest.fn(),
closeWorkspaceWithSavedChanges: jest.fn(),
promptBeforeClosing: jest.fn(),
setTitle: jest.fn(),
};

const mockSaveQueue = jest.mocked(saveQueue);
const mockShowSnackbar = jest.mocked(showSnackbar);
const mockUseLayoutType = jest.mocked(useLayoutType);

jest.mock('./queue-service.resource', () => ({
Expand All @@ -37,31 +40,88 @@ describe('QueueServiceForm', () => {
mockUseLayoutType.mockReturnValue('tablet');
});

it('should display required error messages when form is submitted with missing fields', async () => {
it('renders validation errors when form is submitted with missing fields', async () => {
const user = userEvent.setup();

render(<QueueServiceForm {...defaultProps} />);

const submitButton = screen.getByText('Save');
await user.click(submitButton);
expect(screen.getByText('Missing queue name')).toBeInTheDocument();
const queueNameInput = screen.getByRole('textbox', { name: /queue name/i });
const serviceTypeSelect = screen.getByRole('combobox', { name: /select a service type/i });
const locationSelect = screen.getByRole('combobox', { name: /select a location/i });
const cancelButton = screen.getByRole('button', { name: /cancel/i });
const saveButton = screen.getByRole('button', { name: /save/i });
expect(cancelButton).toBeInTheDocument();
expect(saveButton).toBeInTheDocument();
expect(queueNameInput).toBeInTheDocument();
expect(queueNameInput).not.toBeInvalid();
expect(serviceTypeSelect).toBeInTheDocument();
expect(serviceTypeSelect).not.toBeInvalid();

await user.click(saveButton);
expect(queueNameInput).toBeInvalid();

await user.type(queueNameInput, 'Test Queue');
expect(queueNameInput).not.toBeInvalid();
expect(serviceTypeSelect).toBeInvalid();

await user.selectOptions(serviceTypeSelect, '6f017eb0-b035-4acd-b284-da45f5067502');
await user.selectOptions(locationSelect, '34567eb0-b035-4acd-b284-da45f5067502');
await user.click(saveButton);

expect(serviceTypeSelect).not.toBeInvalid();
expect(queueNameInput).not.toBeInvalid();
expect(locationSelect).not.toBeInvalid();
});

it('should submit the form when all fields are filled', async () => {
it('submits the form when all required fields are filled', async () => {
const user = userEvent.setup();
render(<QueueServiceForm {...defaultProps} />);

const queueNameInput = screen.getByRole('textbox', { name: /queue name/i });
const serviceTypeSelect = screen.getByRole('combobox', { name: /select a service type/i });
const locationSelect = screen.getByRole('combobox', { name: /select a location/i });
const saveButton = screen.getByRole('button', { name: /save/i });

await user.type(queueNameInput, 'Test Queue');
await user.selectOptions(serviceTypeSelect, '6f017eb0-b035-4acd-b284-da45f5067502');
await user.selectOptions(locationSelect, '34567eb0-b035-4acd-b284-da45f5067502');
await user.click(saveButton);

expect(mockSaveQueue).toHaveBeenCalledTimes(1);
expect(mockSaveQueue).toHaveBeenCalledWith(
'Test Queue',
'6f017eb0-b035-4acd-b284-da45f5067502',
'',
'34567eb0-b035-4acd-b284-da45f5067502',
);
expect(mockShowSnackbar).toHaveBeenCalledTimes(1);
expect(mockShowSnackbar).toHaveBeenCalledWith({
kind: 'success',
title: expect.stringMatching(/queue service created/i),
subtitle: expect.stringMatching(/queue service created successfully/i),
});
});

it('renders an error message when the queue service creation fails', async () => {
const user = userEvent.setup();
mockSaveQueue.mockRejectedValueOnce(new Error('Internal server error'));
render(<QueueServiceForm {...defaultProps} />);

const queueNameInput = screen.getByLabelText('Queue name');
const serviceSelect = screen.getByLabelText('Select a service type');
const locationSelect = screen.getByLabelText('Select a location');
const queueNameInput = screen.getByRole('textbox', { name: /queue name/i });
const serviceTypeSelect = screen.getByRole('combobox', { name: /select a service type/i });
const locationSelect = screen.getByRole('combobox', { name: /select a location/i });
const saveButton = screen.getByRole('button', { name: /save/i });

await user.type(queueNameInput, 'Test Queue');
await user.selectOptions(serviceSelect, '6f017eb0-b035-4acd-b284-da45f5067502');
await user.selectOptions(serviceTypeSelect, '6f017eb0-b035-4acd-b284-da45f5067502');
await user.selectOptions(locationSelect, '34567eb0-b035-4acd-b284-da45f5067502');
await user.click(saveButton);

expect(queueNameInput).toHaveValue('Test Queue');
expect(serviceSelect).toHaveValue('6f017eb0-b035-4acd-b284-da45f5067502');
expect(locationSelect).toHaveValue('34567eb0-b035-4acd-b284-da45f5067502');
expect(mockShowSnackbar).toHaveBeenCalledTimes(1);
expect(mockShowSnackbar).toHaveBeenCalledWith({
isLowContrast: false,
kind: 'error',
title: expect.stringMatching(/error creating queue service/i),
subtitle: expect.stringMatching(/internal server error/i),
});
});
});
Loading

0 comments on commit 1689ede

Please sign in to comment.