Skip to content

Commit 97402bf

Browse files
committed
♻️ refactor(cmd): pass git/llm clients as args, add tests & update man pages
Signed-off-by: samzong <samzong.lu@gmail.com>
1 parent 2aae08e commit 97402bf

35 files changed

Lines changed: 459 additions & 360 deletions

cmd/cmd_test.go

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@ import (
66
"os"
77
"strings"
88
"testing"
9+
"time"
910

1011
"github.com/samzong/gmc/internal/config"
12+
"github.com/samzong/gmc/internal/git"
13+
"github.com/samzong/gmc/internal/llm"
1114
"github.com/spf13/viper"
1215
"github.com/stretchr/testify/assert"
1316
)
@@ -137,7 +140,8 @@ func TestHandleBranchCreation_NoBranch(t *testing.T) {
137140
// Test with empty branch description
138141
branchDesc = ""
139142

140-
err := handleBranchCreation()
143+
gitClient := git.NewClient(git.Options{})
144+
err := handleBranchCreation(gitClient)
141145
assert.NoError(t, err)
142146
}
143147

@@ -154,12 +158,13 @@ func TestHandleBranchCreation_InvalidBranch(t *testing.T) {
154158

155159
// The actual branch creation will likely fail in test environment
156160
// but we're testing the validation logic
157-
_ = handleBranchCreation()
161+
gitClient := git.NewClient(git.Options{})
162+
_ = handleBranchCreation(gitClient)
158163

159164
// We expect either no error (if validation passes) or an error about branch creation
160165
// The important thing is that the function doesn't panic
161166
assert.NotPanics(t, func() {
162-
_ = handleBranchCreation()
167+
_ = handleBranchCreation(gitClient)
163168
})
164169

165170
// Reset for other tests
@@ -170,7 +175,8 @@ func TestHandleStaging_NoAddAll(t *testing.T) {
170175
// Test with addAll flag disabled
171176
addAll = false
172177

173-
err := handleStaging()
178+
gitClient := git.NewClient(git.Options{})
179+
err := handleStaging(gitClient)
174180
assert.NoError(t, err)
175181
}
176182

@@ -184,7 +190,8 @@ func TestHandleStaging_WithAddAll(t *testing.T) {
184190

185191
// This will likely fail because we're not in a proper git repo or staging area
186192
// But it tests that the function executes the logic
187-
err := handleStaging()
193+
gitClient := git.NewClient(git.Options{})
194+
err := handleStaging(gitClient)
188195

189196
// We expect an error in test environment, but function should not panic
190197
if err != nil {
@@ -202,7 +209,8 @@ func TestPerformCommit_DryRun(t *testing.T) {
202209

203210
dryRun = true
204211

205-
err := performCommit("test commit message")
212+
gitClient := git.NewClient(git.Options{})
213+
err := performCommit(gitClient, "test commit message")
206214
assert.NoError(t, err)
207215

208216
// Reset
@@ -221,7 +229,8 @@ func TestPerformCommit_WithNoVerify(t *testing.T) {
221229
dryRun = true // Enable dry run to avoid actual commit
222230
noVerify = true
223231

224-
err := performCommit("test commit message")
232+
gitClient := git.NewClient(git.Options{})
233+
err := performCommit(gitClient, "test commit message")
225234
assert.NoError(t, err)
226235

227236
// Reset
@@ -241,7 +250,8 @@ func TestPerformCommit_WithNoSignoff(t *testing.T) {
241250
dryRun = true // Enable dry run to avoid actual commit
242251
noSignoff = true
243252

244-
err := performCommit("test commit message")
253+
gitClient := git.NewClient(git.Options{})
254+
err := performCommit(gitClient, "test commit message")
245255
assert.NoError(t, err)
246256

247257
// Reset
@@ -261,7 +271,8 @@ func TestPerformSelectiveCommit_WithNoSignoff(t *testing.T) {
261271
dryRun = true // Enable dry run to avoid actual commit
262272
noSignoff = true
263273

264-
err := performSelectiveCommit("test commit message", []string{"test.go"})
274+
gitClient := git.NewClient(git.Options{})
275+
err := performSelectiveCommit(gitClient, "test commit message", []string{"test.go"})
265276
assert.NoError(t, err)
266277

267278
// Reset
@@ -345,6 +356,7 @@ func TestGenerateCommitMessage_IssueNumber(t *testing.T) {
345356
viper.Reset()
346357
viper.Set("api_key", "test-api-key")
347358
viper.Set("model", "gpt-3.5-turbo")
359+
viper.Set("api_base", "http://127.0.0.1:1")
348360
viper.Set("role", "Developer")
349361

350362
// Save original issueNum
@@ -362,7 +374,8 @@ func TestGenerateCommitMessage_IssueNumber(t *testing.T) {
362374
assert.NoError(t, err)
363375

364376
// The function will fail at LLM call, but issue number formatting logic will be exercised
365-
_, err = generateCommitMessage(cfg, changedFiles, diff, "")
377+
llmClient := llm.NewClient(llm.Options{Timeout: 250 * time.Millisecond})
378+
_, err = generateCommitMessage(llmClient, cfg, changedFiles, diff, "")
366379

367380
// We expect an error due to fake API key
368381
if err != nil {
@@ -492,7 +505,8 @@ func TestErrorHandlingPatterns(t *testing.T) {
492505
func TestGetStagedChanges(t *testing.T) {
493506
// This will test the getStagedChanges function
494507
// It will likely fail in test environment but exercises the code paths
495-
_, _, err := getStagedChanges()
508+
gitClient := git.NewClient(git.Options{})
509+
_, _, err := getStagedChanges(gitClient)
496510

497511
// We expect an error in test environment (not a git repo or no staging area)
498512
// But the function should execute without panic
@@ -549,6 +563,7 @@ func TestHandleCommitFlow(t *testing.T) {
549563
viper.Reset()
550564
viper.Set("api_key", "test-api-key")
551565
viper.Set("model", "gpt-3.5-turbo")
566+
viper.Set("api_base", "http://127.0.0.1:1")
552567
viper.Set("role", "Developer")
553568

554569
// Save original autoYes value
@@ -562,7 +577,9 @@ func TestHandleCommitFlow(t *testing.T) {
562577
changedFiles := []string{"test.go", "main.go"}
563578

564579
// This will exercise the handleCommitFlow function
565-
err := handleCommitFlow(diff, changedFiles)
580+
gitClient := git.NewClient(git.Options{})
581+
llmClient := llm.NewClient(llm.Options{Timeout: 250 * time.Millisecond})
582+
err := handleCommitFlow(gitClient, llmClient, diff, changedFiles)
566583

567584
// We expect an error due to fake API key or git operations
568585
if err != nil {
@@ -591,7 +608,8 @@ func TestPerformCommit_ActualCommit(t *testing.T) {
591608
dryRun = true // Always use dry run in tests
592609
noVerify = false
593610

594-
err := performCommit("test commit message")
611+
gitClient := git.NewClient(git.Options{})
612+
err := performCommit(gitClient, "test commit message")
595613

596614
// In dry run mode, we should not get an error
597615
assert.NoError(t, err, "performCommit should succeed in dry run mode")
@@ -603,6 +621,7 @@ func TestGenerateCommitMessage_Complete(t *testing.T) {
603621
viper.Reset()
604622
viper.Set("api_key", "test-api-key")
605623
viper.Set("model", "gpt-3.5-turbo")
624+
viper.Set("api_base", "http://127.0.0.1:1")
606625
viper.Set("role", "Senior Go Developer")
607626

608627
// Save original issueNum
@@ -625,14 +644,15 @@ index 1234567..abcdefg 100644
625644

626645
// Test without issue number
627646
issueNum = ""
628-
_, err = generateCommitMessage(cfg, changedFiles, diff, "")
647+
llmClient := llm.NewClient(llm.Options{Timeout: 250 * time.Millisecond})
648+
_, err = generateCommitMessage(llmClient, cfg, changedFiles, diff, "")
629649
if err != nil {
630650
assert.Contains(t, err.Error(), "failed to generate commit message")
631651
}
632652

633653
// Test with issue number
634654
issueNum = "456"
635-
_, err = generateCommitMessage(cfg, changedFiles, diff, "")
655+
_, err = generateCommitMessage(llmClient, cfg, changedFiles, diff, "")
636656
if err != nil {
637657
assert.Contains(t, err.Error(), "failed to generate commit message")
638658
}

cmd/init.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"io"
88
"os"
99
"strings"
10+
"time"
1011

1112
"github.com/samzong/gmc/internal/config"
1213
"github.com/samzong/gmc/internal/llm"
@@ -37,7 +38,10 @@ var (
3738
return config.SaveConfig()
3839
}
3940

40-
testLLMConnection = llm.TestConnection
41+
testLLMConnection = func(model string) error {
42+
client := llm.NewClient(llm.Options{Timeout: time.Duration(timeoutSeconds) * time.Second})
43+
return client.TestConnection(model)
44+
}
4145
)
4246

4347
func runInitWizard(in io.Reader, out io.Writer, current *config.Config) error {

cmd/init_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,6 @@ func TestHandleSelectiveCommitFlow_MissingKeyDeclineInit(t *testing.T) {
167167
viper.Reset()
168168
viper.Set("api_key", "")
169169

170-
err = handleSelectiveCommitFlow("diff", []string{"file.go"})
170+
err = handleSelectiveCommitFlow(nil, nil, "diff", []string{"file.go"})
171171
assert.NoError(t, err)
172172
}

0 commit comments

Comments
 (0)