test: Backport Claude E2E Skill (#1836)

## Summary



This PR backports the claude E2E skill and a few E2E script improvements to the open source repo from the EE repo.

### Screenshots or video



### How to test locally or on Vercel



### References



- Linear Issue: n/a
- Related PRs:
This commit is contained in:
Drew Davis 2026-03-02 16:01:59 -05:00 committed by GitHub
parent d810eb210e
commit ef2646650e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 85 additions and 34 deletions

View file

@ -0,0 +1,67 @@
---
name: playwright
description: Writes end-to-end tests code using Playwright browser automation.
---
# Playwright End-to-End Test Writer
I am a Playwright End-to-End Test Writer. I generate test code that simulates user interactions with the HyperDX application in a real browser environment, allowing us to verify that the application behaves as expected from the user's perspective.
I will write tests covering these requirements: $ARGUMENTS.
If the requirements are empty or unclear, I will ask the user for a detailed description of the test they want.
## Workflow
1. **Test Description**: The user provides a detailed description of the test they want, including the user interactions, expected outcomes, and any specific scenarios or edge cases to cover.
2. **Test Generation**: I generate test code based on the provided description. This includes setting up the test environment, defining the test steps, and incorporating assertions to validate the expected outcomes.
3. **Test Execution**: The generated test code can be executed using Playwright's test runner, which allows me to verify that the test behaves as expected in a real browser environment.
4. **Iterative Refinement**: If the test does not pass or if there are any issues, I can refine the test code based on feedback and re-run it until it meets the desired criteria.
## Test Execution
To run the generated Playwright tests, I can use the following command from the root of the project:
```bash
./scripts/test-e2e.sh --quiet <test-file-name> [--grep "\"<test name pattern>\""]
```
- Example test file name: `packages/app/tests/e2e/features/<feature>.spec.ts`
- The `--grep` flag can be used to specify a particular test name to run within the test file, allowing for faster execution. Patterns should be wrapped in escaped quotes to ensure they are passed correctly.
The output from the script will indicate the success or failure of the tests, along with any relevant logs or error messages to help diagnose issues.
ALWAYS EXECUTE THE TESTS AFTER GENERATION TO ENSURE THEY WORK AS EXPECTED, BEFORE SUBMITTING THE CODE TO THE USER. Tests should be run in full-stack mode (with backend) by default, no need to ask the user if they would prefer local mode.
## Test File structure
- Specs: `packages/app/tests/e2e/features/`
- Page objects: `packages/app/tests/e2e/page-objects/`
- Components: `packages/app/tests/e2e/components/`
- Utilities: `packages/app/tests/e2e/utils/`
- Base test (extends playwright with fixtures): `utils/base-test.ts`
- Constants (source names): `utils/constants.ts`
## Best Practices
- I will follow general Playwright testing best practices, including:
- Use locators with chaining and filtering to target specific elements, rather than relying on brittle selectors.
- Prefer user-facing attributes to CSS selectors for locating elements
- Use web first assertions (eg. `await expect(page.getByText('welcome')).toBeVisible()` instead of `expect(await page.getByText('welcome').isVisible()).toBe(true)`)
- Never use hardcoded waits (eg. `await page.waitForTimeout(1000)`) - instead, wait for specific elements or conditions to be met.
- I will follow the existing code style and patterns used in the current test suite to ensure consistency and maintainability.
- I will obey `eslint-plugin-playwright` rules, and ensure that all generated code passes linting and formatting checks before submission.
### Page objects
- Tests should interact with the UI through selectors and functions defined in `packages/app/tests/e2e/page-objects`.
- Page objects should refer to UI elements using data-testid if possible. Add data-testid values to existing pages when necessary.
### Mock ClickHouse Data
- E2E tests run against a local docker environment, where backend ClickHouse data is mocked
- Update the `packages/app/tests/e2e/seed-clickhouse.ts` if (and only if) the scenario requires specific data
### Assertions Reference
- **Assert successful chart loads** by checking that `.recharts-responsive-container` is visible.

View file

@ -16,7 +16,6 @@ Instead of stuffing all instructions into `CLAUDE.md` (which goes into every con
- **`tech_stack.md`** - Technology choices, UI component patterns, library usage
- **`development.md`** - Development workflows, testing strategy, common tasks, debugging
- **`code_style.md`** - Code patterns and best practices (read only when actively coding)
- **`e2e.md`** - Patterns and workflows for Playwright end-to-end testing
## Usage Pattern

View file

@ -1,27 +0,0 @@
# Playwright E2E Tests
## File structure
- E2E tests are located in `packages/app/tests/e2e/features`
## Page objects
- Tests should interact with the UI through selectors and functions defined in `packages/app/tests/e2e/page-objects`.
- Page objects should refer to UI elements using data-testid if possible. Add data-testid values to existing pages when necessary.
## Running the tests
To verify that the tests pass:
```sh
./scripts/test-e2e.sh
```
## Mock ClickHouse Data
- E2E tests run against a local docker environment, where backend ClickHouse data is mocked
- Update the `packages/app/tests/e2e/seed-clickhouse.ts` if (and only if) the scenario requires specific data
## Best Practices
- **Assert successful chart loads** by checking that `.recharts-responsive-container` is visible.

View file

@ -3,6 +3,8 @@ import path from 'path';
// Check if we should use full-stack mode (with backend)
const USE_FULLSTACK = process.env.E2E_FULLSTACK === 'true';
// Check if we should use next dev (hot reload) instead of build + start
const USE_DEV = process.env.E2E_USE_DEV === 'true';
const AUTH_FILE = path.join(__dirname, 'tests/e2e/.auth/user.json');
// Timeout configuration constants (in milliseconds)
@ -81,8 +83,10 @@ export default defineConfig({
stderr: 'pipe',
},
{
command:
'SERVER_URL=http://localhost:29000 PORT=28081 yarn build && SERVER_URL=http://localhost:29000 PORT=28081 yarn start',
// Full UI: Alerts + Dashboards. Not local mode; Alerts enabled;
command: USE_DEV
? 'SERVER_URL=http://localhost:29000 PORT=28081 next dev --webpack'
: 'SERVER_URL=http://localhost:29000 PORT=28081 yarn build && SERVER_URL=http://localhost:29000 PORT=28081 yarn start',
port: 28081,
reuseExistingServer: !process.env.CI,
timeout: APP_SERVER_STARTUP_TIMEOUT_MS,
@ -92,8 +96,9 @@ export default defineConfig({
]
: {
// Local mode: Frontend only
command:
'NEXT_PUBLIC_IS_LOCAL_MODE=true yarn build && NEXT_PUBLIC_IS_LOCAL_MODE=true PORT=8081 yarn start',
command: USE_DEV
? 'NEXT_PUBLIC_IS_LOCAL_MODE=true PORT=8081 next dev --webpack'
: 'NEXT_PUBLIC_IS_LOCAL_MODE=true yarn build && NEXT_PUBLIC_IS_LOCAL_MODE=true PORT=8081 yarn start',
port: 8081,
reuseExistingServer: !process.env.CI,
timeout: APP_SERVER_STARTUP_TIMEOUT_MS,

View file

@ -10,6 +10,7 @@
* yarn test:e2e --ui --local # Open UI (local mode)
* yarn test:e2e --debug # Debug mode (full-stack)
* yarn test:e2e --debug --local # Debug (local mode)
* yarn test:e2e --dev # Hot reload (next dev) instead of build+start
*/
import { spawn } from 'child_process';
@ -26,10 +27,11 @@ const args = process.argv.slice(2);
const useLocal = args.includes('--local');
const useUI = args.includes('--ui');
const useDebug = args.includes('--debug');
const useDev = args.includes('--dev');
// Remove our custom flags from args
const playwrightArgs = args.filter(
arg => !['--local', '--ui', '--debug'].includes(arg),
arg => !['--local', '--ui', '--debug', '--dev'].includes(arg),
);
// Build playwright command
@ -55,6 +57,7 @@ playwrightCmd.push(...playwrightArgs);
const env = {
...process.env,
...(!useLocal && { E2E_FULLSTACK: 'true' }),
...(useDev && { E2E_USE_DEV: 'true' }),
};
// Full-stack: inject DEFAULT_CONNECTIONS/DEFAULT_SOURCES from fixture so the API gets them
@ -72,7 +75,7 @@ if (!useLocal) {
// eslint-disable-next-line no-console
console.info(`Running: ${playwrightCmd.join(' ')}`);
// eslint-disable-next-line no-console
console.info(`Mode: ${useLocal ? 'Local (frontend only)' : 'Full-stack'}`);
console.info(`Mode: ${useLocal ? 'Local (frontend only)' : 'Full-stack'}${useDev ? ' + dev (hot reload)' : ''}`);
const child = spawn('npx', playwrightCmd, {
stdio: 'inherit',

View file

@ -179,6 +179,10 @@ test.describe('My Feature', () => {
`@full-stack` so that when running with `./scripts/test-e2e.sh --local`, they
are skipped appropriately.
### Claude Skill
Use the `/playwright <requirements to test>` command in Claude Code to have Claude help write E2E tests. Update `.claude/skills/playwright/SKILL.md` with additional guidance whenever Claude does poorly.
## Test Organization
```