@ampath/esm-dha-workflow-app 4.0.0-next.4

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.
Files changed (107) hide show
  1. package/.editorconfig +12 -0
  2. package/.eslintignore +2 -0
  3. package/.eslintrc +57 -0
  4. package/.husky/pre-commit +7 -0
  5. package/.husky/pre-push +6 -0
  6. package/.prettierignore +14 -0
  7. package/.turbo.json +18 -0
  8. package/.yarn/plugins/@yarnpkg/plugin-outdated.cjs +35 -0
  9. package/LICENSE +401 -0
  10. package/README.md +37 -0
  11. package/__mocks__/react-i18next.js +50 -0
  12. package/dist/184.js +2 -0
  13. package/dist/184.js.LICENSE.txt +14 -0
  14. package/dist/184.js.map +1 -0
  15. package/dist/197.js +1 -0
  16. package/dist/255.js +1 -0
  17. package/dist/255.js.map +1 -0
  18. package/dist/282.js +2 -0
  19. package/dist/282.js.LICENSE.txt +32 -0
  20. package/dist/282.js.map +1 -0
  21. package/dist/300.js +1 -0
  22. package/dist/335.js +1 -0
  23. package/dist/353.js +1 -0
  24. package/dist/353.js.map +1 -0
  25. package/dist/420.js +1 -0
  26. package/dist/420.js.map +1 -0
  27. package/dist/540.js +2 -0
  28. package/dist/540.js.LICENSE.txt +9 -0
  29. package/dist/540.js.map +1 -0
  30. package/dist/55.js +1 -0
  31. package/dist/561.js +2 -0
  32. package/dist/561.js.LICENSE.txt +14 -0
  33. package/dist/561.js.map +1 -0
  34. package/dist/652.js +1 -0
  35. package/dist/70.js +1 -0
  36. package/dist/70.js.map +1 -0
  37. package/dist/731.js +2 -0
  38. package/dist/731.js.LICENSE.txt +39 -0
  39. package/dist/731.js.map +1 -0
  40. package/dist/819.js +1 -0
  41. package/dist/819.js.map +1 -0
  42. package/dist/91.js +1 -0
  43. package/dist/91.js.map +1 -0
  44. package/dist/961.js +2 -0
  45. package/dist/961.js.LICENSE.txt +19 -0
  46. package/dist/961.js.map +1 -0
  47. package/dist/99.js +1 -0
  48. package/dist/main.js +1 -0
  49. package/dist/main.js.map +1 -0
  50. package/dist/openmrs-esm-home-app.js +1 -0
  51. package/dist/openmrs-esm-home-app.js.buildmanifest.json +580 -0
  52. package/dist/openmrs-esm-home-app.js.map +1 -0
  53. package/dist/routes.json +1 -0
  54. package/e2e/README.md +115 -0
  55. package/e2e/core/global-setup.ts +32 -0
  56. package/e2e/core/index.ts +1 -0
  57. package/e2e/core/test.ts +20 -0
  58. package/e2e/fixtures/api.ts +26 -0
  59. package/e2e/fixtures/index.ts +1 -0
  60. package/e2e/pages/index.ts +1 -0
  61. package/e2e/pages/root-page.ts +32 -0
  62. package/e2e/specs/template-app.spec.ts +23 -0
  63. package/e2e/support/github/Dockerfile +34 -0
  64. package/e2e/support/github/docker-compose.yml +24 -0
  65. package/e2e/support/github/run-e2e-docker-env.sh +37 -0
  66. package/example.env +6 -0
  67. package/jest.config.js +33 -0
  68. package/package.json +111 -0
  69. package/playwright.config.ts +32 -0
  70. package/prettier.config.js +8 -0
  71. package/src/boxes/extensions/blue-box.component.tsx +15 -0
  72. package/src/boxes/extensions/box.scss +23 -0
  73. package/src/boxes/extensions/brand-box.component.tsx +15 -0
  74. package/src/boxes/extensions/red-box.component.tsx +15 -0
  75. package/src/boxes/slot/boxes.component.tsx +25 -0
  76. package/src/boxes/slot/boxes.scss +29 -0
  77. package/src/config-schema.ts +43 -0
  78. package/src/declarations.d.ts +5 -0
  79. package/src/greeter/greeter.component.tsx +42 -0
  80. package/src/greeter/greeter.scss +20 -0
  81. package/src/greeter/greeter.test.tsx +28 -0
  82. package/src/index.ts +46 -0
  83. package/src/patient-getter/patient-getter.component.tsx +40 -0
  84. package/src/patient-getter/patient-getter.resource.ts +39 -0
  85. package/src/patient-getter/patient-getter.scss +16 -0
  86. package/src/patient-getter/patient-getter.test.tsx +40 -0
  87. package/src/registry/registry.component.tsx +7 -0
  88. package/src/resources/resources.component.tsx +56 -0
  89. package/src/resources/resources.scss +68 -0
  90. package/src/root.component.tsx +39 -0
  91. package/src/root.scss +15 -0
  92. package/src/root.test.tsx +51 -0
  93. package/src/routes.json +19 -0
  94. package/src/side-nav/side-menu.scss +38 -0
  95. package/src/side-nav-menu/nav-links.tsx +22 -0
  96. package/src/widgets/workflow-registry-link.extension.tsx +12 -0
  97. package/tools/i18next-parser.config.js +89 -0
  98. package/tools/setup-tests.ts +1 -0
  99. package/tools/update-openmrs-deps.mjs +43 -0
  100. package/translations/am.json +24 -0
  101. package/translations/en.json +24 -0
  102. package/translations/es.json +24 -0
  103. package/translations/fr.json +24 -0
  104. package/translations/he.json +24 -0
  105. package/translations/km.json +24 -0
  106. package/tsconfig.json +24 -0
  107. package/webpack.config.js +1 -0
