| 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
import { expect, getTest } from 'playwright/fixtures'
const test = getTest()
const test = getTest({ withAnvil: true })
Available Fixtures
-
graphql - Mock GraphQL responses
await graphql.intercept('OperationName', Mocks.Path.to_mock)
await graphql.waitForResponse('OperationName')
-
anvil - Local blockchain client (only in anvil tests)
await anvil.setErc20Balance({ address, balance })
await anvil.getBalance({ address })
await anvil.getErc20Balance(tokenAddress, ownerAddress)
await anvil.setErc20Allowance({ address, spender, amount })
await anvil.setPermit2Allowance({ token, spender, amount })
await anvil.mine({ blocks: 1 })
const snapshotId = await anvil.takeSnapshot()
await anvil.revertToSnapshot(snapshotId)
-
tradingApi - Mock Trading API responses
await stubTradingApiEndpoint({
page,
endpoint: uniswapUrls.tradingApiPaths.swap
})
-
amplitude - Analytics mocking (automatic)
Test Structure
import { expect, getTest } from 'playwright/fixtures'
import { TestID } from 'uniswap/src/test/fixtures/testIDs'
const test = getTest({ withAnvil: true })
test.describe('Feature Name', () => {
test.beforeEach(async ({ page }) => {
})
test('should do something', async ({ page, anvil, graphql }) => {
await graphql.intercept('Operation', Mocks.Path.mock)
await anvil.setErc20Balance({ address, balance })
await page.goto('/path')
await page.getByTestId(TestID.SomeButton).click()
await expect(page.getByText('Expected Text')).toBeVisible()
})
})
Best Practices
-
Use TestIDs - Always use the TestID enum for selectors (not string literals)
await page.getByTestId(TestID.ReviewSwap)
await page.getByTestId('review-swap')
-
Mock External Services - Use fixtures to mock GraphQL, Trading API, REST API etc.
await graphql.intercept('PortfolioBalances', Mocks.PortfolioBalances.test_wallet)
await stubTradingApiEndpoint({ page, endpoint: uniswapUrls.tradingApiPaths.quote })
-
Use Mocks Helper - Import mock paths from playwright/mocks/mocks.ts
import { Mocks } from 'playwright/mocks/mocks'
await graphql.intercept('Token', Mocks.Token.uni_token)
-
Test Constants - Use constants from the codebase
import { USDT, DAI } from 'uniswap/src/constants/tokens'
import { TEST_WALLET_ADDRESS } from
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.
bun e2e
bun e2e:no-anvil
bun e2e:anvil
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.
bun build:e2e
bun preview:e2e
bun anvil:mainnet
bun playwright:test
Test Modes
bun playwright test --headed
bun playwright test --debug
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
await page.goto('/swap?inputCurrency=ETH&outputCurrency=USDT')
await expect(page.getByTestId(TestID.ChooseInputToken + '-label')).toHaveText('ETH')
Form Interactions
await page.getByTestId(TestID.AmountInputIn).fill('0.01')
await page.getByTestId(TestID.AmountInputIn).clear()
Token Selection
await page.getByTestId(TestID.ChooseOutputToken).click()
await page.getByTestId('token-option-1-USDT').first().click()
Waiting for Transaction Completion
await page.getByTestId(TestID.Swap).click()
await expect(page.getByText('Swapped')).toBeVisible()
Blockchain Verification
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:
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:
- Open Claude Code settings (Command/Ctrl + Shift + P → "Claude Code: Open Settings")
- Add the Playwright MCP to your
mcpServers configuration:
{
"mcpServers": {
"playwright": {
"command": "npx",
"args": ["-y", "@executeautomation/playwright-mcp-server"]
}
}
}
- 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:
- Navigate and explore - Use
mcp__playwright__browser_navigate to visit pages
- Take snapshots - Use
mcp__playwright__browser_snapshot to see the page structure and find TestIDs
- Interact with elements - Use
mcp__playwright__browser_click and mcp__playwright__browser_type to test interactions
- Inspect state - Use
mcp__playwright__browser_console_messages and mcp__playwright__browser_network_requests to debug
- 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