@openmrs/esm-patient-programs-app 3.2.1-pre.89 → 4.0.1-pre.221

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/.turbo/turbo-build.log +25 -273
  2. package/dist/109.js +1 -0
  3. package/dist/13.js +1 -0
  4. package/dist/145.js +1 -0
  5. package/dist/154.js +2 -0
  6. package/dist/154.js.LICENSE.txt +53 -0
  7. package/dist/206.js +1 -2
  8. package/dist/238.js +2 -0
  9. package/dist/{707.js.LICENSE.txt → 238.js.LICENSE.txt} +0 -0
  10. package/dist/340.js +1 -0
  11. package/dist/435.js +1 -0
  12. package/dist/461.js +1 -0
  13. package/dist/574.js +1 -1
  14. package/dist/709.js +1 -0
  15. package/dist/784.js +1 -2
  16. package/dist/784.js.LICENSE.txt +2 -7
  17. package/dist/858.js +1 -2
  18. package/dist/858.js.LICENSE.txt +2 -0
  19. package/dist/879.js +1 -2
  20. package/dist/main.js +1 -0
  21. package/dist/openmrs-esm-patient-programs-app.js +1 -1
  22. package/dist/openmrs-esm-patient-programs-app.js.buildmanifest.json +150 -259
  23. package/dist/openmrs-esm-patient-programs-app.old +1 -2
  24. package/package.json +7 -11
  25. package/src/config-schema.ts +12 -0
  26. package/src/dashboard.meta.tsx +1 -1
  27. package/src/index.ts +3 -2
  28. package/src/programs/program-action-button/program-action-button.component.tsx +47 -0
  29. package/src/programs/programs-detailed-summary.component.tsx +68 -37
  30. package/src/programs/programs-detailed-summary.scss +1 -4
  31. package/src/programs/programs-detailed-summary.test.tsx +26 -7
  32. package/src/programs/programs-form.component.tsx +102 -46
  33. package/src/programs/programs-form.scss +1 -9
  34. package/src/programs/programs-form.test.tsx +113 -110
  35. package/src/programs/programs-overview.component.tsx +59 -45
  36. package/src/programs/programs-overview.scss +1 -3
  37. package/src/programs/programs-overview.test.tsx +6 -7
  38. package/src/programs/programs.resource.tsx +63 -8
  39. package/src/types/index.ts +16 -2
  40. package/translations/en.json +8 -2
  41. package/dist/163.js +0 -3
  42. package/dist/163.js.LICENSE.txt +0 -20
  43. package/dist/163.js.map +0 -1
  44. package/dist/186.js +0 -3
  45. package/dist/186.js.LICENSE.txt +0 -23
  46. package/dist/186.js.map +0 -1
  47. package/dist/206.js.map +0 -1
  48. package/dist/252.js +0 -3
  49. package/dist/252.js.LICENSE.txt +0 -23
  50. package/dist/252.js.map +0 -1
  51. package/dist/344.js +0 -2
  52. package/dist/344.js.map +0 -1
  53. package/dist/357.js +0 -2
  54. package/dist/357.js.map +0 -1
  55. package/dist/373.js +0 -2
  56. package/dist/373.js.map +0 -1
  57. package/dist/402.js +0 -2
  58. package/dist/402.js.map +0 -1
  59. package/dist/511.js +0 -2
  60. package/dist/511.js.map +0 -1
  61. package/dist/593.js +0 -2
  62. package/dist/593.js.map +0 -1
  63. package/dist/635.js +0 -3
  64. package/dist/635.js.LICENSE.txt +0 -16
  65. package/dist/635.js.map +0 -1
  66. package/dist/701.js +0 -2
  67. package/dist/701.js.map +0 -1
  68. package/dist/707.js +0 -3
  69. package/dist/707.js.map +0 -1
  70. package/dist/76.js +0 -2
  71. package/dist/76.js.map +0 -1
  72. package/dist/784.js.map +0 -1
  73. package/dist/858.js.map +0 -1
  74. package/dist/879.js.map +0 -1
  75. package/dist/932.js +0 -2
  76. package/dist/932.js.map +0 -1
  77. package/dist/openmrs-esm-patient-programs-app.js.map +0 -1
@@ -1,10 +1,10 @@
1
1
  import React, { SyntheticEvent } from 'react';
2
+ import { useTranslation } from 'react-i18next';
2
3
  import dayjs from 'dayjs';
