# テスト方針書

## 概要

本ドキュメントは、Decap CMS プロジェクトにおけるテスト方針を定義する。Decap CMS はモノレポ構成（Lerna + Nx）で管理されるオープンソースのヘッドレスCMSであり、GitHub・GitLab・Bitbucket・Git Gateway 等の複数バックエンドをサポートする。本書では、単体テストからE2Eテストまでの各テストレベルの戦略、使用ツール、CI/CDパイプラインでの自動テスト実行方針、および品質基準を記載する。

## テスト戦略

### テストレベル

| レベル | 目的 | 担当 |
| --- | --- | --- |
| 単体テスト | 各パッケージ内のコンポーネント・関数・ユーティリティの個別動作を検証する。Reactコンポーネントのレンダリング、状態管理、ユーティリティ関数のロジックを対象とする | 開発者（Jest + Testing Library） |
| 結合テスト | 複数パッケージ間の連携動作を検証する。バックエンドAPI統合、ウィジェット間連携、設定ファイルとの整合性を確認する | 開発者（Jest + モック） |
| E2Eテスト | 実際のブラウザ操作を通じて、CMSの主要ワークフロー（コンテンツ作成・編集・公開・メディア管理）をエンドツーエンドで検証する。各バックエンド（GitHub・GitLab・Bitbucket・Git Gateway・Proxy・Test）に対してシナリオテストを実施する | 開発者・QA（Cypress） |
| 受入テスト | リリース前に主要機能の正常動作を確認し、プロダクション環境でのデグレードを防止する | リリースマネージャー |

### テスト種別

| 種別 | 概要 | 実施タイミング |
| --- | --- | --- |
| 機能テスト | CMSの各機能（エディタ、ウィジェット、メディアライブラリ、ワークフロー）の正常動作を検証 | PR作成時・マージ前 |
| UIスナップショットテスト | Emotionスタイルを含むコンポーネントのレンダリング結果をスナップショットで管理し、意図しないUI変更を検出 | 単体テスト実行時 |
| イメージスナップショットテスト | Cypressによるビジュアルリグレッションテストで、UIの見た目の変更を画像比較により検出 | E2Eテスト実行時 |
| 静的解析 | ESLint・TypeScript strict mode・Prettier・StyleLint によるコード品質・型安全性の確保 | PR作成時・コミット時 |
| セキュリティテスト | 依存パッケージの脆弱性チェック（npm audit）、認証フローの検証 | リリース前・定期実行 |
| 性能テスト | 大量コンテンツ・メディアファイル操作時のCMS応答性能を計測 | リリース前（手動） |

## テスト環境

| 環境 | 用途 | 構成 |
| --- | --- | --- |
| ローカル開発環境 | 開発者による単体テスト・E2Eテスト実行 | Node.js 22.x/24.x、jsdom（Jest）、Chrome headless（Cypress）、http-server（localhost:8080） |
| GitHub Actions CI | 自動テスト実行環境 | Ubuntu Latest / macOS Latest / Windows Latest、Node.js 22.x/24.x マトリックス |
| E2E テスト環境 | Cypress E2Eテスト実行 | デモサイト（dev-test/）をhttp-serverで配信、モックサーバー（localhost:1080）、フィクスチャベースのHTTPスタブ |
| Cypress Cloud | E2Eテスト結果の記録・管理 | projectId: 1c35bs、並列実行対応 |

## テストツール

