Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions tests/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
36 changes: 18 additions & 18 deletions tests/setup-mocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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')
}
Expand All @@ -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(),
Expand All @@ -95,32 +95,32 @@ vi.mock('commander', () => {
}
})

// child_processをモック
// Mock child_process
vi.mock('child_process', async () => {
const actual = await vi.importActual('child_process')

return {
...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: '' })
Expand All @@ -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) => {
Expand Down
55 changes: 52 additions & 3 deletions tests/setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand All @@ -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

Expand All @@ -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
Expand Down Expand Up @@ -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 })
}