Skip to content

RI-6570 Configure code coverage reports for the playwright e2e tests #4722

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"private": true,
"scripts": {
"dev:ui": "cross-env yarn --cwd redisinsight/ui dev",
"dev:ui:coverage": "cross-env COLLECT_COVERAGE=true yarn --cwd redisinsight/ui dev",
"dev:api": "cross-env yarn --cwd redisinsight/api start:dev",
"dev:electron:ui": "cross-env RI_APP_PORT=8080 RI_APP_TYPE=ELECTRON NODE_ENV=development yarn --cwd redisinsight/ui dev",
"dev:electron:api": "cross-env RI_APP_PORT=5540 RI_APP_TYPE=ELECTRON NODE_ENV=development USE_TCP_CLOUD_AUTH=true yarn --cwd redisinsight/api start:dev",
Expand Down Expand Up @@ -222,6 +223,7 @@
"vite-plugin-ejs": "^1.7.0",
"vite-plugin-electron": "^0.28.6",
"vite-plugin-electron-renderer": "^0.14.5",
"vite-plugin-istanbul": "^7.1.0",
"vite-plugin-react-click-to-component": "^3.0.0",
"vite-plugin-svgr": "^4.2.0",
"webpack": "^5.95.0",
Expand Down
23 changes: 21 additions & 2 deletions redisinsight/ui/vite.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import svgr from 'vite-plugin-svgr';
import fixReactVirtualized from 'esbuild-plugin-react-virtualized';
import { reactClickToComponent } from 'vite-plugin-react-click-to-component';
import { ViteEjsPlugin } from 'vite-plugin-ejs';
import istanbul from 'vite-plugin-istanbul';
// import { compression } from 'vite-plugin-compression2'
import { fileURLToPath, URL } from 'url';
import path from 'path';
Expand Down Expand Up @@ -47,8 +48,26 @@ export default defineConfig({
})};</script>`;

return html.replace(/<head>/, `<head>\n ${script}`);
}
}
},
},
// Add istanbul plugin for coverage collection when COLLECT_COVERAGE is true
...(process.env.COLLECT_COVERAGE === 'true'
? [
istanbul({
include: 'src/**/*',
exclude: [
'node_modules',
'test/',
'**/*.spec.ts',
'**/*.spec.tsx',
'**/*.test.ts',
'**/*.test.tsx',
],
extension: ['.js', '.ts', '.tsx'],
requireEnv: false,
}),
]
: []),
// !isElectron && compression({
// include: [/\.(js)$/, /\.(css)$/],
// deleteOriginalAssets: true
Expand Down
2 changes: 2 additions & 0 deletions tests/playwright/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ node_modules/
/blob-report/
/playwright/.cache/
/allure-results/
/.nyc_output/
/coverage/
19 changes: 19 additions & 0 deletions tests/playwright/.nycrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"all": true,
"cwd": "../../",
"include": ["redisinsight/ui/src/**/*.{ts,tsx,js,jsx}"],
"exclude": [
"redisinsight/ui/src/**/*.{test,spec}.{ts,tsx,js,jsx}",
"redisinsight/ui/src/**/__tests__/**",
"redisinsight/ui/src/**/__mocks__/**",
"redisinsight/ui/src/**/*.d.ts",
"redisinsight/ui/src/**/node_modules/**"
],
"reporter": ["text", "html", "lcov"],
"report-dir": "tests/playwright/coverage",
"temp-dir": "tests/playwright/.nyc_output",
"cache": false,
"check-coverage": false,
"skip-full": false,
"skip-empty": false
}
60 changes: 55 additions & 5 deletions tests/playwright/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# RedisInsight Playwright Tests

This project contains Playwright tests for RedisInsight.
This project contains Playwright tests for RedisInsight.
It supports running tests on Electron, Docker and Web Redisinsight builds.

## Folder structure
Expand All @@ -13,18 +13,21 @@ It supports running tests on Electron, Docker and Web Redisinsight builds.
## Prerequisites

### General Requirements

- Docker installed and running.
- Redis test environment and RedisInsight configurations from the `tests/e2e` project.

### Steps to Set Up

1. **Start the Redis Test Environment**
Navigate to the `tests/e2e` directory and run:

```shell
docker compose -p test-docker -f rte.docker-compose.yml up --force-recreate --detach
```

2. **For Docker RI Build**
2. **For Docker RI Build**

- Build the Docker image locally or trigger a [GitHub Action](https://github.com/RedisInsight/RedisInsight/actions/workflows/manual-build.yml) to build and download the artifact (`docker-linux-alpine.amd64.tar`).
- Load the image:
```shell
Expand All @@ -40,14 +43,15 @@ It supports running tests on Electron, Docker and Web Redisinsight builds.
```
- Access the app at: `https://localhost:5540`.

