> ## Documentation Index
> Fetch the complete documentation index at: https://onchaintestkit.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Writing Tests

> Learn how to write comprehensive blockchain tests with OnchainTestKit

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.

## Available Fixtures

OnchainTestKit provides several fixtures for your tests:

<Info>
  Fixtures are automatically injected into your test functions and handle setup/teardown.
</Info>

| Fixture                | Type                   | Description                                   |
| ---------------------- | ---------------------- | --------------------------------------------- |
| `page`                 | `Page`                 | Playwright page object for browser automation |
| `metamask`             | `MetaMask`             | MetaMask wallet automation interface          |
| `coinbase`             | `CoinbaseWallet`       | Coinbase wallet automation interface          |
| `node`                 | `LocalNodeManager`     | Local blockchain node manager                 |
| `smartContractManager` | `SmartContractManager` | Smart contract deployment and interaction     |

## Basic Wallet Operations

### Connecting a Wallet

<Tabs>
  <Tab title="MetaMask">
    ```typescript theme={null}
    test("connect MetaMask", async ({ page, metamask }) => {
      if (!metamask) throw new Error("MetaMask not initialized")

      // Open wallet connect modal
      await page.getByTestId("ockConnectButton").first().click()

      // Select MetaMask from wallet options
      await page
        .getByTestId("ockModalOverlay")
        .first()
        .getByRole("button", { name: "MetaMask" })
        .click()

      // Handle MetaMask connection request
      await metamask.handleAction(BaseActionType.CONNECT_TO_DAPP)
    })
    ```
  </Tab>

  <Tab title="Coinbase Wallet">
    ```typescript theme={null}
    test("connect Coinbase Wallet", async ({ page, coinbase }) => {
      if (!coinbase) throw new Error("Coinbase not initialized")

      // Open wallet connect modal
      await page.getByTestId("ockConnectButton").first().click()

      // Select Coinbase from wallet options
      await page
        .getByTestId("ockModalOverlay")
        .first()
        .getByRole("button", { name: "Coinbase" })
        .click()

      // Handle Coinbase connection request
      await coinbase.handleAction(BaseActionType.CONNECT_TO_DAPP)
    })
    ```
  </Tab>
</Tabs>

### Network Switching

```typescript theme={null}
test("switch networks", async ({ page, metamask }) => {
  // Connect wallet first
  await connectWallet(page, metamask)

  // Switch to Base Sepolia
  await page.getByTestId("switch-to-base-sepolia").click()
  
  // Handle network switch in wallet
  await metamask.handleAction(BaseActionType.SWITCH_NETWORK)
})
```

## Transaction Testing

### Basic Transaction

```typescript theme={null}
test("send transaction", async ({ page, metamask }) => {
  // Connect wallet
  await connectWallet(page, metamask)

  // Ideally, you have some purchase button
  
  // Submit transaction
  await page.getByTestId("purchase-button").click()

  // Approve transaction in wallet
  await metamask.handleAction(BaseActionType.HANDLE_TRANSACTION, {
    approvalType: ActionApprovalType.APPROVE,
  })

  // Wait for confirmation
  await expect(page.getByText("Transaction confirmed!")).toBeVisible()
})
```

### Rejecting Transactions

```typescript theme={null}
test("reject transaction", async ({ page, metamask }) => {
  await connectWallet(page, metamask)

  // Trigger transaction
  await page.getByTestId("purchase-button").click()

  // Reject in wallet
  await metamask.handleAction(BaseActionType.HANDLE_TRANSACTION, {
    approvalType: ActionApprovalType.REJECT,
  })

  // Verify rejection handled
  await expect(page.getByText("Transaction rejected")).toBeVisible()
})
```

## Advanced Testing Patterns

### Parallel Test Execution

```typescript theme={null}
test.describe.parallel("Parallel tests", () => {
  test("test 1", async ({ page, metamask, node }) => {
    console.log(`Test 1 using port: ${node?.port}`)
    // Each test gets its own isolated node
  })

  test("test 2", async ({ page, metamask, node }) => {
    console.log(`Test 2 using port: ${node?.port}`)
    // Different port, isolated environment
  })
})
```

## Best Practices

<Steps>
  <Step title="Wait for state changes">
    Always wait for UI updates after wallet actions:

    ```typescript theme={null}
    // Good
    await metamask.handleAction(BaseActionType.CONNECT_TO_DAPP)
    await page.waitForSelector('[data-testid="wallet-connected"]')

    // Bad - might be flaky
    await metamask.handleAction(BaseActionType.CONNECT_TO_DAPP)
    expect(page.getByText("Connected")).toBeVisible() // Might fail
    ```
  </Step>

  <Step title="Handle errors gracefully">
    Always include error scenarios in your tests:

    ```typescript theme={null}
    test("handle wallet rejection", async ({ page, metamask }) => {
      try {
        await metamask.handleAction(BaseActionType.CONNECT_TO_DAPP, {
          approvalType: ActionApprovalType.REJECT,
        })
      } catch (error) {
        // Verify error is handled in UI
        await expect(page.getByText("Connection rejected")).toBeVisible()
      }
    })
    ```
  </Step>
</Steps>

## Debugging Tests

### Visual Debugging

```bash theme={null}
# Run tests in headed mode
yarn playwright test --headed

# Use Playwright Inspector
yarn playwright test --debug

# Slow down execution
yarn playwright test --slow-mo=1000
```

### Console Logs

```typescript theme={null}
test("debug test", async ({ page, metamask }) => {
  // Log page errors
  page.on('pageerror', error => {
    console.error('Page error:', error)
  })

  // Log console messages
  page.on('console', msg => {
    console.log('Console:', msg.text())
  })

  // Your test code
})
```

## Next Steps

* [Test smart contracts](/onchaintestkit/smart-contracts)
* [See complete examples](/onchaintestkit/examples)
* [Set up CI/CD](/onchaintestkit/ci-cd)
