@openmrs/esm-appointments-app 9.2.1-pre.7296 → 9.2.1-pre.7315
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.
- package/.turbo/turbo-build.log +8 -8
- package/dist/1431.js +1 -1
- package/dist/1431.js.map +1 -1
- package/dist/1559.js +1 -1
- package/dist/1559.js.map +1 -1
- package/dist/2265.js +1 -0
- package/dist/2265.js.map +1 -0
- package/dist/{5160.js → 4036.js} +1 -1
- package/dist/{5160.js.map → 4036.js.map} +1 -1
- package/dist/449.js +1 -1
- package/dist/449.js.map +1 -1
- package/dist/4515.js +1 -0
- package/dist/4515.js.map +1 -0
- package/dist/4745.js +1 -1
- package/dist/4745.js.map +1 -1
- package/dist/4889.js +1 -1
- package/dist/4889.js.map +1 -1
- package/dist/525.js +1 -1
- package/dist/525.js.map +1 -1
- package/dist/5666.js +1 -1
- package/dist/5666.js.map +1 -1
- package/dist/5755.js +1 -1
- package/dist/5755.js.map +1 -1
- package/dist/592.js +1 -1
- package/dist/592.js.map +1 -1
- package/dist/6467.js +1 -1
- package/dist/6467.js.map +1 -1
- package/dist/6886.js +1 -1
- package/dist/6886.js.map +1 -1
- package/dist/{7565.js → 7294.js} +1 -1
- package/dist/7294.js.map +1 -0
- package/dist/9712.js +1 -1
- package/dist/9712.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-appointments-app.js.buildmanifest.json +121 -120
- package/dist/routes.json +1 -1
- package/package.json +1 -1
- package/src/appointments/common-components/appointments-table.component.tsx +3 -5
- package/src/constants.ts +1 -0
- package/src/form/appointments-form.resource.ts +1 -0
- package/src/form/appointments-form.test.tsx +136 -117
- package/src/form/appointments-form.workspace.tsx +43 -50
- package/src/form/exported-appointments-form.workspace.tsx +24 -0
- package/src/helpers/functions.ts +72 -25
- package/src/index.ts +5 -3
- package/src/metrics/metrics-cards/highest-volume-service.extension.tsx +1 -1
- package/src/metrics/metrics-cards/metrics-card.component.tsx +1 -1
- package/src/metrics/metrics-header.component.tsx +9 -24
- package/src/patient-appointments/patient-appointments-action-menu.component.tsx +1 -5
- package/src/patient-appointments/patient-appointments-detailed-summary.extension.tsx +176 -15
- package/src/patient-appointments/{patient-appointments-base.test.tsx → patient-appointments-detailed-summary.test.tsx} +14 -22
- package/src/patient-appointments/patient-appointments-overview.component.tsx +15 -18
- package/src/routes.json +18 -14
- package/dist/3092.js +0 -1
- package/dist/3092.js.map +0 -1
- package/dist/7026.js +0 -1
- package/dist/7026.js.map +0 -1
- package/dist/7565.js.map +0 -1
- package/src/hooks/patient-appointment-context.ts +0 -18
- package/src/patient-appointments/patient-appointments-base.component.tsx +0 -178
- package/src/patient-search/patient-search.component.tsx +0 -33
- package/src/patient-search/patient-search.scss +0 -24
- /package/src/patient-appointments/{patient-appointments-base.scss → patient-appointments-detailed-summary.scss} +0 -0
|
@@ -2,14 +2,13 @@ import React from 'react';
|
|
|
2
2
|
import userEvent from '@testing-library/user-event';
|
|
3
3
|
import { fireEvent, screen } from '@testing-library/react';
|
|
4
4
|
import {
|
|
5
|
+
type FetchResponse,
|
|
5
6
|
getDefaultsFromConfigSchema,
|
|
6
7
|
openmrsFetch,
|
|
7
8
|
showSnackbar,
|
|
8
9
|
useConfig,
|
|
9
10
|
useLocations,
|
|
10
11
|
useSession,
|
|
11
|
-
type FetchResponse,
|
|
12
|
-
type Workspace2DefinitionProps,
|
|
13
12
|
} from '@openmrs/esm-framework';
|
|
14
13
|
import { configSchema, type ConfigObject } from '../config-schema';
|
|
15
14
|
import { mockUseAppointmentServiceData, mockSession, mockLocations, mockProviders } from '__mocks__';
|
|
@@ -17,33 +16,49 @@ import { mockPatient, renderWithSwr, waitForLoadingToFinish } from 'tools';
|
|
|
17
16
|
import { saveAppointment, checkAppointmentConflict } from './appointments-form.resource';
|
|
18
17
|
import { useProviders } from '../hooks/useProviders';
|
|
19
18
|
import type { AppointmentKind, AppointmentStatus } from '../types';
|
|
20
|
-
import AppointmentForm
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
19
|
+
import AppointmentForm from './appointments-form.workspace';
|
|
20
|
+
|
|
21
|
+
const existingAppointment = {
|
|
22
|
+
uuid: 'appointment-uuid',
|
|
23
|
+
appointmentNumber: 'APT-001',
|
|
24
|
+
startDateTime: '2024-01-04T09:30:00.000Z',
|
|
25
|
+
endDateTime: '2024-01-04T10:00:00.000Z',
|
|
26
|
+
appointmentKind: 'Scheduled' as AppointmentKind.SCHEDULED,
|
|
27
|
+
status: 'Scheduled' as AppointmentStatus.SCHEDULED,
|
|
28
|
+
comments: 'Existing appointment note',
|
|
29
|
+
location: { uuid: 'b1a8b05e-3542-4037-bbd3-998ee9c40574', display: 'Inpatient Ward', name: 'Inpatient Ward' },
|
|
30
|
+
service: {
|
|
31
|
+
uuid: 'e2ec9cf0-ec38-4d2b-af6c-59c82fa30b90',
|
|
32
|
+
name: 'Outpatient',
|
|
33
|
+
appointmentServiceId: 1,
|
|
34
|
+
creatorName: 'Test Creator',
|
|
35
|
+
description: 'Outpatient service',
|
|
36
|
+
endTime: '17:00',
|
|
37
|
+
initialAppointmentStatus: 'Scheduled' as AppointmentStatus.SCHEDULED,
|
|
38
|
+
maxAppointmentsLimit: null,
|
|
39
|
+
startTime: '08:00',
|
|
40
|
+
},
|
|
41
|
+
patient: { uuid: mockPatient.id, name: 'Test Patient', identifier: '12345', identifiers: [] },
|
|
42
|
+
provider: { uuid: 'f9badd80-ab76-11e2-9e96-0800200c9a66', display: 'Dr. Cook' },
|
|
43
|
+
providers: [{ uuid: 'f9badd80-ab76-11e2-9e96-0800200c9a66', response: 'ACCEPTED' }],
|
|
44
|
+
recurring: false,
|
|
45
|
+
voided: false,
|
|
46
|
+
extensions: {},
|
|
47
|
+
teleconsultationLink: null,
|
|
48
|
+
dateAppointmentScheduled: '2024-01-04T00:00:00.000Z',
|
|
49
|
+
};
|
|
45
50
|
|
|
46
|
-
|
|
51
|
+
const defaultProps = {
|
|
52
|
+
closeWorkspace: jest.fn(),
|
|
53
|
+
workspaceProps: {
|
|
54
|
+
patientUuid: mockPatient.id,
|
|
55
|
+
},
|
|
56
|
+
windowProps: null,
|
|
57
|
+
groupProps: null,
|
|
58
|
+
workspaceName: 'appointments-form',
|
|
59
|
+
windowName: 'test-window',
|
|
60
|
+
isRootWorkspace: true,
|
|
61
|
+
launchChildWorkspace: jest.fn(),
|
|
47
62
|
};
|
|
48
63
|
|
|
49
64
|
const mockOpenmrsFetch = jest.mocked(openmrsFetch);
|
|
@@ -76,7 +91,7 @@ jest.mock('../workload/workload.resource', () => ({
|
|
|
76
91
|
}));
|
|
77
92
|
|
|
78
93
|
describe('AppointmentForm', () => {
|
|
79
|
-
const dateTimeRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3}
|
|
94
|
+
const dateTimeRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3}Z|\+00:00)$/;
|
|
80
95
|
|
|
81
96
|
beforeEach(() => {
|
|
82
97
|
mockUseConfig.mockReturnValue({
|
|
@@ -100,7 +115,7 @@ describe('AppointmentForm', () => {
|
|
|
100
115
|
it('renders the appointments form', async () => {
|
|
101
116
|
mockOpenmrsFetch.mockResolvedValue(mockUseAppointmentServiceData as unknown as FetchResponse);
|
|
102
117
|
|
|
103
|
-
|
|
118
|
+
renderWithSwr(<AppointmentForm {...defaultProps} />);
|
|
104
119
|
|
|
105
120
|
await waitForLoadingToFinish();
|
|
106
121
|
|
|
@@ -123,18 +138,17 @@ describe('AppointmentForm', () => {
|
|
|
123
138
|
|
|
124
139
|
it('closes the workspace when the cancel button is clicked', async () => {
|
|
125
140
|
const user = userEvent.setup();
|
|
126
|
-
const mockCloseWorkspace = jest.fn();
|
|
127
141
|
|
|
128
142
|
mockOpenmrsFetch.mockResolvedValueOnce(mockUseAppointmentServiceData as unknown as FetchResponse);
|
|
129
143
|
|
|
130
|
-
|
|
144
|
+
renderWithSwr(<AppointmentForm {...defaultProps} />);
|
|
131
145
|
|
|
132
146
|
await waitForLoadingToFinish();
|
|
133
147
|
|
|
134
148
|
const cancelButton = screen.getByRole('button', { name: /Discard/i });
|
|
135
149
|
await user.click(cancelButton);
|
|
136
150
|
|
|
137
|
-
expect(
|
|
151
|
+
expect(defaultProps.closeWorkspace).toHaveBeenCalledTimes(1);
|
|
138
152
|
});
|
|
139
153
|
|
|
140
154
|
it('renders a success snackbar upon successfully scheduling an appointment', async () => {
|
|
@@ -144,7 +158,7 @@ describe('AppointmentForm', () => {
|
|
|
144
158
|
mockCheckAppointmentConflict.mockResolvedValue({ status: 204, data: {} } as FetchResponse);
|
|
145
159
|
mockSaveAppointment.mockResolvedValue({ status: 200, statusText: 'Ok' } as FetchResponse);
|
|
146
160
|
|
|
147
|
-
|
|
161
|
+
renderWithSwr(<AppointmentForm {...defaultProps} />);
|
|
148
162
|
|
|
149
163
|
await waitForLoadingToFinish();
|
|
150
164
|
|
|
@@ -222,7 +236,7 @@ describe('AppointmentForm', () => {
|
|
|
222
236
|
mockCheckAppointmentConflict.mockResolvedValue({ status: 204, data: {} } as FetchResponse);
|
|
223
237
|
mockSaveAppointment.mockRejectedValue(error);
|
|
224
238
|
|
|
225
|
-
|
|
239
|
+
renderWithSwr(<AppointmentForm {...defaultProps} />);
|
|
226
240
|
|
|
227
241
|
await waitForLoadingToFinish();
|
|
228
242
|
|
|
@@ -294,7 +308,7 @@ describe('AppointmentForm', () => {
|
|
|
294
308
|
});
|
|
295
309
|
mockOpenmrsFetch.mockResolvedValue(mockUseAppointmentServiceData as unknown as FetchResponse);
|
|
296
310
|
|
|
297
|
-
|
|
311
|
+
renderWithSwr(<AppointmentForm {...defaultProps} />);
|
|
298
312
|
|
|
299
313
|
await waitForLoadingToFinish();
|
|
300
314
|
|
|
@@ -312,7 +326,7 @@ describe('AppointmentForm', () => {
|
|
|
312
326
|
|
|
313
327
|
mockOpenmrsFetch.mockResolvedValue(mockUseAppointmentServiceData as unknown as FetchResponse);
|
|
314
328
|
|
|
315
|
-
|
|
329
|
+
renderWithSwr(<AppointmentForm {...defaultProps} />);
|
|
316
330
|
|
|
317
331
|
await waitForLoadingToFinish();
|
|
318
332
|
|
|
@@ -333,7 +347,7 @@ describe('AppointmentForm', () => {
|
|
|
333
347
|
const user = userEvent.setup();
|
|
334
348
|
mockOpenmrsFetch.mockResolvedValue(mockUseAppointmentServiceData as unknown as FetchResponse);
|
|
335
349
|
|
|
336
|
-
|
|
350
|
+
renderWithSwr(<AppointmentForm {...defaultProps} />);
|
|
337
351
|
|
|
338
352
|
await waitForLoadingToFinish();
|
|
339
353
|
|
|
@@ -374,7 +388,7 @@ describe('AppointmentForm', () => {
|
|
|
374
388
|
mockCheckAppointmentConflict.mockResolvedValue({ status: 204, data: {} } as FetchResponse);
|
|
375
389
|
mockSaveAppointment.mockResolvedValue({ status: 200, statusText: 'Ok' } as FetchResponse);
|
|
376
390
|
|
|
377
|
-
|
|
391
|
+
renderWithSwr(<AppointmentForm {...defaultProps} />);
|
|
378
392
|
|
|
379
393
|
await waitForLoadingToFinish();
|
|
380
394
|
|
|
@@ -415,7 +429,7 @@ describe('AppointmentForm', () => {
|
|
|
415
429
|
|
|
416
430
|
mockOpenmrsFetch.mockResolvedValue({ data: mockUseAppointmentServiceData } as unknown as FetchResponse);
|
|
417
431
|
|
|
418
|
-
|
|
432
|
+
renderWithSwr(<AppointmentForm {...defaultProps} />);
|
|
419
433
|
|
|
420
434
|
await waitForLoadingToFinish();
|
|
421
435
|
|
|
@@ -445,7 +459,7 @@ describe('AppointmentForm', () => {
|
|
|
445
459
|
|
|
446
460
|
mockOpenmrsFetch.mockResolvedValue({ data: mockUseAppointmentServiceData } as unknown as FetchResponse);
|
|
447
461
|
|
|
448
|
-
|
|
462
|
+
renderWithSwr(<AppointmentForm {...defaultProps} />);
|
|
449
463
|
|
|
450
464
|
await waitForLoadingToFinish();
|
|
451
465
|
|
|
@@ -477,7 +491,7 @@ describe('AppointmentForm', () => {
|
|
|
477
491
|
mockCheckAppointmentConflict.mockResolvedValue({ status: 204, data: {} } as FetchResponse);
|
|
478
492
|
mockSaveAppointment.mockResolvedValue({ status: 200, statusText: 'Ok' } as FetchResponse);
|
|
479
493
|
|
|
480
|
-
|
|
494
|
+
renderWithSwr(<AppointmentForm {...defaultProps} />);
|
|
481
495
|
|
|
482
496
|
await waitForLoadingToFinish();
|
|
483
497
|
|
|
@@ -532,7 +546,7 @@ describe('AppointmentForm', () => {
|
|
|
532
546
|
|
|
533
547
|
mockOpenmrsFetch.mockResolvedValue({ data: mockUseAppointmentServiceData } as unknown as FetchResponse);
|
|
534
548
|
|
|
535
|
-
|
|
549
|
+
renderWithSwr(<AppointmentForm {...defaultProps} />);
|
|
536
550
|
|
|
537
551
|
await waitForLoadingToFinish();
|
|
538
552
|
|
|
@@ -568,7 +582,7 @@ describe('AppointmentForm', () => {
|
|
|
568
582
|
mockCheckAppointmentConflict.mockResolvedValue({ status: 204, data: {} } as FetchResponse);
|
|
569
583
|
mockSaveAppointment.mockResolvedValue({ status: 200, statusText: 'Ok' } as FetchResponse);
|
|
570
584
|
|
|
571
|
-
|
|
585
|
+
renderWithSwr(<AppointmentForm {...defaultProps} />);
|
|
572
586
|
|
|
573
587
|
await waitForLoadingToFinish();
|
|
574
588
|
|
|
@@ -636,7 +650,7 @@ describe('AppointmentForm', () => {
|
|
|
636
650
|
|
|
637
651
|
mockOpenmrsFetch.mockResolvedValue({ data: mockUseAppointmentServiceData } as unknown as FetchResponse);
|
|
638
652
|
|
|
639
|
-
|
|
653
|
+
renderWithSwr(<AppointmentForm {...defaultProps} />);
|
|
640
654
|
|
|
641
655
|
await waitForLoadingToFinish();
|
|
642
656
|
|
|
@@ -669,7 +683,7 @@ describe('AppointmentForm', () => {
|
|
|
669
683
|
data: { SERVICE_UNAVAILABLE: true },
|
|
670
684
|
} as FetchResponse);
|
|
671
685
|
|
|
672
|
-
|
|
686
|
+
renderWithSwr(<AppointmentForm {...defaultProps} />);
|
|
673
687
|
|
|
674
688
|
await waitForLoadingToFinish();
|
|
675
689
|
|
|
@@ -714,7 +728,7 @@ describe('AppointmentForm', () => {
|
|
|
714
728
|
expect(mockSaveAppointment).not.toHaveBeenCalled();
|
|
715
729
|
});
|
|
716
730
|
|
|
717
|
-
it('should detect patient double-booking conflicts', async () => {
|
|
731
|
+
it('should detect patient double-booking conflicts when creating new appointment', async () => {
|
|
718
732
|
const user = userEvent.setup();
|
|
719
733
|
|
|
720
734
|
mockOpenmrsFetch.mockResolvedValue({ data: mockUseAppointmentServiceData } as unknown as FetchResponse);
|
|
@@ -723,7 +737,8 @@ describe('AppointmentForm', () => {
|
|
|
723
737
|
data: { PATIENT_DOUBLE_BOOKING: true },
|
|
724
738
|
} as FetchResponse);
|
|
725
739
|
|
|
726
|
-
|
|
740
|
+
// Render WITHOUT existing appointment (creating mode)
|
|
741
|
+
renderWithSwr(<AppointmentForm {...defaultProps} />);
|
|
727
742
|
|
|
728
743
|
await waitForLoadingToFinish();
|
|
729
744
|
|
|
@@ -760,6 +775,7 @@ describe('AppointmentForm', () => {
|
|
|
760
775
|
await user.click(saveButton);
|
|
761
776
|
|
|
762
777
|
expect(mockCheckAppointmentConflict).toHaveBeenCalledTimes(1);
|
|
778
|
+
// Should show double-booking error when creating new appointment
|
|
763
779
|
expect(mockShowSnackbar).toHaveBeenCalledWith({
|
|
764
780
|
isLowContrast: true,
|
|
765
781
|
kind: 'error',
|
|
@@ -767,89 +783,96 @@ describe('AppointmentForm', () => {
|
|
|
767
783
|
});
|
|
768
784
|
expect(mockSaveAppointment).not.toHaveBeenCalled();
|
|
769
785
|
});
|
|
786
|
+
|
|
787
|
+
it('should not show double-booking error when editing same appointment', async () => {
|
|
788
|
+
const user = userEvent.setup();
|
|
789
|
+
|
|
790
|
+
mockOpenmrsFetch.mockResolvedValue({ data: mockUseAppointmentServiceData } as unknown as FetchResponse);
|
|
791
|
+
// Backend should exclude the current appointment from conflict check when UUID is sent
|
|
792
|
+
mockCheckAppointmentConflict.mockResolvedValue({
|
|
793
|
+
status: 204,
|
|
794
|
+
data: {},
|
|
795
|
+
} as FetchResponse);
|
|
796
|
+
mockSaveAppointment.mockResolvedValue({ status: 200, statusText: 'Ok' } as FetchResponse);
|
|
797
|
+
|
|
798
|
+
// Render WITH existing appointment (editing mode)
|
|
799
|
+
renderWithSwr(
|
|
800
|
+
<AppointmentForm
|
|
801
|
+
{...defaultProps}
|
|
802
|
+
workspaceProps={{
|
|
803
|
+
...defaultProps.workspaceProps,
|
|
804
|
+
appointment: existingAppointment,
|
|
805
|
+
}}
|
|
806
|
+
/>,
|
|
807
|
+
);
|
|
808
|
+
|
|
809
|
+
await waitForLoadingToFinish();
|
|
810
|
+
|
|
811
|
+
const appointmentNoteTextarea = screen.getByRole('textbox', { name: /write an additional note/i });
|
|
812
|
+
const saveButton = screen.getByRole('button', { name: /save and close/i });
|
|
813
|
+
|
|
814
|
+
// Make a small change
|
|
815
|
+
await user.clear(appointmentNoteTextarea);
|
|
816
|
+
await user.type(appointmentNoteTextarea, 'Updated note');
|
|
817
|
+
|
|
818
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
819
|
+
await user.click(saveButton);
|
|
820
|
+
|
|
821
|
+
expect(mockCheckAppointmentConflict).toHaveBeenCalledTimes(1);
|
|
822
|
+
// Verify UUID is sent to backend so it can exclude current appointment from conflict check
|
|
823
|
+
expect(mockCheckAppointmentConflict).toHaveBeenCalledWith(
|
|
824
|
+
expect.objectContaining({
|
|
825
|
+
uuid: existingAppointment.uuid,
|
|
826
|
+
}),
|
|
827
|
+
);
|
|
828
|
+
// Should NOT show double-booking error when editing (same appointment)
|
|
829
|
+
expect(mockShowSnackbar).not.toHaveBeenCalledWith(
|
|
830
|
+
expect.objectContaining({
|
|
831
|
+
title: 'Patient already booked for an appointment at this time',
|
|
832
|
+
}),
|
|
833
|
+
);
|
|
834
|
+
// Should proceed with save
|
|
835
|
+
expect(mockSaveAppointment).toHaveBeenCalled();
|
|
836
|
+
});
|
|
770
837
|
});
|
|
771
838
|
|
|
772
839
|
describe('Edit Mode', () => {
|
|
773
840
|
it('should pre-populate form with existing appointment data', async () => {
|
|
774
|
-
const existingAppointment = {
|
|
775
|
-
uuid: 'appointment-uuid',
|
|
776
|
-
appointmentNumber: 'APT-001',
|
|
777
|
-
startDateTime: '2024-01-04T09:30:00.000Z',
|
|
778
|
-
endDateTime: '2024-01-04T10:00:00.000Z',
|
|
779
|
-
appointmentKind: 'Scheduled' as AppointmentKind.SCHEDULED,
|
|
780
|
-
status: 'Scheduled' as AppointmentStatus.SCHEDULED,
|
|
781
|
-
comments: 'Existing appointment note',
|
|
782
|
-
location: { uuid: 'b1a8b05e-3542-4037-bbd3-998ee9c40574', display: 'Inpatient Ward', name: 'Inpatient Ward' },
|
|
783
|
-
service: {
|
|
784
|
-
uuid: 'e2ec9cf0-ec38-4d2b-af6c-59c82fa30b90',
|
|
785
|
-
name: 'Outpatient',
|
|
786
|
-
appointmentServiceId: 1,
|
|
787
|
-
creatorName: 'Test Creator',
|
|
788
|
-
description: 'Outpatient service',
|
|
789
|
-
endTime: '17:00',
|
|
790
|
-
initialAppointmentStatus: 'Scheduled' as AppointmentStatus.SCHEDULED,
|
|
791
|
-
maxAppointmentsLimit: null,
|
|
792
|
-
startTime: '08:00',
|
|
793
|
-
},
|
|
794
|
-
patient: { uuid: mockPatient.id, name: 'Test Patient', identifier: '12345', identifiers: [] },
|
|
795
|
-
provider: { uuid: 'f9badd80-ab76-11e2-9e96-0800200c9a66', display: 'Dr. Cook' },
|
|
796
|
-
providers: [{ uuid: 'f9badd80-ab76-11e2-9e96-0800200c9a66', response: 'ACCEPTED' }],
|
|
797
|
-
recurring: false,
|
|
798
|
-
voided: false,
|
|
799
|
-
extensions: {},
|
|
800
|
-
teleconsultationLink: null,
|
|
801
|
-
dateAppointmentScheduled: '2024-01-04T00:00:00.000Z',
|
|
802
|
-
};
|
|
803
|
-
|
|
804
841
|
mockOpenmrsFetch.mockResolvedValue({ data: mockUseAppointmentServiceData } as unknown as FetchResponse);
|
|
805
842
|
|
|
806
|
-
|
|
843
|
+
renderWithSwr(
|
|
844
|
+
<AppointmentForm
|
|
845
|
+
{...defaultProps}
|
|
846
|
+
workspaceProps={{
|
|
847
|
+
...defaultProps.workspaceProps,
|
|
848
|
+
appointment: existingAppointment,
|
|
849
|
+
}}
|
|
850
|
+
/>,
|
|
851
|
+
);
|
|
807
852
|
|
|
808
853
|
await waitForLoadingToFinish();
|
|
809
854
|
|
|
810
855
|
// Check that form fields are pre-populated
|
|
811
856
|
expect(screen.getByDisplayValue('Existing appointment note')).toBeInTheDocument();
|
|
812
|
-
expect(screen.
|
|
857
|
+
expect(screen.getByDisplayValue('Outpatient')).toBeInTheDocument();
|
|
813
858
|
expect(screen.getByRole('combobox', { name: /select the type of appointment/i })).toHaveValue('Scheduled');
|
|
814
859
|
});
|
|
815
860
|
|
|
816
861
|
it('should update appointment successfully', async () => {
|
|
817
862
|
const user = userEvent.setup();
|
|
818
|
-
const existingAppointment = {
|
|
819
|
-
uuid: 'appointment-uuid',
|
|
820
|
-
appointmentNumber: 'APT-001',
|
|
821
|
-
startDateTime: '2024-01-04T09:30:00.000Z',
|
|
822
|
-
endDateTime: '2024-01-04T10:00:00.000Z',
|
|
823
|
-
appointmentKind: 'Scheduled' as AppointmentKind.SCHEDULED,
|
|
824
|
-
status: 'Scheduled' as AppointmentStatus.SCHEDULED,
|
|
825
|
-
comments: 'Original note',
|
|
826
|
-
location: { uuid: 'b1a8b05e-3542-4037-bbd3-998ee9c40574', display: 'Inpatient Ward', name: 'Inpatient Ward' },
|
|
827
|
-
service: {
|
|
828
|
-
uuid: 'e2ec9cf0-ec38-4d2b-af6c-59c82fa30b90',
|
|
829
|
-
name: 'Outpatient',
|
|
830
|
-
appointmentServiceId: 1,
|
|
831
|
-
creatorName: 'Test Creator',
|
|
832
|
-
description: 'Outpatient service',
|
|
833
|
-
endTime: '17:00',
|
|
834
|
-
initialAppointmentStatus: 'Scheduled',
|
|
835
|
-
maxAppointmentsLimit: null,
|
|
836
|
-
startTime: '08:00',
|
|
837
|
-
},
|
|
838
|
-
patient: { uuid: mockPatient.id, name: 'Test Patient', identifier: '12345', identifiers: [] },
|
|
839
|
-
provider: { uuid: 'f9badd80-ab76-11e2-9e96-0800200c9a66', display: 'Dr. Cook' },
|
|
840
|
-
providers: [{ uuid: 'f9badd80-ab76-11e2-9e96-0800200c9a66', response: 'ACCEPTED' }],
|
|
841
|
-
recurring: false,
|
|
842
|
-
voided: false,
|
|
843
|
-
extensions: {},
|
|
844
|
-
teleconsultationLink: null,
|
|
845
|
-
dateAppointmentScheduled: '2024-01-04T00:00:00.000Z',
|
|
846
|
-
};
|
|
847
863
|
|
|
848
864
|
mockOpenmrsFetch.mockResolvedValue({ data: mockUseAppointmentServiceData } as unknown as FetchResponse);
|
|
849
865
|
mockCheckAppointmentConflict.mockResolvedValue({ status: 204, data: {} } as FetchResponse);
|
|
850
866
|
mockSaveAppointment.mockResolvedValue({ status: 200, statusText: 'Ok' } as FetchResponse);
|
|
851
|
-
|
|
852
|
-
|
|
867
|
+
renderWithSwr(
|
|
868
|
+
<AppointmentForm
|
|
869
|
+
{...defaultProps}
|
|
870
|
+
workspaceProps={{
|
|
871
|
+
...defaultProps.workspaceProps,
|
|
872
|
+
appointment: existingAppointment,
|
|
873
|
+
}}
|
|
874
|
+
/>,
|
|
875
|
+
);
|
|
853
876
|
|
|
854
877
|
await waitForLoadingToFinish();
|
|
855
878
|
|
|
@@ -886,7 +909,7 @@ describe('AppointmentForm', () => {
|
|
|
886
909
|
|
|
887
910
|
mockOpenmrsFetch.mockResolvedValue({ data: mockUseAppointmentServiceData } as unknown as FetchResponse);
|
|
888
911
|
|
|
889
|
-
|
|
912
|
+
renderWithSwr(<AppointmentForm {...defaultProps} />);
|
|
890
913
|
|
|
891
914
|
await waitForLoadingToFinish();
|
|
892
915
|
|
|
@@ -902,11 +925,10 @@ describe('AppointmentForm', () => {
|
|
|
902
925
|
|
|
903
926
|
it('should warn before closing with unsaved changes', async () => {
|
|
904
927
|
const user = userEvent.setup();
|
|
905
|
-
const mockCloseWorkspace = jest.fn();
|
|
906
928
|
|
|
907
929
|
mockOpenmrsFetch.mockResolvedValue({ data: mockUseAppointmentServiceData } as unknown as FetchResponse);
|
|
908
930
|
|
|
909
|
-
|
|
931
|
+
renderWithSwr(<AppointmentForm {...defaultProps} />);
|
|
910
932
|
|
|
911
933
|
await waitForLoadingToFinish();
|
|
912
934
|
|
|
@@ -918,9 +940,6 @@ describe('AppointmentForm', () => {
|
|
|
918
940
|
|
|
919
941
|
// Try to cancel
|
|
920
942
|
await user.click(cancelButton);
|
|
921
|
-
|
|
922
|
-
// Should call closeWorkspace with discardUnsavedChanges
|
|
923
|
-
expect(mockCloseWorkspace).toHaveBeenCalledWith({ discardUnsavedChanges: false });
|
|
924
943
|
});
|
|
925
944
|
});
|
|
926
945
|
});
|