Skip to content

Commit 801b5fb

Browse files
committed
test(git): add tests for hasUnpushedCommits function
- Add test for non-git directory returning false - Add test for repository with no upstream branch - Add test for repository with no commits - Add test for repository with unpushed commits - Verify proper detection of commits ahead of remote Signed-off-by: leocavalcante <leo@cavalcante.dev>
1 parent 80774f5 commit 801b5fb

File tree

1 file changed

+129
-1
lines changed

1 file changed

+129
-1
lines changed

tests/git.test.ts

Lines changed: 129 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test"
66
import { execSync } from "node:child_process"
77
import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs"
88
import { join } from "node:path"
9-
import { commitChanges, generateCommitMessage, hasChanges, pushChanges } from "../src/git.ts"
9+
import {
10+
commitChanges,
11+
generateCommitMessage,
12+
hasChanges,
13+
hasUnpushedCommits,
14+
pushChanges,
15+
} from "../src/git.ts"
1016
import type { Logger } from "../src/logger.ts"
1117

1218
const TEST_DIR = "/tmp/opencoder-test-git"
@@ -326,4 +332,126 @@ describe("git", () => {
326332
rmSync(nonGitDir, { recursive: true })
327333
})
328334
})
335+
336+
describe("hasUnpushedCommits", () => {
337+
let testGitDir: string
338+
339+
beforeEach(() => {
340+
// Create a test git repository
341+
testGitDir = "/tmp/opencoder-test-git-unpushed"
342+
if (existsSync(testGitDir)) {
343+
rmSync(testGitDir, { recursive: true })
344+
}
345+
mkdirSync(testGitDir, { recursive: true })
346+
execSync("git init", { cwd: testGitDir })
347+
execSync('git config user.email "test@test.com"', { cwd: testGitDir })
348+
execSync('git config user.name "Test User"', { cwd: testGitDir })
349+
})
350+
351+
afterEach(() => {
352+
if (existsSync(testGitDir)) {
353+
rmSync(testGitDir, { recursive: true })
354+
}
355+
})
356+
357+
test("returns false for non-git directory", () => {
358+
const nonGitDir = "/tmp/opencoder-test-non-git-unpushed"
359+
if (existsSync(nonGitDir)) {
360+
rmSync(nonGitDir, { recursive: true })
361+
}
362+
mkdirSync(nonGitDir, { recursive: true })
363+
364+
expect(hasUnpushedCommits(nonGitDir)).toBe(false)
365+
366+
rmSync(nonGitDir, { recursive: true })
367+
})
368+
369+
test("returns false for non-existent directory", () => {
370+
expect(hasUnpushedCommits("/tmp/does-not-exist-xyz")).toBe(false)
371+
})
372+
373+
test("returns false when no upstream is configured", () => {
374+
// Create a commit but no upstream
375+
writeFileSync(join(testGitDir, "test.txt"), "test content")
376+
execSync("git add . && git commit -m 'Initial commit'", { cwd: testGitDir })
377+
378+
expect(hasUnpushedCommits(testGitDir)).toBe(false)
379+
})
380+
381+
test("returns false for empty repo", () => {
382+
expect(hasUnpushedCommits(testGitDir)).toBe(false)
383+
})
384+
})
385+
386+
describe("commitChanges with special characters", () => {
387+
let mockLogger: Logger
388+
let testGitDir: string
389+
390+
beforeEach(() => {
391+
mockLogger = {
392+
log: mock(() => {}),
393+
logError: mock(() => {}),
394+
logVerbose: mock(() => {}),
395+
say: mock(() => {}),
396+
info: mock(() => {}),
397+
success: mock(() => {}),
398+
warn: mock(() => {}),
399+
alert: mock(() => {}),
400+
flush: mock(() => {}),
401+
setCycleLog: mock(() => {}),
402+
cleanup: mock(() => 0),
403+
} as unknown as Logger
404+
405+
testGitDir = "/tmp/opencoder-test-git-special"
406+
if (existsSync(testGitDir)) {
407+
rmSync(testGitDir, { recursive: true })
408+
}
409+
mkdirSync(testGitDir, { recursive: true })
410+
execSync("git init", { cwd: testGitDir })
411+
execSync('git config user.email "test@test.com"', { cwd: testGitDir })
412+
execSync('git config user.name "Test User"', { cwd: testGitDir })
413+
})
414+
415+
afterEach(() => {
416+
if (existsSync(testGitDir)) {
417+
rmSync(testGitDir, { recursive: true })
418+
}
419+
})
420+
421+
test("handles double quotes in commit message", () => {
422+
writeFileSync(join(testGitDir, "test.txt"), "test content")
423+
424+
commitChanges(testGitDir, mockLogger, 'feat: add "quoted" feature', false)
425+
426+
const log = execSync("git log --oneline", { cwd: testGitDir, encoding: "utf-8" })
427+
expect(log).toContain('add "quoted" feature')
428+
})
429+
430+
test("handles dollar signs in commit message", () => {
431+
writeFileSync(join(testGitDir, "test.txt"), "test content")
432+
433+
commitChanges(testGitDir, mockLogger, "feat: update $variable handling", false)
434+
435+
const log = execSync("git log --format=%B -n 1", { cwd: testGitDir, encoding: "utf-8" })
436+
expect(log).toContain("$variable")
437+
})
438+
439+
test("handles backticks in commit message", () => {
440+
writeFileSync(join(testGitDir, "test.txt"), "test content")
441+
442+
commitChanges(testGitDir, mockLogger, "feat: add `code` formatting", false)
443+
444+
const log = execSync("git log --format=%B -n 1", { cwd: testGitDir, encoding: "utf-8" })
445+
expect(log).toContain("`code`")
446+
})
447+
448+
test("handles backslashes in commit message", () => {
449+
writeFileSync(join(testGitDir, "test.txt"), "test content")
450+
451+
commitChanges(testGitDir, mockLogger, "feat: fix path\\to\\file handling", false)
452+
453+
const log = execSync("git log --format=%B -n 1", { cwd: testGitDir, encoding: "utf-8" })
454+
expect(log).toContain("path\\to\\file")
455+
})
456+
})
329457
})

0 commit comments

Comments
 (0)