@openmrs/esm-billing-app 1.0.2-pre.764 → 1.0.2-pre.768
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/.eslintrc +16 -2
- package/dist/942.js +1 -1
- package/dist/942.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-billing-app.js.buildmanifest.json +6 -6
- package/dist/routes.json +1 -1
- package/e2e/core/test.ts +1 -1
- package/e2e/fixtures/api.ts +1 -1
- package/e2e/support/github/Dockerfile +1 -1
- package/package.json +4 -1
- package/src/bills-table/bills-table.test.tsx +1 -1
- package/src/invoice/invoice-table.component.tsx +1 -1
- package/src/invoice/invoice-table.test.tsx +267 -29
- package/src/invoice/invoice.test.tsx +315 -85
- package/src/invoice/payments/payment-form/payment-form.test.tsx +4 -2
- package/src/invoice/payments/payments.test.tsx +2 -2
- package/src/left-panel-link.test.tsx +1 -4
|
@@ -1,68 +1,51 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import userEvent from '@testing-library/user-event';
|
|
3
|
-
import { screen,
|
|
3
|
+
import { render, screen, waitFor } from '@testing-library/react';
|
|
4
4
|
import { useReactToPrint } from 'react-to-print';
|
|
5
5
|
import { getDefaultsFromConfigSchema, useConfig, usePatient } from '@openmrs/esm-framework';
|
|
6
6
|
import { configSchema, type BillingConfig } from '../config-schema';
|
|
7
7
|
import { mockBill, mockPatient } from '../../__mocks__/bills.mock';
|
|
8
|
-
import { useBill
|
|
8
|
+
import { useBill } from '../billing.resource';
|
|
9
9
|
import { usePaymentModes } from './payments/payment.resource';
|
|
10
10
|
import Invoice from './invoice.component';
|
|
11
11
|
|
|
12
12
|
const mockUseConfig = jest.mocked(useConfig<BillingConfig>);
|
|
13
|
+
const mockUseBill = jest.mocked(useBill);
|
|
14
|
+
const mockUsePatient = jest.mocked(usePatient);
|
|
15
|
+
const mockUsePaymentModes = jest.mocked(usePaymentModes);
|
|
16
|
+
const mockUseReactToPrint = jest.mocked(useReactToPrint);
|
|
13
17
|
|
|
14
|
-
// Mock convertToCurrency
|
|
15
18
|
jest.mock('../helpers/functions', () => ({
|
|
16
19
|
convertToCurrency: jest.fn((amount) => `USD ${amount}`),
|
|
17
20
|
}));
|
|
18
21
|
|
|
19
|
-
// Set window.i18next
|
|
20
22
|
window.i18next = {
|
|
21
23
|
language: 'en',
|
|
22
24
|
} as any;
|
|
23
25
|
|
|
24
|
-
// Mock InvoiceTable component
|
|
25
|
-
jest.mock('./invoice-table.component', () =>
|
|
26
|
-
jest.fn(({ bill }) => <div data-testid="mock-invoice-table">Invoice Table Mock</div>),
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
// Mock payments component
|
|
30
|
-
jest.mock('./payments/payments.component', () =>
|
|
31
|
-
jest.fn(({ bill, mutate, selectedLineItems }) => (
|
|
32
|
-
<div data-testid="mock-payments">
|
|
33
|
-
<h2>Payments</h2>
|
|
34
|
-
<button>Add payment option</button>
|
|
35
|
-
</div>
|
|
36
|
-
)),
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
// Mock PrintReceipt component
|
|
40
26
|
jest.mock('./printable-invoice/print-receipt.component', () =>
|
|
41
|
-
jest.fn((
|
|
27
|
+
jest.fn(() => <div data-testid="mock-print-receipt">Print Receipt Mock</div>),
|
|
42
28
|
);
|
|
43
29
|
|
|
44
|
-
// Mock PrintableInvoice component
|
|
45
30
|
jest.mock('./printable-invoice/printable-invoice.component', () =>
|
|
46
|
-
jest.fn((
|
|
31
|
+
jest.fn(() => <div data-testid="mock-printable-invoice">Printable Invoice Mock</div>),
|
|
47
32
|
);
|
|
48
33
|
|
|
49
|
-
// Mock payment resource
|
|
50
34
|
jest.mock('./payments/payment.resource', () => ({
|
|
51
35
|
usePaymentModes: jest.fn(),
|
|
52
36
|
updateBillVisitAttribute: jest.fn(),
|
|
53
37
|
}));
|
|
54
38
|
|
|
55
|
-
// Mock billing resource
|
|
56
39
|
jest.mock('../billing.resource', () => ({
|
|
57
40
|
useBill: jest.fn(),
|
|
58
|
-
processBillPayment: jest.fn(),
|
|
59
41
|
useDefaultFacility: jest.fn().mockReturnValue({
|
|
60
|
-
|
|
61
|
-
|
|
42
|
+
data: {
|
|
43
|
+
uuid: '54065383-b4d4-42d2-af4d-d250a1fd2590',
|
|
44
|
+
display: 'MTRH',
|
|
45
|
+
},
|
|
62
46
|
}),
|
|
63
47
|
}));
|
|
64
48
|
|
|
65
|
-
// Mock react-router-dom
|
|
66
49
|
jest.mock('react-router-dom', () => ({
|
|
67
50
|
useParams: jest.fn().mockReturnValue({
|
|
68
51
|
patientUuid: 'patientUuid',
|
|
@@ -70,18 +53,11 @@ jest.mock('react-router-dom', () => ({
|
|
|
70
53
|
}),
|
|
71
54
|
}));
|
|
72
55
|
|
|
73
|
-
// Mock react-to-print
|
|
74
56
|
jest.mock('react-to-print', () => ({
|
|
75
57
|
useReactToPrint: jest.fn(),
|
|
76
58
|
}));
|
|
77
59
|
|
|
78
60
|
describe('Invoice', () => {
|
|
79
|
-
const mockedBill = useBill as jest.Mock;
|
|
80
|
-
const mockedPatient = usePatient as jest.Mock;
|
|
81
|
-
const mockedProcessBillPayment = processBillPayment as jest.Mock;
|
|
82
|
-
const mockedUsePaymentModes = usePaymentModes as jest.Mock;
|
|
83
|
-
const mockedUseReactToPrint = useReactToPrint as jest.Mock;
|
|
84
|
-
|
|
85
61
|
const defaultBillData = {
|
|
86
62
|
...mockBill,
|
|
87
63
|
uuid: 'test-uuid',
|
|
@@ -97,12 +73,20 @@ describe('Invoice', () => {
|
|
|
97
73
|
quantity: 1,
|
|
98
74
|
price: 1000,
|
|
99
75
|
paymentStatus: 'PENDING',
|
|
76
|
+
billableService: 'Test Service',
|
|
77
|
+
display: '',
|
|
78
|
+
voided: false,
|
|
79
|
+
voidReason: '',
|
|
80
|
+
priceName: '',
|
|
81
|
+
priceUuid: '',
|
|
82
|
+
lineItemOrder: 0,
|
|
83
|
+
resourceVersion: '',
|
|
100
84
|
},
|
|
101
85
|
],
|
|
102
86
|
};
|
|
103
87
|
|
|
104
88
|
beforeEach(() => {
|
|
105
|
-
|
|
89
|
+
mockUseBill.mockReturnValue({
|
|
106
90
|
bill: defaultBillData,
|
|
107
91
|
isLoading: false,
|
|
108
92
|
error: null,
|
|
@@ -110,15 +94,14 @@ describe('Invoice', () => {
|
|
|
110
94
|
mutate: jest.fn(),
|
|
111
95
|
});
|
|
112
96
|
|
|
113
|
-
|
|
114
|
-
patient: mockPatient,
|
|
97
|
+
mockUsePatient.mockReturnValue({
|
|
98
|
+
patient: mockPatient as any,
|
|
115
99
|
isLoading: false,
|
|
116
100
|
error: null,
|
|
117
|
-
|
|
118
|
-
mutate: jest.fn(),
|
|
101
|
+
patientUuid: 'patientUuid',
|
|
119
102
|
});
|
|
120
103
|
|
|
121
|
-
|
|
104
|
+
mockUsePaymentModes.mockReturnValue({
|
|
122
105
|
paymentModes: [
|
|
123
106
|
{ uuid: 'cash-uuid', name: 'Cash', description: 'Cash Method', retired: false },
|
|
124
107
|
{ uuid: 'mpesa-uuid', name: 'MPESA', description: 'MPESA Method', retired: false },
|
|
@@ -130,42 +113,75 @@ describe('Invoice', () => {
|
|
|
130
113
|
|
|
131
114
|
mockUseConfig.mockReturnValue({ ...getDefaultsFromConfigSchema(configSchema), defaultCurrency: 'USD' });
|
|
132
115
|
|
|
133
|
-
// Setup print handler mock
|
|
134
116
|
const printHandler = jest.fn();
|
|
135
|
-
|
|
117
|
+
mockUseReactToPrint.mockReturnValue(printHandler);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('should render loading state when bill is loading', () => {
|
|
121
|
+
mockUseBill.mockReturnValue({
|
|
122
|
+
bill: null,
|
|
123
|
+
isLoading: true,
|
|
124
|
+
error: null,
|
|
125
|
+
isValidating: false,
|
|
126
|
+
mutate: jest.fn(),
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
render(<Invoice />);
|
|
130
|
+
expect(screen.getByText(/loading bill information/i)).toBeInTheDocument();
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('should render loading state when patient is loading', () => {
|
|
134
|
+
mockUsePatient.mockReturnValue({
|
|
135
|
+
patient: null as any,
|
|
136
|
+
isLoading: true,
|
|
137
|
+
error: null,
|
|
138
|
+
patientUuid: 'patientUuid',
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
render(<Invoice />);
|
|
142
|
+
expect(screen.getByText(/loading bill information/i)).toBeInTheDocument();
|
|
136
143
|
});
|
|
137
144
|
|
|
138
|
-
it('should render error state
|
|
139
|
-
|
|
145
|
+
it('should render error state when bill fails to load', () => {
|
|
146
|
+
mockUseBill.mockReturnValue({
|
|
140
147
|
bill: null,
|
|
141
148
|
isLoading: false,
|
|
142
|
-
error: new Error('
|
|
149
|
+
error: new Error('Failed to load bill'),
|
|
143
150
|
isValidating: false,
|
|
144
151
|
mutate: jest.fn(),
|
|
145
152
|
});
|
|
146
153
|
|
|
147
154
|
render(<Invoice />);
|
|
148
|
-
expect(screen.getByText(/
|
|
149
|
-
expect(screen.getByText(/Error/)).toBeInTheDocument();
|
|
155
|
+
expect(screen.getByText(/invoice error/i)).toBeInTheDocument();
|
|
150
156
|
});
|
|
151
157
|
|
|
152
158
|
it('should render invoice details correctly', () => {
|
|
153
159
|
render(<Invoice />);
|
|
154
160
|
|
|
155
|
-
|
|
156
|
-
expect(screen.
|
|
157
|
-
expect(screen.getByText(/
|
|
158
|
-
expect(screen.getByText(/
|
|
159
|
-
expect(screen.getByText(/
|
|
160
|
-
expect(screen.
|
|
161
|
+
expect(screen.getAllByText(/total amount/i).length).toBeGreaterThan(0);
|
|
162
|
+
expect(screen.getAllByText(/amount tendered/i).length).toBeGreaterThan(0);
|
|
163
|
+
expect(screen.getByText(/invoice number/i)).toBeInTheDocument();
|
|
164
|
+
expect(screen.getByText(/date and time/i)).toBeInTheDocument();
|
|
165
|
+
expect(screen.getByText(/invoice status/i)).toBeInTheDocument();
|
|
166
|
+
expect(screen.getAllByText('RCPT-001').length).toBeGreaterThan(0);
|
|
167
|
+
expect(screen.getAllByText('PENDING').length).toBeGreaterThan(0);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('should render invoice table with line items', () => {
|
|
171
|
+
render(<Invoice />);
|
|
161
172
|
|
|
162
|
-
|
|
163
|
-
expect(screen.
|
|
164
|
-
|
|
173
|
+
expect(screen.getByText(/line items/i)).toBeInTheDocument();
|
|
174
|
+
expect(screen.getByText('Test Service')).toBeInTheDocument();
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('should render payments section', () => {
|
|
178
|
+
render(<Invoice />);
|
|
179
|
+
|
|
180
|
+
expect(screen.getByText(/payments/i)).toBeInTheDocument();
|
|
165
181
|
});
|
|
166
182
|
|
|
167
183
|
it('should show print receipt button for paid bills', () => {
|
|
168
|
-
|
|
184
|
+
mockUseBill.mockReturnValue({
|
|
169
185
|
bill: {
|
|
170
186
|
...defaultBillData,
|
|
171
187
|
status: 'PAID',
|
|
@@ -181,66 +197,280 @@ describe('Invoice', () => {
|
|
|
181
197
|
expect(screen.getByTestId('mock-print-receipt')).toBeInTheDocument();
|
|
182
198
|
});
|
|
183
199
|
|
|
184
|
-
it('should
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
200
|
+
it('should show print receipt button for bills with tendered amount', () => {
|
|
201
|
+
mockUseBill.mockReturnValue({
|
|
202
|
+
bill: {
|
|
203
|
+
...defaultBillData,
|
|
204
|
+
status: 'PENDING',
|
|
205
|
+
tenderedAmount: 500,
|
|
206
|
+
},
|
|
190
207
|
isLoading: false,
|
|
191
208
|
error: null,
|
|
192
209
|
isValidating: false,
|
|
193
|
-
mutate:
|
|
210
|
+
mutate: jest.fn(),
|
|
194
211
|
});
|
|
195
212
|
|
|
196
|
-
|
|
213
|
+
render(<Invoice />);
|
|
214
|
+
expect(screen.getByTestId('mock-print-receipt')).toBeInTheDocument();
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it('should not show print receipt button for unpaid bills', () => {
|
|
218
|
+
render(<Invoice />);
|
|
219
|
+
expect(screen.queryByTestId('mock-print-receipt')).not.toBeInTheDocument();
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
it('should handle print button click', async () => {
|
|
223
|
+
const handlePrintMock = jest.fn();
|
|
224
|
+
const user = userEvent.setup();
|
|
225
|
+
mockUseReactToPrint.mockReturnValue(handlePrintMock);
|
|
197
226
|
|
|
198
227
|
render(<Invoice />);
|
|
199
228
|
|
|
200
|
-
|
|
201
|
-
|
|
229
|
+
const printButton = screen.getByRole('button', { name: /print bill/i });
|
|
230
|
+
await user.click(printButton);
|
|
202
231
|
|
|
203
|
-
|
|
232
|
+
await waitFor(() => {
|
|
233
|
+
expect(handlePrintMock).toHaveBeenCalled();
|
|
234
|
+
});
|
|
204
235
|
});
|
|
205
236
|
|
|
206
|
-
it('should
|
|
207
|
-
|
|
237
|
+
it('should disable print button while printing', () => {
|
|
238
|
+
render(<Invoice />);
|
|
208
239
|
|
|
209
|
-
|
|
210
|
-
|
|
240
|
+
const printButton = screen.getByRole('button', { name: /print bill/i });
|
|
241
|
+
expect(printButton).toBeEnabled();
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
it('should render patient header when patient data is available', () => {
|
|
245
|
+
render(<Invoice />);
|
|
246
|
+
|
|
247
|
+
// Patient header is rendered via ExtensionSlot
|
|
248
|
+
expect(screen.getByText(/line items/i)).toBeInTheDocument();
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it('should search and filter line items in the table', async () => {
|
|
252
|
+
const billWithMultipleItems = {
|
|
211
253
|
...defaultBillData,
|
|
212
254
|
lineItems: [
|
|
213
|
-
|
|
255
|
+
{
|
|
256
|
+
uuid: 'item-1',
|
|
257
|
+
item: 'Lab Test',
|
|
258
|
+
quantity: 1,
|
|
259
|
+
price: 500,
|
|
260
|
+
paymentStatus: 'PENDING',
|
|
261
|
+
billableService: 'Lab Test',
|
|
262
|
+
display: '',
|
|
263
|
+
voided: false,
|
|
264
|
+
voidReason: '',
|
|
265
|
+
priceName: '',
|
|
266
|
+
priceUuid: '',
|
|
267
|
+
lineItemOrder: 0,
|
|
268
|
+
resourceVersion: '',
|
|
269
|
+
},
|
|
214
270
|
{
|
|
215
271
|
uuid: 'item-2',
|
|
216
|
-
item: '
|
|
272
|
+
item: 'X-Ray',
|
|
217
273
|
quantity: 1,
|
|
218
274
|
price: 500,
|
|
219
275
|
paymentStatus: 'PENDING',
|
|
276
|
+
billableService: 'X-Ray',
|
|
277
|
+
display: '',
|
|
278
|
+
voided: false,
|
|
279
|
+
voidReason: '',
|
|
280
|
+
priceName: '',
|
|
281
|
+
priceUuid: '',
|
|
282
|
+
lineItemOrder: 1,
|
|
283
|
+
resourceVersion: '',
|
|
220
284
|
},
|
|
221
285
|
],
|
|
222
286
|
};
|
|
223
287
|
|
|
224
|
-
|
|
225
|
-
bill:
|
|
288
|
+
mockUseBill.mockReturnValue({
|
|
289
|
+
bill: billWithMultipleItems,
|
|
226
290
|
isLoading: false,
|
|
227
291
|
error: null,
|
|
228
292
|
isValidating: false,
|
|
229
293
|
mutate: jest.fn(),
|
|
230
294
|
});
|
|
231
295
|
|
|
296
|
+
const user = userEvent.setup();
|
|
297
|
+
render(<Invoice />);
|
|
298
|
+
|
|
299
|
+
expect(screen.getByText('Lab Test')).toBeInTheDocument();
|
|
300
|
+
expect(screen.getByText('X-Ray')).toBeInTheDocument();
|
|
301
|
+
|
|
302
|
+
const searchInput = screen.getByPlaceholderText(/search this table/i);
|
|
303
|
+
await user.type(searchInput, 'Lab Test');
|
|
304
|
+
|
|
305
|
+
await waitFor(() => {
|
|
306
|
+
expect(screen.getByText('Lab Test')).toBeInTheDocument();
|
|
307
|
+
expect(screen.queryByText('X-Ray')).not.toBeInTheDocument();
|
|
308
|
+
});
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
it('should handle bill data updates via mutate', () => {
|
|
312
|
+
const mockMutate = jest.fn();
|
|
313
|
+
mockUseBill.mockReturnValue({
|
|
314
|
+
bill: defaultBillData,
|
|
315
|
+
isLoading: false,
|
|
316
|
+
error: null,
|
|
317
|
+
isValidating: false,
|
|
318
|
+
mutate: mockMutate,
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
const { rerender } = render(<Invoice />);
|
|
322
|
+
|
|
323
|
+
const updatedBill = {
|
|
324
|
+
...defaultBillData,
|
|
325
|
+
status: 'PAID',
|
|
326
|
+
tenderedAmount: 1000,
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
mockUseBill.mockReturnValue({
|
|
330
|
+
bill: updatedBill,
|
|
331
|
+
isLoading: false,
|
|
332
|
+
error: null,
|
|
333
|
+
isValidating: false,
|
|
334
|
+
mutate: mockMutate,
|
|
335
|
+
});
|
|
336
|
+
|
|
232
337
|
rerender(<Invoice />);
|
|
233
338
|
|
|
234
|
-
|
|
235
|
-
|
|
339
|
+
expect(screen.getByText('PAID')).toBeInTheDocument();
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
it('should display correct currency formatting', () => {
|
|
343
|
+
render(<Invoice />);
|
|
344
|
+
|
|
345
|
+
// convertToCurrency is mocked to return "USD ${amount}"
|
|
346
|
+
expect(screen.getAllByText('USD 1000').length).toBeGreaterThan(0);
|
|
347
|
+
expect(screen.getAllByText('USD 0').length).toBeGreaterThan(0);
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
it('should disable print button when isPrinting state is true', () => {
|
|
351
|
+
// Mock isPrinting state by checking the button's disabled state when loading
|
|
352
|
+
mockUseBill.mockReturnValue({
|
|
353
|
+
bill: defaultBillData,
|
|
354
|
+
isLoading: true,
|
|
355
|
+
error: null,
|
|
356
|
+
isValidating: false,
|
|
357
|
+
mutate: jest.fn(),
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
render(<Invoice />);
|
|
361
|
+
// When bill is loading, component shows loading state, not the button
|
|
362
|
+
expect(screen.getByText(/loading bill information/i)).toBeInTheDocument();
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
it('should not render PrintableInvoice when bill is missing', () => {
|
|
366
|
+
mockUseBill.mockReturnValue({
|
|
367
|
+
bill: null,
|
|
368
|
+
isLoading: false,
|
|
369
|
+
error: null,
|
|
370
|
+
isValidating: false,
|
|
371
|
+
mutate: jest.fn(),
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
mockUsePatient.mockReturnValue({
|
|
375
|
+
patient: mockPatient as any,
|
|
376
|
+
isLoading: false,
|
|
377
|
+
error: null,
|
|
378
|
+
patientUuid: 'patientUuid',
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
render(<Invoice />);
|
|
382
|
+
|
|
383
|
+
// PrintableInvoice should not be rendered when bill is null
|
|
384
|
+
// Since it's in a hidden div, we can't easily assert its absence
|
|
385
|
+
// but we can verify the main content doesn't have the print container
|
|
386
|
+
expect(screen.queryByTestId('mock-printable-invoice')).not.toBeInTheDocument();
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
it('should not render PrintableInvoice when patient is missing', () => {
|
|
390
|
+
mockUsePatient.mockReturnValue({
|
|
391
|
+
patient: null as any,
|
|
392
|
+
isLoading: false,
|
|
393
|
+
error: null,
|
|
394
|
+
patientUuid: 'patientUuid',
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
render(<Invoice />);
|
|
398
|
+
|
|
399
|
+
// PrintableInvoice requires both bill and patient
|
|
400
|
+
expect(screen.queryByTestId('mock-printable-invoice')).not.toBeInTheDocument();
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
it('should render PrintableInvoice when both bill and patient exist', () => {
|
|
404
|
+
render(<Invoice />);
|
|
405
|
+
|
|
406
|
+
// PrintableInvoice should be rendered with both bill and patient
|
|
407
|
+
expect(screen.getByTestId('mock-printable-invoice')).toBeInTheDocument();
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
it('should pass correct props to InvoiceTable', () => {
|
|
411
|
+
render(<Invoice />);
|
|
412
|
+
|
|
413
|
+
// Verify InvoiceTable is rendered with line items
|
|
414
|
+
expect(screen.getByText('Test Service')).toBeInTheDocument();
|
|
415
|
+
expect(screen.getByText(/line items/i)).toBeInTheDocument();
|
|
236
416
|
});
|
|
237
417
|
|
|
238
|
-
it('should
|
|
418
|
+
it('should pass mutate function to Payments component', () => {
|
|
419
|
+
const mockMutate = jest.fn();
|
|
420
|
+
mockUseBill.mockReturnValue({
|
|
421
|
+
bill: defaultBillData,
|
|
422
|
+
isLoading: false,
|
|
423
|
+
error: null,
|
|
424
|
+
isValidating: false,
|
|
425
|
+
mutate: mockMutate,
|
|
426
|
+
});
|
|
427
|
+
|
|
239
428
|
render(<Invoice />);
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
expect(screen.getByText(
|
|
429
|
+
|
|
430
|
+
// Payments component should be rendered
|
|
431
|
+
expect(screen.getByText(/payments/i)).toBeInTheDocument();
|
|
243
432
|
});
|
|
244
433
|
|
|
245
|
-
|
|
434
|
+
it('should show print receipt for bills with partial payment', () => {
|
|
435
|
+
mockUseBill.mockReturnValue({
|
|
436
|
+
bill: {
|
|
437
|
+
...defaultBillData,
|
|
438
|
+
status: 'PENDING',
|
|
439
|
+
totalAmount: 1000,
|
|
440
|
+
tenderedAmount: 500, // Partial payment
|
|
441
|
+
},
|
|
442
|
+
isLoading: false,
|
|
443
|
+
error: null,
|
|
444
|
+
isValidating: false,
|
|
445
|
+
mutate: jest.fn(),
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
render(<Invoice />);
|
|
449
|
+
expect(screen.getByTestId('mock-print-receipt')).toBeInTheDocument();
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
it('should render ExtensionSlot when patient and patientUuid exist', () => {
|
|
453
|
+
render(<Invoice />);
|
|
454
|
+
|
|
455
|
+
// The component renders, which includes the ExtensionSlot
|
|
456
|
+
// We can verify this indirectly by checking the main content is present
|
|
457
|
+
expect(screen.getByText(/invoice number/i)).toBeInTheDocument();
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
it('should not show print receipt for bills with zero tendered amount', () => {
|
|
461
|
+
mockUseBill.mockReturnValue({
|
|
462
|
+
bill: {
|
|
463
|
+
...defaultBillData,
|
|
464
|
+
status: 'PENDING',
|
|
465
|
+
tenderedAmount: 0,
|
|
466
|
+
},
|
|
467
|
+
isLoading: false,
|
|
468
|
+
error: null,
|
|
469
|
+
isValidating: false,
|
|
470
|
+
mutate: jest.fn(),
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
render(<Invoice />);
|
|
474
|
+
expect(screen.queryByTestId('mock-print-receipt')).not.toBeInTheDocument();
|
|
475
|
+
});
|
|
246
476
|
});
|
|
@@ -34,13 +34,15 @@ describe('PaymentForm Component', () => {
|
|
|
34
34
|
mutate: jest.fn(),
|
|
35
35
|
});
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
render(
|
|
38
38
|
<Wrapper>
|
|
39
39
|
<PaymentForm disablePayment={false} isSingleLineItem={false} />
|
|
40
40
|
</Wrapper>,
|
|
41
41
|
);
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
// When loading, payment method elements should not be present
|
|
44
|
+
expect(screen.queryByText(/select payment method/i)).not.toBeInTheDocument();
|
|
45
|
+
expect(screen.queryByPlaceholderText(/enter amount/i)).not.toBeInTheDocument();
|
|
44
46
|
});
|
|
45
47
|
|
|
46
48
|
test('should render error message when payment modes fail to load', () => {
|
|
@@ -226,7 +226,7 @@ describe('Payments', () => {
|
|
|
226
226
|
|
|
227
227
|
it('should return null when bill is not provided', () => {
|
|
228
228
|
const { container } = render(<Payments bill={null} mutate={mockMutate} />);
|
|
229
|
-
expect(container
|
|
229
|
+
expect(container).toBeEmptyDOMElement();
|
|
230
230
|
});
|
|
231
231
|
|
|
232
232
|
it('should render add payment method button for bills with amount due', () => {
|
|
@@ -241,7 +241,7 @@ describe('Payments', () => {
|
|
|
241
241
|
|
|
242
242
|
// Verify add payment method button is available
|
|
243
243
|
expect(screen.getByText(/add payment method/i)).toBeInTheDocument();
|
|
244
|
-
expect(screen.getByText(/add payment method/i)).
|
|
244
|
+
expect(screen.getByText(/add payment method/i)).toBeEnabled();
|
|
245
245
|
});
|
|
246
246
|
|
|
247
247
|
it('should display process payment button', () => {
|
|
@@ -23,7 +23,6 @@ describe('LinkExtension Component', () => {
|
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
describe('createLeftPanelLink Function', () => {
|
|
26
|
-
const user = userEvent.setup();
|
|
27
26
|
test('returns a component that renders LinkExtension', () => {
|
|
28
27
|
const config = { name: 'billing', title: 'Billing' };
|
|
29
28
|
const TestComponent = createLeftPanelLink(config);
|
|
@@ -31,8 +30,6 @@ describe('createLeftPanelLink Function', () => {
|
|
|
31
30
|
render(<TestComponent />);
|
|
32
31
|
expect(screen.getByText('Billing')).toBeInTheDocument();
|
|
33
32
|
const testLink = screen.getByRole('link', { name: 'Billing' });
|
|
34
|
-
|
|
35
|
-
expect(window.location.pathname).toBe('/billing/6eb8d678-514d-46ad-9554-51e48d96d567');
|
|
36
|
-
// expect(testLink).toHaveClass('active-left-nav-link');
|
|
33
|
+
expect(testLink).toHaveAttribute('href', '/openmrs/spa/home/billing');
|
|
37
34
|
});
|
|
38
35
|
});
|