@@ -3,12 +3,17 @@ package command
33import (
44 "bytes"
55 "encoding/json"
6+ "fmt"
67 "io/ioutil"
8+ "reflect"
79 "strings"
810 "testing"
911
1012 "github.com/cli/cli/context"
1113 "github.com/cli/cli/utils"
14+
15+ "github.com/AlecAivazis/survey/v2"
16+ "github.com/AlecAivazis/survey/v2/core"
1217)
1318
1419func TestPRCreate (t * testing.T ) {
@@ -215,10 +220,143 @@ func TestPRCreate_cross_repo_same_branch(t *testing.T) {
215220 it seems that each survey prompt needs to be an injectable hook.
216221*/
217222
218- func PRCreate_survey_preview_defaults (t * testing.T ) {
219- // there are going to be calls to:
220- // - git status
221- // - git push
222- // - git rev-parse
223- // - git log
223+ type askStubber struct {
224+ Asks [][]* survey.Question
225+ Count int
226+ Stubs [][]* QuestionStub
227+ }
228+
229+ func initAskStubber () (* askStubber , func ()) {
230+ origSurveyAsk := SurveyAsk
231+ as := askStubber {}
232+ SurveyAsk = func (qs []* survey.Question , response interface {}, opts ... survey.AskOpt ) error {
233+ as .Asks = append (as .Asks , qs )
234+ count := as .Count
235+ as .Count += 1
236+ if count >= len (as .Stubs ) {
237+ panic (fmt .Sprintf ("more asks than stubs. most recent call: %v" , qs ))
238+ }
239+
240+ // actually set response
241+ stubbedQuestions := as .Stubs [count ]
242+ for i , sq := range stubbedQuestions {
243+ q := qs [i ]
244+ if q .Name != sq .Name {
245+ panic (fmt .Sprintf ("stubbed question mismatch: %s != %s" , q .Name , sq .Name ))
246+ }
247+ if sq .Default {
248+ defaultValue := reflect .ValueOf (q .Prompt ).Elem ().FieldByName ("Default" )
249+ core .WriteAnswer (response , q .Name , defaultValue )
250+ } else {
251+ core .WriteAnswer (response , q .Name , sq .Value )
252+ }
253+ }
254+
255+ return nil
256+ }
257+ teardown := func () {
258+ SurveyAsk = origSurveyAsk
259+ }
260+ return & as , teardown
261+ }
262+
263+ type QuestionStub struct {
264+ Name string
265+ Value interface {}
266+ Default bool
267+ }
268+
269+ func (as * askStubber ) Stub (stubbedQuestions []* QuestionStub ) {
270+ // A call to .Ask takes a list of questions; a stub is then a list of questions in the same order.
271+ as .Stubs = append (as .Stubs , stubbedQuestions )
272+ }
273+
274+ func (as * askStubber ) StubWithDefaults () {
275+ as .Stubs = append (as .Stubs , nil )
276+ }
277+
278+ /*
279+ there are going to be calls to:
280+ - git status
281+ - git push
282+ - git rev-parse
283+ - git log
284+
285+ I can handle all that with the new CmdStubber.
286+
287+ For survey, there is going to be:
288+ - potentially template select Ask
289+ - title, body Ask
290+ - Confirm Action Ask
291+
292+ */
293+ func TestPRCreate_survey_preview_defaults (t * testing.T ) {
294+ initBlankContext ("OWNER/REPO" , "feature" )
295+ http := initFakeHTTP ()
296+ http .StubRepoResponse ("OWNER" , "REPO" )
297+ http .StubResponse (200 , bytes .NewBufferString (`
298+ { "data": { "createPullRequest": { "pullRequest": {
299+ "URL": "https://github.com/OWNER/REPO/pull/12"
300+ } } } }
301+ ` ))
302+
303+ // TODO initCmdStubber in command/testing
304+ cs := CmdStubber {}
305+ cmdTeardown := utils .SetPrepareCmd (createStubbedPrepareCmd (& cs ))
306+ defer cmdTeardown ()
307+
308+ cs .Stub ("" ) // git status
309+ cs .Stub ("1234567890,commit 0\n 2345678901,commit 1" ) // git log
310+ cs .Stub ("" ) // git rev-parse
311+ cs .Stub ("" ) // git push
312+
313+ as , surveyTeardown := initAskStubber ()
314+ defer surveyTeardown ()
315+
316+ // so here is a problem: we lose survey's default detection. This works for specifying what a user
317+ // has typed in, but not for simulating when a user inputs nothing.
318+ // so; how to simulate when a user inputs nothing? can have a special method for that--even just
319+ // "all defaults" would be ok -- but need to figure out if we can even /access/ what the default
320+ // values would be.
321+ as .Stub ([]* QuestionStub {
322+ & QuestionStub {
323+ Name : "title" ,
324+ Default : true ,
325+ },
326+ & QuestionStub {
327+ Name : "body" ,
328+ Default : true ,
329+ },
330+ })
331+ as .Stub ([]* QuestionStub {
332+ & QuestionStub {
333+ Name : "confirmation" ,
334+ Value : 1 ,
335+ },
336+ })
337+
338+ output , err := RunCommand (prCreateCmd , `pr create` )
339+ eq (t , err , nil )
340+
341+ bodyBytes , _ := ioutil .ReadAll (http .Requests [1 ].Body )
342+ reqBody := struct {
343+ Variables struct {
344+ Input struct {
345+ RepositoryID string
346+ Title string
347+ Body string
348+ BaseRefName string
349+ HeadRefName string
350+ }
351+ }
352+ }{}
353+ json .Unmarshal (bodyBytes , & reqBody )
354+
355+ eq (t , reqBody .Variables .Input .RepositoryID , "REPOID" )
356+ eq (t , reqBody .Variables .Input .Title , "my title" )
357+ eq (t , reqBody .Variables .Input .Body , "my body lies" )
358+ eq (t , reqBody .Variables .Input .BaseRefName , "master" )
359+ eq (t , reqBody .Variables .Input .HeadRefName , "feature" )
360+
361+ eq (t , output .String (), "https://github.com/OWNER/REPO/pull/12\n " )
224362}
0 commit comments