Skip to content

Commit

Permalink
(test) O3-2113 : Setup playwright and add login e2e test (#740)
Browse files Browse the repository at this point in the history
  • Loading branch information
RandilaP authored Aug 21, 2023
1 parent dabecc7 commit da40164
Show file tree
Hide file tree
Showing 17 changed files with 415 additions and 7 deletions.
2 changes: 1 addition & 1 deletion .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
- [ ] This PR has a title that briefly describes the work done including the ticket number. If there is a ticket, make sure your PR title includes a [conventional commit](https://o3-dev.docs.openmrs.org/#/getting_started/contributing?id=your-pr-title-should-indicate-the-type-of-change-it-is) label. See existing PR titles for inspiration.

#### For changes to apps
- [ ] My work conforms to the [**OpenMRS 3.0 Styleguide**](https://om.rs/styleguide) and [**design documentation**](https://zeroheight.com/23a080e38/p/880723-introduction).
- [ ] My work conforms to the [**OpenMRS 3.0 Styleguide**](https://om.rs/styleguide) and **design documentation**.

#### If applicable
- [ ] My work includes tests or is validated by existing tests.
Expand Down
107 changes: 107 additions & 0 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
name: E2E Tests

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
testOnPR:
if: ${{ github.event_name == 'pull_request' }}
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: 16

- name: Cache dependencies
id: cache
uses: actions/cache@v3
with:
path: '**/node_modules'
key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}

- name: Install dependencies
run: yarn setup

- name: Install Playwright Browsers
run: yarn playwright install chromium --with-deps

- name: Run dev server
run: yarn run:omrs develop --sources packages/apps/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

testOnPush:
if: ${{ github.event_name == 'push' }}
timeout-minutes: 60
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: 16

- name: Cache dependencies
id: cache
uses: actions/cache@v3
with:
path: '**/node_modules'
key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}

- name: Install dependencies
run: yarn setup

- name: Install Playwright Browsers
run: yarn playwright install chromium --with-deps

- name: Run db and web containers
run: |
cd e2e/support
docker-compose up -d
- name: Wait for OpenMRS instance to start
run: while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' http://localhost:9000/openmrs/login.htm)" != "200" ]]; do sleep 10; done

- name: Run dev server
run: yarn run:omrs develop --sources packages/apps/esm-login-app --backend "http://localhost:9000" --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
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,9 @@ package-lock.json
!.yarn/releases
!.yarn/sdks
!.yarn/versions

# Playwright and e2e tests
/test-results/
/playwright-report/
/playwright/.cache/
e2e/storageState.json
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,5 +184,5 @@ will cause GitHub Actions to publish the packages, completing the release proces
## Design Patterns

For documentation about our design patterns, please visit our [design system](https://zeroheight.com/23a080e38/p/880723--introduction) documentation website.
For documentation about our design patterns, please visit our design system documentation website.

2 changes: 1 addition & 1 deletion docs/main/upgrade_3_to_4.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ For a complete look at what needs to be upgraded, please read the relevant docum
- [React Router 5 to 6](https://reactrouter.com/en/main/upgrading/v5)
- [Carbon 10 to 11](https://github.com/carbon-design-system/carbon/blob/main/docs/migration/v11.md)
- [Jest 26 to 27](https://jestjs.io/blog/2021/05/25/jest-27)
- [Jest 27 to 28](https://jestjs.io/docs/28.x/migration-guide)
- [Jest 27 to 28](https://jestjs.io/blog/2022/04/25/jest-28)
- [User Event 12 to 13](https://github.com/testing-library/user-event/releases/tag/v12.0.0)
- [User Event 13 to 14](https://github.com/testing-library/user-event/releases/tag/v14.0.0)

Expand Down
115 changes: 115 additions & 0 deletions e2e/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# 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 --sources 'packages/esm-*-app/'
```
Then, in a separate terminal, run:

```sh
yarn test-e2e --headed
```
<!-- markdown-link-check-disable-next-line -->
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:
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 Action 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/<user>/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```
1 change: 1 addition & 0 deletions e2e/core/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./test";
9 changes: 9 additions & 0 deletions e2e/core/test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { test as base } from "@playwright/test";

// 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 const test = base.extend({});
1 change: 1 addition & 0 deletions e2e/pages/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./login-page";
9 changes: 9 additions & 0 deletions e2e/pages/login-page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Page } from "@playwright/test";

export class LoginPage {
constructor(readonly page: Page) {}

async goto() {
await this.page.goto(`${process.env.E2E_BASE_URL}/spa/login`);
}
}
42 changes: 42 additions & 0 deletions e2e/specs/login.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { test } from "../core";
import { expect } from "@playwright/test";
import { LoginPage } from "../pages";

test("Should login as Admin", async ({ page }) => {
const loginPage = new LoginPage(page);

await test.step("When I goto the login page", async () => {
await loginPage.goto();
});

await test.step("And I enter the username", async () => {
await page
.locator("#username")
.fill(`${process.env.E2E_USER_ADMIN_USERNAME}`);
await page.getByText("Continue").click();
});

await test.step("And I enter the password", async () => {
await page
.locator("#password")
.fill(`${process.env.E2E_USER_ADMIN_PASSWORD}`);
});

await test.step("And I click login buttion", async () => {
await page.getByText("Log in").click();
});

await test.step("And I choose the location", async () => {
await page.getByText("Outpatient clinic").click();
await page.getByText("Confirm").click();
});

await test.step("Then I should be logged in", async () => {
await expect(page).toHaveURL(`${process.env.E2E_BASE_URL}/spa/home`);
});

await test.step("Then I logged out", async () => {
await page.getByRole("button", { name: "Users" }).click();
await page.getByText("Logout").click();
});
});
39 changes: 39 additions & 0 deletions e2e/support/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# This docker compose file is used to create a backend environment for the e2e.yml workflow.
version: "3.7"

services:
backend:
image: openmrs/openmrs-reference-application-3-backend:${TAG:-nightly}
depends_on:
- db
environment:
OMRS_CONFIG_MODULE_WEB_ADMIN: "true"
OMRS_CONFIG_AUTO_UPDATE_DATABASE: "true"
OMRS_CONFIG_CREATE_TABLES: "true"
OMRS_CONFIG_CONNECTION_SERVER: db
OMRS_CONFIG_CONNECTION_DATABASE: openmrs
OMRS_CONFIG_CONNECTION_USERNAME: ${OPENMRS_DB_USER:-openmrs}
OMRS_CONFIG_CONNECTION_PASSWORD: ${OPENMRS_DB_PASSWORD:-openmrs}
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/openmrs"]
timeout: 5s
volumes:
- openmrs-data:/openmrs/data
ports:
- 9000:8080

# MariaDB
db:
image: mariadb:10.8.2
command: "mysqld --character-set-server=utf8 --collation-server=utf8_general_ci"
environment:
MYSQL_DATABASE: openmrs
MYSQL_USER: ${OPENMRS_DB_USER:-openmrs}
MYSQL_PASSWORD: ${OPENMRS_DB_PASSWORD:-openmrs}
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-openmrs}
volumes:
- db-data:/var/lib/mysql

volumes:
openmrs-data: ~
db-data: ~
6 changes: 6 additions & 0 deletions example.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# This is an example environment file for configuring dynamic values.
E2E_BASE_URL=http://localhost:8080/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
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,16 @@
"verify": "turbo run lint && turbo run test && turbo run typescript",
"prettier": "prettier \"packages/**/src/**/*\" --write",
"postinstall": "husky install",
"extract-translations": "lerna run extract-translations -- --config ../../../tools/i18next-parser.config.js"
"extract-translations": "lerna run extract-translations -- --config ../../../tools/i18next-parser.config.js",
"test": "cross-env TZ=UTC jest --config jest.config.json --verbose false --passWithNoTests",
"test-watch": "cross-env TZ=UTC jest --watch --config jest.config.json",
"test-e2e": "playwright test",
"coverage": "yarn test --coverage"
},
"devDependencies": {
"@babel/highlight": "^7.18.6",
"@jest/types": "^28.1.3",
"@playwright/test": "^1.30.0",
"@swc/core": "^1.3.58",
"@swc/jest": "^0.2.22",
"@testing-library/dom": "^8.16.0",
Expand All @@ -38,6 +43,7 @@
"autoprefixer": "^10.4.2",
"cross-env": "7.0.2",
"docsify": "^4.12.2",
"dotenv": "^16.0.3",
"eslint": "^7.10.0",
"eslint-config-prettier": "^6.11.0",
"eslint-config-ts-react-important-stuff": "^3.0.0",
Expand Down
Loading

0 comments on commit da40164

Please sign in to comment.