3
4
  import filter from 'lodash-es/filter';
4
5
  import includes from 'lodash-es/includes';
5
6
  import map from 'lodash-es/map';
6
7
  import { useSWRConfig } from 'swr';
7
- import { useTranslation } from 'react-i18next';
8
8
  import {
9
9
  createErrorHandler,
10
10
  showNotification,
@@ -12,27 +12,34 @@ import {
12
12
  useSession,
13
13
  useLocations,
14
14
  useLayoutType,
15
+ parseDate,
15
16
  } from '@openmrs/esm-framework';
16
17
  import {
17
18
  Button,
19
+ ButtonSet,
18
20
  DatePicker,
19
21
  DatePickerInput,
20
- Select,
21
- SelectItem,
22
22
  Form,
23
23
  FormGroup,
24
- ButtonSet,
25
- } from 'carbon-components-react';
24
+ Select,
25
+ SelectItem,
26
+ Stack,
27
+ } from '@carbon/react';
26
28
  import {
27
29
  createProgramEnrollment,
28
30
  useAvailablePrograms,
29
31
  useEnrollments,
30
32
  customRepresentation,
33
+ updateProgramEnrollment,
31
34
  } from './programs.resource';
32
35
  import { DefaultWorkspaceProps } from '@openmrs/esm-patient-common-lib';
33
36
  import styles from './programs-form.scss';
34
37
 
