Lesson 19 of 26

Урок 19 — Cookie vs Cache

Название: Cookie и Cache — что хранит браузер и зачем
Описание: Разбираем два механизма хранения данных в браузере: Cookie и Cache. Объясняем, чем они отличаются, как работают, как их проверять через DevTools и почему это важно для тестировщика.
Почему это важно для QA: Многие баги связаны именно с Cookie и Cache: устаревший кеш показывает старую версию страницы, некорректные Cookie ломают авторизацию. QA должен уметь работать с ними в DevTools.


1. Cookie — что это и зачем

Cookie (куки) — небольшие текстовые файлы, которые сервер отправляет в браузер, а браузер сохраняет и отправляет обратно серверу при каждом последующем запросе.

Аналогия

Представь, что ты пришёл в кафе. Бариста не знает тебя в лицо. Ты говоришь: «Мне всегда латте». Он выдаёт тебе карточку постоянного гостя с твоим заказом. При следующем визите ты показываешь карточку — бариста уже знает что ты хочешь.

Cookie — это такая «карточка постоянного гостя» для браузера.


2. Как работают Cookie

1. Пользователь входит в аккаунт
      ↓
2. Сервер создаёт сессию и отправляет Cookie:
   Set-Cookie: sessionId=abc123; HttpOnly; Secure; Max-Age=86400
      ↓
3. Браузер сохраняет Cookie
      ↓
4. При каждом следующем запросе браузер отправляет:
   Cookie: sessionId=abc123
      ↓
5. Сервер узнаёт пользователя по sessionId

3. Атрибуты Cookie

АтрибутЗначениеДля чего
NameИмя cookieИдентификатор
ValueЗначениеДанные (sessionId, userId и т.д.)
Domainexample.comДля каких доменов отправлять
Path/ или /adminДля каких путей отправлять
Expires / Max-AgeДата или секундыСрок жизни cookie
HttpOnlytrue/falseНельзя прочитать через JavaScript
Securetrue/falseОтправлять только по HTTPS
SameSiteStrict / Lax / NoneЗащита от CSRF атак

Важный флаг HttpOnly

HttpOnly = true → Cookie нельзя прочитать через document.cookie
→ Защита от XSS (скрипт злоумышленника не украдёт сессию)

HttpOnly = false → document.cookie в консоли вернёт значение cookie
→ Уязвимость, если в куки хранится sessionId!

Важный флаг SameSite

SameSite=Strict → Cookie не отправляется при переходе с другого сайта
SameSite=Lax    → Cookie отправляется при GET-запросах с других сайтов
SameSite=None   → Cookie отправляется всегда (нужен Secure=true)

4. Виды Cookie по сроку жизни

Session Cookie:
├── Нет атрибута Expires / Max-Age
├── Хранится пока открыт браузер
└── Удаляется при закрытии браузера

Persistent Cookie:
├── Имеет Expires или Max-Age
├── Хранится заданное время (дни, месяцы, годы)
└── Пример: "Запомнить меня" на 30 дней

5. Cache — что это и зачем

Cache (кеш браузера) — это механизм сохранения ресурсов веб-страницы (HTML, CSS, JS, изображения) на стороне клиента, чтобы не загружать их повторно с сервера.

Аналогия

Ты скачал фильм на компьютер. В следующий раз ты его смотришь уже без интернета — с жёсткого диска. Браузерный кеш работает так же: скачал страницу один раз — при повторном визите загружает с диска.

Зачем нужен Cache

Без кеша: каждый раз загружаем 500 КБ JavaScript
С кешем:  первый раз — 500 КБ, потом — 0 байт (с диска)

Результат:
✓ Страница загружается быстрее
✓ Меньше нагрузки на сервер
✓ Меньше трафика пользователя

6. Как работает Cache

Cache-Control заголовок

Сервер сообщает браузеру, как кешировать ресурс:

HTTP/1.1 200 OK
Cache-Control: max-age=31536000    ← хранить 1 год
Cache-Control: no-cache            ← всегда проверять у сервера (но можно хранить)
Cache-Control: no-store            ← никогда не кешировать
Cache-Control: private             ← кешировать только в браузере (не CDN)
Cache-Control: public              ← можно кешировать везде (CDN тоже)

ETag — умный кеш

1. Браузер запрашивает файл: GET /app.js
2. Сервер отвечает: ETag: "abc123" + файл
3. Браузер сохраняет файл + ETag

При следующем запросе:
4. Браузер: If-None-Match: "abc123"
5a. Файл не изменился → сервер: 304 Not Modified (файл не передаётся!)
5b. Файл изменился → сервер: 200 OK + новый файл + новый ETag

7. Сравнительная таблица Cookie vs Cache

КритерийCookieCache
НазначениеХранение пользовательских данныхУскорение загрузки ресурсов
Что хранитДанные сессии, настройки, идентификаторыHTML, CSS, JS, изображения
Кто создаётСервер (Set-Cookie)Браузер автоматически
Кто читаетСервер (при каждом запросе)Только браузер
Срок жизниЗадаётся явно (или до закрытия вкладки)Задаётся через Cache-Control
Максимальный размер~4 КБГигабайты (на диске)
Влияет на авторизациюДаНет
Влияет на производительностьНемного (добавляет к запросу)Значительно (экономит трафик)

