Hi, I’m Sehani Chathurangi. I specialize in software quality and automation, with experience scaling testing, refactoring legacy suites, and embedding Cypress into CI/CD pipelines. I’m passionate about simplifying complexity, improving test practices, and mentoring teams. You can find me sharing insights on testing and automation on LinkedIn or at Cypress community events.
What is Salesforce Testing and Why is it Unique?
Salesforce is a powerful CRM platform, but testing its workflows can be frustrating—especially for teams adopting Cypress for end-to-end testing. Unlike simple web apps, Salesforce pages are heavy, often slow to load, and use complex DOM structures. Beginners quickly hit timeouts, broken selectors, and disappearing test runners.
Salesforce testing involves verifying the functionality and integrity of your Salesforce customizations, integrations, and business processes. This can include:
- UI/UX Testing: Ensuring the user interface works as expected in Salesforce Lightning or Classic.
- Business Process Validation: Confirming that your custom workflows, approvals, and automations (e.g., in a Sales Cloud or Service Cloud implementation) run correctly.
- Integration Testing: Checking that data is correctly passed between Salesforce and external systems (like a payment gateway or an ERP).
The key challenge with Salesforce is that it's a "low-code/no-code" platform built on a complex, pre-existing UI framework. This means standard testing practices often fail. Instead of simple HTML IDs and classes, you'll encounter dynamically generated IDs, nested iframes, and a large number of components, all of which require a specialized approach.
This post kicks off our 4-part series “Mastering Cypress Testing with Salesforce,” where we’ll solve the most common Cypress + Salesforce challenges.
In Part 1, we’ll walk through:
- Setting up Cypress for Salesforce
- Configuring timeouts and project settings
- Installing helpful plugins
- Running your first Salesforce test
- Avoiding common setup pitfalls
By the end, you’ll have a working Cypress environment tailored for Salesforce and ready to expand in the next posts.
Step 1: Project Structure and Dependencies
Start with a well-organized project structure:
npm init -y
npm install cypress --save-dev
A Quick Note on npx: If you're new to the command line, npx is a package runner that lets you execute an npm package command without having to install it globally. It's the recommended way to open Cypress and will automatically create the default project structure for you, including the cypress/ folder and cypress.config.js file.
The organized folder structure we use ensures maintainability:
cypress/
├── e2e/
│ └── salesforce/
│ └── ui-login.cy.js
└── support/
├── commands.js # Custom commands
├── constants.js # Shared configurations
├── utils.js # Helper functions
└── e2e.js # Support file imports
Step 2: Configure Cypress for Salesforce
Salesforce pages often take longer to load than normal web apps. Let’s update the default configuration to be more resilient to these factors.
Cross-origin Security Settings
module.exports = defineConfig({
experimentalSessionAndOrigin: true,
experimentalModifyObstructiveThirdPartyCode: true,
defaultCommandTimeout: 30000,
includeShadowDom: true,
...
})
- Salesforce authentication flows through multiple domains: login.salesforce.com → my.salesforce.com → your-org.lightning.force.com
- chromeWebSecurity: false allows Cypress to navigate across these different origins
- experimentalSessionAndOrigin enables modern cross-origin testing capabilities
- experimentalModifyObstructiveThirdPartyCode handles Salesforce's JavaScript that might block automation
Timeout and DOM Configuration
defaultCommandTimeout: 30000,
includeShadowDom: true,
- 30-second timeouts: Salesforce can be slow, especially in shared environments. Standard 4-second timeouts would fail constantly
- Shadow DOM support: Lightning Web Components use Shadow DOM extensively. Without this, most selectors wouldn't work
Test Isolation Setting
Critical for Salesforce session management:
- Salesforce login is expensive (takes 5-15 seconds)
- With testIsolation: True, Cypress would clear cookies between tests, forcing re-login for every test
- testIsolation: False maintains session state across tests in the same spec file
Environment Variables Purpose
const env = {
SF_USERNAME: config.env.SF_USERNAME, // Salesforce username
SF_PASSWORD: config.env.SF_PASSWORD, // Password (may include token)
SF_LOGIN_URL: config.env.SF_LOGIN_URL, // Login endpoint (my.salesforce.com)
SF_HOME_RETURL: config.env.SF_HOME_RETURL, // Post-login destination
SF_BASE_URL: config.env.SF_BASE_URL, // Lightning instance URL
};
Each variable's role:
- SF_BASE_URL: Your specific Lightning instance for navigation
- SF_LOGIN_URL: Where jsforce API connects for authentication
- SF_HOME_RETURL: Ensures you land in Lightning Experience, not Classic
Step 3: Install Helpful Plugins
While Cypress works out of the box, Salesforce testing is smoother with some plugins that add specific commands.
npm install jsforce --save-dev # For Salesforce API interactions
npm install -D cypress-xpath
Why import them here? This file is a great place to extend Cypress's behavior because it's loaded before all of your test files. It's the standard way to add custom commands or third-party plugins.
🔧 Why these plugins?
- cypress-xpath: Salesforce UI often uses complex, nested DOM structures where CSS selectors are unreliable. XPath provides a powerful alternative for finding these deep elements.
- cypress-wait-until: Helps when waiting for dynamic components, like a spinner disappearing or a specific value appearing after an async operation.
- Cypress-iframe: Salesforce Lightning often nests content in iframes; the cypress-iframe plugin is essential. Import within cypress/support/e2e.js to bring iframe support to your test suite. You may also want advanced browser flags for Chrome stability—see the custom config for launch arguments to disable security features and extensions.
Step 4: Running Your First Salesforce Test
Edit cypress.env.json with your Salesforce org URLs and credentials:
{
"SF_BASE_URL": "https://<your-org>.lightning.force.com/",
"SF_LOGIN_URL": "https://<your-org>.my.salesforce.com/",
"SF_USERNAME": "<your-username>",
"SF_PASSWORD": "<your-password>",
"SF_HOME_RETURL": "lightning/setup/SetupOneHome/home"
}
Use npm install to fetch dependencies. Then, launch Cypress interactively:
npm run cypress:open
Or run headlessly:
npm run cypress:run
To run only login tests:
npx cypress run --spec cypress/e2e/salesforce/salesforceLogin.cy.js
Step 5: Common Setup Pitfalls (and Fixes)
Selector Best Practices: Avoid using IDs or class names that look like id="j_id0:j_id55". Salesforce often auto-generates these, making them brittle and subject to change. Prioritize stable selectors like attributes or, as a last resort, cypress-xpath to create resilient tests.
Wrapping Up
In this post, we:
- Installed and configured Cypress for Salesforce.
- Increased timeouts to handle slow pages.
- Added plugins for better Salesforce support.
What's Next?
In Part 2, we'll dive deeper into handling cross-origin challenges, managing multi-domain navigation, and solving the disappearing Cypress runner issue that commonly plagues Salesforce testing.
This setup provides a solid foundation for reliable Salesforce UI testing with Cypress. The key is understanding Salesforce's unique architecture and configuring Cypress to work within those constraints.