From Cypress Basics to CI/CD with GitHub Actions

From Cypress Basics to CI/CD with GitHub Actions

Getting started in QA Automation can feel overwhelming. You write your first local tests… but then what? In this guide, we'll walk through how a beginner-friendly Cypress project evolves into a fully functional Continuous Integration (CI) pipeline using GitHub Actions.

This is more than a simple login test. It’s a full educational example based on this repository:
πŸ‘‰ jsaldaza/cypress-login-dashboard-ci-demo


πŸš€ Why Cypress?

Cypress is a modern JavaScript-based end-to-end (E2E) testing tool that makes writing and running tests a breeze for web applications. Why is it great for QA?

  • βœ… Runs in the browser for real-time feedback

  • βœ… Automatically waits for elements (no sleep() nonsense)

  • βœ… Has a slick UI for test execution and debugging

  • βœ… Offers full support for CI/CD and parallel test execution

  • βœ… Integrates smoothly with BDD and Page Object Models

It’s especially great for frontend-heavy apps and teams that want quick test feedback and robust debugging tools.


🧱 Project Structure Breakdown

The goal of this project is to teach and demonstrate what a Cypress-based automation project looks like β€” from scratch to CI/CD.

cypress-login-dashboard-ci-demo/
β”œβ”€β”€ cypress/
β”‚   β”œβ”€β”€ e2e/
β”‚   β”‚   β”œβ”€β”€ login/
β”‚   β”‚   β”‚   β”œβ”€β”€ login.feature
β”‚   β”‚   β”‚   └── login.js
β”‚   β”‚   β”œβ”€β”€ dashboard/
β”‚   β”‚   β”‚   β”œβ”€β”€ dashboard.feature
β”‚   β”‚   β”‚   └── dashboard.js
β”‚   β”œβ”€β”€ support/
β”‚   β”‚   β”œβ”€β”€ pageObjects/
β”‚   β”‚   β”‚   β”œβ”€β”€ loginPage.js
β”‚   β”‚   β”‚   └── dashboardPage.js
β”‚   β”‚   β”œβ”€β”€ commands.js
β”‚   β”‚   └── e2e.js
β”œβ”€β”€ .github/
β”‚   └── workflows/
β”‚       └── cypress.yml
β”œβ”€β”€ .env.example
β”œβ”€β”€ cypress.config.js
└── package.json

Highlights:

  • Feature files written in Gherkin (login.feature, dashboard.feature)

  • Test steps implemented in .js files using Cypress + Cucumber

  • Page Object Model (POM) separates locators and actions (loginPage.js, dashboardPage.js)

  • .env.example shows how to use environment variables for credentials

  • CI configured via GitHub Actions in .github/workflows/cypress.yml


πŸ” Login Testing with Gherkin + Page Objects

Here’s a simplified feature example for login:

Feature: Login functionality

  Scenario: Successful login
    Given I visit the login page
    When I enter valid credentials
    Then I should see the dashboard

  Scenario Outline: Invalid logins
    Given I visit the login page
    When I enter "<username>" and "<password>"
    Then I should see an error "<error>"

    Examples:
      | username  | password  | error               |
      | Admin     | wrong123  | Invalid credentials |
      | wrongUser | admin123  | Invalid credentials |

And the Cypress implementation using POM:

Given('I visit the login page', () => {
  loginPage.visit();
});

When('I enter valid credentials', () => {
  loginPage.fillCredentials(Cypress.env('username'), Cypress.env('password'));
  loginPage.submit();
});

Then('I should see the dashboard', () => {
  cy.url().should('include', '/dashboard');
});

Environment variables (CYPRESS_username, CYPRESS_password) are stored safely via .env and GitHub Secrets in CI. πŸ™Œ


πŸ“Š Dashboard Testing and UI Validations

Once logged in, we verify the dashboard loads correctly and UI elements are visible. Some assertions include:

  • Correct page title based on language (English/Spanish)

  • Widgets like β€œTime at Work” or β€œMy Actions” visible

  • Language toggle functionality

We encapsulate all of this in the dashboardPage.js Page Object.

verifyHeader(expectedText) {
  cy.get('h1.page-title').should('have.text', expectedText);
}

This keeps our test logic clean and readable.


βš™οΈ CI/CD Setup with GitHub Actions

Inside .github/workflows/cypress.yml, we define a CI pipeline:

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: Setup Node
        uses: actions/setup-node@v3
        with:
          node-version: 18

      - name: Install dependencies
        run: npm ci

      - name: Run Cypress tests
        run: npx cypress run --env allure=true
        env:
          CYPRESS_username: ${{ secrets.CYPRESS_username }}
          CYPRESS_password: ${{ secrets.CYPRESS_password }}

Highlights:

  • GitHub Secrets manage credentials safely πŸ”

  • Cypress runs in headless mode (npx cypress run)

  • CI triggers on push and pull_request

  • Generates Allure reports (optional)


🧠 Key Best Practices in This Project

  • Use POM (Page Object Model): Centralize selectors and actions

  • Keep tests data-driven: Easily extend login scenarios

  • Use Gherkin + Cucumber: Make specs readable and maintainable

  • Store secrets safely: No hardcoded credentials, ever!

  • Set up CI early: Don’t wait until the end of the project to automate

This base project is intentionally simple and beginner-friendly, but scalable. It’s meant to teach, not overwhelm.


πŸ§ͺ Why Start with Automation + CI Early?

  • Catch bugs before release

  • Give fast feedback to developers

  • Create confidence in your releases

  • Save time on repetitive manual tests

  • Build a culture of quality

By starting small and growing your test suite, you're investing in stability and agility for your team.


🎯 Ready to Try It Yourself?

You can clone the full project from GitHub:

πŸ‘‰ jsaldaza/cypress-login-dashboard-ci-demo

Use it to learn, practice, or extend your own automation framework.


Happy testing!
~ jsaldaza

0
Subscribe to my newsletter

Read articles from Andres Saldarriaga directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Andres Saldarriaga
Andres Saldarriaga