github.com/ungtb10d/cli/v2@v2.0.0-20221110210412-98537dd9d6a1/pkg/cmd/pr/list/list_test.go (about) 1 package list 2 3 import ( 4 "bytes" 5 "io" 6 "net/http" 7 "strings" 8 "testing" 9 "time" 10 11 "github.com/MakeNowJust/heredoc" 12 "github.com/ungtb10d/cli/v2/internal/browser" 13 "github.com/ungtb10d/cli/v2/internal/ghrepo" 14 "github.com/ungtb10d/cli/v2/internal/run" 15 "github.com/ungtb10d/cli/v2/pkg/cmdutil" 16 "github.com/ungtb10d/cli/v2/pkg/httpmock" 17 "github.com/ungtb10d/cli/v2/pkg/iostreams" 18 "github.com/ungtb10d/cli/v2/test" 19 "github.com/google/shlex" 20 "github.com/stretchr/testify/assert" 21 ) 22 23 func runCommand(rt http.RoundTripper, isTTY bool, cli string) (*test.CmdOut, error) { 24 ios, _, stdout, stderr := iostreams.Test() 25 ios.SetStdoutTTY(isTTY) 26 ios.SetStdinTTY(isTTY) 27 ios.SetStderrTTY(isTTY) 28 29 browser := &browser.Stub{} 30 factory := &cmdutil.Factory{ 31 IOStreams: ios, 32 Browser: browser, 33 HttpClient: func() (*http.Client, error) { 34 return &http.Client{Transport: rt}, nil 35 }, 36 BaseRepo: func() (ghrepo.Interface, error) { 37 return ghrepo.New("OWNER", "REPO"), nil 38 }, 39 } 40 41 fakeNow := func() time.Time { 42 return time.Date(2022, time.August, 24, 23, 50, 0, 0, time.UTC) 43 } 44 45 cmd := NewCmdList(factory, func(opts *ListOptions) error { 46 opts.Now = fakeNow 47 return listRun(opts) 48 }) 49 50 argv, err := shlex.Split(cli) 51 if err != nil { 52 return nil, err 53 } 54 cmd.SetArgs(argv) 55 56 cmd.SetIn(&bytes.Buffer{}) 57 cmd.SetOut(io.Discard) 58 cmd.SetErr(io.Discard) 59 60 _, err = cmd.ExecuteC() 61 return &test.CmdOut{ 62 OutBuf: stdout, 63 ErrBuf: stderr, 64 BrowsedURL: browser.BrowsedURL(), 65 }, err 66 } 67 68 func initFakeHTTP() *httpmock.Registry { 69 return &httpmock.Registry{} 70 } 71 72 func TestPRList(t *testing.T) { 73 http := initFakeHTTP() 74 defer http.Verify(t) 75 76 http.Register(httpmock.GraphQL(`query PullRequestList\b`), httpmock.FileResponse("./fixtures/prList.json")) 77 78 output, err := runCommand(http, true, "") 79 if err != nil { 80 t.Fatal(err) 81 } 82 83 assert.Equal(t, heredoc.Doc(` 84 85 Showing 3 of 3 open pull requests in OWNER/REPO 86 87 #32 New feature feature about 3 hours ago 88 #29 Fixed bad bug hubot:bug-fix about 1 month ago 89 #28 Improve documentation docs about 2 years ago 90 `), output.String()) 91 assert.Equal(t, ``, output.Stderr()) 92 } 93 94 func TestPRList_nontty(t *testing.T) { 95 http := initFakeHTTP() 96 defer http.Verify(t) 97 98 http.Register(httpmock.GraphQL(`query PullRequestList\b`), httpmock.FileResponse("./fixtures/prList.json")) 99 100 output, err := runCommand(http, false, "") 101 if err != nil { 102 t.Fatal(err) 103 } 104 105 assert.Equal(t, "", output.Stderr()) 106 107 assert.Equal(t, `32 New feature feature DRAFT 2022-08-24 20:01:12 +0000 UTC 108 29 Fixed bad bug hubot:bug-fix OPEN 2022-07-20 19:01:12 +0000 UTC 109 28 Improve documentation docs MERGED 2020-01-26 19:01:12 +0000 UTC 110 `, output.String()) 111 } 112 113 func TestPRList_filtering(t *testing.T) { 114 http := initFakeHTTP() 115 defer http.Verify(t) 116 117 http.Register( 118 httpmock.GraphQL(`query PullRequestList\b`), 119 httpmock.GraphQLQuery(`{}`, func(_ string, params map[string]interface{}) { 120 assert.Equal(t, []interface{}{"OPEN", "CLOSED", "MERGED"}, params["state"].([]interface{})) 121 })) 122 123 output, err := runCommand(http, true, `-s all`) 124 assert.Error(t, err) 125 126 assert.Equal(t, "", output.String()) 127 assert.Equal(t, "", output.Stderr()) 128 } 129 130 func TestPRList_filteringRemoveDuplicate(t *testing.T) { 131 http := initFakeHTTP() 132 defer http.Verify(t) 133 134 http.Register( 135 httpmock.GraphQL(`query PullRequestList\b`), 136 httpmock.FileResponse("./fixtures/prListWithDuplicates.json")) 137 138 output, err := runCommand(http, true, "") 139 if err != nil { 140 t.Fatal(err) 141 } 142 143 out := output.String() 144 idx := strings.Index(out, "New feature") 145 if idx < 0 { 146 t.Fatalf("text %q not found in %q", "New feature", out) 147 } 148 assert.Equal(t, idx, strings.LastIndex(out, "New feature")) 149 } 150 151 func TestPRList_filteringClosed(t *testing.T) { 152 http := initFakeHTTP() 153 defer http.Verify(t) 154 155 http.Register( 156 httpmock.GraphQL(`query PullRequestList\b`), 157 httpmock.GraphQLQuery(`{}`, func(_ string, params map[string]interface{}) { 158 assert.Equal(t, []interface{}{"CLOSED", "MERGED"}, params["state"].([]interface{})) 159 })) 160 161 _, err := runCommand(http, true, `-s closed`) 162 assert.Error(t, err) 163 } 164 165 func TestPRList_filteringHeadBranch(t *testing.T) { 166 http := initFakeHTTP() 167 defer http.Verify(t) 168 169 http.Register( 170 httpmock.GraphQL(`query PullRequestList\b`), 171 httpmock.GraphQLQuery(`{}`, func(_ string, params map[string]interface{}) { 172 assert.Equal(t, interface{}("bug-fix"), params["headBranch"]) 173 })) 174 175 _, err := runCommand(http, true, `-H bug-fix`) 176 assert.Error(t, err) 177 } 178 179 func TestPRList_filteringAssignee(t *testing.T) { 180 http := initFakeHTTP() 181 defer http.Verify(t) 182 183 http.Register( 184 httpmock.GraphQL(`query PullRequestSearch\b`), 185 httpmock.GraphQLQuery(`{}`, func(_ string, params map[string]interface{}) { 186 assert.Equal(t, `assignee:hubot base:develop is:merged label:"needs tests" repo:OWNER/REPO type:pr`, params["q"].(string)) 187 })) 188 189 _, err := runCommand(http, true, `-s merged -l "needs tests" -a hubot -B develop`) 190 assert.Error(t, err) 191 } 192 193 func TestPRList_filteringDraft(t *testing.T) { 194 tests := []struct { 195 name string 196 cli string 197 expectedQuery string 198 }{ 199 { 200 name: "draft", 201 cli: "--draft", 202 expectedQuery: `draft:true repo:OWNER/REPO state:open type:pr`, 203 }, 204 { 205 name: "non-draft", 206 cli: "--draft=false", 207 expectedQuery: `draft:false repo:OWNER/REPO state:open type:pr`, 208 }, 209 } 210 211 for _, test := range tests { 212 t.Run(test.name, func(t *testing.T) { 213 http := initFakeHTTP() 214 defer http.Verify(t) 215 216 http.Register( 217 httpmock.GraphQL(`query PullRequestSearch\b`), 218 httpmock.GraphQLQuery(`{}`, func(_ string, params map[string]interface{}) { 219 assert.Equal(t, test.expectedQuery, params["q"].(string)) 220 })) 221 222 _, err := runCommand(http, true, test.cli) 223 assert.Error(t, err) 224 }) 225 } 226 } 227 228 func TestPRList_filteringAuthor(t *testing.T) { 229 tests := []struct { 230 name string 231 cli string 232 expectedQuery string 233 }{ 234 { 235 name: "author @me", 236 cli: `--author "@me"`, 237 expectedQuery: `author:@me repo:OWNER/REPO state:open type:pr`, 238 }, 239 { 240 name: "author user", 241 cli: `--author "monalisa"`, 242 expectedQuery: `author:monalisa repo:OWNER/REPO state:open type:pr`, 243 }, 244 { 245 name: "app author", 246 cli: `--author "app/dependabot"`, 247 expectedQuery: `author:app/dependabot repo:OWNER/REPO state:open type:pr`, 248 }, 249 { 250 name: "app author with app option", 251 cli: `--app "dependabot"`, 252 expectedQuery: `author:app/dependabot repo:OWNER/REPO state:open type:pr`, 253 }, 254 } 255 256 for _, test := range tests { 257 t.Run(test.name, func(t *testing.T) { 258 http := initFakeHTTP() 259 defer http.Verify(t) 260 261 http.Register( 262 httpmock.GraphQL(`query PullRequestSearch\b`), 263 httpmock.GraphQLQuery(`{}`, func(_ string, params map[string]interface{}) { 264 assert.Equal(t, test.expectedQuery, params["q"].(string)) 265 })) 266 267 _, err := runCommand(http, true, test.cli) 268 assert.Error(t, err) 269 }) 270 } 271 } 272 273 func TestPRList_withInvalidLimitFlag(t *testing.T) { 274 http := initFakeHTTP() 275 defer http.Verify(t) 276 _, err := runCommand(http, true, `--limit=0`) 277 assert.EqualError(t, err, "invalid value for --limit: 0") 278 } 279 280 func TestPRList_web(t *testing.T) { 281 tests := []struct { 282 name string 283 cli string 284 expectedBrowserURL string 285 }{ 286 { 287 name: "filters", 288 cli: "-a peter -l bug -l docs -L 10 -s merged -B trunk", 289 expectedBrowserURL: "https://github.com/OWNER/REPO/pulls?q=assignee%3Apeter+base%3Atrunk+is%3Amerged+label%3Abug+label%3Adocs+type%3Apr", 290 }, 291 { 292 name: "draft", 293 cli: "--draft=true", 294 expectedBrowserURL: "https://github.com/OWNER/REPO/pulls?q=draft%3Atrue+state%3Aopen+type%3Apr", 295 }, 296 { 297 name: "non-draft", 298 cli: "--draft=0", 299 expectedBrowserURL: "https://github.com/OWNER/REPO/pulls?q=draft%3Afalse+state%3Aopen+type%3Apr", 300 }, 301 } 302 303 for _, test := range tests { 304 t.Run(test.name, func(t *testing.T) { 305 http := initFakeHTTP() 306 defer http.Verify(t) 307 308 _, cmdTeardown := run.Stub() 309 defer cmdTeardown(t) 310 311 output, err := runCommand(http, true, "--web "+test.cli) 312 if err != nil { 313 t.Errorf("error running command `pr list` with `--web` flag: %v", err) 314 } 315 316 assert.Equal(t, "", output.String()) 317 assert.Equal(t, "Opening github.com/OWNER/REPO/pulls in your browser.\n", output.Stderr()) 318 assert.Equal(t, test.expectedBrowserURL, output.BrowsedURL) 319 }) 320 } 321 }