Skip to main content

UI Testing

Frappe Framework supports end-to-end (UI) testing using Cypress, a modern JavaScript testing framework that runs directly in the browser without relying on Selenium. Cypress allows you to automate user interactions, verify application behavior, and test complete workflows from the user’s perspective.

Overview

UI tests are written in JavaScript and executed against a running Frappe application. They can simulate real user actions such as logging in, navigating pages, filling forms, clicking buttons, and verifying results.

Writing UI Tests

Create your Cypress test files inside the following directory of your application:

cypress/integration

Each test file should contain one or more Cypress test cases that verify your application’s user interface.

Example Test

The following example logs into the application, creates a new ToDo record, and verifies that it appears in the list view.

context('ToDo', () => {
    before(() => {
        cy.login('Administrator', 'admin');
        cy.visit('/desk');
    });

    it('creates a new todo', () => {
        cy.visit('/app/todo/new-todo-1');
        cy.fill_field('description', 'this is a test todo', 'Text Editor').blur();
        cy.get('.page-title').should('contain', 'Not Saved');
        cy.get('.primary-action').click();

        cy.visit('/desk#List/ToDo');
        cy.location('hash').should('eq', '/app/todo');
        cy.get('.list-row').should('contain', 'this is a test todo');
    });
});

Running Cypress Tests

Cypress uses any Chromium-based browser installed on your machine. Run UI tests from the frappe-bench directory.

Command Description
bench --site [sitename] run-ui-tests [app] Launches the Cypress interface for interactive testing.
--headless Runs all tests without opening the Cypress interface.
--parallel Executes tests in parallel to reduce execution time.

Headless Mode

bench --site [sitename] run-ui-tests [app] --headless

Parallel Execution

bench --site [sitename] run-ui-tests [app] --parallel

Running tests in parallel is especially useful in Continuous Integration (CI) environments where multiple machines can execute tests simultaneously.

Code Coverage

Code coverage measures how much of your application’s source code is executed while running tests. Frappe uses Istanbul (nyc) together with the Cypress Code Coverage plugin to generate coverage reports.

How Code Coverage Works

Before running tests, JavaScript source files are instrumented. Instrumentation inserts counters into the code that record which statements, functions, and branches are executed during testing.

After the tests finish, these counters are combined to generate a coverage report showing which parts of the application were exercised.

Generate Coverage Reports

Step 1: Instrument the source code

npx nyc instrument \
-x 'frappe/public/dist/**' \
-x 'frappe/public/js/lib/**' \
-x '**/*.bundle.js' \
--compact=false \
--in-place frappe

Step 2: Run Cypress tests with coverage enabled

bench --site test_site run-ui-tests frappe --with-coverage

Step 3: Generate the coverage report

npx nyc report --reporter=text

You can generate reports in multiple formats depending on your reporting requirements.

Testing Library Queries

Cypress can also be used together with Testing Library, which encourages writing tests that closely resemble real user interactions.

Benefits include:

  • More user-focused UI tests.
  • Less dependency on implementation details.
  • Better long-term maintainability.
  • More reliable selectors during UI refactoring.

Common Testing Library Queries

Query Purpose
findByRole() Find elements by their accessibility role such as buttons, textboxes, or checkboxes.
findByLabelText() Locate form controls using their visible labels.
findByPlaceholderText() Find input fields using placeholder text.
findByText() Locate elements based on their displayed text.
findByDisplayValue() Find form controls by their current value.
findByTitle() Locate elements using the HTML title attribute.
findByAltText() Find images using their alternative text.
findByTestId() Locate elements using a dedicated testing identifier.

Best Practice

Write UI tests that simulate real user behavior rather than relying on implementation-specific selectors. Prefer Testing Library queries whenever possible, execute tests in headless mode for CI pipelines, and generate code coverage reports regularly to identify untested areas of your application.

Rating: 0 / 5 (0 votes)