35
- const ProgramsForm: React.FC<DefaultWorkspaceProps> = ({ closeWorkspace, patientUuid }) => {
38
+ interface ProgramsFormProps extends DefaultWorkspaceProps {
39
+ programEnrollmentId?: string;
40
+ }
41
+
42
+ const ProgramsForm: React.FC<ProgramsFormProps> = ({ closeWorkspace, patientUuid, programEnrollmentId }) => {
36
43
  const { t } = useTranslation();
37
44
  const isTablet = useLayoutType() === 'tablet';
38
45
  const session = useSession();
@@ -41,16 +48,25 @@ const ProgramsForm: React.FC<DefaultWorkspaceProps> = ({ closeWorkspace, patient
41
48
 
42
49
  const { data: availablePrograms } = useAvailablePrograms();
43
50
  const { data: enrollments } = useEnrollments(patientUuid);
51
+ const currentEnrollment = programEnrollmentId && enrollments.filter((e) => e.uuid == programEnrollmentId)[0];
52
+ const currentProgram = currentEnrollment
53
+ ? {
54
+ display: currentEnrollment.program.name,
55
+ ...currentEnrollment.program,
56
+ }
57
+ : null;
44
58
 
45
- const eligiblePrograms = filter(
46
- availablePrograms,
47
- (program) => !includes(map(enrollments, 'program.uuid'), program.uuid),
59
+ const eligiblePrograms = currentProgram
60
+ ? [currentProgram]
61
+ : filter(availablePrograms, (program) => !includes(map(enrollments, 'program.uuid'), program.uuid));
62
+ const [completionDate, setCompletionDate] = React.useState<Date>(
63
+ currentEnrollment?.dateCompleted ? parseDate(currentEnrollment.dateCompleted) : null,
48
64
  );
49
-
50
- const [completionDate, setCompletionDate] = React.useState(null);
51
- const [enrollmentDate, setEnrollmentDate] = React.useState(new Date());
52
- const [selectedProgram, setSelectedProgram] = React.useState<string>('');
53
- const [userLocation, setUserLocation] = React.useState('');
65
+ const [enrollmentDate, setEnrollmentDate] = React.useState<Date>(
66
+ currentEnrollment?.dateEnrolled ? parseDate(currentEnrollment.dateEnrolled) : new Date(),
67
+ );
68
+ const [selectedProgram, setSelectedProgram] = React.useState<string>(currentEnrollment?.program.uuid ?? '');
69
+ const [userLocation, setUserLocation] = React.useState<string>(currentEnrollment?.location.uuid ?? '');
54
70
 
55
71
  if (!userLocation && session?.sessionLocation?.uuid) {
56
72
  setUserLocation(session?.sessionLocation?.uuid);
@@ -71,43 +87,83 @@ const ProgramsForm: React.FC<DefaultWorkspaceProps> = ({ closeWorkspace, patient
71
87
  };
72
88
 
73
89
  const abortController = new AbortController();
74
- const sub = createProgramEnrollment(payload, abortController).subscribe(
75
- (response) => {
76
- if (response.status === 201) {
77
- closeWorkspace();
78
-
79
- showToast({
80
- critical: true,
81
- kind: 'success',
82
- description: t('enrollmentNowVisible', 'It is now visible on the Programs page'),
83
- title: t('enrollmentSaved', 'Program enrollment saved'),
84
- });
85
-
86
- mutate(`/ws/rest/v1/programenrollment?patient=${patientUuid}&v=${customRepresentation}`);
87
- }
88
- },
89
- (err) => {
90
- createErrorHandler();
91
-
92
- showNotification({
93
- title: t('programEnrollmentSaveError', 'Error saving program enrollment'),
94
- kind: 'error',
95
- critical: true,
96
- description: err?.message,
97
- });
98
- },
99
- );
90
+ const sub = currentEnrollment
91
+ ? updateProgramEnrollment(currentEnrollment.uuid, payload, abortController).subscribe(
92
+ (response) => {
93
+ if (response.status === 200) {
94
+ closeWorkspace();
95
+
96
+ showToast({
97
+ critical: true,
98
+ kind: 'success',
99
+ description: t(
100
+ 'enrollmentUpdatesNowVisible',
101
+ 'Changes to the program are now visible in the Programs table',
102
+ ),
103
+ title: t('enrollmentUpdated', 'Program enrollment updated'),
104
+ });
105
+
106
+ mutate(`/ws/rest/v1/programenrollment?patient=${patientUuid}&v=${customRepresentation}`);
107
+ }
108
+ },
109
+ (err) => {
110
+ createErrorHandler();
111
+
112
+ showNotification({
113
+ title: t('programEnrollmentSaveError', 'Error saving program enrollment'),
114
+ kind: 'error',
115
+ critical: true,
116
+ description: err?.message,
117
+ });
118
+ },
119
+ )
120
+ : createProgramEnrollment(payload, abortController).subscribe(
121
+ (response) => {
122
+ if (response.status === 201) {
123
+ closeWorkspace();
124
+
125
+ showToast({
126
+ critical: true,
127
+ kind: 'success',
128
+ description: t('enrollmentNowVisible', 'It is now visible in the Programs table'),
129
+ title: t('enrollmentSaved', 'Program enrollment saved'),
130
+ });
131
+
132
+ mutate(`/ws/rest/v1/programenrollment?patient=${patientUuid}&v=${customRepresentation}`);
133
+ }
134
+ },
135
+ (err) => {
136
+ createErrorHandler();
137
+
138
+ showNotification({
139
+ title: t('programEnrollmentSaveError', 'Error saving program enrollment'),
140
+ kind: 'error',
141
+ critical: true,
142
+ description: err?.message,
143
+ });
144
+ },
145
+ );
100
146
  return () => {
101
147
  sub.unsubscribe();
102
148
  };
103
149
  },
104
- [closeWorkspace, completionDate, enrollmentDate, mutate, patientUuid, selectedProgram, t, userLocation],
150
+ [
151
+ closeWorkspace,
152
+ completionDate,
153
+ enrollmentDate,
154
+ mutate,
155
+ patientUuid,
156
+ selectedProgram,
157
+ t,
158
+ userLocation,
159
+ currentEnrollment,
160
+ ],
105
161
  );
106
162
 
107
163
  return (
108
164
  <Form className={styles.form} onSubmit={handleSubmit}>
109
- <div className={styles.formContainer}>
110
- <FormGroup style={{ width: '50%' }} legendText={t('program', 'Program')}>
165
+ <Stack className={styles.formContainer} gap={7}>
166
+ <FormGroup style={{ maxWidth: '50%' }} legendText={t('programName', 'Program name')}>
111
167
  <div className={styles.selectContainer}>
112
168
  <Select
113
169
  id="program"
@@ -126,7 +182,7 @@ const ProgramsForm: React.FC<DefaultWorkspaceProps> = ({ closeWorkspace, patient
126
182
  </Select>
127
183
  </div>
128
184
  </FormGroup>
129
- <FormGroup legendText={t('dateEnrolled', 'Date enrolled')}>
185
+ <FormGroup style={{ maxWidth: '50%' }} legendText={t('dateEnrolled', 'Date enrolled')}>
130
186
  <DatePicker
131
187
  id="enrollmentDate"
132
188
  datePickerType="single"
@@ -140,7 +196,7 @@ const ProgramsForm: React.FC<DefaultWorkspaceProps> = ({ closeWorkspace, patient
140
196
  <DatePickerInput id="enrollmentDateInput" labelText="" />
141
197
  </DatePicker>
142
198
  </FormGroup>
143
- <FormGroup legendText={t('dateCompleted', 'Date completed')}>
199
+ <FormGroup style={{ width: '50%' }} legendText={t('dateCompleted', 'Date completed')}>
144
200
  <DatePicker
145
201
  id="completionDate"
146
202
  datePickerType="single"
@@ -173,7 +229,7 @@ const ProgramsForm: React.FC<DefaultWorkspaceProps> = ({ closeWorkspace, patient
173
229
  ))}
174
230
  </Select>
175
231
  </FormGroup>
176
- </div>
232
+ </Stack>
177
233
  <ButtonSet className={isTablet ? styles.tablet : styles.desktop}>
178
234
  <Button className={styles.button} kind="secondary" onClick={() => closeWorkspace()}>
179
235
  {t('cancel', 'Cancel')}
@@ -1,11 +1,4 @@
1
- @import "~@openmrs/esm-styleguide/src/vars";
2
- @import "~carbon-components/src/globals/scss/vars";
3
- @import "~carbon-components/src/globals/scss/mixins";
4
-
5
- .selectContainer {
6
- display: flex;
7
- align-items: center;
8
- }
1
+ @import '~@openmrs/esm-styleguide/src/vars';
9
2
 
10
3
  .loading {
11
4
  margin-left: 1rem;
@@ -13,7 +6,6 @@
13
6
  min-height: 2.5rem;
14
7
  }
15
8
 
16
-
17
9
  .button {
18
10
  height: 4rem;
19
11
  display: flex;
@@ -1,18 +1,20 @@
1
1
  import React from 'react';
2
2
  import { throwError } from 'rxjs';
3
3
  import { of } from 'rxjs/internal/observable/of';
4
- import { render, screen, waitFor } from '@testing-library/react';
4
+ import { render, screen, waitFor, within } from '@testing-library/react';
5
5
  import userEvent from '@testing-library/user-event';
6
- import { createErrorHandler, openmrsFetch, showNotification, showToast, useLayoutType } from '@openmrs/esm-framework';
6
+ import { createErrorHandler, openmrsFetch, showNotification, showToast } from '@openmrs/esm-framework';
7
7
  import { mockPatient } from '../../../../__mocks__/patient.mock';
8
8
  import {
9
9
  mockCareProgramsResponse,
10
10
  mockEnrolledProgramsResponse,
11
11
  mockLocationsResponse,
12
12
  } from '../../../../__mocks__/programs.mock';
13
- import { createProgramEnrollment } from './programs.resource';
13
+ import { createProgramEnrollment, updateProgramEnrollment } from './programs.resource';
14
14
  import ProgramsForm from './programs-form.component';
15
15
 
16
+ jest.setTimeout(20000);
17
+
16
18
  const testProps = {
17
19
  closeWorkspace: jest.fn(),
18
20
  patientUuid: mockPatient.id,
@@ -21,10 +23,10 @@ const testProps = {
21
23
 
22
24
  const mockCreateErrorHandler = createErrorHandler as jest.Mock;
23
25
  const mockCreateProgramEnrollment = createProgramEnrollment as jest.Mock;
26
+ const mockUpdateProgramEnrollment = updateProgramEnrollment as jest.Mock;
24
27
  const mockOpenmrsFetch = openmrsFetch as jest.Mock;
25
28
  const mockShowNotification = showNotification as jest.Mock;
26
29
  const mockShowToast = showToast as jest.Mock;
27
- const mockUseLayoutType = useLayoutType as jest.Mock;
28
30
 
29
31
  jest.mock('@openmrs/esm-framework', () => {
30
32
  const originalModule = jest.requireActual('@openmrs/esm-framework');
@@ -44,142 +46,143 @@ jest.mock('./programs.resource', () => {
44
46
  return {
45
47
  ...originalModule,
46
48
  createProgramEnrollment: jest.fn(),
49
+ updateProgramEnrollment: jest.fn(),
47
50
  };
48
51
  });
49
52
 
50
- describe('ProgramsForm: ', () => {
51
- beforeEach(() => {
53
+ describe('ProgramsForm', () => {
54
+ it('renders a success toast notification upon successfully recording a program enrollment', async () => {
55
+ const user = userEvent.setup();
56
+
57
+ const inpatientWardUuid = 'b1a8b05e-3542-4037-bbd3-998ee9c40574';
58
+ const oncologyScreeningProgramUuid = '11b129ca-a5e7-4025-84bf-b92a173e20de';
59
+
52
60
  mockOpenmrsFetch.mockReturnValueOnce({ data: { results: mockCareProgramsResponse } });
53
61
  mockOpenmrsFetch.mockReturnValueOnce({ data: { results: mockEnrolledProgramsResponse } });
54
- });
62
+ mockCreateProgramEnrollment.mockReturnValueOnce(of({ status: 201, statusText: 'Created' }));
55
63
 
56
- it('renders the programs form with all the relevant fields and values', async () => {
57
64
  renderProgramsForm();
58
65
 
59
- await screen.findByRole('group', { name: /Program/i });
60
- expect(screen.getByRole('group', { name: /Date enrolled/i })).toBeInTheDocument();
61
- expect(screen.getByRole('group', { name: /Date completed/i })).toBeInTheDocument();
62
- expect(screen.getByRole('group', { name: /Enrollment location/i })).toBeInTheDocument();
63
- expect(screen.getByRole('option', { name: /Choose a program/i })).toBeInTheDocument();
64
- expect(screen.getByRole('option', { name: /Oncology Screening and Diagnosis/i })).toBeInTheDocument();
65
- expect(screen.getByRole('option', { name: /Choose a location/i })).toBeInTheDocument();
66
- expect(screen.getByRole('option', { name: /Amani Hospital/i })).toBeInTheDocument();
66
+ const enrollButton = screen.getByRole('button', { name: /save and close/i });
67
+ const enrollmentDateInput = screen.getAllByRole('textbox', { name: '' })[0];
68
+ const selectLocationInput = screen.getAllByRole('combobox', { name: '' })[1];
69
+ const selectProgramInput = screen.getAllByRole('combobox', { name: '' })[0];
70
+
71
+ await waitFor(() => user.type(enrollmentDateInput, '2020-05-05'));
72
+ await waitFor(() => user.selectOptions(selectProgramInput, [oncologyScreeningProgramUuid]));
73
+ await waitFor(() => user.selectOptions(selectLocationInput, [inpatientWardUuid]));
74
+
67
75
  expect(screen.getByRole('option', { name: /Inpatient Ward/i })).toBeInTheDocument();
68
- expect(screen.getByRole('option', { name: /Isolation Ward/i })).toBeInTheDocument();
69
- expect(screen.getByRole('option', { name: /Laboratory/i })).toBeInTheDocument();
70
76
 
71
- const cancelButton = screen.getByRole('button', { name: /cancel/i });
72
- const enrollButton = screen.getByRole('button', { name: /save and close/i });
73
- expect(cancelButton).toBeInTheDocument();
74
- expect(enrollButton).toBeInTheDocument();
75
- expect(enrollButton).toBeDisabled();
77
+ await waitFor(() => user.click(enrollButton));
78
+
79
+ expect(mockCreateProgramEnrollment).toHaveBeenCalledTimes(1);
80
+ expect(mockCreateProgramEnrollment).toHaveBeenCalledWith(
81
+ expect.objectContaining({
82
+ dateCompleted: null,
83
+ location: inpatientWardUuid,
84
+ patient: mockPatient.id,
85
+ program: oncologyScreeningProgramUuid,
86
+ }),
87
+ new AbortController(),
88
+ );
89
+
90
+ expect(mockShowToast).toHaveBeenCalledTimes(1);
91
+ expect(mockShowToast).toHaveBeenCalledWith({
92
+ critical: true,
93
+ description: 'It is now visible in the Programs table',
94
+ kind: 'success',
95
+ title: 'Program enrollment saved',
96
+ });
76
97
  });
77
98
 
78
- it('closes the form and the workspace when the cancel button is clicked', () => {
79
- renderProgramsForm();
99
+ it('updates a program enrollment', async () => {
100
+ const user = userEvent.setup();
80
101
 
81
- const cancelButton = screen.getByRole('button', { name: /Cancel/i });
82
- userEvent.click(cancelButton);
102
+ renderProgramsForm(mockEnrolledProgramsResponse[0].uuid);
83
103
 
84
- expect(testProps.closeWorkspace).toHaveBeenCalledTimes(1);
85
- });
104
+ const enrollButton = screen.getByRole('button', { name: /save and close/i });
105
+ const dateCompletedGroup = screen.getByRole('group', { name: /Date completed/i });
106
+ const dateCompletedInput = within(dateCompletedGroup).getByRole('textbox');
86
107
 
87
- it('renders a light background for date inputs in the tablet viewport ', () => {
88
- mockUseLayoutType.mockReturnValueOnce('tablet').mockReturnValueOnce('tablet');
108
+ mockUpdateProgramEnrollment.mockReturnValueOnce(of({ status: 200, statusText: 'OK' }));
89
109
 
90
- renderProgramsForm();
110
+ await waitFor(() => user.type(dateCompletedInput, '05/05/2020'));
91
111
 
92
- expect(screen.getAllByPlaceholderText('dd/mm/yyyy')[0]).toHaveClass('bx--date-picker--light', { exact: false });
93
- expect(screen.getAllByPlaceholderText('dd/mm/yyyy')[1]).toHaveClass('bx--date-picker--light', { exact: false });
112
+ expect(dateCompletedInput).toHaveValue('05/05/2020');
113
+
114
+ await waitFor(() => user.tab());
115
+
116
+ expect(enrollButton).not.toBeDisabled();
117
+
118
+ await waitFor(() => user.click(enrollButton));
119
+
120
+ expect(mockUpdateProgramEnrollment).toHaveBeenCalledTimes(1);
121
+ expect(mockUpdateProgramEnrollment).toHaveBeenCalledWith(
122
+ mockEnrolledProgramsResponse[0].uuid,
123
+ expect.objectContaining({
124
+ dateEnrolled: '2020-01-16T00:00:00+00:00',
125
+ dateCompleted: '2020-05-05T00:00:00+00:00',
126
+ location: mockEnrolledProgramsResponse[0].location.uuid,
127
+ patient: mockPatient.id,
128
+ program: mockEnrolledProgramsResponse[0].program.uuid,
129
+ }),
130
+ new AbortController(),
131
+ );
132
+
133
+ expect(mockShowToast).toHaveBeenCalledWith(
134
+ expect.objectContaining({
135
+ critical: true,
136
+ description: 'Changes to the program are now visible in the Programs table',
137
+ kind: 'success',
138
+ title: 'Program enrollment updated',
139
+ }),
140
+ );
94
141
  });
95
142
 
96
- describe('Form submission: ', () => {
143
+ it('renders an error notification if there was a problem recording a program enrollment', async () => {
144
+ const user = userEvent.setup();
145
+
97
146
  const inpatientWardUuid = 'b1a8b05e-3542-4037-bbd3-998ee9c40574';
98
147
  const oncologyScreeningProgramUuid = '11b129ca-a5e7-4025-84bf-b92a173e20de';
99
- let cancelButton: HTMLElement;
100
- let enrollButton: HTMLElement;
101
- let enrollmentDateInput: HTMLElement;
102
- let selectLocationInput: HTMLElement;
103
- let selectProgramInput: HTMLElement;
104
-
105
- beforeEach(() => {
106
- renderProgramsForm();
107
-
108
- cancelButton = screen.getByRole('button', { name: /cancel/i });
109
- enrollButton = screen.getByRole('button', { name: /save and close/i });
110
- enrollmentDateInput = screen.getAllByRole('textbox', { name: '' })[0];
111
- selectLocationInput = screen.getAllByRole('combobox', { name: '' })[1];
112
- selectProgramInput = screen.getAllByRole('combobox', { name: '' })[0];
113
- });
114
148
 
115
- it('renders a success toast notification upon successfully recording a program enrollment', async () => {
116
- mockCreateProgramEnrollment.mockReturnValueOnce(of({ status: 201, statusText: 'Created' }));
117
-
118
- userEvent.selectOptions(selectProgramInput, [oncologyScreeningProgramUuid]);
119
- userEvent.selectOptions(selectLocationInput, [inpatientWardUuid]);
120
- userEvent.type(enrollmentDateInput, '2020-05-05');
121
-
122
- expect(screen.getByDisplayValue('Oncology Screening and Diagnosis')).toBeInTheDocument();
123
- expect(screen.getByDisplayValue('Inpatient Ward')).toBeInTheDocument();
124
- expect(enrollButton).not.toBeDisabled();
125
-
126
- await waitFor(() => userEvent.click(enrollButton));
127
-
128
- expect(mockCreateProgramEnrollment).toHaveBeenCalledTimes(1);
129
- expect(mockCreateProgramEnrollment).toHaveBeenCalledWith(
130
- expect.objectContaining({
131
- dateCompleted: null,
132
- location: inpatientWardUuid,
133
- patient: mockPatient.id,
134
- program: oncologyScreeningProgramUuid,
135
- }),
136
- new AbortController(),
137
- );
138
-
139
- expect(mockShowToast).toHaveBeenCalledTimes(1);
140
- expect(mockShowToast).toHaveBeenCalledWith(
141
- expect.objectContaining({
142
- critical: true,
143
- description: 'It is now visible on the Programs page',
144
- kind: 'success',
145
- title: 'Program enrollment saved',
146
- }),
147
- );
148
- });
149
+ const error = {
150
+ message: 'Internal Server Error',
151
+ response: {
152
+ status: 500,
153
+ statusText: 'Internal Server Error',
154
+ },
155
+ };
149
156
 
150
- xit('renders an error notification if there was a problem recording a program enrollment', async () => {
151
- const error = {
152
- message: 'Internal Server Error',
153
- response: {
154
- status: 500,
155
- statusText: 'Internal Server Error',
156
- },
157
- };
157
+ mockOpenmrsFetch.mockReturnValueOnce({ data: { results: mockCareProgramsResponse } });
158
+ mockOpenmrsFetch.mockReturnValueOnce({ data: { results: mockEnrolledProgramsResponse } });
159
+ mockCreateProgramEnrollment.mockReturnValueOnce(throwError(error));
158
160
 
159
- mockCreateProgramEnrollment.mockReturnValueOnce(throwError(error));
161
+ renderProgramsForm();
160
162
 
161
- userEvent.selectOptions(selectProgramInput, [oncologyScreeningProgramUuid]);
162
- userEvent.selectOptions(selectLocationInput, [inpatientWardUuid]);
163
- userEvent.type(enrollmentDateInput, '2020-05-05');
163
+ const enrollButton = screen.getByRole('button', { name: /save and close/i });
164
+ const enrollmentDateInput = screen.getAllByRole('textbox', { name: '' })[0];
165
+ const selectLocationInput = screen.getAllByRole('combobox', { name: '' })[1];
166
+ const selectProgramInput = screen.getAllByRole('combobox', { name: '' })[0];
164
167
 
165
- expect(screen.getByDisplayValue('Oncology Screening and Diagnosis')).toBeInTheDocument();
166
- expect(screen.getByDisplayValue('2020-05-05')).toBeInTheDocument();
167
- expect(screen.getByDisplayValue('Inpatient Ward')).toBeInTheDocument();
168
- expect(enrollButton).not.toBeDisabled();
168
+ await waitFor(() => user.type(enrollmentDateInput, '2020-05-05'));
169
+ await waitFor(() => user.selectOptions(selectProgramInput, [oncologyScreeningProgramUuid]));
170
+ await waitFor(() => user.selectOptions(selectLocationInput, [inpatientWardUuid]));
169
171
 
170
- userEvent.click(enrollButton);
172
+ expect(enrollButton).not.toBeDisabled();
171
173
 
172
- expect(mockCreateErrorHandler).toHaveBeenCalledTimes(1);
173
- expect(mockShowNotification).toHaveBeenCalledWith({
174
- critical: true,
175
- description: 'Internal Server Error',
176
- kind: 'error',
177
- title: 'Error saving program enrollment',
178
- });
174
+ await waitFor(() => user.click(enrollButton));
175
+
176
+ expect(mockCreateErrorHandler).toHaveBeenCalledTimes(1);
177
+ expect(mockShowNotification).toHaveBeenCalledWith({
178
+ critical: true,
179
+ description: 'Internal Server Error',
180
+ kind: 'error',
181
+ title: 'Error saving program enrollment',
179
182
  });
180
183
  });
181
184
  });
182
185
 
183
- function renderProgramsForm() {
184
- render(<ProgramsForm {...testProps} />);
186
+ function renderProgramsForm(programEnrollmentUuidToEdit?: string) {
187
+ render(<ProgramsForm {...testProps} programEnrollmentId={programEnrollmentUuidToEdit} />);
185
188
  }