# 機能設計書 28-@jest/environment-jsdom-abstract

## 概要

本ドキュメントは、Jestのjsdom環境の抽象実装（@jest/environment-jsdom-abstract）の機能設計を記述する。このパッケージは、jsdomベースのテスト環境の共通実装を提供する抽象基底クラスである。

### 本機能の処理概要

@jest/environment-jsdom-abstractは、jsdomを使用するJestテスト環境の抽象基底クラスを提供するパッケージである。jest-environment-jsdomはこのクラスを継承し、具体的なjsdomモジュールを注入する。

**業務上の目的・背景**：jsdomベースのテスト環境を実装する際の共通ロジックを抽象化し、異なるjsdomバージョンや実装での再利用を可能にする。jsdomモジュールを外部から注入する設計により、将来的なjsdomバージョンアップや代替実装への対応が容易になる。

**機能の利用シーン**：
- jest-environment-jsdomパッケージの内部実装
- カスタムjsdom環境の実装時の基底クラス
- 異なるjsdomバージョンのサポート

**主要な処理内容**：
1. jsdomモジュールの受け取りとJSDOMインスタンス作成
2. VirtualConsoleの設定（コンソール出力転送）
3. Windowオブジェクトのグローバル設定
4. エラーイベントリスナーの設定とユーザーリスナー追跡
5. フェイクタイマー（Legacy/Modern）の初期化
6. ModuleMockerの初期化

**関連システム・外部連携**：
- jsdom: ブラウザ環境シミュレーション（ピア依存）
- @jest/environment: 環境インターフェース
- @jest/fake-timers: フェイクタイマー
- jest-mock: モック機能

**権限による制御**：この機能に権限による制御は存在しない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本パッケージは内部実装を提供する抽象クラス |

## 機能種別

テスト実行環境 / 抽象基底クラス

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| config | JestEnvironmentConfig | Yes | 環境設定（projectConfig, globalConfig） | - |
| context | EnvironmentContext | Yes | 環境コンテキスト（console, testPath） | - |
| jsdomModule | typeof jsdom | Yes | jsdomモジュール | - |

### 入力データソース

- 継承クラスからのjsdomモジュール注入
- Jest設定ファイル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| global | Win (Window) | jsdomのWindowオブジェクト |
| dom | JSDOM | jsdomインスタンス |
| fakeTimers | LegacyFakeTimers | レガシーフェイクタイマー |
| fakeTimersModern | ModernFakeTimers | モダンフェイクタイマー |
| moduleMocker | ModuleMocker | モジュールモッカー |

### 出力先

- 継承クラス（jest-environment-jsdom等）

## 処理フロー

### 処理シーケンス

```
1. コンストラクタ呼び出し（protected）
   └─ jsdomモジュールから JSDOM, ResourceLoader, VirtualConsole を取得
   └─ VirtualConsoleの設定

2. JSDOMインスタンス作成
   └─ html（testEnvironmentOptions）またはデフォルトHTML
   └─ オプション設定（url, runScripts, pretendToBeVisual等）

3. グローバル設定
   └─ Windowオブジェクトの取得
   └─ Error.stackTraceLimitを100に設定
   └─ installCommonGlobals呼び出し
   └─ Bufferの設定

4. エラーハンドリング設定
   └─ errorEventListenerの設定
   └─ ユーザーリスナー追跡のためaddEventListener/removeEventListenerをラップ

5. モック/タイマーの初期化

6. teardown()
   └─ fakeTimersのdispose
   └─ errorEventListenerの削除
   └─ window.close()
   └─ リソース解放
```

### フローチャート

