Engineering

Why ASD Tunnel makes real Mollie payment testing possible in CI

Published:
Updated:
Kelvin Wuite
By Kelvin Wuite • 5 min read
Share
Why ASD Tunnel makes real Mollie payment testing possible in CI

Why ASD Tunnel makes real Mollie payment testing possible in CI

If you've ever tried to write an end-to-end test for a payment provider like Mollie, you've hit the same wall we did: the webhook. Your test can create a payment, your test can click through the Mollie checkout in a headless browser, but then Mollie needs to phone home  to tell your backend "the payment succeeded, activate the subscription." And Mollie's servers cannot reach http://localhost:54321.

This is not a Mollie-specific problem. Any payment provider requires a publicly reachable webhook endpoint. Without that, you can’t test the full payment lifecycle.

What most teams do

Most projects fall back to one of these approaches:

  • Mock the webhook by POSTing a synthetic payload to their handler

  • Use a shared staging environment with a public URL

  • Rely on external tunneling tools in development

Mocking is fast and useful, but it only verifies your handler logic. It does not verify that:

  • Mollie can actually reach your endpoint

  • Your routing, auth, and proxy layers are correct

  • The full payment → webhook → database pipeline works

In other words, you’re testing components and not the system.

The three-tier test strategy

We wanted both speed and realism. In our Playwright E2E suite (e2e/payment-webhook.spec.ts), we split the Mollie tests into three layers:

  1. One-time payment (local) — pure API: call create-payment, verify the DB row, then POST a synthetic webhook to our own edge function. No browser, no tunnel, runs on every PR in under a second.

  2. Subscription (local) — same idea for create-subscription: verify customer creation, subscription row, linked order, and simulate the webhook.

  3. Full Mollie checkout (CI + tunnel) — the real flow. Playwright drives the actual Mollie checkout page, fills the PCI iframe with a test card, clicks "Paid" on Mollie’s status screen, and then waits for Mollie itself to deliver the webhook.

The key difference is that the third test runs inside a GitHub runner, not a staging environment.

The test polls the database until orders.status = 'paid' appears — meaning the entire pipeline completed successfully.

Why a tunnel is required in CI

GitHub runners are ephemeral and not publicly reachable:

  • No inbound traffic

  • No stable IP

  • No exposed ports

So without a public endpoint, Mollie cannot deliver webhooks to your test environment.

A tunnel solves this by creating a temporary, publicly accessible HTTPS endpoint that forwards traffic into the runner.

What ASD Tunnel actually does

The setup in CI is four lines:

bash
asd init --yes
asd caddy start
asd net apply --seed --caddy --tunnel
API_TUNNEL_URL=$(grep '^API_TUNNEL_URL=' .env | cut -d= -f2- | tr -d '"')

This provisions an ephemeral HTTPS endpoint — for example:

https://dev1-api-clientid.eu1.tn.asd.engineer

Requests to that URL are routed through:

  • Caddy (TLS + auth + reverse proxy)

  • into the GitHub runner

  • into local Supabase edge functions

We pass this URL as webhookUrl when creating a Mollie payment. From Mollie’s perspective, this is just a normal production endpoint.

The full payment flow

Playwright → Mollie checkout (real browser)
  → Mollie servers → ASD tunnel
  → Caddy → Supabase edge function
  → Postgres update → test assertion

Every hop is real:

  • Real browser

  • Real Mollie API

  • Real webhook delivery

  • Real database mutation

No mocks, no stubs, no staging environment.

Why this matters

Running this flow inside CI unlocks a few things:

  • End-to-end verification of the webhook path
    You’re testing the actual network boundary, not a simulated call.

  • Detection of integration drift
    Changes in Mollie responses, redirect behavior, or iframe flows surface automatically.

  • Visibility into test-mode quirks
    Subscription and mandate behavior in Mollie test mode is not always deterministic. Running the real flow exposes this early.

  • CI and local parity
    The exact same setup runs locally and in CI. No dependency on shared staging infrastructure.

  • No long-lived public environments
    No staging servers to maintain, sync, or debug.

What’s actually different here

Tunnels themselves are not new. Tools like ngrok and Cloudflare Tunnel solve the same underlying problem.

The difference here is operational:

  • Runs inside a GitHub runner

  • Fully ephemeral (per run)

  • Requires no external setup or accounts

  • Integrated into the same CLI that runs the rest of the stack

This makes full webhook E2E testing something you can run on every PR — not something reserved for staging or manual QA.

Beyond Mollie

The Mollie use case is just one example. The same pattern applies to:

  • Stripe webhooks

  • OAuth callbacks

  • Third-party event systems

  • Any inbound HTTP integration

Boilerplate (Angular + Supabase)

Everything described in this setup is available out of the box in the ASD Angular + Supabase boilerplate:

https://github.com/asd-engineering/asd-angular-supabase

This boilerplate is designed specifically for Angular developers and includes:

  • Playwright E2E setup with webhook testing patterns

  • Supabase edge functions wired for real payment flows

  • ASD CLI integration (tunnel, Caddy, dev stack)

  • Secure defaults (auth, routing, environment handling)

The goal is not just to demonstrate the approach, but to make it directly usable without additional infrastructure work.

Support for additional frameworks is planned and will follow the same pattern.

Closing

The core problem isn’t "testing payments",  it’s testing systems that depend on inbound webhooks in environments that are not publicly reachable.

ASD Tunnel doesn’t introduce a new concept. It removes the operational friction of using that concept in CI.

And that’s what makes full end-to-end webhook testing finally practical.

Kelvin Wuite
Written by

Kelvin Wuite

Kelvin Wuite is the founder of ASD B.V. With over eighteen years of development experience, he has witnessed the same patterns repeat across every software team - endless documentation, manual preparation, environment mismatches, and fragmented collaboration. His drive is to remove these barriers, enabling engineers to work together in unified environments with shorter feedback loops and hands-on collaboration. Since 2015 he has been refining these ideas, leading to ASD — a platform designed to create a faster, more integrated way for development teams to collaborate in an age where AI is thriving.