# E2E Tests with Playwright + Synpress: A Developer's Journey > ChainHackers Weekly - Developer Notes Entry #5 **Published by:** [ChainHacker](https://paragraph.com/@chainhacker/) **Published on:** 2025-07-24 **Categories:** betswirl, devtools, e2e, tests, web3 **URL:** https://paragraph.com/@chainhacker/e2e-tests-with-playwright-synpress ## Content So you've decided to dive into end-to-end testing for your Web3 app? Excellent choice! Getting started with e2e testing is straightforward with the right tools, and once you get the hang of it, you'll wonder how you ever lived without it.Why Playwright + Synpress?Before we jump into code, let's talk about why this combo works well. Playwright gives you a solid foundation for browser automation with great debugging tools, while Synpress adds Web3-specific features – MetaMask integration, wallet caching, and transaction handling.Getting Started: The Setup DanceFirst things first, let's get everything installed. It's surprisingly straightforward:npm install @synthetixio/synpressNow, here's where it gets interesting. Your basic test setup looks something like this:import { testWithSynpress } from '@synthetixio/synpress'; import { MetaMask, metaMaskFixtures } from '@synthetixio/synpress/playwright'; import basicSetup from './wallet-setup/metamask.setup'; const test = testWithSynpress(metaMaskFixtures(basicSetup)); let metamask: MetaMask; const { expect } = test;This setup tells Synpress to use MetaMask in your tests with your specified configuration.sdk/packages/ui-react/test/wallet-setup/basic.setup.ts at main · BetSwirl/sdkSDK to interact with BetSwirl's smart-contracts. Contribute to BetSwirl/sdk development by creating an account on GitHub.https://github.comWriting Tests: Connect That Wallet!Let's start with something every Web3 app needs – connecting a wallet. Here's what a basic test looks like:test.describe('My Awesome DApp Tests', () => { test('should connect wallet successfully', async ({ page }) => { // Navigate to your app await page.goto('http://localhost:3000'); // Click that connect button await page.click('[data-testid="connect-wallet"]'); // Synpress handles the MetaMask popup automatically // Check if we're connected await expect(page.locator('[data-testid="wallet-address"]')).toBeVisible(); }); });What I love about this is how clean it is. No wrestling with popup windows or iframe nightmares – Synpress handles all that for you.The Transaction Test: Where Things Get RealOnce you've mastered wallet connection, it's time for the main event – testing transactions:test('should send tokens successfully', async ({ page }) => { // Navigate to coin toss game await page.goto("/coinToss.html") // Connect wallet const connectButton = page.getByTestId("ockConnectButton") await connectButton.click() // Find and click play button const playButton = page.locator('button:has-text("Place Bet")') // Click play button await playButton.click() await metamask.confirmTransaction() // Verify success const resultModal = page.locator('[role="dialog"]').filter({ hasText: /You (won|lost)/i }) const hasResultModal = await resultModal.isVisible({ timeout: 10000 }).catch(() => false) });sdk/packages/ui-react/tests/coinToss.spec.ts at main · BetSwirl/sdkSDK to interact with BetSwirl's smart-contracts. Contribute to BetSwirl/sdk development by creating an account on GitHub.https://github.comDebugging: When Tests Go Wrong (And They Will)Let's be real – tests won't work perfectly the first time. Here are essential debugging techniques:1. The Debug FlagDEBUG=synpress:* npm testThis gives you detailed logs about what's happening under the hood.2. Slow Things DownWhen a test fails and you need to see what's happening:SLOW_MO=1000 npm testThis adds a 1-second delay between actions, making it easier to follow the test execution.3. Screenshots on FailureAdd this to your test for automatic failure documentation:test.afterEach(async ({ page }, testInfo) => { if (testInfo.status !== 'passed') { await page.screenshot({ path: `screenshots/${testInfo.title}.png` }); } });The Setup Script That Wouldn't QuitHere's a fun one that had me pulling my hair out. When running pnpm test:e2e-setup, the process would just... hang. Forever. No errors, no timeout, just an eternal loading state staring back at me. The setup script looked innocent enough:test("Setup wallet", async ({ context, metamask }) => { await metamask.connectToDapp() await metamask.switchNetwork('base') // ... rest of setup })After what felt like hours of staring at a frozen terminal, I finally ran it with debug flags:DEBUG=synpress:* pnpm test:e2e-setupAnd there it was! The debug logs revealed MetaMask was showing a network switch confirmation dialog that the script couldn't handle:synpress:metamask Switching to network: base synpress:metamask Waiting for network switch confirmation... [hanging here forever]The solution? Remove the network switch from the setup entirely. The cached wallet doesn't need to be on a specific network – let each test handle its own network requirements. Sometimes the simplest solutions are the best ones.Writing Better TestsHere's what separates good e2e tests from great ones:Test user journeys, not implementation details – Think "user connects wallet and sends tokens" not "button click triggers function X"Keep tests independent – Each test should work on its own. No test should depend on another test running first.Use data-testid attributes – They're more stable than CSS selectors:Be generous with assertions – But not too generous. Check what matters, ignore what doesn't.Wrapping UpE2E testing with Playwright and Synpress might seem daunting at first, but it's genuinely worth the investment. Start small – maybe just test your wallet connection flow. Then gradually add more complex scenarios. Remember: done is better than perfect. Tests don't need to cover every edge case right away. They just need to catch the obvious breaks while you focus on building features. The best part? Once you have a solid test suite, you can refactor with confidence, ship features faster, and actually enjoy your weekends without worrying about production issues. Happy testing! ## Publication Information - [ChainHacker](https://paragraph.com/@chainhacker/): Publication homepage - [All Posts](https://paragraph.com/@chainhacker/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@chainhacker): Subscribe to updates - [Twitter](https://twitter.com/ChainHackerClan): Follow on Twitter