Files
fce9bd8f96 Agent tooling relocation, architecture redesign docs (#3343)
* add export for address txs

* transfer all export from page to dialog

* remove old route and components

* improve file name and fix loading state of icon button

* basic implementation

* refetch item status

* status indicator for download items

* changes for multichain

* handle too many requests for downloads error

* update button styles and spacing

* fix tests

* disable async export for multichain

* Fix CSV export cancel flow and stabilize context updates

Applied via @cursor push command

* test and review fixes

* move file to client folder

* round 3

* add glossary

* migration tasks and skill

* move skills to .agents folder

* rename migrate skill

* refine project rules

* move MIGRATION_TASKS.md to client directory

* update sym links

* refine migration skills

* fixes after merging the main branch

---------

Co-authored-by: Hanzo Dev <[email protected]>
2026-03-02 16:42:12 +02:00

190 lines
6.2 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
description: Playwright component visual tests — purpose, setup, fixtures, and conventions
globs: "*.pw.tsx"
alwaysApply: false
---
# Visual Component Tests (Playwright)
## Purpose
Playwright tests verify the visual presentation and interactive behavior of UI components across multiple viewports and color modes. Use them when a change affects what the user sees — layout, styling, conditional UI states.
## File naming and location
Test files must be named `*.pw.tsx` and placed alongside the component they test. Run all tests:
```bash
pnpm test:pw # locally (fast, no Docker)
pnpm test:pw:docker # in Docker (required for screenshot updates)
pnpm test:pw:docker path/to/Component.pw.ts --update-snapshots # Run single file in Docker and update all corresponding screenshots
```
**Never commit screenshots generated by `pnpm test:pw` (local).** Screenshots used in CI must be generated via `pnpm test:pw:docker`, otherwise tests will fail in CI due to rendering differences.
## Test projects
Three projects run against every test file:
| Project | Tag | Browser | Viewport |
|---|---|---|---|
| `default` | _(runs unless excluded with `-@default`)_ | Desktop Chrome | 1200×750 |
| `mobile` | `+@mobile` | iPhone 13 Pro (Safari) | 375×812 |
| `dark-color-mode` | `+@dark-mode` | Desktop Chrome | 1200×750, forced dark |
Tag a test to include or exclude it from a project:
```tsx
test('renders correctly +@mobile', async ({ render }) => { ... });
test('mobile only -@default +@mobile', async ({ render }) => { ... });
test('dark mode variant +@dark-mode', async ({ render }) => { ... });
```
## Imports
**Never import directly from `@playwright/experimental-ct-react`.** Use the project's extended test:
```tsx
import { test, expect } from 'playwright/index';
```
`playwright/index.ts` extends Playwright's `test` with all project fixtures and re-exports everything from `@playwright/experimental-ct-react`.
## Component mounting
Use the `render` fixture — it mounts the component inside `TestApp`, which provides the full provider stack: ChakraProvider, QueryClientProvider, SocketProvider, AppContextProvider, SettingsContextProvider, GrowthBookProvider, WagmiProvider, RewardsContextProvider, and CsvExportContextProvider.
```tsx
test('example', async ({ render }) => {
const component = await render(<MyComponent prop="value" />);
await expect(component).toHaveScreenshot();
});
```
`render` accepts optional second and third arguments to customize `hooksConfig` (mainly used for mocking Next.js router object), `appContext` and `marketplaceContext` props passed to `TestApp`.
## Fixtures
All fixtures are injected via the `test` function. Available fixtures:
### `mockApiResponse`
Intercepts Blockscout API calls. Returns the mocked URL.
```tsx
await mockApiResponse('token', tokenMock, {
pathParams: { hash: '0x...' },
queryParams: { tab: 'holders' },
status: 200, // optional, default 200
times: 1, // optional, intercept N times
});
```
### `mockEnvs`
Sets environment variables for the test (stored in localStorage, read by `getEnvValue`). Use the built-in `ENVS_MAP` for common configs:
```tsx
await mockEnvs([
['NEXT_PUBLIC_ROLLUP_TYPE', 'optimistic'],
['NEXT_PUBLIC_API_HOST', 'localhost'],
]);
```
### `mockFeatures`
Sets feature flags in localStorage:
```tsx
await mockFeatures([
['account', true],
['rewards', false],
]);
```
### `mockAssetResponse`
Routes any URL to serve a file from disk:
```tsx
await mockAssetResponse('https://example.com/logo.png', './playwright/mocks/duck.png');
```
### `mockConfigResponse`
Routes an external config asset URL (JSON or image) derived from an env var name:
```tsx
await mockConfigResponse('NEXT_PUBLIC_MARKETPLACE_CONFIG_URL', 'https://example.com/config.json', content);
```
### `mockRpcResponse`
Mocks RPC calls (typed against viem's `PublicRpcSchema`):
```tsx
await mockRpcResponse([{ method: 'eth_blockNumber', result: '0x1' }]);
```
### `mockContractReadResponse`
Mocks `eth_call` for a specific contract read:
```tsx
await mockContractReadResponse({
abiItem: erc20ABI[0],
args: ['0x123'],
address: '0x00ab',
result: '1000000',
});
```
### `createSocket`
Creates a local WebSocket server on port 3200. Resolves when a client connects:
```tsx
const socket = await createSocket();
// push events via socket
```
### `mockTextAd`
Mocks the text ad provider (Sevio + duck ad data). Call this in tests that render ad-containing layouts to avoid network requests and visual noise.
### `injectMetaMaskProvider`
Injects `window.ethereum` with `isMetaMask: true`:
```tsx
await injectMetaMaskProvider();
```
### `auth` helpers
For tests requiring an authenticated user, use the `contextWithAuth` fixture or call `authenticateUser(context)` to set the API token cookie.
### `mockMultichainConfig`
Injects `window.__multichainConfig` with 5 mock chains (chainA–E). Use in tests that render multichain UI.
## Selectors
Always use semantic selectors — never CSS class names. CSS classes are implementation details and break when styling changes.
```tsx
// BAD
page.locator('.tx-hash-link')
// GOOD
page.getByRole('link', { name: /transaction/i })
page.getByLabel('Address menu')
page.getByText('0x1234…')
page.getByTestId('tx-hash')
```
## Environment and date
`playwright/lib.tsx` runs before every component mount and:
- Mocks `next/router.useRouter()` with a configurable router object.
- Fixes the current date to `2022-11-11T12:00:00Z` via MockDate — all `new Date()` / `Date.now()` calls return this value.
## Mock data
Use existing files from `mocks/` and `playwright/mocks/` rather than hardcoding values inline. The `mocks/` directory contains shared mock data (API responses, entities) used across both Vitest and Playwright tests. `playwright/mocks/` contains Playwright-specific assets (images, JSON files, module mocks).
Extract any non-obvious test values (IDs, amounts, hashes) into named constants above the test suite.
## Conventions
- Do not use the `testFn: TestFixture<...>` pattern. It makes refactoring harder and can bypass Playwright lint rules. Use it only when genuinely sharing fixture logic across multiple suites.
- Keep each test focused on one visual state or interaction.
- Screenshots are the contract — keep them up to date and review diffs carefully in PRs.