8. Как работать с Cookie и Cache в DevTools

Cookie в Chrome DevTools

1. Открыть DevTools (F12)
2. Перейти: Application → Cookies → [домен сайта]
3. Здесь видны все Cookie:
   - Name, Value, Domain, Path, Expires, HttpOnly, Secure, SameSite

Что можно делать:
✓ Просматривать значения
✓ Удалять конкретные Cookie (правый клик → Delete)
✓ Редактировать значение (двойной клик)
✓ Добавлять новые Cookie

Cache в Chrome DevTools

1. DevTools → Application → Cache Storage
   - Здесь хранятся Service Worker кеши

2. DevTools → Network
   - Status 304 → ресурс взят из кеша (Not Modified)
   - "(disk cache)" → взят с диска
   - "(memory cache)" → взят из оперативной памяти
   - Серые строки → ресурсы из кеша

Очистка кеша:
Ctrl+Shift+Delete → выбрать "Cached images and files"
Или: DevTools → Application → Clear storage → Clear site data

9. Тестирование Cookie и Cache

Что проверять для Cookie

□ Cookie авторизации создаётся при входе
□ Cookie удаляется при выходе (или истекает)
□ Cookie с HttpOnly=true не доступен через document.cookie
□ Cookie с Secure=true передаётся только по HTTPS
□ SameSite настроен корректно
□ Истёкший Cookie не даёт доступ к защищённым страницам
□ Cookie не содержит чувствительных данных в открытом виде

Что проверять для Cache

□ После деплоя новой версии старый CSS/JS не кешируется (cache busting)
□ Приватные данные не кешируются (Cache-Control: no-store)
□ Страница правильно отображается при жёстком обновлении (Ctrl+F5)
□ Ресурсы с длинным cache max-age имеют уникальные имена (app.abc123.js)

Распространённые баги, связанные с Cache

❌ Пользователь видит старую версию после деплоя
→ Причина: CSS/JS закешированы без версионирования
→ Решение: добавить hash в имя файла (app.abc123.css)

❌ Изменения в производительности не видны в Production
→ Причина: старые ресурсы в CDN кеше
→ Решение: инвалидация CDN кеша после деплоя

❌ Приватные данные видны на общем компьютере
→ Причина: страницы с данными пользователя кешируются
→ Решение: Cache-Control: private, no-store для страниц с личными данными

10. Пример работы с Cookie в Playwright

typescripttypescript
import { test, expect, BrowserContext } from "@playwright/test";

test.describe("Cookie авторизации", () => {
  test("cookie сессии создаётся при входе", async ({ page, context }) => {
    await page.goto("/login");
    await page.fill('[name="email"]', "user@test.com");
    await page.fill('[name="password"]', "TestPass123");
    await page.click('[type="submit"]');

    // Получаем все Cookie текущего домена
    const cookies = await context.cookies();
    const sessionCookie = cookies.find((c) => c.name === "sessionId");

    expect(sessionCookie, "Cookie сессии должен быть создан").toBeDefined();
    expect(sessionCookie?.httpOnly, "Cookie должен быть HttpOnly").toBe(true);
    expect(sessionCookie?.secure, "Cookie должен быть Secure").toBe(true);
  });

  test("cookie сессии удаляется при выходе", async ({ page, context }) => {
    // Устанавливаем Cookie сессии (минуя UI)
    await context.addCookies([
      {
        name: "sessionId",
        value: "test-session-123",
        domain: "localhost",
        path: "/",
      },
    ]);

    await page.goto("/dashboard");
    await page.click('[data-testid="logout-button"]');

    const cookies = await context.cookies();
    const sessionCookie = cookies.find((c) => c.name === "sessionId");

    expect(sessionCookie, "Cookie сессии должен быть удалён после выхода").toBeUndefined();
  });
});

11. Другие виды хранилищ браузера

Кроме Cookie и Cache, в браузере есть и другие хранилища:

ХранилищеОбъёмДоступСрок жизни
Cookie~4 КБСервер + JSЗадаётся вручную
LocalStorage~5–10 МБТолько JSБессрочно
SessionStorage~5–10 МБТолько JSДо закрытия вкладки
IndexedDBСотни МБТолько JSБессрочно
Cache APIГигабайтыService WorkerДо очистки

Итог

COOKIE
├── Назначение: хранение данных для сервера (сессия, настройки)
├── Размер: ~4 КБ
├── Создаёт: сервер (Set-Cookie)
├── Читает: сервер (при каждом запросе)
└── Важные флаги: HttpOnly, Secure, SameSite, Max-Age

CACHE (браузерный кеш)
├── Назначение: ускорение загрузки ресурсов
├── Хранит: HTML, CSS, JS, изображения
├── Управляется: через Cache-Control заголовки
└── Проблема: устаревший кеш может показывать старый контент

КЛЮЧЕВОЕ ОТЛИЧИЕ:
Cookie = данные о пользователе (кто ты?)
Cache = ресурсы страницы (что показать?)