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
15 changes: 15 additions & 0 deletions pkg/tui/components/sidebar/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package sidebar

import (
"os"
"testing"
)

// The test binary runs inside the repository checkout; pin the working
// directory and branch so layouts do not depend on the checkout's branch name.
func TestMain(m *testing.M) {
restore := SetWorkingDirectoryForTesting("/work/app", "")
code := m.Run()
restore()
os.Exit(code)
}
34 changes: 30 additions & 4 deletions pkg/tui/components/sidebar/sidebar.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package sidebar

import (
"context"
"errors"
"fmt"
"log/slog"
"maps"
Expand Down Expand Up @@ -161,6 +162,31 @@ type Model interface {

type gitBranchChangedMsg string

// Seams for the process state the sidebar reads at construction. Unit tests
// run inside the repository checkout, so without them the checkout's branch
// name (60 characters in a merge queue) leaks into every rendered layout.
var (
getwd = os.Getwd
currentBranch = gitbranch.Current
watchBranch = gitbranch.Watch
)

var errBranchWatcherDisabled = errors.New("sidebar: git branch watcher disabled for testing")

// SetWorkingDirectoryForTesting makes every sidebar created afterwards report
// dir and branch instead of the process's working directory and its git
// branch, with no branch watcher, and returns a function restoring the
// defaults. Call it from TestMain: it is not safe alongside running tests.
func SetWorkingDirectoryForTesting(dir, branch string) (restore func()) {
prevGetwd, prevCurrent, prevWatch := getwd, currentBranch, watchBranch
getwd = func() (string, error) { return dir, nil }
currentBranch = func(string) string { return branch }
watchBranch = func(context.Context, string) (*gitbranch.Watcher, error) {
return nil, errBranchWatcherDisabled
}
return func() { getwd, currentBranch, watchBranch = prevGetwd, prevCurrent, prevWatch }
}

func waitForGitBranch(watcher *gitbranch.Watcher) tea.Cmd {
if watcher == nil {
return nil
Expand Down Expand Up @@ -397,9 +423,9 @@ func New(ar *animation.Runtime, ctx context.Context, sessionState *service.Sessi
ti.CharLimit = 50
ti.Prompt = "" // No prompt to maximize usable width in collapsed sidebar

rawDir, _ := os.Getwd()
rawDir, _ := getwd()
wd, branch := formatWorkingDirectory(rawDir)
branchWatcher, _ := gitbranch.Watch(ctx, rawDir)
branchWatcher, _ := watchBranch(ctx, rawDir)

m := &model{
ctx: func() context.Context { return context.WithoutCancel(ctx) },
Expand Down Expand Up @@ -1024,7 +1050,7 @@ func (m *model) LoadFromSession(sess *session.Session) {
if m.gitBranchWatcher != nil {
m.gitBranchName = m.gitBranchWatcher.SetDir(sess.WorkingDir)
} else {
m.gitBranchName = gitbranch.Current(sess.WorkingDir)
m.gitBranchName = currentBranch(sess.WorkingDir)
}
}

Expand Down Expand Up @@ -1156,7 +1182,7 @@ func formatWorkingDirectory(rawDir string) (display, branch string) {
if rawDir == "" {
return "", ""
}
return pathx.ShortenHome(rawDir), gitbranch.Current(rawDir)
return pathx.ShortenHome(rawDir), currentBranch(rawDir)
}

// workingDirWithBranch returns the working directory path with the git branch
Expand Down
30 changes: 30 additions & 0 deletions pkg/tui/components/sidebar/working_directory_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package sidebar

import (
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/docker/docker-agent/pkg/session"
"github.com/docker/docker-agent/pkg/tui/animation"
"github.com/docker/docker-agent/pkg/tui/service"
)

// TestNewIgnoresProcessGitState pins the TestMain seam: a new sidebar shows
// the injected directory with no branch and no watcher, whatever repository
// the test binary happens to run in.
func TestNewIgnoresProcessGitState(t *testing.T) {
t.Parallel()

sess := session.New()
sb := New(animation.NewRuntime(), t.Context(), service.NewSessionState(sess))
m := sb.(*model)

// The display path is normalized to the OS separator.
assert.Equal(t, filepath.FromSlash("/work/app"), m.workingDirectory)
assert.Empty(t, m.gitBranchName)
require.Nil(t, m.gitBranchWatcher)
assert.Nil(t, m.Init(), "no watcher means nothing to wait for")
}
18 changes: 18 additions & 0 deletions pkg/tui/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package tui

import (
"os"
"testing"

"github.com/docker/docker-agent/pkg/tui/components/sidebar"
)

// The test binary runs inside the repository checkout; pin the sidebar's
// working directory and branch so layouts do not depend on the checkout's
// branch name.
func TestMain(m *testing.M) {
restore := sidebar.SetWorkingDirectoryForTesting("/work/app", "")
code := m.Run()
restore()
os.Exit(code)
}
18 changes: 18 additions & 0 deletions pkg/tui/page/chat/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package chat

import (
"os"
"testing"

"github.com/docker/docker-agent/pkg/tui/components/sidebar"
)

// The test binary runs inside the repository checkout; pin the sidebar's
// working directory and branch so layouts do not depend on the checkout's
// branch name.
func TestMain(m *testing.M) {
restore := sidebar.SetWorkingDirectoryForTesting("/work/app", "")
code := m.Run()
restore()
os.Exit(code)
}
Loading