Setting up Cypress tests for 1C-Bitrix

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1175
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    747
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

Setting Up Cypress Tests for 1C-Bitrix

Cypress is a more modern alternative to Selenium for E2E frontend testing on 1C-Bitrix sites. The key advantage: tests run inside the browser, have full access to the DOM and network, and automatically wait for elements to appear. Cypress has fewer flaky tests ("sometimes fails, sometimes not") than Selenium because there is no race condition with explicit sleep() calls.

Setting Up Cypress Tests for 1C-Bitrix

Installation and Structure

Cypress is installed as a dev dependency in the template folder or in the project root:

npm install --save-dev cypress

Test structure for a 1C-Bitrix project:

cypress/
    e2e/
        catalog/
            filter.cy.ts
            product-card.cy.ts
        cart/
            add-to-cart.cy.ts
            checkout.cy.ts
        auth/
            login.cy.ts
    support/
        commands.ts      <- custom commands
        e2e.ts           <- global imports
    fixtures/
        user.json        <- test data
        product.json
cypress.config.ts

cypress.config.ts for 1C-Bitrix

import { defineConfig } from 'cypress';

export default defineConfig({
    e2e: {
        baseUrl: 'https://test.site.ru',
        specPattern: 'cypress/e2e/**/*.cy.ts',
        supportFile: 'cypress/support/e2e.ts',
        viewportWidth:  1280,
        viewportHeight: 900,
        defaultCommandTimeout: 8000,
        requestTimeout:        10000,
        video: false,
        screenshotOnRunFailure: true,

        // Settings for Bitrix — sessions and CSRF
        experimentalModifyObstructiveThirdPartyCode: true,
    },
    env: {
        adminLogin:    'admin',
        adminPassword: '', // from environment variable CYPRESS_adminPassword
        siteSessid:    '', // CSRF token for API requests
    },
});

Custom Commands for 1C-Bitrix

// cypress/support/commands.ts
declare global {
    namespace Cypress {
        interface Chainable {
            loginBitrix(login: string, password: string): Chainable<void>;
            addToCart(productUrl: string): Chainable<void>;
            getBitrixSessid(): Chainable<string>;
        }
    }
}

Cypress.Commands.add('loginBitrix', (login, password) => {
    cy.visit('/');
    // Get sessid from cookie
    cy.getCookie('PHPSESSID').then(() => {
        cy.request({
            method: 'POST',
            url:    '/local/ajax/auth.php',
            body:   { action: 'login', login, password },
        }).then(resp => {
            expect(resp.body.status).to.eq('success');
        });
    });
});

Cypress.Commands.add('addToCart', (productUrl) => {
    cy.visit(productUrl);
    cy.get('[data-action="add-to-cart"]').click();
    // Wait for cart counter to update
    cy.get('.cart-counter', { timeout: 5000 }).should('not.have.text', '0');
});

E2E Test for the Catalog Filter

// cypress/e2e/catalog/filter.cy.ts
describe('Smart catalog filter', () => {
    beforeEach(() => {
        cy.visit('/catalog/tools/');
        // Wait for filter and products to load
        cy.get('.catalog-filter').should('be.visible');
        cy.get('.product-list').should('be.visible');
    });

    it('filters products by brand', () => {
        cy.get('[data-filter-prop="BRAND"] [value="bosch"]').click();

        // Wait for AJAX update (loader disappears)
        cy.get('.catalog-loading').should('not.exist');

        // URL must change
        cy.url().should('include', 'brand=bosch');

        // All cards contain the Bosch brand
        cy.get('.product-brand').each($el => {
            cy.wrap($el).should('have.text', 'Bosch');
        });
    });

    it('resets the filter', () => {
        cy.get('[data-filter-prop="BRAND"] [value="bosch"]').click();
        cy.get('.catalog-loading').should('not.exist');

        cy.get('.filter-reset-btn').click();
        cy.get('.catalog-loading').should('not.exist');

        cy.url().should('not.include', 'brand=bosch');
    });

    it('displays the correct product count in the filter counter', () => {
        // Verify the counter updates when the filter changes
        cy.get('[data-filter-prop="BRAND"] [value="makita"]').click();
        cy.get('.catalog-loading').should('not.exist');

        cy.get('.products-count').invoke('text').then(text => {
            const count = parseInt(text.replace(/\D/g, ''));
            cy.get('.product-card').should('have.length', Math.min(count, 24)); // 24 — pageSize
        });
    });
});

Order Form Test

// cypress/e2e/cart/checkout.cy.ts
describe('Order checkout', () => {
    it('successfully places an order as a guest', () => {
        // Add product to cart via UI
        cy.addToCart('/catalog/tools/drills/bosch-gsh/');
        cy.visit('/cart/');
        cy.get('.checkout-btn').click();

        // Fill in the order form
        cy.get('#ORDER_PROP_1').type('Ivan Ivanov');          // Name
        cy.get('#ORDER_PROP_2').type('[email protected]');     // Email
        cy.get('#ORDER_PROP_3').type('+79001234567');          // Phone
        cy.get('#ORDER_PROP_6').type('Moscow, Test Street, 1'); // Address

        // Select delivery
        cy.get('[name="DELIVERY_ID"][value="1"]').click();

        // Select payment method
        cy.get('[name="PAY_SYSTEM_ID"][value="1"]').click();

        // Accept user agreement
        cy.get('#agree').check();

        // Submit order
        cy.get('.order-submit-btn').click();

        // Wait for order success page
        cy.url({ timeout: 15000 }).should('include', '/personal/order/');
        cy.get('.order-success-message').should('be.visible');
    });
});

Intercepting AJAX Requests to 1C-Bitrix

// Mocking an AJAX response for isolated testing
cy.intercept('POST', '/local/ajax/cart.php', {
    statusCode: 200,
    body: {
        status: 'success',
        cart: { items: [], totalCount: 0, totalPrice: 0 },
    },
}).as('cartRequest');

cy.get('[data-action="add-to-cart"]').click();
cy.wait('@cartRequest').its('response.statusCode').should('eq', 200);

Timelines

Task Timeline
Install Cypress, base configuration, custom commands 4–8 hours
E2E tests for critical scenarios (5–10 tests) 1–2 days
Full test suite: catalog + cart + checkout 2–4 days
Integration with GitHub Actions / GitLab CI 4–8 hours