mirror of
https://github.com/coder/coder.git
synced 2025-07-12 00:14:10 +00:00
refactor: Rename 'expect' package to 'console' (#297)
Fixes #291 - renames the `expect` go package to `console`, and changes the api from `expect.NewTestConsole` to `console.New`, and a few other small changes to support the linter (ie, `ConsoleOpts` -> `Opts`)
This commit is contained in:
@ -3,11 +3,12 @@ package clitest_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/coder/coder/cli/clitest"
|
||||
"github.com/coder/coder/coderd/coderdtest"
|
||||
"github.com/coder/coder/expect"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/goleak"
|
||||
|
||||
"github.com/coder/coder/cli/clitest"
|
||||
"github.com/coder/coder/coderd/coderdtest"
|
||||
"github.com/coder/coder/console"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
@ -20,11 +21,11 @@ func TestCli(t *testing.T) {
|
||||
client := coderdtest.New(t)
|
||||
cmd, config := clitest.New(t)
|
||||
clitest.SetupConfig(t, client, config)
|
||||
console := expect.NewTestConsole(t, cmd)
|
||||
cons := console.New(t, cmd)
|
||||
go func() {
|
||||
err := cmd.Execute()
|
||||
require.NoError(t, err)
|
||||
}()
|
||||
_, err := console.ExpectString("coder")
|
||||
_, err := cons.ExpectString("coder")
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
@ -4,8 +4,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/coder/coder/cli/clitest"
|
||||
"github.com/coder/coder/expect"
|
||||
"github.com/coder/coder/coderd/coderdtest"
|
||||
"github.com/coder/coder/console"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@ -26,7 +26,7 @@ func TestLogin(t *testing.T) {
|
||||
// accurately detect Windows ptys when they are not attached to a process:
|
||||
// https://github.com/mattn/go-isatty/issues/59
|
||||
root, _ := clitest.New(t, "login", client.URL.String(), "--force-tty")
|
||||
console := expect.NewTestConsole(t, root)
|
||||
cons := console.New(t, root)
|
||||
go func() {
|
||||
err := root.Execute()
|
||||
require.NoError(t, err)
|
||||
@ -42,12 +42,12 @@ func TestLogin(t *testing.T) {
|
||||
for i := 0; i < len(matches); i += 2 {
|
||||
match := matches[i]
|
||||
value := matches[i+1]
|
||||
_, err := console.ExpectString(match)
|
||||
_, err := cons.ExpectString(match)
|
||||
require.NoError(t, err)
|
||||
_, err = console.SendLine(value)
|
||||
_, err = cons.SendLine(value)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
_, err := console.ExpectString("Welcome to Coder")
|
||||
_, err := cons.ExpectString("Welcome to Coder")
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
@ -7,8 +7,8 @@ import (
|
||||
|
||||
"github.com/coder/coder/cli/clitest"
|
||||
"github.com/coder/coder/coderd/coderdtest"
|
||||
"github.com/coder/coder/console"
|
||||
"github.com/coder/coder/database"
|
||||
"github.com/coder/coder/expect"
|
||||
"github.com/coder/coder/provisioner/echo"
|
||||
"github.com/coder/coder/provisionersdk/proto"
|
||||
)
|
||||
@ -26,7 +26,7 @@ func TestProjectCreate(t *testing.T) {
|
||||
cmd, root := clitest.New(t, "projects", "create", "--directory", source, "--provisioner", string(database.ProvisionerTypeEcho))
|
||||
clitest.SetupConfig(t, client, root)
|
||||
_ = coderdtest.NewProvisionerDaemon(t, client)
|
||||
console := expect.NewTestConsole(t, cmd)
|
||||
console := console.New(t, cmd)
|
||||
closeChan := make(chan struct{})
|
||||
go func() {
|
||||
err := cmd.Execute()
|
||||
@ -73,7 +73,7 @@ func TestProjectCreate(t *testing.T) {
|
||||
cmd, root := clitest.New(t, "projects", "create", "--directory", source, "--provisioner", string(database.ProvisionerTypeEcho))
|
||||
clitest.SetupConfig(t, client, root)
|
||||
coderdtest.NewProvisionerDaemon(t, client)
|
||||
console := expect.NewTestConsole(t, cmd)
|
||||
cons := console.New(t, cmd)
|
||||
closeChan := make(chan struct{})
|
||||
go func() {
|
||||
err := cmd.Execute()
|
||||
@ -91,9 +91,9 @@ func TestProjectCreate(t *testing.T) {
|
||||
for i := 0; i < len(matches); i += 2 {
|
||||
match := matches[i]
|
||||
value := matches[i+1]
|
||||
_, err := console.ExpectString(match)
|
||||
_, err := cons.ExpectString(match)
|
||||
require.NoError(t, err)
|
||||
_, err = console.SendLine(value)
|
||||
_, err = cons.SendLine(value)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
<-closeChan
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
|
||||
"github.com/coder/coder/cli/clitest"
|
||||
"github.com/coder/coder/coderd/coderdtest"
|
||||
"github.com/coder/coder/expect"
|
||||
"github.com/coder/coder/console"
|
||||
"github.com/coder/coder/provisioner/echo"
|
||||
"github.com/coder/coder/provisionersdk/proto"
|
||||
"github.com/stretchr/testify/require"
|
||||
@ -36,7 +36,7 @@ func TestWorkspaceCreate(t *testing.T) {
|
||||
cmd, root := clitest.New(t, "workspaces", "create", project.Name)
|
||||
clitest.SetupConfig(t, client, root)
|
||||
|
||||
console := expect.NewTestConsole(t, cmd)
|
||||
cons := console.New(t, cmd)
|
||||
closeChan := make(chan struct{})
|
||||
go func() {
|
||||
err := cmd.Execute()
|
||||
@ -51,12 +51,12 @@ func TestWorkspaceCreate(t *testing.T) {
|
||||
for i := 0; i < len(matches); i += 2 {
|
||||
match := matches[i]
|
||||
value := matches[i+1]
|
||||
_, err := console.ExpectString(match)
|
||||
_, err := cons.ExpectString(match)
|
||||
require.NoError(t, err)
|
||||
_, err = console.SendLine(value)
|
||||
_, err = cons.SendLine(value)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
_, err := console.ExpectString("Create")
|
||||
_, err := cons.ExpectString("Create")
|
||||
require.NoError(t, err)
|
||||
<-closeChan
|
||||
})
|
||||
|
@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expect
|
||||
package console
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
@ -23,7 +23,7 @@ import (
|
||||
"os"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/coder/coder/expect/pty"
|
||||
"github.com/coder/coder/console/pty"
|
||||
)
|
||||
|
||||
// Console is an interface to automate input and output for interactive
|
||||
@ -31,17 +31,17 @@ import (
|
||||
// input back on it's tty. Console can also multiplex other sources of input
|
||||
// and multiplex its output to other writers.
|
||||
type Console struct {
|
||||
opts ConsoleOpts
|
||||
opts Opts
|
||||
pty pty.Pty
|
||||
runeReader *bufio.Reader
|
||||
closers []io.Closer
|
||||
}
|
||||
|
||||
// ConsoleOpt allows setting Console options.
|
||||
type ConsoleOpt func(*ConsoleOpts) error
|
||||
// Opt allows setting Console options.
|
||||
type Opt func(*Opts) error
|
||||
|
||||
// ConsoleOpts provides additional options on creating a Console.
|
||||
type ConsoleOpts struct {
|
||||
// Opts provides additional options on creating a Console.
|
||||
type Opts struct {
|
||||
Logger *log.Logger
|
||||
Stdouts []io.Writer
|
||||
ExpectObservers []Observer
|
||||
@ -62,8 +62,8 @@ type Observer func(matchers []Matcher, buf string, err error)
|
||||
// last writer, writing to it's internal buffer for matching expects.
|
||||
// If a listed writer returns an error, that overall write operation stops and
|
||||
// returns the error; it does not continue down the list.
|
||||
func WithStdout(writers ...io.Writer) ConsoleOpt {
|
||||
return func(opts *ConsoleOpts) error {
|
||||
func WithStdout(writers ...io.Writer) Opt {
|
||||
return func(opts *Opts) error {
|
||||
opts.Stdouts = append(opts.Stdouts, writers...)
|
||||
return nil
|
||||
}
|
||||
@ -71,24 +71,24 @@ func WithStdout(writers ...io.Writer) ConsoleOpt {
|
||||
|
||||
// WithLogger adds a logger for Console to log debugging information to. By
|
||||
// default Console will discard logs.
|
||||
func WithLogger(logger *log.Logger) ConsoleOpt {
|
||||
return func(opts *ConsoleOpts) error {
|
||||
func WithLogger(logger *log.Logger) Opt {
|
||||
return func(opts *Opts) error {
|
||||
opts.Logger = logger
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithExpectObserver adds an ExpectObserver to allow monitoring Expect operations.
|
||||
func WithExpectObserver(observers ...Observer) ConsoleOpt {
|
||||
return func(opts *ConsoleOpts) error {
|
||||
func WithExpectObserver(observers ...Observer) Opt {
|
||||
return func(opts *Opts) error {
|
||||
opts.ExpectObservers = append(opts.ExpectObservers, observers...)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// NewConsole returns a new Console with the given options.
|
||||
func NewConsole(opts ...ConsoleOpt) (*Console, error) {
|
||||
options := ConsoleOpts{
|
||||
func NewConsole(opts ...Opt) (*Console, error) {
|
||||
options := Opts{
|
||||
Logger: log.New(ioutil.Discard, "", 0),
|
||||
}
|
||||
|
||||
@ -105,14 +105,14 @@ func NewConsole(opts ...ConsoleOpt) (*Console, error) {
|
||||
closers := []io.Closer{consolePty}
|
||||
reader := consolePty.Reader()
|
||||
|
||||
console := &Console{
|
||||
cons := &Console{
|
||||
opts: options,
|
||||
pty: consolePty,
|
||||
runeReader: bufio.NewReaderSize(reader, utf8.UTFMax),
|
||||
closers: closers,
|
||||
}
|
||||
|
||||
return console, nil
|
||||
return cons, nil
|
||||
}
|
||||
|
||||
// Tty returns an input Tty for accepting input
|
@ -16,4 +16,4 @@
|
||||
// applications. It is unlike expect in that it does not spawn or manage
|
||||
// process lifecycle. This package only focuses on expecting output and sending
|
||||
// input through it's psuedoterminal.
|
||||
package expect
|
||||
package console
|
@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expect
|
||||
package console
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
@ -40,8 +40,8 @@ func (c *Console) ExpectString(s string) (string, error) {
|
||||
// expecting input yet, it will be blocked. Sends are queued up in tty's
|
||||
// internal buffer so that the next Expect will read the remaining bytes (i.e.
|
||||
// rest of prompt) as well as its conditions.
|
||||
func (c *Console) Expect(opts ...Opt) (string, error) {
|
||||
var options Opts
|
||||
func (c *Console) Expect(opts ...ExpectOpt) (string, error) {
|
||||
var options ExpectOpts
|
||||
for _, opt := range opts {
|
||||
if err := opt(&options); err != nil {
|
||||
return "", err
|
@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expect
|
||||
package console
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -20,22 +20,22 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Opt allows settings Expect options.
|
||||
type Opt func(*Opts) error
|
||||
// ExpectOpt allows settings Expect options.
|
||||
type ExpectOpt func(*ExpectOpts) error
|
||||
|
||||
// ConsoleCallback is a callback function to execute if a match is found for
|
||||
// Callback is a callback function to execute if a match is found for
|
||||
// the chained matcher.
|
||||
type ConsoleCallback func(buf *bytes.Buffer) error
|
||||
type Callback func(buf *bytes.Buffer) error
|
||||
|
||||
// Opts provides additional options on Expect.
|
||||
type Opts struct {
|
||||
// ExpectOpts provides additional options on Expect.
|
||||
type ExpectOpts struct {
|
||||
Matchers []Matcher
|
||||
ReadTimeout *time.Duration
|
||||
}
|
||||
|
||||
// Match sequentially calls Match on all matchers in ExpectOpts and returns the
|
||||
// first matcher if a match exists, otherwise nil.
|
||||
func (eo Opts) Match(v interface{}) Matcher {
|
||||
func (eo ExpectOpts) Match(v interface{}) Matcher {
|
||||
for _, matcher := range eo.Matchers {
|
||||
if matcher.Match(v) {
|
||||
return matcher
|
||||
@ -83,7 +83,7 @@ func (sm *stringMatcher) Criteria() interface{} {
|
||||
// allMatcher fulfills the Matcher interface to match a group of ExpectOpt
|
||||
// against any value.
|
||||
type allMatcher struct {
|
||||
options Opts
|
||||
options ExpectOpts
|
||||
}
|
||||
|
||||
func (am *allMatcher) Match(v interface{}) bool {
|
||||
@ -109,9 +109,9 @@ func (am *allMatcher) Criteria() interface{} {
|
||||
|
||||
// All adds an Expect condition to exit if the content read from Console's tty
|
||||
// matches all of the provided ExpectOpt, in any order.
|
||||
func All(expectOpts ...Opt) Opt {
|
||||
return func(opts *Opts) error {
|
||||
var options Opts
|
||||
func All(expectOpts ...ExpectOpt) ExpectOpt {
|
||||
return func(opts *ExpectOpts) error {
|
||||
var options ExpectOpts
|
||||
for _, opt := range expectOpts {
|
||||
if err := opt(&options); err != nil {
|
||||
return err
|
||||
@ -127,8 +127,8 @@ func All(expectOpts ...Opt) Opt {
|
||||
|
||||
// String adds an Expect condition to exit if the content read from Console's
|
||||
// tty contains any of the given strings.
|
||||
func String(strs ...string) Opt {
|
||||
return func(opts *Opts) error {
|
||||
func String(strs ...string) ExpectOpt {
|
||||
return func(opts *ExpectOpts) error {
|
||||
for _, str := range strs {
|
||||
opts.Matchers = append(opts.Matchers, &stringMatcher{
|
||||
str: str,
|
@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expect_test
|
||||
package console_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -20,7 +20,7 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
. "github.com/coder/coder/expect"
|
||||
. "github.com/coder/coder/console"
|
||||
)
|
||||
|
||||
func TestExpectOptString(t *testing.T) {
|
||||
@ -28,7 +28,7 @@ func TestExpectOptString(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
title string
|
||||
opt Opt
|
||||
opt ExpectOpt
|
||||
data string
|
||||
expected bool
|
||||
}{
|
||||
@ -63,7 +63,7 @@ func TestExpectOptString(t *testing.T) {
|
||||
t.Run(test.title, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var options Opts
|
||||
var options ExpectOpts
|
||||
err := test.opt(&options)
|
||||
require.Nil(t, err)
|
||||
|
||||
@ -86,7 +86,7 @@ func TestExpectOptAll(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
title string
|
||||
opt Opt
|
||||
opt ExpectOpt
|
||||
data string
|
||||
expected bool
|
||||
}{
|
||||
@ -144,7 +144,7 @@ func TestExpectOptAll(t *testing.T) {
|
||||
test := test
|
||||
t.Run(test.title, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
var options Opts
|
||||
var options ExpectOpts
|
||||
err := test.opt(&options)
|
||||
require.Nil(t, err)
|
||||
|
@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expect_test
|
||||
package console_test
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
@ -26,7 +26,7 @@ import (
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
. "github.com/coder/coder/expect"
|
||||
. "github.com/coder/coder/console"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -71,14 +71,14 @@ func Prompt(in io.Reader, out io.Writer) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func newTestConsole(t *testing.T, opts ...ConsoleOpt) (*Console, error) {
|
||||
opts = append([]ConsoleOpt{
|
||||
func newTestConsole(t *testing.T, opts ...Opt) (*Console, error) {
|
||||
opts = append([]Opt{
|
||||
expectNoError(t),
|
||||
}, opts...)
|
||||
return NewConsole(opts...)
|
||||
}
|
||||
|
||||
func expectNoError(t *testing.T) ConsoleOpt {
|
||||
func expectNoError(t *testing.T) Opt {
|
||||
return WithExpectObserver(
|
||||
func(matchers []Matcher, buf string, err error) {
|
||||
if err == nil {
|
@ -9,7 +9,7 @@ import (
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
|
||||
"github.com/coder/coder/expect/conpty"
|
||||
"github.com/coder/coder/console/conpty"
|
||||
)
|
||||
|
||||
func newPty() (Pty, error) {
|
@ -1,4 +1,4 @@
|
||||
package expect
|
||||
package console
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
@ -16,9 +16,9 @@ var (
|
||||
stripAnsi = regexp.MustCompile("[\u001B\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[a-zA-Z\\d]*)*)?\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))")
|
||||
)
|
||||
|
||||
// NewTestConsole creates a new TTY bound to the command provided.
|
||||
// New creates a new TTY bound to the command provided.
|
||||
// All ANSI escape codes are stripped to provide clean output.
|
||||
func NewTestConsole(t *testing.T, cmd *cobra.Command) *Console {
|
||||
func New(t *testing.T, cmd *cobra.Command) *Console {
|
||||
reader, writer := io.Pipe()
|
||||
scanner := bufio.NewScanner(reader)
|
||||
t.Cleanup(func() {
|
Reference in New Issue
Block a user