🏗️ Framework Architecture (SOLID + POM)

Framework Architecture (SOLID + POM): In Selenium and Playwright, at this point you would write a "Page Object Model" class — Cypress's official documentation recommends the OPPO

In Selenium and Playwright, at this point you would write a "Page Object Model" class — Cypress's official documentation recommends the OPPOSITE: instead of classic POM classes, it recommends "Custom Commands" and "App Actions". Why? Because Cypress does not send commands to the browser REMOTELY like Selenium does — your test code is injected INSIDE the same process, the same event loop, that the application runs in. This is why, instead of driving the "log in via UI" flow through the UI on every test, calling the application's own login function or API DIRECTLY is both faster and less fragile. Second analogy: like a restaurant's back door — instead of the customer (the test) queuing at the front door (the UI) every time to sit at the table, they can enter directly through the kitchen's back door (an API/App Action) and sit down; the result is the same ("the customer is at the table, ready to order") but the path is far shorter and more predictable. But if the UI login test is already written somewhere, why NOT go through the UI in the other 79 tests too — isn't using the UI only for the "does login work" test and the back door for the rest enough? Exactly that: UI login is tested ONCE, by itself; the remaining scenarios start from the assumption "the user is already logged in". Java comparison: this is the SAME motivation as preparing the database directly with `@Sql` in integration tests versus creating a record through the UI in EVERY test — preparing state is NOT the scenario, it is the scenario's PRECONDITION. QA context: with 80 spec files logging in through the UI, adding a CAPTCHA to the login form breaks all 80 files at once; in a suite using App Actions, ONLY 1 function (loginByApi) is updated, and all 80 tests continue unchanged.

Build Your Cypress Framework Step by Step

The 4 pieces below are the BIG PICTURE of the architecture you are about to build piece by piece in this tab. They all start locked — the first time you correctly finish that step's "Try It Yourself" practice, that piece flips from locked to BUILT.

Custom Command / Core Layer

App Actions Instead of "POM"

🧭 Step 1 — The Big Picture: The Custom Command Chain Mindmap

The same architecture is shown here from five angles: first the main flow (what happens when a test calls cy.login()), then the setup flow (from config to the support file, then to the spec), then parallel execution (why Cypress's "same process" architecture parallelizes DIFFERENTLY from Selenium/Playwright), then the data-sharing scope (Cypress.env / fixture / custom command scope), and finally a "does / does not" list for every file.

3️⃣ Parallel Execution — Why Does Cypress Parallelize Differently from Selenium/Playwright?

Spec File = Isolation Unit

CI Parallelism = Machine Level

In Selenium, ThreadLocal, and in Playwright, the worker process managed parallelism within the same run. Cypress by default runs spec files SEQUENTIALLY in a single browser — "parallelism" here moves to a different layer: Cypress Cloud/Dashboard splits a suite's spec files across N different CI machines (`cypress run --record --parallel`), and each machine opens its own browser as a SEPARATE process. So what matters FOR your framework architecture is not ThreadLocal, but that every spec file can stand on its own from start to finish (it must not depend on the previous file's state) — because YOU do not choose which file lands on which machine.

4️⃣ Data-Sharing Scope — How Long Does Each Thing Live?

Cypress.Commands.add(...)

5️⃣ Who Does What? — File Responsibilities