Directory Layout
Overlay Documentation
This page covers writing tests within rhdh-plugin-export-overlays. For using @red-hat-developer-hub/e2e-test-utils in external projects, see the Guide.
This page documents the standard directory layout for E2E tests in overlay workspaces.
Standard Structure
workspaces/<plugin>/e2e-tests/
├── .env # Environment variables (optional)
├── .yarn/ # Yarn PnP cache (auto-generated)
├── .yarnrc.yml # Yarn configuration
├── eslint.config.js # ESLint configuration
├── package.json # Dependencies and scripts
├── playwright.config.ts # Playwright configuration
├── tsconfig.json # TypeScript configuration
├── yarn.lock # Dependency lock file
└── tests/
├── config/ # All files here are OPTIONAL
└── specs/
└── <plugin>.spec.ts # Main test specification2
3
4
5
6
7
8
9
10
11
12
13
Configuration Files Are Optional
The tests/config/ directory can be empty. Configuration is auto-generated from plugin metadata. See Configuration Files for when to create specific files.
Root Files
package.json
Defines the test package with dependencies and scripts:
{
"name": "<plugin>-e2e-tests",
"version": "1.0.0",
"private": true,
"type": "module",
"engines": {
"node": ">=22",
"yarn": ">=3"
},
"packageManager": "yarn@4.12.0",
"scripts": {
"test": "playwright test",
"test:vault": "VAULT=1 playwright test",
"report": "playwright show-report",
"test:ui": "playwright test --ui",
"test:headed": "playwright test --headed",
"lint:check": "eslint .",
"lint:fix": "eslint . --fix",
"prettier:check": "prettier --check .",
"prettier:fix": "prettier --write .",
"tsc:check": "tsc --noEmit",
"check": "yarn tsc:check && yarn lint:check && yarn prettier:check"
},
"devDependencies": {
"@eslint/js": "10.0.1",
"@playwright/test": "1.59.1",
"@red-hat-developer-hub/e2e-test-utils": "1.1.33",
"@types/node": "25.5.2",
"eslint": "10.2.0",
"eslint-plugin-check-file": "3.3.1",
"eslint-plugin-playwright": "2.10.1",
"prettier": "3.8.1",
"typescript": "6.0.2",
"typescript-eslint": "8.58.1"
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
playwright.config.ts
Extends the base configuration from @red-hat-developer-hub/e2e-test-utils:
import { defineConfig } from "@red-hat-developer-hub/e2e-test-utils/playwright-config";
export default defineConfig({
projects: [
{
name: "<plugin>",
},
],
});2
3
4
5
6
7
8
9
tsconfig.json
Extends TypeScript configuration from the package:
{
"extends": "@red-hat-developer-hub/e2e-test-utils/tsconfig",
"include": ["**/*.ts"]
}2
3
4
eslint.config.js
Uses the ESLint configuration factory:
import { createEslintConfig } from "@red-hat-developer-hub/e2e-test-utils/eslint";
export default createEslintConfig(import.meta.dirname);2
3
.yarnrc.yml
Configures Yarn to use node_modules (required for compatibility):
nodeLinker: node-modules.env
Optional file for environment variables. Can contain:
# Cluster configuration (usually set in CI)
# RHDH_VERSION=1.5
# INSTALLATION_METHOD=helm
# Plugin-specific variables
# MY_PLUGIN_API_KEY=xxx2
3
4
5
6
tests/config/ Directory
Contains YAML configuration files that are merged with defaults when deploying RHDH.
All Files Are Optional
All configuration files in this directory are optional. The package provides sensible defaults. Only create files when you need to override or extend defaults.
| File | Purpose | When to Create |
|---|---|---|
app-config-rhdh.yaml | RHDH configuration | Plugin-specific settings needed |
rhdh-secrets.yaml | Kubernetes secrets | Using env vars in RHDH configs |
dynamic-plugins.yaml | Plugin configuration | Usually not needed - auto-generated |
value_file.yaml | Helm values | Override Helm defaults |
subscription.yaml | Operator config | Override Operator defaults |
See Configuration Files for complete details on each file.
tests/specs/ Directory
Contains test specification files and optional deployment scripts.
<plugin>.spec.ts
Main test file using Playwright and @red-hat-developer-hub/e2e-test-utils fixtures:
import { test, expect } from "@red-hat-developer-hub/e2e-test-utils/test";
test.describe("Test <plugin>", () => {
test.beforeAll(async ({ rhdh }) => {
await rhdh.configure({ auth: "keycloak" });
await rhdh.deploy();
});
test.beforeEach(async ({ loginHelper }) => {
await loginHelper.loginAsKeycloakUser();
});
test("Verify functionality", async ({ uiHelper }) => {
// Test implementation
});
});2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
deploy-*.sh (Optional)
Bash scripts for deploying external services:
#!/bin/bash
set -e
deploy_external_service() {
local project=$1
echo "Deploying service in namespace ${project}"
# Deployment logic
}
deploy_external_service "$1"2
3
4
5
6
7
8
9
10
File Naming Conventions
| File Type | Convention | Example |
|---|---|---|
| Spec files | <plugin-name>.spec.ts | tech-radar.spec.ts |
| Deployment scripts | deploy-<service>.sh | deploy-customization-provider.sh |
| Config files | Standard names | app-config-rhdh.yaml |
Path Resolution (WorkspacePaths)
Tests in this repo can run from two different working directories:
| Context | CWD | How |
|---|---|---|
| Individual workspace | workspaces/<plugin>/e2e-tests/ | cd workspaces/tech-radar/e2e-tests && yarn test |
| Repo root (unified runner) | Repository root | ./run-e2e.sh -w tech-radar |
Configuration files live under tests/config/ relative to each workspace's e2e-tests/ directory. If paths were resolved from process.cwd(), they would break when running from the repo root.
How It Works
The WorkspacePaths utility resolves all config file paths from Playwright's test.info().project.testDir — an absolute path set by Playwright itself — instead of relying on CWD. This makes path resolution correct regardless of where the process was launched.
test.info().project.testDir
→ /abs/path/workspaces/tech-radar/e2e-tests/tests
→ e2eRoot: /abs/path/workspaces/tech-radar/e2e-tests
→ configDir: /abs/path/workspaces/tech-radar/e2e-tests/tests/config
→ appConfig: /abs/path/workspaces/tech-radar/e2e-tests/tests/config/app-config-rhdh.yaml
→ metadataDir: /abs/path/workspaces/tech-radar/metadata2
3
4
5
6
Complementary CWD Fix
The worker fixture also sets process.chdir(e2eRoot) and $.cwd = e2eRoot when the test worker starts. This ensures that any code using relative paths (e.g., shell scripts, fs.readFileSync) also resolves correctly. WorkspacePaths handles the framework-level paths; the CWD change covers everything else.
No Action Required
WorkspacePaths is used internally by RHDHDeployment. You don't need to use it directly unless you're resolving custom file paths in your test setup. See WorkspacePaths API for available properties.
Related Pages
- Configuration Files - Detailed YAML configuration
- Spec Files - Writing test specifications
- Pre-requisite Services - Deploy dependencies before RHDH
- Unified Test Runner - Running tests from repo root