@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.
@@ -134,10 +134,10 @@
134
134
  "initial": true,
135
135
  "entry": true,
136
136
  "recorded": false,
137
- "size": 5408566,
137
+ "size": 5409050,
138
138
  "sizes": {
139
139
  "consume-shared": 252,
140
- "javascript": 5386617,
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": "bde00c76e90fc524",
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": 1749694,
610
+ "size": 1750178,
611
611
  "sizes": {
612
- "javascript": 1749484,
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": "4e40bb4e6400af3e",
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.706"}
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';
@@ -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,9 @@
1
+ import { Page } from '@playwright/test';
2
+
3
+ export class HomePage {
4
+ constructor(readonly page: Page) {}
5
+
6
+ async gotoHome() {
7
+ await this.page.goto('/openmrs/spa/login');
8
+ }
9
+ }
@@ -0,0 +1,2 @@
1
+ export * from './home-page';
2
+ export * from './chart-page';
@@ -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.706",
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
  }