Uniswap / web-e2e
Install for your project team
Run this command in your project directory to install the skill for your entire team:
mkdir -p .claude/skills/web-e2e && curl -o .claude/skills/web-e2e/SKILL.md https://fastmcp.me/Skills/DownloadRaw?id=155
Project Skills
This skill will be saved in .claude/skills/web-e2e/ and checked into git. All team members will have access to it automatically.
Important: Please verify the skill by reviewing its instructions before using it.
Run, create, and debug Playwright e2e tests for the web app. ALWAYS invoke this skill using the SlashCommand tool (i.e., `/web-e2e`) BEFORE attempting to run any e2e tests, playwright tests, anvil tests, or debug test failures. DO NOT run `bun playwright test` or other e2e commands directly - you must invoke this skill first to learn the correct commands and test architecture.
1 views
0 installs
Skill Content
---
name: web-e2e
description: Run, create, and debug Playwright e2e tests for the web app. ALWAYS invoke this skill using the SlashCommand tool (i.e., `/web-e2e`) BEFORE attempting to run any e2e tests, playwright tests, anvil tests, or debug test failures. DO NOT run `bun playwright test` or other e2e commands directly - you must invoke this skill first to learn the correct commands and test architecture.
allowed-tools: [Read, Write, Edit, Bash, Glob, Grep, mcp__playwright__browser_navigate, mcp__playwright__browser_snapshot, mcp__playwright__browser_click, mcp__playwright__browser_type, mcp__playwright__browser_take_screenshot, mcp__playwright__browser_console_messages, mcp__playwright__browser_network_requests, mcp__playwright__browser_evaluate]
---
# Web E2E Testing Skill
This skill helps you create and run end-to-end (e2e) Playwright tests for the Uniswap web application.
## Test Architecture
### Test Location
- All e2e tests live in `apps/web/src/` directory structure
- Test files use the naming convention: `*.e2e.test.ts`
- Anvil-specific tests (requiring local blockchain): `*.anvil.e2e.test.ts`
### Automatic Wallet Connection
**Important**: When running Playwright tests, the app automatically connects to a test wallet:
- **Address**: `0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266` (constant: `TEST_WALLET_ADDRESS`)
- **Display name**: `test0` (the Unitag associated with this address)
- **Connection**: Happens automatically via `wagmiAutoConnect.ts` when in Playwright environment
This means:
- Tests start with a wallet already connected
- You can immediately test wallet-dependent features
- The wallet button will show "test0" instead of "Connect wallet"
**When using Playwright MCP**: To enable automatic wallet connection when browsing via MCP tools, set the environment variable `REACT_APP_IS_PLAYWRIGHT_ENV=true` before starting the dev server. This makes the app behave identically to how it does in automated tests, with the test wallet auto-connected.
### Custom Fixtures
The web app uses custom Playwright fixtures and mocks that extend base Playwright functionality.
They are located in `apps/web/src/playwright/fixtures/*` and `apps/web/src/playwright/mocks/*`.
#### Import Pattern
```typescript
import { expect, getTest } from 'playwright/fixtures'
// For regular tests (no blockchain)
const test = getTest()
// For anvil tests (with blockchain)
const test = getTest({ withAnvil: true })
```
#### Available Fixtures
1. **graphql** - Mock GraphQL responses
```typescript
await graphql.intercept('OperationName', Mocks.Path.to_mock)
await graphql.waitForResponse('OperationName')
```
2. **anvil** - Local blockchain client (only in anvil tests)
```typescript
// Set token balances
await anvil.setErc20Balance({ address, balance })
// Check balances
await anvil.getBalance({ address })
await anvil.getErc20Balance(tokenAddress, ownerAddress)
// Manage allowances
await anvil.setErc20Allowance({ address, spender, amount })
await anvil.setPermit2Allowance({ token, spender, amount })
// Mining blocks
await anvil.mine({ blocks: 1 })
// Snapshots for isolation
const snapshotId = await anvil.takeSnapshot()
await anvil.revertToSnapshot(snapshotId)
```
3. **tradingApi** - Mock Trading API responses
```typescript
await stubTradingApiEndpoint({
page,
endpoint: uniswapUrls.tradingApiPaths.swap
})
```
4. **amplitude** - Analytics mocking (automatic)
### Test Structure
```typescript
import { expect, getTest } from 'playwright/fixtures'
import { TestID } from 'uniswap/src/test/fixtures/testIDs'
const test = getTest({ withAnvil: true }) // or getTest() for non-anvil
test.describe('Feature Name', () => {
test.beforeEach(async ({ page }) => {
// Setup before each test
})
test('should do something', async ({ page, anvil, graphql }) => {
// Setup mocks
await graphql.intercept('Operation', Mocks.Path.mock)
// Setup blockchain state (if anvil test)
await anvil.setErc20Balance({ address, balance })
// Navigate to page
await page.goto('/path')
// Interact with UI using TestIDs
await page.getByTestId(TestID.SomeButton).click()
// Make assertions
await expect(page.getByText('Expected Text')).toBeVisible()
})
})
```
### Best Practices
1. **Use TestIDs** - Always use the TestID enum for selectors (not string literals)
```typescript
// Good
await page.getByTestId(TestID.ReviewSwap)
// Bad
await page.getByTestId('review-swap')
```
2. **Mock External Services** - Use fixtures to mock GraphQL, Trading API, REST API etc.
```typescript
await graphql.intercept('PortfolioBalances', Mocks.PortfolioBalances.test_wallet)
await stubTradingApiEndpoint({ page, endpoint: uniswapUrls.tradingApiPaths.quote })
```
3. **Use Mocks Helper** - Import mock paths from `playwright/mocks/mocks.ts`
```typescript
import { Mocks } from 'playwright/mocks/mocks'
await graphql.intercept('Token', Mocks.Token.uni_token)
```
4. **Test Constants** - Use constants from the codebase
```typescript
import { USDT, DAI } from 'uniswap/src/constants/tokens'
import { TEST_WALLET_ADDRESS } from 'playwright/fixtures/wallets'
// TEST_WALLET_ADDRESS is the automatically connected wallet
// It displays as "test0" in the UI
```
5. **Anvil State Management** - Set up blockchain state properly
```typescript
// Always set token balances before testing swaps
await anvil.setErc20Balance({
address: assume0xAddress(USDT.address),
balance: 100_000_000n
})
```
## Running Tests
The following commands must be run from the `apps/web/` folder.
**⚠️ PREREQUISITE**: Playwright tests require the Vite preview server to be running at `http://localhost:3000` BEFORE tests start. The `bun e2e` commands handle this automatically, but if running tests directly you must start the server first.
### Development Commands
The `e2e` commands handle all requisite setup tasks for the playwright tests. These include building the app for production and running the Vite preview server.
```bash
# Run all e2e tests (starts anvil, builds, and runs tests)
bun e2e
# Run only non-anvil tests (faster, no blockchain required)
bun e2e:no-anvil
# Run only anvil tests (blockchain tests only)
bun e2e:anvil
# Run specific test file
bun e2e TokenSelector.e2e.test
```
### Direct Playwright Commands
In some cases it may be helpful to run the commands more directly with the different tasks in different terminals.
```bash
# Step 1: Build the web app for e2e
bun build:e2e
# Step 2: Start the Vite preview server (REQUIRED - must be running before tests)
bun preview:e2e
# Wait for "Local: http://localhost:3000" message
# (Optional) Step 3: Start Anvil (note, Anvil tests can start this themselves)
bun anvil:mainnet
# Wait for "Listening on 127.0.0.1:8545" message
# Step 4: Run the playwright tests (only after servers are ready)
bun playwright:test
```
### Test Modes
```bash
# Headed mode (see browser)
bun playwright test --headed
# Debug mode with Playwright Inspector
bun playwright test --debug
# UI mode (interactive)
bun playwright test --ui
```
## Configuration
### Playwright Config (`playwright.config.ts`)
Key settings:
- `testDir`: `./src`
- `testMatch`: `**/*.e2e.test.ts`
- `workers`: 1 (configured in CI)
- `fullyParallel`: false
- `baseURL`: `http://localhost:3000`
## Common Patterns
### Navigation and URL Testing
```typescript
await page.goto('/swap?inputCurrency=ETH&outputCurrency=USDT')
await expect(page.getByTestId(TestID.ChooseInputToken + '-label')).toHaveText('ETH')
```
### Form Interactions
```typescript
await page.getByTestId(TestID.AmountInputIn).fill('0.01')
await page.getByTestId(TestID.AmountInputIn).clear()
```
### Token Selection
```typescript
await page.getByTestId(TestID.ChooseOutputToken).click()
await page.getByTestId('token-option-1-USDT').first().click()
```
### Waiting for Transaction Completion
```typescript
await page.getByTestId(TestID.Swap).click()
await expect(page.getByText('Swapped')).toBeVisible()
```
### Blockchain Verification
```typescript
const balance = await anvil.getBalance({ address: TEST_WALLET_ADDRESS })
await expect(balance).toBeLessThan(parseEther('10000'))
```
## Troubleshooting
### Tests Timeout
- Check if Anvil is running: `bun anvil:mainnet`
- Ensure preview server is running: `bun preview:e2e`
### Anvil Issues
- Tests automatically manage Anvil snapshots for isolation
- Anvil restarts automatically if unhealthy
- For manual restart: stop the e2e command and run again
### Mock Not Working
- Ensure mock path is correct in `Mocks` object
- Check GraphQL operation name matches exactly
- Verify timing - intercept before the request is made
### Test Flakiness
- Use proper waiting: `await expect(element).toBeVisible()`
- Don't use fixed `setTimeout` - use Playwright's auto-waiting
- Check for race conditions with network requests
### Debugging
- Run tests with `--headed` flag to watch the browser
- Use `--debug` flag to step through with Playwright Inspector
- Add `await page.pause()` in your test to stop at a specific point
- Check test output and error messages carefully
- Review screenshots/videos in `test-results/` directory after failures
## Playwright Documentation References
For more details on Playwright features, refer to:
- **[Writing Tests](https://playwright.dev/docs/writing-tests)** - Test structure, actions, assertions
- **[Test Fixtures](https://playwright.dev/docs/test-fixtures)** - Creating custom fixtures (like our anvil/graphql fixtures)
- **[Running Tests](https://playwright.dev/docs/running-tests)** - Command line options, filtering, debugging
- **[API Testing](https://playwright.dev/docs/api-testing)** - Mocking and intercepting network requests
- **[Locators](https://playwright.dev/docs/locators)** - Finding elements (we use `getByTestId` primarily)
- **[Assertions](https://playwright.dev/docs/test-assertions)** - Available expect matchers
- **[Test Hooks](https://playwright.dev/docs/api/class-test#test-before-each)** - beforeEach, afterEach, beforeAll, afterAll
- **[Test Configuration](https://playwright.dev/docs/test-configuration)** - playwright.config.ts options
- **[Debugging Tests](https://playwright.dev/docs/debug)** - UI mode, inspector, trace viewer
## Playwright MCP Integration (Optional but Recommended)
The Playwright MCP (Model Context Protocol) provides browser automation capabilities that make test development and debugging easier:
- **Interactive debugging** - Navigate the app in a real browser to understand behavior
- **Creating tests** - Explore the UI to identify selectors and interactions
- **Debugging failures** - Inspect page state when tests fail
### Installing Playwright MCP
If you don't have the Playwright MCP installed, you can add it to your Claude Code configuration:
1. Open Claude Code settings (Command/Ctrl + Shift + P → "Claude Code: Open Settings")
2. Add the Playwright MCP to your `mcpServers` configuration:
```json
{
"mcpServers": {
"playwright": {
"command": "npx",
"args": ["-y", "@executeautomation/playwright-mcp-server"]
}
}
}
```
3. Restart Claude Code
Alternatively, follow the installation guide at: https://github.com/executeautomation/playwright-mcp
### Using Playwright MCP for Test Development (Optional)
**If you have the MCP installed**, you can use these tools during development:
1. **Navigate and explore** - Use `mcp__playwright__browser_navigate` to visit pages
2. **Take snapshots** - Use `mcp__playwright__browser_snapshot` to see the page structure and find TestIDs
3. **Interact with elements** - Use `mcp__playwright__browser_click` and `mcp__playwright__browser_type` to test interactions
4. **Inspect state** - Use `mcp__playwright__browser_console_messages` and `mcp__playwright__browser_network_requests` to debug
5. **Take screenshots** - Use `mcp__playwright__browser_take_screenshot` to visualize issues
## When to Use This Skill
Use this skill when you need to:
- Create new end-to-end tests for web features
- Debug or fix failing e2e tests
- Run e2e tests during development
- Understand the e2e testing architecture
- Set up test fixtures or mocks
- Work with Anvil blockchain state in tests