From Playwright to Cypress.io: Solving 5 Real-World Testing Challenges
If you’re coming from Playwright and diving into Cypress.io, you’ll quickly notice some differences in how these tools handle real-world…
From Playwright to Cypress.io: Solving 5 Real-World Testing Challenges
If you’re coming from Playwright and diving into Cypress.io, you’ll quickly notice some differences in how these tools handle real-world test scenarios.
While Cypress offers powerful features, certain use cases — like handling multiple sessions, running in parallel, or adjusting timeouts — require a bit of a mindset shift.
In this guide, we’ll break down five common challenges for Playwright users switching to Cypress and show exactly how to implement solutions in Cypress with best practices, examples, and code snippets.
1. Multiple User Sessions in Cypress
The Playwright Way:
Playwright makes multi-user flows straightforward with isolated browser contexts.
The Cypress Way:
Cypress traditionally runs tests in a single browser context, but since v9.6, we have cy.session()
to store and restore sessions efficiently.
Why This Matters:
Multi-user scenarios are common in apps with admin/user roles, messaging systems, or collaborative features.
Implementation Example:
// cypress/support/commands.js
Cypress.Commands.add('loginAs', (username, password) => {
cy.session(\[username\], () => {
cy.visit('/login');
cy.get('#username').type(username);
cy.get('#password').type(password);
cy.get('button\[type="submit"\]').click();
cy.url().should('not.include', '/login');
});
});
// Example usage in test
describe('Multi-user flow', () => {
it('should switch between admin and regular user', () => {
cy.loginAs('admin', 'adminPass');
cy.visit('/admin-dashboard');
cy.loginAs('user', 'userPass');
cy.visit('/user-dashboard');
});
});
Pro Tip:
If role-switching within a single test is too complex, split the tests into separate spec files and run them in parallel (see next section).
2. Parallel Testing for Faster Execution
The Playwright Way:
Playwright Test supports parallelism out of the box via workers.
The Cypress Way:
Cypress supports parallelism via the Cypress Dashboard or by splitting specs manually in CI.
Using Cypress Dashboard (Recommended for Scaling):
npx cypress run \--record \--key <your\_record\_key> \--parallel \--ci-build-id $BUILD\_ID
This distributes your specs across multiple machines, reducing execution time significantly.
Without Cypress Dashboard (Manual Spec Splitting in CI):
# Example: GitHub Actions workflow
npx cypress run --spec "cypress/e2e/spec1.cy.js"
npx cypress run --spec "cypress/e2e/spec2.cy.js"
Pro Tip:
For auto-splitting, try cypress-split to evenly distribute specs across workers.
3. Handling Long-Running Tests (Changing Timeouts)
The Playwright Way:
Playwright lets you adjust timeouts globally or per action easily.
The Cypress Way:
Cypress commands have built-in retry-ability but come with strict default timeouts (defaultCommandTimeout
= 4s, pageLoadTimeout
= 60s).
Global Timeout Config (**cypress.config.js**
):
module.exports = {
defaultCommandTimeout: 15000, // 15 seconds
pageLoadTimeout: 120000, // 2 minutes
requestTimeout: 20000,
};
Per Command Timeout:
cy.get('.slow-element', { timeout: 20000 }).should('be.visible');
Pro Tip:
Combine smart waits (assertions + retries) instead of adding large static waits like cy.wait(5000)
.
4. Uploading Files in Cypress
The Playwright Way:
Playwright handles file uploads with setInputFiles()
directly.
The Cypress Way:
Requires a helper plugin (cypress-file-upload
) for convenient syntax.
Setup:
npm install \--save-dev cypress-file-upload
In commands.js
:
import 'cypress-file-upload';
Usage:
const filePath = 'files/sample.pdf';
cy.get('input\[type="file"\]').attachFile(filePath);
// For drag-and-drop zones
cy.get('#dropzone').attachFile(filePath, { subjectType: 'drag-n-drop' });
Pro Tip:
Keep test files inside cypress/fixtures/
for easier access and CI compatibility.
5. cy.request()
vs cy.intercept()
These two commands are often confused, but they serve different purposes.
Featurecy.request()cy.intercept()
PurposeSend HTTP requests directlySpy, stub, or modify app’s network calls
Needs UI? NoYes, triggers via app
Best ForAPI testing, data setup, bypassing UIMocking backend, validating network calls, controlling responses
Example
cy.request('POST', '/api/login', { user, pass })cy.intercept('GET', '/api/items').as('getItems');
cy.wait('@getItems')
When to use:
-
**cy.request()**
: Preparing test data faster without UI (like logging in or cleaning DB state). -
**cy.intercept()**
: Observing or mocking network behavior during UI tests.
Final Thoughts
Switching from Playwright to Cypress.io is easier when you know how to adapt your test strategies to Cypress’s architecture.
Here’s a quick takeaway table:
Playwright to Cypress.io
By mastering these adjustments, you can write fast, maintainable, and reliable Cypress tests while leveraging your existing Playwright skills.
You have read about: Cypress multiple user sessions, Cypress parallel testing, Cypress timeouts, Cypress file upload, cy.request vs cy.intercept, Cypress for Playwright users, Cypress vs Playwright network requests, Cypress configuration best practices.
By Mohamed Said Ibrahim on August 30, 2025.
Exported from Medium on October 2, 2025.
Top comments (0)