Client-side storage

В браузере существует несколько механизмов хранения данных: Web Storage (LocalStorage / SessionStorage) и IndexedDB.

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

  • кэширования данных (состояние интерфейса, ответы API)
  • хранения токенов (небезопасно)
  • поддержки оффлайн-режима (PWA-приложения)
  • ускорения загрузки приложения (предзагрузка данных, восстановление состояния)
  • временного хранения данных (пошаговые формы, незавершённые действия пользователя)
LocalStorage - это простейшее хранилище ключ-значение в браузере, предназначенное для хранения небольших объёмов данных, которые должны сохраняться между сессиями пользователя.
Он работает только со строками, поэтому любые структуры (объекты, массивы) приходится сериализовать в JSON при записи и десериализовать при чтении. Операции с LocalStorage выполняются синхронно, то есть блокируют основной поток браузера*, из-за чего при работе с большим объёмом данных могут возникать задержки в интерфейсе.
*В браузере есть основной поток (main thread) - это поток, в котором выполняется почти всё:
  • JavaScript
  • обработка кликов
  • обновление интерфейса (рендеринг)
  • анимации
На практике в LocalStorage обычно сохраняют настройки пользователя (например, тему или язык интерфейса), различные флаги и A/B-тесты, а также в LocalStorage сохраняют ответы API (в формате JSON), чтобы при следующем открытии страницы можно было сразу показать данные без повторного запроса к серверу. Обычно вместе с данными сохраняют время их получения, чтобы понимать, насколько они актуальны.
Данные доступны из всех вкладок в рамках одного сайта. При этом LocalStorage не контролирует структуру и формат хранимых данных, а также не поддерживает версионирование и атомарные обновления, поэтому изменение формата данных может привести к ошибкам при их чтении.
SessionStorage работает почти так же, как LocalStorage. Данные хранятся в виде строк, а объекты и массивы нужно сериализовать в JSON. Все операции выполняются синхронно, поэтому при работе с большим объёмом данных могут возникать задержки в интерфейсе.
Главное отличие - данные доступны только в рамках одной вкладки браузера и удаляются при её закрытии. У каждой вкладки своё отдельное хранилище, поэтому SessionStorage не подходит для обмена данными между вкладками. На практике его используют для временных данных - например, чтобы запомнить шаг в форме, введённые пользователем данные или текущее состояние страницы. Это позволяет сохранить состояние при перезагрузке страницы, но не хранить его дольше, чем нужно.
На скриншоте показано содержимое SessionStorage. Здесь сохраняются данные, относящиеся к текущей сессии пользователя в рамках одной вкладки. В частности, видна информация о посещении страниц (например, последний открытый путь и признак первого визита), служебные данные аналитики и трекинга, временные идентификаторы, а также настройки браузерного расширения. Эти данные используются во время текущей сессии и автоматически удаляются после закрытия вкладки.
IndexedDB - это встроенная в браузер база данных, которая используется для хранения большого объёма данных и более сложной клиентской логики.
В отличие от LocalStorage и SessionStorage, она работает с объектами напрямую и не требует ручной сериализации в JSON, а операции выполняются асинхронно и не блокируют интерфейс. Данные в IndexedDB хранятся в виде наборов записей, к которым можно обращаться по ключу или по нужным полям, а операции чтения и записи выполняются безопасно и последовательно.
На практике IndexedDB используют для кеширования данных на уровне приложения, реализации оффлайн-режима, хранения пользовательских данных (например, сообщений или списков товаров) и накопления действий для последующей отправки на сервер. Работа с ней требует учитывать версии базы и изменения структуры данных, поэтому по своей сути это уже не просто хранилище, а полноценный слой хранения данных на клиенте.
На скриншоте показан пример данных из IndexedDB - здесь хранится объект с полями hash и lastSentTime. Это уже не просто строка, как в LocalStorage или SessionStorage, а структурированные данные, с которыми можно работать напрямую. В данном случае это некая служебная информация - идентификатор и время последней отправки данных. Такие записи могут использоваться для кеширования, трекинга или контроля повторных действий (например, чтобы не отправлять одно и то же событие несколько раз).
Тестирование
В LocalStorage обычно проверяется корректность работы с постоянными данными: важно убедиться, что данные правильно записываются и читаются, не ломаются при изменении формата и корректно обрабатываются при повторных запусках приложения. Отдельное внимание стоит уделять очистке данных (например, при logout), работе в нескольких вкладках и поведению при наличии устаревшего или повреждённого содержимого. Также важно проверять, как приложение ведёт себя при отсутствии данных в storage.
В SessionStorage фокус на временном состоянии. Проверяется, что данные сохраняются в рамках одной вкладки и корректно восстанавливаются после перезагрузки страницы, но исчезают при её закрытии. Важно убедиться, что данные не протекают между вкладками и не сохраняются дольше, чем нужно. Часто проверяются сценарии с формами, навигацией и промежуточными действиями пользователя.
При тестировании IndexedDB делается упор на работе с более сложными данными и сценариями. Например, корректность записи и чтения объектов, целостность данных при последовательных и параллельных операциях, а также поведение при изменении структуры данных (миграции). Важно тестировать оффлайн-сценарии, кеширование и последующую синхронизацию с сервером. Также стоит проверять обработку ошибок, очистку базы и работу при частично повреждённых данных.

Обсудить статью можно в канале «Тестировщики нужны» — в Telegram и MAX.