```mermaid
flowchart TD
    A[継承クラスからコンストラクタ呼び出し] --> B[jsdomモジュール受け取り]
    B --> C[VirtualConsole設定]
    C --> D[JSDOM作成]
    D --> E[Window取得]
    E --> F[グローバル設定]
    F --> G[エラーハンドリング設定]
    G --> H[モック/タイマー初期化]
    H --> I[テスト実行]
    I --> J[teardown]
    J --> K[リソース解放]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-28-01 | デフォルトHTML | testEnvironmentOptions.htmlが未指定の場合、`<!DOCTYPE html>`を使用 | 常時 |
| BR-28-02 | VirtualConsole互換性 | jsdom 27+はforwardTo、jsdom 26はsendToを使用 | VirtualConsole設定時 |
| BR-28-03 | ユーザーリスナー追跡 | ユーザーがerrorリスナーを追加した場合、uncaughtExceptionへの転送を抑制 | エラー発生時 |
| BR-28-04 | customExportConditions | 文字列配列でない場合はエラー | 設定時 |

### 計算ロジック

計算処理は存在しない。

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

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

データベース操作は存在しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | TypeError | VirtualConsoleのforwardTo/sendToメソッドがない場合 | jsdomバージョンを確認 |
| - | Error | JSDOMがWindowオブジェクトを返さない場合 | jsdomの設定を確認 |
| - | Error | customExportConditionsが文字列配列でない場合 | 文字列配列を指定 |

### リトライ仕様

リトライ処理は存在しない。

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

トランザクション処理は存在しない。

## パフォーマンス要件

特になし。継承クラスでの使用を前提とした抽象実装。

## セキュリティ考慮事項

- runScripts: 'dangerously'が設定されるため、信頼できないコードは実行しないこと
- テスト用途のみを想定

## 備考

- 本パッケージは抽象クラスを提供し、直接インスタンス化することはできない
- jsdomはピア依存として定義されている

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | index.ts | `packages/jest-environment-jsdom-abstract/src/index.ts` | Win型、BaseJSDOMEnvironmentクラス |

**読解のコツ**:
- Win型（22-27行目）はWindow + Global.Global + Error.stackTraceLimitを含む拡張型
- BaseJSDOMEnvironment（33行目）はabstract classとして定義

#### Step 2: コンストラクタを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.ts | `packages/jest-environment-jsdom-abstract/src/index.ts` | コンストラクタ（43-172行目） |

**主要処理フロー**:
- **43-47行目**: protected constructorの定義（jsdomモジュールを受け取る）
- **50行目**: jsdomモジュールから必要なクラスを取得
- **52-71行目**: VirtualConsoleの設定
  - **54-59行目**: jsdom 27+のforwardTo対応
  - **60-65行目**: jsdom 26のsendTo対応
  - **66-70行目**: フォールバックエラー
- **77-94行目**: JSDOMインスタンスの作成
  - **78-80行目**: htmlオプションの取得
  - **82行目**: pretendToBeVisual: true
  - **89行目**: runScripts: 'dangerously'
  - **90行目**: url: 'http://localhost/'
- **95-99行目**: Windowオブジェクトの取得と検証
- **102行目**: global.global = globalの設定
- **106行目**: Error.stackTraceLimitを100に設定
- **107行目**: installCommonGlobalsの呼び出し
- **110行目**: Bufferの設定
- **113-140行目**: エラーイベントリスナーの設定
- **142-154行目**: customExportConditionsの設定
- **156-171行目**: モック/タイマーの初期化

#### Step 3: ライフサイクルメソッドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.ts | `packages/jest-environment-jsdom-abstract/src/index.ts` | setup/teardown/getVmContext |

**主要処理フロー**:
- **175行目**: setup() - 空実装
- **177-196行目**: teardown() - リソース解放
  - **178-183行目**: fakeTimersのdispose
  - **184-188行目**: errorEventListenerの削除とwindow.close()
- **198-200行目**: exportConditions() - エクスポート条件取得
- **202-207行目**: getVmContext() - VMコンテキスト取得（dom.getInternalVMContext()）

### プログラム呼び出し階層図

```
jest-environment-jsdom
    │
    └─ @jest/environment-jsdom-abstract
           │
           └─ BaseJSDOMEnvironment (abstract class)
                  │
                  ├─ constructor(config, context, jsdomModule)
                  │      ├─ VirtualConsole設定
                  │      ├─ JSDOM作成
                  │      ├─ installCommonGlobals()
                  │      ├─ エラーリスナー設定
                  │      ├─ ModuleMocker()
                  │      ├─ LegacyFakeTimers()
                  │      └─ ModernFakeTimers()
                  │
                  ├─ setup()
                  ├─ teardown()
                  │      ├─ fakeTimers.dispose()
                  │      └─ window.close()
                  │
                  ├─ getVmContext()
                  └─ exportConditions()
```

### データフロー図

```
[入力]                              [処理]                              [出力]

JestEnvironmentConfig ─────┐
                          │
EnvironmentContext ───────┼──▶ BaseJSDOMEnvironment ──▶ ブラウザ環境
                          │           │
jsdomModule ──────────────┘           ├─▶ JSDOM インスタンス
                                      │      ├─ window
                                      │      ├─ document
                                      │      └─ VirtualConsole
                                      │
                                      ├─▶ ModuleMocker
                                      │
                                      └─▶ FakeTimers
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.ts | `packages/jest-environment-jsdom-abstract/src/index.ts` | ソース | BaseJSDOMEnvironment実装 |
| package.json | `packages/jest-environment-jsdom-abstract/package.json` | 設定 | パッケージ定義 |
