Skip to content

Commit

Permalink
chore(tests): Improve E2E Documentation (#16909)
Browse files Browse the repository at this point in the history
* chore(tests): Improve E2E Documentation

* Update libs/testing/e2e/README.md

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored and jonnigs committed Nov 26, 2024
1 parent 5370180 commit 7dc0708
Showing 1 changed file with 194 additions and 27 deletions.
221 changes: 194 additions & 27 deletions libs/testing/e2e/README.md
Original file line number Diff line number Diff line change
@@ -1,48 +1,215 @@
# E2E Testing
# E2E Testing Library

This library was generated with [Nx](https://nx.dev). It contains utility functions and configuration files that assist with end-to-end (E2E) testing in Playwright for various apps.
This library contains utility functions, shared configuration, and documentation to assist with end-to-end (E2E) testing for all apps using Playwright.

## Overview
## 📚 Overview

This library includes:
### Contents

- **Helper Functions:** Utility functions designed to streamline E2E testing with Playwright. These functions cater to different applications across the project and help automate common testing workflows.
- **Global Playwright Configuration:** The `createGlobalConfig` function provides a shared Playwright configuration used across multiple applications. It standardizes the testing environment.
- **🔧 Helper Functions**: Utility functions to simplify and standardize E2E testing across apps.
- **⚙️ Shared Playwright Configuration**: A common configuration used as the base for all app-specific Playwright configurations.
- **🌍 Multi-Environment Testing**: Support for running tests in `local`, `dev`, `staging`, and `prod` environments.

## Mockoon Usage Guide for E2E Tests
## 🚀 How to Use This Library

This section explains how to use [Mockoon](https://mockoon.com/) to set up mock APIs for end-to-end (e2e) testing.
### Importing Helper Functions

### What is Mockoon?
To use helper functions in your tests, import them directly from this library:

[Mockoon](https://mockoon.com/) is an open-source tool for creating mock APIs quickly and easily. It allows developers to simulate backend servers without relying on live backend services. This is especially useful for e2e testing, where consistency and repeatability of backend responses are important.
```typescript
import { myHelperFunction } from '@island.is/testing/e2e'
```

### Extending the Common Playwright Config

Each app should create its own `playwright.config.ts` file that extends the shared configuration:

```typescript
import { createPlaywrightConfig } from '@island.is/testing/e2e'

const playwrightConfig = createPlaywrightConfig({
webServerUrl: '<web-server-url>',
command: '<command>',
// Add any app-specific configurations here
})

export default playwrightConfig
```

## 🏃 Running Tests

Use the following command structure to run tests for any app:

```bash
yarn e2e <app-name>
```

### Useful Playwright Commands and Flags

Mockoon provides both a graphical user interface (GUI) for managing API mock files and a command-line interface (CLI) for running these mock APIs in various environments, such as pipelines.
- **Run with UI Mode**: Launch the tests with a UI to select and debug tests interactively.

### Opening an Existing Mock File in Mockoon
```bash
yarn e2e <app-name> --ui
```

To view or modify an existing mock file:
- **Run Tests Without Caching**: Ensure a fresh run of tests without using cached results.

1. Open Mockoon.
2. Click on **+** and then click on **Open Local Environment**.
3. Choose the desired mock file, such as `apps/<my-app>/e2e/mocks/<my-app-mock>.json`.
```bash
yarn e2e <app-name> --skip-nx-cache
```

This will load the mock configuration into the Mockoon UI, allowing you to inspect and edit the mock endpoints.
- **Run a Specific Project**: Run only the tests defined under a specific project in your Playwright config:

### Creating a Mock File with Mockoon UI
```bash
yarn e2e <app-name> -- --project=smoke
yarn e2e <app-name> -- --project=acceptance
yarn e2e <app-name> -- --project=everything
```

To create or modify a mock file:
- **View the Test Report**: After running tests, use this command to view the generated report:

1. Download and install [Mockoon](https://mockoon.com/download/) if you haven't already.
2. Open Mockoon and create a new environment:
- Click on **+** and then click on **New Local Environment**.
- Nema your mock file and choose a location for it e.g. `apps/<my-app>/e2e/mocks/<my-app-mock>.json`.
- Add endpoints, routes, and response details as needed.
```bash
yarn playwright show-report
```

### Running a Mockoon Server with the CLI
- **Run Specific Tests**: Use `--grep` to run tests matching a specific pattern:

To run a mock server with the cli, use the following command:
```bash
yarn e2e <app-name> --grep "Home Page Test"
```

- **Debug Mode**: Run tests in debug mode for better visibility:

```bash
yarn e2e <app-name> --debug
```

## ✍️ Writing Tests

Run `yarn playwright codegen <url-to-your-app> --output <path/to/your/app/spec.ts>` and modify the output. The selectors need special attention; they should be transformed to use roles or `data-testid` attributes for stability (see below on how to).

### 🤔 What to Test

Writing tests for every possible combination is time-consuming for you and the CI pipeline, with diminishing value beyond the most common cases.

You should therefore aim to write test for:

- Most common usage patterns
- Usage/patterns that MUST NOT break
- Problematic cases likely to cause an error/bug

### 🏗️ Test structure

Test cases are written in spec files. Tests that do not modify anything (e.g., _create_ an application, _change_ the user’s name, etc.) and verify basic functionality are called **smoke tests**. Tests that are more detailed and/or make any changes at all, are called **acceptance tests**. Test cases are put into folders by what app they are testing, smoke/acceptance test, and each file tests some aspect of an app. Here is an example of the folder layout for testing the search engine and front-page of the `web` project (within the system-e2e app):

```shell
web/ (app name)
├── smoke/ (test type)
│ └── home-page.spec.ts (feature name, kebab-case)
└── acceptance/
└── search.spec.ts
```

### 🗃️ Spec files

A spec file should have only one description (`test.describe`) of what part of an app is being tested. Therein can be one or more test cases (`test`) with a description of what scenario each test case is testing. Setup and tear down can be done in `test.beforeAll`, `test.beforeEach`, `test.afterAll`, and `test.afterEach`. You should not _rely_ on `after*` ever running, and you should prepare your environment every time _before_ each test. For example:

```jsx
test.describe('Overview part of banking app', () => {
test.beforeAll(() => {
// Create/clear database
// Seed database
})

/* NOTE: there is no guarantee this will run */
test.afterAll(() => {
// Tear down database
// Log out
})

test.beforeEach(() => {
// Log in
// Basic state reset, e.g. clear inbox
})

test('should get paid', () => {
// Make user get money using page.selector, page.click, etc.
// Verify money is present
})
})
```

Each test case (`test`) should test a specific scenario from end-to-end. If your test is getting long and complicated consider breaking it up within a `test` with `test.step`; each step will run in succession and the failure/success report is easier to read. Let’s take the operating licence application as an example; test various routes/cases:

- Hotel permit with food, but no alcohol
- Hotel permit with food and alcohol
- Bar with only alcohol
- Home accommodation (AirBnB style), no food, no alcohol

### 🧰 Using Fixtures and Mocking Server Responses

Fixtures are essential for setting up controlled test data to ensure predictable test behavior. Mocking server responses can help simulate specific backend scenarios without relying on live data. Use the following approach to mock server responses:

```typescript
await page.route('/api/endpoint', (route) =>
route.fulfill({
status: 200,
body: JSON.stringify({ key: 'mockData' }),
}),
)
```

### 😬 Tricky element searching

Some apps, like service-portal and application-system-form, load their components _very_ asynchronously. This can be an issue when targeting some elements, but they do not appear on the first page load, but instead load after the basic page has loaded.

In such cases you can wait for the elements to exist with `page.waitFor*` ([docs](https://playwright.dev/docs/api/class-page#page-wait-for-event)):

```jsx
// Wait for there to be at least 3 checkboxes
await page.waitForSelector(':nth-match("role=checkbox", 3')
// Wait for any arbitrary function
await page.waitForFunction(async () => {
const timer = page.locator('role=timer')
const timeLeft = await timer.textContent()
return Number(timeLeft) < 10
})
```

## 🤖 Mockoon Usage Guide for E2E Tests

### ❓ What is Mockoon?

[Mockoon](https://mockoon.com/) is a tool for creating mock APIs, useful for simulating backend services during E2E testing.

### 📂 Opening and Creating Mock Files

- **To open an existing mock file**: Navigate to `apps/<app>/e2e/mocks/<app-mock>.json` in the Mockoon UI.
- **To create a new mock file**:
1. Download [Mockoon](https://mockoon.com/download/).
2. Create a new environment and save it to `apps/<app>/e2e/mocks/`.

### 🖥️ Running Mockoon Server with CLI

To start a mock server:

```bash
yarn mockoon-cli start --data ./apps/<my-app>/e2e/mocks/<my-app-mock>.json --port <port>
yarn mockoon-cli start --data ./apps/<app>/e2e/mocks/<app-mock>.json --port <port>
```

## 🛠️ Troubleshooting and FAQs

### 🔄 Common Issues

- **500: Internal Server Error**: If not related to your code, contact the DevOps team.
- **💀 ESOCKETTIMEDOUT**: Likely an infrastructure issue. Reach out to DevOps if persistent.
- **⌛ Tests Timing Out**: Increase the timeout if known network issues exist:

```typescript
await page.goto('/my-url', { timeout: Timeout.medium })
```

## 📖 Additional Resources

- Refer to each app directory's `README.md` for app-specific details and usage instructions.
- Check out the [Playwright Documentation](https://playwright.dev) for further information.

0 comments on commit 7dc0708

Please sign in to comment.