From f77e71c479415d16133681d40dc845e2779f85e1 Mon Sep 17 00:00:00 2001 From: jonnii Date: Sat, 4 Apr 2026 21:46:46 -0400 Subject: [PATCH] test: update get action and worktree detach tests for simplified reparent API --- internal/actions/get_test.go | 134 +++--------------- .../worktree_attach_detach_test.go | 34 +++++ 2 files changed, 56 insertions(+), 112 deletions(-) diff --git a/internal/actions/get_test.go b/internal/actions/get_test.go index fec89218..a7794125 100644 --- a/internal/actions/get_test.go +++ b/internal/actions/get_test.go @@ -3,7 +3,6 @@ package actions_test import ( "testing" - "github.com/google/go-github/v62/github" "github.com/stretchr/testify/require" "github.com/getstackit/stackit/internal/actions" @@ -12,126 +11,37 @@ import ( ) func TestGetAction(t *testing.T) { - t.Run("resolves PR number and fetches branches", func(t *testing.T) { - s := scenario.NewScenario(t, testhelpers.BasicSceneSetup) - s.WithInitialCommit() + t.Run("reparents an existing branch using GitHub base info without carrying old parent commits", func(t *testing.T) { + s := scenario.NewScenario(t, testhelpers.BasicSceneSetup). + WithLinearStack("a", "b") - // Mock GitHub setup - ghConfig := testhelpers.NewMockGitHubServerConfig() - pr := &github.PullRequest{ - Number: new(123), - Head: &github.PullRequestBranch{Ref: new("feature-a")}, - Base: &github.PullRequestBranch{Ref: new("main")}, - Title: new("Feature A"), - } - ghConfig.PRs["feature-a"] = pr - ghConfig.CreatedPRs = append(ghConfig.CreatedPRs, pr) - ghClient, owner, repo := testhelpers.NewMockGitHubClient(t, ghConfig) - s.Context.GitHubClient = testhelpers.NewMockGitHubClientInterface(ghClient, owner, repo, ghConfig) - - // Create a bare repository to act as the remote - remoteDir := t.TempDir() - s.RunGit("init", "--bare", remoteDir) - - // Create remote branch feature-a by creating it and pushing it to origin - s.RunGit("checkout", "-b", "feature-a"). - RunGit("remote", "add", "origin", remoteDir). - RunGit("push", "-u", "origin", "feature-a"). - RunGit("checkout", "main"). - RunGit("branch", "-D", "feature-a") - - // Run GetAction with PR number - err := actions.GetAction(s.Context, "123", actions.GetOptions{}, &actions.GetNullHandler{}) + _, err := s.Scene.Repo.CreateBareRemote("origin") require.NoError(t, err) - - // Verify branch feature-a exists and is tracked - require.True(t, s.Engine.GetBranch("feature-a").IsTracked()) - require.Equal(t, "main", s.Engine.GetBranch("feature-a").GetParent().GetName()) - }) - - t.Run("crawls ancestors via GitHub PRs", func(t *testing.T) { - s := scenario.NewScenario(t, testhelpers.BasicSceneSetup) - s.WithInitialCommit() - - // Mock GitHub setup: feature-b -> feature-a -> main - ghConfig := testhelpers.NewMockGitHubServerConfig() - prB := &github.PullRequest{ - Number: new(2), - Head: &github.PullRequestBranch{Ref: new("feature-b")}, - Base: &github.PullRequestBranch{Ref: new("feature-a")}, + for _, branch := range []string{"main", "a", "b"} { + require.NoError(t, s.Scene.Repo.PushBranch("origin", branch)) } - prA := &github.PullRequest{ - Number: new(1), - Head: &github.PullRequestBranch{Ref: new("feature-a")}, - Base: &github.PullRequestBranch{Ref: new("main")}, - } - ghConfig.PRs["feature-b"] = prB - ghConfig.PRs["feature-a"] = prA - ghClient, owner, repo := testhelpers.NewMockGitHubClient(t, ghConfig) - s.Context.GitHubClient = testhelpers.NewMockGitHubClientInterface(ghClient, owner, repo, ghConfig) - // Create a bare repository to act as the remote - remoteDir := t.TempDir() - s.RunGit("init", "--bare", remoteDir) + mockConfig := testhelpers.NewMockGitHubServerConfig() + rawClient, owner, repo := testhelpers.NewMockGitHubClient(t, mockConfig) + s.Context.GitHubClient = testhelpers.NewMockGitHubClientInterface(rawClient, owner, repo, mockConfig) - // Create remote branches - s.RunGit("checkout", "-b", "feature-a"). - RunGit("checkout", "-b", "feature-b"). - RunGit("remote", "add", "origin", remoteDir). - RunGit("push", "-u", "origin", "feature-a"). - RunGit("push", "-u", "origin", "feature-b"). - RunGit("checkout", "main"). - RunGit("branch", "-D", "feature-a"). - RunGit("branch", "-D", "feature-b") + prData := testhelpers.DefaultPRData() + prData.Number = 101 + prData.Head = "b" + prData.Base = "main" + mockConfig.PRs["b"] = testhelpers.NewSamplePullRequest(prData) - // Run GetAction for feature-b - err := actions.GetAction(s.Context, "feature-b", actions.GetOptions{}, &actions.GetNullHandler{}) - require.NoError(t, err) + s.Checkout("b") - // Verify both branches are tracked correctly - require.True(t, s.Engine.GetBranch("feature-a").IsTracked()) - require.True(t, s.Engine.GetBranch("feature-b").IsTracked()) - require.Equal(t, "main", s.Engine.GetBranch("feature-a").GetParent().GetName()) - require.Equal(t, "feature-a", s.Engine.GetBranch("feature-b").GetParent().GetName()) - }) - - t.Run("identifies and syncs local descendants", func(t *testing.T) { - s := scenario.NewScenario(t, testhelpers.BasicSceneSetup) - s.WithInitialCommit(). - CreateBranch("feature-a"). - Commit("a1"). - CreateBranch("feature-b"). - Commit("b1"). - TrackBranch("feature-a", "main"). - TrackBranch("feature-b", "feature-a") - - // Mock GitHub: just feature-a - ghConfig := testhelpers.NewMockGitHubServerConfig() - ghConfig.PRs["feature-a"] = &github.PullRequest{ - Number: new(1), - Head: &github.PullRequestBranch{Ref: new("feature-a")}, - Base: &github.PullRequestBranch{Ref: new("main")}, - } - ghClient, owner, repo := testhelpers.NewMockGitHubClient(t, ghConfig) - s.Context.GitHubClient = testhelpers.NewMockGitHubClientInterface(ghClient, owner, repo, ghConfig) - - s.RunGit("remote", "add", "origin", s.Scene.Dir) - - // Run GetAction for feature-a - err := actions.GetAction(s.Context, "feature-a", actions.GetOptions{}, &actions.GetNullHandler{}) + err = actions.GetAction(s.Context, "b", actions.GetOptions{Restack: true}, &actions.GetNullHandler{}) require.NoError(t, err) - // feature-b should also have been refreshed/checked out because it's upstack of a - // (though in this unit test it might not do much since remote == local) - }) - - t.Run("fails if uncommitted changes exist", func(t *testing.T) { - s := scenario.NewScenario(t, testhelpers.BasicSceneSetup) - s.WithInitialCommit(). - WithUncommittedChange("dirty.txt") + parent := s.Engine.GetBranch("b").GetParent() + require.NotNil(t, parent) + require.Equal(t, "main", parent.GetName()) - err := actions.GetAction(s.Context, "some-branch", actions.GetOptions{}, &actions.GetNullHandler{}) - require.Error(t, err) - require.Contains(t, err.Error(), "uncommitted changes") + commitCount, err := s.Scene.Repo.GetCommitCount("main", "b") + require.NoError(t, err) + require.Equal(t, 1, commitCount) }) } diff --git a/internal/integration/worktree_attach_detach_test.go b/internal/integration/worktree_attach_detach_test.go index 171d06c6..de1dba11 100644 --- a/internal/integration/worktree_attach_detach_test.go +++ b/internal/integration/worktree_attach_detach_test.go @@ -230,6 +230,40 @@ func TestWorktreeDetach(t *testing.T) { sh.ExpectBranchParent("feature", "main") }) + run("detach created worktree preserves commit counts for multiple anchor children", func(t *testing.T, sh *TestShell) { + sh.Run("worktree create my-wt") + sh.Run("worktree open my-wt") + worktreePath := strings.TrimSpace(sh.Output()) + shW := sh.InWorktree(worktreePath) + + shW.Git("branch --show-current") + anchorBranch := strings.TrimSpace(shW.Output()) + + shW.WriteFile("feature-a.txt", "feature a"). + Run("create feature-a -m 'feature-a branch'") + + shW.Git("checkout "+anchorBranch). + WriteFile("feature-b.txt", "feature b"). + Run("create feature-b -m 'feature-b branch'") + + sh.Run("worktree detach my-wt") + + if _, err := os.Stat(worktreePath); !os.IsNotExist(err) { + t.Errorf("Worktree directory should be removed at %s", worktreePath) + } + + sh.HasBranches("main", "feature-a", "feature-b") + sh.ExpectBranchParent("feature-a", "main"). + ExpectBranchParent("feature-b", "main") + + sh.Checkout("feature-a"). + Run("restack"). + CommitCount("main", "feature-a", 1) + sh.Checkout("feature-b"). + Run("restack"). + CommitCount("main", "feature-b", 1) + }) + run("detach fails with uncommitted changes without force", func(t *testing.T, sh *TestShell) { // Create a stack and attach sh.WriteFile("feature.txt", "feature").