Skip to content

Commit d53c836

Browse files
committed
OCTK docs
1 parent 63a2f92 commit d53c836

File tree

6 files changed

+422
-4
lines changed

6 files changed

+422
-4
lines changed

docs/base-chain/tools/base-products.mdx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ title: "Base Products"
2323
<Card title="Paymaster" icon="square-6" href="https://docs.cdp.coinbase.com/paymaster/introduction/welcome">
2424
Account Abstraction endpoints to send transactions and sponsor gas.
2525
</Card>
26+
<Card title="OnchainTestKit" icon="square-7" href="https://docs.base.org/onchainkit/guides/testing-with-onchaintestkit">
27+
End-to-end testing framework for blockchain applications.
28+
</Card>
2629
</CardGroup>
2730

2831
import PolicyBanner from "/snippets/PolicyBanner.mdx";
Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
---
2+
title: "Writing Tests"
3+
description: "Learn how to write comprehensive blockchain tests with OnchainTestKit"
4+
---
5+
6+
This guide covers everything you need to know about writing tests with OnchainTestKit, from basic wallet connections to complex transaction scenarios. NOTE that some of these examples may be different from what you implement depending on your frontend code.
7+
8+
## Available Fixtures
9+
10+
OnchainTestKit provides several fixtures for your tests:
11+
12+
<Info>
13+
Fixtures are automatically injected into your test functions and handle setup/teardown.
14+
</Info>
15+
16+
| Fixture | Type | Description |
17+
|---------|------|-------------|
18+
| `page` | `Page` | Playwright page object for browser automation |
19+
| `metamask` | `MetaMask` | MetaMask wallet automation interface |
20+
| `coinbase` | `CoinbaseWallet` | Coinbase wallet automation interface |
21+
| `node` | `LocalNodeManager` | Local blockchain node manager |
22+
| `smartContractManager` | `SmartContractManager` | Smart contract deployment and interaction |
23+
24+
## Basic Wallet Operations
25+
26+
### Connecting a Wallet
27+
28+
<Tabs>
29+
<Tab title="MetaMask">
30+
```typescript
31+
test("connect MetaMask", async ({ page, metamask }) => {
32+
if (!metamask) throw new Error("MetaMask not initialized")
33+
34+
// Open wallet connect modal
35+
await page.getByTestId("ockConnectButton").first().click()
36+
37+
// Select MetaMask from wallet options
38+
await page
39+
.getByTestId("ockModalOverlay")
40+
.first()
41+
.getByRole("button", { name: "MetaMask" })
42+
.click()
43+
44+
// Handle MetaMask connection request
45+
await metamask.handleAction(BaseActionType.CONNECT_TO_DAPP)
46+
})
47+
```
48+
</Tab>
49+
50+
<Tab title="Coinbase Wallet">
51+
```typescript
52+
test("connect Coinbase Wallet", async ({ page, coinbase }) => {
53+
if (!coinbase) throw new Error("Coinbase not initialized")
54+
55+
// Open wallet connect modal
56+
await page.getByTestId("ockConnectButton").first().click()
57+
58+
// Select Coinbase from wallet options
59+
await page
60+
.getByTestId("ockModalOverlay")
61+
.first()
62+
.getByRole("button", { name: "Coinbase" })
63+
.click()
64+
65+
// Handle Coinbase connection request
66+
await coinbase.handleAction(BaseActionType.CONNECT_TO_DAPP)
67+
})
68+
```
69+
</Tab>
70+
</Tabs>
71+
72+
### Network Switching
73+
74+
```typescript
75+
test("switch networks", async ({ page, metamask }) => {
76+
// Connect wallet first
77+
await connectWallet(page, metamask)
78+
79+
// Switch to Base Sepolia
80+
await page.getByTestId("switch-to-base-sepolia").click()
81+
82+
// Handle network switch in wallet
83+
await metamask.handleAction(BaseActionType.SWITCH_NETWORK)
84+
})
85+
```
86+
87+
## Transaction Testing
88+
89+
### Basic Transaction
90+
91+
```typescript
92+
test("send transaction", async ({ page, metamask }) => {
93+
// Connect wallet
94+
await connectWallet(page, metamask)
95+
96+
// Ideally, you have some purchase button
97+
98+
// Submit transaction
99+
await page.getByTestId("purchase-button").click()
100+
101+
// Approve transaction in wallet
102+
await metamask.handleAction(BaseActionType.HANDLE_TRANSACTION, {
103+
approvalType: ActionApprovalType.APPROVE,
104+
})
105+
106+
// Wait for confirmation
107+
await expect(page.getByText("Transaction confirmed!")).toBeVisible()
108+
})
109+
```
110+
111+
### Rejecting Transactions
112+
113+
```typescript
114+
test("reject transaction", async ({ page, metamask }) => {
115+
await connectWallet(page, metamask)
116+
117+
// Trigger transaction
118+
await page.getByTestId("purchase-button").click()
119+
120+
// Reject in wallet
121+
await metamask.handleAction(BaseActionType.HANDLE_TRANSACTION, {
122+
approvalType: ActionApprovalType.REJECT,
123+
})
124+
125+
// Verify rejection handled
126+
await expect(page.getByText("Transaction rejected")).toBeVisible()
127+
})
128+
```
129+
130+
## Advanced Testing Patterns
131+
132+
### Parallel Test Execution
133+
134+
```typescript
135+
test.describe.parallel("Parallel tests", () => {
136+
test("test 1", async ({ page, metamask, node }) => {
137+
console.log(`Test 1 using port: ${node?.port}`)
138+
// Each test gets its own isolated node
139+
})
140+
141+
test("test 2", async ({ page, metamask, node }) => {
142+
console.log(`Test 2 using port: ${node?.port}`)
143+
// Different port, isolated environment
144+
})
145+
})
146+
```
147+
148+
## Best Practices
149+
150+
<Steps>
151+
152+
<Step title="Wait for state changes">
153+
Always wait for UI updates after wallet actions:
154+
155+
```typescript
156+
// Good
157+
await metamask.handleAction(BaseActionType.CONNECT_TO_DAPP)
158+
await page.waitForSelector('[data-testid="wallet-connected"]')
159+
160+
// Bad - might be flaky
161+
await metamask.handleAction(BaseActionType.CONNECT_TO_DAPP)
162+
expect(page.getByText("Connected")).toBeVisible() // Might fail
163+
```
164+
</Step>
165+
166+
<Step title="Handle errors gracefully">
167+
Always include error scenarios in your tests:
168+
169+
```typescript
170+
test("handle wallet rejection", async ({ page, metamask }) => {
171+
try {
172+
await metamask.handleAction(BaseActionType.CONNECT_TO_DAPP, {
173+
approvalType: ActionApprovalType.REJECT,
174+
})
175+
} catch (error) {
176+
// Verify error is handled in UI
177+
await expect(page.getByText("Connection rejected")).toBeVisible()
178+
}
179+
})
180+
```
181+
</Step>
182+
</Steps>
183+
184+
## Debugging Tests
185+
186+
### Visual Debugging
187+
188+
```bash
189+
# Run tests in headed mode
190+
yarn playwright test --headed
191+
192+
# Use Playwright Inspector
193+
yarn playwright test --debug
194+
195+
# Slow down execution
196+
yarn playwright test --slow-mo=1000
197+
```
198+
199+
### Console Logs
200+
201+
```typescript
202+
test("debug test", async ({ page, metamask }) => {
203+
// Log page errors
204+
page.on('pageerror', error => {
205+
console.error('Page error:', error)
206+
})
207+
208+
// Log console messages
209+
page.on('console', msg => {
210+
console.log('Console:', msg.text())
211+
})
212+
213+
// Your test code
214+
})
215+
```
216+
217+
## CI/CD Integration
218+
219+
### GitHub Actions Example
220+
221+
```yaml
222+
name: E2E Tests
223+
224+
on:
225+
push:
226+
branches: [main, develop]
227+
pull_request:
228+
branches: [main]
229+
230+
jobs:
231+
e2e:
232+
runs-on: ubuntu-latest
233+
timeout-minutes: 30
234+
235+
steps:
236+
- name: Checkout code
237+
uses: actions/checkout@v4
238+
239+
- name: Setup Node.js
240+
uses: actions/setup-node@v4
241+
with:
242+
node-version: '18'
243+
cache: 'npm'
244+
245+
- name: Set up Corepack + yarn
246+
run: |
247+
npm install -g corepack
248+
yarn set version 4.9.2
249+
250+
- name: Install root dependencies
251+
run: yarn
252+
253+
- name: Install Foundry
254+
uses: foundry-rs/foundry-toolchain@v1
255+
256+
- name: Build contracts
257+
run: |
258+
cd smart-contracts
259+
forge install foundry-rs/forge-std
260+
forge install OpenZeppelin/openzeppelin-contracts
261+
forge build
262+
263+
- name: Install Playwright browsers
264+
run: yarn playwright install --with-deps
265+
266+
- name: Prepare wallet extensions
267+
run: |
268+
yarn prepare-metamask
269+
yarn prepare-coinbase
270+
271+
- name: Build application
272+
run: |
273+
echo "E2E_TEST_SEED_PHRASE=${{ secrets.E2E_TEST_SEED_PHRASE }}" > .env
274+
echo "E2E_CONTRACT_PROJECT_ROOT=../smart-contracts" >> .env
275+
yarn build
276+
277+
- name: Install xvfb
278+
run: sudo apt-get update && sudo apt-get install -y xvfb
279+
280+
- name: Run E2E tests
281+
env:
282+
NODE_OPTIONS: '--dns-result-order=ipv4first'
283+
run: xvfb-run --auto-servernum --server-args="-screen 0 1920x1080x24" yarn test:e2e
284+
```
285+
286+
## Next Steps
287+
288+
Start testing your onchain application today:
289+
290+
1. Install OnchainTestKit in your project
291+
2. Write your first test following the examples above
292+
3. Integrate tests into your CI/CD pipeline
293+
4. Expand test coverage as you build new features
294+
5. See [example tests](https://github.com/coinbase/onchaintestkit/tree/master/example/frontend/e2e)
295+
6. Access the [full docs here](https://onchaintestkit.xyz/)
296+
297+
Remember: comprehensive testing leads to more reliable onchain applications and better user experiences.

docs/docs.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,8 @@
391391
"onchainkit/guides/themes",
392392
"onchainkit/guides/use-basename-in-onchain-app",
393393
"onchainkit/guides/using-ai-powered-ides",
394-
"onchainkit/guides/ai-prompting-guide"
394+
"onchainkit/guides/ai-prompting-guide",
395+
"onchainkit/guides/testing-with-onchaintestkit"
395396
]
396397
},
397398
{
@@ -648,7 +649,8 @@
648649
"cookbook/deploy-a-chain",
649650
"cookbook/onchain-social",
650651
"cookbook/defi-your-app",
651-
"cookbook/go-gasless"
652+
"cookbook/go-gasless",
653+
"cookbook/testing-onchain-apps"
652654
]
653655
},
654656
{

docs/get-started/products.mdx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: 'Products'
3-
keywords: ['onchainkit', 'minikit', 'agentkit', 'base account', 'appchains', 'paymaster','l3','deploy a chain','smart wallet']
3+
keywords: ['onchainkit', 'minikit', 'agentkit', 'base account', 'appchains', 'paymaster','l3','deploy a chain','smart wallet', 'onchaintestkit', 'testing']
44
---
55

66
<CardGroup cols={2}>
@@ -13,9 +13,12 @@ keywords: ['onchainkit', 'minikit', 'agentkit', 'base account', 'appchains', 'pa
1313
<Card title="Smart Wallet" icon="fingerprint" href="/smart-wallet/quickstart">
1414
A passkey-based universal account to connect with the onchain world.
1515
</Card>
16-
<Card title="Base Appchains" icon="cube" href="https://docs.cdp.coinbase.com/appchains/docs/welcome">
16+
<Card title="Base Appchains" icon="cube" href="https://docs.cdp.coinbase.com/appchains/docs/welcome">
1717
Launch a chain with dedicated blockspace on Base, in minutes.
1818
</Card>
19+
<Card title="OnchainTestKit" icon="flask" href="/onchainkit/guides/testing-with-onchaintestkit">
20+
End-to-end testing framework for blockchain applications.
21+
</Card>
1922
</CardGroup>
2023

2124
import PolicyBanner from "/snippets/PolicyBanner.mdx";

docs/onchainkit/getting-started.mdx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ Add OnchainKit to your existing project manually.
5555

5656
<InstallationOptions />
5757

58+
## Testing Your OnchainKit App
59+
60+
Build reliable applications with comprehensive end-to-end testing using [OnchainTestKit](/onchainkit/guides/testing-with-onchaintestkit). Test wallet connections, transactions, and complex user flows with automated browser testing.
61+
5862
<StartBuilding />
5963

6064
import PolicyBanner from "/snippets/PolicyBanner.mdx";

0 commit comments

Comments
 (0)