SessionStorage API

SessionStorage — это встроенный веб-API, предоставляющее возможность временно хранить данные на стороне клиента в течение одной сессии браузера. В отличие от localStorage, данные sessionStorage существуют только до закрытия вкладки или браузера. Использование sessionStorage в тестах позволяет проверять состояние приложения, основанное на временных данных, таких как токены аутентификации, промежуточные значения форм или флаги пользовательского интерфейса.

Доступ к SessionStorage

Cypress предоставляет несколько способов взаимодействия с sessionStorage. Прямой доступ возможен через стандартный объект window.sessionStorage. Для работы с ним в тестах используются команды cy.window() и then():

cy.window().then((win) => {
    // Получение значения из sessionStorage
    const token = win.sessionStorage.getItem('authToken');
    
    // Установка значения в sessionStorage
    win.sessionStorage.setItem('authToken', '12345');
    
    // Удаление конкретного ключа
    win.sessionStorage.removeItem('authToken');
    
    // Очистка sessionStorage
    win.sessionStorage.clear();
});

Важный момент: доступ к объекту window возможен только после полной загрузки страницы. Поэтому команды cy.visit() или любые действия, инициирующие загрузку, должны выполняться до обращения к sessionStorage.

Работа с данными sessionStorage при авторизации

Частая задача — проверка токена аутентификации или идентификатора сессии. Пример сохранения токена после успешного входа:

cy.visit('/login');
cy.get('#username').type('user1');
cy.get('#password').type('password123');
cy.get('button[type=submit]').click();

cy.window().then((win) => {
    const token = win.sessionStorage.getItem('authToken');
    expect(token).to.exist;
});

Использование sessionStorage позволяет избежать повторной авторизации между тестами, если данные сохраняются корректно. Однако, так как sessionStorage очищается при закрытии вкладки, для долгих сценариев нужно учитывать необходимость повторной установки данных.

Создание кастомных команд для удобства

Для упрощения повторяющихся операций можно создавать кастомные Cypress-команды. Например:

Cypress.Commands.add('setSessionItem', (key, value) => {
    cy.window().then((win) => {
        win.sessionStorage.setItem(key, value);
    });
});

Cypress.Commands.add('getSessionItem', (key) => {
    return cy.window().then((win) => {
        return win.sessionStorage.getItem(key);
    });
});

Применение кастомных команд делает тесты более читаемыми:

cy.setSessionItem('authToken', 'abcdef');
cy.getSessionItem('authToken').then((token) => {
    expect(token).to.equal('abcdef');
});

Использование sessionStorage для подготовки состояния теста

Многие сценарии требуют определенного состояния приложения до начала проверки. SessionStorage позволяет эмулировать уже залогиненного пользователя или заполненные поля форм:

cy.visit('/');
cy.setSessionItem('cart', JSON.stringify([{id: 1, qty: 2}, {id: 2, qty: 1}]));

cy.window().then((win) => {
    const cart = JSON.parse(win.sessionStorage.getItem('cart'));
    expect(cart).to.have.length(2);
});

Такой подход сокращает время выполнения тестов и делает их независимыми от ручного взаимодействия с интерфейсом.

Очистка и восстановление sessionStorage между тестами

Для обеспечения изолированности тестов необходимо очищать sessionStorage после каждого сценария:

afterEach(() => {
    cy.window().then((win) => {
        win.sessionStorage.clear();
    });
});

Если требуется восстановление состояния перед каждым тестом, данные можно сохранять в объекте и восстанавливать через beforeEach:

let sessionData;

beforeEach(() => {
    cy.visit('/');
    if (sessionData) {
        cy.window().then((win) => {
            Object.entries(sessionData).forEach(([key, value]) => {
                win.sessionStorage.setItem(key, value);
            });
        });
    }
});

afterEach(() => {
    cy.window().then((win) => {
        sessionData = {};
        for (let i = 0; i < win.sessionStorage.length; i++) {
            const key = win.sessionStorage.key(i);
            sessionData[key] = win.sessionStorage.getItem(key);
        }
        win.sessionStorage.clear();
    });
});

Особенности использования sessionStorage в Cypress

  1. Изолированность тестов — sessionStorage существует только в рамках одной вкладки. Cypress использует одну вкладку на тест, что упрощает управление данными.
  2. Асинхронность — команды Cypress, работающие с window, являются асинхронными. Использование then() обязательно для корректной работы с данными.
  3. JSON-значения — sessionStorage хранит только строки, поэтому для объектов и массивов необходимо использовать JSON.stringify() и JSON.parse().
  4. Совместимость с CI/CD — sessionStorage может вести себя иначе в headless-режиме. Необходимо проверять тесты в обоих режимах, чтобы убедиться, что данные сохраняются корректно.

Интеграция sessionStorage с другими стратегиями тестирования

SessionStorage можно комбинировать с network-stubbing и fixture-файлами. Например, можно подставлять токен авторизации и одновременно мокировать ответы сервера:

cy.fixture('user.json').then((user) => {
    cy.setSessionItem('authToken', user.token);
});

cy.intercept('GET', '/api/profile', { fixture: 'profile.json' }).as('getProfile');

cy.visit('/dashboard');
cy.wait('@getProfile');

Такой подход ускоряет тестирование и позволяет полностью контролировать состояние приложения без зависимости от реального бэкенда.

Рекомендации по использованию

  • Использовать sessionStorage для временных данных и состояния, которое не должно сохраняться между сессиями.
  • Создавать кастомные команды для частых операций с sessionStorage.
  • Всегда очищать sessionStorage после теста, чтобы избежать скрытых зависимостей.
  • При необходимости восстанавливать состояние сессии между тестами через beforeEach/afterEach.

SessionStorage в сочетании с Cypress обеспечивает гибкий и быстрый инструмент для управления временными данными, упрощая создание стабильных и воспроизводимых тестов.