From ec88b9063208b751931217566b7871e5c275f537 Mon Sep 17 00:00:00 2001 From: nrs <38722970+nrslib@users.noreply.github.com> Date: Mon, 9 Feb 2026 23:54:01 +0900 Subject: [PATCH] takt: github-issue-188 (#190) --- README.md | 1 + .../en/instructions/implement-e2e-test.md | 51 ++++ builtins/en/instructions/plan-e2e-test.md | 11 + builtins/en/piece-categories.yaml | 1 + builtins/en/pieces/e2e-test.yaml | 236 ++++++++++++++++++ .../ja/instructions/implement-e2e-test.md | 51 ++++ builtins/ja/instructions/plan-e2e-test.md | 11 + builtins/ja/piece-categories.yaml | 1 + builtins/ja/pieces/e2e-test.yaml | 236 ++++++++++++++++++ docs/README.ja.md | 1 + src/__tests__/config.test.ts | 7 +- src/__tests__/it-piece-loader.test.ts | 37 ++- src/__tests__/piece-category-config.test.ts | 39 ++- 13 files changed, 674 insertions(+), 9 deletions(-) create mode 100644 builtins/en/instructions/implement-e2e-test.md create mode 100644 builtins/en/instructions/plan-e2e-test.md create mode 100644 builtins/en/pieces/e2e-test.yaml create mode 100644 builtins/ja/instructions/implement-e2e-test.md create mode 100644 builtins/ja/instructions/plan-e2e-test.md create mode 100644 builtins/ja/pieces/e2e-test.yaml diff --git a/README.md b/README.md index 602309b..2964cca 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/builtins/en/instructions/implement-e2e-test.md b/builtins/en/instructions/implement-e2e-test.md new file mode 100644 index 0000000..b7f5c3a --- /dev/null +++ b/builtins/en/instructions/implement-e2e-test.md @@ -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} diff --git a/builtins/en/instructions/plan-e2e-test.md b/builtins/en/instructions/plan-e2e-test.md new file mode 100644 index 0000000..94518ee --- /dev/null +++ b/builtins/en/instructions/plan-e2e-test.md @@ -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/.e2e.ts`) +5. Provide concrete guidance for failure analysis → fix → rerun workflow diff --git a/builtins/en/piece-categories.yaml b/builtins/en/piece-categories.yaml index 8d400a6..ad5a5bc 100644 --- a/builtins/en/piece-categories.yaml +++ b/builtins/en/piece-categories.yaml @@ -11,6 +11,7 @@ piece_categories: - review-fix-minimal - review-only - unit-test + - e2e-test 🎨 Frontend: {} ⚙️ Backend: {} 🔧 Expert: diff --git a/builtins/en/pieces/e2e-test.yaml b/builtins/en/pieces/e2e-test.yaml new file mode 100644 index 0000000..eab791d --- /dev/null +++ b/builtins/en/pieces/e2e-test.yaml @@ -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 diff --git a/builtins/ja/instructions/implement-e2e-test.md b/builtins/ja/instructions/implement-e2e-test.md new file mode 100644 index 0000000..fa57076 --- /dev/null +++ b/builtins/ja/instructions/implement-e2e-test.md @@ -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. {決定内容} +- **背景**: {なぜ決定が必要だったか} +- **検討した選択肢**: {選択肢リスト} +- **理由**: {選んだ理由} +``` + +**必須出力(見出しを含める)** +## 作業結果 +- {実施内容の要約} +## 変更内容 +- {変更内容の要約} +## テスト結果 +- {実行コマンドと結果} diff --git a/builtins/ja/instructions/plan-e2e-test.md b/builtins/ja/instructions/plan-e2e-test.md new file mode 100644 index 0000000..57bec6f --- /dev/null +++ b/builtins/ja/instructions/plan-e2e-test.md @@ -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/.e2e.ts`) +5. 実装者向けに、失敗解析→修正→再実行の手順を具体化する diff --git a/builtins/ja/piece-categories.yaml b/builtins/ja/piece-categories.yaml index f1dbf8c..28721f6 100644 --- a/builtins/ja/piece-categories.yaml +++ b/builtins/ja/piece-categories.yaml @@ -11,6 +11,7 @@ piece_categories: - review-fix-minimal - review-only - unit-test + - e2e-test 🎨 フロントエンド: {} ⚙️ バックエンド: {} 🔧 エキスパート: diff --git a/builtins/ja/pieces/e2e-test.yaml b/builtins/ja/pieces/e2e-test.yaml new file mode 100644 index 0000000..1ce0262 --- /dev/null +++ b/builtins/ja/pieces/e2e-test.yaml @@ -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 diff --git a/docs/README.ja.md b/docs/README.ja.md index e492d77..c9b689c 100644 --- a/docs/README.ja.md +++ b/docs/README.ja.md @@ -465,6 +465,7 @@ TAKTには複数のビルトインピースが同梱されています: | `review-only` | 変更を加えない読み取り専用のコードレビューピース。 | | `structural-reform` | プロジェクト全体の構造改革: 段階的なファイル分割を伴う反復的なコードベース再構成。 | | `unit-test` | ユニットテスト重視ピース: テスト分析 → テスト実装 → レビュー → 修正。 | +| `e2e-test` | E2Eテスト重視ピース: E2E分析 → E2E実装 → レビュー → 修正(VitestベースのE2Eフロー)。 | **ペルソナ別プロバイダー設定:** 設定ファイルの `persona_providers` で、特定のペルソナを異なるプロバイダーにルーティングできます(例: coder は Codex、レビュアーは Claude)。ピースを複製する必要はありません。 diff --git a/src/__tests__/config.test.ts b/src/__tests__/config.test.ts index ea73552..e628d92 100644 --- a/src/__tests__/config.test.ts +++ b/src/__tests__/config.test.ts @@ -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', () => { diff --git a/src/__tests__/it-piece-loader.test.ts b/src/__tests__/it-piece-loader.test.ts index 5037bc3..de34adb 100644 --- a/src/__tests__/it-piece-loader.test.ts +++ b/src/__tests__/it-piece-loader.test.ts @@ -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', () => { diff --git a/src/__tests__/piece-category-config.test.ts b/src/__tests__/piece-category-config.test.ts index 9bdc3bc..e89edc4 100644 --- a/src/__tests__/piece-category-config.test.ts +++ b/src/__tests__/piece-category-config.test.ts @@ -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; 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; 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: