@openmrs/esm-billing-app 1.0.2-pre.112 → 1.0.2-pre.1124
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/README.md +54 -9
- package/__mocks__/bills.mock.ts +12 -0
- package/__mocks__/react-i18next.js +6 -5
- package/dist/1119.js +1 -1
- package/dist/1146.js +1 -2
- package/dist/1146.js.map +1 -1
- package/dist/1197.js +1 -1
- package/dist/1537.js +1 -0
- package/dist/1537.js.map +1 -0
- package/dist/1856.js +1 -0
- package/dist/1856.js.map +1 -0
- package/dist/2146.js +1 -1
- package/dist/2177.js +1 -1
- package/dist/2177.js.map +1 -1
- package/dist/2524.js +1 -0
- package/dist/2524.js.map +1 -0
- package/dist/2690.js +1 -1
- package/dist/3099.js +1 -1
- package/dist/3584.js +1 -1
- package/dist/3717.js +2 -0
- package/dist/3717.js.map +1 -0
- package/dist/4055.js +1 -1
- package/dist/4132.js +1 -1
- package/dist/4300.js +1 -1
- package/dist/4335.js +1 -1
- package/dist/439.js +1 -0
- package/dist/4618.js +1 -1
- package/dist/4652.js +1 -1
- package/dist/4724.js +1 -0
- package/dist/4724.js.map +1 -0
- package/dist/4739.js +1 -1
- package/dist/4739.js.map +1 -1
- package/dist/4944.js +1 -1
- package/dist/5173.js +1 -1
- package/dist/5241.js +1 -1
- package/dist/5442.js +1 -1
- package/dist/5661.js +1 -1
- package/dist/6022.js +1 -1
- package/dist/6468.js +1 -1
- package/dist/6540.js +1 -1
- package/dist/6540.js.map +1 -1
- package/dist/6589.js +1 -0
- package/dist/6679.js +1 -1
- package/dist/6840.js +1 -1
- package/dist/6859.js +1 -1
- package/dist/7097.js +1 -1
- package/dist/7159.js +1 -1
- package/dist/723.js +1 -1
- package/dist/7255.js +1 -1
- package/dist/7255.js.map +1 -1
- package/dist/7617.js +1 -1
- package/dist/795.js +1 -1
- package/dist/8163.js +1 -1
- package/dist/8349.js +1 -1
- package/dist/8371.js +1 -0
- package/dist/8572.js +1 -0
- package/dist/8572.js.map +1 -0
- package/dist/8618.js +1 -1
- package/dist/8708.js +2 -0
- package/dist/{6557.js.LICENSE.txt → 8708.js.LICENSE.txt} +22 -0
- package/dist/8708.js.map +1 -0
- package/dist/890.js +1 -1
- package/dist/9214.js +1 -1
- package/dist/9538.js +1 -1
- package/dist/9569.js +1 -1
- package/dist/961.js +1 -1
- package/dist/961.js.map +1 -1
- package/dist/986.js +1 -1
- package/dist/9879.js +1 -1
- package/dist/9895.js +1 -1
- package/dist/9900.js +1 -1
- package/dist/9913.js +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-billing-app.js +1 -1
- package/dist/openmrs-esm-billing-app.js.buildmanifest.json +321 -249
- package/dist/openmrs-esm-billing-app.js.map +1 -1
- package/dist/routes.json +1 -1
- package/e2e/README.md +19 -18
- package/e2e/commands/billing-operations.ts +96 -0
- package/e2e/commands/index.ts +3 -0
- package/e2e/commands/patient-operations.ts +82 -0
- package/e2e/commands/types.ts +73 -0
- package/e2e/core/test.ts +12 -1
- package/e2e/fixtures/api.ts +2 -3
- package/e2e/pages/billing-dashboard-page.ts +84 -0
- package/e2e/pages/billing-form-page.ts +114 -0
- package/e2e/pages/index.ts +4 -1
- package/e2e/pages/invoice-page.ts +113 -0
- package/e2e/pages/payment-page.ts +104 -0
- package/e2e/specs/billing-dashboard.spec.ts +203 -0
- package/e2e/specs/billing-patient-chart.spec.ts +738 -0
- package/e2e/support/github/Dockerfile +1 -1
- package/e2e/support/github/run-e2e-docker-env.sh +29 -32
- package/example.env +15 -1
- package/package.json +19 -16
- package/playwright.config.ts +4 -2
- package/src/bill-history/bill-history.component.tsx +15 -17
- package/src/bill-history/bill-history.scss +4 -94
- package/src/bill-history/bill-history.test.tsx +37 -77
- package/src/bill-item-actions/bill-item-actions.scss +21 -5
- package/src/bill-item-actions/edit-bill-item.modal.tsx +227 -0
- package/src/bill-item-actions/edit-bill-item.test.tsx +233 -40
- package/src/billable-services/bill-waiver/bill-selection.component.tsx +5 -5
- package/src/billable-services/bill-waiver/bill-waiver-form.component.tsx +37 -39
- package/src/billable-services/bill-waiver/patient-bills.component.tsx +7 -7
- package/src/billable-services/bill-waiver/utils.ts +13 -3
- package/src/billable-services/{create-edit/add-billable-service.scss → billable-service-form/billable-service-form.scss} +32 -64
- package/src/billable-services/billable-service-form/billable-service-form.test.tsx +1099 -0
- package/src/billable-services/billable-service-form/billable-service-form.workspace.tsx +516 -0
- package/src/billable-services/billable-service.resource.ts +71 -27
- package/src/billable-services/billable-services-home.component.tsx +13 -42
- package/src/billable-services/billable-services-left-panel-link.component.tsx +50 -0
- package/src/billable-services/billable-services-left-panel-menu.component.tsx +48 -0
- package/src/billable-services/billable-services-menu-item/item.component.tsx +5 -4
- package/src/billable-services/billable-services.component.tsx +156 -152
- package/src/billable-services/billable-services.scss +29 -0
- package/src/billable-services/billable-services.test.tsx +6 -49
- package/src/billable-services/cash-point/add-cash-point.modal.tsx +170 -0
- package/src/billable-services/cash-point/cash-point-configuration.component.tsx +19 -193
- package/src/billable-services/cash-point/cash-point-configuration.scss +1 -5
- package/src/billable-services/dashboard/dashboard.component.tsx +0 -2
- package/src/billable-services/payment-modes/delete-payment-mode.modal.tsx +77 -0
- package/src/billable-services/payment-modes/payment-mode-form.modal.tsx +131 -0
- package/src/billable-services/payment-modes/payment-modes-config.component.tsx +139 -0
- package/src/billable-services/{payyment-modes → payment-modes}/payment-modes-config.scss +5 -4
- package/src/billable-services-admin-card-link.component.test.tsx +2 -2
- package/src/billable-services-admin-card-link.component.tsx +1 -1
- package/src/billing-dashboard/billing-dashboard.scss +1 -1
- package/src/billing-form/billing-checkin-form.component.tsx +29 -29
- package/src/billing-form/billing-checkin-form.scss +0 -7
- package/src/billing-form/billing-checkin-form.test.tsx +100 -27
- package/src/billing-form/billing-form.component.tsx +226 -284
- package/src/billing-form/billing-form.scss +143 -0
- package/src/billing-form/visit-attributes/visit-attributes-form.component.tsx +47 -41
- package/src/billing-form/visit-attributes/visit-attributes-form.scss +16 -3
- package/src/billing.resource.test.ts +503 -0
- package/src/billing.resource.ts +68 -76
- package/src/bills-table/bills-table.component.tsx +17 -24
- package/src/bills-table/bills-table.test.tsx +98 -54
- package/src/config-schema.ts +84 -31
- package/src/dashboard.meta.ts +5 -3
- package/src/helpers/functions.ts +5 -4
- package/src/index.ts +75 -13
- package/src/invoice/invoice-table.component.tsx +36 -70
- package/src/invoice/invoice-table.scss +8 -5
- package/src/invoice/invoice-table.test.tsx +273 -62
- package/src/invoice/invoice.component.tsx +44 -38
- package/src/invoice/invoice.scss +11 -4
- package/src/invoice/invoice.test.tsx +324 -120
- package/src/invoice/payments/invoice-breakdown/invoice-breakdown.scss +9 -9
- package/src/invoice/payments/payment-form/payment-form.component.tsx +45 -36
- package/src/invoice/payments/payment-form/payment-form.scss +5 -6
- package/src/invoice/payments/payment-form/payment-form.test.tsx +217 -67
- package/src/invoice/payments/payment-history/payment-history.component.tsx +6 -4
- package/src/invoice/payments/payment-history/payment-history.test.tsx +9 -14
- package/src/invoice/payments/payments.component.tsx +56 -68
- package/src/invoice/payments/payments.scss +4 -3
- package/src/invoice/payments/payments.test.tsx +282 -0
- package/src/invoice/payments/utils.ts +15 -27
- package/src/invoice/printable-invoice/print-receipt.component.tsx +3 -3
- package/src/invoice/printable-invoice/print-receipt.test.tsx +14 -25
- package/src/invoice/printable-invoice/printable-footer.component.tsx +2 -2
- package/src/invoice/printable-invoice/printable-footer.test.tsx +4 -13
- package/src/invoice/printable-invoice/printable-invoice-header.component.tsx +20 -11
- package/src/invoice/printable-invoice/printable-invoice-header.test.tsx +95 -16
- package/src/invoice/printable-invoice/printable-invoice.component.tsx +21 -35
- package/src/left-panel-link.component.tsx +9 -8
- package/src/left-panel-link.test.tsx +1 -4
- package/src/metrics-cards/metrics-cards.component.tsx +16 -6
- package/src/metrics-cards/metrics-cards.scss +4 -0
- package/src/metrics-cards/metrics-cards.test.tsx +18 -5
- package/src/modal/require-payment-modal.test.tsx +27 -22
- package/src/modal/{require-payment-modal.component.tsx → require-payment.modal.tsx} +18 -19
- package/src/routes.json +44 -20
- package/src/types/index.ts +87 -24
- package/translations/am.json +140 -80
- package/translations/ar.json +141 -81
- package/translations/ar_SY.json +141 -81
- package/translations/bn.json +143 -83
- package/translations/cs.json +230 -0
- package/translations/de.json +141 -81
- package/translations/en.json +142 -81
- package/translations/en_US.json +141 -81
- package/translations/es.json +140 -80
- package/translations/es_MX.json +141 -81
- package/translations/fr.json +224 -164
- package/translations/he.json +140 -80
- package/translations/hi.json +141 -81
- package/translations/hi_IN.json +141 -81
- package/translations/id.json +141 -81
- package/translations/it.json +166 -106
- package/translations/ka.json +141 -81
- package/translations/km.json +140 -80
- package/translations/ku.json +141 -81
- package/translations/ky.json +141 -81
- package/translations/lg.json +141 -81
- package/translations/ne.json +141 -81
- package/translations/pl.json +141 -81
- package/translations/pt.json +141 -81
- package/translations/pt_BR.json +141 -81
- package/translations/qu.json +141 -81
- package/translations/ro_RO.json +225 -165
- package/translations/ru_RU.json +141 -81
- package/translations/si.json +141 -81
- package/translations/sq.json +230 -0
- package/translations/sw.json +141 -81
- package/translations/sw_KE.json +141 -81
- package/translations/tr.json +141 -81
- package/translations/tr_TR.json +141 -81
- package/translations/uk.json +141 -81
- package/translations/uz.json +141 -81
- package/translations/uz@Latn.json +141 -81
- package/translations/uz_UZ.json +141 -81
- package/translations/vi.json +141 -81
- package/translations/zh.json +141 -81
- package/translations/zh_CN.json +171 -111
- package/translations/zh_TW.json +230 -0
- package/dist/1146.js.LICENSE.txt +0 -21
- package/dist/2352.js +0 -1
- package/dist/2352.js.map +0 -1
- package/dist/246.js +0 -1
- package/dist/246.js.map +0 -1
- package/dist/4689.js +0 -2
- package/dist/4689.js.map +0 -1
- package/dist/6557.js +0 -2
- package/dist/6557.js.map +0 -1
- package/dist/8638.js +0 -1
- package/dist/8638.js.map +0 -1
- package/dist/9968.js +0 -1
- package/dist/9968.js.map +0 -1
- package/e2e/pages/home-page.ts +0 -9
- package/e2e/specs/sample-test.spec.ts +0 -11
- package/src/bill-item-actions/edit-bill-item.component.tsx +0 -221
- package/src/billable-services/create-edit/add-billable-service.component.tsx +0 -401
- package/src/billable-services/create-edit/add-billable-service.test.tsx +0 -154
- package/src/billable-services/dashboard/service-metrics.component.tsx +0 -41
- package/src/billable-services/payyment-modes/payment-modes-config.component.tsx +0 -280
- package/src/invoice/payments/payments.component.test.tsx +0 -121
- /package/dist/{4689.js.LICENSE.txt → 3717.js.LICENSE.txt} +0 -0
|
@@ -4,46 +4,43 @@
|
|
|
4
4
|
script_dir=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
|
5
5
|
# create a temporary working directory
|
|
6
6
|
working_dir=$(mktemp -d "${TMPDIR:-/tmp/}openmrs-e2e-frontends.XXXXXXXXXX")
|
|
7
|
-
#
|
|
8
|
-
|
|
9
|
-
#
|
|
10
|
-
|
|
7
|
+
# cleanup temp directory on exit
|
|
8
|
+
trap 'rm -rf "$working_dir"' EXIT
|
|
9
|
+
# get the app name
|
|
10
|
+
app_name=$(jq -r '.name' "$script_dir/../../../package.json")
|
|
11
11
|
|
|
12
|
-
echo "Creating packed
|
|
13
|
-
#
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
# add to our array
|
|
19
|
-
app_names+=("$app_name.tgz");
|
|
20
|
-
# run yarn pack for our app and add it to the working directory
|
|
21
|
-
yarn workspace "$app" pack -o "$working_dir/$app_name.tgz" >/dev/null;
|
|
22
|
-
done;
|
|
23
|
-
echo "Created packed app archives"
|
|
12
|
+
echo "Creating packed archive of the app for Docker build..."
|
|
13
|
+
# @openmrs/esm-whatever -> _openmrs_esm_whatever
|
|
14
|
+
packed_app_name=$(echo "$app_name" | tr '[:punct:]' '_');
|
|
15
|
+
# run yarn pack for our app and add it to the working directory
|
|
16
|
+
yarn pack -o "$working_dir/$packed_app_name.tgz" >/dev/null;
|
|
17
|
+
echo "Successfully created packed app archive: $packed_app_name.tgz"
|
|
24
18
|
|
|
25
|
-
echo "Creating dynamic spa-assemble-config.json..."
|
|
26
|
-
# dynamically assemble our list of frontend modules, prepending the
|
|
27
|
-
#
|
|
19
|
+
echo "Creating dynamic spa-assemble-config.json with frontend modules..."
|
|
20
|
+
# dynamically assemble our list of frontend modules, prepending the primary navigation
|
|
21
|
+
# and patient banner apps; apps will all be in the /app directory of the Docker
|
|
28
22
|
# container
|
|
29
23
|
jq -n \
|
|
30
|
-
--arg
|
|
31
|
-
--arg
|
|
32
|
-
'{
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
24
|
+
--arg app_name "$app_name" \
|
|
25
|
+
--arg app_file "/app/$packed_app_name.tgz" \
|
|
26
|
+
'{
|
|
27
|
+
"@openmrs/esm-home-app": "next",
|
|
28
|
+
"@openmrs/esm-patient-banner-app": "next",
|
|
29
|
+
"@openmrs/esm-patient-chart-app": "next",
|
|
30
|
+
"@openmrs/esm-patient-forms-app": "next",
|
|
31
|
+
"@openmrs/esm-primary-navigation-app": "next",
|
|
32
|
+
"@openmrs/esm-system-admin-app": "next",
|
|
33
|
+
} + {
|
|
34
|
+
($app_name): $app_file
|
|
35
|
+
}' | jq '{"frontendModules": .}' > "$working_dir/spa-assemble-config.json"
|
|
36
|
+
echo "Successfully created spa-assemble-config.json with frontend modules"
|
|
40
37
|
|
|
41
|
-
echo "Copying Docker configuration..."
|
|
38
|
+
echo "Copying Docker configuration files to working directory..."
|
|
42
39
|
cp "$script_dir/Dockerfile" "$working_dir/Dockerfile"
|
|
43
40
|
cp "$script_dir/docker-compose.yml" "$working_dir/docker-compose.yml"
|
|
44
41
|
|
|
45
|
-
cd $working_dir
|
|
46
|
-
echo "
|
|
42
|
+
cd "$working_dir"
|
|
43
|
+
echo "Building and starting Docker containers for e2e testing..."
|
|
47
44
|
# CACHE_BUST to ensure the assemble step is always run
|
|
48
45
|
docker compose build --build-arg CACHE_BUST=$(date +%s) frontend
|
|
49
46
|
docker compose up -d
|
package/example.env
CHANGED
|
@@ -2,5 +2,19 @@
|
|
|
2
2
|
E2E_BASE_URL=http://localhost:8080/openmrs
|
|
3
3
|
E2E_USER_ADMIN_USERNAME=admin
|
|
4
4
|
E2E_USER_ADMIN_PASSWORD=Admin123
|
|
5
|
+
|
|
6
|
+
# "Outpatient Clinic" location UUID
|
|
5
7
|
E2E_LOGIN_DEFAULT_LOCATION_UUID=44c3efb0-2583-4c80-a79e-1f756a03c0a1
|
|
6
|
-
|
|
8
|
+
|
|
9
|
+
# Billing Module Test Configuration
|
|
10
|
+
# Default UUIDs from openmrs-content-referenceapplication-demo
|
|
11
|
+
# These should work if you're using the reference application demo data
|
|
12
|
+
|
|
13
|
+
# Cash Point UUID - OPD Cash Point from reference application demo
|
|
14
|
+
E2E_CASH_POINT_UUID=54065383-b4d4-42d2-af4d-d250a1fd2590
|
|
15
|
+
|
|
16
|
+
# Admin User UUID
|
|
17
|
+
E2E_USER_ADMIN_UUID=82f18b44-6814-11e8-923f-e9a88dcb533f
|
|
18
|
+
|
|
19
|
+
# Billable Service UUID - OPD Consultation from reference application demo
|
|
20
|
+
E2E_TEST_SERVICE_UUID=360fab13-d92b-4a9f-ad4e-0ac223e7f54c
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openmrs/esm-billing-app",
|
|
3
|
-
"version": "1.0.2-pre.
|
|
3
|
+
"version": "1.0.2-pre.1124",
|
|
4
4
|
"description": "O3 frontend module for handling billing concerns in healthcare settings",
|
|
5
5
|
"browser": "dist/openmrs-esm-billing-app.js",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"build": "webpack --mode production",
|
|
14
14
|
"coverage": "yarn test --coverage",
|
|
15
15
|
"debug": "npm run serve",
|
|
16
|
-
"extract-translations": "i18next 'src/**/*.component.tsx' 'src/index.ts' --config ./tools/i18next-parser.config.js",
|
|
16
|
+
"extract-translations": "i18next 'src/**/*.component.tsx' 'src/**/*.workspace.tsx' 'src/**/*.modal.tsx' 'src/index.ts' --config ./tools/i18next-parser.config.js",
|
|
17
17
|
"lint": "eslint src --ext ts,tsx --max-warnings=0",
|
|
18
18
|
"postinstall": "husky install",
|
|
19
19
|
"prettier": "prettier --config prettier.config.js --write \"src/**/*.{ts,tsx,css,scss}\" \"e2e/**/*.ts\"",
|
|
@@ -47,22 +47,22 @@
|
|
|
47
47
|
"fuzzy": "^0.1.3",
|
|
48
48
|
"lodash-es": "^4.17.21",
|
|
49
49
|
"react-hook-form": "^7.49.3",
|
|
50
|
-
"react-to-print": "^
|
|
50
|
+
"react-to-print": "^3.1.1",
|
|
51
51
|
"zod": "^3.22.4"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
|
54
|
-
"@openmrs/esm-framework": "
|
|
55
|
-
"@openmrs/esm-patient-common-lib": "
|
|
54
|
+
"@openmrs/esm-framework": "8.x",
|
|
55
|
+
"@openmrs/esm-patient-common-lib": "11.x",
|
|
56
56
|
"react": "18.x",
|
|
57
57
|
"react-dom": "18.x",
|
|
58
|
-
"react-i18next": "
|
|
58
|
+
"react-i18next": "16.x",
|
|
59
59
|
"rxjs": "6.x",
|
|
60
60
|
"swr": "2.x"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
63
|
"@openmrs/esm-framework": "next",
|
|
64
64
|
"@openmrs/esm-patient-common-lib": "next",
|
|
65
|
-
"@playwright/test": "^1.
|
|
65
|
+
"@playwright/test": "^1.53.2",
|
|
66
66
|
"@swc/cli": "^0.3.2",
|
|
67
67
|
"@swc/core": "^1.3.106",
|
|
68
68
|
"@swc/jest": "^0.2.31",
|
|
@@ -72,8 +72,8 @@
|
|
|
72
72
|
"@testing-library/user-event": "^14.5.2",
|
|
73
73
|
"@types/jest": "^29.5.11",
|
|
74
74
|
"@types/lodash-es": "^4.17.12",
|
|
75
|
-
"@types/react": "^18.
|
|
76
|
-
"@types/react-dom": "^18.
|
|
75
|
+
"@types/react": "^18.3.21",
|
|
76
|
+
"@types/react-dom": "^18.3.0",
|
|
77
77
|
"@types/webpack-env": "^1.18.4",
|
|
78
78
|
"@typescript-eslint/eslint-plugin": "^6.19.1",
|
|
79
79
|
"@typescript-eslint/parser": "^6.19.1",
|
|
@@ -86,10 +86,13 @@
|
|
|
86
86
|
"dotenv": "^16.4.1",
|
|
87
87
|
"eslint": "^8.56.0",
|
|
88
88
|
"eslint-plugin-import": "^2.31.0",
|
|
89
|
+
"eslint-plugin-jest-dom": "^5.5.0",
|
|
90
|
+
"eslint-plugin-playwright": "^2.2.2",
|
|
89
91
|
"eslint-plugin-react-hooks": "^5.0.0",
|
|
92
|
+
"eslint-plugin-testing-library": "^7.13.1",
|
|
90
93
|
"husky": "^9.0.6",
|
|
91
|
-
"i18next": "^
|
|
92
|
-
"i18next-parser": "^
|
|
94
|
+
"i18next": "^25.0.0",
|
|
95
|
+
"i18next-parser": "^9.3.0",
|
|
93
96
|
"identity-obj-proxy": "^3.0.0",
|
|
94
97
|
"jest": "^29.7.0",
|
|
95
98
|
"jest-cli": "^29.7.0",
|
|
@@ -99,16 +102,16 @@
|
|
|
99
102
|
"openmrs": "next",
|
|
100
103
|
"pinst": "^3.0.0",
|
|
101
104
|
"prettier": "^3.2.4",
|
|
102
|
-
"react": "^18.
|
|
103
|
-
"react-dom": "^18.
|
|
104
|
-
"react-i18next": "^
|
|
105
|
+
"react": "^18.3.1",
|
|
106
|
+
"react-dom": "^18.3.1",
|
|
107
|
+
"react-i18next": "^16.0.0",
|
|
105
108
|
"react-router-dom": "^6.21.3",
|
|
106
109
|
"rxjs": "^6.6.7",
|
|
107
110
|
"sass": "^1.70.0",
|
|
108
111
|
"swc-loader": "^0.2.3",
|
|
109
112
|
"swr": "^2.2.4",
|
|
110
113
|
"turbo": "^2.5.2",
|
|
111
|
-
"typescript": "^
|
|
114
|
+
"typescript": "^5.0.0",
|
|
112
115
|
"webpack": "^5.99.9",
|
|
113
116
|
"webpack-cli": "^6.0.1",
|
|
114
117
|
"webpack-dev-server": "^5.2.1"
|
|
@@ -117,6 +120,6 @@
|
|
|
117
120
|
"*.{ts,tsx}": "eslint --cache --fix --max-warnings 0",
|
|
118
121
|
"*.{css,scss,ts,tsx}": "prettier --write --list-different"
|
|
119
122
|
},
|
|
120
|
-
"packageManager": "yarn@4.
|
|
123
|
+
"packageManager": "yarn@4.10.3",
|
|
121
124
|
"stableVersion": "1.0.1"
|
|
122
125
|
}
|
package/playwright.config.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { devices, PlaywrightTestConfig } from '@playwright/test';
|
|
1
|
+
import { devices, type PlaywrightTestConfig } from '@playwright/test';
|
|
2
2
|
import * as dotenv from 'dotenv';
|
|
3
3
|
dotenv.config();
|
|
4
4
|
|
|
@@ -7,7 +7,7 @@ const config: PlaywrightTestConfig = {
|
|
|
7
7
|
testDir: './e2e/specs',
|
|
8
8
|
timeout: 3 * 60 * 1000,
|
|
9
9
|
expect: {
|
|
10
|
-
timeout:
|
|
10
|
+
timeout: 20 * 1000,
|
|
11
11
|
},
|
|
12
12
|
fullyParallel: true,
|
|
13
13
|
forbidOnly: !!process.env.CI,
|
|
@@ -16,7 +16,9 @@ const config: PlaywrightTestConfig = {
|
|
|
16
16
|
globalSetup: require.resolve('./e2e/core/global-setup'),
|
|
17
17
|
use: {
|
|
18
18
|
baseURL: `${process.env.E2E_BASE_URL}/spa/`,
|
|
19
|
+
locale: 'en-US',
|
|
19
20
|
storageState: 'e2e/storageState.json',
|
|
21
|
+
trace: 'retain-on-failure',
|
|
20
22
|
video: 'retain-on-failure',
|
|
21
23
|
},
|
|
22
24
|
projects: [
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
2
|
import { useTranslation } from 'react-i18next';
|
|
3
3
|
import {
|
|
4
4
|
Button,
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
Tile,
|
|
20
20
|
} from '@carbon/react';
|
|
21
21
|
import { Add } from '@carbon/react/icons';
|
|
22
|
-
import {
|
|
22
|
+
import { launchWorkspace, useConfig, usePagination } from '@openmrs/esm-framework';
|
|
23
23
|
import { CardHeader, EmptyDataIllustration, ErrorState, usePaginationInfo } from '@openmrs/esm-patient-common-lib';
|
|
24
24
|
import { convertToCurrency } from '../helpers';
|
|
25
25
|
import { useBills } from '../billing.resource';
|
|
@@ -33,11 +33,9 @@ interface BillHistoryProps {
|
|
|
33
33
|
const BillHistory: React.FC<BillHistoryProps> = ({ patientUuid }) => {
|
|
34
34
|
const { t } = useTranslation();
|
|
35
35
|
const { bills, isLoading, error } = useBills(patientUuid);
|
|
36
|
-
const layout = useLayoutType();
|
|
37
|
-
const responsiveSize = isDesktop(layout) ? 'sm' : 'lg';
|
|
38
36
|
const { paginated, goTo, results, currentPage } = usePagination(bills);
|
|
39
37
|
const { pageSize, defaultCurrency } = useConfig();
|
|
40
|
-
const [currentPageSize, setCurrentPageSize] =
|
|
38
|
+
const [currentPageSize, setCurrentPageSize] = useState(pageSize);
|
|
41
39
|
const { pageSizes } = usePaginationInfo(pageSize, bills?.length, currentPage, results?.length);
|
|
42
40
|
|
|
43
41
|
const headerData = [
|
|
@@ -74,7 +72,7 @@ const BillHistory: React.FC<BillHistoryProps> = ({ patientUuid }) => {
|
|
|
74
72
|
if (isLoading) {
|
|
75
73
|
return (
|
|
76
74
|
<div className={styles.loaderContainer}>
|
|
77
|
-
<DataTableSkeleton showHeader={false} showToolbar={false} zebra size=
|
|
75
|
+
<DataTableSkeleton showHeader={false} showToolbar={false} zebra size="md" />
|
|
78
76
|
</div>
|
|
79
77
|
);
|
|
80
78
|
}
|
|
@@ -83,7 +81,7 @@ const BillHistory: React.FC<BillHistoryProps> = ({ patientUuid }) => {
|
|
|
83
81
|
return (
|
|
84
82
|
<div className={styles.errorContainer}>
|
|
85
83
|
<Layer>
|
|
86
|
-
<ErrorState error={error} headerTitle={t('
|
|
84
|
+
<ErrorState error={error} headerTitle={t('billList', 'Bill list')} />
|
|
87
85
|
</Layer>
|
|
88
86
|
</div>
|
|
89
87
|
);
|
|
@@ -109,22 +107,22 @@ const BillHistory: React.FC<BillHistoryProps> = ({ patientUuid }) => {
|
|
|
109
107
|
<div>
|
|
110
108
|
<CardHeader title={t('billingHistory', 'Billing History')}>
|
|
111
109
|
<Button renderIcon={Add} onClick={() => launchWorkspace('billing-form-workspace', {})} kind="ghost">
|
|
112
|
-
{t('addBill', 'Add bill
|
|
110
|
+
{t('addBill', 'Add bill items')}
|
|
113
111
|
</Button>
|
|
114
112
|
</CardHeader>
|
|
115
113
|
<div className={styles.billHistoryContainer}>
|
|
116
|
-
<DataTable isSortable rows={rowData} headers={headerData} size=
|
|
114
|
+
<DataTable isSortable rows={rowData} headers={headerData} size="md" useZebraStyles>
|
|
117
115
|
{({
|
|
118
|
-
rows,
|
|
119
|
-
headers,
|
|
120
116
|
getExpandHeaderProps,
|
|
121
|
-
getTableProps,
|
|
122
|
-
getTableContainerProps,
|
|
123
117
|
getHeaderProps,
|
|
124
118
|
getRowProps,
|
|
119
|
+
getTableContainerProps,
|
|
120
|
+
getTableProps,
|
|
121
|
+
headers,
|
|
122
|
+
rows,
|
|
125
123
|
}) => (
|
|
126
124
|
<TableContainer {...getTableContainerProps}>
|
|
127
|
-
<Table className={styles.table} {...getTableProps()} aria-label=
|
|
125
|
+
<Table className={styles.table} {...getTableProps()} aria-label={t('billList', 'Bill list')}>
|
|
128
126
|
<TableHead>
|
|
129
127
|
<TableRow>
|
|
130
128
|
<TableExpandHeader enableToggle {...getExpandHeaderProps()} />
|
|
@@ -153,9 +151,9 @@ const BillHistory: React.FC<BillHistoryProps> = ({ patientUuid }) => {
|
|
|
153
151
|
))}
|
|
154
152
|
</TableExpandRow>
|
|
155
153
|
{row.isExpanded ? (
|
|
156
|
-
<TableExpandedRow
|
|
154
|
+
<TableExpandedRow colSpan={headers.length + 1}>
|
|
157
155
|
<div className={styles.container} key={i}>
|
|
158
|
-
<InvoiceTable bill={currentBill}
|
|
156
|
+
<InvoiceTable bill={currentBill} />
|
|
159
157
|
</div>
|
|
160
158
|
</TableExpandedRow>
|
|
161
159
|
) : (
|
|
@@ -178,7 +176,7 @@ const BillHistory: React.FC<BillHistoryProps> = ({ patientUuid }) => {
|
|
|
178
176
|
pageSizes={pageSizes}
|
|
179
177
|
totalItems={bills.length}
|
|
180
178
|
className={styles.pagination}
|
|
181
|
-
size=
|
|
179
|
+
size="md"
|
|
182
180
|
onChange={({ page: newPage, pageSize }) => {
|
|
183
181
|
if (newPage !== currentPage) {
|
|
184
182
|
goTo(newPage);
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
@use '@openmrs/esm-styleguide/src/vars' as *;
|
|
4
4
|
|
|
5
5
|
.container {
|
|
6
|
-
margin: layout.$spacing-
|
|
6
|
+
margin: layout.$spacing-03 0;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
.emptyStateContainer,
|
|
@@ -21,27 +21,8 @@
|
|
|
21
21
|
padding-bottom: 0;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
.
|
|
25
|
-
|
|
26
|
-
justify-content: space-between;
|
|
27
|
-
align-items: center;
|
|
28
|
-
padding: layout.$spacing-04 0 layout.$spacing-04 layout.$spacing-05;
|
|
29
|
-
background-color: $ui-02;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
.backgroundDataFetchingIndicator {
|
|
33
|
-
align-items: center;
|
|
34
|
-
display: flex;
|
|
35
|
-
flex: 1 1 0%;
|
|
36
|
-
justify-content: center;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
.tableContainer section {
|
|
40
|
-
position: relative;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
.tableContainer a {
|
|
44
|
-
text-decoration: none;
|
|
24
|
+
.errorContainer {
|
|
25
|
+
@extend .container;
|
|
45
26
|
}
|
|
46
27
|
|
|
47
28
|
.pagination {
|
|
@@ -56,34 +37,6 @@
|
|
|
56
37
|
display: none;
|
|
57
38
|
}
|
|
58
39
|
|
|
59
|
-
.emptyRow {
|
|
60
|
-
padding: 0 layout.$spacing-05;
|
|
61
|
-
display: flex;
|
|
62
|
-
align-items: center;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
.visitSummaryContainer {
|
|
66
|
-
width: 100%;
|
|
67
|
-
max-width: 768px;
|
|
68
|
-
margin: layout.$spacing-05 auto;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
.expandedActiveVisitRow > td > div {
|
|
72
|
-
max-height: max-content !important;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
.expandedActiveVisitRow td {
|
|
76
|
-
padding: 0 layout.$spacing-07;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
.expandedActiveVisitRow th[colspan] td[colspan] > div:first-child {
|
|
80
|
-
padding: 0 layout.$spacing-05;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
.action {
|
|
84
|
-
margin-bottom: layout.$spacing-03;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
40
|
.illo {
|
|
88
41
|
margin-top: layout.$spacing-05;
|
|
89
42
|
}
|
|
@@ -95,55 +48,11 @@
|
|
|
95
48
|
margin-bottom: layout.$spacing-03;
|
|
96
49
|
}
|
|
97
50
|
|
|
98
|
-
.desktopHeading,
|
|
99
|
-
.tabletHeading {
|
|
100
|
-
text-align: left;
|
|
101
|
-
text-transform: capitalize;
|
|
102
|
-
|
|
103
|
-
h4 {
|
|
104
|
-
@include type.type-style('heading-compact-02');
|
|
105
|
-
color: $text-02;
|
|
106
|
-
|
|
107
|
-
&:after {
|
|
108
|
-
content: '';
|
|
109
|
-
display: block;
|
|
110
|
-
width: layout.$spacing-07;
|
|
111
|
-
padding-top: 3px;
|
|
112
|
-
border-bottom: 0.375rem solid;
|
|
113
|
-
@include brand-03(border-bottom-color);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
51
|
.tile {
|
|
119
52
|
text-align: center;
|
|
120
53
|
border: 1px solid $ui-03;
|
|
121
54
|
}
|
|
122
55
|
|
|
123
|
-
.filterEmptyState {
|
|
124
|
-
display: flex;
|
|
125
|
-
justify-content: center;
|
|
126
|
-
align-items: center;
|
|
127
|
-
padding: layout.$spacing-05;
|
|
128
|
-
margin: layout.$spacing-09;
|
|
129
|
-
text-align: center;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
.filterEmptyStateTile {
|
|
133
|
-
margin: auto;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
.filterEmptyStateContent {
|
|
137
|
-
@include type.type-style('heading-compact-02');
|
|
138
|
-
color: $text-02;
|
|
139
|
-
margin-bottom: 0.5rem;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
.filterEmptyStateHelper {
|
|
143
|
-
@include type.type-style('body-compact-01');
|
|
144
|
-
color: $text-02;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
56
|
.table {
|
|
148
57
|
width: 100%;
|
|
149
58
|
table-layout: fixed; // This helps with uniform column sizing
|
|
@@ -156,6 +65,7 @@
|
|
|
156
65
|
text-overflow: unset;
|
|
157
66
|
}
|
|
158
67
|
}
|
|
68
|
+
|
|
159
69
|
:global(tr.cds--parent-row.cds--expandable-row + tr[data-child-row]) td {
|
|
160
70
|
padding-left: layout.$spacing-05;
|
|
161
71
|
}
|
|
@@ -1,17 +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 { getDefaultsFromConfigSchema, useConfig } from '@openmrs/esm-framework';
|
|
5
|
+
import { configSchema, type BillingConfig } from '../config-schema';
|
|
4
6
|
import { useBills } from '../billing.resource';
|
|
5
7
|
import BillHistory from './bill-history.component';
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
jest.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
const mockUseConfig = jest.mocked(useConfig<BillingConfig>);
|
|
10
|
+
const mockUseBills = jest.mocked(useBills);
|
|
11
|
+
|
|
12
|
+
jest.mock('../billing.resource', () => ({
|
|
13
|
+
useBills: jest.fn(() => ({
|
|
14
|
+
bills: mockBillData,
|
|
15
|
+
isLoading: false,
|
|
16
|
+
isValidating: false,
|
|
17
|
+
error: null,
|
|
18
|
+
})),
|
|
12
19
|
}));
|
|
13
20
|
|
|
14
|
-
// Mock window.i18next
|
|
15
21
|
window.i18next = {
|
|
16
22
|
language: 'en-US',
|
|
17
23
|
} as any;
|
|
@@ -20,9 +26,7 @@ const testProps = {
|
|
|
20
26
|
patientUuid: 'some-uuid',
|
|
21
27
|
};
|
|
22
28
|
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
const mockBillsData = [
|
|
29
|
+
const mockBillData = [
|
|
26
30
|
{ uuid: '1', patientName: 'John Doe', identifier: '12345678', billingService: 'Checkup', totalAmount: 500 },
|
|
27
31
|
{ uuid: '2', patientName: 'John Doe', identifier: '12345678', billingService: 'Consulatation', totalAmount: 600 },
|
|
28
32
|
{ uuid: '3', patientName: 'John Doe', identifier: '12345678', billingService: 'Child services', totalAmount: 700 },
|
|
@@ -37,69 +41,19 @@ const mockBillsData = [
|
|
|
37
41
|
{ uuid: '12', patientName: 'John Doe', identifier: '12345678', billingService: 'MCH', totalAmount: 1300 },
|
|
38
42
|
];
|
|
39
43
|
|
|
40
|
-
// Mock the invoice table component
|
|
41
|
-
jest.mock('../invoice/invoice-table.component', () => jest.fn(() => <div>Invoice table</div>));
|
|
42
|
-
|
|
43
|
-
// Mock the billing resource
|
|
44
|
-
jest.mock('../billing.resource', () => ({
|
|
45
|
-
useBills: jest.fn(() => ({
|
|
46
|
-
bills: mockBillsData,
|
|
47
|
-
isLoading: false,
|
|
48
|
-
isValidating: false,
|
|
49
|
-
error: null,
|
|
50
|
-
})),
|
|
51
|
-
}));
|
|
52
|
-
|
|
53
|
-
// Mock esm-patient-common-lib
|
|
54
|
-
jest.mock('@openmrs/esm-patient-common-lib', () => ({
|
|
55
|
-
CardHeader: jest.fn(({ children }) => <div>{children}</div>),
|
|
56
|
-
EmptyDataIllustration: jest.fn(() => <div>Empty state illustration</div>),
|
|
57
|
-
ErrorState: jest.fn(({ error }) => <div>Error: {error?.message}</div>),
|
|
58
|
-
usePaginationInfo: jest.fn(() => ({
|
|
59
|
-
pageSizes: [10, 20, 30],
|
|
60
|
-
currentPage: 1,
|
|
61
|
-
})),
|
|
62
|
-
}));
|
|
63
|
-
|
|
64
|
-
// Mock esm-framework
|
|
65
|
-
jest.mock('@openmrs/esm-framework', () => ({
|
|
66
|
-
useLayoutType: jest.fn(() => 'small-desktop'),
|
|
67
|
-
isDesktop: jest.fn(() => true),
|
|
68
|
-
usePagination: jest.fn().mockImplementation((data) => ({
|
|
69
|
-
currentPage: 1,
|
|
70
|
-
goTo: jest.fn(),
|
|
71
|
-
results: data,
|
|
72
|
-
paginated: true,
|
|
73
|
-
})),
|
|
74
|
-
showToast: jest.fn(),
|
|
75
|
-
showNotification: jest.fn(),
|
|
76
|
-
createErrorHandler: jest.fn(),
|
|
77
|
-
createGlobalStore: jest.fn(),
|
|
78
|
-
getGlobalStore: jest.fn(() => ({
|
|
79
|
-
subscribe: jest.fn(),
|
|
80
|
-
getState: jest.fn(),
|
|
81
|
-
setState: jest.fn(),
|
|
82
|
-
})),
|
|
83
|
-
useConfig: jest.fn(() => ({
|
|
84
|
-
pageSize: 10,
|
|
85
|
-
defaultCurrency: 'USD',
|
|
86
|
-
})),
|
|
87
|
-
useSession: jest.fn(() => ({
|
|
88
|
-
sessionLocation: { uuid: 'some-uuid', display: 'Location' },
|
|
89
|
-
})),
|
|
90
|
-
formatDate: jest.fn((date) => date?.toString() ?? ''),
|
|
91
|
-
formatDatetime: jest.fn((date) => date?.toString() ?? ''),
|
|
92
|
-
parseDate: jest.fn((dateString) => new Date(dateString)),
|
|
93
|
-
ExtensionSlot: jest.fn(({ children }) => <>{children}</>),
|
|
94
|
-
}));
|
|
95
|
-
|
|
96
44
|
describe('BillHistory', () => {
|
|
97
|
-
|
|
98
|
-
|
|
45
|
+
beforeEach(() => {
|
|
46
|
+
mockUseConfig.mockReturnValue({ ...getDefaultsFromConfigSchema(configSchema), defaultCurrency: 'USD' });
|
|
99
47
|
});
|
|
100
48
|
|
|
101
49
|
test('should render loading datatable skeleton', () => {
|
|
102
|
-
|
|
50
|
+
mockUseBills.mockReturnValueOnce({
|
|
51
|
+
isLoading: true,
|
|
52
|
+
isValidating: false,
|
|
53
|
+
error: null,
|
|
54
|
+
bills: [],
|
|
55
|
+
mutate: jest.fn(),
|
|
56
|
+
});
|
|
103
57
|
render(<BillHistory {...testProps} />);
|
|
104
58
|
const loadingSkeleton = screen.getByRole('table');
|
|
105
59
|
expect(loadingSkeleton).toBeInTheDocument();
|
|
@@ -107,7 +61,7 @@ describe('BillHistory', () => {
|
|
|
107
61
|
});
|
|
108
62
|
|
|
109
63
|
test('should render error state when API call fails', () => {
|
|
110
|
-
|
|
64
|
+
mockUseBills.mockReturnValueOnce({
|
|
111
65
|
isLoading: false,
|
|
112
66
|
isValidating: false,
|
|
113
67
|
error: new Error('some error'),
|
|
@@ -115,31 +69,31 @@ describe('BillHistory', () => {
|
|
|
115
69
|
mutate: jest.fn(),
|
|
116
70
|
});
|
|
117
71
|
render(<BillHistory {...testProps} />);
|
|
118
|
-
const errorState = screen.getByText(
|
|
72
|
+
const errorState = screen.getByText(/Error/);
|
|
119
73
|
expect(errorState).toBeInTheDocument();
|
|
120
74
|
});
|
|
121
75
|
|
|
122
76
|
test('should render bills table', async () => {
|
|
123
77
|
const user = userEvent.setup();
|
|
124
|
-
|
|
78
|
+
mockUseBills.mockReturnValueOnce({
|
|
125
79
|
isLoading: false,
|
|
126
80
|
isValidating: false,
|
|
127
81
|
error: null,
|
|
128
|
-
bills:
|
|
82
|
+
bills: mockBillData as any,
|
|
129
83
|
mutate: jest.fn(),
|
|
130
84
|
});
|
|
131
85
|
render(<BillHistory {...testProps} />);
|
|
132
86
|
|
|
133
87
|
// Verify headers
|
|
134
|
-
expect(screen.getByText('
|
|
135
|
-
expect(screen.getByText('
|
|
88
|
+
expect(screen.getByText('Visit time')).toBeInTheDocument();
|
|
89
|
+
expect(screen.getByText('Identifier')).toBeInTheDocument();
|
|
136
90
|
|
|
137
91
|
const tableRowGroup = screen.getAllByRole('rowgroup');
|
|
138
92
|
expect(tableRowGroup).toHaveLength(2);
|
|
139
93
|
|
|
140
94
|
// Page navigation should work as expected
|
|
141
|
-
const nextPageButton = screen.getByRole('button', { name: /
|
|
142
|
-
const prevPageButton = screen.getByRole('button', { name: /
|
|
95
|
+
const nextPageButton = screen.getByRole('button', { name: /Next page/ });
|
|
96
|
+
const prevPageButton = screen.getByRole('button', { name: /Previous page/ });
|
|
143
97
|
|
|
144
98
|
expect(nextPageButton).toBeInTheDocument();
|
|
145
99
|
expect(prevPageButton).toBeInTheDocument();
|
|
@@ -155,7 +109,13 @@ describe('BillHistory', () => {
|
|
|
155
109
|
});
|
|
156
110
|
|
|
157
111
|
test('should render empty state view when there are no bills', () => {
|
|
158
|
-
|
|
112
|
+
mockUseBills.mockReturnValueOnce({
|
|
113
|
+
isLoading: false,
|
|
114
|
+
isValidating: false,
|
|
115
|
+
error: null,
|
|
116
|
+
bills: [],
|
|
117
|
+
mutate: jest.fn(),
|
|
118
|
+
});
|
|
159
119
|
render(<BillHistory {...testProps} />);
|
|
160
120
|
const emptyState = screen.getByText(/There are no bills to display./);
|
|
161
121
|
expect(emptyState).toBeInTheDocument();
|