@kenyaemr/esm-appointments-app 7.0.3-pre.88 → 7.0.3-pre.94

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 (112) hide show
  1. package/.turbo/turbo-build.log +23 -22
  2. package/dist/130.js +1 -1
  3. package/dist/130.js.map +1 -1
  4. package/dist/23.js +2 -0
  5. package/dist/23.js.map +1 -0
  6. package/dist/265.js +1 -1
  7. package/dist/271.js +1 -1
  8. package/dist/319.js +1 -1
  9. package/dist/460.js +1 -1
  10. package/dist/529.js +1 -1
  11. package/dist/574.js +1 -1
  12. package/dist/581.js +1 -0
  13. package/dist/581.js.map +1 -0
  14. package/dist/644.js +1 -1
  15. package/dist/646.js +2 -0
  16. package/dist/646.js.map +1 -0
  17. package/dist/757.js +1 -1
  18. package/dist/788.js +1 -1
  19. package/dist/807.js +1 -1
  20. package/dist/833.js +1 -1
  21. package/dist/85.js +1 -0
  22. package/dist/85.js.map +1 -0
  23. package/dist/89.js +1 -0
  24. package/dist/89.js.map +1 -0
  25. package/dist/kenyaemr-esm-appointments-app.js +1 -1
  26. package/dist/kenyaemr-esm-appointments-app.js.buildmanifest.json +167 -143
  27. package/dist/kenyaemr-esm-appointments-app.js.map +1 -1
  28. package/dist/main.js +1 -1
  29. package/dist/main.js.map +1 -1
  30. package/dist/routes.json +1 -1
  31. package/package.json +1 -1
  32. package/src/admin/appointment-services/appointment-services.scss +5 -5
  33. package/src/appointments/appointment-tabs.scss +6 -7
  34. package/src/appointments/appointment-tabs.test.tsx +4 -11
  35. package/src/appointments/common-components/appointments-actions.test.tsx +121 -74
  36. package/src/appointments/common-components/appointments-table.scss +6 -6
  37. package/src/appointments/common-components/appointments-table.test.tsx +30 -32
  38. package/src/appointments/common-components/end-appointment.test.tsx +20 -19
  39. package/src/appointments/details/appointment-details.component.tsx +1 -1
  40. package/src/appointments/details/appointment-details.scss +13 -13
  41. package/src/appointments/details/appointment-details.test.tsx +49 -48
  42. package/src/appointments/scheduled/scheduled-appointments.component.tsx +1 -1
  43. package/src/appointments/scheduled/scheduled-appointments.scss +3 -1
  44. package/src/appointments/unscheduled/unscheduled-appointments.test.tsx +35 -37
  45. package/src/appointments.component.tsx +0 -1
  46. package/src/calendar/appointments-calendar-view-view.scss +3 -4
  47. package/src/calendar/appointments-calendar-view.test.tsx +1 -5
  48. package/src/calendar/header/calendar-header.scss +4 -4
  49. package/src/calendar/monthly/days-of-week.scss +1 -1
  50. package/src/calendar/monthly/monthly-view-workload.scss +10 -10
  51. package/src/config-schema.ts +88 -90
  52. package/src/empty-state/empty-state.scss +4 -4
  53. package/src/form/appointments-form.component.tsx +58 -26
  54. package/src/form/appointments-form.resource.ts +2 -2
  55. package/src/form/appointments-form.scss +11 -11
  56. package/src/form/appointments-form.test.tsx +42 -43
  57. package/src/header/appointments-header.scss +12 -12
  58. package/src/home/home-appointments.scss +0 -1
  59. package/src/homepage-tile/appointments-tile.component.tsx +23 -0
  60. package/src/homepage-tile/appointments-tile.scss +39 -0
  61. package/src/homepage-tile/appointments.resource.ts +15 -0
  62. package/src/hooks/useClinicalMetrics.ts +1 -1
  63. package/src/hooks/useDefaultLocation.ts +1 -1
  64. package/src/hooks/usePatientAppointmentHistory.ts +1 -1
  65. package/src/hooks/useProviders.ts +1 -1
  66. package/src/index.ts +5 -0
  67. package/src/metrics/appointments-metrics.scss +0 -1
  68. package/src/metrics/appointments-metrics.test.tsx +25 -31
  69. package/src/metrics/metrics-card.component.tsx +6 -33
  70. package/src/metrics/metrics-card.scss +8 -8
  71. package/src/metrics/metrics-header.scss +1 -1
  72. package/src/past-visit/past-visit.component.tsx +1 -1
  73. package/src/past-visit/past-visit.resource.ts +1 -1
  74. package/src/past-visit/past-visit.scss +19 -14
  75. package/src/patient-appointments/patient-appointments-action-menu.scss +6 -0
  76. package/src/patient-appointments/patient-appointments-base.component.tsx +6 -6
  77. package/src/patient-appointments/patient-appointments-base.scss +24 -29
  78. package/src/patient-appointments/patient-appointments-base.test.tsx +13 -11
  79. package/src/patient-appointments/patient-appointments-header.scss +4 -5
  80. package/src/patient-appointments/patient-appointments-overview.component.tsx +2 -2
  81. package/src/patient-appointments/patient-appointments-overview.scss +0 -1
  82. package/src/patient-appointments/patient-appointments.resource.ts +1 -1
  83. package/src/patient-appointments/patient-upcoming-appointments-card.component.tsx +3 -3
  84. package/src/patient-appointments/patient-upcoming-appointments-card.scss +11 -10
  85. package/src/patient-search/patient-search.scss +15 -14
  86. package/src/routes.json +5 -0
  87. package/src/types/index.ts +4 -0
  88. package/src/workload/monthly-view-workload/monthly-workload.scss +21 -6
  89. package/src/workload/monthly-view-workload/monthlyWorkCard.tsx +2 -2
  90. package/src/workload/workload.scss +3 -3
  91. package/translations/am.json +2 -0
  92. package/translations/ar.json +2 -0
  93. package/translations/en.json +2 -0
  94. package/translations/es.json +2 -0
  95. package/translations/fr.json +30 -28
  96. package/translations/he.json +2 -0
  97. package/translations/km.json +2 -0
  98. package/translations/zh.json +2 -0
  99. package/translations/zh_CN.json +2 -0
  100. package/dist/224.js +0 -1
  101. package/dist/224.js.map +0 -1
  102. package/dist/445.js +0 -2
  103. package/dist/445.js.map +0 -1
  104. package/dist/857.js +0 -2
  105. package/dist/857.js.map +0 -1
  106. package/dist/904.js +0 -1
  107. package/dist/904.js.map +0 -1
  108. package/src/root.scss +0 -50
  109. /package/dist/{857.js.LICENSE.txt → 23.js.LICENSE.txt} +0 -0
  110. /package/dist/{445.js.LICENSE.txt → 646.js.LICENSE.txt} +0 -0
  111. /package/src/helpers/{time.tsx → time.ts} +0 -0
  112. /package/src/patient-appointments/{patient-appointments-table.tsx → patient-appointments-table.component.tsx} +0 -0
