# バッチ設計書 27-cypress/utils/mock-server.js

## 概要

本ドキュメントは、Decap CMSプロジェクトにおけるE2Eテスト用のモックサーバー管理モジュール `cypress/utils/mock-server.js` の設計を記述する。

### 本バッチの処理概要

本スクリプトは、E2Eテスト実行時にGitHub/GitLab/Bitbucket等の外部APIリクエストを記録・再現するためのモックサーバー（mockserver-node）を起動・停止・リセットするユーティリティモジュールである。E2Eテストを外部サービスに依存せず実行するために使用する。

**業務上の目的・背景**：Decap CMSは複数のGitホスティングサービス（GitHub, GitLab, Bitbucket）をバックエンドとしてサポートしており、E2Eテストではこれらの外部APIとの通信をシミュレートする必要がある。本モジュールにより、外部APIリクエストをモックサーバーで記録・管理し、テストの安定性と再現性を確保する。外部サービスの障害やレート制限に影響されないテスト環境を提供する。

**バッチの実行タイミング**：E2Eテストのセットアップ・ティアダウン時に実行される。`npm run mock:server:start` / `npm run mock:server:stop` でも直接呼び出し可能。E2Eテストのフィクスチャ記録モード（`RECORD_FIXTURES=true`）で使用される。

**主要な処理内容**：
1. `start` - mockserver-nodeをポート1080で起動
2. `stop` - mockserverを停止
3. `retrieveRecordedExpectations` - 記録されたHTTPリクエスト/レスポンスを取得し、対象ホスト（GitHub API, GitLab API, Bitbucket API等）でフィルタリング
4. `resetMockServerState` - モックサーバーの状態をリセット

**前後の処理との関連**：E2Eテスト実行前にモックサーバーが起動され、テスト終了後に停止される。`package.json` の `mock:server:start` / `mock:server:stop` スクリプトから直接利用される。E2Eテストのフィクスチャ記録時（`test:e2e:record-fixtures:dev`）に `HTTP_PROXY=http://localhost:1080` でプロキシ経由のリクエスト記録が行われる。

**影響範囲**：E2Eテストの外部API通信。モックサーバーが正しく動作しない場合、E2Eテストが実際の外部サービスにリクエストを送信するか、テストが失敗する。

## バッチ種別

テストユーティリティ（E2Eテスト用モックサーバー管理）

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | E2Eテスト実行時（随時） |
| 実行時刻 | N/A |
| 実行曜日 | N/A |
| 実行日 | N/A |
| トリガー | E2Eテストのセットアップ/ティアダウン、または `npm run mock:server:start/stop` |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Node.js実行環境 | Node.jsが利用可能であること |
| mockserver-node | mockserver-nodeパッケージがインストール済みであること |
| mockserver-client | mockserver-clientパッケージがインストール済みであること |
| Java実行環境 | mockserver-nodeはJavaベースのため、Java Runtime Environmentが必要 |
| ポート1080の空き | ポート1080が他のプロセスに使用されていないこと |

### 実行可否判定

ポート1080が既に使用されている場合、`start` 関数の呼び出しが失敗する。明示的な事前チェックは実装されていない。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| N/A | - | - | - | 各関数は引数を受け取らない。ポート番号等はモジュール内で定数定義 |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| PROXY_PORT | 定数（1080） | モックサーバーのリスニングポート |
| PROXY_HOST | 定数（'localhost'） | モックサーバーのホスト名 |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| モックサーバープロセス | プロセス | ポート1080でリッスンするHTTPプロキシサーバー |
| retrieveRecordedExpectations戻り値 | JavaScript配列 | フィルタリング済みの記録されたHTTPリクエスト/レスポンス |

### 出力ファイル仕様

本モジュールはファイル出力を行わない。モックサーバーはメモリ上でHTTPリクエスト/レスポンスを管理する。

| 項目 | 内容 |
|-----|------|
| ファイル名 | N/A |
| 出力先 | N/A |
| 文字コード | N/A |
| 区切り文字 | N/A |

## 処理フロー

### 処理シーケンス

