© TOOLS BOX — Next.js / React / TypeScript コードサンプル集

サンプルガイド
←サンプル一覧
nextjstesting

Jest で document.cookie を使ったクッキー操作関数をテストする

document.cookie の get / set / delete を操作するユーティリティ関数を Jest でユニットテストする例。jsdom 環境での cookie 挙動とモックパターンを示す。

難易度: 初級·更新: 2026-04-18·
jest

対応バージョン

nextjs 15react 19jest 29

前提環境

Jest の基本的なテスト記述と document.cookie API の基本を理解していること

概要

document.cookie を操作する getCookie / setCookie / deleteCookie ユーティリティ関数を純粋関数として実装し、Jest でユニットテストする。jsdom 環境では document.cookie が実際にセットされるため追加モック不要な点と、httpOnly クッキーが jsdom では操作できない点を示す。

インストール

npm install jest @types/jest ts-jest

実装

テスト対象のクッキーユーティリティ

// lib/cookie.ts

/** クッキー値を取得する */
export function getCookie(name: string): string | undefined {
  const value = `; ${document.cookie}`;
  const parts = value.split(`; ${encodeURIComponent(name)}=`);
  if (parts.length === 2) {
    const raw = parts.pop()?.split(";").shift();
    return raw !== undefined ? decodeURIComponent(raw) : undefined;
  }
  return undefined;
}

/** クッキーをセットする */
export function setCookie(
  name: string,
  value: string,
  options: {
    maxAge?: number;
    path?: string;
    sameSite?: "Strict" | "Lax" | "None";
  } = {}
): void {
  const { maxAge, path = "/", sameSite = "Lax" } = options;
  let cookie = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
  if (maxAge !== undefined) cookie += `; max-age=${maxAge}`;
  cookie += `; path=${path}`;
  cookie += `; SameSite=${sameSite}`;
  document.cookie = cookie;
}

/** クッキーを削除する(max-age=0 で上書き) */
export function deleteCookie(name: string, path = "/"): void {
  document.cookie = `${encodeURIComponent(name)}=; max-age=0; path=${path}`;
}

基本的なテスト

// lib/cookie.test.ts
import { getCookie, setCookie, deleteCookie } from "./cookie";

describe("getCookie", () => {
  beforeEach(() => {
    // jsdom の cookie をリセット
    document.cookie.split(";").forEach((c) => {
      const name = c.trim().split("=")[0];
      document.cookie = `${name}=; max-age=0; path=/`;
    });
  });

  it("存在するクッキーの値を返す", () => {
    document.cookie = "theme=dark; path=/";
    expect(getCookie("theme")).toBe("dark");
  });

  it("存在しないクッキーは undefined を返す", () => {
    expect(getCookie("nonexistent")).toBeUndefined();
  });

  it("複数のクッキーがある場合に正しい値を返す", () => {
    document.cookie = "a=1; path=/";
    document.cookie = "b=2; path=/";
    expect(getCookie("a")).toBe("1");
    expect(getCookie("b")).toBe("2");
  });
});

describe("setCookie / deleteCookie", () => {
  beforeEach(() => {
    document.cookie.split(";").forEach((c) => {
      const name = c.trim().split("=")[0];
      document.cookie = `${name}=; max-age=0; path=/`;
    });
  });

  it("setCookie でクッキーをセットできる", () => {
    setCookie("lang", "ja");
    expect(getCookie("lang")).toBe("ja");
  });

  it("deleteCookie で削除するとクッキーが取得できなくなる", () => {
    setCookie("lang", "ja");
    deleteCookie("lang");
    expect(getCookie("lang")).toBeUndefined();
  });

  it("値に特殊文字が含まれても往復変換できる", () => {
    setCookie("filter", "a=1&b=2");
    expect(getCookie("filter")).toBe("a=1&b=2");
  });
});

document.cookie を Object.defineProperty でモックする場合

jsdom の document.cookie は読み書きできるが、Secure や HttpOnly を含む完全なモックが必要なときは Object.defineProperty を使う。

// テスト内でのモック例
let cookieStore = "";

beforeEach(() => {
  cookieStore = "";
  Object.defineProperty(document, "cookie", {
    get: () => cookieStore,
    set: (val: string) => {
      const [pair] = val.split(";");
      const [key, value] = pair.split("=");
      if (val.includes("max-age=0")) {
        cookieStore = cookieStore
          .split("; ")
          .filter((c) => !c.startsWith(`${key}=`))
          .join("; ");
      } else {
        const existing = cookieStore
          .split("; ")
          .filter((c) => !c.startsWith(`${key}=`));
        cookieStore = [...existing, `${key}=${value}`].filter(Boolean).join("; ");
      }
    },
    configurable: true,
  });
});

ポイント

  • jsdom 環境では document.cookie への書き込みが実際に機能するため、getCookie / setCookie の基本テストは追加モック不要
  • beforeEach でクッキーをリセットする処理は document.cookie.split(";") ループで行う。document.cookie = "" は動作しない
  • encodeURIComponent / decodeURIComponent を通す往復テストで、特殊文字(& = + など)が安全に扱われることを確認する
  • jsdom では Secure フラグ付きクッキーの書き込みが非 HTTPS 環境で無視される場合がある。Secure を含むロジックは Object.defineProperty モックで制御する
  • httpOnly クッキーは JavaScript から読み書きできない。Next.js の cookies() を使うサーバーサイドの cookie は別途 next/headers のモックが必要になる

注意点

jest-localstorage-mock は localStorage のモック。jest-url-search-params-test は URLSearchParams の単体テスト。これは document.cookie を介したクッキー操作関数のユニットテストと jsdom での挙動に特化。

関連サンプル

同じテーマや技術スタックを使った実装例

  • Jest + React Testing Library でカスタムフックをテストする

    renderHook を使ってカスタムフックの動作を単体テストする例。act でステート更新をラップし、非同期フックの検証パターンも示す。

  • Jest で fetch をモックしてクライアントのデータ取得ロジックをテストする

    jest.spyOn(global, 'fetch') または global.fetch のモック置換で、クライアント側のデータ取得関数の成功・エラー・ネットワーク障害ケースをテストする例。

  • Jest で localStorage / sessionStorage をモックしてフロントエンドロジックをテストする

    jest の beforeEach でストレージをクリア・spyOn でモック化し、localStorage や sessionStorage を使うカスタムフックや関数を単体テストする例。

  • Jest で Next.js Route Handler をテストする

    Request / Response オブジェクトを直接渡して Route Handler 関数をユニットテストする例。GET / POST それぞれのハッピーパスとエラーパスを検証する。

  • Jest で URLSearchParams を使った URL クエリ変換ロジックをテストする

    URLSearchParams を操作するフィルタクエリ生成・パース関数を Jest でユニットテストする例。jsdom 環境での URLSearchParams の挙動とエッジケースの検証パターン。

関連仕様

このサンプルを理解するのに役立つ仕様や概念

  • FrameworkNext.jsReact ベースのフルスタックフレームワーク。SSR・SSG・App Router・API Routes を提供する。
  • API / OptionhttpOnlyJavaScript からの Cookie アクセスを禁止するオプション。XSS によるトークン窃取を防ぐ基本設定。
  • API / OptionsameSiteCookie の送信範囲をクロスサイトリクエスト時に制御するオプション。CSRF 対策の基本設定。
  • API / OptionsecureHTTPS 接続時のみ Cookie を送信するオプション。本番環境では必須のセキュリティ設定。
←サンプル一覧に戻る