@openmrs/esm-billing-app 1.1.2-pre.9 → 1.2.0
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/cache/31f1dfc7f71601df-meta.json +1 -0
- package/.turbo/cache/31f1dfc7f71601df.tar.zst +0 -0
- package/.turbo/turbo-build.log +13 -42
- package/__mocks__/bills.mock.ts +3 -2
- package/dist/1480.js +1 -0
- package/dist/1480.js.map +1 -0
- package/dist/1564.js +1 -0
- package/dist/1564.js.map +1 -0
- package/dist/1578.js +1 -0
- package/dist/1578.js.map +1 -0
- package/dist/1646.js +1 -0
- package/dist/1646.js.map +1 -0
- package/dist/1869.js +1 -0
- package/dist/1869.js.map +1 -0
- package/dist/1877.js +1 -0
- package/dist/1877.js.map +1 -0
- package/dist/1899.js +1 -0
- package/dist/1899.js.map +1 -0
- package/dist/196.js +2 -0
- package/dist/196.js.map +1 -0
- package/dist/2250.js +43 -0
- package/dist/2250.js.map +1 -0
- package/dist/2269.js +1 -0
- package/dist/2269.js.map +1 -0
- package/dist/2317.js +1 -0
- package/dist/2317.js.map +1 -0
- package/dist/2416.js +1 -0
- package/dist/2416.js.map +1 -0
- package/dist/2489.js +1 -0
- package/dist/2489.js.map +1 -0
- package/dist/282.js +1 -0
- package/dist/282.js.map +1 -0
- package/dist/2881.js +1 -0
- package/dist/2881.js.map +1 -0
- package/dist/2997.js +1 -0
- package/dist/2997.js.map +1 -0
- package/dist/3378.js +1 -0
- package/dist/3378.js.map +1 -0
- package/dist/3379.js +1 -0
- package/dist/3379.js.map +1 -0
- package/dist/3784.js +1 -0
- package/dist/3784.js.map +1 -0
- package/dist/3963.js +1 -0
- package/dist/3963.js.map +1 -0
- package/dist/4106.js +1 -0
- package/dist/4106.js.map +1 -0
- package/dist/4111.js +1 -0
- package/dist/4111.js.map +1 -0
- package/dist/434.js +1 -0
- package/dist/434.js.map +1 -0
- package/dist/4348.js +1 -0
- package/dist/4348.js.map +1 -0
- package/dist/4383.js +1 -0
- package/dist/4383.js.map +1 -0
- package/dist/4658.js +1 -0
- package/dist/4658.js.map +1 -0
- package/dist/4870.js +1 -0
- package/dist/4870.js.map +1 -0
- package/dist/4928.js +1 -0
- package/dist/4928.js.map +1 -0
- package/dist/5098.js +1 -0
- package/dist/5098.js.map +1 -0
- package/dist/5117.js +1 -0
- package/dist/5117.js.map +1 -0
- package/dist/5132.js +1 -0
- package/dist/5132.js.map +1 -0
- package/dist/5145.js +1 -0
- package/dist/5145.js.map +1 -0
- package/dist/5390.js +1 -0
- package/dist/5390.js.map +1 -0
- package/dist/5503.js +1 -0
- package/dist/5503.js.map +1 -0
- package/dist/556.js +1 -0
- package/dist/556.js.map +1 -0
- package/dist/5644.js +1 -0
- package/dist/5644.js.map +1 -0
- package/dist/5898.js +1 -0
- package/dist/5898.js.map +1 -0
- package/dist/5940.js +1 -0
- package/dist/5940.js.map +1 -0
- package/dist/6047.js +1 -0
- package/dist/6047.js.map +1 -0
- package/dist/6237.js +1 -0
- package/dist/6237.js.map +1 -0
- package/dist/6362.js +1 -0
- package/dist/6362.js.map +1 -0
- package/dist/6371.js +1 -0
- package/dist/6371.js.map +1 -0
- package/dist/6377.js +1 -0
- package/dist/6377.js.map +1 -0
- package/dist/6444.js +1 -0
- package/dist/6444.js.map +1 -0
- package/dist/6508.js +1 -0
- package/dist/6508.js.map +1 -0
- package/dist/6594.js +1 -0
- package/dist/6594.js.map +1 -0
- package/dist/6724.js +1 -0
- package/dist/6724.js.map +1 -0
- package/dist/6904.js +1 -0
- package/dist/6904.js.map +1 -0
- package/dist/7045.js +1 -0
- package/dist/7045.js.map +1 -0
- package/dist/7175.js +1 -0
- package/dist/7175.js.map +1 -0
- package/dist/7182.js +1 -0
- package/dist/7182.js.map +1 -0
- package/dist/7247.js +1 -0
- package/dist/7247.js.map +1 -0
- package/dist/7742.js +1 -0
- package/dist/7742.js.map +1 -0
- package/dist/7912.js +1 -0
- package/dist/7912.js.map +1 -0
- package/dist/8358.js +1 -0
- package/dist/8358.js.map +1 -0
- package/dist/8359.js +1 -0
- package/dist/8359.js.map +1 -0
- package/dist/8695.js +1 -0
- package/dist/8695.js.map +1 -0
- package/dist/903.js +1 -0
- package/dist/903.js.map +1 -0
- package/dist/9072.js +1 -0
- package/dist/9072.js.map +1 -0
- package/dist/9414.js +1 -0
- package/dist/9414.js.map +1 -0
- package/dist/9655.js +11 -0
- package/dist/9655.js.map +1 -0
- package/dist/9806.js +1 -0
- package/dist/9806.js.map +1 -0
- package/dist/990.js +1 -0
- package/dist/990.js.map +1 -0
- package/dist/main.js +17 -2
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-billing-app.js +6 -1
- package/dist/openmrs-esm-billing-app.js.buildmanifest.json +643 -436
- package/dist/openmrs-esm-billing-app.js.map +1 -1
- package/dist/routes.json +1 -1
- package/e2e/commands/billing-operations.ts +21 -0
- package/e2e/commands/types.ts +9 -1
- package/e2e/pages/discounts-page.ts +75 -0
- package/e2e/pages/index.ts +1 -0
- package/e2e/pages/invoice-page.ts +7 -7
- package/e2e/specs/bill-discounts.spec.ts +255 -0
- package/e2e/specs/billing-dashboard.spec.ts +3 -3
- package/e2e/specs/billing-patient-chart.spec.ts +2 -2
- package/package.json +13 -22
- package/rspack.config.js +1 -0
- package/src/bill-history/bill-action-menu.component.tsx +20 -2
- package/src/bill-history/bill-history.test.tsx +23 -22
- package/src/bill-item-actions/edit-bill-item.modal.tsx +1 -1
- package/src/bill-item-actions/edit-bill-item.test.tsx +29 -27
- package/src/billable-services/billable-service-form/billable-service-form.test.tsx +74 -73
- package/src/billable-services/billable-services-home.component.tsx +4 -2
- package/src/billable-services/billable-services.test.tsx +8 -7
- package/src/billable-services/dashboard/dashboard.test.tsx +3 -2
- package/src/billable-services-admin-card-link.test.tsx +2 -1
- package/src/billing-dashboard/billing-dashboard.test.tsx +19 -3
- package/src/billing-form/billing-checkin-form.component.tsx +7 -3
- package/src/billing-form/billing-checkin-form.test.tsx +22 -21
- package/src/billing-form/billing-form.resource.test.ts +7 -6
- package/src/billing-form/billing-form.test.tsx +77 -40
- package/src/billing-form/billing-form.workspace.tsx +25 -6
- package/src/billing-form/visit-attributes/visit-attributes-form.component.tsx +6 -2
- package/src/billing.resource.test.ts +43 -41
- package/src/billing.resource.ts +65 -16
- package/src/bills-table/bills-table.component.tsx +15 -4
- package/src/bills-table/bills-table.test.tsx +72 -71
- package/src/config-schema.ts +0 -7
- package/src/discounts/admin/discount-requests-left-panel-link.component.tsx +43 -0
- package/src/discounts/admin/discount-requests.component.tsx +316 -0
- package/src/discounts/admin/discount-requests.scss +133 -0
- package/src/discounts/admin/discount-requests.test.tsx +104 -0
- package/src/discounts/admin/review-bill-discounts/bill-line-items-table/bill-line-items-table.component.tsx +42 -0
- package/src/discounts/admin/review-bill-discounts/bill-line-items-table/bill-line-items-table.scss +76 -0
- package/src/discounts/admin/review-bill-discounts/bill-payments-table/bill-payments-table.component.tsx +50 -0
- package/src/discounts/admin/review-bill-discounts/bill-payments-table/bill-payments-table.scss +63 -0
- package/src/discounts/admin/review-bill-discounts/bill-receipt-rail/bill-receipt-rail.component.tsx +73 -0
- package/src/discounts/admin/review-bill-discounts/bill-receipt-rail/bill-receipt-rail.scss +54 -0
- package/src/discounts/admin/review-bill-discounts/bill-totals-summary/bill-totals-summary.component.tsx +95 -0
- package/src/discounts/admin/review-bill-discounts/bill-totals-summary/bill-totals-summary.scss +128 -0
- package/src/discounts/admin/review-bill-discounts/discount-card/discount-card.component.tsx +158 -0
- package/src/discounts/admin/review-bill-discounts/discount-card/discount-card.scss +164 -0
- package/src/discounts/admin/review-bill-discounts/discount-review-stack/discount-review-stack.component.tsx +86 -0
- package/src/discounts/admin/review-bill-discounts/discount-review-stack/discount-review-stack.scss +40 -0
- package/src/discounts/admin/review-bill-discounts/review-bill-discounts.modal.scss +14 -0
- package/src/discounts/admin/review-bill-discounts/review-bill-discounts.modal.test.tsx +153 -0
- package/src/discounts/admin/review-bill-discounts/review-bill-discounts.modal.tsx +167 -0
- package/src/discounts/admin/review-bill-discounts/review-bill-discounts.utils.ts +42 -0
- package/src/discounts/discounts-table.component.tsx +109 -0
- package/src/discounts/discounts-table.scss +37 -0
- package/src/discounts/discounts-table.test.tsx +67 -0
- package/src/discounts/discounts.resource.ts +71 -0
- package/src/discounts/request-discount.modal.scss +88 -0
- package/src/discounts/request-discount.modal.test.tsx +161 -0
- package/src/discounts/request-discount.modal.tsx +253 -0
- package/src/index.ts +52 -21
- package/src/invoice/invoice-table.component.tsx +116 -18
- package/src/invoice/invoice-table.test.tsx +165 -13
- package/src/invoice/invoice.component.tsx +111 -7
- package/src/invoice/invoice.test.tsx +366 -66
- package/src/invoice/line-item-action-menu.component.tsx +31 -1
- package/src/invoice/payments/payment-form/payment-form.test.tsx +20 -19
- package/src/invoice/payments/payment-history/payment-history.test.tsx +13 -10
- package/src/invoice/payments/payments.component.tsx +20 -6
- package/src/invoice/payments/payments.test.tsx +88 -23
- package/src/invoice/printable-invoice/print-receipt.test.tsx +10 -28
- package/src/invoice/printable-invoice/printable-footer.test.tsx +5 -4
- package/src/invoice/printable-invoice/printable-invoice-header.component.tsx +3 -3
- package/src/invoice/printable-invoice/printable-invoice-header.test.tsx +26 -11
- package/src/invoice/printable-invoice/printable-invoice.component.tsx +38 -15
- package/src/left-panel-link.test.tsx +3 -3
- package/src/metrics-cards/metrics-cards.test.tsx +11 -10
- package/src/modal/delete-bill-confirmation.modal.test.tsx +134 -0
- package/src/modal/delete-bill-confirmation.modal.tsx +98 -0
- package/src/modal/delete-line-item-confirmation.modal.test.tsx +11 -9
- package/src/modal/finalize-bill-confirmation.modal.test.tsx +10 -8
- package/src/modal/require-payment-modal.test.tsx +12 -11
- package/src/payment-status-tag/payment-status-tag.component.tsx +50 -0
- package/src/payment-status-tag/payment-status-tag.scss +6 -0
- package/src/payment-status-tag/payment-status-tag.test.tsx +113 -0
- package/src/refunds/admin/refund-requests-left-panel-link.component.tsx +43 -0
- package/src/refunds/admin/refund-requests.component.tsx +324 -0
- package/src/refunds/admin/refund-requests.scss +133 -0
- package/src/refunds/admin/refund-requests.test.tsx +99 -0
- package/src/refunds/admin/review-bill-refunds/bill-line-items-table/bill-line-items-table.component.tsx +42 -0
- package/src/refunds/admin/review-bill-refunds/bill-line-items-table/bill-line-items-table.scss +76 -0
- package/src/refunds/admin/review-bill-refunds/bill-payments-table/bill-payments-table.component.tsx +50 -0
- package/src/refunds/admin/review-bill-refunds/bill-payments-table/bill-payments-table.scss +63 -0
- package/src/refunds/admin/review-bill-refunds/bill-receipt-rail/bill-receipt-rail.component.tsx +84 -0
- package/src/refunds/admin/review-bill-refunds/bill-receipt-rail/bill-receipt-rail.scss +54 -0
- package/src/refunds/admin/review-bill-refunds/bill-totals-summary/bill-totals-summary.component.tsx +83 -0
- package/src/refunds/admin/review-bill-refunds/bill-totals-summary/bill-totals-summary.scss +65 -0
- package/src/refunds/admin/review-bill-refunds/refund-card/refund-card.component.tsx +170 -0
- package/src/refunds/admin/review-bill-refunds/refund-card/refund-card.scss +155 -0
- package/src/refunds/admin/review-bill-refunds/refund-review-stack/refund-review-stack.component.tsx +86 -0
- package/src/refunds/admin/review-bill-refunds/refund-review-stack/refund-review-stack.scss +40 -0
- package/src/refunds/admin/review-bill-refunds/review-bill-refunds.modal.scss +14 -0
- package/src/refunds/admin/review-bill-refunds/review-bill-refunds.modal.test.tsx +313 -0
- package/src/refunds/admin/review-bill-refunds/review-bill-refunds.modal.tsx +188 -0
- package/src/refunds/admin/review-bill-refunds/review-bill-refunds.utils.ts +66 -0
- package/src/refunds/refunds-table.component.tsx +137 -0
- package/src/refunds/refunds-table.scss +37 -0
- package/src/refunds/refunds-table.test.tsx +105 -0
- package/src/refunds/refunds.resource.test.ts +44 -0
- package/src/refunds/refunds.resource.ts +42 -0
- package/src/refunds/refunds.types.test.ts +15 -0
- package/src/refunds/request-refund.modal.scss +84 -0
- package/src/refunds/request-refund.modal.test.tsx +204 -0
- package/src/refunds/request-refund.modal.tsx +218 -0
- package/src/routes.json +36 -2
- package/src/types/index.ts +116 -1
- package/src/visit-bills/visit-bills-panel.component.tsx +151 -0
- package/src/visit-bills/visit-bills-panel.scss +31 -0
- package/src/visit-bills/visit-bills-panel.test.tsx +113 -0
- package/tools/empty-module.ts +1 -0
- package/tools/setup-tests.ts +9 -9
- package/translations/am.json +154 -16
- package/translations/ar.json +154 -16
- package/translations/ar_SY.json +154 -16
- package/translations/bn.json +154 -16
- package/translations/cs.json +154 -16
- package/translations/de.json +154 -16
- package/translations/en.json +154 -16
- package/translations/en_US.json +154 -16
- package/translations/es.json +154 -16
- package/translations/es_MX.json +154 -16
- package/translations/fr.json +154 -16
- package/translations/he.json +154 -16
- package/translations/hi.json +154 -16
- package/translations/hi_IN.json +154 -16
- package/translations/id.json +154 -16
- package/translations/it.json +154 -16
- package/translations/ka.json +154 -16
- package/translations/km.json +154 -16
- package/translations/ku.json +154 -16
- package/translations/ky.json +154 -16
- package/translations/lg.json +154 -16
- package/translations/ne.json +154 -16
- package/translations/pl.json +154 -16
- package/translations/pt.json +154 -16
- package/translations/pt_BR.json +154 -16
- package/translations/qu.json +154 -16
- package/translations/ro_RO.json +154 -16
- package/translations/ru_RU.json +154 -16
- package/translations/si.json +154 -16
- package/translations/sq.json +154 -16
- package/translations/sw.json +154 -16
- package/translations/sw_KE.json +154 -16
- package/translations/tr.json +154 -16
- package/translations/tr_TR.json +154 -16
- package/translations/uk.json +154 -16
- package/translations/uz.json +154 -16
- package/translations/uz@Latn.json +154 -16
- package/translations/uz_UZ.json +154 -16
- package/translations/vi.json +154 -16
- package/translations/zh.json +154 -16
- package/translations/zh_CN.json +179 -41
- package/translations/zh_TW.json +154 -16
- package/tsconfig.json +3 -3
- package/vitest.config.js +28 -0
- package/.turbo/cache/4e30f71f570fc412-meta.json +0 -1
- package/.turbo/cache/4e30f71f570fc412.tar.zst +0 -0
- package/dist/1119.js +0 -1
- package/dist/1197.js +0 -1
- package/dist/1435.js +0 -1
- package/dist/1435.js.map +0 -1
- package/dist/1807.js +0 -1
- package/dist/1807.js.map +0 -1
- package/dist/2146.js +0 -1
- package/dist/2177.js +0 -2
- package/dist/2177.js.LICENSE.txt +0 -9
- package/dist/2177.js.map +0 -1
- package/dist/2690.js +0 -1
- package/dist/2704.js +0 -1
- package/dist/2704.js.map +0 -1
- package/dist/3002.js +0 -1
- package/dist/3002.js.map +0 -1
- package/dist/3041.js +0 -1
- package/dist/3041.js.map +0 -1
- package/dist/3099.js +0 -1
- package/dist/3184.js +0 -2
- package/dist/3184.js.LICENSE.txt +0 -14
- package/dist/3184.js.map +0 -1
- package/dist/3584.js +0 -1
- package/dist/4055.js +0 -1
- package/dist/4132.js +0 -1
- package/dist/4225.js +0 -1
- package/dist/4225.js.map +0 -1
- package/dist/4300.js +0 -1
- package/dist/4335.js +0 -1
- package/dist/439.js +0 -1
- package/dist/4618.js +0 -1
- package/dist/4652.js +0 -1
- package/dist/4944.js +0 -1
- package/dist/5173.js +0 -1
- package/dist/5241.js +0 -1
- package/dist/5422.js +0 -1
- package/dist/5422.js.map +0 -1
- package/dist/5442.js +0 -1
- package/dist/5661.js +0 -1
- package/dist/6022.js +0 -1
- package/dist/6404.js +0 -1
- package/dist/6404.js.map +0 -1
- package/dist/6468.js +0 -1
- package/dist/6540.js +0 -2
- package/dist/6540.js.LICENSE.txt +0 -9
- package/dist/6540.js.map +0 -1
- package/dist/6589.js +0 -1
- package/dist/6606.js +0 -1
- package/dist/6606.js.map +0 -1
- package/dist/6679.js +0 -1
- package/dist/6792.js +0 -1
- package/dist/6792.js.map +0 -1
- package/dist/6840.js +0 -1
- package/dist/6859.js +0 -1
- package/dist/7097.js +0 -1
- package/dist/7159.js +0 -1
- package/dist/723.js +0 -1
- package/dist/7255.js +0 -1
- package/dist/7255.js.map +0 -1
- package/dist/7617.js +0 -1
- package/dist/795.js +0 -1
- package/dist/8163.js +0 -1
- package/dist/8341.js +0 -2
- package/dist/8341.js.LICENSE.txt +0 -52
- package/dist/8341.js.map +0 -1
- package/dist/8349.js +0 -1
- package/dist/8371.js +0 -1
- package/dist/8421.js +0 -1
- package/dist/8421.js.map +0 -1
- package/dist/8618.js +0 -1
- package/dist/890.js +0 -1
- package/dist/9214.js +0 -1
- package/dist/9538.js +0 -1
- package/dist/9569.js +0 -1
- package/dist/961.js +0 -2
- package/dist/961.js.LICENSE.txt +0 -19
- package/dist/961.js.map +0 -1
- package/dist/986.js +0 -1
- package/dist/9879.js +0 -1
- package/dist/9895.js +0 -1
- package/dist/9900.js +0 -1
- package/dist/9913.js +0 -1
- package/dist/main.js.LICENSE.txt +0 -62
- package/src/billable-services/bill-waiver/bill-selection.component.tsx +0 -76
- package/src/billable-services/bill-waiver/bill-waiver-form.component.tsx +0 -107
- package/src/billable-services/bill-waiver/bill-waiver-form.scss +0 -34
- package/src/billable-services/bill-waiver/bill-waiver.component.tsx +0 -34
- package/src/billable-services/bill-waiver/bill-waiver.scss +0 -10
- package/src/billable-services/bill-waiver/patient-bills.component.tsx +0 -134
- package/webpack.config.js +0 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
2
3
|
import userEvent from '@testing-library/user-event';
|
|
3
4
|
import { render, screen, waitFor } from '@testing-library/react';
|
|
4
5
|
import { type Workspace2DefinitionProps, type FetchResponse } from '@openmrs/esm-framework';
|
|
@@ -18,20 +19,20 @@ import BillableServiceFormWorkspace, {
|
|
|
18
19
|
} from './billable-service-form.workspace';
|
|
19
20
|
import type { BillableService } from '../../types';
|
|
20
21
|
|
|
21
|
-
const mockUseBillableServices =
|
|
22
|
-
const mockUsePaymentModes =
|
|
23
|
-
const mockUseServiceTypes =
|
|
24
|
-
const mockCreateBillableService =
|
|
25
|
-
const mockUpdateBillableService =
|
|
26
|
-
const mockUseConceptsSearch =
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
useBillableServices:
|
|
30
|
-
usePaymentModes:
|
|
31
|
-
useServiceTypes:
|
|
32
|
-
createBillableService:
|
|
33
|
-
updateBillableService:
|
|
34
|
-
useConceptsSearch:
|
|
22
|
+
const mockUseBillableServices = vi.mocked(useBillableServices);
|
|
23
|
+
const mockUsePaymentModes = vi.mocked(usePaymentModes);
|
|
24
|
+
const mockUseServiceTypes = vi.mocked(useServiceTypes);
|
|
25
|
+
const mockCreateBillableService = vi.mocked(createBillableService);
|
|
26
|
+
const mockUpdateBillableService = vi.mocked(updateBillableService);
|
|
27
|
+
const mockUseConceptsSearch = vi.mocked(useConceptsSearch);
|
|
28
|
+
|
|
29
|
+
vi.mock('../billable-service.resource', () => ({
|
|
30
|
+
useBillableServices: vi.fn(),
|
|
31
|
+
usePaymentModes: vi.fn(),
|
|
32
|
+
useServiceTypes: vi.fn(),
|
|
33
|
+
createBillableService: vi.fn(),
|
|
34
|
+
updateBillableService: vi.fn(),
|
|
35
|
+
useConceptsSearch: vi.fn(),
|
|
35
36
|
}));
|
|
36
37
|
|
|
37
38
|
const mockPaymentModes = [
|
|
@@ -66,14 +67,14 @@ const setupMocks = () => {
|
|
|
66
67
|
billableServices: [],
|
|
67
68
|
isLoading: false,
|
|
68
69
|
error: null,
|
|
69
|
-
mutate:
|
|
70
|
+
mutate: vi.fn(),
|
|
70
71
|
isValidating: false,
|
|
71
72
|
});
|
|
72
73
|
mockUsePaymentModes.mockReturnValue({
|
|
73
74
|
paymentModes: mockPaymentModes,
|
|
74
75
|
error: null,
|
|
75
76
|
isLoadingPaymentModes: false,
|
|
76
|
-
mutate:
|
|
77
|
+
mutate: vi.fn(),
|
|
77
78
|
});
|
|
78
79
|
mockUseServiceTypes.mockReturnValue({ serviceTypes: mockServiceTypes, error: false, isLoadingServiceTypes: false });
|
|
79
80
|
mockUseConceptsSearch.mockReturnValue({ searchResults: [], isSearching: false, error: null });
|
|
@@ -82,7 +83,7 @@ const setupMocks = () => {
|
|
|
82
83
|
const renderBillableServicesForm = (
|
|
83
84
|
props: Partial<Workspace2DefinitionProps<Partial<BillableServiceFormWorkspaceProps>>> = {},
|
|
84
85
|
) => {
|
|
85
|
-
const closeWorkspace = props.closeWorkspace ||
|
|
86
|
+
const closeWorkspace = props.closeWorkspace || vi.fn();
|
|
86
87
|
const workspaceProps: BillableServiceFormWorkspaceProps = {
|
|
87
88
|
serviceToEdit: props.workspaceProps?.serviceToEdit,
|
|
88
89
|
closeWorkspaceWithSavedChanges: props.workspaceProps?.closeWorkspaceWithSavedChanges,
|
|
@@ -98,7 +99,7 @@ const renderBillableServicesForm = (
|
|
|
98
99
|
groupProps: props.groupProps || {},
|
|
99
100
|
windowProps: props.windowProps || {},
|
|
100
101
|
workspaceName: props.workspaceName || 'billable-service-form-workspace',
|
|
101
|
-
launchChildWorkspace:
|
|
102
|
+
launchChildWorkspace: vi.fn(),
|
|
102
103
|
windowName: 'billable-service-form-window',
|
|
103
104
|
isRootWorkspace: false,
|
|
104
105
|
showActionMenu: true,
|
|
@@ -142,9 +143,9 @@ const submitForm = async () => {
|
|
|
142
143
|
};
|
|
143
144
|
|
|
144
145
|
describe('BillableServiceFormWorkspace', () => {
|
|
145
|
-
|
|
146
|
+
it('should render billable services form and generate correct payload', async () => {
|
|
146
147
|
const user = userEvent.setup();
|
|
147
|
-
const mockCloseWorkspace =
|
|
148
|
+
const mockCloseWorkspace = vi.fn();
|
|
148
149
|
renderBillableServicesForm({ closeWorkspace: mockCloseWorkspace });
|
|
149
150
|
|
|
150
151
|
await fillRequiredFields(user);
|
|
@@ -170,9 +171,9 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
170
171
|
});
|
|
171
172
|
|
|
172
173
|
describe('Workspace Interactions', () => {
|
|
173
|
-
|
|
174
|
+
it('should call closeWorkspace when Cancel button is clicked', async () => {
|
|
174
175
|
const user = userEvent.setup();
|
|
175
|
-
const mockCloseWorkspace =
|
|
176
|
+
const mockCloseWorkspace = vi.fn();
|
|
176
177
|
renderBillableServicesForm({ closeWorkspace: mockCloseWorkspace });
|
|
177
178
|
|
|
178
179
|
const cancelButton = screen.getByRole('button', { name: /cancel/i });
|
|
@@ -181,9 +182,9 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
181
182
|
expect(mockCloseWorkspace).toHaveBeenCalledTimes(1);
|
|
182
183
|
});
|
|
183
184
|
|
|
184
|
-
|
|
185
|
+
it('should call closeWorkspaceWithSavedChanges after successful save', async () => {
|
|
185
186
|
const user = userEvent.setup();
|
|
186
|
-
const mockCloseWorkspaceWithSavedChanges =
|
|
187
|
+
const mockCloseWorkspaceWithSavedChanges = vi.fn();
|
|
187
188
|
renderBillableServicesForm({
|
|
188
189
|
workspaceProps: { closeWorkspaceWithSavedChanges: mockCloseWorkspaceWithSavedChanges },
|
|
189
190
|
});
|
|
@@ -197,7 +198,7 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
197
198
|
});
|
|
198
199
|
});
|
|
199
200
|
|
|
200
|
-
|
|
201
|
+
it('should disable buttons during submission', async () => {
|
|
201
202
|
const user = userEvent.setup();
|
|
202
203
|
let resolveCreate: (value: any) => void;
|
|
203
204
|
const createPromise = new Promise((resolve) => {
|
|
@@ -224,7 +225,7 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
224
225
|
});
|
|
225
226
|
});
|
|
226
227
|
|
|
227
|
-
|
|
228
|
+
it('should show loading indicator in save button during submission', async () => {
|
|
228
229
|
const user = userEvent.setup();
|
|
229
230
|
let resolveCreate: (value: any) => void;
|
|
230
231
|
const createPromise = new Promise((resolve) => {
|
|
@@ -249,8 +250,8 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
249
250
|
});
|
|
250
251
|
});
|
|
251
252
|
|
|
252
|
-
|
|
253
|
-
const mockOnWorkspaceClose =
|
|
253
|
+
it('should call onWorkspaceClose callback after successful edit', async () => {
|
|
254
|
+
const mockOnWorkspaceClose = vi.fn();
|
|
254
255
|
const mockServiceToEdit: BillableService = {
|
|
255
256
|
uuid: 'test-uuid',
|
|
256
257
|
name: 'Test Service',
|
|
@@ -289,7 +290,7 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
289
290
|
});
|
|
290
291
|
|
|
291
292
|
describe('Form Validation', () => {
|
|
292
|
-
|
|
293
|
+
it('should accept form submission without short name (short name is optional)', async () => {
|
|
293
294
|
const user = userEvent.setup();
|
|
294
295
|
renderBillableServicesForm();
|
|
295
296
|
|
|
@@ -317,7 +318,7 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
317
318
|
);
|
|
318
319
|
});
|
|
319
320
|
|
|
320
|
-
|
|
321
|
+
it('should trim leading and trailing whitespace from service name and short name', async () => {
|
|
321
322
|
const user = userEvent.setup();
|
|
322
323
|
renderBillableServicesForm();
|
|
323
324
|
|
|
@@ -347,7 +348,7 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
347
348
|
);
|
|
348
349
|
});
|
|
349
350
|
|
|
350
|
-
|
|
351
|
+
it('should enforce 255 character limit on service name input', async () => {
|
|
351
352
|
const user = userEvent.setup();
|
|
352
353
|
renderBillableServicesForm();
|
|
353
354
|
|
|
@@ -359,7 +360,7 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
359
360
|
expect(input).toHaveValue('A'.repeat(255));
|
|
360
361
|
});
|
|
361
362
|
|
|
362
|
-
|
|
363
|
+
it('should enforce 255 character limit on short name input', async () => {
|
|
363
364
|
const user = userEvent.setup();
|
|
364
365
|
renderBillableServicesForm();
|
|
365
366
|
|
|
@@ -371,7 +372,7 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
371
372
|
expect(input).toHaveValue('B'.repeat(255));
|
|
372
373
|
});
|
|
373
374
|
|
|
374
|
-
|
|
375
|
+
it('should show "Price must be greater than 0" error for zero price', async () => {
|
|
375
376
|
const user = userEvent.setup();
|
|
376
377
|
renderBillableServicesForm();
|
|
377
378
|
|
|
@@ -386,7 +387,7 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
386
387
|
expect(mockCreateBillableService).not.toHaveBeenCalled();
|
|
387
388
|
});
|
|
388
389
|
|
|
389
|
-
|
|
390
|
+
it('should show "Price must be greater than 0" error for negative price', async () => {
|
|
390
391
|
const user = userEvent.setup();
|
|
391
392
|
renderBillableServicesForm();
|
|
392
393
|
|
|
@@ -401,7 +402,7 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
401
402
|
expect(mockCreateBillableService).not.toHaveBeenCalled();
|
|
402
403
|
});
|
|
403
404
|
|
|
404
|
-
|
|
405
|
+
it('should show "Service name is required" error when service name is empty', async () => {
|
|
405
406
|
const user = userEvent.setup();
|
|
406
407
|
renderBillableServicesForm();
|
|
407
408
|
|
|
@@ -423,7 +424,7 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
423
424
|
expect(mockCreateBillableService).not.toHaveBeenCalled();
|
|
424
425
|
});
|
|
425
426
|
|
|
426
|
-
|
|
427
|
+
it('should accept valid decimal price values', async () => {
|
|
427
428
|
const user = userEvent.setup();
|
|
428
429
|
renderBillableServicesForm();
|
|
429
430
|
|
|
@@ -455,7 +456,7 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
455
456
|
});
|
|
456
457
|
});
|
|
457
458
|
|
|
458
|
-
|
|
459
|
+
it('should show "Service type is required" error when not selected', async () => {
|
|
459
460
|
const user = userEvent.setup();
|
|
460
461
|
renderBillableServicesForm();
|
|
461
462
|
|
|
@@ -474,7 +475,7 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
474
475
|
expect(mockCreateBillableService).not.toHaveBeenCalled();
|
|
475
476
|
});
|
|
476
477
|
|
|
477
|
-
|
|
478
|
+
it('should show "Payment mode is required" error when not selected', async () => {
|
|
478
479
|
const user = userEvent.setup();
|
|
479
480
|
renderBillableServicesForm();
|
|
480
481
|
|
|
@@ -493,7 +494,7 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
493
494
|
expect(mockCreateBillableService).not.toHaveBeenCalled();
|
|
494
495
|
});
|
|
495
496
|
|
|
496
|
-
|
|
497
|
+
it('should show "Price is required" error when price field is empty', async () => {
|
|
497
498
|
const user = userEvent.setup();
|
|
498
499
|
renderBillableServicesForm();
|
|
499
500
|
|
|
@@ -530,16 +531,16 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
530
531
|
],
|
|
531
532
|
};
|
|
532
533
|
|
|
533
|
-
|
|
534
|
+
it('should populate form with existing service data', () => {
|
|
534
535
|
renderBillableServicesForm({ workspaceProps: { serviceToEdit: mockServiceToEdit } });
|
|
535
536
|
|
|
536
537
|
expect(screen.getByText('X-Ray Service')).toBeInTheDocument(); // Service name shown as label
|
|
537
538
|
expect(screen.getByDisplayValue('XRay')).toBeInTheDocument(); // Short name
|
|
538
539
|
});
|
|
539
540
|
|
|
540
|
-
|
|
541
|
+
it('should call updateBillableService instead of createBillableService', async () => {
|
|
541
542
|
const user = userEvent.setup();
|
|
542
|
-
const mockCloseWorkspace =
|
|
543
|
+
const mockCloseWorkspace = vi.fn();
|
|
543
544
|
renderBillableServicesForm({
|
|
544
545
|
closeWorkspace: mockCloseWorkspace,
|
|
545
546
|
workspaceProps: { serviceToEdit: mockServiceToEdit },
|
|
@@ -571,9 +572,9 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
571
572
|
expect(mockCreateBillableService).not.toHaveBeenCalled();
|
|
572
573
|
});
|
|
573
574
|
|
|
574
|
-
|
|
575
|
+
it('should trim whitespace from short name when updating service', async () => {
|
|
575
576
|
const user = userEvent.setup();
|
|
576
|
-
const mockCloseWorkspace =
|
|
577
|
+
const mockCloseWorkspace = vi.fn();
|
|
577
578
|
renderBillableServicesForm({
|
|
578
579
|
closeWorkspace: mockCloseWorkspace,
|
|
579
580
|
workspaceProps: { serviceToEdit: mockServiceToEdit },
|
|
@@ -596,8 +597,8 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
596
597
|
);
|
|
597
598
|
});
|
|
598
599
|
|
|
599
|
-
|
|
600
|
-
const mockOnWorkspaceClose =
|
|
600
|
+
it('should call onWorkspaceClose callback after successful edit', async () => {
|
|
601
|
+
const mockOnWorkspaceClose = vi.fn();
|
|
601
602
|
renderBillableServicesForm({
|
|
602
603
|
workspaceProps: { serviceToEdit: mockServiceToEdit, onWorkspaceClose: mockOnWorkspaceClose },
|
|
603
604
|
});
|
|
@@ -609,7 +610,7 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
609
610
|
expect(mockOnWorkspaceClose).toHaveBeenCalledTimes(1);
|
|
610
611
|
});
|
|
611
612
|
|
|
612
|
-
|
|
613
|
+
it('should not allow editing service name in edit mode', () => {
|
|
613
614
|
renderBillableServicesForm({ workspaceProps: { serviceToEdit: mockServiceToEdit } });
|
|
614
615
|
|
|
615
616
|
// Service name should be displayed as a label, not an editable input
|
|
@@ -617,7 +618,7 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
617
618
|
expect(screen.queryByRole('textbox', { name: /Service name/i })).not.toBeInTheDocument();
|
|
618
619
|
});
|
|
619
620
|
|
|
620
|
-
|
|
621
|
+
it('should handle asynchronous loading of dependencies and populate form correctly', async () => {
|
|
621
622
|
// Scenario: User opens edit form, but payment modes/service types haven't loaded yet
|
|
622
623
|
// The form should wait for dependencies to load, then populate correctly
|
|
623
624
|
|
|
@@ -635,7 +636,7 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
635
636
|
});
|
|
636
637
|
|
|
637
638
|
describe('Dynamic Payment Options', () => {
|
|
638
|
-
|
|
639
|
+
it('should add new payment option when clicking "Add payment option" button', async () => {
|
|
639
640
|
const user = userEvent.setup();
|
|
640
641
|
renderBillableServicesForm();
|
|
641
642
|
|
|
@@ -646,7 +647,7 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
646
647
|
expect(paymentModeDropdowns).toHaveLength(2);
|
|
647
648
|
});
|
|
648
649
|
|
|
649
|
-
|
|
650
|
+
it('should be able to add multiple payment options', async () => {
|
|
650
651
|
const user = userEvent.setup();
|
|
651
652
|
renderBillableServicesForm();
|
|
652
653
|
|
|
@@ -658,7 +659,7 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
658
659
|
expect(paymentModeDropdowns).toHaveLength(2);
|
|
659
660
|
});
|
|
660
661
|
|
|
661
|
-
|
|
662
|
+
it('should allow adding multiple payment options with different payment modes', async () => {
|
|
662
663
|
const user = userEvent.setup();
|
|
663
664
|
renderBillableServicesForm();
|
|
664
665
|
|
|
@@ -706,7 +707,7 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
706
707
|
);
|
|
707
708
|
});
|
|
708
709
|
|
|
709
|
-
|
|
710
|
+
it('should validate each payment option independently', async () => {
|
|
710
711
|
const user = userEvent.setup();
|
|
711
712
|
renderBillableServicesForm();
|
|
712
713
|
|
|
@@ -740,7 +741,7 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
740
741
|
expect(mockCreateBillableService).not.toHaveBeenCalled();
|
|
741
742
|
});
|
|
742
743
|
|
|
743
|
-
|
|
744
|
+
it('should allow selecting different payment modes in multiple fields', async () => {
|
|
744
745
|
const user = userEvent.setup();
|
|
745
746
|
renderBillableServicesForm();
|
|
746
747
|
|
|
@@ -801,7 +802,7 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
801
802
|
});
|
|
802
803
|
|
|
803
804
|
describe('Error Handling', () => {
|
|
804
|
-
|
|
805
|
+
it('should display error snackbar when create API call fails', async () => {
|
|
805
806
|
const user = userEvent.setup();
|
|
806
807
|
renderBillableServicesForm();
|
|
807
808
|
|
|
@@ -818,7 +819,7 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
818
819
|
expect(mockCreateBillableService).toHaveBeenCalledTimes(1);
|
|
819
820
|
});
|
|
820
821
|
|
|
821
|
-
|
|
822
|
+
it('should display error snackbar when update API call fails', async () => {
|
|
822
823
|
const mockServiceToEdit: BillableService = {
|
|
823
824
|
uuid: 'service-uuid',
|
|
824
825
|
name: 'Test Service',
|
|
@@ -859,7 +860,7 @@ describe('BillableServiceFormWorkspace', () => {
|
|
|
859
860
|
|
|
860
861
|
describe('Helper Functions', () => {
|
|
861
862
|
describe('transformServiceToFormData', () => {
|
|
862
|
-
|
|
863
|
+
it('should return default form data when no service is provided', () => {
|
|
863
864
|
const result = transformServiceToFormData();
|
|
864
865
|
|
|
865
866
|
expect(result).toEqual({
|
|
@@ -871,7 +872,7 @@ describe('Helper Functions', () => {
|
|
|
871
872
|
});
|
|
872
873
|
});
|
|
873
874
|
|
|
874
|
-
|
|
875
|
+
it('should return default form data when undefined service is provided', () => {
|
|
875
876
|
const result = transformServiceToFormData(undefined);
|
|
876
877
|
|
|
877
878
|
expect(result).toEqual({
|
|
@@ -883,7 +884,7 @@ describe('Helper Functions', () => {
|
|
|
883
884
|
});
|
|
884
885
|
});
|
|
885
886
|
|
|
886
|
-
|
|
887
|
+
it('should transform a complete service to form data', () => {
|
|
887
888
|
const service: BillableService = {
|
|
888
889
|
uuid: 'service-uuid',
|
|
889
890
|
name: 'X-Ray',
|
|
@@ -949,7 +950,7 @@ describe('Helper Functions', () => {
|
|
|
949
950
|
});
|
|
950
951
|
});
|
|
951
952
|
|
|
952
|
-
|
|
953
|
+
it('should handle service without concept', () => {
|
|
953
954
|
const service: BillableService = {
|
|
954
955
|
uuid: 'service-uuid',
|
|
955
956
|
name: 'Basic Service',
|
|
@@ -978,7 +979,7 @@ describe('Helper Functions', () => {
|
|
|
978
979
|
expect(result.concept).toBeNull();
|
|
979
980
|
});
|
|
980
981
|
|
|
981
|
-
|
|
982
|
+
it('should handle service with missing or empty price using nullish coalescing', () => {
|
|
982
983
|
const service: BillableService = {
|
|
983
984
|
uuid: 'service-uuid',
|
|
984
985
|
name: 'Test Service',
|
|
@@ -1010,32 +1011,32 @@ describe('Helper Functions', () => {
|
|
|
1010
1011
|
});
|
|
1011
1012
|
|
|
1012
1013
|
describe('normalizePrice', () => {
|
|
1013
|
-
|
|
1014
|
+
it('should return number as-is', () => {
|
|
1014
1015
|
expect(normalizePrice(100)).toBe(100);
|
|
1015
1016
|
expect(normalizePrice(10.5)).toBe(10.5);
|
|
1016
1017
|
expect(normalizePrice(0)).toBe(0);
|
|
1017
1018
|
});
|
|
1018
1019
|
|
|
1019
|
-
|
|
1020
|
+
it('should convert string to number', () => {
|
|
1020
1021
|
expect(normalizePrice('100')).toBe(100);
|
|
1021
1022
|
expect(normalizePrice('10.5')).toBe(10.5);
|
|
1022
1023
|
expect(normalizePrice('0')).toBe(0);
|
|
1023
1024
|
});
|
|
1024
1025
|
|
|
1025
|
-
|
|
1026
|
+
it('should handle decimal strings correctly', () => {
|
|
1026
1027
|
expect(normalizePrice('10.99')).toBe(10.99);
|
|
1027
1028
|
expect(normalizePrice('0.50')).toBe(0.5);
|
|
1028
1029
|
});
|
|
1029
1030
|
|
|
1030
|
-
|
|
1031
|
+
it('should handle undefined by converting to NaN', () => {
|
|
1031
1032
|
expect(normalizePrice(undefined)).toBeNaN();
|
|
1032
1033
|
});
|
|
1033
1034
|
|
|
1034
|
-
|
|
1035
|
+
it('should handle empty string by converting to NaN', () => {
|
|
1035
1036
|
expect(normalizePrice('')).toBeNaN();
|
|
1036
1037
|
});
|
|
1037
1038
|
|
|
1038
|
-
|
|
1039
|
+
it('should handle invalid string by converting to NaN', () => {
|
|
1039
1040
|
expect(normalizePrice('invalid')).toBeNaN();
|
|
1040
1041
|
});
|
|
1041
1042
|
});
|
|
@@ -1047,14 +1048,14 @@ describe('Helper Functions', () => {
|
|
|
1047
1048
|
{ uuid: 'mpesa-uuid', name: 'MPESA' },
|
|
1048
1049
|
];
|
|
1049
1050
|
|
|
1050
|
-
|
|
1051
|
+
it('should return all payment modes when no modes are selected', () => {
|
|
1051
1052
|
const fields = [{ paymentMode: '', price: '' }];
|
|
1052
1053
|
const result = getAvailablePaymentModes(allPaymentModes, fields, 0, '');
|
|
1053
1054
|
|
|
1054
1055
|
expect(result).toEqual(allPaymentModes);
|
|
1055
1056
|
});
|
|
1056
1057
|
|
|
1057
|
-
|
|
1058
|
+
it('should exclude already-selected payment modes from other fields', () => {
|
|
1058
1059
|
const fields = [
|
|
1059
1060
|
{ paymentMode: 'cash-uuid', price: '100' },
|
|
1060
1061
|
{ paymentMode: '', price: '' },
|
|
@@ -1068,7 +1069,7 @@ describe('Helper Functions', () => {
|
|
|
1068
1069
|
expect(result).not.toContainEqual({ uuid: 'cash-uuid', name: 'Cash' });
|
|
1069
1070
|
});
|
|
1070
1071
|
|
|
1071
|
-
|
|
1072
|
+
it('should keep current field selection visible even if selected elsewhere', () => {
|
|
1072
1073
|
const fields = [
|
|
1073
1074
|
{ paymentMode: 'cash-uuid', price: '100' },
|
|
1074
1075
|
{ paymentMode: 'insurance-uuid', price: '80' },
|
|
@@ -1081,7 +1082,7 @@ describe('Helper Functions', () => {
|
|
|
1081
1082
|
expect(result).toContainEqual({ uuid: 'mpesa-uuid', name: 'MPESA' });
|
|
1082
1083
|
});
|
|
1083
1084
|
|
|
1084
|
-
|
|
1085
|
+
it('should filter multiple selected payment modes', () => {
|
|
1085
1086
|
const fields = [
|
|
1086
1087
|
{ paymentMode: 'cash-uuid', price: '100' },
|
|
1087
1088
|
{ paymentMode: 'insurance-uuid', price: '80' },
|
|
@@ -1092,7 +1093,7 @@ describe('Helper Functions', () => {
|
|
|
1092
1093
|
expect(result).toEqual([{ uuid: 'mpesa-uuid', name: 'MPESA' }]);
|
|
1093
1094
|
});
|
|
1094
1095
|
|
|
1095
|
-
|
|
1096
|
+
it('should handle empty payment mode values correctly', () => {
|
|
1096
1097
|
const fields = [
|
|
1097
1098
|
{ paymentMode: '', price: '' },
|
|
1098
1099
|
{ paymentMode: 'cash-uuid', price: '100' },
|
|
@@ -1107,7 +1108,7 @@ describe('Helper Functions', () => {
|
|
|
1107
1108
|
]);
|
|
1108
1109
|
});
|
|
1109
1110
|
|
|
1110
|
-
|
|
1111
|
+
it('should work with generic types having uuid property', () => {
|
|
1111
1112
|
const customModes = [
|
|
1112
1113
|
{ uuid: 'a', customProp: 'value1' },
|
|
1113
1114
|
{ uuid: 'b', customProp: 'value2' },
|
|
@@ -1122,7 +1123,7 @@ describe('Helper Functions', () => {
|
|
|
1122
1123
|
expect(result).toEqual([{ uuid: 'b', customProp: 'value2' }]);
|
|
1123
1124
|
});
|
|
1124
1125
|
|
|
1125
|
-
|
|
1126
|
+
it('should return all modes when only current field has a selection', () => {
|
|
1126
1127
|
const fields = [{ paymentMode: 'cash-uuid', price: '100' }];
|
|
1127
1128
|
const result = getAvailablePaymentModes(allPaymentModes, fields, 0, 'cash-uuid');
|
|
1128
1129
|
|
|
@@ -3,11 +3,12 @@ import classNames from 'classnames';
|
|
|
3
3
|
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
|
4
4
|
import { useTranslation } from 'react-i18next';
|
|
5
5
|
import { useLeftNav, WorkspaceContainer, useLayoutType, isDesktop } from '@openmrs/esm-framework';
|
|
6
|
-
// import BillWaiver from './bill-waiver/bill-waiver.component';
|
|
7
6
|
import BillableServicesDashboard from './dashboard/dashboard.component';
|
|
8
7
|
import BillingHeader from '../billing-header/billing-header.component';
|
|
9
8
|
import CashPointConfiguration from './cash-point/cash-point-configuration.component';
|
|
10
9
|
import PaymentModesConfig from './payment-modes/payment-modes-config.component';
|
|
10
|
+
import DiscountRequests from '../discounts/admin/discount-requests.component';
|
|
11
|
+
import RefundRequests from '../refunds/admin/refund-requests.component';
|
|
11
12
|
import styles from './billable-services.scss';
|
|
12
13
|
|
|
13
14
|
const BillableServiceHome: React.FC = () => {
|
|
@@ -26,7 +27,8 @@ const BillableServiceHome: React.FC = () => {
|
|
|
26
27
|
<Route path="/" element={<BillableServicesDashboard />} />
|
|
27
28
|
<Route path="/cash-point-config" element={<CashPointConfiguration />} />
|
|
28
29
|
<Route path="/payment-modes-config" element={<PaymentModesConfig />} />
|
|
29
|
-
|
|
30
|
+
<Route path="/discount-requests" element={<DiscountRequests />} />
|
|
31
|
+
<Route path="/refund-requests" element={<RefundRequests />} />
|
|
30
32
|
</Routes>
|
|
31
33
|
</main>
|
|
32
34
|
</div>
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { describe, expect, type Mock, it, vi } from 'vitest';
|
|
2
3
|
import { render, screen } from '@testing-library/react';
|
|
3
4
|
import userEvent from '@testing-library/user-event';
|
|
4
5
|
import BillableServices from './billable-services.component';
|
|
5
6
|
import { useBillableServices } from './billable-service.resource';
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
useBillableServices:
|
|
8
|
+
vi.mock('./billable-service.resource', () => ({
|
|
9
|
+
useBillableServices: vi.fn(),
|
|
9
10
|
}));
|
|
10
11
|
|
|
11
12
|
describe('BillableService', () => {
|
|
12
|
-
const mockedUseBillableServices = useBillableServices as
|
|
13
|
+
const mockedUseBillableServices = useBillableServices as Mock;
|
|
13
14
|
|
|
14
15
|
it('renders an empty state when there are no billable services', () => {
|
|
15
16
|
mockedUseBillableServices.mockReturnValue({
|
|
@@ -17,7 +18,7 @@ describe('BillableService', () => {
|
|
|
17
18
|
isLoading: false,
|
|
18
19
|
isValidating: false,
|
|
19
20
|
error: null,
|
|
20
|
-
mutate:
|
|
21
|
+
mutate: vi.fn(),
|
|
21
22
|
});
|
|
22
23
|
|
|
23
24
|
render(<BillableServices />);
|
|
@@ -51,7 +52,7 @@ describe('BillableService', () => {
|
|
|
51
52
|
isLoading: false,
|
|
52
53
|
isValidating: false,
|
|
53
54
|
error: null,
|
|
54
|
-
mutate:
|
|
55
|
+
mutate: vi.fn(),
|
|
55
56
|
});
|
|
56
57
|
|
|
57
58
|
render(<BillableServices />);
|
|
@@ -92,7 +93,7 @@ describe('BillableService', () => {
|
|
|
92
93
|
isLoading: false,
|
|
93
94
|
isValidating: false,
|
|
94
95
|
error: null,
|
|
95
|
-
mutate:
|
|
96
|
+
mutate: vi.fn(),
|
|
96
97
|
});
|
|
97
98
|
|
|
98
99
|
const user = userEvent.setup();
|
|
@@ -122,7 +123,7 @@ describe('BillableService', () => {
|
|
|
122
123
|
isLoading: false,
|
|
123
124
|
isValidating: false,
|
|
124
125
|
error: null,
|
|
125
|
-
mutate:
|
|
126
|
+
mutate: vi.fn(),
|
|
126
127
|
});
|
|
127
128
|
|
|
128
129
|
const user = userEvent.setup();
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { it } from 'vitest';
|
|
3
|
+
import { waitForLoadingToFinish } from '@tools/test-helpers';
|
|
2
4
|
import { render } from '@testing-library/react';
|
|
3
|
-
import { waitForLoadingToFinish } from 'tools/test-helpers';
|
|
4
5
|
import BillableServicesDashboard from './dashboard.component';
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
it('renders an empty state when there are no services', async () => {
|
|
7
8
|
renderBillingDashboard();
|
|
8
9
|
await waitForLoadingToFinish();
|
|
9
10
|
});
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
2
3
|
import { render, screen } from '@testing-library/react';
|
|
3
4
|
import BillableServicesCardLink from './billable-services-admin-card-link.component';
|
|
4
5
|
|
|
5
6
|
describe('BillableServicesCardLink', () => {
|
|
6
|
-
|
|
7
|
+
it('should render billable services admin link', () => {
|
|
7
8
|
renderBillableServicesCardLink();
|
|
8
9
|
const manageBillableServicesText = screen.getByText('Manage billable services');
|
|
9
10
|
expect(manageBillableServicesText).toHaveClass('heading');
|
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
2
3
|
import { screen, render } from '@testing-library/react';
|
|
3
4
|
import { BillingDashboard } from './billing-dashboard.component';
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
vi.mock('../billing.resource', () => ({
|
|
7
|
+
usePaginatedBills: vi.fn(() => ({
|
|
8
|
+
bills: [],
|
|
9
|
+
error: null,
|
|
10
|
+
isLoading: false,
|
|
11
|
+
isValidating: false,
|
|
12
|
+
mutate: vi.fn(),
|
|
13
|
+
currentPage: 1,
|
|
14
|
+
totalCount: 0,
|
|
15
|
+
goTo: vi.fn(),
|
|
16
|
+
})),
|
|
17
|
+
}));
|
|
7
18
|
|
|
8
|
-
|
|
19
|
+
describe('BillingDashboard', () => {
|
|
20
|
+
it('renders an empty state when there are no billing records', () => {
|
|
21
|
+
renderBillingDashboard();
|
|
22
|
+
|
|
23
|
+
expect(screen.getByTitle(/billing module illustration/i)).toBeInTheDocument();
|
|
24
|
+
});
|
|
9
25
|
});
|
|
10
26
|
|
|
11
27
|
function renderBillingDashboard() {
|