@openmrs/esm-stock-management-app 1.0.1-pre.706 → 1.0.1-pre.716
Sign up to get free protection for your applications and to get access to all the features.
- package/.eslintrc +9 -1
- package/dist/973.js +1 -1
- package/dist/973.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-stock-management-app.js.buildmanifest.json +6 -6
- package/dist/routes.json +1 -1
- package/e2e/README.md +117 -0
- package/e2e/core/global-setup.ts +32 -0
- package/e2e/core/index.ts +1 -0
- package/e2e/core/test.ts +20 -0
- package/e2e/fixtures/api.ts +26 -0
- package/e2e/fixtures/index.ts +1 -0
- package/e2e/pages/chart-page.ts +11 -0
- package/e2e/pages/home-page.ts +9 -0
- package/e2e/pages/index.ts +2 -0
- package/e2e/specs/stock-overview-test.spec.ts +19 -0
- package/e2e/support/github/Dockerfile +34 -0
- package/e2e/support/github/docker-compose.yml +24 -0
- package/e2e/support/github/run-e2e-docker-env.sh +49 -0
- package/example.env +6 -0
- package/jest.config.js +5 -1
- package/package.json +5 -2
- package/playwright.config.ts +34 -0
- package/src/stock-operations/add-stock-operation/validationSchema.ts +13 -0
@@ -134,10 +134,10 @@
|
|
134
134
|
"initial": true,
|
135
135
|
"entry": true,
|
136
136
|
"recorded": false,
|
137
|
-
"size":
|
137
|
+
"size": 5409050,
|
138
138
|
"sizes": {
|
139
139
|
"consume-shared": 252,
|
140
|
-
"javascript":
|
140
|
+
"javascript": 5387101,
|
141
141
|
"share-init": 252,
|
142
142
|
"runtime": 21445
|
143
143
|
},
|
@@ -154,7 +154,7 @@
|
|
154
154
|
"auxiliaryFiles": [
|
155
155
|
"main.js.map"
|
156
156
|
],
|
157
|
-
"hash": "
|
157
|
+
"hash": "549717c7f94ac2f7",
|
158
158
|
"childrenByOrder": {}
|
159
159
|
},
|
160
160
|
{
|
@@ -607,9 +607,9 @@
|
|
607
607
|
"initial": false,
|
608
608
|
"entry": false,
|
609
609
|
"recorded": false,
|
610
|
-
"size":
|
610
|
+
"size": 1750178,
|
611
611
|
"sizes": {
|
612
|
-
"javascript":
|
612
|
+
"javascript": 1749968,
|
613
613
|
"consume-shared": 210
|
614
614
|
},
|
615
615
|
"names": [],
|
@@ -623,7 +623,7 @@
|
|
623
623
|
"auxiliaryFiles": [
|
624
624
|
"973.js.map"
|
625
625
|
],
|
626
|
-
"hash": "
|
626
|
+
"hash": "3c6bcfc1834a0d12",
|
627
627
|
"childrenByOrder": {}
|
628
628
|
}
|
629
629
|
]
|
package/dist/routes.json
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"fhir2":">=1.2","webservices.rest":"^2.24.0"},"extensions":[{"name":"stock-nav-menu","slot":"stock-sidebar-slot","component":"stockNavMenu","online":true,"offline":true},{"name":"overview-db-link","slot":"stock-page-dashboard-slot","component":"stockOverviewLink","meta":{"name":"overview","slot":"overview-dashboard-slot","title":"overview"},"order":0,"online":true,"offline":true},{"name":"stock-overview-db","slot":"overview-dashboard-slot","component":"stockOverview"},{"name":"operations-db-link","slot":"stock-page-dashboard-slot","component":"stockOperationsLink","meta":{"name":"operations","slot":"operations-dashboard-slot","title":"operations"},"order":2,"online":true,"offline":true},{"name":"stock-operations-db","slot":"operations-dashboard-slot","component":"stockOperations"},{"name":"items-db-link","slot":"stock-page-dashboard-slot","component":"stockItemsLink","meta":{"name":"items","slot":"items-dashboard-slot","title":"items"},"order":1,"online":true,"offline":true},{"name":"stock-items-db","slot":"items-dashboard-slot","component":"stockItems"},{"name":"user-scopes-db-link","slot":"stock-page-dashboard-slot","component":"stockUserScopesLink","meta":{"name":"user-scopes","slot":"user-scopes-dashboard-slot","title":"user-scopes"},"order":3,"online":true,"offline":true},{"name":"stock-user-scopes-db","slot":"user-scopes-dashboard-slot","component":"stockUserScopes"},{"name":"sources-db-link","slot":"stock-page-dashboard-slot","component":"stockSourcesLink","meta":{"name":"sources","slot":"sources-dashboard-slot","title":"Sources"},"order":2,"online":true,"offline":true},{"name":"stock-sources-db","slot":"sources-dashboard-slot","component":"stockSources"},{"name":"locations-db-link","slot":"stock-page-dashboard-slot","component":"stockLocationsLink","meta":{"name":"locations","slot":"locations-dashboard-slot","title":"Locations"},"order":4,"online":true,"offline":true},{"name":"stock-locations-db","slot":"locations-dashboard-slot","component":"stockLocations"},{"name":"reports-db-link","slot":"stock-page-dashboard-slot","component":"stockReportsLink","meta":{"name":"reports","slot":"reports-dashboard-slot","title":"Reports"},"order":5,"online":true,"offline":true},{"name":"stock-reports-db","slot":"reports-dashboard-slot","component":"stockReports"},{"name":"settings-db-link","slot":"stock-page-dashboard-slot","component":"stockSettingsLink","meta":{"name":"settings","slot":"settings-dashboard-slot","title":"Settings"},"order":6,"online":true,"offline":true},{"name":"stock-settings-db","slot":"settings-dashboard-slot","component":"stockSettings"},{"name":"stock-management-admin-card-link","slot":"system-admin-page-card-link-slot","component":"stockManagementAdminCardLink"},{"name":"stock-management-app-menu-item","component":"stockManagementAppMenuItem","slot":"app-menu-item-slot","meta":{"name":" Stock Management"}},{"name":"delete-packaging-unit-button","component":"deletePackagingUnitButton"}],"modals":[{"name":"delete-stock-modal","component":"deleteStockModal"},{"name":"delete-stock-user-scope-modal","component":"deleteUserScopeModal"},{"name":"delete-stock-rule-modal","component":"deleteStockRuleModal"},{"name":"delete-packaging-unit-modal","component":"deletePackagingUnitModal"},{"name":"import-bulk-stock-items","component":"importBulkStockItemsModal"},{"name":"stock-operation-dialog","component":"stockOperationModal"}],"pages":[{"component":"root","route":"stock-management"}],"version":"1.0.1-pre.
|
1
|
+
{"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"fhir2":">=1.2","webservices.rest":"^2.24.0"},"extensions":[{"name":"stock-nav-menu","slot":"stock-sidebar-slot","component":"stockNavMenu","online":true,"offline":true},{"name":"overview-db-link","slot":"stock-page-dashboard-slot","component":"stockOverviewLink","meta":{"name":"overview","slot":"overview-dashboard-slot","title":"overview"},"order":0,"online":true,"offline":true},{"name":"stock-overview-db","slot":"overview-dashboard-slot","component":"stockOverview"},{"name":"operations-db-link","slot":"stock-page-dashboard-slot","component":"stockOperationsLink","meta":{"name":"operations","slot":"operations-dashboard-slot","title":"operations"},"order":2,"online":true,"offline":true},{"name":"stock-operations-db","slot":"operations-dashboard-slot","component":"stockOperations"},{"name":"items-db-link","slot":"stock-page-dashboard-slot","component":"stockItemsLink","meta":{"name":"items","slot":"items-dashboard-slot","title":"items"},"order":1,"online":true,"offline":true},{"name":"stock-items-db","slot":"items-dashboard-slot","component":"stockItems"},{"name":"user-scopes-db-link","slot":"stock-page-dashboard-slot","component":"stockUserScopesLink","meta":{"name":"user-scopes","slot":"user-scopes-dashboard-slot","title":"user-scopes"},"order":3,"online":true,"offline":true},{"name":"stock-user-scopes-db","slot":"user-scopes-dashboard-slot","component":"stockUserScopes"},{"name":"sources-db-link","slot":"stock-page-dashboard-slot","component":"stockSourcesLink","meta":{"name":"sources","slot":"sources-dashboard-slot","title":"Sources"},"order":2,"online":true,"offline":true},{"name":"stock-sources-db","slot":"sources-dashboard-slot","component":"stockSources"},{"name":"locations-db-link","slot":"stock-page-dashboard-slot","component":"stockLocationsLink","meta":{"name":"locations","slot":"locations-dashboard-slot","title":"Locations"},"order":4,"online":true,"offline":true},{"name":"stock-locations-db","slot":"locations-dashboard-slot","component":"stockLocations"},{"name":"reports-db-link","slot":"stock-page-dashboard-slot","component":"stockReportsLink","meta":{"name":"reports","slot":"reports-dashboard-slot","title":"Reports"},"order":5,"online":true,"offline":true},{"name":"stock-reports-db","slot":"reports-dashboard-slot","component":"stockReports"},{"name":"settings-db-link","slot":"stock-page-dashboard-slot","component":"stockSettingsLink","meta":{"name":"settings","slot":"settings-dashboard-slot","title":"Settings"},"order":6,"online":true,"offline":true},{"name":"stock-settings-db","slot":"settings-dashboard-slot","component":"stockSettings"},{"name":"stock-management-admin-card-link","slot":"system-admin-page-card-link-slot","component":"stockManagementAdminCardLink"},{"name":"stock-management-app-menu-item","component":"stockManagementAppMenuItem","slot":"app-menu-item-slot","meta":{"name":" Stock Management"}},{"name":"delete-packaging-unit-button","component":"deletePackagingUnitButton"}],"modals":[{"name":"delete-stock-modal","component":"deleteStockModal"},{"name":"delete-stock-user-scope-modal","component":"deleteUserScopeModal"},{"name":"delete-stock-rule-modal","component":"deleteStockRuleModal"},{"name":"delete-packaging-unit-modal","component":"deletePackagingUnitModal"},{"name":"import-bulk-stock-items","component":"importBulkStockItemsModal"},{"name":"stock-operation-dialog","component":"stockOperationModal"}],"pages":[{"component":"root","route":"stock-management"}],"version":"1.0.1-pre.716"}
|
package/e2e/README.md
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
# E2E Tests
|
2
|
+
|
3
|
+
This directory contains an E2E test suite using the [Playwright](https://playwright.dev)
|
4
|
+
framework.
|
5
|
+
|
6
|
+
## Getting Started
|
7
|
+
|
8
|
+
Please ensure that you have followed the basic installation guide in the [root README](../README.md). Once everything is set up, make sure the dev server is running by using:
|
9
|
+
|
10
|
+
```sh
|
11
|
+
yarn start
|
12
|
+
```
|
13
|
+
|
14
|
+
Then, in a separate terminal, run:
|
15
|
+
|
16
|
+
```sh
|
17
|
+
yarn test-e2e --headed
|
18
|
+
```
|
19
|
+
|
20
|
+
By default, the test suite will run against the http://localhost:8080. You can override this by exporting `E2E_BASE_URL` environment variables beforehand:
|
21
|
+
|
22
|
+
```sh
|
23
|
+
# Ex: Set the server URL to dev3:
|
24
|
+
export E2E_BASE_URL=https://dev3.openmrs.org/openmrs
|
25
|
+
|
26
|
+
# Run all e2e tests:
|
27
|
+
|
28
|
+
```sh
|
29
|
+
yarn test-e2e --headed
|
30
|
+
```
|
31
|
+
|
32
|
+
To run a specific test by title:
|
33
|
+
|
34
|
+
```sh
|
35
|
+
yarn test-e2e --headed -g "title of the test"
|
36
|
+
```
|
37
|
+
|
38
|
+
Check [this documentation](https://playwright.dev/docs/running-tests#command-line) for more running options.
|
39
|
+
|
40
|
+
It is also highly recommended to install the companion VS Code extension:
|
41
|
+
https://playwright.dev/docs/getting-started-vscode
|
42
|
+
|
43
|
+
## Writing New Tests
|
44
|
+
|
45
|
+
In general, it is recommended to read through the official [Playwright docs](https://playwright.dev/docs/intro)
|
46
|
+
before writing new test cases. The project uses the official Playwright test runner and,
|
47
|
+
generally, follows a very simple project structure:
|
48
|
+
|
49
|
+
```
|
50
|
+
e2e
|
51
|
+
|__ commands
|
52
|
+
| ^ Contains "commands" (simple reusable functions) that can be used in test cases/specs,
|
53
|
+
| e.g. generate a random patient.
|
54
|
+
|__ core
|
55
|
+
| ^ Contains code related to the test runner itself, e.g. setting up the custom fixtures.
|
56
|
+
| You probably need to touch this infrequently.
|
57
|
+
|__ fixtures
|
58
|
+
| ^ Contains fixtures (https://playwright.dev/docs/test-fixtures) which are used
|
59
|
+
| to run reusable setup/teardown tasks
|
60
|
+
|__ pages
|
61
|
+
| ^ Contains page object model classes for interacting with the frontend.
|
62
|
+
| See https://playwright.dev/docs/test-pom for details.
|
63
|
+
|__ specs
|
64
|
+
| ^ Contains the actual test cases/specs. New tests should be placed in this folder.
|
65
|
+
|__ support
|
66
|
+
^ Contains support files that requires to run e2e tests, e.g. docker compose files.
|
67
|
+
```
|
68
|
+
|
69
|
+
When you want to write a new test case, start by creating a new spec in `./specs`.
|
70
|
+
Depending on what you want to achieve, you might want to create new fixtures and/or
|
71
|
+
page object models. To see examples, have a look at the existing code to see how these
|
72
|
+
different concepts play together.
|
73
|
+
|
74
|
+
## Open reports from GitHub Actions / Bamboo
|
75
|
+
|
76
|
+
To download the report from the GitHub action/Bamboo plan, follow these steps:
|
77
|
+
|
78
|
+
1. Go to the artifact section of the action/plan and locate the report file.
|
79
|
+
2. Download the report file and unzip it using a tool of your choice.
|
80
|
+
3. Open the index.html file in a web browser to view the report.
|
81
|
+
|
82
|
+
The report will show you a full summary of your tests, including information on which
|
83
|
+
tests passed, failed, were skipped, or were flaky. You can filter the report by browser
|
84
|
+
and explore the details of individual tests, including any errors or failures, video
|
85
|
+
recordings, and the steps involved in each test. Simply click on a test to view its details.
|
86
|
+
|
87
|
+
## Debugging Tests
|
88
|
+
|
89
|
+
Refer to [this documentation](https://playwright.dev/docs/debug) on how to debug a test.
|
90
|
+
|
91
|
+
## Configuration
|
92
|
+
|
93
|
+
This is very much underdeveloped/WIP. At the moment, there exists a (git-shared) `.env`
|
94
|
+
file which can be used for configuring certain test attributes. This is most likely
|
95
|
+
about to change in the future. Stay tuned for updates!
|
96
|
+
|
97
|
+
## Github Actions integration
|
98
|
+
|
99
|
+
The e2e.yml workflow is made up of two jobs: one for running on pull requests (PRs) and
|
100
|
+
one for running on commits.
|
101
|
+
|
102
|
+
1. When running on PRs, the workflow will start the dev server, use dev3.openmrs.org as the backend,
|
103
|
+
and run tests only on chromium. This is done in order to quickly provide feedback to the developer.
|
104
|
+
The tests are designed to generate their own data and clean up after themselves once they are finished.
|
105
|
+
This ensures that the tests will have minimum effect from changes made to dev3 by other developers.
|
106
|
+
In the future, we plan to use a docker container to run the tests in an isolated environment once we
|
107
|
+
figure out a way to spin up the container within a small amount of time.
|
108
|
+
2. When running on commits, the workflow will spin up a docker container and run the dev server against
|
109
|
+
it in order to provide a known and isolated environment. In addition, tests will be run on multiple
|
110
|
+
browsers (chromium, firefox, and WebKit) to ensure compatibility.
|
111
|
+
|
112
|
+
## Troubleshooting tips
|
113
|
+
|
114
|
+
On MacOS, you might run into the following error:
|
115
|
+
```browserType.launch: Executable doesn't exist at /Users/<user>/Library/Caches/ms-playwright/chromium-1015/chrome-mac/Chromium.app/Contents/MacOS/Chromium```
|
116
|
+
In order to fix this, you can attempt to force the browser reinstallation by running:
|
117
|
+
```PLAYWRIGHT_BROWSERS_PATH=/Users/$USER/Library/Caches/ms-playwright npx playwright install```
|
@@ -0,0 +1,32 @@
|
|
1
|
+
import { request } from '@playwright/test';
|
2
|
+
import * as dotenv from 'dotenv';
|
3
|
+
|
4
|
+
dotenv.config();
|
5
|
+
|
6
|
+
/**
|
7
|
+
* This configuration is to reuse the signed-in state in the tests
|
8
|
+
* by log in only once using the API and then skip the log in step for all the tests.
|
9
|
+
*
|
10
|
+
* https://playwright.dev/docs/auth#reuse-signed-in-state
|
11
|
+
*/
|
12
|
+
|
13
|
+
async function globalSetup() {
|
14
|
+
const requestContext = await request.newContext();
|
15
|
+
const token = Buffer.from(`${process.env.E2E_USER_ADMIN_USERNAME}:${process.env.E2E_USER_ADMIN_PASSWORD}`).toString(
|
16
|
+
'base64',
|
17
|
+
);
|
18
|
+
await requestContext.post(`${process.env.E2E_BASE_URL}/ws/rest/v1/session`, {
|
19
|
+
data: {
|
20
|
+
sessionLocation: process.env.E2E_LOGIN_DEFAULT_LOCATION_UUID,
|
21
|
+
locale: 'en',
|
22
|
+
},
|
23
|
+
headers: {
|
24
|
+
Accept: 'application/json',
|
25
|
+
Authorization: `Basic ${token}`,
|
26
|
+
},
|
27
|
+
});
|
28
|
+
await requestContext.storageState({ path: 'e2e/storageState.json' });
|
29
|
+
await requestContext.dispose();
|
30
|
+
}
|
31
|
+
|
32
|
+
export default globalSetup;
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from './test';
|
package/e2e/core/test.ts
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
import { APIRequestContext, Page, test as base } from '@playwright/test';
|
2
|
+
import { api } from '../fixtures';
|
3
|
+
|
4
|
+
// This file sets up our custom test harness using the custom fixtures.
|
5
|
+
// See https://playwright.dev/docs/test-fixtures#creating-a-fixture for details.
|
6
|
+
// If a spec intends to use one of the custom fixtures, the special `test` function
|
7
|
+
// exported from this file must be used instead of the default `test` function
|
8
|
+
// provided by playwright.
|
9
|
+
|
10
|
+
export interface CustomTestFixtures {
|
11
|
+
loginAsAdmin: Page;
|
12
|
+
}
|
13
|
+
|
14
|
+
export interface CustomWorkerFixtures {
|
15
|
+
api: APIRequestContext;
|
16
|
+
}
|
17
|
+
|
18
|
+
export const test = base.extend<CustomTestFixtures, CustomWorkerFixtures>({
|
19
|
+
api: [api, { scope: 'worker' }],
|
20
|
+
});
|
@@ -0,0 +1,26 @@
|
|
1
|
+
import { APIRequestContext, PlaywrightWorkerArgs, WorkerFixture } from '@playwright/test';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* A fixture which initializes an [`APIRequestContext`](https://playwright.dev/docs/api/class-apirequestcontext)
|
5
|
+
* that is bound to the configured OpenMRS API server. The context is automatically authenticated
|
6
|
+
* using the configured admin account.
|
7
|
+
*
|
8
|
+
* Use the request context like this:
|
9
|
+
* ```ts
|
10
|
+
* test('your test', async ({ api }) => {
|
11
|
+
* const res = await api.get('patient/1234');
|
12
|
+
* await expect(res.ok()).toBeTruthy();
|
13
|
+
* });
|
14
|
+
* ```
|
15
|
+
*/
|
16
|
+
export const api: WorkerFixture<APIRequestContext, PlaywrightWorkerArgs> = async ({ playwright }, use) => {
|
17
|
+
const ctx = await playwright.request.newContext({
|
18
|
+
baseURL: `${process.env.E2E_BASE_URL}/ws/rest/v1/`,
|
19
|
+
httpCredentials: {
|
20
|
+
username: process.env.E2E_USER_ADMIN_USERNAME,
|
21
|
+
password: process.env.E2E_USER_ADMIN_PASSWORD,
|
22
|
+
},
|
23
|
+
});
|
24
|
+
|
25
|
+
await use(ctx);
|
26
|
+
};
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from './api';
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import { type Page } from '@playwright/test';
|
2
|
+
|
3
|
+
export class ChartPage {
|
4
|
+
constructor(readonly page: Page) {}
|
5
|
+
|
6
|
+
readonly formsTable = () => this.page.getByRole('table', { name: /forms/i });
|
7
|
+
|
8
|
+
async goTo(patientUuid: string) {
|
9
|
+
await this.page.goto('/openmrs/spa/patient/' + patientUuid + '/chart');
|
10
|
+
}
|
11
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import { test, expect } from '@playwright/test';
|
2
|
+
import dotenv from 'dotenv';
|
3
|
+
import { HomePage } from '../pages';
|
4
|
+
|
5
|
+
dotenv.config();
|
6
|
+
//This is a sample test which can be deleted
|
7
|
+
test.describe('Overview Page Test', () => {
|
8
|
+
test('should navigate to the Overview page and verify sections', async ({ page }) => {
|
9
|
+
const homePage = new HomePage(page);
|
10
|
+
|
11
|
+
await test.step('When I visit the home page', async () => {
|
12
|
+
await homePage.gotoHome();
|
13
|
+
});
|
14
|
+
|
15
|
+
await test.step('Then I should be at the home page', async () => {
|
16
|
+
await expect(page).toHaveURL(`${process.env.E2E_BASE_URL}spa/login`);
|
17
|
+
});
|
18
|
+
});
|
19
|
+
});
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# syntax=docker/dockerfile:1.3
|
2
|
+
FROM --platform=$BUILDPLATFORM node:18-alpine as dev
|
3
|
+
|
4
|
+
ARG APP_SHELL_VERSION=next
|
5
|
+
|
6
|
+
RUN mkdir -p /app
|
7
|
+
WORKDIR /app
|
8
|
+
|
9
|
+
COPY . .
|
10
|
+
|
11
|
+
RUN npm_config_legacy_peer_deps=true npm install -g openmrs@${APP_SHELL_VERSION:-next}
|
12
|
+
ARG CACHE_BUST
|
13
|
+
RUN npm_config_legacy_peer_deps=true openmrs assemble --manifest --mode config --config spa-assemble-config.json --target ./spa
|
14
|
+
|
15
|
+
FROM --platform=$BUILDPLATFORM openmrs/openmrs-reference-application-3-frontend:nightly as frontend
|
16
|
+
FROM nginx:1.23-alpine
|
17
|
+
|
18
|
+
RUN apk update && \
|
19
|
+
apk upgrade && \
|
20
|
+
# add more utils for sponge to support our startup script
|
21
|
+
apk add --no-cache moreutils
|
22
|
+
|
23
|
+
# clear any default files installed by nginx
|
24
|
+
RUN rm -rf /usr/share/nginx/html/*
|
25
|
+
|
26
|
+
COPY --from=frontend /etc/nginx/nginx.conf /etc/nginx/nginx.conf
|
27
|
+
# this assumes that NOTHING in the framework is in a subdirectory
|
28
|
+
COPY --from=frontend /usr/share/nginx/html/* /usr/share/nginx/html/
|
29
|
+
COPY --from=frontend /usr/local/bin/startup.sh /usr/local/bin/startup.sh
|
30
|
+
RUN chmod +x /usr/local/bin/startup.sh
|
31
|
+
|
32
|
+
COPY --from=dev /app/spa/ /usr/share/nginx/html/
|
33
|
+
|
34
|
+
CMD ["/usr/local/bin/startup.sh"]
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# This docker compose file is used to create a backend environment for the e2e.yml workflow.
|
2
|
+
version: "3.7"
|
3
|
+
|
4
|
+
services:
|
5
|
+
gateway:
|
6
|
+
image: openmrs/openmrs-reference-application-3-gateway:${TAG:-nightly}
|
7
|
+
ports:
|
8
|
+
- "8080:80"
|
9
|
+
|
10
|
+
frontend:
|
11
|
+
build:
|
12
|
+
context: .
|
13
|
+
environment:
|
14
|
+
SPA_PATH: /openmrs/spa
|
15
|
+
API_URL: /openmrs
|
16
|
+
|
17
|
+
backend:
|
18
|
+
image: openmrs/openmrs-reference-application-3-backend:nightly-with-data
|
19
|
+
depends_on:
|
20
|
+
- db
|
21
|
+
|
22
|
+
# MariaDB
|
23
|
+
db:
|
24
|
+
image: openmrs/openmrs-reference-application-3-db:nightly-with-data
|
@@ -0,0 +1,49 @@
|
|
1
|
+
#!/usr/bin/env bash -eu
|
2
|
+
|
3
|
+
# get the dir containing the script
|
4
|
+
script_dir=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
5
|
+
# create a temporary working directory
|
6
|
+
working_dir=$(mktemp -d "${TMPDIR:-/tmp/}openmrs-e2e-frontends.XXXXXXXXXX")
|
7
|
+
# get a list of all the apps in this workspace
|
8
|
+
apps=$(yarn workspaces list --json | jq -r 'if ((.location == ".") or (.location | test("form-engine-app")) or (.location | test("-app") | not)) then halt else .name end')
|
9
|
+
# this array will hold all of the packed app names
|
10
|
+
app_names=()
|
11
|
+
|
12
|
+
echo "Creating packed archives of apps..."
|
13
|
+
# for each app
|
14
|
+
for app in $apps
|
15
|
+
do
|
16
|
+
# @openmrs/esm-whatever -> _openmrs_esm_whatever
|
17
|
+
app_name=$(echo "$app" | tr '[:punct:]' '_');
|
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"
|
24
|
+
|
25
|
+
echo "Creating dynamic spa-assemble-config.json..."
|
26
|
+
# dynamically assemble our list of frontend modules, prepending the login app and
|
27
|
+
# primary navigation apps; apps will all be in the /app directory of the Docker
|
28
|
+
# container
|
29
|
+
jq -n \
|
30
|
+
--arg apps "$apps" \
|
31
|
+
--arg app_names "$(echo ${app_names[@]})" \
|
32
|
+
'{"@openmrs/esm-primary-navigation-app": "next", "@openmrs/esm-home-app": "next"} + (
|
33
|
+
($apps | split("\n")) as $apps | ($app_names | split(" ") | map("/app/" + .)) as $app_files
|
34
|
+
| [$apps, $app_files]
|
35
|
+
| transpose
|
36
|
+
| map({"key": .[0], "value": .[1]})
|
37
|
+
| from_entries
|
38
|
+
)' | jq '{"frontendModules": .}' > "$working_dir/spa-assemble-config.json"
|
39
|
+
echo "Created dynamic spa-assemble-config.json"
|
40
|
+
|
41
|
+
echo "Copying Docker configuration..."
|
42
|
+
cp "$script_dir/Dockerfile" "$working_dir/Dockerfile"
|
43
|
+
cp "$script_dir/docker-compose.yml" "$working_dir/docker-compose.yml"
|
44
|
+
|
45
|
+
cd $working_dir
|
46
|
+
echo "Starting Docker containers..."
|
47
|
+
# CACHE_BUST to ensure the assemble step is always run
|
48
|
+
docker compose build --build-arg CACHE_BUST=$(date +%s) frontend
|
49
|
+
docker compose up -d
|
package/example.env
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
# This is an example environment file for configuring dynamic values.
|
2
|
+
E2E_BASE_URL=http://localhost:8080/openmrs/
|
3
|
+
E2E_USER_ADMIN_USERNAME=admin
|
4
|
+
E2E_USER_ADMIN_PASSWORD=Admin123
|
5
|
+
E2E_LOGIN_DEFAULT_LOCATION_UUID=44c3efb0-2583-4c80-a79e-1f756a03c0a1
|
6
|
+
# The above location UUID is for the "Outpatient Clinic" location in the reference application
|
package/jest.config.js
CHANGED
@@ -5,7 +5,7 @@ const path = require('path');
|
|
5
5
|
|
6
6
|
module.exports = {
|
7
7
|
clearMocks: true,
|
8
|
-
collectCoverageFrom: ['**/src/**/*.component.tsx', '!**/node_modules/**', '!**/src/declarations.d.ts'],
|
8
|
+
collectCoverageFrom: ['**/src/**/*.component.tsx', '!**/node_modules/**', '!**/src/declarations.d.ts', '!**/e2e/**'],
|
9
9
|
transform: {
|
10
10
|
'^.+\\.tsx?$': ['@swc/jest'],
|
11
11
|
},
|
@@ -23,4 +23,8 @@ module.exports = {
|
|
23
23
|
testEnvironmentOptions: {
|
24
24
|
url: 'http://localhost/',
|
25
25
|
},
|
26
|
+
testPathIgnorePatterns: [
|
27
|
+
"/node_modules/",
|
28
|
+
"/e2e/" // Ignore the e2e directory containing Playwright tests
|
29
|
+
]
|
26
30
|
};
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@openmrs/esm-stock-management-app",
|
3
|
-
"version": "1.0.1-pre.
|
3
|
+
"version": "1.0.1-pre.716",
|
4
4
|
"license": "MPL-2.0",
|
5
5
|
"description": "Stock management microfrontend for OpenMRS 3.x",
|
6
6
|
"browser": "dist/openmrs-esm-stock-management-app.js",
|
@@ -19,7 +19,8 @@
|
|
19
19
|
"coverage": "yarn test --coverage",
|
20
20
|
"prepare": "husky install",
|
21
21
|
"extract-translations": "i18next 'src/**/*.component.tsx' 'src/**/*.tsx' --config ./i18next-parser.config.js",
|
22
|
-
"postinstall": "husky"
|
22
|
+
"postinstall": "husky",
|
23
|
+
"test-e2e": "playwright test"
|
23
24
|
},
|
24
25
|
"browserslist": [
|
25
26
|
"extends browserslist-config-openmrs"
|
@@ -43,6 +44,8 @@
|
|
43
44
|
"dependencies": {
|
44
45
|
"@carbon/react": "^1.33.1",
|
45
46
|
"@hookform/resolvers": "^3.3.0",
|
47
|
+
"@playwright/test": "^1.48.0",
|
48
|
+
"dotenv": "^16.4.5",
|
46
49
|
"file-saver": "^2.0.5",
|
47
50
|
"lodash-es": "^4.17.21",
|
48
51
|
"react-hook-form": "^7.45.4",
|
@@ -0,0 +1,34 @@
|
|
1
|
+
import { devices, type PlaywrightTestConfig } from '@playwright/test';
|
2
|
+
import { config as dotenvConfig } from 'dotenv';
|
3
|
+
import { resolve } from 'node:path';
|
4
|
+
dotenvConfig({ path: resolve(process.cwd(), '.env') });
|
5
|
+
dotenvConfig();
|
6
|
+
|
7
|
+
// See https://playwright.dev/docs/test-configuration.
|
8
|
+
const config: PlaywrightTestConfig = {
|
9
|
+
testDir: './e2e/specs',
|
10
|
+
timeout: 3 * 60 * 1000,
|
11
|
+
expect: {
|
12
|
+
timeout: 40 * 1000,
|
13
|
+
},
|
14
|
+
fullyParallel: true,
|
15
|
+
forbidOnly: !!process.env.CI,
|
16
|
+
retries: 0,
|
17
|
+
reporter: process.env.CI ? [['junit', { outputFile: 'results.xml' }], ['html']] : [['html']],
|
18
|
+
globalSetup: require.resolve('./e2e/core/global-setup'),
|
19
|
+
use: {
|
20
|
+
baseURL: `${process.env.E2E_BASE_URL}/spa/stock-management`,
|
21
|
+
storageState: 'e2e/storageState.json',
|
22
|
+
video: 'retain-on-failure',
|
23
|
+
},
|
24
|
+
projects: [
|
25
|
+
{
|
26
|
+
name: 'chromium',
|
27
|
+
use: {
|
28
|
+
...devices['Desktop Chrome'],
|
29
|
+
},
|
30
|
+
},
|
31
|
+
],
|
32
|
+
};
|
33
|
+
|
34
|
+
export default config;
|
@@ -37,5 +37,18 @@ export function useValidationSchema(operationType?: string) {
|
|
37
37
|
stockItems: z.array(customSchema),
|
38
38
|
});
|
39
39
|
}
|
40
|
+
if (operationType === 'adjustment') {
|
41
|
+
const customSchema = stockItemTableSchema.extend({
|
42
|
+
quantity: z.coerce
|
43
|
+
.number()
|
44
|
+
.refine((value) => value !== 0, {
|
45
|
+
message: 'Quantity cannot be zero.',
|
46
|
+
})
|
47
|
+
.or(z.literal(0, { invalid_type_error: 'Invalid quantity format' })),
|
48
|
+
});
|
49
|
+
return z.object({
|
50
|
+
stockItems: z.array(customSchema),
|
51
|
+
});
|
52
|
+
}
|
40
53
|
return stockOperationItemsSchema;
|
41
54
|
}
|