```
1. start関数
   └─ mockserver.start_mockserver({ serverPort: 1080 }) でモックサーバーを起動
2. stop関数
   └─ mockserver.stop_mockserver({ serverPort: 1080 }) でモックサーバーを停止
3. retrieveRecordedExpectations関数
   ├─ mockServerClient(localhost, 1080).retrieveRecordedExpectations({}) を呼び出し
   ├─ 3秒のタイムアウト付きPromise.raceで応答を待機
   ├─ タイムアウト時は空配列を返却
   └─ 取得結果をHostヘッダーでフィルタリング
      ├─ api.github.com
      ├─ gitlab.com（/api/v4パス含む）
      ├─ api.bitbucket.org
      ├─ bitbucket.org（/info/lfsパス含む）
      ├─ api.media.atlassian.com
      ├─ *.netlify.com
      ├─ *.netlify.app
      └─ *.s3.amazonaws.com
4. resetMockServerState関数
   └─ mockServerClient(localhost, 1080).reset() で記録状態をリセット
```

### フローチャート

```mermaid
flowchart TD
    A[モジュールロード] --> B[定数定義: PROXY_PORT=1080, PROXY_HOST=localhost]
    B --> C[4つの関数をエクスポート]

    subgraph start
    D[start呼び出し] --> E[mockserver.start_mockserver]
    E --> F[ポート1080でサーバー起動]
    end

    subgraph stop
    G[stop呼び出し] --> H[mockserver.stop_mockserver]
    H --> I[サーバー停止]
    end

    subgraph retrieveRecordedExpectations
    J[関数呼び出し] --> K[mockServerClient.retrieveRecordedExpectations]
    K --> L{3秒以内に応答?}
    L -->|Yes| M[Hostヘッダーでフィルタリング]
    L -->|No| N[空配列を返却]
    M --> O[フィルタ済み結果を返却]
    end

    subgraph resetMockServerState
    P[関数呼び出し] --> Q[mockServerClient.reset]
    Q --> R[状態リセット完了]
    end
```

## データベース操作仕様

### 操作別データベース影響一覧

本モジュールはデータベース操作を行わない。

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| N/A | N/A | N/A | データベース操作なし |

### テーブル別操作詳細

N/A

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| N/A | ポート競合エラー | ポート1080が既に使用されている | 競合するプロセスを停止する |
| N/A | Java不在エラー | Java Runtime Environmentがインストールされていない | JREをインストールする |
| N/A | タイムアウト | retrieveRecordedExpectationsが3秒以内に応答しない | モックサーバーの状態を確認する。console.warnが出力される |
| N/A | 接続エラー | モックサーバーが起動していない状態でclient操作を実行 | 先にstart関数を実行する |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | N/A（リトライ機構なし） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

### 障害時対応

モックサーバーの起動に失敗した場合、ポート1080の使用状況を確認し、競合プロセスを停止する。Java環境が不足している場合はJREをインストールする。retrieveRecordedExpectationsのタイムアウトが頻発する場合、モックサーバーの負荷状態やメモリを確認する。

## トランザクション仕様

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | N/A（テストユーティリティのため該当なし） |
| コミットタイミング | N/A |
| ロールバック条件 | N/A |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | E2Eテスト実行中のAPIリクエスト数に依存 |
| 目標処理時間 | retrieveRecordedExpectations: 3秒以内（タイムアウト設定） |
| メモリ使用量上限 | mockserver-nodeのデフォルト設定に依存（JVMヒープサイズ） |

## 排他制御

ポート1080を単一プロセスで占有するため、同時に複数のモックサーバーを同一ホストで起動できない。E2Eテストは通常単一プロセスで実行されるため、排他制御の追加実装は不要。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 警告ログ | retrieveRecordedExpectationsタイムアウト時 | `retrieveRecordedExpectations timeout`（console.warn） |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| N/A | N/A | テストユーティリティのため監視対象外。E2Eテストの成否で間接的に検知 |

## 備考

- mockserver-nodeはJavaベースのMockServerをNode.jsから操作するラッパーライブラリである
- mockserver-clientはMockServerのREST APIクライアントであり、記録されたexpectationsの取得やリセットに使用される
- フィルタリング対象のHostは以下の通り：
  - `api.github.com` - GitHub API
  - `gitlab.com`（`/api/v4`パス含む） - GitLab API
  - `api.bitbucket.org` - Bitbucket API
  - `bitbucket.org`（`/info/lfs`パス含む） - Bitbucket LFS
  - `api.media.atlassian.com` - Atlassian Media API
  - `*.netlify.com` - Netlify
  - `*.netlify.app` - Netlify App
  - `*.s3.amazonaws.com` - AWS S3
- retrieveRecordedExpectationsのタイムアウトは3秒に設定されており、タイムアウト時は空配列が返却される（テストをブロックしない設計）
- package.jsonの `mock:server:start` / `mock:server:stop` スクリプトで直接このモジュールの `start`/`stop` 関数を呼び出している
