github.com/andrewhsu/cli/v2@v2.0.1-0.20210910131313-d4b4061f5b89/git/git_test.go (about) 1 package git 2 3 import ( 4 "os" 5 "reflect" 6 "testing" 7 8 "github.com/andrewhsu/cli/v2/internal/run" 9 ) 10 11 func setGitDir(t *testing.T, dir string) { 12 // TODO: also set XDG_CONFIG_HOME, GIT_CONFIG_NOSYSTEM 13 old_GIT_DIR := os.Getenv("GIT_DIR") 14 os.Setenv("GIT_DIR", dir) 15 t.Cleanup(func() { 16 os.Setenv("GIT_DIR", old_GIT_DIR) 17 }) 18 } 19 20 func TestLastCommit(t *testing.T) { 21 setGitDir(t, "./fixtures/simple.git") 22 c, err := LastCommit() 23 if err != nil { 24 t.Fatalf("LastCommit error: %v", err) 25 } 26 if c.Sha != "6f1a2405cace1633d89a79c74c65f22fe78f9659" { 27 t.Errorf("expected sha %q, got %q", "6f1a2405cace1633d89a79c74c65f22fe78f9659", c.Sha) 28 } 29 if c.Title != "Second commit" { 30 t.Errorf("expected title %q, got %q", "Second commit", c.Title) 31 } 32 } 33 34 func TestCommitBody(t *testing.T) { 35 setGitDir(t, "./fixtures/simple.git") 36 body, err := CommitBody("6f1a2405cace1633d89a79c74c65f22fe78f9659") 37 if err != nil { 38 t.Fatalf("CommitBody error: %v", err) 39 } 40 if body != "I'm starting to get the hang of things\n" { 41 t.Errorf("expected %q, got %q", "I'm starting to get the hang of things\n", body) 42 } 43 } 44 45 /* 46 NOTE: below this are stubbed git tests, i.e. those that do not actually invoke `git`. If possible, utilize 47 `setGitDir()` to allow new tests to interact with `git`. For write operations, you can use `t.TempDir()` to 48 host a temporary git repository that is safe to be changed. 49 */ 50 51 func Test_UncommittedChangeCount(t *testing.T) { 52 type c struct { 53 Label string 54 Expected int 55 Output string 56 } 57 cases := []c{ 58 {Label: "no changes", Expected: 0, Output: ""}, 59 {Label: "one change", Expected: 1, Output: " M poem.txt"}, 60 {Label: "untracked file", Expected: 2, Output: " M poem.txt\n?? new.txt"}, 61 } 62 63 for _, v := range cases { 64 t.Run(v.Label, func(t *testing.T) { 65 cs, restore := run.Stub() 66 defer restore(t) 67 cs.Register(`git status --porcelain`, 0, v.Output) 68 69 ucc, _ := UncommittedChangeCount() 70 if ucc != v.Expected { 71 t.Errorf("UncommittedChangeCount() = %d, expected %d", ucc, v.Expected) 72 } 73 }) 74 } 75 } 76 77 func Test_CurrentBranch(t *testing.T) { 78 type c struct { 79 Stub string 80 Expected string 81 } 82 cases := []c{ 83 { 84 Stub: "branch-name\n", 85 Expected: "branch-name", 86 }, 87 { 88 Stub: "refs/heads/branch-name\n", 89 Expected: "branch-name", 90 }, 91 { 92 Stub: "refs/heads/branch\u00A0with\u00A0non\u00A0breaking\u00A0space\n", 93 Expected: "branch\u00A0with\u00A0non\u00A0breaking\u00A0space", 94 }, 95 } 96 97 for _, v := range cases { 98 cs, teardown := run.Stub() 99 cs.Register(`git symbolic-ref --quiet HEAD`, 0, v.Stub) 100 101 result, err := CurrentBranch() 102 if err != nil { 103 t.Errorf("got unexpected error: %w", err) 104 } 105 if result != v.Expected { 106 t.Errorf("unexpected branch name: %s instead of %s", result, v.Expected) 107 } 108 teardown(t) 109 } 110 } 111 112 func Test_CurrentBranch_detached_head(t *testing.T) { 113 cs, teardown := run.Stub() 114 defer teardown(t) 115 cs.Register(`git symbolic-ref --quiet HEAD`, 1, "") 116 117 _, err := CurrentBranch() 118 if err == nil { 119 t.Fatal("expected an error, got nil") 120 } 121 if err != ErrNotOnAnyBranch { 122 t.Errorf("got unexpected error: %s instead of %s", err, ErrNotOnAnyBranch) 123 } 124 } 125 126 func TestParseExtraCloneArgs(t *testing.T) { 127 type Wanted struct { 128 args []string 129 dir string 130 } 131 tests := []struct { 132 name string 133 args []string 134 want Wanted 135 }{ 136 { 137 name: "args and target", 138 args: []string{"target_directory", "-o", "upstream", "--depth", "1"}, 139 want: Wanted{ 140 args: []string{"-o", "upstream", "--depth", "1"}, 141 dir: "target_directory", 142 }, 143 }, 144 { 145 name: "only args", 146 args: []string{"-o", "upstream", "--depth", "1"}, 147 want: Wanted{ 148 args: []string{"-o", "upstream", "--depth", "1"}, 149 dir: "", 150 }, 151 }, 152 { 153 name: "only target", 154 args: []string{"target_directory"}, 155 want: Wanted{ 156 args: []string{}, 157 dir: "target_directory", 158 }, 159 }, 160 { 161 name: "no args", 162 args: []string{}, 163 want: Wanted{ 164 args: []string{}, 165 dir: "", 166 }, 167 }, 168 } 169 for _, tt := range tests { 170 t.Run(tt.name, func(t *testing.T) { 171 args, dir := parseCloneArgs(tt.args) 172 got := Wanted{ 173 args: args, 174 dir: dir, 175 } 176 177 if !reflect.DeepEqual(got, tt.want) { 178 t.Errorf("got %#v want %#v", got, tt.want) 179 } 180 }) 181 } 182 } 183 184 func TestAddUpstreamRemote(t *testing.T) { 185 tests := []struct { 186 name string 187 upstreamURL string 188 cloneDir string 189 branches []string 190 want string 191 }{ 192 { 193 name: "fetch all", 194 upstreamURL: "URL", 195 cloneDir: "DIRECTORY", 196 branches: []string{}, 197 want: "git -C DIRECTORY remote add -f upstream URL", 198 }, 199 { 200 name: "fetch specific branches only", 201 upstreamURL: "URL", 202 cloneDir: "DIRECTORY", 203 branches: []string{"master", "dev"}, 204 want: "git -C DIRECTORY remote add -t master -t dev -f upstream URL", 205 }, 206 } 207 for _, tt := range tests { 208 t.Run(tt.name, func(t *testing.T) { 209 cs, cmdTeardown := run.Stub() 210 defer cmdTeardown(t) 211 212 cs.Register(tt.want, 0, "") 213 214 err := AddUpstreamRemote(tt.upstreamURL, tt.cloneDir, tt.branches) 215 if err != nil { 216 t.Fatalf("error running command `git remote add -f`: %v", err) 217 } 218 }) 219 } 220 }