From 1419700dba773b5de08c8e5aee0fb961c5ea7a90 Mon Sep 17 00:00:00 2001 From: nhatthm Date: Mon, 19 Apr 2021 09:53:16 +0200 Subject: [PATCH] Use nhatthm/consoledog --- features/bootstrap/godog_test.go | 5 ++- go.mod | 3 +- go.sum | 5 ++- manager.go | 74 ++++++++++++++++++++++++-------- manager_test.go | 8 ++-- survey.go | 49 +-------------------- 6 files changed, 73 insertions(+), 71 deletions(-) diff --git a/features/bootstrap/godog_test.go b/features/bootstrap/godog_test.go index 9bbdf0c..283a62b 100644 --- a/features/bootstrap/godog_test.go +++ b/features/bootstrap/godog_test.go @@ -42,11 +42,12 @@ func TestIntegration(t *testing.T) { t.Skip(`Missing "-godog" flag, skipping integration test.`) } - m := surveydog.New() p := NewPrompt() + m := surveydog.New(t). + WithStarter(p.WithStdio) RunSuite(t, "..", func(_ *testing.T, ctx *godog.ScenarioContext) { - m.RegisterContext(t, ctx, p.WithStdio) + m.RegisterContext(ctx) p.RegisterContext(ctx) }) } diff --git a/go.mod b/go.mod index 810966a..6964619 100644 --- a/go.mod +++ b/go.mod @@ -7,10 +7,11 @@ require ( github.com/Netflix/go-expect v0.0.0-20201125194554-85d881c3777e github.com/creack/pty v1.1.11 // indirect github.com/cucumber/godog v0.11.0 - github.com/hinshun/vt10x v0.0.0-20180809195222-d55458df857c + github.com/hinshun/vt10x v0.0.0-20180809195222-d55458df857c // indirect github.com/kr/pty v1.1.8 // indirect github.com/mattn/go-colorable v0.1.8 // indirect github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect + github.com/nhatthm/consoledog v0.1.3 github.com/nhatthm/surveyexpect v0.3.0 github.com/stretchr/testify v1.7.0 golang.org/x/text v0.3.6 // indirect diff --git a/go.sum b/go.sum index 8ae1e14..12cf36a 100644 --- a/go.sum +++ b/go.sum @@ -169,6 +169,8 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nhatthm/consoledog v0.1.3 h1:udYv6qO79JC5KcXy8iPS+iB92XaZGUbUocBjpsRIrG0= +github.com/nhatthm/consoledog v0.1.3/go.mod h1:Zb1FInjsGiXmWYCEUE4NWCf4nR9LgVT/TGkpgCTiFOM= github.com/nhatthm/surveyexpect v0.3.0 h1:DZBEY67ynBlwDa/hqq5ZVw2vW2oUqY7DChmWEEJiBGY= github.com/nhatthm/surveyexpect v0.3.0/go.mod h1:KlX6gIkfmduh8f6WP1FyAbJHOzj0nGLgOJ/3gjDLu2A= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= @@ -233,8 +235,9 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210415154028-4f45737414dc h1:+q90ECDSAQirdykUN6sPEiBXBsp8Csjcca8Oy7bgLTA= +golang.org/x/crypto v0.0.0-20210415154028-4f45737414dc/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= diff --git a/manager.go b/manager.go index 9abdcb4..d268c62 100644 --- a/manager.go +++ b/manager.go @@ -6,31 +6,51 @@ import ( "time" "github.com/AlecAivazis/survey/v2/terminal" + "github.com/Netflix/go-expect" "github.com/cucumber/godog" + "github.com/nhatthm/consoledog" "github.com/nhatthm/surveyexpect" "github.com/stretchr/testify/assert" ) +// Starter is a callback when survey starts. +type Starter func(sc *godog.Scenario, stdio terminal.Stdio) + // Manager is a wrapper around *surveyexpect.Survey to make it run with cucumber/godog. type Manager struct { + console *consoledog.Manager surveys map[string]*Survey current string - mu sync.Mutex + starters []Starter + + test surveyexpect.TestingT + mu sync.Mutex options []surveyexpect.ExpectOption } -// RegisterContext register the survey to a *godog.ScenarioContext. -func (m *Manager) RegisterContext(t surveyexpect.TestingT, ctx *godog.ScenarioContext, listeners ...func(sc *godog.Scenario, stdio terminal.Stdio)) { +func (m *Manager) registerConsole(ctx *godog.ScenarioContext) { + if m.console != nil { + return + } + + console := consoledog.New(m.test) + m.attach(console) + // Manage state. ctx.BeforeScenario(func(sc *godog.Scenario) { - m.beforeScenario(t, sc, listeners...) + console.NewConsole(sc) }) ctx.AfterScenario(func(sc *godog.Scenario, _ error) { - m.afterScenario(t, sc) + console.CloseConsole(sc) }) +} + +// RegisterContext register the survey to a *godog.ScenarioContext. +func (m *Manager) RegisterContext(ctx *godog.ScenarioContext) { + m.registerConsole(ctx) // Confirm prompt ctx.Step(`(?:(?:get)|(?:see))s? a(?:nother)? confirm prompt "([^"]*)".* answers? yes`, m.expectConfirmYes) @@ -45,26 +65,25 @@ func (m *Manager) RegisterContext(t surveyexpect.TestingT, ctx *godog.ScenarioCo ctx.Step(`(?:(?:get)|(?:see))s? a(?:nother)? password prompt "([^"]*)".* asks? for help and sees? "([^"]*)"`, m.expectPasswordHelp) } -// Stdio returns terminal.Stdio of the current survey. -func (m *Manager) Stdio() terminal.Stdio { - return m.survey().Stdio() -} - -func (m *Manager) beforeScenario(t surveyexpect.TestingT, sc *godog.Scenario, listeners ...func(sc *godog.Scenario, stdio terminal.Stdio)) { +func (m *Manager) start(sc *godog.Scenario, console *expect.Console) { m.mu.Lock() defer m.mu.Unlock() - s := NewSurvey(t, m.options...).Start(sc.Name) + s := NewSurvey(m.test, m.options...).Start(console) m.current = sc.Id m.surveys[m.current] = s - for _, l := range listeners { - l(sc, s.Stdio()) + for _, start := range m.starters { + start(sc, terminal.Stdio{ + In: console.Tty(), + Out: console.Tty(), + Err: console.Tty(), + }) } } -func (m *Manager) afterScenario(t surveyexpect.TestingT, sc *godog.Scenario) { +func (m *Manager) close(sc *godog.Scenario) { m.mu.Lock() defer m.mu.Unlock() @@ -72,7 +91,7 @@ func (m *Manager) afterScenario(t surveyexpect.TestingT, sc *godog.Scenario) { s.Close() delete(m.surveys, sc.Id) - assert.NoError(t, m.expectationsWereMet(sc.Name, s)) + assert.NoError(m.test, m.expectationsWereMet(sc.Name, s)) } m.current = "" @@ -146,10 +165,31 @@ func (m *Manager) expectationsWereMet(scenario string, s *Survey) error { return fmt.Errorf("in scenario %q, %w", scenario, err) } +func (m *Manager) attach(console *consoledog.Manager) *consoledog.Manager { + return console. + WithStarter(m.start). + WithCloser(m.close) +} + +// WithConsole sets console manager. +func (m *Manager) WithConsole(console *consoledog.Manager) *Manager { + m.console = m.attach(console) + + return m +} + +// WithStarter adds a mew Starter to Manager. +func (m *Manager) WithStarter(s Starter) *Manager { + m.starters = append(m.starters, s) + + return m +} + // New initiates a new *surveydog.Manager. -func New(options ...surveyexpect.ExpectOption) *Manager { +func New(t surveyexpect.TestingT, options ...surveyexpect.ExpectOption) *Manager { return &Manager{ surveys: make(map[string]*Survey), options: options, + test: t, } } diff --git a/manager_test.go b/manager_test.go index 3c45276..afdc0fc 100644 --- a/manager_test.go +++ b/manager_test.go @@ -6,6 +6,7 @@ import ( "time" "github.com/cucumber/godog" + "github.com/nhatthm/consoledog" "github.com/nhatthm/surveyexpect" "github.com/stretchr/testify/assert" ) @@ -57,16 +58,17 @@ func TestManager_ExpectationsWereNotMet(t *testing.T) { t.Parallel() testingT := T() - s := New() + c := consoledog.New(testingT) + s := New(testingT).WithConsole(c) sc := &godog.Scenario{Id: "42", Name: "ExpectationsWereNotMet"} - s.beforeScenario(testingT, sc) + c.NewConsole(sc) assert.Nil(t, s.expectPasswordAnswer("Enter password:", "password")) <-time.After(50 * time.Millisecond) - s.afterScenario(testingT, sc) + s.close(sc) expectedError := `in scenario "ExpectationsWereNotMet", there are remaining expectations that were not met:\ [\t\s]*Type : Password\ diff --git a/survey.go b/survey.go index 3ec1219..cfd1b49 100644 --- a/survey.go +++ b/survey.go @@ -4,20 +4,13 @@ import ( "errors" "sync" - "github.com/AlecAivazis/survey/v2/terminal" - "github.com/Netflix/go-expect" - "github.com/hinshun/vt10x" "github.com/nhatthm/surveyexpect" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) // Survey is a wrapper around *surveyexpect.Survey to make it run with cucumber/godog. type Survey struct { *surveyexpect.Survey - console surveyexpect.Console - output *surveyexpect.Buffer - state *vt10x.State test surveyexpect.TestingT mu sync.Mutex @@ -57,18 +50,6 @@ func (s *Survey) closeDoneChan() { } } -// Stdio returns terminal.Stdio from surveyexpect.Console. -func (s *Survey) Stdio() terminal.Stdio { - s.mu.Lock() - defer s.mu.Unlock() - - return terminal.Stdio{ - In: s.console.Tty(), - Out: s.console.Tty(), - Err: s.console.Tty(), - } -} - // Expect runs an expectation against a given console. func (s *Survey) Expect(c surveyexpect.Console) error { for { @@ -86,22 +67,9 @@ func (s *Survey) Expect(c surveyexpect.Console) error { } // Start starts a new survey. -func (s *Survey) Start(scenario string) *Survey { - s.mu.Lock() - defer s.mu.Unlock() - - s.test.Logf("Scenario: %s\n", scenario) - - s.output = new(surveyexpect.Buffer) - - console, state, err := vt10x.NewVT10XConsole(expect.WithStdout(s.output)) - require.NoError(s.test, err) - - s.console = console - s.state = state - +func (s *Survey) Start(console surveyexpect.Console) *Survey { go func() { - assert.NoError(s.test, s.Expect(s.console)) + assert.NoError(s.test, s.Expect(console)) }() return s @@ -110,19 +78,6 @@ func (s *Survey) Start(scenario string) *Survey { // Close notifies other parties and close the survey. func (s *Survey) Close() { s.closeDoneChan() - - s.mu.Lock() - defer s.mu.Unlock() - - s.test.Logf("Raw output: %q\n", s.output.String()) - - // Dump the terminal's screen. - s.test.Logf("State: \n%s\n", expect.StripTrailingEmptyLines(s.state.String())) - s.test.Log() - - s.console = nil - s.state = nil - s.output = nil } // NewSurvey creates a new survey.