package/dist/routes.json CHANGED
@@ -1 +1 @@
1
- {"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"webservices.rest":"^2.2.0"},"modals":[{"name":"end-appointment-modal","component":"endAppointmentModal"}],"extensions":[{"name":"home-appointments","slot":"homepage-widgets-slot","component":"homeAppointments","order":1},{"name":"clinical-appointments-dashboard-link","slot":"homepage-dashboard-slot","component":"appointmentsDashboardLink","meta":{"name":"appointments","slot":"clinical-appointments-dashboard-slot","title":"Appointments"}},{"component":"root","name":"clinical-appointments-dashboard","slot":"clinical-appointments-dashboard-slot"},{"name":"appointments-calendar-dashboard-link","slot":"calendar-dashboard-slot","component":"appointmentsCalendarDashboardLink"},{"name":"check-in-appointment-modal","slot":"todays-appointment-slot","component":"checkInModal"},{"name":"todays-appointments-dashboard","slot":"todays-appointment-slot","component":"homeAppointments"},{"name":"expected-appointments-panel","slot":"scheduled-appointments-panels-slot","component":"appointmentsList"},{"name":"checked-in-appointments-panel","slot":"scheduled-appointments-panels-slot","component":"appointmentsList"},{"name":"completed-appointments-panel","slot":"scheduled-appointments-panels-slot","component":"appointmentsList"},{"name":"missed-appointments-panel","slot":"scheduled-appointments-panels-slot","component":"appointmentsList"},{"name":"cancelled-appointments-panel","slot":"scheduled-appointments-panels-slot","component":"appointmentsList"},{"name":"early-appointments-panel","component":"earlyAppointments"},{"name":"appointments-form-workspace","component":"appointmentsFormWorkspace","meta":{"title":{"key":"createNewAppointment","default":"Create new appointment"}}},{"name":"patient-appointments-summary-dashboard","component":"patientAppointmentsSummaryDashboardLink","slot":"patient-chart-dashboard-slot","order":11,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-appointments-dashboard-slot","title":"Appointments","path":"Appointments"}},{"name":"patientAppointments-details-widget","component":"patientAppointmentsDetailedSummary","slot":"patient-chart-appointments-dashboard-slot","meta":{"columnSpan":1}},{"name":"patient-upcoming-appointment-widget","component":"patientUpcomingAppointmentsWidget","slot":"upcoming-appointment-slot"},{"name":"patient-appointment-cancel-confirmation-dialog","component":"patientAppointmentsCancelConfirmationDialog"},{"name":"edit-appointments-form","component":"appointementForm","meta":{"title":{"key":"editAppointment","default":"Edit Appointment"}}},{"name":"search-patient","component":"searchPatient"},{"name":"create-appointment","component":"appointementForm","meta":{"title":{"key":"appointmentForm","default":"Appointment Form"}}},{"name":"add-appointment","component":"appointementForm","meta":{"title":{"key":"createNewAppointment","default":"Create new appointment"}}}],"version":"7.0.3-pre.88"}
1
+ {"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"webservices.rest":"^2.2.0"},"modals":[{"name":"end-appointment-modal","component":"endAppointmentModal"}],"extensions":[{"name":"home-appointments","slot":"homepage-widgets-slot","component":"homeAppointments","order":1},{"name":"clinical-appointments-dashboard-link","slot":"homepage-dashboard-slot","component":"appointmentsDashboardLink","meta":{"name":"appointments","slot":"clinical-appointments-dashboard-slot","title":"Appointments"}},{"component":"root","name":"clinical-appointments-dashboard","slot":"clinical-appointments-dashboard-slot"},{"name":"appointments-calendar-dashboard-link","slot":"calendar-dashboard-slot","component":"appointmentsCalendarDashboardLink"},{"name":"check-in-appointment-modal","slot":"todays-appointment-slot","component":"checkInModal"},{"name":"todays-appointments-dashboard","slot":"todays-appointment-slot","component":"homeAppointments"},{"name":"expected-appointments-panel","slot":"scheduled-appointments-panels-slot","component":"appointmentsList"},{"name":"checked-in-appointments-panel","slot":"scheduled-appointments-panels-slot","component":"appointmentsList"},{"name":"completed-appointments-panel","slot":"scheduled-appointments-panels-slot","component":"appointmentsList"},{"name":"missed-appointments-panel","slot":"scheduled-appointments-panels-slot","component":"appointmentsList"},{"name":"cancelled-appointments-panel","slot":"scheduled-appointments-panels-slot","component":"appointmentsList"},{"name":"early-appointments-panel","component":"earlyAppointments"},{"name":"appointments-form-workspace","component":"appointmentsFormWorkspace","meta":{"title":{"key":"createNewAppointment","default":"Create new appointment"}}},{"name":"patient-appointments-summary-dashboard","component":"patientAppointmentsSummaryDashboardLink","slot":"patient-chart-dashboard-slot","order":11,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-appointments-dashboard-slot","title":"Appointments","path":"Appointments"}},{"name":"patientAppointments-details-widget","component":"patientAppointmentsDetailedSummary","slot":"patient-chart-appointments-dashboard-slot","meta":{"columnSpan":1}},{"name":"patient-upcoming-appointment-widget","component":"patientUpcomingAppointmentsWidget","slot":"upcoming-appointment-slot"},{"name":"patient-appointment-cancel-confirmation-dialog","component":"patientAppointmentsCancelConfirmationDialog"},{"name":"edit-appointments-form","component":"appointementForm","meta":{"title":{"key":"editAppointment","default":"Edit Appointment"}}},{"name":"search-patient","component":"searchPatient"},{"name":"create-appointment","component":"appointementForm","meta":{"title":{"key":"appointmentForm","default":"Appointment Form"}}},{"name":"add-appointment","component":"appointementForm","meta":{"title":{"key":"createNewAppointment","default":"Create new appointment"}}},{"name":"home-appointments-tile","slot":"home-metrics-tiles-slot","component":"homeAppointmentsTile"}],"version":"7.0.3-pre.94"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kenyaemr/esm-appointments-app",
3
- "version": "7.0.3-pre.88",
3
+ "version": "7.0.3-pre.94",
4
4
  "description": "Appointments front-end module for the OpenMRS SPA",