3. **For Electron RI Build**
3. **For Electron RI Build**

- Build the project from the root directory:
```shell
yarn package:prod
```
- Update `ELECTRON_EXECUTABLE_PATH` in `tests/playwright/env/.desktop.env` to point to the generated executable file (MacOS by default).

4. **For Local Web Build**
4. **For Local Web Build**
- Stop the Docker RI container from step 2 (to free up port 5540).
- Start the UI and API servers:
```shell
Expand All @@ -59,11 +63,13 @@ It supports running tests on Electron, Docker and Web Redisinsight builds.
## Installation

1. Install dependencies:

```shell
yarn install
```

2. Install Playwright browsers:

```shell
yarn playwright install
```
Expand All @@ -77,53 +83,66 @@ For more details, refer to the [Playwright documentation](https://playwright.dev

## Running Tests

*Note: Make sure to run the commands bellow from the `e2e/playwright` directory.*
_Note: Make sure to run the commands bellow from the `e2e/playwright` directory._

### Docker RI Build

Run end-to-end tests in Chromium:

```shell
yarn test:chromium:docker
```

Run tests in debug mode:

```shell
yarn test:chromium:docker:debug
```

Run tests for a specific `.spec` file:

```shell
yarn test:chromium:docker basic-navigation
```

### Electron RI Build

Run end-to-end tests for the Electron build:

```shell
yarn test:electron
```

### Local Web Environment

Run tests for the local web environment:

```shell
yarn test:chromium:local-web
```

## Extra Tooling

### Auto-Generate Tests

Use Playwright's Codegen to auto-generate tests:
```shell
yarn playwright codegen
```
### Interactive UI Mode
Start Playwright's interactive UI mode:

```shell
yarn playwright test --ui
```

## Reports

### Allure Reports

- Ensure `JAVA_HOME` is set and JDK version 8 to 11 is installed.
- Generate a report with history:
```shell
Expand All @@ -132,9 +151,40 @@ yarn playwright test --ui
- For more details, refer to the [Allure documentation](https://allurereport.org/docs/playwright-reference/).

### Execution Time Comparison

| Test Name | Framework | Browser | Duration |
| --------------------------------- | ---------- | -------- | -------- |
| Verify that user can add Hash Key | TestCafe | Chromium | 27s |
| Verify that user can add Hash Key | Playwright | Chromium | 10s |
| Verify that user can add Hash Key | TestCafe | Electron | 30s |
| Verify that user can add Hash Key | Playwright | Electron | 18s |

## Code Coverage

### Overview

The Playwright tests can collect code coverage for the React frontend application. This helps track which parts of the UI code are being exercised by the end-to-end tests.

### Quick Start

# Start the UI with instrumentation for collecting code coverage

Ensure UI app is running with `COLLECT_COVERAGE=true` env variable, or simply run the following helper from the root folder

```shell
yarn dev:ui:coverage
```

# Run tests with coverage and generate both text and HTML reports

```shell
cd tests/playwright
yarn test:coverage
```

### Coverage Reports Location

After running coverage tests, reports are generated in:

- **HTML Report**: `tests/playwright/coverage/index.html` - Interactive, browsable coverage report
- **LCOV Report**: `tests/playwright/coverage/lcov.info` - For CI/CD integration
63 changes: 61 additions & 2 deletions tests/playwright/fixtures/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,29 @@ import {
_electron as electron,
} from 'playwright'
import log from 'node-color-log'

import { AxiosInstance } from 'axios'
import * as crypto from 'crypto'
import fs from 'fs'
import path from 'path'

import { apiUrl, isElectron, electronExecutablePath } from '../helpers/conf'
import { generateApiClient } from '../helpers/api/http-client'
import { APIKeyRequests } from '../helpers/api/api-keys'
import { DatabaseAPIRequests } from '../helpers/api/api-databases'
import { UserAgreementDialog } from '../pageObjects'

// Coverage type declaration
declare global {
interface Window {
// eslint-disable-next-line no-underscore-dangle
__coverage__: any
}
}

export function generateUUID(): string {
return crypto.randomBytes(16).toString('hex')
}

type CommonFixtures = {
forEachTest: void
api: {
Expand All @@ -25,6 +40,32 @@ type CommonFixtures = {
}

const commonTest = base.extend<CommonFixtures>({
// Simple context setup for coverage
context: async ({ context }, use) => {
if (process.env.COLLECT_COVERAGE === 'true') {
const outputDir = path.join(process.cwd(), '.nyc_output')
await fs.promises.mkdir(outputDir, { recursive: true })

// Expose coverage collection function
await context.exposeFunction(
'collectIstanbulCoverage',
(coverageJSON: string) => {
if (coverageJSON) {
fs.writeFileSync(
path.join(
outputDir,
`playwright_coverage_${generateUUID()}.json`,
),
coverageJSON,
)
}
},
)
}

await use(context)
},

api: async ({ page }, use) => {
const windowId = await page.evaluate(() => window.windowId)

Expand Down Expand Up @@ -55,7 +96,25 @@ const commonTest = base.extend<CommonFixtures>({

await use()

// after each test:
// Collect coverage after each test
if (process.env.COLLECT_COVERAGE === 'true') {
await page
.evaluate(() => {
if (
typeof window !== 'undefined' &&
// eslint-disable-next-line no-underscore-dangle
window.__coverage__
) {
;(window as any).collectIstanbulCoverage(
// eslint-disable-next-line no-underscore-dangle
JSON.stringify(window.__coverage__),
)
}
})
.catch(() => {
// Ignore errors - page might be closed
})
}
},
{ auto: true },
],
Expand Down
6 changes: 5 additions & 1 deletion tests/playwright/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"allure-commandline": "^2.33.0",
"allure-js-commons": "^3.2.0",
"allure-playwright": "^3.2.0",
"cross-env": "^7.0.3"
"cross-env": "^7.0.3",
"nyc": "^17.1.0"
},
"scripts": {
"removeReportDirs": "rm -rf allure-results playwright-report test-results",
Expand All @@ -22,6 +23,9 @@
"test:chromium:local-web:debug": "yarn test:chromium:local-web --debug",
"test:electron": "cross-env envPath=env/.desktop.env yarn playwright test --project=Chromium",
"test:electron:debug": "yarn test:electron --debug",
"test:coverage": "cross-env COLLECT_COVERAGE=true yarn playwright test; yarn coverage",
"coverage": "npx nyc report --reporter=html --reporter=lcov --reporter=text",
"coverage:clean": "rm -rf .nyc_output coverage",
"clean:results": "rm -rf allure-results",
"prep:history": "if [ -d allure-report/history ]; then cp -R allure-report/history allure-results; fi",
"test:allureHistoryReport": "yarn run prep:history && yarn allTests && yarn allure generate --clean -o allure-report allure-results",
Expand Down
Loading
Loading