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  }