5
5
  "browser": "dist/kenyaemr-esm-appointments-app.js",
6
6
  "main": "src/index.ts",
@@ -1,10 +1,10 @@
1
- @use '@carbon/styles/scss/spacing';
1
+ @use '@carbon/layout';
2
2
 
3
3
  .appointmentServiceContainer {
4
- margin: spacing.$spacing-05 spacing.$spacing-05;
4
+ margin: layout.$spacing-05 layout.$spacing-05;
5
5
 
6
6
  & > div {
7
- padding: spacing.$spacing-03 0;
7
+ padding: layout.$spacing-03 0;
8
8
  }
9
9
  }
10
10
 
@@ -13,11 +13,11 @@
13
13
  bottom: 0;
14
14
  left: 0;
15
15
  right: 0;
16
- margin: 0 spacing.$spacing-05;
16
+ margin: 0 layout.$spacing-05;
17
17
  }
18
18
 
19
19
  .button {
20
- height: spacing.$spacing-10;
20
+ height: layout.$spacing-10;
21
21
  display: flex;
22
22
  align-content: flex-start;
23
23
  align-items: baseline;
@@ -1,10 +1,9 @@
1
- @use '@carbon/styles/scss/spacing';
2
- @use '@carbon/styles/scss/type';
3
1
  @use '@carbon/colors';
4
- @import '../root.scss';
2
+ @use '@carbon/layout';
3
+ @use '@openmrs/esm-styleguide/src/vars' as *;
5
4
 
6
5
  .appointmentList {
7
- margin: 1rem;
6
+ margin: layout.$spacing-05;
8
7
 
9
8
  & > div {
10
9
  background-color: $ui-02;
@@ -30,19 +29,19 @@
30
29
 
31
30
  .tabPanel {
32
31
  padding: 0;
33
- margin: 1rem;
32
+ margin: layout.$spacing-05;
34
33
  }
35
34
 
36
35
  .calendarButton {
37
36
  float: right;
38
37
  position: absolute;
39
38
  right: 0;
40
- height: spacing.$spacing-09;
39
+ height: layout.$spacing-09;
41
40
  min-height: 0;
42
41
  }
43
42
 
44
43
  .downloadButton {
45
- margin: spacing.$spacing-05;
44
+ margin: layout.$spacing-05;
46
45
  & > button {
47
46
  border: 1px solid colors.$blue-60;
48
47
  }
@@ -1,20 +1,17 @@
1
1
  import React from 'react';
2
2
  import { screen } from '@testing-library/react';
3
- import userEvent from '@testing-library/user-event';
4
- import { openmrsFetch } from '@openmrs/esm-framework';
3
+ import { type FetchResponse, openmrsFetch } from '@openmrs/esm-framework';
5
4
  import { renderWithSwr, waitForLoadingToFinish } from 'tools';
6
5
  import { mockAppointmentsData } from '__mocks__';
7
6
  import AppointmentTabs from './appointment-tabs.component';
8
7
 
9
- const mockOpenmrsFetch = openmrsFetch as jest.Mock;
8
+ const mockOpenmrsFetch = jest.mocked(openmrsFetch);
10
9
 
11
10
  describe('AppointmentTabs', () => {
12
11
  xit(`renders tabs showing different appointment lists`, async () => {
13
- const user = userEvent.setup();
12
+ mockOpenmrsFetch.mockResolvedValue({ ...mockAppointmentsData } as unknown as FetchResponse);
14
13
 
15
- mockOpenmrsFetch.mockReturnValueOnce({ data: mockAppointmentsData.data });
16
-
17
- renderAppointmentTabs();
14
+ renderWithSwr(<AppointmentTabs appointmentServiceType="" />);
18
15
 
19
16
  await waitForLoadingToFinish();
20
17
 
@@ -49,7 +46,3 @@ describe('AppointmentTabs', () => {
49
46
  });
50
47
  });
51
48
  });
52
-
53
- function renderAppointmentTabs() {
54
- renderWithSwr(<AppointmentTabs appointmentServiceType="" />);
55
- }
@@ -1,9 +1,10 @@
1
- import { render } from '@testing-library/react';
2
1
  import React from 'react';
3
- import AppointmentActions from './appointments-actions.component';
2
+ import { render, screen } from '@testing-library/react';
3
+ import { getDefaultsFromConfigSchema, useConfig } from '@openmrs/esm-framework';
4
4
  import { useTodaysVisits } from '../../hooks/useTodaysVisits';
5
+ import { type ConfigObject, configSchema } from '../../config-schema';
5
6
  import { type Appointment, AppointmentKind, AppointmentStatus } from '../../types';
6
- import { useConfig } from '@openmrs/esm-framework';
7
+ import AppointmentActions from './appointments-actions.component';
7
8
 
8
9
  const appointment: Appointment = {
9
10
  uuid: '7cd38a6d-377e-491b-8284-b04cf8b8c6d8',
@@ -46,137 +47,183 @@ const appointment: Appointment = {
46
47
  voided: false,
47
48
  teleconsultationLink: null,
48
49
  extensions: [],
50
+ endDateTime: null,
51
+ dateAppointmentScheduled: null,
49
52
  };
50
53
 
51
- jest.mock('../../hooks/useTodaysVisits', () => {
52
- const originalModule = jest.requireActual('../../hooks/useTodaysVisits');
54
+ const defaultProps = {
55
+ visits: [],
56
+ appointment: appointment,
57
+ scheduleType: 'Pending',
58
+ mutate: () => {},
59
+ };
53
60
 
54
- return {
55
- ...originalModule,
56
- useTodaysVisits: jest.fn(),
57
- };
58
- });
61
+ const mockUseConfig = jest.mocked(useConfig<ConfigObject>);
62
+ const mockUseTodaysVisits = jest.mocked(useTodaysVisits);
59
63
 
60
- jest.mock('@openmrs/esm-framework', () => {
61
- const originalModule = jest.requireActual('@openmrs/esm-framework');
62
- return {
63
- ...originalModule,
64
- useConfig: jest.fn(),
65
- };
66
- });
64
+ jest.mock('../../hooks/useTodaysVisits', () => ({
65
+ ...jest.requireActual('../../hooks/useTodaysVisits'),
66
+ useTodaysVisits: jest.fn(),
67
+ }));
67
68
 
68
69
  describe('AppointmentActions', () => {
69
- const defaultProps = {
70
- visits: [],
71
- appointment: appointment,
72
- scheduleType: 'Pending',
73
- mutate: () => {},
74
- };
75
-
76
70
  afterAll(() => {
77
71
  jest.useRealTimers();
78
72
  });
79
73
 
80
74
  it('renders the check in button when appointment is today and the patient has not checked in and check in button enabled', () => {
81
75
  appointment.status = AppointmentStatus.SCHEDULED;
82
- useConfig.mockImplementation(() => ({
83
- checkInButton: { enabled: true },
84
- checkOutButton: { enabled: true },
85
- }));
86
- useTodaysVisits.mockImplementation(() => ({
76
+
77
+ mockUseConfig.mockReturnValue({
78
+ ...getDefaultsFromConfigSchema(configSchema),
79
+ checkInButton: { enabled: true, showIfActiveVisit: false, customUrl: '' },
80
+ checkOutButton: { enabled: true, customUrl: '' },
81
+ });
82
+
83
+ mockUseTodaysVisits.mockReturnValue({
87
84
  visits: [],
88
- }));
85
+ error: null,
86
+ isLoading: false,
87
+ mutateVisit: jest.fn(),
88
+ });
89
+
89
90
  const props = { ...defaultProps };
90
- const { getByText } = render(<AppointmentActions {...props} />);
91
- const button = getByText(/check in/i);
92
- expect(button).toBeInTheDocument();
91
+ render(<AppointmentActions {...props} />);
92
+
93
+ expect(screen.getByText(/check in/i)).toBeInTheDocument();
93
94
  });
94
95
 
95
- it('does not renders the check in button when appointment is today and the patient has not checked in but the check-in button is disabled', () => {
96
+ it('does not render the check in button when appointment is today and the patient has not checked in but the check-in button is disabled', () => {
96
97
  appointment.status = AppointmentStatus.SCHEDULED;
97
- useConfig.mockImplementation(() => ({
98
- checkInButton: { enabled: false },
99
- checkOutButton: { enabled: true },
100
- }));
101
- useTodaysVisits.mockImplementation(() => ({
98
+
99
+ mockUseConfig.mockReturnValue({
100
+ ...getDefaultsFromConfigSchema(configSchema),
101
+ checkInButton: { enabled: false, showIfActiveVisit: false, customUrl: '' },
102
+ checkOutButton: { enabled: true, customUrl: '' },
103
+ });
104
+
105
+ mockUseTodaysVisits.mockReturnValue({
102
106
  visits: [],
103
- }));
107
+ error: null,
108
+ isLoading: false,
109
+ mutateVisit: jest.fn(),
110
+ });
111
+
104
112
  const props = { ...defaultProps };
105
- const { queryByText } = render(<AppointmentActions {...props} />);
106
- const button = queryByText('Check In');
107
- expect(button).not.toBeInTheDocument();
113
+ render(<AppointmentActions {...props} />);
114
+
115
+ expect(screen.queryByText(/check in/i)).not.toBeInTheDocument();
108
116
  });
109
117
 
110
118
  it('renders the checked out button when the patient has checked out', () => {
111
119
  appointment.status = AppointmentStatus.COMPLETED;
112
- useConfig.mockImplementation(() => ({
113
- checkInButton: { enabled: true },
114
- checkOutButton: { enabled: true },
115
- }));
116
- useTodaysVisits.mockImplementation(() => ({
120
+
121
+ mockUseConfig.mockReturnValue({
122
+ ...getDefaultsFromConfigSchema(configSchema),
123
+ checkInButton: { enabled: true, showIfActiveVisit: false, customUrl: '' },
124
+ checkOutButton: { enabled: true, customUrl: '' },
125
+ });
126
+
127
+ mockUseTodaysVisits.mockReturnValue({
117
128
  visits: [
118
129
  {
119
130
  patient: { uuid: '8673ee4f-e2ab-4077-ba55-4980f408773e' },
120
131
  startDatetime: new Date().toISOString(),
121
132
  stopDatetime: new Date().toISOString(),
133
+ uuid: '',
134
+ encounters: [],
135
+ visitType: {
136
+ uuid: '',
137
+ display: 'Facility Visit',
138
+ },
122
139
  },
123
140
  ],
124
- }));
141
+ error: null,
142
+ isLoading: false,
143
+ mutateVisit: jest.fn(),
144
+ });
145
+
125
146
  const props = { ...defaultProps };
126
- const { getByText } = render(<AppointmentActions {...props} />);
127
- const button = getByText('Checked out');
128
- expect(button).toBeInTheDocument();
147
+ render(<AppointmentActions {...props} />);
148
+
149
+ expect(screen.getByText('Checked out')).toBeInTheDocument();
129
150
  });
130
151
 
131
152
  it('renders the check out button when the patient has an active visit and today is the appointment date and the check out button enabled', () => {
132
153
  appointment.status = AppointmentStatus.CHECKEDIN;
133
- useConfig.mockImplementation(() => ({
134
- checkInButton: { enabled: true },
135
- checkOutButton: { enabled: true },
136
- }));
137
- useTodaysVisits.mockImplementation(() => ({
154
+
155
+ mockUseConfig.mockReturnValue({
156
+ ...getDefaultsFromConfigSchema(configSchema),
157
+ checkInButton: { enabled: true, showIfActiveVisit: false, customUrl: '' },
158
+ checkOutButton: { enabled: true, customUrl: '' },
159
+ });
160
+
161
+ mockUseTodaysVisits.mockReturnValue({
138
162
  visits: [
139
163
  {
140
164
  patient: { uuid: '8673ee4f-e2ab-4077-ba55-4980f408773e' },
141
165
  startDatetime: new Date().toISOString(),
142
166
  stopDatetime: null,
167
+ uuid: '',
168
+ encounters: [],
169
+ visitType: {
170
+ uuid: '',
171
+ display: 'Facility Visit',
172
+ },
143
173
  },
144
174
  ],
145
- }));
175
+ error: null,
176
+ isLoading: false,
177
+ mutateVisit: jest.fn(),
178
+ });
179
+
146
180
  const props = { ...defaultProps, scheduleType: 'Scheduled' };
147
- const { getByText } = render(<AppointmentActions {...props} />);
148
- const button = getByText('Check out');
149
- expect(button).toBeInTheDocument();
181
+ render(<AppointmentActions {...props} />);
182
+
183
+ expect(screen.getByText(/check out/i)).toBeInTheDocument();
150
184
  });
151
185
 
152
186
  it('does not render check out button when the patient has an active visit and today is the appointment date but the check out button is disabled', () => {
153
187
  appointment.status = AppointmentStatus.CHECKEDIN;
154
- useConfig.mockImplementation(() => ({
155
- checkInButton: { enabled: true },
156
- checkOutButton: { enabled: false },
157
- }));
158
- useTodaysVisits.mockImplementation(() => ({
188
+
189
+ mockUseConfig.mockReturnValue({
190
+ ...getDefaultsFromConfigSchema(configSchema),
191
+ checkInButton: { enabled: true, showIfActiveVisit: false, customUrl: '' },
192
+ checkOutButton: { enabled: false, customUrl: '' },
193
+ });
194
+
195
+ mockUseTodaysVisits.mockReturnValue({
159
196
  visits: [
160
197
  {
161
198
  patient: { uuid: '8673ee4f-e2ab-4077-ba55-4980f408773e' },
162
199
  startDatetime: new Date().toISOString(),
163
200
  stopDatetime: null,
201
+ uuid: '',
202
+ encounters: [],
203
+ visitType: {
204
+ uuid: '',
205
+ display: 'Facility Visit',
206
+ },
164
207
  },
165
208
  ],
166
- }));
209
+ error: null,
210
+ isLoading: false,
211
+ mutateVisit: jest.fn(),
212
+ });
213
+
167
214
  const props = { ...defaultProps, scheduleType: 'Scheduled' };
168
- const { queryByText } = render(<AppointmentActions {...props} />);
169
- const button = queryByText('Check out');
170
- expect(button).not.toBeInTheDocument();
215
+ render(<AppointmentActions {...props} />);
216
+
217
+ expect(screen.queryByText(/check out/i)).not.toBeInTheDocument();
171
218
  });
172
219
 
173
220
  // commenting these tests out as this functionality is not implemented yet so not sure how they would have ever passed?
174
221
  /*it('renders the correct button when today is the appointment date and the schedule type is pending', () => {
175
- useConfig.mockImplementation(() => ({
222
+ mockUseConfig.mockReturnValue({
176
223
  checkInButton: { enabled: true },
177
224
  checkOutButton: { enabled: true },
178
225
  }));
179
- useTodaysVisits.mockImplementation(() => ({
226
+ mockUseTodaysVisits.mockReturnValue({
180
227
  visits: [],
181
228
  }));
182
229
  const props = { ...defaultProps, scheduleType: 'Pending' };
@@ -186,11 +233,11 @@ describe('AppointmentActions', () => {
186
233
  });
187
234
 
188
235
  it('renders the correct button when today is the appointment date and the schedule type is not pending', () => {
189
- useConfig.mockImplementation(() => ({
236
+ mockUseConfig.mockReturnValue({
190
237
  checkInButton: { enabled: true },
191
238
  checkOutButton: { enabled: true },
192
239
  }));
193
- useTodaysVisits.mockImplementation(() => ({
240
+ mockUseTodaysVisits.mockReturnValue({
194
241
  visits: [],
195
242
  }));
196
243
  const props = { ...defaultProps, scheduleType: 'Confirmed' };
@@ -1,18 +1,18 @@
1
1
  @use '@carbon/colors';
2
2
  @use '@carbon/layout';
3
3
  @use '@carbon/type';
4
- @import '~@openmrs/esm-styleguide/src/vars';
4
+ @use '@openmrs/esm-styleguide/src/vars' as *;
5
5
 
6
6
  .expandedRow > td > div {
7
7
  max-height: max-content !important;
8
8
  }
9
9
 
10
10
  .expandedRow td {
11
- padding: 0 2rem;
11
+ padding: 0 layout.$spacing-07;
12
12
  }
13
13
 
14
14
  .expandedRow th[colspan] td[colspan] > div:first-child {
15
- padding: 0 1rem;
15
+ padding: 0 layout.$spacing-05;
16
16
  }
17
17
 
18
18
  .hiddenRow {
@@ -52,7 +52,7 @@
52
52
  &:after {
53
53
  content: '';
54
54
  display: block;
55
- width: 2rem;
55
+ width: layout.$spacing-07;
56
56
  padding-top: 3px;
57
57
  border-bottom: 0.375rem solid var(--brand-03);
58
58
  }
@@ -90,13 +90,13 @@
90
90
  .content {
91
91
  @include type.type-style('heading-compact-02');
92
92
  color: $text-02;
93
- margin-bottom: 0.5rem;
93
+ margin-bottom: layout.$spacing-03;
94
94
  }
95
95
 
96
96
  .tileContainer {
97
97
  background-color: $ui-02;
98
98
  border-top: 1px solid $ui-03;
99
- padding: 5rem 0;
99
+ padding: layout.$spacing-11 0;
100
100
  }
101
101
 
102
102
  .tile {
@@ -1,16 +1,23 @@
1
1
  import React from 'react';
2
2
  import userEvent from '@testing-library/user-event';
3
3
  import { render, screen } from '@testing-library/react';
4
- import { defineConfigSchema, getDefaultsFromConfigSchema, useConfig } from '@openmrs/esm-framework';
5
- import { type Appointment } from '../../types';
4
+ import { getDefaultsFromConfigSchema, useConfig, defineConfigSchema } from '@openmrs/esm-framework';
5
+ import { type ConfigObject, configSchema } from '../../config-schema';
6
+ import type { Appointment, AppointmentKind, AppointmentStatus } from '../../types';
6
7
  import { downloadAppointmentsAsExcel } from '../../helpers/excel';
8
+ import { getByTextWithMarkup } from 'tools';
7
9
  import AppointmentsTable from './appointments-table.component';
8
- import { configSchema } from '../../config-schema';
9
- import { getByTextWithMarkup } from '../../../../../tools/test-utils';
10
10
 
11
+ const defaultProps = {
12
+ appointments: [],
13
+ isLoading: false,
14
+ scheduleType: 'Scheduled',
15
+ tableHeading: 'scheduled',
16
+ visits: [],
17
+ };
11
18
  defineConfigSchema('@kenyaemr/esm-appointments-app', configSchema);
12
19
 
13
- const appointments: Array<Appointment> = [
20
+ const mockAppointments = [
14
21
  {
15
22
  uuid: '7cd38a6d-377e-491b-8284-b04cf8b8c6d8',
16
23
  appointmentNumber: '00001',
@@ -21,8 +28,6 @@ const appointments: Array<Appointment> = [
21
28
  uuid: '8673ee4f-e2ab-4077-ba55-4980f408773e',
22
29
  gender: 'M',
23
30
  age: '35',
24
- birthDate: '1986-04-03T00:00:00.000+0000',
25
- phoneNumber: '0700000000',
26
31
  },
27
32
  service: {
28
33
  appointmentServiceId: 1,
@@ -45,8 +50,8 @@ const appointments: Array<Appointment> = [
45
50
  },
46
51
  location: { name: 'HIV Clinic', uuid: '2131aff8-2e2a-480a-b7ab-4ac53250262b' },
47
52
  startDateTime: new Date().toISOString(),
48
- appointmentKind: 'WalkIn',
49
- status: 'Scheduled',
53
+ appointmentKind: 'WalkIn' as AppointmentKind,
54
+ status: 'Scheduled' as AppointmentStatus,
50
55
  comments: 'Some comments',
51
56
  additionalInfo: null,
52
57
  providers: [{ uuid: '24252571-dd5a-11e6-9d9c-0242ac150002', display: 'Dr James Cook' }],
@@ -55,34 +60,26 @@ const appointments: Array<Appointment> = [
55
60
  teleconsultationLink: null,
56
61
  extensions: [],
57
62
  },
58
- ];
63
+ ] as unknown as Array<Appointment>;
59
64
 
60
- const mockedDownloadAppointmentsAsExcel = downloadAppointmentsAsExcel as jest.Mock;
61
- const mockedUseConfig = useConfig as jest.Mock;
65
+ const mockDownloadAppointmentsAsExcel = jest.mocked(downloadAppointmentsAsExcel);
66
+ const mockUseConfig = jest.mocked(useConfig<ConfigObject>);
62
67
 
63
68
  jest.mock('../../helpers/excel');
64
69
  jest.mock('../../hooks/useOverlay');
65
70
 
66
71
  describe('AppointmentsTable', () => {
67
- const props = {
68
- appointments: [],
69
- isLoading: false,
70
- tableHeading: 'scheduled',
71
- visits: [],
72
- scheduleType: 'Scheduled',
73
- };
74
-
75
72
  beforeEach(() => {
76
- mockedUseConfig.mockReturnValue({
73
+ mockUseConfig.mockReturnValue({
77
74
  ...getDefaultsFromConfigSchema(configSchema),
78
75
  customPatientChartUrl: 'url-to-patient-chart',
79
- checkInButton: { enabled: false },
80
- checkOutButton: { enabled: false },
76
+ checkInButton: { enabled: false, showIfActiveVisit: false, customUrl: null },
77
+ checkOutButton: { enabled: false, customUrl: null },
81
78
  });
82
79
  });
83
80
 
84
81
  it('renders an empty state if appointments data is unavailable', async () => {
85
- render(<AppointmentsTable {...props} />);
82
+ renderAppointmentsTable();
86
83
 
87
84
  await screen.findByRole('heading', { name: /scheduled appointment/i });
88
85
 
@@ -90,13 +87,13 @@ describe('AppointmentsTable', () => {
90
87
  });
91
88
 
92
89
  it('renders a loading state when fetching data', () => {
93
- render(<AppointmentsTable {...props} isLoading={true} />);
90
+ renderAppointmentsTable({ isLoading: true });
94
91
 
95
92
  expect(screen.getByRole('progressbar')).toBeInTheDocument();
96
93
  });
97
94
 
98
95
  it('renders a tabular overview of the scheduled appointments', async () => {
99
- render(<AppointmentsTable {...props} appointments={appointments} />);
96
+ renderAppointmentsTable({ appointments: mockAppointments });
100
97
 
101
98
  await screen.findByRole('heading', { name: /scheduled appointment/i });
102
99
  expect(screen.getByRole('search', { name: /filter table/i })).toBeInTheDocument();
@@ -109,12 +106,10 @@ describe('AppointmentsTable', () => {
109
106
  it('updates the search string when the search input changes', async () => {
110
107
  const user = userEvent.setup();
111
108
 
112
- render(<AppointmentsTable {...props} appointments={appointments} />);
109
+ renderAppointmentsTable({ appointments: mockAppointments });
113
110
 
114
111
  await screen.findByRole('heading', { name: /scheduled appointment/i });
115
-
116
112
  const searchInput = screen.getByRole('searchbox');
117
-
118
113
  await user.type(searchInput, 'John');
119
114
  expect(searchInput).toHaveValue('John');
120
115
  });
@@ -122,13 +117,16 @@ describe('AppointmentsTable', () => {
122
117
  it('clicking the download button should download the scheduled appointments as an excel file', async () => {
123
118
  const user = userEvent.setup();
124
119
 
125
- render(<AppointmentsTable {...props} appointments={appointments} />);
120
+ renderAppointmentsTable({ appointments: mockAppointments });
126
121
 
127
122
  await screen.findByRole('heading', { name: /scheduled appointment/i });
128
123
  const downloadButton = screen.getByRole('button', { name: /download/i });
129
-
130
124
  await user.click(downloadButton);
131
125
  expect(downloadButton).toBeInTheDocument();
132
- expect(mockedDownloadAppointmentsAsExcel).toHaveBeenCalledWith(appointments, expect.anything());
126
+ expect(mockDownloadAppointmentsAsExcel).toHaveBeenCalledWith(mockAppointments, expect.anything());
133
127
  });
134
128
  });
129
+
130
+ function renderAppointmentsTable(props = {}) {
131
+ render(<AppointmentsTable {...defaultProps} {...props} />);
132
+ }