takt: github-issue-188 (#190)
This commit is contained in:
parent
c7305374d7
commit
ec88b90632
@ -465,6 +465,7 @@ TAKT includes multiple builtin pieces:
|
||||
| `review-only` | Read-only code review piece that makes no changes. |
|
||||
| `structural-reform` | Full project review and structural reform: iterative codebase restructuring with staged file splits. |
|
||||
| `unit-test` | Unit test focused piece: test analysis → test implementation → review → fix. |
|
||||
| `e2e-test` | E2E test focused piece: E2E analysis → E2E implementation → review → fix (Vitest-based E2E flow). |
|
||||
|
||||
**Per-persona provider overrides:** Use `persona_providers` in config to route specific personas to different providers (e.g., coder on Codex, reviewers on Claude) without duplicating pieces.
|
||||
|
||||
|
||||
51
builtins/en/instructions/implement-e2e-test.md
Normal file
51
builtins/en/instructions/implement-e2e-test.md
Normal file
@ -0,0 +1,51 @@
|
||||
Implement E2E tests according to the test plan.
|
||||
Refer only to files within the Report Directory shown in the Piece Context. Do not search or reference other report directories.
|
||||
|
||||
**Actions:**
|
||||
1. Review the test plan report
|
||||
2. Implement or update tests following existing E2E layout (e.g., `e2e/specs/`)
|
||||
3. Run E2E tests (minimum: `npm run test:e2e:mock`, and targeted spec runs when needed)
|
||||
4. If tests fail, analyze root cause, fix test or code, and rerun
|
||||
5. Confirm related existing tests are not broken
|
||||
|
||||
**Constraints:**
|
||||
- Keep the current E2E framework (Vitest) unchanged
|
||||
- Keep one scenario per test and make assertions explicit
|
||||
- Reuse existing fixtures/helpers/mock strategy for external dependencies
|
||||
|
||||
**Scope output contract (create at the start of implementation):**
|
||||
```markdown
|
||||
# Change Scope Declaration
|
||||
|
||||
## Task
|
||||
{One-line task summary}
|
||||
|
||||
## Planned changes
|
||||
| Type | File |
|
||||
|------|------|
|
||||
| Create | `e2e/specs/example.e2e.ts` |
|
||||
|
||||
## Estimated size
|
||||
Small / Medium / Large
|
||||
|
||||
## Impact area
|
||||
- {Affected modules or features}
|
||||
```
|
||||
|
||||
**Decisions output contract (at implementation completion, only if decisions were made):**
|
||||
```markdown
|
||||
# Decision Log
|
||||
|
||||
## 1. {Decision}
|
||||
- **Context**: {Why the decision was needed}
|
||||
- **Options considered**: {List of options}
|
||||
- **Rationale**: {Reason for the choice}
|
||||
```
|
||||
|
||||
**Required output (include headings)**
|
||||
## Work results
|
||||
- {Summary of actions taken}
|
||||
## Changes made
|
||||
- {Summary of changes}
|
||||
## Test results
|
||||
- {Command executed and results}
|
||||
11
builtins/en/instructions/plan-e2e-test.md
Normal file
11
builtins/en/instructions/plan-e2e-test.md
Normal file
@ -0,0 +1,11 @@
|
||||
Analyze the target code and identify missing E2E tests.
|
||||
|
||||
**Note:** If a Previous Response exists, this is a replan due to rejection.
|
||||
Revise the test plan taking that feedback into account.
|
||||
|
||||
**Actions:**
|
||||
1. Read target features, implementation, and existing E2E specs (`e2e/specs/**/*.e2e.ts`) to understand behavior
|
||||
2. Summarize current E2E coverage (happy path, failure path, regression points)
|
||||
3. Identify missing E2E scenarios with expected outcomes and observability points
|
||||
4. Specify execution commands (`npm run test:e2e:mock` and, when needed, `npx vitest run e2e/specs/<target>.e2e.ts`)
|
||||
5. Provide concrete guidance for failure analysis → fix → rerun workflow
|
||||
@ -11,6 +11,7 @@ piece_categories:
|
||||
- review-fix-minimal
|
||||
- review-only
|
||||
- unit-test
|
||||
- e2e-test
|
||||
🎨 Frontend: {}
|
||||
⚙️ Backend: {}
|
||||
🔧 Expert:
|
||||
|
||||
236
builtins/en/pieces/e2e-test.yaml
Normal file
236
builtins/en/pieces/e2e-test.yaml
Normal file
@ -0,0 +1,236 @@
|
||||
name: e2e-test
|
||||
description: E2E test focused piece (E2E analysis → E2E implementation → review → fix)
|
||||
max_iterations: 20
|
||||
initial_movement: plan_test
|
||||
loop_monitors:
|
||||
- cycle:
|
||||
- ai_review
|
||||
- ai_fix
|
||||
threshold: 3
|
||||
judge:
|
||||
persona: supervisor
|
||||
instruction_template: |
|
||||
The ai_review ↔ ai_fix loop has repeated {cycle_count} times.
|
||||
|
||||
Review the reports from each cycle and determine whether this loop
|
||||
is healthy (making progress) or unproductive (repeating the same issues).
|
||||
|
||||
**Reports to reference:**
|
||||
- AI Review results: {report:04-ai-review.md}
|
||||
|
||||
**Judgment criteria:**
|
||||
- Are new issues being found/fixed in each cycle?
|
||||
- Are the same findings being repeated?
|
||||
- Are fixes actually being applied?
|
||||
rules:
|
||||
- condition: Healthy (making progress)
|
||||
next: ai_review
|
||||
- condition: Unproductive (no improvement)
|
||||
next: review_test
|
||||
movements:
|
||||
- name: plan_test
|
||||
edit: false
|
||||
persona: test-planner
|
||||
policy: testing
|
||||
knowledge:
|
||||
- architecture
|
||||
- backend
|
||||
allowed_tools:
|
||||
- Read
|
||||
- Glob
|
||||
- Grep
|
||||
- Bash
|
||||
- WebSearch
|
||||
- WebFetch
|
||||
rules:
|
||||
- condition: Test plan complete
|
||||
next: implement_test
|
||||
- condition: User is asking a question (not an E2E test task)
|
||||
next: COMPLETE
|
||||
- condition: Requirements unclear, insufficient info
|
||||
next: ABORT
|
||||
appendix: |
|
||||
Clarifications needed:
|
||||
- {Question 1}
|
||||
- {Question 2}
|
||||
instruction: plan-e2e-test
|
||||
output_contracts:
|
||||
report:
|
||||
- name: 00-test-plan.md
|
||||
format: test-plan
|
||||
|
||||
- name: implement_test
|
||||
edit: true
|
||||
persona: coder
|
||||
policy:
|
||||
- coding
|
||||
- testing
|
||||
session: refresh
|
||||
knowledge:
|
||||
- backend
|
||||
- architecture
|
||||
allowed_tools:
|
||||
- Read
|
||||
- Glob
|
||||
- Grep
|
||||
- Edit
|
||||
- Write
|
||||
- Bash
|
||||
- WebSearch
|
||||
- WebFetch
|
||||
permission_mode: edit
|
||||
rules:
|
||||
- condition: Test implementation complete
|
||||
next: ai_review
|
||||
- condition: No implementation (report only)
|
||||
next: ai_review
|
||||
- condition: Cannot proceed, insufficient info
|
||||
next: ai_review
|
||||
- condition: User input required
|
||||
next: implement_test
|
||||
requires_user_input: true
|
||||
interactive_only: true
|
||||
instruction: implement-e2e-test
|
||||
output_contracts:
|
||||
report:
|
||||
- Scope: 02-coder-scope.md
|
||||
- Decisions: 03-coder-decisions.md
|
||||
|
||||
- name: ai_review
|
||||
edit: false
|
||||
persona: ai-antipattern-reviewer
|
||||
policy:
|
||||
- review
|
||||
- ai-antipattern
|
||||
allowed_tools:
|
||||
- Read
|
||||
- Glob
|
||||
- Grep
|
||||
- WebSearch
|
||||
- WebFetch
|
||||
rules:
|
||||
- condition: No AI-specific issues
|
||||
next: review_test
|
||||
- condition: AI-specific issues found
|
||||
next: ai_fix
|
||||
instruction: ai-review
|
||||
output_contracts:
|
||||
report:
|
||||
- name: 04-ai-review.md
|
||||
format: ai-review
|
||||
|
||||
- name: ai_fix
|
||||
edit: true
|
||||
persona: coder
|
||||
policy:
|
||||
- coding
|
||||
- testing
|
||||
session: refresh
|
||||
knowledge:
|
||||
- backend
|
||||
- architecture
|
||||
allowed_tools:
|
||||
- Read
|
||||
- Glob
|
||||
- Grep
|
||||
- Edit
|
||||
- Write
|
||||
- Bash
|
||||
- WebSearch
|
||||
- WebFetch
|
||||
permission_mode: edit
|
||||
rules:
|
||||
- condition: AI issues fixed
|
||||
next: ai_review
|
||||
- condition: No fix needed (verified target files/spec)
|
||||
next: ai_no_fix
|
||||
- condition: Cannot proceed, insufficient info
|
||||
next: ai_no_fix
|
||||
instruction: ai-fix
|
||||
|
||||
- name: ai_no_fix
|
||||
edit: false
|
||||
persona: architecture-reviewer
|
||||
policy: review
|
||||
allowed_tools:
|
||||
- Read
|
||||
- Glob
|
||||
- Grep
|
||||
rules:
|
||||
- condition: ai_review's findings are valid (fix required)
|
||||
next: ai_fix
|
||||
- condition: ai_fix's judgment is valid (no fix needed)
|
||||
next: review_test
|
||||
instruction: arbitrate
|
||||
|
||||
- name: review_test
|
||||
edit: false
|
||||
persona: qa-reviewer
|
||||
policy:
|
||||
- review
|
||||
- qa
|
||||
allowed_tools:
|
||||
- Read
|
||||
- Glob
|
||||
- Grep
|
||||
- WebSearch
|
||||
- WebFetch
|
||||
rules:
|
||||
- condition: approved
|
||||
next: supervise
|
||||
- condition: needs_fix
|
||||
next: fix
|
||||
instruction: review-test
|
||||
output_contracts:
|
||||
report:
|
||||
- name: 05-qa-review.md
|
||||
format: qa-review
|
||||
|
||||
- name: fix
|
||||
edit: true
|
||||
persona: coder
|
||||
policy:
|
||||
- coding
|
||||
- testing
|
||||
session: refresh
|
||||
knowledge:
|
||||
- backend
|
||||
- architecture
|
||||
allowed_tools:
|
||||
- Read
|
||||
- Glob
|
||||
- Grep
|
||||
- Edit
|
||||
- Write
|
||||
- Bash
|
||||
- WebSearch
|
||||
- WebFetch
|
||||
permission_mode: edit
|
||||
rules:
|
||||
- condition: Fix complete
|
||||
next: review_test
|
||||
- condition: Cannot proceed, insufficient info
|
||||
next: plan_test
|
||||
instruction: fix
|
||||
|
||||
- name: supervise
|
||||
edit: false
|
||||
persona: supervisor
|
||||
policy: review
|
||||
allowed_tools:
|
||||
- Read
|
||||
- Glob
|
||||
- Grep
|
||||
- Bash
|
||||
- WebSearch
|
||||
- WebFetch
|
||||
rules:
|
||||
- condition: All checks passed
|
||||
next: COMPLETE
|
||||
- condition: Requirements unmet, tests failing, build errors
|
||||
next: plan_test
|
||||
instruction: supervise
|
||||
output_contracts:
|
||||
report:
|
||||
- Validation: 06-supervisor-validation.md
|
||||
- Summary: summary.md
|
||||
51
builtins/ja/instructions/implement-e2e-test.md
Normal file
51
builtins/ja/instructions/implement-e2e-test.md
Normal file
@ -0,0 +1,51 @@
|
||||
テスト計画に従ってE2Eテストを実装してください。
|
||||
Piece Contextに示されたReport Directory内のファイルのみ参照してください。他のレポートディレクトリは検索/参照しないでください。
|
||||
|
||||
**やること:**
|
||||
1. テスト計画のレポートを確認する
|
||||
2. `e2e/specs/` など既存E2E配置に従ってテストを実装・更新する
|
||||
3. E2Eテストを実行する(最低: `npm run test:e2e:mock`、必要に応じて対象specの単体実行)
|
||||
4. 失敗時は原因を特定し、テストまたは対象コードを修正して再実行する
|
||||
5. 既存の関連テストが壊れていないことを確認する
|
||||
|
||||
**実装の制約:**
|
||||
- 既存のE2Eフレームワーク(Vitest)を変更しない
|
||||
- テストは1シナリオ1関心で記述し、期待結果を明確にする
|
||||
- 外部依存があるケースは既存のfixture/helper/mock方針に合わせる
|
||||
|
||||
**Scope出力契約(実装開始時に作成):**
|
||||
```markdown
|
||||
# 変更スコープ宣言
|
||||
|
||||
## タスク
|
||||
{タスクの1行要約}
|
||||
|
||||
## 変更予定
|
||||
| 種別 | ファイル |
|
||||
|------|---------|
|
||||
| 作成 | `e2e/specs/example.e2e.ts` |
|
||||
|
||||
## 推定規模
|
||||
Small / Medium / Large
|
||||
|
||||
## 影響範囲
|
||||
- {影響するモジュールや機能}
|
||||
```
|
||||
|
||||
**Decisions出力契約(実装完了時、決定がある場合のみ):**
|
||||
```markdown
|
||||
# 決定ログ
|
||||
|
||||
## 1. {決定内容}
|
||||
- **背景**: {なぜ決定が必要だったか}
|
||||
- **検討した選択肢**: {選択肢リスト}
|
||||
- **理由**: {選んだ理由}
|
||||
```
|
||||
|
||||
**必須出力(見出しを含める)**
|
||||
## 作業結果
|
||||
- {実施内容の要約}
|
||||
## 変更内容
|
||||
- {変更内容の要約}
|
||||
## テスト結果
|
||||
- {実行コマンドと結果}
|
||||
11
builtins/ja/instructions/plan-e2e-test.md
Normal file
11
builtins/ja/instructions/plan-e2e-test.md
Normal file
@ -0,0 +1,11 @@
|
||||
対象コードを分析し、不足しているE2Eテストを洗い出してください。
|
||||
|
||||
**注意:** Previous Responseがある場合は差し戻しのため、
|
||||
その内容を踏まえてテスト計画を見直してください。
|
||||
|
||||
**やること:**
|
||||
1. 対象機能の仕様・実装・既存E2Eテスト(`e2e/specs/**/*.e2e.ts`)を読み、振る舞いを理解する
|
||||
2. 既存E2Eテストのカバー範囲(正常系・異常系・回帰観点)を整理する
|
||||
3. 不足しているE2Eケースを洗い出す(シナリオ、期待結果、失敗時の観測点)
|
||||
4. 実行コマンドを明記する(`npm run test:e2e:mock` / 必要時 `npx vitest run e2e/specs/<target>.e2e.ts`)
|
||||
5. 実装者向けに、失敗解析→修正→再実行の手順を具体化する
|
||||
@ -11,6 +11,7 @@ piece_categories:
|
||||
- review-fix-minimal
|
||||
- review-only
|
||||
- unit-test
|
||||
- e2e-test
|
||||
🎨 フロントエンド: {}
|
||||
⚙️ バックエンド: {}
|
||||
🔧 エキスパート:
|
||||
|
||||
236
builtins/ja/pieces/e2e-test.yaml
Normal file
236
builtins/ja/pieces/e2e-test.yaml
Normal file
@ -0,0 +1,236 @@
|
||||
name: e2e-test
|
||||
description: E2Eテスト追加に特化したピース(E2E分析→E2E実装→レビュー→修正)
|
||||
max_iterations: 20
|
||||
initial_movement: plan_test
|
||||
loop_monitors:
|
||||
- cycle:
|
||||
- ai_review
|
||||
- ai_fix
|
||||
threshold: 3
|
||||
judge:
|
||||
persona: supervisor
|
||||
instruction_template: |
|
||||
ai_review と ai_fix のループが {cycle_count} 回繰り返されました。
|
||||
|
||||
各サイクルのレポートを確認し、このループが健全(進捗がある)か、
|
||||
非生産的(同じ問題を繰り返している)かを判断してください。
|
||||
|
||||
**参照するレポート:**
|
||||
- AIレビュー結果: {report:04-ai-review.md}
|
||||
|
||||
**判断基準:**
|
||||
- 各サイクルで新しい問題が発見・修正されているか
|
||||
- 同じ指摘が繰り返されていないか
|
||||
- 修正が実際に反映されているか
|
||||
rules:
|
||||
- condition: 健全(進捗あり)
|
||||
next: ai_review
|
||||
- condition: 非生産的(改善なし)
|
||||
next: review_test
|
||||
movements:
|
||||
- name: plan_test
|
||||
edit: false
|
||||
persona: test-planner
|
||||
policy: testing
|
||||
knowledge:
|
||||
- architecture
|
||||
- backend
|
||||
allowed_tools:
|
||||
- Read
|
||||
- Glob
|
||||
- Grep
|
||||
- Bash
|
||||
- WebSearch
|
||||
- WebFetch
|
||||
rules:
|
||||
- condition: テスト計画が完了
|
||||
next: implement_test
|
||||
- condition: ユーザーが質問をしている(E2Eテスト追加タスクではない)
|
||||
next: COMPLETE
|
||||
- condition: 要件が不明確、情報不足
|
||||
next: ABORT
|
||||
appendix: |
|
||||
確認事項:
|
||||
- {質問1}
|
||||
- {質問2}
|
||||
instruction: plan-e2e-test
|
||||
output_contracts:
|
||||
report:
|
||||
- name: 00-test-plan.md
|
||||
format: test-plan
|
||||
|
||||
- name: implement_test
|
||||
edit: true
|
||||
persona: coder
|
||||
policy:
|
||||
- coding
|
||||
- testing
|
||||
session: refresh
|
||||
knowledge:
|
||||
- backend
|
||||
- architecture
|
||||
allowed_tools:
|
||||
- Read
|
||||
- Glob
|
||||
- Grep
|
||||
- Edit
|
||||
- Write
|
||||
- Bash
|
||||
- WebSearch
|
||||
- WebFetch
|
||||
permission_mode: edit
|
||||
rules:
|
||||
- condition: テスト実装完了
|
||||
next: ai_review
|
||||
- condition: 実装未着手(レポートのみ)
|
||||
next: ai_review
|
||||
- condition: 判断できない、情報不足
|
||||
next: ai_review
|
||||
- condition: ユーザー入力が必要
|
||||
next: implement_test
|
||||
requires_user_input: true
|
||||
interactive_only: true
|
||||
instruction: implement-e2e-test
|
||||
output_contracts:
|
||||
report:
|
||||
- Scope: 02-coder-scope.md
|
||||
- Decisions: 03-coder-decisions.md
|
||||
|
||||
- name: ai_review
|
||||
edit: false
|
||||
persona: ai-antipattern-reviewer
|
||||
policy:
|
||||
- review
|
||||
- ai-antipattern
|
||||
allowed_tools:
|
||||
- Read
|
||||
- Glob
|
||||
- Grep
|
||||
- WebSearch
|
||||
- WebFetch
|
||||
rules:
|
||||
- condition: AI特有の問題なし
|
||||
next: review_test
|
||||
- condition: AI特有の問題あり
|
||||
next: ai_fix
|
||||
instruction: ai-review
|
||||
output_contracts:
|
||||
report:
|
||||
- name: 04-ai-review.md
|
||||
format: ai-review
|
||||
|
||||
- name: ai_fix
|
||||
edit: true
|
||||
persona: coder
|
||||
policy:
|
||||
- coding
|
||||
- testing
|
||||
session: refresh
|
||||
knowledge:
|
||||
- backend
|
||||
- architecture
|
||||
allowed_tools:
|
||||
- Read
|
||||
- Glob
|
||||
- Grep
|
||||
- Edit
|
||||
- Write
|
||||
- Bash
|
||||
- WebSearch
|
||||
- WebFetch
|
||||
permission_mode: edit
|
||||
rules:
|
||||
- condition: AI問題の修正完了
|
||||
next: ai_review
|
||||
- condition: 修正不要(指摘対象ファイル/仕様の確認済み)
|
||||
next: ai_no_fix
|
||||
- condition: 判断できない、情報不足
|
||||
next: ai_no_fix
|
||||
instruction: ai-fix
|
||||
|
||||
- name: ai_no_fix
|
||||
edit: false
|
||||
persona: architecture-reviewer
|
||||
policy: review
|
||||
allowed_tools:
|
||||
- Read
|
||||
- Glob
|
||||
- Grep
|
||||
rules:
|
||||
- condition: ai_reviewの指摘が妥当(修正すべき)
|
||||
next: ai_fix
|
||||
- condition: ai_fixの判断が妥当(修正不要)
|
||||
next: review_test
|
||||
instruction: arbitrate
|
||||
|
||||
- name: review_test
|
||||
edit: false
|
||||
persona: qa-reviewer
|
||||
policy:
|
||||
- review
|
||||
- qa
|
||||
allowed_tools:
|
||||
- Read
|
||||
- Glob
|
||||
- Grep
|
||||
- WebSearch
|
||||
- WebFetch
|
||||
rules:
|
||||
- condition: approved
|
||||
next: supervise
|
||||
- condition: needs_fix
|
||||
next: fix
|
||||
instruction: review-test
|
||||
output_contracts:
|
||||
report:
|
||||
- name: 05-qa-review.md
|
||||
format: qa-review
|
||||
|
||||
- name: fix
|
||||
edit: true
|
||||
persona: coder
|
||||
policy:
|
||||
- coding
|
||||
- testing
|
||||
session: refresh
|
||||
knowledge:
|
||||
- backend
|
||||
- architecture
|
||||
allowed_tools:
|
||||
- Read
|
||||
- Glob
|
||||
- Grep
|
||||
- Edit
|
||||
- Write
|
||||
- Bash
|
||||
- WebSearch
|
||||
- WebFetch
|
||||
permission_mode: edit
|
||||
rules:
|
||||
- condition: 修正完了
|
||||
next: review_test
|
||||
- condition: 判断できない、情報不足
|
||||
next: plan_test
|
||||
instruction: fix
|
||||
|
||||
- name: supervise
|
||||
edit: false
|
||||
persona: supervisor
|
||||
policy: review
|
||||
allowed_tools:
|
||||
- Read
|
||||
- Glob
|
||||
- Grep
|
||||
- Bash
|
||||
- WebSearch
|
||||
- WebFetch
|
||||
rules:
|
||||
- condition: すべて問題なし
|
||||
next: COMPLETE
|
||||
- condition: 要求未達成、テスト失敗、ビルドエラー
|
||||
next: plan_test
|
||||
instruction: supervise
|
||||
output_contracts:
|
||||
report:
|
||||
- Validation: 06-supervisor-validation.md
|
||||
- Summary: summary.md
|
||||
@ -465,6 +465,7 @@ TAKTには複数のビルトインピースが同梱されています:
|
||||
| `review-only` | 変更を加えない読み取り専用のコードレビューピース。 |
|
||||
| `structural-reform` | プロジェクト全体の構造改革: 段階的なファイル分割を伴う反復的なコードベース再構成。 |
|
||||
| `unit-test` | ユニットテスト重視ピース: テスト分析 → テスト実装 → レビュー → 修正。 |
|
||||
| `e2e-test` | E2Eテスト重視ピース: E2E分析 → E2E実装 → レビュー → 修正(VitestベースのE2Eフロー)。 |
|
||||
|
||||
**ペルソナ別プロバイダー設定:** 設定ファイルの `persona_providers` で、特定のペルソナを異なるプロバイダーにルーティングできます(例: coder は Codex、レビュアーは Claude)。ピースを複製する必要はありません。
|
||||
|
||||
|
||||
@ -217,7 +217,7 @@ describe('loadPiece (builtin fallback)', () => {
|
||||
expect(piece).toBeNull();
|
||||
});
|
||||
|
||||
it('should load builtin pieces like minimal, research', () => {
|
||||
it('should load builtin pieces like minimal, research, e2e-test', () => {
|
||||
const minimal = loadPiece('minimal', process.cwd());
|
||||
expect(minimal).not.toBeNull();
|
||||
expect(minimal!.name).toBe('minimal');
|
||||
@ -225,6 +225,10 @@ describe('loadPiece (builtin fallback)', () => {
|
||||
const research = loadPiece('research', process.cwd());
|
||||
expect(research).not.toBeNull();
|
||||
expect(research!.name).toBe('research');
|
||||
|
||||
const e2eTest = loadPiece('e2e-test', process.cwd());
|
||||
expect(e2eTest).not.toBeNull();
|
||||
expect(e2eTest!.name).toBe('e2e-test');
|
||||
});
|
||||
});
|
||||
|
||||
@ -246,6 +250,7 @@ describe('listPieces (builtin fallback)', () => {
|
||||
const pieces = listPieces(testDir);
|
||||
expect(pieces).toContain('default');
|
||||
expect(pieces).toContain('minimal');
|
||||
expect(pieces).toContain('e2e-test');
|
||||
});
|
||||
|
||||
it('should return sorted list', () => {
|
||||
|
||||
@ -14,10 +14,11 @@ import { join } from 'node:path';
|
||||
import { tmpdir } from 'node:os';
|
||||
|
||||
// --- Mocks ---
|
||||
const languageState = vi.hoisted(() => ({ value: 'en' as 'en' | 'ja' }));
|
||||
|
||||
vi.mock('../infra/config/global/globalConfig.js', () => ({
|
||||
loadGlobalConfig: vi.fn().mockReturnValue({}),
|
||||
getLanguage: vi.fn().mockReturnValue('en'),
|
||||
getLanguage: vi.fn(() => languageState.value),
|
||||
getDisabledBuiltins: vi.fn().mockReturnValue([]),
|
||||
getBuiltinPiecesEnabled: vi.fn().mockReturnValue(true),
|
||||
}));
|
||||
@ -40,6 +41,7 @@ describe('Piece Loader IT: builtin piece loading', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
testDir = createTestDir();
|
||||
languageState.value = 'en';
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@ -64,6 +66,39 @@ describe('Piece Loader IT: builtin piece loading', () => {
|
||||
const config = loadPiece('non-existent-piece-xyz', testDir);
|
||||
expect(config).toBeNull();
|
||||
});
|
||||
|
||||
it('should include and load e2e-test as a builtin piece', () => {
|
||||
expect(builtinNames).toContain('e2e-test');
|
||||
|
||||
const config = loadPiece('e2e-test', testDir);
|
||||
expect(config).not.toBeNull();
|
||||
|
||||
const planMovement = config!.movements.find((movement) => movement.name === 'plan_test');
|
||||
const implementMovement = config!.movements.find((movement) => movement.name === 'implement_test');
|
||||
|
||||
expect(planMovement).toBeDefined();
|
||||
expect(implementMovement).toBeDefined();
|
||||
expect(planMovement!.instructionTemplate).toContain('missing E2E tests');
|
||||
expect(implementMovement!.instructionTemplate).toContain('npm run test:e2e:mock');
|
||||
});
|
||||
|
||||
it('should load e2e-test as a builtin piece in ja locale', () => {
|
||||
languageState.value = 'ja';
|
||||
|
||||
const jaBuiltinNames = listBuiltinPieceNames({ includeDisabled: true });
|
||||
expect(jaBuiltinNames).toContain('e2e-test');
|
||||
|
||||
const config = loadPiece('e2e-test', testDir);
|
||||
expect(config).not.toBeNull();
|
||||
|
||||
const planMovement = config!.movements.find((movement) => movement.name === 'plan_test');
|
||||
const implementMovement = config!.movements.find((movement) => movement.name === 'implement_test');
|
||||
|
||||
expect(planMovement).toBeDefined();
|
||||
expect(implementMovement).toBeDefined();
|
||||
expect(planMovement!.instructionTemplate).toContain('E2Eテスト');
|
||||
expect(implementMovement!.instructionTemplate).toContain('npm run test:e2e:mock');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Piece Loader IT: project-local piece override', () => {
|
||||
|
||||
@ -9,8 +9,12 @@ import { tmpdir } from 'node:os';
|
||||
import { randomUUID } from 'node:crypto';
|
||||
import type { PieceWithSource } from '../infra/config/index.js';
|
||||
|
||||
const languageState = vi.hoisted(() => ({
|
||||
value: 'en' as 'en' | 'ja',
|
||||
}));
|
||||
|
||||
const pathsState = vi.hoisted(() => ({
|
||||
resourcesDir: '',
|
||||
resourcesRoot: '',
|
||||
userCategoriesPath: '',
|
||||
}));
|
||||
|
||||
@ -18,7 +22,7 @@ vi.mock('../infra/config/global/globalConfig.js', async (importOriginal) => {
|
||||
const original = await importOriginal() as Record<string, unknown>;
|
||||
return {
|
||||
...original,
|
||||
getLanguage: () => 'en',
|
||||
getLanguage: () => languageState.value,
|
||||
getBuiltinPiecesEnabled: () => true,
|
||||
getDisabledBuiltins: () => [],
|
||||
};
|
||||
@ -28,7 +32,7 @@ vi.mock('../infra/resources/index.js', async (importOriginal) => {
|
||||
const original = await importOriginal() as Record<string, unknown>;
|
||||
return {
|
||||
...original,
|
||||
getLanguageResourcesDir: () => pathsState.resourcesDir,
|
||||
getLanguageResourcesDir: (lang: string) => join(pathsState.resourcesRoot, lang),
|
||||
};
|
||||
});
|
||||
|
||||
@ -74,10 +78,12 @@ describe('piece category config loading', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
testDir = join(tmpdir(), `takt-cat-config-${randomUUID()}`);
|
||||
resourcesDir = join(testDir, 'resources');
|
||||
resourcesDir = join(testDir, 'resources', 'en');
|
||||
|
||||
mkdirSync(resourcesDir, { recursive: true });
|
||||
pathsState.resourcesDir = resourcesDir;
|
||||
mkdirSync(join(testDir, 'resources', 'ja'), { recursive: true });
|
||||
pathsState.resourcesRoot = join(testDir, 'resources');
|
||||
languageState.value = 'en';
|
||||
pathsState.userCategoriesPath = join(testDir, 'user-piece-categories.yaml');
|
||||
});
|
||||
|
||||
@ -142,6 +148,7 @@ piece_categories:
|
||||
Review:
|
||||
pieces:
|
||||
- review-only
|
||||
- e2e-test
|
||||
show_others_category: true
|
||||
others_category_name: Others
|
||||
`);
|
||||
@ -168,7 +175,7 @@ others_category_name: Unclassified
|
||||
{ name: 'Child', pieces: ['nested'], children: [] },
|
||||
],
|
||||
},
|
||||
{ name: 'Review', pieces: ['review-only'], children: [] },
|
||||
{ name: 'Review', pieces: ['review-only', 'e2e-test'], children: [] },
|
||||
{ name: 'My Team', pieces: ['team-flow'], children: [] },
|
||||
]);
|
||||
expect(config!.builtinPieceCategories).toEqual([
|
||||
@ -179,7 +186,7 @@ others_category_name: Unclassified
|
||||
{ name: 'Child', pieces: ['nested'], children: [] },
|
||||
],
|
||||
},
|
||||
{ name: 'Review', pieces: ['review-only'], children: [] },
|
||||
{ name: 'Review', pieces: ['review-only', 'e2e-test'], children: [] },
|
||||
]);
|
||||
expect(config!.userPieceCategories).toEqual([
|
||||
{ name: 'Main', pieces: ['custom'], children: [] },
|
||||
@ -189,6 +196,24 @@ others_category_name: Unclassified
|
||||
expect(config!.othersCategoryName).toBe('Unclassified');
|
||||
});
|
||||
|
||||
it('should load ja builtin categories and include e2e-test under レビュー', () => {
|
||||
languageState.value = 'ja';
|
||||
|
||||
writeYaml(join(testDir, 'resources', 'ja', 'piece-categories.yaml'), `
|
||||
piece_categories:
|
||||
レビュー:
|
||||
pieces:
|
||||
- review-only
|
||||
- e2e-test
|
||||
`);
|
||||
|
||||
const config = getPieceCategories();
|
||||
expect(config).not.toBeNull();
|
||||
expect(config!.pieceCategories).toEqual([
|
||||
{ name: 'レビュー', pieces: ['review-only', 'e2e-test'], children: [] },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should override others settings without replacing categories when user overlay has no piece_categories', () => {
|
||||
writeYaml(join(resourcesDir, 'piece-categories.yaml'), `
|
||||
piece_categories:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user