#!/usr/bin/env node /** * テスト作成後のチェックフック * * このフックは /create-tests コマンド実行後に自動的に実行され、 * 作成されたテストを実行します。 */ const fs = require('fs'); const path = require('path'); const { execSync } = require('child_process'); // テストを実行 function runTests() { console.log('🧪 テストを実行中...\n'); try { // package.json の存在確認 if (fs.existsSync('package.json')) { const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf-8')); if (packageJson.scripts && packageJson.scripts.test) { const output = execSync('npm test', { encoding: 'utf-8', stdio: 'pipe' }); console.log(output); return { success: true, output }; } } // pytest の確認 if (fs.existsSync('pytest.ini') || fs.existsSync('setup.py')) { const output = execSync('pytest', { encoding: 'utf-8', stdio: 'pipe' }); console.log(output); return { success: true, output }; } console.log('⚠️ テスト実行コマンドが見つかりません'); return { success: false, output: '' }; } catch (error) { // テストが失敗するのは期待通り(TDD) console.log('❌ テストが失敗しました(TDDでは正常)\n'); console.log(error.stdout || error.message); return { success: false, output: error.stdout || error.message, expected: true }; } } // メイン処理 function main() { console.log('🧪 テストを実行中...\n'); console.log('=' .repeat(50)); // テストの実行 const testResult = runTests(); if (testResult.expected) { console.log('\n📝 TDDのフロー:'); console.log(' 1. テストが失敗している(Red) ← 今ここ'); console.log(' 2. /implement を実行して実装する'); console.log(' 3. テストが成功する(Green)'); console.log(' 4. リファクタリング'); } console.log('\n次のステップ: /implement を実行して機能を実装'); // タスク状態の自動更新 updateTaskStatus(3, 'completed'); } // タスク状態を更新する関数 function updateTaskStatus(taskId, status) { const tasksFile = '.tasks.json'; const historyFile = '.tasks-history.json'; if (!fs.existsSync(tasksFile)) { console.log('\n⚠️ タスクファイルが見つかりません。タスク状態は更新されませんでした。'); return; } try { const data = JSON.parse(fs.readFileSync(tasksFile, 'utf-8')); const taskIndex = data.tasks.findIndex(t => t.id === taskId); if (taskIndex === -1) { console.log(`\n⚠️ タスク #${taskId} が見つかりません。`); return; } const task = data.tasks[taskIndex]; task.status = status; task.completedAt = new Date().toISOString(); console.log(`\n📋 タスク #${taskId} (${task.name}) を完了としてマークしました`); // 完了したタスクを履歴に移動 if (status === 'completed') { moveTaskToHistory(data.feature, task, historyFile); // アクティブタスクから削除 data.tasks.splice(taskIndex, 1); data.updatedAt = new Date().toISOString(); } // .tasks.json を更新(完了したタスクは除外される) fs.writeFileSync(tasksFile, JSON.stringify(data, null, 2)); } catch (error) { console.log(`\n⚠️ タスク状態の更新に失敗しました: ${error.message}`); } } // 履歴ファイルの読み込み function loadHistory(historyFile) { if (!fs.existsSync(historyFile)) { return { features: [] }; } return JSON.parse(fs.readFileSync(historyFile, 'utf-8')); } // タスクを履歴に移動 function moveTaskToHistory(featureName, task, historyFile) { const history = loadHistory(historyFile); // 現在の機能を検索(まだ完了していないもの) let currentFeature = history.features.find(f => f.feature === featureName && !f.completedAt); if (!currentFeature) { // 新しい機能エントリを作成 currentFeature = { feature: featureName, createdAt: new Date().toISOString(), tasks: [] }; history.features.push(currentFeature); } // タスクを履歴に追加 currentFeature.tasks.push({ id: task.id, type: task.type, name: task.name, status: task.status, command: task.command, parent: task.parent, dependencies: task.dependencies, createdAt: task.createdAt, startedAt: task.startedAt, completedAt: task.completedAt }); // 履歴ファイルに書き込み fs.writeFileSync(historyFile, JSON.stringify(history, null, 2)); } // エラーハンドリング try { main(); } catch (error) { console.error('❌ チェック中にエラーが発生しました:', error.message); process.exit(1); }