| ツール | 用途 | バージョン |
| --- | --- | --- |
| Jest | 単体テスト・スナップショットテストフレームワーク | 27.x |
| jest-environment-jsdom | ブラウザ環境シミュレーション | Jest 27同梱 |
| @testing-library/react | Reactコンポーネントテストユーティリティ | 16.x |
| @testing-library/dom | DOM操作テストユーティリティ | 10.x |
| @testing-library/jest-dom | カスタムJestマッチャー（DOM検証用） | 5.11.1 |
| @emotion/jest | Emotionスタイルのスナップショットシリアライザ | 11.11.0 |
| ts-jest | TypeScriptファイルのJestトランスパイラ | - |
| babel-jest | Babelベースのトランスパイラ | - |
| Cypress | E2Eテストフレームワーク | 12.17.4 |
| @simonsmith/cypress-image-snapshot | ビジュアルリグレッションテスト | - |
| cypress-jest-adapter | CypressでJestスタイルのアサーション使用 | - |
| cypress-plugin-tab | タブキー操作シミュレーション | - |
| nock | HTTPリクエストモック（Node.js環境） | 13.x |
| mockserver-node / mockserver-client | HTTPモックサーバー | - |
| start-server-and-test | サーバー起動待機後のテスト実行 | 2.1.3 |
| http-server | E2Eテスト用静的ファイルサーバー | - |
| cross-env | 環境変数のクロスプラットフォーム設定 | - |
| ESLint | JavaScript/TypeScript静的解析 | - |
| Prettier | コードフォーマッタ | - |
| StyleLint | CSS/SCSS静的解析 | - |
| TypeScript | 型チェック（strict mode） | - |
| CommitLint | コミットメッセージ規約チェック | @commitlint/config-conventional |
| Husky | Gitフックによるコミット時検証 | - |

## カバレッジ目標

| 対象 | 目標値 |
| --- | --- |
| 行カバレッジ | 明示的な数値目標の設定なし（Jestデフォルトカバレッジを使用） |
| 分岐カバレッジ | 明示的な数値目標の設定なし |

> **備考**: プロジェクトではJestのデフォルトカバレッジ機能を利用可能だが、jest.config.js に `collectCoverage` や `coverageThreshold` の明示的な設定は存在しない。カバレッジの計測は `jest --coverage` オプションにより手動で実行可能。カバレッジ閾値の強制は現時点でCI/CDパイプラインに組み込まれていない。

## テストデータ

### 単体テスト

- **モック/スタブ**: `setupTestFramework.js` にて `window.fetch`（node-fetch）、`window.URL.createObjectURL`（jest.fn()）、`path`モジュール（posix固定）をグローバルモックとして設定
- **スタイルモック**: `__mocks__/styleMock.js` にてCSS/LESSモジュールを空オブジェクトでスタブ
- **Emotionシリアライザ**: スナップショットテストで `@emotion/jest/serializer` を使用し、スタイル付きコンポーネントの安定したスナップショットを生成

### E2Eテスト

- **フィクスチャ**: `cypress/fixtures/` 配下に141個のJSONファイルとして、各バックエンド（GitHub REST/GraphQL・GitLab・Bitbucket・Git Gateway）のHTTPリクエスト/レスポンスをレコーディング
- **フィクスチャ記録**: `test:e2e:record-fixtures:dev` スクリプトによりHTTPプロキシ経由で実際のAPI通信を記録可能
- **モックサーバー**: `cypress/utils/mock-server.js` にてlocalhost:1080でHTTPモックサーバーを起動
- **カスタムコマンド**: `cypress/support/commands.js`（12,370行）にてfetchスタブ、Base64エンコード、FormData対応、タイムスタンプパターンマッチング等を実装
- **共有テストステップ**: `cypress/utils/steps.js`（20,832行）にて各バックエンド共通のE2Eテストステップを定義
- **メディアフィクスチャ**: `cypress/fixtures/media/` 配下に画像等のメディアテストデータを配置
- **イメージスナップショット**: `cypress/snapshots/` 配下にビジュアルリグレッション用の基準画像を4件管理

## 不具合管理

