diff --git a/tests/index.test.js b/tests/index.test.js index 74cc983..8d2e3c7 100644 --- a/tests/index.test.js +++ b/tests/index.test.js @@ -11,14 +11,21 @@ import * as gitGptCommit from '../index.js' describe('Git GPT Commit', () => { let tempDir + let originalDir beforeEach(() => { + // Store original directory + originalDir = process.cwd() + // Set up a new test environment before each test tempDir = setupTestRepo() vi.clearAllMocks() }) afterEach(() => { + // Change back to original directory before cleaning up + process.chdir(originalDir) + // Clean up the test environment after each test cleanupTestRepo(tempDir) vi.clearAllMocks() diff --git a/tests/setup-mocks.js b/tests/setup-mocks.js index 4c99e69..1dc7f2f 100644 --- a/tests/setup-mocks.js +++ b/tests/setup-mocks.js @@ -21,12 +21,12 @@ vi.mock('openai', () => { } }) -// index.jsモジュール全体をモック +// Mock the entire index.js module vi.mock('../index.js', () => { return { getGitSummary: vi.fn((options) => { try { - // 実際のdiffコマンドを実行せず、ファイルの変更があるかチェック + // Check if there are file changes without actually executing the diff command const gitStatus = require('child_process') .execSync('git status --porcelain') .toString() @@ -35,8 +35,8 @@ vi.mock('../index.js', () => { throw new Error('No changes to commit') } - // モックされたdiffの内容を返す - return `diff --git a/file1.js b/file1.js\nindex 123456..789012 100644\n--- a/file1.js\n+++ b/file1.js\n@@ -1,5 +1,8 @@\nfunction greet(name) {\n- return \`Hello, \${name}!\`;\n+ // 名前が空の場合のデフォルト値を追加\n+ const userName = name || 'Guest';\n+ return \`Hello, \${userName}!\`;\n }` + // Return mocked diff content + return `diff --git a/file1.js b/file1.js\nindex 123456..789012 100644\n--- a/file1.js\n+++ b/file1.js\n@@ -1,5 +1,8 @@\nfunction greet(name) {\n- return \`Hello, \${name}!\`;\n+ // Add default value when name is empty\n+ const userName = name || 'Guest';\n+ return \`Hello, \${userName}!\`;\n }` } catch (error) { throw new Error('Failed to get git summary') } @@ -45,40 +45,40 @@ vi.mock('../index.js', () => { return 'Mock commit message' }), gitExtension: vi.fn(), - // その他必要な関数やオブジェクト + // Other necessary functions or objects } }) -// fs モジュールをモック +// Mock fs module vi.mock('fs', async () => { const actual = await vi.importActual('fs') return { ...actual, existsSync: vi.fn((path) => { - // 特定のパスのみモックレスポンスを返す + // Return mock response only for specific paths if (path.includes('.git-gpt-commit-config.json')) { return true } - // それ以外は実際の実装を使用 + // Use actual implementation for others return actual.existsSync(path) }), readFileSync: vi.fn((path, options) => { - // コンフィグファイルの場合、モックデータを返す + // Return mock data for config file if (path.includes('.git-gpt-commit-config.json')) { return JSON.stringify({ model: 'gpt-4o', language: 'English', }) } - // それ以外は実際の実装を使用 + // Use actual implementation for others return actual.readFileSync(path, options) }), writeFileSync: vi.fn(), } }) -// commanderをモック +// Mock commander vi.mock('commander', () => { const mockProgram = { command: vi.fn().mockReturnThis(), @@ -95,7 +95,7 @@ vi.mock('commander', () => { } }) -// child_processをモック +// Mock child_process vi.mock('child_process', async () => { const actual = await vi.importActual('child_process') @@ -103,24 +103,24 @@ vi.mock('child_process', async () => { ...actual, execSync: vi.fn((command) => { if (typeof command === 'string') { - // git statusコマンドの場合は変更があるとみなす + // Treat as having changes for git status commands if (command.includes('git status')) { return Buffer.from('M file1.js') } - // git commitコマンドの場合はモック応答 + // Mock response for git commit commands if (command.includes('git commit')) { return Buffer.from('Commit successful') } } - // その他のコマンドは実際に実行 + // Actually execute other commands return actual.execSync(command) }), exec: vi.fn((command, callback) => { if (command.includes('git diff')) { const stdout = - "diff --git a/file1.js b/file1.js\nindex 123456..789012 100644\n--- a/file1.js\n+++ b/file1.js\n@@ -1,5 +1,8 @@\nfunction greet(name) {\n- return `Hello, ${name}!`;\n+ // 名前が空の場合のデフォルト値を追加\n+ const userName = name || 'Guest';\n+ return `Hello, ${userName}!`;\n }" + "diff --git a/file1.js b/file1.js\nindex 123456..789012 100644\n--- a/file1.js\n+++ b/file1.js\n@@ -1,5 +1,8 @@\nfunction greet(name) {\n- return \`Hello, \${name}!\`;\n+ // Add default value when name is empty\n+ const userName = name || 'Guest';\n+ return \`Hello, \${userName}!\`;\n }" callback(null, { stdout }) } else { callback(null, { stdout: '' }) @@ -129,12 +129,12 @@ vi.mock('child_process', async () => { } }) -// promptsモジュールをモック +// Mock prompts module vi.mock('prompts', () => ({ default: vi.fn().mockResolvedValue({ value: true }), })) -// process.exitをモック +// Mock process.exit vi.stubGlobal('process', { ...process, exit: vi.fn((code) => { diff --git a/tests/setup.js b/tests/setup.js index ee1f000..1aaa754 100644 --- a/tests/setup.js +++ b/tests/setup.js @@ -17,10 +17,51 @@ if (fs.existsSync(testEnvPath)) { * @returns {string} Path to the created temporary directory */ export function setupTestRepo() { + // Find the project root to access fixtures + let projectRoot = process.cwd() + let currentPath = projectRoot + while (!fs.existsSync(path.join(currentPath, 'package.json'))) { + const parentPath = path.dirname(currentPath) + if (parentPath === currentPath) break + currentPath = parentPath + } + if (fs.existsSync(path.join(currentPath, 'package.json'))) { + projectRoot = currentPath + } + // Create a temporary directory const tempDir = path.join(os.tmpdir(), `git-gpt-commit-test-${Date.now()}`) fs.mkdirSync(tempDir, { recursive: true }) + // Create fixtures directory in the temp directory + const fixturesDir = path.join(tempDir, 'fixtures') + fs.mkdirSync(fixturesDir, { recursive: true }) + + // Copy fixture files from original project to test directory + const sourceFixturesDir = path.join(projectRoot, 'fixtures') + if (fs.existsSync(sourceFixturesDir)) { + const files = fs.readdirSync(sourceFixturesDir) + files.forEach((file) => { + const sourcePath = path.join(sourceFixturesDir, file) + const destPath = path.join(fixturesDir, file) + + if (fs.statSync(sourcePath).isFile()) { + fs.copyFileSync(sourcePath, destPath) + } else if (fs.statSync(sourcePath).isDirectory()) { + // Handle subdirectories like 'expected' + fs.mkdirSync(destPath, { recursive: true }) + const subFiles = fs.readdirSync(sourcePath) + subFiles.forEach((subFile) => { + const subSourcePath = path.join(sourcePath, subFile) + const subDestPath = path.join(destPath, subFile) + if (fs.statSync(subSourcePath).isFile()) { + fs.copyFileSync(subSourcePath, subDestPath) + } + }) + } + }) + } + // Initialize Git repository process.chdir(tempDir) execSync('git init') @@ -40,7 +81,17 @@ export function setupTestRepo() { * @returns {string} Path to the copied file */ export function copyFixture(fixtureName, destName = fixtureName) { - // Find the project root by looking for package.json up the directory tree + // First check if fixture exists in the current working directory + const localFixturePath = path.join(process.cwd(), 'fixtures', fixtureName) + const destPath = path.join(process.cwd(), destName) + + // If fixture exists locally, use it + if (fs.existsSync(localFixturePath)) { + fs.copyFileSync(localFixturePath, destPath) + return destPath + } + + // Otherwise, look for it in the project root let projectRoot = process.cwd() let currentPath = projectRoot @@ -59,7 +110,6 @@ export function copyFixture(fixtureName, destName = fixtureName) { } const fixturePath = path.join(projectRoot, 'fixtures', fixtureName) - const destPath = path.join(process.cwd(), destName) if (!fs.existsSync(fixturePath)) { // Create a mock file if the fixture directory doesn't exist @@ -94,6 +144,5 @@ export function modifyAndStageFile(filePath, content) { */ export function cleanupTestRepo(tempDir) { // Delete the directory after the test - // テスト後にディレクトリを削除 fs.rmSync(tempDir, { recursive: true, force: true }) }