package/e2e/README.md ADDED
@@ -0,0 +1,115 @@
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
9
+ [root README](../README.md).
10
+ Once everything is set up, make sure the dev server is running by using:
11
+
12
+ ```sh
13
+ yarn start --sources 'packages/esm-*-app/'
14
+ ```
15
+ Then, in a separate terminal, run:
16
+
17
+ ```sh
18
+ yarn test-e2e --headed
19
+ ```
20
+
21
+ By default, the test suite will run against the http://localhost:8080.
22
+ You can override this by exporting `E2E_BASE_URL` environment variables beforehand:
23
+
24
+ ```sh
25
+ # Ex: Set the server URL to dev3:
26
+ export E2E_BASE_URL=https://dev3.openmrs.org/openmrs
27
+
28
+ # Run all e2e tests:
29
+ yarn test-e2e --headed
30
+ ```
31
+ To run a specific test by title:
32
+ ```sh
33
+ yarn test-e2e --headed -g "title of the test"
34
+ ```
35
+ Check [this documentation](https://playwright.dev/docs/running-tests#command-line) for more running options.
36
+
37
+ It is also highly recommended to install the companion VS Code extension:
38
+ https://playwright.dev/docs/getting-started-vscode
39
+
40
+
41
+ ## Writing New Tests
42
+
43
+ In general, it is recommended to read through the official [Playwright docs](https://playwright.dev/docs/intro)
44
+ before writing new test cases. The project uses the official Playwright test runner and,
45
+ generally, follows a very simple project structure:
46
+
47
+ ```
48
+ e2e
49
+ |__ commands
50
+ | ^ Contains "commands" (simple reusable functions) that can be used in test cases/specs,
51
+ | e.g. generate a random patient.
52
+ |__ core
53
+ | ^ Contains code related to the test runner itself, e.g. setting up the custom fixtures.
54
+ | You probably need to touch this infrequently.
55
+ |__ fixtures
56
+ | ^ Contains fixtures (https://playwright.dev/docs/test-fixtures) which are used
57
+ | to run reusable setup/teardown tasks
58
+ |__ pages
59
+ | ^ Contains page object model classes for interacting with the frontend.
60
+ | See https://playwright.dev/docs/test-pom for details.
61
+ |__ specs
62
+ | ^ Contains the actual test cases/specs. New tests should be placed in this folder.
63
+ |__ support
64
+ ^ Contains support files that requires to run e2e tests, e.g. docker compose files.
65
+ ```
66
+
67
+ When you want to write a new test case, start by creating a new spec in `./specs`.
68
+ Depending on what you want to achieve, you might want to create new fixtures and/or
69
+ page object models. To see examples, have a look at the existing code to see how these
70
+ different concepts play together.
71
+
72
+ ## Open reports from GitHub Actions / Bamboo
73
+
74
+ To download the report from the GitHub action/Bamboo plan, follow these steps:
75
+
76
+ 1. Go to the artifact section of the action/plan and locate the report file.
77
+ 2. Download the report file and unzip it using a tool of your choice.
78
+ 3. Open the index.html file in a web browser to view the report.
79
+
80
+ The report will show you a full summary of your tests, including information on which
81
+ tests passed, failed, were skipped, or were flaky. You can filter the report by browser
82
+ and explore the details of individual tests, including any errors or failures, video
83
+ recordings, and the steps involved in each test. Simply click on a test to view its details.
84
+
85
+ ## Debugging Tests
86
+
87
+ Refer to [this documentation](https://playwright.dev/docs/debug) on how to debug a test.
88
+
89
+ ## Configuration
90
+
91
+ This is very much underdeveloped/WIP. At the moment, there exists a (git-shared) `example.env`
92
+ file which can be used for configuring certain test attributes. This is most likely
93
+ about to change in the future. Stay tuned for updates!
94
+
95
+
96
+ ## Github Action integration
97
+ The e2e.yml workflow is made up of two jobs: one for running on pull requests (PRs) and
98
+ one for running on commits.
99
+
100
+ 1. When running on PRs, the workflow will start the dev server, use dev3.openmrs.org as the backend,
101
+ and run tests only on chromium. This is done in order to quickly provide feedback to the developer.
102
+ The tests are designed to generate their own data and clean up after themselves once they are finished.
103
+ This ensures that the tests will have minimum effect from changes made to dev3 by other developers.
104
+ In the future, we plan to use a docker container to run the tests in an isolated environment once we
105
+ figure out a way to spin up the container within a small amount of time.
106
+ 2. When running on commits, the workflow will spin up a docker container and run the dev server against
107
+ it in order to provide a known and isolated environment. In addition, tests will be run on multiple
108
+ browsers (chromium, firefox, and WebKit) to ensure compatibility.
109
+
110
+ ## Troubleshooting tips
111
+
112
+ On MacOS, you might run into the following error:
113
+ ```browserType.launch: Executable doesn't exist at /Users/<user>/Library/Caches/ms-playwright/chromium-1015/chrome-mac/Chromium.app/Contents/MacOS/Chromium```
114
+ In order to fix this, you can attempt to force the browser reinstallation by running:
115
+ ```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
+ 'Content-Type': '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 @@
1
+ export * from './root-page';
@@ -0,0 +1,32 @@
1
+ import type { Page, Locator } from '@playwright/test';
2
+
3
+ export class RootPage {
4
+ readonly page: Page;
5
+ readonly welcomeHeading: Locator;
6
+ readonly configSection: Locator;
7
+ readonly extensionSection: Locator;
8
+ readonly dataFetchingSection: Locator;
9
+ readonly resourcesSection: Locator;
10
+
11
+ constructor(page: Page) {
12
+ this.page = page;
13
+ this.welcomeHeading = page.getByRole('heading', { name: /welcome to the o3 template app/i });
14
+ this.configSection = page.getByRole('heading', { name: /configuration system/i });
15
+ this.extensionSection = page.getByRole('heading', { name: /extension system/i });
16
+ this.dataFetchingSection = page.getByRole('heading', { name: /data fetching/i });
17
+ this.resourcesSection = page.getByRole('heading', { name: /resources/i });
18
+ }
19
+
20
+ async goto() {
21
+ await this.page.goto('/openmrs/spa/root');
22
+ await this.welcomeHeading.waitFor();
23
+ }
24
+
25
+ async waitForPageLoad() {
26
+ await this.welcomeHeading.waitFor();
27
+ await this.configSection.waitFor();
28
+ await this.extensionSection.waitFor();
29
+ await this.dataFetchingSection.waitFor();
30
+ await this.resourcesSection.waitFor();
31
+ }
32
+ }
@@ -0,0 +1,23 @@
1
+ import { test, expect } from '@playwright/test';
2
+ import { RootPage } from '../pages';
3
+
4
+ test('Home app loads and displays all core components', async ({ page }) => {
5
+ const rootPage = new RootPage(page);
6
+ await rootPage.goto();
7
+
8
+ await expect(page).toHaveURL(/\/openmrs\/spa\/root/);
9
+
10
+ await expect(rootPage.welcomeHeading).toBeVisible();
11
+ await expect(
12
+ page.getByText('The following examples demonstrate some key features of the O3 framework'),
13
+ ).toBeVisible();
14
+
15
+ await expect(rootPage.configSection).toBeVisible();
16
+ await expect(rootPage.extensionSection).toBeVisible();
17
+ await expect(rootPage.dataFetchingSection).toBeVisible();
18
+ await expect(rootPage.resourcesSection).toBeVisible();
19
+
20
+ await expect(page.getByText(/hello world!/i)).toBeVisible(); // Configuration greeting tile content
21
+ await expect(page.locator('[data-extension-slot-name="Boxes"]')).toBeVisible(); // Extension boxes slot
22
+ await expect(page.getByRole('button', { name: /get a patient named 'test'/i })).toBeVisible();
23
+ });
@@ -0,0 +1,34 @@
1
+ # syntax=docker/dockerfile:1.3
2
+ FROM --platform=$BUILDPLATFORM node:22-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,37 @@
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 the app name
8
+ app_name=$(jq -r '.name' "$script_dir/../../../package.json")
9
+
10
+ echo "Creating packed archive of the app..."
11
+ # @openmrs/esm-whatever -> _openmrs_esm_whatever
12
+ packed_app_name=$(echo "$app_name" | tr '[:punct:]' '_');
13
+ # run yarn pack for our app and add it to the working directory
14
+ yarn pack -o "$working_dir/$packed_app_name.tgz" >/dev/null;
15
+ echo "Created packed app archives"
16
+
17
+ echo "Creating dynamic spa-assemble-config.json..."
18
+ # dynamically assemble our list of frontend modules, prepending the login app and
19
+ # primary navigation apps; apps will all be in the /app directory of the Docker
20
+ # container
21
+ jq -n \
22
+ --arg app_name "$app_name" \
23
+ --arg app_file "/app/$packed_app_name.tgz" \
24
+ '{"@openmrs/esm-primary-navigation-app": "next", "@openmrs/esm-home-app": "next"} + {
25
+ ($app_name): $app_file
26
+ }' | jq '{"frontendModules": .}' > "$working_dir/spa-assemble-config.json"
27
+ echo "Created dynamic spa-assemble-config.json"
28
+
29
+ echo "Copying Docker configuration..."
30
+ cp "$script_dir/Dockerfile" "$working_dir/Dockerfile"
31
+ cp "$script_dir/docker-compose.yml" "$working_dir/docker-compose.yml"
32
+
33
+ cd $working_dir
34
+ echo "Starting Docker containers..."
35
+ # CACHE_BUST to ensure the assemble step is always run
36
+ docker compose build --build-arg CACHE_BUST=$(date +%s) frontend
37
+ 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 ADDED
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @returns {Promise<import('jest').Config>}
3
+ */
4
+ const path = require('path');
5
+
6
+ module.exports = {
7
+ collectCoverageFrom: [
8
+ '**/src/**/*.component.tsx',
9
+ '!**/node_modules/**',
10
+ '!**/vendor/**',
11
+ '!**/src/**/*.test.*',
12
+ '!**/src/declarations.d.ts',
13
+ '!**/e2e/**',
14
+ ],
15
+ transform: {
16
+ '^.+\\.[jt]sx?$': ['@swc/jest'],
17
+ },
18
+ transformIgnorePatterns: ['/node_modules/(?!@openmrs|.+\\.pnp\\.[^\\/]+$)'],
19
+ moduleNameMapper: {
20
+ '@openmrs/esm-framework': '@openmrs/esm-framework/mock',
21
+ '\\.(s?css)$': 'identity-obj-proxy',
22
+ '^lodash-es/(.*)$': 'lodash/$1',
23
+ 'lodash-es': 'lodash',
24
+ '^dexie$': require.resolve('dexie'),
25
+ '^dayjs$': require.resolve('dayjs'),
26
+ },
27
+ setupFilesAfterEnv: [path.resolve(__dirname, 'tools', 'setup-tests.ts')],
28
+ testPathIgnorePatterns: [path.resolve(__dirname, 'e2e')],
29
+ testEnvironment: 'jsdom',
30
+ testEnvironmentOptions: {
31
+ url: 'http://localhost/',
32
+ },
33
+ };
package/package.json ADDED
@@ -0,0 +1,111 @@
1
+ {
2
+ "name": "@ampath/esm-dha-workflow-app",
3
+ "version": "4.0.0-next.4",
4
+ "license": "MPL-2.0",
5
+ "description": "An OpenMRS seed application for building microfrontends",
6
+ "browser": "dist/openmrs-esm-home-app.js",
7
+ "main": "src/index.ts",
8
+ "source": true,
9
+ "scripts": {
10
+ "start": "openmrs develop",
11
+ "dev": "openmrs develop --backend=https://staging.ampath.or.ke --api-url=/openmrs --port=9000",
12
+ "serve": "webpack serve --mode=development",
13
+ "build": "webpack --mode production",
14
+ "analyze": "webpack --mode=production --env analyze=true",
15
+ "lint": "eslint src --ext js,jsx,ts,tsx --max-warnings 0",
16
+ "prettier": "prettier --write \"src/**/*.{ts,tsx}\" --list-different",
17
+ "typescript": "tsc",
18
+ "test": "jest --config jest.config.js --passWithNoTests",
19
+ "verify": "turbo lint typescript coverage",
20
+ "coverage": "yarn test --coverage",
21
+ "prepare": "husky install",
22
+ "extract-translations": "i18next 'src/**/*.component.tsx' --config ./tools/i18next-parser.config.js",
23
+ "test-e2e": "playwright test"
24
+ },
25
+ "browserslist": [
26
+ "extends browserslist-config-openmrs"
27
+ ],
28
+ "keywords": [
29
+ "openmrs",
30
+ "microfrontends"
31
+ ],
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "git+https://github.com/openmrs/openmrs-esm-home-app.git"
35
+ },
36
+ "homepage": "https://github.com/openmrs/openmrs-esm-home-app#readme",
37
+ "publishConfig": {
38
+ "access": "public"
39
+ },
40
+ "bugs": {
41
+ "url": "https://github.com/openmrs/openmrs-esm-home-app/issues"
42
+ },
43
+ "dependencies": {
44
+ "@carbon/react": "^1.83.0",
45
+ "lodash-es": "^4.17.21"
46
+ },
47
+ "peerDependencies": {
48
+ "@openmrs/esm-framework": "*",
49
+ "@openmrs/esm-patient-common-lib": "*",
50
+ "dayjs": "1.x",
51
+ "react": "18.x",
52
+ "react-i18next": "16.x",
53
+ "react-router-dom": "6.x",
54
+ "rxjs": "6.x"
55
+ },
56
+ "devDependencies": {
57
+ "@openmrs/esm-framework": "next",
58
+ "@openmrs/esm-patient-common-lib": "next",
59
+ "@openmrs/esm-styleguide": "next",
60
+ "@playwright/test": "^1.52.0",
61
+ "@swc/cli": "^0.3.12",
62
+ "@swc/core": "^1.3.68",
63
+ "@swc/jest": "^0.2.36",
64
+ "@testing-library/dom": "^10.1.0",
65
+ "@testing-library/jest-dom": "^6.4.5",
66
+ "@testing-library/react": "^15.0.6",
67
+ "@testing-library/user-event": "^14.5.2",
68
+ "@types/jest": "^29.5.12",
69
+ "@types/react": "^18.3.21",
70
+ "@types/react-dom": "^18.3.0",
71
+ "@types/react-router": "^5.1.20",
72
+ "@types/react-router-dom": "^5.3.3",
73
+ "@types/webpack-env": "^1.18.1",
74
+ "@typescript-eslint/eslint-plugin": "^7.8.0",
75
+ "@typescript-eslint/parser": "^7.8.0",
76
+ "css-loader": "^6.8.1",
77
+ "dayjs": "^1.11.13",
78
+ "dotenv": "^16.0.3",
79
+ "eslint": "^8.50.0",
80
+ "eslint-config-prettier": "^8.8.0",
81
+ "eslint-plugin-jest-dom": "^5.4.0",
82
+ "eslint-plugin-prettier": "^5.1.3",
83
+ "eslint-plugin-react-hooks": "^4.6.2",
84
+ "husky": "^8.0.3",
85
+ "i18next": "^25.0.0",
86
+ "i18next-parser": "^9.3.0",
87
+ "identity-obj-proxy": "^3.0.0",
88
+ "jest": "^29.7.0",
89
+ "jest-cli": "^29.7.0",
90
+ "jest-environment-jsdom": "^29.7.0",
91
+ "lint-staged": "^15.2.2",
92
+ "openmrs": "next",
93
+ "prettier": "^3.3.3",
94
+ "react": "^18.3.1",
95
+ "react-dom": "^18.3.1",
96
+ "react-i18next": "^16.0.0",
97
+ "react-router-dom": "^6.14.1",
98
+ "rxjs": "^6.6.7",
99
+ "swc-loader": "^0.2.3",
100
+ "turbo": "^2.5.2",
101
+ "typescript": "^5.0.0",
102
+ "webpack": "^5.99.9",
103
+ "webpack-cli": "^6.0.1"
104
+ },
105
+ "lint-staged": {
106
+ "packages/**/src/**/*.{ts,tsx}": "eslint --cache --fix --max-warnings 0",
107
+ "*.{css,scss,ts,tsx}": "prettier --write --list-different"
108
+ },
109
+ "packageManager": "yarn@4.10.3",
110
+ "stableVersion": "4.0.0"
111
+ }
@@ -0,0 +1,32 @@
1
+ import { devices, PlaywrightTestConfig } from '@playwright/test';
2
+ import * as dotenv from 'dotenv';
3
+ dotenv.config();
4
+
5
+ // See https://playwright.dev/docs/test-configuration.
6
+ const config: PlaywrightTestConfig = {
7
+ testDir: './e2e/specs',
8
+ timeout: 3 * 60 * 1000,
9
+ expect: {
10
+ timeout: 40 * 1000,
11
+ },
12
+ fullyParallel: true,
13
+ forbidOnly: !!process.env.CI,
14
+ retries: 0,
15
+ reporter: process.env.CI ? [['junit', { outputFile: 'results.xml' }], ['html']] : [['html']],
16
+ globalSetup: require.resolve('./e2e/core/global-setup'),
17
+ use: {
18
+ baseURL: `${process.env.E2E_BASE_URL}/spa/`,
19
+ storageState: 'e2e/storageState.json',
20
+ video: 'retain-on-failure',
21
+ },
22
+ projects: [
23
+ {
24
+ name: 'chromium',
25
+ use: {
26
+ ...devices['Desktop Chrome'],
27
+ },
28
+ },
29
+ ],
30
+ };
31
+
32
+ export default config;
@@ -0,0 +1,8 @@
1
+ module.exports = {
2
+ bracketSpacing: true,
3
+ printWidth: 120,
4
+ semi: true,
5
+ singleQuote: true,
6
+ tabWidth: 2,
7
+ trailingComma: 'all',
8
+ };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * This component demonstrates the creation of an extension.
3
+ *
4
+ * Check out the Extension System docs:
5
+ * https://o3-docs.vercel.app/docs/extension-system
6
+ */
7
+
8
+ import React from 'react';
9
+ import styles from './box.scss';
10
+
11
+ const BlueBox: React.FC = () => {
12
+ return <div className={styles.blue}></div>;
13
+ };
14
+
15
+ export default BlueBox;
@@ -0,0 +1,23 @@
1
+ /* Extensions should supply the minimum amount of styling
2
+ * necessary. Here, the extensions set only their colors.
3
+ * Their sizes and other general features of their display
4
+ * is controlled by the slot. */
5
+ @use "@carbon/layout";
6
+ @use '@openmrs/esm-styleguide/src/vars' as *;
7
+
8
+ .blue {
9
+ background-color: darkblue;
10
+ }
11
+
12
+ .red {
13
+ background-color: darkred;
14
+ }
15
+
16
+ /* Brand colors are special. They must be included using a
17
+ * SASS mix-in (shown here) or using a CSS variable like
18
+ * `var(--brand-01)`. */
19
+ .brand {
20
+ @include brand-01(background-color);
21
+ color: white;
22
+ padding: layout.$spacing-03;
23
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * This component demonstrates the creation of an extension.
3
+ *
4
+ * Check out the Extension System docs:
5
+ * https://o3-docs.vercel.app/docs/extension-system
6
+ */
7
+
8
+ import React from 'react';
9
+ import styles from './box.scss';
10
+
11
+ const RedBox: React.FC = () => {
12
+ return <div className={styles.brand}></div>;
13
+ };
14
+
15
+ export default RedBox;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * This component demonstrates the creation of an extension.
3
+ *
4
+ * Check out the Extension System docs:
5
+ * https://o3-docs.vercel.app/docs/extension-system
6
+ */
7
+
8
+ import React from 'react';
9
+ import styles from './box.scss';
10
+
11
+ const RedBox: React.FC = () => {
12
+ return <div className={styles.red}></div>;
13
+ };
14
+
15
+ export default RedBox;
@@ -0,0 +1,25 @@
1
+ import React from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { Extension, ExtensionSlot } from '@openmrs/esm-framework';
4
+ import styles from './boxes.scss';
5
+
6
+ export const Boxes: React.FC = () => {
7
+ const { t } = useTranslation();
8
+
9
+ return (
10
+ <div className={styles.container}>
11
+ <h5>{t('extensionSystem', 'Extension system')}</h5>
12
+ <p>
13
+ {t(
14
+ 'extensionExplainer',
15
+ 'Here are some colored boxes. Because they are attached as extensions within a slot, an admin can change what boxes are shown using configuration. These boxes happen to be defined in this module, but they could attach to this slot even if they were in a different module.',
16
+ )}
17
+ </p>
18
+ <ExtensionSlot name="Boxes" className={styles.boxes}>
19
+ <div className={styles.box}>
20
+ <Extension />
21
+ </div>
22
+ </ExtensionSlot>
23
+ </div>
24
+ );
25
+ };