- **課題管理**: GitHubのIssue/Pull Requestで不具合を管理
- **コミット規約**: Husky + CommitLint により `@commitlint/config-conventional` に準拠したコミットメッセージを強制。不具合修正コミットは `fix:` プレフィックスを使用
- **バージョン管理**: Lerna の independent versioning + conventional commits により、不具合修正は自動的にパッチバージョンとしてリリース対象に含まれる
- **リリースブランチ**: `main` および `release/*` ブランチからのみバージョンリリースを許可（lerna.json の `allowBranch` 設定）
- **CI失敗時の対応**: GitHub Actions のテスト失敗時はPRマージがブロックされ、E2Eテストのスクリーンショット・ビデオがアーティファクトとして保存される

## CI/CD連携

### GitHub Actions パイプライン

#### 単体テスト・静的解析ジョブ (`build-unit`)

- **トリガー**: `main`/`master` ブランチへのpush、全Pull Request
- **マトリックス構成**: OS 3種（Ubuntu・macOS・Windows） × Node.js 2バージョン（22.x・24.x）= 最大6パターン
- **パスフィルタリング**: `website/**` 配下の変更は除外
- **実行コマンド**: `npm run test:ci`（lint-quiet → type-check → test:unit）
- **並行制御**: `ci-${{ github.workflow }}-${{ github.ref }}` によりグループ化し、同一ブランチの古い実行を自動キャンセル

#### E2Eテストジョブ (`e2e`)

- **前提**: `build-unit` ジョブの成功
- **並列実行**: 4マシンで分散実行（`MACHINE_INDEX` / `MACHINE_COUNT` 環境変数で制御）
- **実行フロー**: `npm run build:demo` → `npm run test:e2e:run-ci`（`cypress/run.mjs` による分散実行）
- **リトライ**: Cypress設定で `retries: 4`（runMode）
- **タイムゾーン**: `TZ=Europe/Amsterdam` で統一
- **キャッシング**: Cypressバイナリ・npmキャッシュを活用
- **アーティファクト保存**: テスト失敗時に `cypress/screenshots/` と `cypress/videos/` を保存

#### パブリッシュジョブ

- **トリガー**: `decap-*@*` タグのpush
- **フロー**: build → test:ci → lerna:publish
- **認証**: OIDC trusted publishers

### ローカル開発でのテスト実行

```bash
# 単体テスト（lint + type-check + unit test）
npm run test

# E2Eテスト（ビルド + サーバー起動 + Cypress実行）
npm run test:e2e

# E2Eテスト（開発モード - Cypress GUI起動）
npm run test:e2e:dev

# 全テスト実行
npm run test:all
```

## 備考

### モノレポ構成

- **パッケージ管理**: Lerna（independent versioning）+ Nx（ビルドキャッシュ）
- **パッケージ数**: `packages/` 配下に複数のパッケージ（decap-cms-core, decap-cms-app, decap-server, 各バックエンド, 各ウィジェット等）
- **テスト配置**: 各パッケージの `src/__tests__/` または `src/*.spec.ts` にユニットテストを配置
- **ユニットテストファイル数**: 約80ファイル
- **E2Eテストファイル数**: 51ファイル（`cypress/e2e/`）

### マルチバックエンド対応

E2Eテストは以下の全バックエンドに対してシナリオテストを実施：
- GitHub（REST API / GraphQL API）
- GitLab
- Bitbucket
- Git Gateway
- Proxy
- Test Backend

各バックエンド用のCypressプラグイン（`cypress/plugins/`）がセットアップ・ティアダウン処理を提供し、フィクスチャベースのHTTPスタブにより外部サービスへの依存なくテストを実行可能としている。

### テスト関連の注意事項

- TypeScript の `tsconfig.json` では `**/*.spec.ts` がコンパイル対象から除外されている（テストコードのトランスパイルは ts-jest / babel-jest が担当）
- Babel設定では `test` 環境で `babel-plugin-inline-react-svg` のみを適用（軽量なテスト用ビルド）
- Lerna設定では `**/__fixtures__/**`, `**/__tests__/**`, `**/*.md` の変更がバージョン変更のトリガーから除外されている
