# Dev Login Trick: Test Paywalls in 1 Click, Not 4

> Staging-dependent paywall testing is slow. A local-only bypass flag gives one-click login as any fixture user. Setup plus safeguards inside.

Source: https://boringpush.com/blog/dev-login-test-paywalls-locally

## Testing paid flows requires paying

You change the paywall redirect. To verify, you need four logins: free user (sees pricing), trial (sees app with banner), lifetime (sees app), expired (sees renew). Each needs Google OAuth round-trips or magic-link inbox waits — per check, per browser, all day.

So paywall testing happens on staging once a week, or never. The redirect bug ships to prod where a stranger finds it in checkout. Access logic is the least-tested code guarding the most money.

Dev login test paywalls fixes it with a local-only door: one click, any fixture user, zero network, instant iteration.

## Paywall testing without bypass vs with

| Check | No bypass (OAuth each time) | Bypass (1 click) |
|---|---|---|
| Free → pricing redirect | 2 min (login dance) | 3 seconds |
| Trial banner renders | New trial account setup | Click "trial fixture" |
| Expired → renew flow | Wait for expiry (days!) | Click "expired fixture" |
| Regression per deploy | Skipped (too slow) | 4 clicks, 30 seconds |
| Auth edge coverage | Happy path only | Full matrix, routinely |

Three details make bypass-free testing fail structurally:

1. **Expiry is untestable without fixtures.** Trial ends, subscription lapses, grace periods — all time-based states no OAuth dance can produce on demand. Without fixture users frozen in each state, expiry logic ships untested by definition.
2. **OAuth round-trips kill iteration.** Two-minute logins turn paywall tweaks into twenty-minute cycles; developers batch changes to amortize the dance, and batches break more than singles. Speed of iteration determines quality of access code directly.
3. **Staging auth differs from prod auth.** Test-mode providers, relaxed cookies, shared secrets — staging login proving little about prod behavior. Local fixtures plus drilled staging plus one live check form the complete chain; any single link alone lies.

The starter post wired auth; this one makes its paywall testable at desk speed.

## The dev login rig

BoringPush ships a development-only login with two ready-made users: a free one and a paying one. They exist on your own machine only, and are absent from production builds.

**Step 1: Two fixture users cover the two states that matter.** The free user gets the pricing redirect. The paying user gets the full app. Together they let you walk through every paid page and API without a purchase. The emails are obviously fake, so a leaked screenshot embarrasses nobody. If your product has trials or an expired state, add those users yourself.

**Step 2: One-click login behind a local-only gate.** In development, the sign-in page offers a login that needs no Google round trip and no inbox. Pick the free or paying user and you land in the app in seconds. The gate is environmental: it only works when the app runs in development mode with a local settings file present, and in any other environment the login does not exist.

**Step 3: Guard the bypass out of production.** A dev backdoor in prod is a severity-1 incident wearing convenience clothes, so verify the seal rather than trust it. Check that production builds refuse the dev login. Check that your production settings carry no development flag. And once a quarter, try the dev login against production and confirm it does not work.

Which is the point: paywalls proven at desk speed, and production sealed by construction.

## The paywall matrix, 30 seconds

| Fixture | Action | Expect |
|---|---|---|
| Free user | Sign in with the dev login, open the dashboard | Redirect to pricing |
| Paying user | Sign in with the dev login, open the dashboard | The full app |
| Paid API, free user | Call a paid endpoint | 403 |
| Production probe | Try the dev login on production | Not available |

Run the matrix on every deploy that touches auth, paywall or pricing. Four checks take thirty seconds and give complete access confidence. A green matrix is the merge gate for access code, and red blocks like a failing test, because it is one.

Naming the cost: fixtures can drift from real user shapes as you add fields and tiers, until the tests prove fiction. Audit them against the current schema every quarter, never against production data. And the speed tempts you to skip staging, so keep the chain: local matrix, then staging with real sign-in, then one live check.

## FAQ

### Is a dev login safe? Isn't a bypass a backdoor?

A backdoor is an undocumented remote entrance. This is a documented local-only login that does not exist in production builds.

The difference is construction plus verification, not intention. Audit the seal every quarter and sleep well.

### How do fixture users stay realistic as the schema evolves?

Audit them quarterly. Compare the fixtures against the current user shape, add new fields with representative values and prune obsolete ones. Fixtures are test code, and test code rots without tending.

### Can Playwright or Cypress drive the bypass for end-to-end tests?

Yes, and it is the best use. A test can start from a known user state in seconds with no OAuth mocking. Real routes, real guards and fixture users catch the breaks that unit tests structurally miss.

### Should staging have a bypass too?

No. Staging proves the real sign-in path, which is its job in the chain.

Use test-mode providers and documented test accounts there. Bypass locally for speed, real sign-in on staging for fidelity and one live check in production for truth.

### What about testing the sign-up flow itself?

Sign-up needs the real path even locally. Use a Google test user and an email address you control.

The bypass covers post-sign-up states, and test-mode providers cover acquisition. Two rigs, a clean split.

### How do I stop teammates using the bypass against staging data?

They cannot, because the dev login does not exist outside development mode. The guard is environmental, not honor-based. Document it once, demonstrate that it is absent in staging and the question retires.

## Keep reading

- [Next.js Auth in an Afternoon: Google + Magic Links](/blog/nextjs-google-oauth-magic-links-starter) — the auth this bypass accelerates
- [requirePaidUser(): One Boolean, Zero Paywall Holes](/blog/requirepaiduser-paywall-one-boolean) — the guard the matrix proves
- [Auth Without the 2 a.m. Pages: Google + Magic Links](/blog/auth-without-headaches) — the founding sketch behind both
