From cc7ff72d97bbc455ee39ce72e79c701a9e3e9b97 Mon Sep 17 00:00:00 2001 From: lucyjemutai <130601439+lucyjemutai@users.noreply.github.com> Date: Thu, 3 Oct 2024 08:50:45 +0300 Subject: [PATCH 1/9] Setup playwright for automated tests in Stock Management --- .eslintrc | 10 ++- .github/workflows/e2e.yml | 63 ++++++++++++++ .github/workflows/node.js.yml | 2 + .gitignore | 6 ++ e2e/README.md | 117 ++++++++++++++++++++++++++ e2e/commands/index.ts | 2 + e2e/commands/patient-operations.ts | 105 +++++++++++++++++++++++ e2e/commands/visit-operations.ts | 31 +++++++ e2e/core/global-setup.ts | 32 +++++++ e2e/core/index.ts | 1 + e2e/core/test.ts | 20 +++++ e2e/fixtures/api.ts | 26 ++++++ e2e/fixtures/index.ts | 1 + e2e/pages/chart-page.ts | 11 +++ e2e/pages/home-page.ts | 9 ++ e2e/pages/index.ts | 2 + e2e/specs/stock-overview-test.spec.ts | 23 +++++ example.env | 6 ++ jest.config.js | 6 +- package.json | 4 +- yarn.lock | 8 ++ 21 files changed, 482 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/e2e.yml create mode 100644 e2e/README.md create mode 100644 e2e/commands/index.ts create mode 100644 e2e/commands/patient-operations.ts create mode 100644 e2e/commands/visit-operations.ts create mode 100644 e2e/core/global-setup.ts create mode 100644 e2e/core/index.ts create mode 100644 e2e/core/test.ts create mode 100644 e2e/fixtures/api.ts create mode 100644 e2e/fixtures/index.ts create mode 100644 e2e/pages/chart-page.ts create mode 100644 e2e/pages/home-page.ts create mode 100644 e2e/pages/index.ts create mode 100644 e2e/specs/stock-overview-test.spec.ts create mode 100644 example.env diff --git a/.eslintrc b/.eslintrc index 8987e825..f60dd60a 100644 --- a/.eslintrc +++ b/.eslintrc @@ -48,5 +48,13 @@ ] } ] - } + }, + "overrides": [ + { + "files": ["e2e/**/*.spec.ts"], + "rules": { + "testing-library/prefer-screen-queries": "off" + } + } + ] } diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml new file mode 100644 index 00000000..26ebd77d --- /dev/null +++ b/.github/workflows/e2e.yml @@ -0,0 +1,63 @@ +name: E2E Tests + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + main: + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v3 + + - name: Copy test environment variables + run: | + cp example.env .env + sed -i 's/8080/8180/g' .env + + - name: Setup node + uses: actions/setup-node@v3 + with: + node-version: 18 + + - name: Cache dependencies + id: cache + uses: actions/cache@v3 + with: + path: '**/node_modules' + key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }} + + - name: Install dependencies + if: steps.cache.outputs.cache-hit != 'true' + run: yarn install --immutable + + - name: Install Playwright Browsers + run: npx playwright install chromium --with-deps + + - name: Run dev server + run: yarn start --sources 'packages/esm-*-app/' --port 8180 & # Refer to O3-1994 + + - name: Run E2E tests + run: yarn playwright test + + - name: Upload Report + uses: actions/upload-artifact@v3 + if: always() + with: + name: playwright-report + path: playwright-report/ + retention-days: 30 + + github-action: + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v3 + + - name: Run Playwright tests with GitHub Action + run: yarn playwright test \ No newline at end of file diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index d3b2b8e3..499ebe93 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -54,6 +54,8 @@ jobs: dist overwrite: true + + pre_release: runs-on: ubuntu-latest needs: build diff --git a/.gitignore b/.gitignore index 3617d0b9..3ccee9e0 100644 --- a/.gitignore +++ b/.gitignore @@ -80,6 +80,12 @@ dist/ !.yarn/sdks !.yarn/versions +# Playwright and e2e tests +/test-results/ +/playwright-report/ +/playwright/.cache/ +e2e/storageState.json + # Turborepo .turbo /*.idea/ diff --git a/e2e/README.md b/e2e/README.md new file mode 100644 index 00000000..32a0d90c --- /dev/null +++ b/e2e/README.md @@ -0,0 +1,117 @@ +# E2E Tests + +This directory contains an E2E test suite using the [Playwright](https://playwright.dev) +framework. + +## Getting Started + +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: + +```sh +yarn start +``` + +Then, in a separate terminal, run: + +```sh +yarn test-e2e --headed +``` + +By default, the test suite will run against the http://localhost:8080. You can override this by exporting `E2E_BASE_URL` environment variables beforehand: + +```sh +# Ex: Set the server URL to dev3: +export E2E_BASE_URL=https://dev3.openmrs.org/openmrs + +# Run all e2e tests: + +```sh +yarn test-e2e --headed +``` + +To run a specific test by title: + +```sh +yarn test-e2e --headed -g "title of the test" +``` + +Check [this documentation](https://playwright.dev/docs/running-tests#command-line) for more running options. + +It is also highly recommended to install the companion VS Code extension: +https://playwright.dev/docs/getting-started-vscode + +## Writing New Tests + +In general, it is recommended to read through the official [Playwright docs](https://playwright.dev/docs/intro) +before writing new test cases. The project uses the official Playwright test runner and, +generally, follows a very simple project structure: + +``` +e2e +|__ commands +| ^ Contains "commands" (simple reusable functions) that can be used in test cases/specs, +| e.g. generate a random patient. +|__ core +| ^ Contains code related to the test runner itself, e.g. setting up the custom fixtures. +| You probably need to touch this infrequently. +|__ fixtures +| ^ Contains fixtures (https://playwright.dev/docs/test-fixtures) which are used +| to run reusable setup/teardown tasks +|__ pages +| ^ Contains page object model classes for interacting with the frontend. +| See https://playwright.dev/docs/test-pom for details. +|__ specs +| ^ Contains the actual test cases/specs. New tests should be placed in this folder. +|__ support + ^ Contains support files that requires to run e2e tests, e.g. docker compose files. +``` + +When you want to write a new test case, start by creating a new spec in `./specs`. +Depending on what you want to achieve, you might want to create new fixtures and/or +page object models. To see examples, have a look at the existing code to see how these +different concepts play together. + +## Open reports from GitHub Actions / Bamboo + +To download the report from the GitHub action/Bamboo plan, follow these steps: + +1. Go to the artifact section of the action/plan and locate the report file. +2. Download the report file and unzip it using a tool of your choice. +3. Open the index.html file in a web browser to view the report. + +The report will show you a full summary of your tests, including information on which +tests passed, failed, were skipped, or were flaky. You can filter the report by browser +and explore the details of individual tests, including any errors or failures, video +recordings, and the steps involved in each test. Simply click on a test to view its details. + +## Debugging Tests + +Refer to [this documentation](https://playwright.dev/docs/debug) on how to debug a test. + +## Configuration + +This is very much underdeveloped/WIP. At the moment, there exists a (git-shared) `.env` +file which can be used for configuring certain test attributes. This is most likely +about to change in the future. Stay tuned for updates! + +## Github Actions integration + +The e2e.yml workflow is made up of two jobs: one for running on pull requests (PRs) and +one for running on commits. + +1. When running on PRs, the workflow will start the dev server, use dev3.openmrs.org as the backend, +and run tests only on chromium. This is done in order to quickly provide feedback to the developer. +The tests are designed to generate their own data and clean up after themselves once they are finished. +This ensures that the tests will have minimum effect from changes made to dev3 by other developers. +In the future, we plan to use a docker container to run the tests in an isolated environment once we +figure out a way to spin up the container within a small amount of time. +2. When running on commits, the workflow will spin up a docker container and run the dev server against +it in order to provide a known and isolated environment. In addition, tests will be run on multiple +browsers (chromium, firefox, and WebKit) to ensure compatibility. + +## Troubleshooting tips + +On MacOS, you might run into the following error: +```browserType.launch: Executable doesn't exist at /Users//Library/Caches/ms-playwright/chromium-1015/chrome-mac/Chromium.app/Contents/MacOS/Chromium``` +In order to fix this, you can attempt to force the browser reinstallation by running: +```PLAYWRIGHT_BROWSERS_PATH=/Users/$USER/Library/Caches/ms-playwright npx playwright install``` diff --git a/e2e/commands/index.ts b/e2e/commands/index.ts new file mode 100644 index 00000000..a3640e32 --- /dev/null +++ b/e2e/commands/index.ts @@ -0,0 +1,2 @@ +export * from './patient-operations'; +export * from './visit-operations'; diff --git a/e2e/commands/patient-operations.ts b/e2e/commands/patient-operations.ts new file mode 100644 index 00000000..f04171b5 --- /dev/null +++ b/e2e/commands/patient-operations.ts @@ -0,0 +1,105 @@ +import { APIRequestContext, expect } from '@playwright/test'; + +export interface Patient { + uuid: string; + identifiers: Identifier[]; + display: string; + person: { + uuid: string; + display: string; + gender: string; + age: number; + birthdate: string; + birthdateEstimated: boolean; + dead: boolean; + deathDate?: string; + causeOfDeath?: string; + preferredAddress: { + address1: string; + cityVillage: string; + country: string; + postalCode: string; + stateProvince: string; + countyDistrict: string; + }; + attributes: Array>; + voided: boolean; + birthtime?: string; + deathdateEstimated: boolean; + resourceVersion: string; + }; + attributes: { value: string; attributeType: { uuid: string; display: string } }[]; + voided: boolean; +} + +export interface Address { + preferred: boolean; + address1: string; + cityVillage: string; + country: string; + postalCode: string; + stateProvince: string; +} + +export interface Identifier { + uuid: string; + display: string; +} + +export const generateRandomPatient = async (api: APIRequestContext): Promise => { + const identifierRes = await api.post('idgen/identifiersource/8549f706-7e85-4c1d-9424-217d50a2988b/identifier', { + data: {}, + }); + await expect(identifierRes.ok()).toBeTruthy(); + const { identifier } = await identifierRes.json(); + + const patientRes = await api.post('patient', { + // TODO: This is not configurable right now. It probably should be. + data: { + identifiers: [ + { + identifier, + identifierType: '05a29f94-c0ed-11e2-94be-8c13b969e334', + location: '44c3efb0-2583-4c80-a79e-1f756a03c0a1', + preferred: true, + }, + ], + person: { + addresses: [ + { + address1: 'Bom Jesus Street', + address2: '', + cityVillage: 'Recife', + country: 'Brazil', + postalCode: '50030-310', + stateProvince: 'Pernambuco', + }, + ], + attributes: [], + birthdate: '2020-2-1', + birthdateEstimated: true, + dead: false, + gender: 'M', + names: [ + { + familyName: `Smith${Math.floor(Math.random() * 10000)}`, + givenName: `John${Math.floor(Math.random() * 10000)}`, + middleName: '', + preferred: true, + }, + ], + }, + }, + }); + await expect(patientRes.ok()).toBeTruthy(); + return await patientRes.json(); +}; + +export const getPatient = async (api: APIRequestContext, uuid: string): Promise => { + const patientRes = await api.get(`patient/${uuid}?v=full`); + return await patientRes.json(); +}; + +export const deletePatient = async (api: APIRequestContext, uuid: string) => { + await api.delete(`patient/${uuid}`, { data: {} }); +}; diff --git a/e2e/commands/visit-operations.ts b/e2e/commands/visit-operations.ts new file mode 100644 index 00000000..5aff4209 --- /dev/null +++ b/e2e/commands/visit-operations.ts @@ -0,0 +1,31 @@ +import { APIRequestContext, expect } from '@playwright/test'; +import { Visit } from '@openmrs/esm-framework'; +import dayjs from 'dayjs'; + +export const startVisit = async (api: APIRequestContext, patientId: string): Promise => { + const visitRes = await api.post('visit', { + data: { + startDatetime: dayjs().subtract(1, 'D').format('YYYY-MM-DDTHH:mm:ss.SSSZZ'), + patient: patientId, + location: process.env.E2E_LOGIN_DEFAULT_LOCATION_UUID, + visitType: '7b0f5697-27e3-40c4-8bae-f4049abfb4ed', + attributes: [], + }, + }); + + await expect(visitRes.ok()).toBeTruthy(); + return await visitRes.json(); +}; + +export const endVisit = async (api: APIRequestContext, uuid: string) => { + const visitRes = await api.post(`visit/${uuid}`, { + data: { + location: process.env.E2E_LOGIN_DEFAULT_LOCATION_UUID, + startDatetime: dayjs().subtract(1, 'D').format('YYYY-MM-DDTHH:mm:ss.SSSZZ'), + visitType: '7b0f5697-27e3-40c4-8bae-f4049abfb4ed', + stopDatetime: dayjs().format('YYYY-MM-DDTHH:mm:ss.SSSZZ'), + }, + }); + + return await visitRes.json(); +}; diff --git a/e2e/core/global-setup.ts b/e2e/core/global-setup.ts new file mode 100644 index 00000000..74897499 --- /dev/null +++ b/e2e/core/global-setup.ts @@ -0,0 +1,32 @@ +import { request } from '@playwright/test'; +import * as dotenv from 'dotenv'; + +dotenv.config(); + +/** + * This configuration is to reuse the signed-in state in the tests + * by log in only once using the API and then skip the log in step for all the tests. + * + * https://playwright.dev/docs/auth#reuse-signed-in-state + */ + +async function globalSetup() { + const requestContext = await request.newContext(); + const token = Buffer.from(`${process.env.E2E_USER_ADMIN_USERNAME}:${process.env.E2E_USER_ADMIN_PASSWORD}`).toString( + 'base64', + ); + await requestContext.post(`${process.env.E2E_BASE_URL}/ws/rest/v1/session`, { + data: { + sessionLocation: process.env.E2E_LOGIN_DEFAULT_LOCATION_UUID, + locale: 'en', + }, + headers: { + Accept: 'application/json', + Authorization: `Basic ${token}`, + }, + }); + await requestContext.storageState({ path: 'e2e/storageState.json' }); + await requestContext.dispose(); +} + +export default globalSetup; diff --git a/e2e/core/index.ts b/e2e/core/index.ts new file mode 100644 index 00000000..607718c2 --- /dev/null +++ b/e2e/core/index.ts @@ -0,0 +1 @@ +export * from './test'; diff --git a/e2e/core/test.ts b/e2e/core/test.ts new file mode 100644 index 00000000..dd3e40bb --- /dev/null +++ b/e2e/core/test.ts @@ -0,0 +1,20 @@ +import { APIRequestContext, Page, test as base } from '@playwright/test'; +import { api } from '../fixtures'; + +// This file sets up our custom test harness using the custom fixtures. +// See https://playwright.dev/docs/test-fixtures#creating-a-fixture for details. +// If a spec intends to use one of the custom fixtures, the special `test` function +// exported from this file must be used instead of the default `test` function +// provided by playwright. + +export interface CustomTestFixtures { + loginAsAdmin: Page; +} + +export interface CustomWorkerFixtures { + api: APIRequestContext; +} + +export const test = base.extend({ + api: [api, { scope: 'worker' }], +}); diff --git a/e2e/fixtures/api.ts b/e2e/fixtures/api.ts new file mode 100644 index 00000000..6afd8d59 --- /dev/null +++ b/e2e/fixtures/api.ts @@ -0,0 +1,26 @@ +import { APIRequestContext, PlaywrightWorkerArgs, WorkerFixture } from '@playwright/test'; + +/** + * A fixture which initializes an [`APIRequestContext`](https://playwright.dev/docs/api/class-apirequestcontext) + * that is bound to the configured OpenMRS API server. The context is automatically authenticated + * using the configured admin account. + * + * Use the request context like this: + * ```ts + * test('your test', async ({ api }) => { + * const res = await api.get('patient/1234'); + * await expect(res.ok()).toBeTruthy(); + * }); + * ``` + */ +export const api: WorkerFixture = async ({ playwright }, use) => { + const ctx = await playwright.request.newContext({ + baseURL: `${process.env.E2E_BASE_URL}/ws/rest/v1/`, + httpCredentials: { + username: process.env.E2E_USER_ADMIN_USERNAME, + password: process.env.E2E_USER_ADMIN_PASSWORD, + }, + }); + + await use(ctx); +}; diff --git a/e2e/fixtures/index.ts b/e2e/fixtures/index.ts new file mode 100644 index 00000000..b1c13e73 --- /dev/null +++ b/e2e/fixtures/index.ts @@ -0,0 +1 @@ +export * from './api'; diff --git a/e2e/pages/chart-page.ts b/e2e/pages/chart-page.ts new file mode 100644 index 00000000..cd5191a4 --- /dev/null +++ b/e2e/pages/chart-page.ts @@ -0,0 +1,11 @@ +import { type Page } from '@playwright/test'; + +export class ChartPage { + constructor(readonly page: Page) {} + + readonly formsTable = () => this.page.getByRole('table', { name: /forms/i }); + + async goTo(patientUuid: string) { + await this.page.goto('/openmrs/spa/patient/' + patientUuid + '/chart'); + } +} diff --git a/e2e/pages/home-page.ts b/e2e/pages/home-page.ts new file mode 100644 index 00000000..c90be35a --- /dev/null +++ b/e2e/pages/home-page.ts @@ -0,0 +1,9 @@ +import { Page } from '@playwright/test'; + +export class HomePage { + constructor(readonly page: Page) {} + + async gotoHome() { + await this.page.goto('/openmrs/spa/stock-management'); + } +} diff --git a/e2e/pages/index.ts b/e2e/pages/index.ts new file mode 100644 index 00000000..4be01a0d --- /dev/null +++ b/e2e/pages/index.ts @@ -0,0 +1,2 @@ +export * from './home-page'; +export * from './chart-page'; diff --git a/e2e/specs/stock-overview-test.spec.ts b/e2e/specs/stock-overview-test.spec.ts new file mode 100644 index 00000000..220722bb --- /dev/null +++ b/e2e/specs/stock-overview-test.spec.ts @@ -0,0 +1,23 @@ +import { test, expect } from '@playwright/test'; +import dotenv from 'dotenv'; +import { HomePage } from '../pages'; + +dotenv.config(); + +test.describe('Overview Page Test', () => { + test('should navigate to the Overview page and verify sections', async ({ page }) => { + const homePage = new HomePage(page); + + await test.step('When I visit the home page', async () => { + await homePage.gotoHome(); + }); + + await test.step('Then I should be at the home page', async () => { + await expect(page).toHaveURL(`${process.env.E2E_BASE_URL}/spa/stock-management`); + }); + + await test.step('Then Stock Management should be visible', async () => { + await expect(page.getByText('Stock Management')).toBeVisible(); + }); + }); +}); diff --git a/example.env b/example.env new file mode 100644 index 00000000..4e4e820b --- /dev/null +++ b/example.env @@ -0,0 +1,6 @@ +# This is an environment file for configuring dynamic values. +E2E_BASE_URL=https://openmrs-refapp.globalhealthapp.net/openmrs/ +E2E_USER_ADMIN_USERNAME=admin +E2E_USER_ADMIN_PASSWORD=Admin123 +E2E_LOGIN_DEFAULT_LOCATION_UUID=44c3efb0-2583-4c80-a79e-1f756a03c0a1 +# The above location UUID is for the "Outpatient Clinic" location in the reference application diff --git a/jest.config.js b/jest.config.js index 5b3017cc..08ac9a1c 100644 --- a/jest.config.js +++ b/jest.config.js @@ -5,7 +5,7 @@ const path = require('path'); module.exports = { clearMocks: true, - collectCoverageFrom: ['**/src/**/*.component.tsx', '!**/node_modules/**', '!**/src/declarations.d.ts'], + collectCoverageFrom: ['**/src/**/*.component.tsx', '!**/node_modules/**', '!**/src/declarations.d.ts', '!**/e2e/**'], transform: { '^.+\\.tsx?$': ['@swc/jest'], }, @@ -23,4 +23,8 @@ module.exports = { testEnvironmentOptions: { url: 'http://localhost/', }, + testPathIgnorePatterns: [ + "/node_modules/", + "/e2e/" // Ignore the e2e directory containing Playwright tests + ] }; diff --git a/package.json b/package.json index c2950a4e..aab6e4e5 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,8 @@ "coverage": "yarn test --coverage", "prepare": "husky install", "extract-translations": "i18next 'src/**/*.component.tsx' 'src/**/*.tsx' --config ./i18next-parser.config.js", - "postinstall": "husky" + "postinstall": "husky", + "test-e2e": "playwright test" }, "browserslist": [ "extends browserslist-config-openmrs" @@ -43,6 +44,7 @@ "dependencies": { "@carbon/react": "^1.33.1", "@hookform/resolvers": "^3.3.0", + "dotenv": "^16.4.5", "file-saver": "^2.0.5", "lodash-es": "^4.17.21", "react-hook-form": "^7.45.4", diff --git a/yarn.lock b/yarn.lock index 7cf19fad..a72d875e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4164,6 +4164,7 @@ __metadata: cross-env: "npm:^7.0.3" css-loader: "npm:^6.8.1" dayjs: "npm:^1.11.9" + dotenv: "npm:^16.4.5" eslint: "npm:^8.44.0" eslint-plugin-react-hooks: "npm:^4.6.2" eslint-plugin-testing-library: "npm:^6.3.0" @@ -12016,6 +12017,13 @@ __metadata: languageName: node linkType: hard +"dotenv@npm:^16.4.5": + version: 16.4.5 + resolution: "dotenv@npm:16.4.5" + checksum: 10/55a3134601115194ae0f924e54473459ed0d9fc340ae610b676e248cca45aa7c680d86365318ea964e6da4e2ea80c4514c1adab5adb43d6867fb57ff068f95c8 + languageName: node + linkType: hard + "downshift@npm:8.1.0": version: 8.1.0 resolution: "downshift@npm:8.1.0" From cb719a9e9b8138c4f11655c193db65acbc009945 Mon Sep 17 00:00:00 2001 From: lucyjemutai <130601439+lucyjemutai@users.noreply.github.com> Date: Thu, 3 Oct 2024 08:59:39 +0300 Subject: [PATCH 2/9] add playwright dependency --- package.json | 4 +++- yarn.lock | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index aab6e4e5..ae815bf8 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,8 @@ "prepare": "husky install", "extract-translations": "i18next 'src/**/*.component.tsx' 'src/**/*.tsx' --config ./i18next-parser.config.js", "postinstall": "husky", - "test-e2e": "playwright test" + "test-e2e": "playwright test", + "playwright": "playwright test" }, "browserslist": [ "extends browserslist-config-openmrs" @@ -44,6 +45,7 @@ "dependencies": { "@carbon/react": "^1.33.1", "@hookform/resolvers": "^3.3.0", + "@playwright/test": "^1.47.2", "dotenv": "^16.4.5", "file-saver": "^2.0.5", "lodash-es": "^4.17.21", diff --git a/yarn.lock b/yarn.lock index a72d875e..3566273b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4145,6 +4145,7 @@ __metadata: "@hookform/resolvers": "npm:^3.3.0" "@openmrs/esm-framework": "npm:next" "@openmrs/esm-styleguide": "npm:next" + "@playwright/test": "npm:^1.47.2" "@swc/cli": "npm:^0.1.62" "@swc/core": "npm:^1.3.68" "@swc/jest": "npm:^0.2.26" @@ -4318,6 +4319,17 @@ __metadata: languageName: node linkType: hard +"@playwright/test@npm:^1.47.2": + version: 1.47.2 + resolution: "@playwright/test@npm:1.47.2" + dependencies: + playwright: "npm:1.47.2" + bin: + playwright: cli.js + checksum: 10/374bf386b4eb8f3b6664fa017402f87e57ee121970661a5b3c83f0fa146a7e6b7456e28cd5b1539c0981cb9a9166b1c7484549d87dc0d8076305ec64278ec770 + languageName: node + linkType: hard + "@pnpm/config.env-replace@npm:^1.1.0": version: 1.1.0 resolution: "@pnpm/config.env-replace@npm:1.1.0" @@ -13672,6 +13684,16 @@ __metadata: languageName: node linkType: hard +"fsevents@npm:2.3.2": + version: 2.3.2 + resolution: "fsevents@npm:2.3.2" + dependencies: + node-gyp: "npm:latest" + checksum: 10/6b5b6f5692372446ff81cf9501c76e3e0459a4852b3b5f1fc72c103198c125a6b8c72f5f166bdd76ffb2fca261e7f6ee5565daf80dca6e571e55bcc589cc1256 + conditions: os=darwin + languageName: node + linkType: hard + "fsevents@npm:^2.3.2, fsevents@npm:~2.3.2": version: 2.3.3 resolution: "fsevents@npm:2.3.3" @@ -13682,6 +13704,15 @@ __metadata: languageName: node linkType: hard +"fsevents@patch:fsevents@npm%3A2.3.2#optional!builtin": + version: 2.3.2 + resolution: "fsevents@patch:fsevents@npm%3A2.3.2#optional!builtin::version=2.3.2&hash=df0bf1" + dependencies: + node-gyp: "npm:latest" + conditions: os=darwin + languageName: node + linkType: hard + "fsevents@patch:fsevents@npm%3A^2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin": version: 2.3.3 resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" @@ -19735,6 +19766,30 @@ __metadata: languageName: node linkType: hard +"playwright-core@npm:1.47.2": + version: 1.47.2 + resolution: "playwright-core@npm:1.47.2" + bin: + playwright-core: cli.js + checksum: 10/2a2b28b2f1d01bc447f4f1cb4b5248ed053fde38429484c909efa17226e692a79cd5e6d4c337e9040eaaf311b6cb4a36027d6d14f1f44c482c5fb3feb081f913 + languageName: node + linkType: hard + +"playwright@npm:1.47.2": + version: 1.47.2 + resolution: "playwright@npm:1.47.2" + dependencies: + fsevents: "npm:2.3.2" + playwright-core: "npm:1.47.2" + dependenciesMeta: + fsevents: + optional: true + bin: + playwright: cli.js + checksum: 10/73494a187be3e75222b65ebcce8d790eada340bd61ca0d07410060a52232ddbc2357c4882d7b42434054dc1f4802fdb039a47530b4b5500dcfd1bf0edd63c191 + languageName: node + linkType: hard + "pngjs@npm:^3.0.0, pngjs@npm:^3.3.3": version: 3.4.0 resolution: "pngjs@npm:3.4.0" From 75beb2efead4183cdfcc56213d99a3f1c81dd6f1 Mon Sep 17 00:00:00 2001 From: lucyjemutai <130601439+lucyjemutai@users.noreply.github.com> Date: Thu, 3 Oct 2024 09:26:09 +0300 Subject: [PATCH 3/9] add playwright cofig and sample test --- e2e/specs/stock-overview-test.spec.ts | 6 +---- playwright.config.ts | 34 +++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 playwright.config.ts diff --git a/e2e/specs/stock-overview-test.spec.ts b/e2e/specs/stock-overview-test.spec.ts index 220722bb..c7afb396 100644 --- a/e2e/specs/stock-overview-test.spec.ts +++ b/e2e/specs/stock-overview-test.spec.ts @@ -13,11 +13,7 @@ test.describe('Overview Page Test', () => { }); await test.step('Then I should be at the home page', async () => { - await expect(page).toHaveURL(`${process.env.E2E_BASE_URL}/spa/stock-management`); - }); - - await test.step('Then Stock Management should be visible', async () => { - await expect(page.getByText('Stock Management')).toBeVisible(); + await expect(page).toHaveURL(`${process.env.E2E_BASE_URL}spa/login`); }); }); }); diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 00000000..d9041080 --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,34 @@ +import { devices, type PlaywrightTestConfig } from '@playwright/test'; +import { config as dotenvConfig } from 'dotenv'; +import { resolve } from 'node:path'; +dotenvConfig({ path: resolve(process.cwd(), '.env') }); +dotenvConfig(); + +// See https://playwright.dev/docs/test-configuration. +const config: PlaywrightTestConfig = { + testDir: './e2e/specs', + timeout: 3 * 60 * 1000, + expect: { + timeout: 40 * 1000, + }, + fullyParallel: true, + forbidOnly: !!process.env.CI, + retries: 0, + reporter: process.env.CI ? [['junit', { outputFile: 'results.xml' }], ['html']] : [['html']], + globalSetup: require.resolve('./e2e/core/global-setup'), + use: { + baseURL: `${process.env.E2E_BASE_URL}/spa/stock-management`, + storageState: 'e2e/storageState.json', + video: 'retain-on-failure', + }, + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'], + }, + }, + ], +}; + +export default config; From 93512f3855b6c3d54d8858da3131c4c34c1f108c Mon Sep 17 00:00:00 2001 From: lucille Date: Thu, 3 Oct 2024 13:47:57 +0300 Subject: [PATCH 4/9] failling github job --- .github/workflows/e2e.yml | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 26ebd77d..fba9c5ca 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -11,6 +11,7 @@ on: jobs: main: runs-on: ubuntu-latest + steps: - name: Checkout repo uses: actions/checkout@v3 @@ -26,21 +27,22 @@ jobs: node-version: 18 - name: Cache dependencies - id: cache uses: actions/cache@v3 with: - path: '**/node_modules' - key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }} - + path: node_modules + key: ${{ runner.os }}-${{ hashFiles('yarn.lock') }} + - name: Install dependencies - if: steps.cache.outputs.cache-hit != 'true' - run: yarn install --immutable + run: yarn install - name: Install Playwright Browsers run: npx playwright install chromium --with-deps - name: Run dev server - run: yarn start --sources 'packages/esm-*-app/' --port 8180 & # Refer to O3-1994 + run: yarn start --sources 'packages/esm-*-app/' --port 8180 & + + - name: Wait for server to be ready + run: npx wait-on http://localhost:8180 - name: Run E2E tests run: yarn playwright test @@ -52,12 +54,3 @@ jobs: name: playwright-report path: playwright-report/ retention-days: 30 - - github-action: - runs-on: ubuntu-latest - steps: - - name: Checkout repo - uses: actions/checkout@v3 - - - name: Run Playwright tests with GitHub Action - run: yarn playwright test \ No newline at end of file From 621509c4aaa617ab70acc1ee5a6cc789348fd62a Mon Sep 17 00:00:00 2001 From: lucille Date: Thu, 3 Oct 2024 14:09:53 +0300 Subject: [PATCH 5/9] failling github jobs --- .github/workflows/e2e.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index fba9c5ca..e565c3e0 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -41,9 +41,6 @@ jobs: - name: Run dev server run: yarn start --sources 'packages/esm-*-app/' --port 8180 & - - name: Wait for server to be ready - run: npx wait-on http://localhost:8180 - - name: Run E2E tests run: yarn playwright test From 5cdb1f6460e470267224688f4d0e0c692ab57f4a Mon Sep 17 00:00:00 2001 From: lucille Date: Fri, 11 Oct 2024 08:21:20 +0300 Subject: [PATCH 6/9] latest version of Playwright, --- e2e/specs/stock-overview-test.spec.ts | 2 +- package.json | 2 +- yarn.lock | 30 +++++++++++++-------------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/e2e/specs/stock-overview-test.spec.ts b/e2e/specs/stock-overview-test.spec.ts index c7afb396..b9fc976c 100644 --- a/e2e/specs/stock-overview-test.spec.ts +++ b/e2e/specs/stock-overview-test.spec.ts @@ -13,7 +13,7 @@ test.describe('Overview Page Test', () => { }); await test.step('Then I should be at the home page', async () => { - await expect(page).toHaveURL(`${process.env.E2E_BASE_URL}spa/login`); + await expect(page).toHaveURL(`${process.env.E2E_BASE_URL}/spa/stock-management`); }); }); }); diff --git a/package.json b/package.json index ae815bf8..c624d6b1 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "dependencies": { "@carbon/react": "^1.33.1", "@hookform/resolvers": "^3.3.0", - "@playwright/test": "^1.47.2", + "@playwright/test": "^1.48.0", "dotenv": "^16.4.5", "file-saver": "^2.0.5", "lodash-es": "^4.17.21", diff --git a/yarn.lock b/yarn.lock index 3566273b..99904335 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4145,7 +4145,7 @@ __metadata: "@hookform/resolvers": "npm:^3.3.0" "@openmrs/esm-framework": "npm:next" "@openmrs/esm-styleguide": "npm:next" - "@playwright/test": "npm:^1.47.2" + "@playwright/test": "npm:^1.48.0" "@swc/cli": "npm:^0.1.62" "@swc/core": "npm:^1.3.68" "@swc/jest": "npm:^0.2.26" @@ -4319,14 +4319,14 @@ __metadata: languageName: node linkType: hard -"@playwright/test@npm:^1.47.2": - version: 1.47.2 - resolution: "@playwright/test@npm:1.47.2" +"@playwright/test@npm:^1.48.0": + version: 1.48.0 + resolution: "@playwright/test@npm:1.48.0" dependencies: - playwright: "npm:1.47.2" + playwright: "npm:1.48.0" bin: playwright: cli.js - checksum: 10/374bf386b4eb8f3b6664fa017402f87e57ee121970661a5b3c83f0fa146a7e6b7456e28cd5b1539c0981cb9a9166b1c7484549d87dc0d8076305ec64278ec770 + checksum: 10/8845ed0f0b303e10ee0a0f04562ef83be3f9123fac91d722f697ad964a119af74cd5fb08e1139f1b20b27396479456c984bfdc699fadedd92af9c0490fb4c7c0 languageName: node linkType: hard @@ -19766,27 +19766,27 @@ __metadata: languageName: node linkType: hard -"playwright-core@npm:1.47.2": - version: 1.47.2 - resolution: "playwright-core@npm:1.47.2" +"playwright-core@npm:1.48.0": + version: 1.48.0 + resolution: "playwright-core@npm:1.48.0" bin: playwright-core: cli.js - checksum: 10/2a2b28b2f1d01bc447f4f1cb4b5248ed053fde38429484c909efa17226e692a79cd5e6d4c337e9040eaaf311b6cb4a36027d6d14f1f44c482c5fb3feb081f913 + checksum: 10/644489b4de9cc181e83eb639a283d3c4f8e4c3b1b1759d7c93b72fd0373b5a66ba376ee6a5ee3eca67f1b773bf15c5e01b6aeedd43c94c355bf4fc0d110713bc languageName: node linkType: hard -"playwright@npm:1.47.2": - version: 1.47.2 - resolution: "playwright@npm:1.47.2" +"playwright@npm:1.48.0": + version: 1.48.0 + resolution: "playwright@npm:1.48.0" dependencies: fsevents: "npm:2.3.2" - playwright-core: "npm:1.47.2" + playwright-core: "npm:1.48.0" dependenciesMeta: fsevents: optional: true bin: playwright: cli.js - checksum: 10/73494a187be3e75222b65ebcce8d790eada340bd61ca0d07410060a52232ddbc2357c4882d7b42434054dc1f4802fdb039a47530b4b5500dcfd1bf0edd63c191 + checksum: 10/85b06ae8d0ab7a5a8c9a0d416007b18f35a59455fad40438bda98cbe07c48f338e97b98b1d9214e27f08d6ac284eba0eaab722f5684cd17dd4a47f5b69d004b9 languageName: node linkType: hard From 2b7f9ed8221dddcc6ddbd791c0d86b3d36294e31 Mon Sep 17 00:00:00 2001 From: lucille Date: Fri, 11 Oct 2024 08:28:11 +0300 Subject: [PATCH 7/9] failling test --- e2e/specs/stock-overview-test.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/specs/stock-overview-test.spec.ts b/e2e/specs/stock-overview-test.spec.ts index b9fc976c..1fbe5a63 100644 --- a/e2e/specs/stock-overview-test.spec.ts +++ b/e2e/specs/stock-overview-test.spec.ts @@ -13,7 +13,7 @@ test.describe('Overview Page Test', () => { }); await test.step('Then I should be at the home page', async () => { - await expect(page).toHaveURL(`${process.env.E2E_BASE_URL}/spa/stock-management`); + await expect(page).toHaveURL(`${process.env.E2E_BASE_URL}/spa/login`); }); }); }); From b9a84505b149a1e490f0b4da23749ad08351e50c Mon Sep 17 00:00:00 2001 From: lucille Date: Fri, 11 Oct 2024 08:33:37 +0300 Subject: [PATCH 8/9] failling test --- e2e/specs/stock-overview-test.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/specs/stock-overview-test.spec.ts b/e2e/specs/stock-overview-test.spec.ts index 1fbe5a63..c7afb396 100644 --- a/e2e/specs/stock-overview-test.spec.ts +++ b/e2e/specs/stock-overview-test.spec.ts @@ -13,7 +13,7 @@ test.describe('Overview Page Test', () => { }); await test.step('Then I should be at the home page', async () => { - await expect(page).toHaveURL(`${process.env.E2E_BASE_URL}/spa/login`); + await expect(page).toHaveURL(`${process.env.E2E_BASE_URL}spa/login`); }); }); }); From 44330d3172cd1e4c0a98f0ec53949da112f3d2ce Mon Sep 17 00:00:00 2001 From: lucille Date: Fri, 11 Oct 2024 16:55:52 +0300 Subject: [PATCH 9/9] remove duplicated script --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index c624d6b1..4cf5fcdb 100644 --- a/package.json +++ b/package.json @@ -20,8 +20,7 @@ "prepare": "husky install", "extract-translations": "i18next 'src/**/*.component.tsx' 'src/**/*.tsx' --config ./i18next-parser.config.js", "postinstall": "husky", - "test-e2e": "playwright test", - "playwright": "playwright test" + "test-e2e": "playwright test" }, "browserslist": [ "extends browserslist-config-openmrs"