User-flows Tests
| Key | Value |
|---|
| Status | Active |
| Owner | QA Automation |
| Updated | 2026-03-26 |
| Scope | Authenticated subscription and paywall journeys across all 6 CNC sites |
User-flows tests exist because login, session management, paywall access, and subscription routing are the revenue-critical paths on CNC sites. A reader who cannot log in, cannot reach premium content, or sees a broken subscription page is a reader who does not convert. These tests keep those paths verified on a nightly basis.
What The Suite Does
| Capability | What It Means |
|---|
| fresh login | performs the full redirect through login.cncenter.cz and confirms user is logged in |
| premium access | verifies a premium user does not hit a paywall on premium content |
| paywall enforcement | verifies an anonymous user does see a paywall on premium content |
| subscription page | confirms the subscription page loads and a buy button is present |
| logout | confirms the user can log out and the login button reappears |
| session persistence | confirms session survives navigating to an article and returning to homepage |
| SSO cross-site | confirms login on one CNC domain carries session to another domain |
Current Shape
| Metric | Current Snapshot |
|---|
| total tests | 34 |
| passing | 30 |
| skipped by design | 4 |
| pass rate | 88.2% (30/30 among eligible tests) |
| sites covered | 6 |
| schedule | nightly |
| parallelism | sequential only (--workers=1) |
What "Skipped By Design" Means
Four tests are marked as skipped by design, not failures.
| Skip Reason | Which Tests |
|---|
Opinio has no shared CNC credentials configured (supportsAuth: false) | Test A (login), Test E (logout), Test F (session) on Opinio |
Blesk has no premium subscription product (hasSubscription: false) | Test D (subscription page) on Blesk |
These are permanent skips because the underlying capability does not exist on those sites. They are counted as skipped, not failed.
Test Matrix By Site
| Site | Test A: Login | Test B: Premium Access | Test C: Paywall | Test D: Subscription | Test E: Logout | Test F: Session | Notes |
|---|
| Auto | pass | pass | pass | pass | pass | pass | /autoplus premium path |
| Blesk | pass | — (no premium) | — (no premium) | skipped | pass | pass | no subscription product |
| E15 | pass | pass | pass | pass | pass | pass | /e15-premium path |
| iSport | pass | pass | pass | — (no sub selector) | pass | pass | paywall via iSport premium |
| Reflex | pass | pass | pass | pass | pass | pass | /premium path |
| Opinio | — | pass | pass | — (no sub selector) | — | — | supportsAuth=false; known paywall URL |
SSO Tests (Test G)
Three cross-site SSO pairs are verified separately.
| Pair | Domain Relationship | Expected Behavior |
|---|
| Blesk → iSport | same domain (.blesk.cz) | auto-authenticated, no credentials needed |
| Auto → E15 | cross-domain | SSO redirect, no credential entry |
| E15 → Reflex | cross-domain | SSO redirect, no credential entry |
CPEX Deadlock Pattern
The CPEX consent system can cause test hangs on E15 when a subscription modal overlay (#cpexSubs_modalWrapper) appears after the initial consent is dismissed. This overlay has a high z-index and intercepts clicks meant for the subscription button.
| Where It Occurs | How It Is Handled |
|---|
| Test D on E15 (subscription page) | force-remove #cpexSubs_veil, #cpexSubs_modalWrapper, #cpexSubs_modal via page.evaluate() before clicking the subscription link |
The fix is in the Test D step block and runs only on sites where a CPEX overlay is a known risk.
Paywall Detection Strategy
Test C (non-premium paywall) runs as an anonymous user and uses page.waitForFunction() to poll for paywall elements rather than standard Playwright locators. This is intentional.
| Why waitForFunction | Reason |
|---|
| Piano/Tinypass is JavaScript-injected | the paywall DOM node does not exist at domcontentloaded |
| Locator handlers can deadlock | waitForFunction() runs in page context without triggering Playwright handler loops |
| Height check required | some paywall elements render in DOM with height: 0 — the check requires getBoundingClientRect().height > 0 |
Sequential-Only Constraint
This suite must run with --workers=1. Running parallel workers causes storageState collisions.
| Problem | Why |
|---|
Multiple tests share the same storageState file (e.g. blesk-premium.json) | when test B (premium) passes and its trace is deleted, test E (logout) tries to reopen the same trace file ID and gets ENOENT |
| Traces are disabled for user-flows project | this avoids the trace file collision entirely; traces are off in playwright.config.ts for this project |
How To Run
| Command | What It Does |
|---|
npm run test:user-flows | All 34 tests (sequential, --workers=1) |
npm run test:user-flows -- --grep "auto" | Auto only |
npm run test:user-flows -- --grep "Test A" | All login tests |
npm run test:user-flows -- --grep "SSO" | SSO tests only |
Always use the npm script, which enforces --workers=1 via the project config. Never run this suite with multiple workers.
Auth Setup Dependency
User-flows depends on the auth-setup project, which runs first and saves storageState files. If auth-setup fails, all user-flows tests will fall back to fresh login inline.
| StorageState File Pattern | Purpose |
|---|
{site}-premium.json | pre-authenticated session for premium user |
consent-chrome.json | pre-accepted consent state |
StorageState files are stored in the directory referenced by STORAGE_STATE_DIR in playwright.config.ts.
Related Pages