495 lines
13 KiB
Go
495 lines
13 KiB
Go
package command
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"io/ioutil"
|
|
"regexp"
|
|
"testing"
|
|
|
|
"github.com/cli/cli/pkg/prompt"
|
|
"github.com/cli/cli/test"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestPRReview_validation(t *testing.T) {
|
|
initBlankContext("", "OWNER/REPO", "master")
|
|
http := initFakeHTTP()
|
|
for _, cmd := range []string{
|
|
`pr review --approve --comment 123`,
|
|
`pr review --approve --comment -b"hey" 123`,
|
|
} {
|
|
http.StubRepoResponse("OWNER", "REPO")
|
|
http.StubResponse(200, bytes.NewBufferString(`
|
|
{ "data": { "repository": {
|
|
"pullRequest": { "number": 123 }
|
|
} } }
|
|
`))
|
|
_, err := RunCommand(cmd)
|
|
if err == nil {
|
|
t.Fatal("expected error")
|
|
}
|
|
eq(t, err.Error(), "did not understand desired review action: need exactly one of --approve, --request-changes, or --comment")
|
|
}
|
|
}
|
|
|
|
func TestPRReview_bad_body(t *testing.T) {
|
|
initBlankContext("", "OWNER/REPO", "master")
|
|
http := initFakeHTTP()
|
|
http.StubRepoResponse("OWNER", "REPO")
|
|
http.StubResponse(200, bytes.NewBufferString(`
|
|
{ "data": { "repository": {
|
|
"pullRequest": { "number": 123 }
|
|
} } }
|
|
`))
|
|
_, err := RunCommand(`pr review 123 -b "radical"`)
|
|
if err == nil {
|
|
t.Fatal("expected error")
|
|
}
|
|
eq(t, err.Error(), "did not understand desired review action: --body unsupported without --approve, --request-changes, or --comment")
|
|
}
|
|
|
|
func TestPRReview_url_arg(t *testing.T) {
|
|
initBlankContext("", "OWNER/REPO", "master")
|
|
defer stubTerminal(true)()
|
|
http := initFakeHTTP()
|
|
http.StubResponse(200, bytes.NewBufferString(`
|
|
{ "data": { "repository": { "pullRequest": {
|
|
"id": "foobar123",
|
|
"number": 123,
|
|
"headRefName": "feature",
|
|
"headRepositoryOwner": {
|
|
"login": "hubot"
|
|
},
|
|
"headRepository": {
|
|
"name": "REPO",
|
|
"defaultBranchRef": {
|
|
"name": "master"
|
|
}
|
|
},
|
|
"isCrossRepository": false,
|
|
"maintainerCanModify": false
|
|
} } } } `))
|
|
http.StubResponse(200, bytes.NewBufferString(`{"data": {} }`))
|
|
|
|
output, err := RunCommand("pr review --approve https://github.com/OWNER/REPO/pull/123")
|
|
if err != nil {
|
|
t.Fatalf("error running pr review: %s", err)
|
|
}
|
|
|
|
test.ExpectLines(t, output.Stderr(), "Approved pull request #123")
|
|
|
|
bodyBytes, _ := ioutil.ReadAll(http.Requests[1].Body)
|
|
reqBody := struct {
|
|
Variables struct {
|
|
Input struct {
|
|
PullRequestID string
|
|
Event string
|
|
Body string
|
|
}
|
|
}
|
|
}{}
|
|
_ = json.Unmarshal(bodyBytes, &reqBody)
|
|
|
|
eq(t, reqBody.Variables.Input.PullRequestID, "foobar123")
|
|
eq(t, reqBody.Variables.Input.Event, "APPROVE")
|
|
eq(t, reqBody.Variables.Input.Body, "")
|
|
}
|
|
|
|
func TestPRReview_number_arg(t *testing.T) {
|
|
initBlankContext("", "OWNER/REPO", "master")
|
|
defer stubTerminal(true)()
|
|
http := initFakeHTTP()
|
|
http.StubRepoResponse("OWNER", "REPO")
|
|
http.StubResponse(200, bytes.NewBufferString(`
|
|
{ "data": { "repository": { "pullRequest": {
|
|
"id": "foobar123",
|
|
"number": 123,
|
|
"headRefName": "feature",
|
|
"headRepositoryOwner": {
|
|
"login": "hubot"
|
|
},
|
|
"headRepository": {
|
|
"name": "REPO",
|
|
"defaultBranchRef": {
|
|
"name": "master"
|
|
}
|
|
},
|
|
"isCrossRepository": false,
|
|
"maintainerCanModify": false
|
|
} } } } `))
|
|
http.StubResponse(200, bytes.NewBufferString(`{"data": {} }`))
|
|
|
|
output, err := RunCommand("pr review --approve 123")
|
|
if err != nil {
|
|
t.Fatalf("error running pr review: %s", err)
|
|
}
|
|
|
|
test.ExpectLines(t, output.Stderr(), "Approved pull request #123")
|
|
|
|
bodyBytes, _ := ioutil.ReadAll(http.Requests[2].Body)
|
|
reqBody := struct {
|
|
Variables struct {
|
|
Input struct {
|
|
PullRequestID string
|
|
Event string
|
|
Body string
|
|
}
|
|
}
|
|
}{}
|
|
_ = json.Unmarshal(bodyBytes, &reqBody)
|
|
|
|
eq(t, reqBody.Variables.Input.PullRequestID, "foobar123")
|
|
eq(t, reqBody.Variables.Input.Event, "APPROVE")
|
|
eq(t, reqBody.Variables.Input.Body, "")
|
|
}
|
|
|
|
func TestPRReview_no_arg(t *testing.T) {
|
|
initBlankContext("", "OWNER/REPO", "feature")
|
|
defer stubTerminal(true)()
|
|
http := initFakeHTTP()
|
|
http.StubRepoResponse("OWNER", "REPO")
|
|
http.StubResponse(200, bytes.NewBufferString(`
|
|
{ "data": { "repository": { "pullRequests": { "nodes": [
|
|
{ "url": "https://github.com/OWNER/REPO/pull/123",
|
|
"number": 123,
|
|
"id": "foobar123",
|
|
"headRefName": "feature",
|
|
"baseRefName": "master" }
|
|
] } } } }`))
|
|
http.StubResponse(200, bytes.NewBufferString(`{"data": {} }`))
|
|
|
|
output, err := RunCommand(`pr review --comment -b "cool story"`)
|
|
if err != nil {
|
|
t.Fatalf("error running pr review: %s", err)
|
|
}
|
|
|
|
test.ExpectLines(t, output.Stderr(), "Reviewed pull request #123")
|
|
|
|
bodyBytes, _ := ioutil.ReadAll(http.Requests[2].Body)
|
|
reqBody := struct {
|
|
Variables struct {
|
|
Input struct {
|
|
PullRequestID string
|
|
Event string
|
|
Body string
|
|
}
|
|
}
|
|
}{}
|
|
_ = json.Unmarshal(bodyBytes, &reqBody)
|
|
|
|
eq(t, reqBody.Variables.Input.PullRequestID, "foobar123")
|
|
eq(t, reqBody.Variables.Input.Event, "COMMENT")
|
|
eq(t, reqBody.Variables.Input.Body, "cool story")
|
|
}
|
|
|
|
func TestPRReview_blank_comment(t *testing.T) {
|
|
initBlankContext("", "OWNER/REPO", "master")
|
|
http := initFakeHTTP()
|
|
http.StubRepoResponse("OWNER", "REPO")
|
|
http.StubResponse(200, bytes.NewBufferString(`
|
|
{ "data": { "repository": {
|
|
"pullRequest": { "number": 123 }
|
|
} } }
|
|
`))
|
|
|
|
_, err := RunCommand(`pr review --comment 123`)
|
|
eq(t, err.Error(), "did not understand desired review action: body cannot be blank for comment review")
|
|
}
|
|
|
|
func TestPRReview_blank_request_changes(t *testing.T) {
|
|
initBlankContext("", "OWNER/REPO", "master")
|
|
http := initFakeHTTP()
|
|
http.StubRepoResponse("OWNER", "REPO")
|
|
http.StubResponse(200, bytes.NewBufferString(`
|
|
{ "data": { "repository": {
|
|
"pullRequest": { "number": 123 }
|
|
} } }
|
|
`))
|
|
|
|
_, err := RunCommand(`pr review -r 123`)
|
|
eq(t, err.Error(), "did not understand desired review action: body cannot be blank for request-changes review")
|
|
}
|
|
|
|
func TestPRReview(t *testing.T) {
|
|
type c struct {
|
|
Cmd string
|
|
ExpectedEvent string
|
|
ExpectedBody string
|
|
}
|
|
cases := []c{
|
|
{`pr review --request-changes -b"bad"`, "REQUEST_CHANGES", "bad"},
|
|
{`pr review --approve`, "APPROVE", ""},
|
|
{`pr review --approve -b"hot damn"`, "APPROVE", "hot damn"},
|
|
{`pr review --comment --body "i donno"`, "COMMENT", "i donno"},
|
|
}
|
|
|
|
for _, kase := range cases {
|
|
initBlankContext("", "OWNER/REPO", "feature")
|
|
http := initFakeHTTP()
|
|
http.StubRepoResponse("OWNER", "REPO")
|
|
http.StubResponse(200, bytes.NewBufferString(`
|
|
{ "data": { "repository": { "pullRequests": { "nodes": [
|
|
{ "url": "https://github.com/OWNER/REPO/pull/123",
|
|
"id": "foobar123",
|
|
"headRefName": "feature",
|
|
"baseRefName": "master" }
|
|
] } } } }
|
|
`))
|
|
http.StubResponse(200, bytes.NewBufferString(`{"data": {} }`))
|
|
|
|
_, err := RunCommand(kase.Cmd)
|
|
if err != nil {
|
|
t.Fatalf("got unexpected error running %s: %s", kase.Cmd, err)
|
|
}
|
|
|
|
bodyBytes, _ := ioutil.ReadAll(http.Requests[2].Body)
|
|
reqBody := struct {
|
|
Variables struct {
|
|
Input struct {
|
|
Event string
|
|
Body string
|
|
}
|
|
}
|
|
}{}
|
|
_ = json.Unmarshal(bodyBytes, &reqBody)
|
|
|
|
eq(t, reqBody.Variables.Input.Event, kase.ExpectedEvent)
|
|
eq(t, reqBody.Variables.Input.Body, kase.ExpectedBody)
|
|
}
|
|
}
|
|
|
|
func TestPRReview_nontty_insufficient_flags(t *testing.T) {
|
|
initBlankContext("", "OWNER/REPO", "feature")
|
|
defer stubTerminal(false)()
|
|
http := initFakeHTTP()
|
|
http.StubRepoResponse("OWNER", "REPO")
|
|
http.StubResponse(200, bytes.NewBufferString(`
|
|
{ "data": { "repository": { "pullRequests": { "nodes": [
|
|
{ "url": "https://github.com/OWNER/REPO/pull/123",
|
|
"number": 123,
|
|
"id": "foobar123",
|
|
"headRefName": "feature",
|
|
"baseRefName": "master" }
|
|
] } } } }
|
|
`))
|
|
|
|
output, err := RunCommand("pr review")
|
|
if err == nil {
|
|
t.Fatal("expected error")
|
|
}
|
|
|
|
assert.Equal(t, "", output.String())
|
|
|
|
assert.Equal(t, "did not understand desired review action: --approve, --request-changes, or --comment required when not attached to a tty", err.Error())
|
|
}
|
|
|
|
func TestPRReview_nontty(t *testing.T) {
|
|
initBlankContext("", "OWNER/REPO", "feature")
|
|
defer stubTerminal(false)()
|
|
http := initFakeHTTP()
|
|
http.StubRepoResponse("OWNER", "REPO")
|
|
http.StubResponse(200, bytes.NewBufferString(`
|
|
{ "data": { "repository": { "pullRequests": { "nodes": [
|
|
{ "url": "https://github.com/OWNER/REPO/pull/123",
|
|
"number": 123,
|
|
"id": "foobar123",
|
|
"headRefName": "feature",
|
|
"baseRefName": "master" }
|
|
] } } } }
|
|
`))
|
|
|
|
http.StubResponse(200, bytes.NewBufferString(`{"data": {} }`))
|
|
output, err := RunCommand("pr review -c -bcool")
|
|
if err != nil {
|
|
t.Fatalf("unexpected error running command: %s", err)
|
|
}
|
|
|
|
assert.Equal(t, "", output.String())
|
|
assert.Equal(t, "", output.Stderr())
|
|
|
|
bodyBytes, _ := ioutil.ReadAll(http.Requests[2].Body)
|
|
reqBody := struct {
|
|
Variables struct {
|
|
Input struct {
|
|
Event string
|
|
Body string
|
|
}
|
|
}
|
|
}{}
|
|
_ = json.Unmarshal(bodyBytes, &reqBody)
|
|
|
|
assert.Equal(t, "COMMENT", reqBody.Variables.Input.Event)
|
|
assert.Equal(t, "cool", reqBody.Variables.Input.Body)
|
|
}
|
|
|
|
func TestPRReview_interactive(t *testing.T) {
|
|
initBlankContext("", "OWNER/REPO", "feature")
|
|
defer stubTerminal(true)()
|
|
http := initFakeHTTP()
|
|
http.StubRepoResponse("OWNER", "REPO")
|
|
http.StubResponse(200, bytes.NewBufferString(`
|
|
{ "data": { "repository": { "pullRequests": { "nodes": [
|
|
{ "url": "https://github.com/OWNER/REPO/pull/123",
|
|
"number": 123,
|
|
"id": "foobar123",
|
|
"headRefName": "feature",
|
|
"baseRefName": "master" }
|
|
] } } } }
|
|
`))
|
|
http.StubResponse(200, bytes.NewBufferString(`{"data": {} }`))
|
|
as, teardown := prompt.InitAskStubber()
|
|
defer teardown()
|
|
|
|
as.Stub([]*prompt.QuestionStub{
|
|
{
|
|
Name: "reviewType",
|
|
Value: "Approve",
|
|
},
|
|
})
|
|
as.Stub([]*prompt.QuestionStub{
|
|
{
|
|
Name: "body",
|
|
Value: "cool story",
|
|
},
|
|
})
|
|
as.Stub([]*prompt.QuestionStub{
|
|
{
|
|
Name: "confirm",
|
|
Value: true,
|
|
},
|
|
})
|
|
|
|
output, err := RunCommand(`pr review`)
|
|
if err != nil {
|
|
t.Fatalf("got unexpected error running pr review: %s", err)
|
|
}
|
|
|
|
test.ExpectLines(t, output.Stderr(), "Approved pull request #123")
|
|
|
|
test.ExpectLines(t, output.String(),
|
|
"Got:",
|
|
"cool.*story")
|
|
|
|
bodyBytes, _ := ioutil.ReadAll(http.Requests[2].Body)
|
|
reqBody := struct {
|
|
Variables struct {
|
|
Input struct {
|
|
Event string
|
|
Body string
|
|
}
|
|
}
|
|
}{}
|
|
_ = json.Unmarshal(bodyBytes, &reqBody)
|
|
|
|
eq(t, reqBody.Variables.Input.Event, "APPROVE")
|
|
eq(t, reqBody.Variables.Input.Body, "cool story")
|
|
}
|
|
|
|
func TestPRReview_interactive_no_body(t *testing.T) {
|
|
initBlankContext("", "OWNER/REPO", "feature")
|
|
defer stubTerminal(true)()
|
|
http := initFakeHTTP()
|
|
http.StubRepoResponse("OWNER", "REPO")
|
|
http.StubResponse(200, bytes.NewBufferString(`
|
|
{ "data": { "repository": { "pullRequests": { "nodes": [
|
|
{ "url": "https://github.com/OWNER/REPO/pull/123",
|
|
"id": "foobar123",
|
|
"headRefName": "feature",
|
|
"baseRefName": "master" }
|
|
] } } } }
|
|
`))
|
|
http.StubResponse(200, bytes.NewBufferString(`{"data": {} }`))
|
|
as, teardown := prompt.InitAskStubber()
|
|
defer teardown()
|
|
|
|
as.Stub([]*prompt.QuestionStub{
|
|
{
|
|
Name: "reviewType",
|
|
Value: "Request changes",
|
|
},
|
|
})
|
|
as.Stub([]*prompt.QuestionStub{
|
|
{
|
|
Name: "body",
|
|
Default: true,
|
|
},
|
|
})
|
|
as.Stub([]*prompt.QuestionStub{
|
|
{
|
|
Name: "confirm",
|
|
Value: true,
|
|
},
|
|
})
|
|
|
|
_, err := RunCommand(`pr review`)
|
|
if err == nil {
|
|
t.Fatal("expected error")
|
|
}
|
|
eq(t, err.Error(), "this type of review cannot be blank")
|
|
}
|
|
|
|
func TestPRReview_interactive_blank_approve(t *testing.T) {
|
|
initBlankContext("", "OWNER/REPO", "feature")
|
|
defer stubTerminal(true)()
|
|
http := initFakeHTTP()
|
|
http.StubRepoResponse("OWNER", "REPO")
|
|
http.StubResponse(200, bytes.NewBufferString(`
|
|
{ "data": { "repository": { "pullRequests": { "nodes": [
|
|
{ "url": "https://github.com/OWNER/REPO/pull/123",
|
|
"number": 123,
|
|
"id": "foobar123",
|
|
"headRefName": "feature",
|
|
"baseRefName": "master" }
|
|
] } } } }
|
|
`))
|
|
http.StubResponse(200, bytes.NewBufferString(`{"data": {} }`))
|
|
as, teardown := prompt.InitAskStubber()
|
|
defer teardown()
|
|
|
|
as.Stub([]*prompt.QuestionStub{
|
|
{
|
|
Name: "reviewType",
|
|
Value: "Approve",
|
|
},
|
|
})
|
|
as.Stub([]*prompt.QuestionStub{
|
|
{
|
|
Name: "body",
|
|
Default: true,
|
|
},
|
|
})
|
|
as.Stub([]*prompt.QuestionStub{
|
|
{
|
|
Name: "confirm",
|
|
Value: true,
|
|
},
|
|
})
|
|
|
|
output, err := RunCommand(`pr review`)
|
|
if err != nil {
|
|
t.Fatalf("got unexpected error running pr review: %s", err)
|
|
}
|
|
|
|
unexpect := regexp.MustCompile("Got:")
|
|
if unexpect.MatchString(output.String()) {
|
|
t.Errorf("did not expect to see body printed in %s", output.String())
|
|
}
|
|
|
|
test.ExpectLines(t, output.Stderr(), "Approved pull request #123")
|
|
|
|
bodyBytes, _ := ioutil.ReadAll(http.Requests[2].Body)
|
|
reqBody := struct {
|
|
Variables struct {
|
|
Input struct {
|
|
Event string
|
|
Body string
|
|
}
|
|
}
|
|
}{}
|
|
_ = json.Unmarshal(bodyBytes, &reqBody)
|
|
|
|
eq(t, reqBody.Variables.Input.Event, "APPROVE")
|
|
eq(t, reqBody.Variables.Input.Body, "")
|
|
|
|
}
|