# 機能設計書 46-jest-message-util

## 概要

本ドキュメントは、jest-message-utilパッケージの機能設計について記載する。jest-message-utilは、エラーメッセージとスタックトレースの整形機能を提供するパッケージである。

### 本機能の処理概要

jest-message-utilは、テスト実行時のエラーメッセージを見やすく整形し、スタックトレースを開発者フレンドリーな形式で表示する。コードフレーム（エラー発生箇所のソースコード表示）、色付け、不要なスタックエントリの除去などの機能を提供する。

**業務上の目的・背景**：テスト失敗時のエラーメッセージは、問題の特定と修正に不可欠である。しかし、生のスタックトレースは冗長で読みにくい場合が多い。jest-message-utilは、Jestの内部スタック、Node.jsの内部スタック、匿名関数などのノイズを除去し、テストファイルのパスをハイライトすることで、開発者が素早く問題箇所を特定できるようにする。

**機能の利用シーン**：テスト失敗時のエラー表示、テストスイート実行エラーの表示、コンソール出力の整形など、テスト結果の表示全般で使用される。@jest/reportersパッケージと連携してテスト結果を整形する。

**主要な処理内容**：
1. formatExecError: テストスイート実行エラーの整形
2. formatResultsErrors: テスト結果のエラー整形
3. formatStackTrace: スタックトレースの整形とコードフレーム表示
4. separateMessageFromStack: エラーメッセージとスタックの分離
5. getTopFrame: スタックトレースから最上位フレームを取得

**関連システム・外部連携**：@babel/code-frame（コードフレーム表示）、chalk（色付け）、stack-utils（スタック解析）、picomatch（パターンマッチング）を使用。

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | CLIのみで使用される機能のため関連画面なし |

## 機能種別

メッセージ整形 / スタックトレース処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| error | Error \| SerializableError \| string | Yes | エラーオブジェクトまたはメッセージ | - |
| config | StackTraceConfig | Yes | 設定（rootDir, testMatch） | - |
| options | StackTraceOptions | Yes | オプション（noStackTrace, noCodeFrame） | - |
| testPath | string | No | テストファイルパス | - |

### 入力データソース

- エラーオブジェクト
- テスト結果（AssertionResult）
- Jest設定

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| formattedError | string | 整形されたエラーメッセージ |
| frame | Frame \| null | 最上位スタックフレーム |

### 出力先

- コンソール出力用の文字列

## 処理フロー

### 処理シーケンス

```
1. エラー受け取り
   └─ error、config、options、testPathを受け取る
2. メッセージとスタック分離
   └─ separateMessageFromStackでエラーメッセージとスタックを分離
3. 環境エラーチェック
   └─ document/window/navigatorの参照エラーを検出
4. スタックトレース整形
   └─ formatStackTraceで整形
5. 内部スタック除去
   └─ Jest内部、Node内部、匿名関数のスタックを除去
6. コードフレーム生成
   └─ getTopFrameで最上位フレームを取得し、コードフレームを表示
7. パス整形
   └─ formatPathでパスを相対化し、テストファイルをハイライト
8. 結果返却
   └─ 整形されたメッセージを返却
```

### フローチャート

```mermaid
flowchart TD
    A[エラー受け取り] --> B[separateMessageFromStack]
    B --> C[環境エラーチェック]
    C --> D{jsdom/node環境エラー?}
    D -->|Yes| E[警告メッセージ追加]
    D -->|No| F[スタックトレース処理]
    E --> F
    F --> G[getStackTraceLines]
    G --> H[removeInternalStackEntries]
    H --> I{noStackTrace?}
    I -->|Yes| J[スタック非表示]
    I -->|No| K[getTopFrame]
    K --> L{noCodeFrame?}
    L -->|No| M[codeFrameColumns生成]
    L -->|Yes| N[formatPath]
    M --> N
    J --> O[結果返却]
    N --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-46-01 | 最初のスタック保持 | Jest内部スタックでも最初の1行は保持 | 常時 |
| BR-46-02 | 環境エラー警告 | document/window/navigator参照エラーにはjsdom環境を推奨 | 該当エラー検出時 |
| BR-46-03 | .unrefエラー警告 | .unrefエラーにはnode環境を推奨 | 該当エラー検出時 |
| BR-46-04 | テストファイルハイライト | testMatchパターンまたはtestPathに一致するパスをシアン色でハイライト | パスフォーマット時 |

### 計算ロジック

スタックフィルタリングルール:
```
除去対象:
- JASMINE_IGNORE: /^\s+at(?:(?:.jasmine-)|\s+jasmine\.buildExpectationResult)/
- JEST_INTERNALS_IGNORE: /^\s+at.*?jest(-.*?)?(\/|\\)(build|node_modules|packages)(\/|\\)/
- ANONYMOUS_FN_IGNORE: /^\s+at <anonymous>.*$/
- ANONYMOUS_PROMISE_IGNORE: /^\s+at (new )?Promise \(<anonymous>\).*$/
- ANONYMOUS_GENERATOR_IGNORE: /^\s+at Generator.next \(<anonymous>\).*$/
- NATIVE_NEXT_IGNORE: /^\s+at next \(native\).*$/
- nodeInternals: StackUtils.nodeInternals()
```

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

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

該当なし（データベース操作は行わない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | フォールバック | ファイル読み込み失敗 | コードフレームを表示しない |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- メッセージ整形: ミリ秒単位

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

- ファイルシステムからソースコードを読み込むため、テストファイルパスのみを使用

## 備考

- インデント: TITLE_INDENT = '  ', MESSAGE_INDENT = '    ', STACK_INDENT = '      '
- 行長制限80文字推奨

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | types.ts | `packages/jest-message-util/src/types.ts` | Frame型の定義 |

**読解のコツ**: FrameはStackDataを拡張し、file: stringを必須としている。

#### Step 2: 定数と設定を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.ts | `packages/jest-message-util/src/index.ts` | 定数定義（47-65行目） |

**主要処理フロー**:
- **49-56行目**: フィルタリング用の正規表現定義
- **57-62行目**: インデント定数（TITLE_INDENT、MESSAGE_INDENT、STACK_INDENT）
- **63-65行目**: 色とスタイル定数

#### Step 3: separateMessageFromStackを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.ts | `packages/jest-message-util/src/index.ts` | メッセージ分離ロジック（521-542行目） |

**主要処理フロー**:
- **532-534行目**: 正規表現でメッセージとスタックを分離
- **539-541行目**: それぞれからブランク行を削除して返却

#### Step 4: formatStackTraceを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | index.ts | `packages/jest-message-util/src/index.ts` | スタック整形（344-387行目） |

**主要処理フロー**:
- **350行目**: getStackTraceLinesでスタック行を取得
- **356-373行目**: getTopFrameでコードフレーム用の位置を取得
- **375-384行目**: formatPathでパスを整形

#### Step 5: formatExecError/formatResultsErrorsを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | index.ts | `packages/jest-message-util/src/index.ts` | エラー整形（125-236, 465-506行目） |

**主要処理フロー**:
- **formatExecError (125-236行目)**: テストスイート実行エラーの整形
- **formatResultsErrors (465-506行目)**: テスト結果エラーの整形
- **152-175行目**: causeチェーンの再帰処理
- **176-189行目**: AggregateErrorのerrorsの処理

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

```
formatExecError(error, config, options, testPath)
    │
    ├─ separateMessageFromStack(stack)
    │      └─ messageMatch正規表現
    │
    ├─ checkForCommonEnvironmentErrors(message)
    │      └─ warnAboutWrongTestEnvironment()
    │
    └─ formatStackTrace(stack, config, options, testPath)
           │
           ├─ getStackTraceLines(stack, options)
           │      └─ removeInternalStackEntries(lines, options)
           │
           ├─ getTopFrame(lines)
           │      └─ stackUtils.parseLine()
           │
           ├─ getRenderedCallsite(fileContent, line, column)
           │      └─ codeFrameColumns()
           │
           └─ formatPath(line, config, relativeTestPath)
                  └─ picomatch(config.testMatch)
```

### データフロー図

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

Error ───────────────────▶ separateMessageFromStack ───▶ {message, stack}
                              │
                              ▼
                         checkForCommonEnvironmentErrors
                              │
                              ▼
                         formatStackTrace
                              │
                              ├─ removeInternalStackEntries
                              │
                              ├─ getTopFrame
                              │      └─ codeFrameColumns
                              │
                              └─ formatPath
                                     │
                                     ▼
                         整形済みメッセージ ─────────────▶ string
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.ts | `packages/jest-message-util/src/index.ts` | ソース | メイン処理 |
| types.ts | `packages/jest-message-util/src/types.ts` | ソース | 型定義 |
| __tests__/messages.test.ts | `packages/jest-message-util/src/__tests__/messages.test.ts` | テスト | ユニットテスト |
