@@ -10,6 +10,7 @@ import (
10
10
11
11
"github.com/stretchr/testify/assert"
12
12
"github.com/stretchr/testify/require"
13
+ "golang.org/x/xerrors"
13
14
14
15
"github.com/coder/coder/v2/cli/cliui"
15
16
"github.com/coder/coder/v2/pty"
@@ -22,26 +23,29 @@ func TestPrompt(t *testing.T) {
22
23
t .Parallel ()
23
24
t .Run ("Success" , func (t * testing.T ) {
24
25
t .Parallel ()
26
+ ctx := testutil .Context (t , testutil .WaitShort )
25
27
ptty := ptytest .New (t )
26
28
msgChan := make (chan string )
27
29
go func () {
28
- resp , err := newPrompt (ptty , cliui.PromptOptions {
30
+ resp , err := newPrompt (ctx , ptty , cliui.PromptOptions {
29
31
Text : "Example" ,
30
32
}, nil )
31
33
assert .NoError (t , err )
32
34
msgChan <- resp
33
35
}()
34
36
ptty .ExpectMatch ("Example" )
35
37
ptty .WriteLine ("hello" )
36
- require .Equal (t , "hello" , <- msgChan )
38
+ resp := testutil .RequireRecvCtx (ctx , t , msgChan )
39
+ require .Equal (t , "hello" , resp )
37
40
})
38
41
39
42
t .Run ("Confirm" , func (t * testing.T ) {
40
43
t .Parallel ()
44
+ ctx := testutil .Context (t , testutil .WaitShort )
41
45
ptty := ptytest .New (t )
42
46
doneChan := make (chan string )
43
47
go func () {
44
- resp , err := newPrompt (ptty , cliui.PromptOptions {
48
+ resp , err := newPrompt (ctx , ptty , cliui.PromptOptions {
45
49
Text : "Example" ,
46
50
IsConfirm : true ,
47
51
}, nil )
@@ -50,18 +54,20 @@ func TestPrompt(t *testing.T) {
50
54
}()
51
55
ptty .ExpectMatch ("Example" )
52
56
ptty .WriteLine ("yes" )
53
- require .Equal (t , "yes" , <- doneChan )
57
+ resp := testutil .RequireRecvCtx (ctx , t , doneChan )
58
+ require .Equal (t , "yes" , resp )
54
59
})
55
60
56
61
t .Run ("Skip" , func (t * testing.T ) {
57
62
t .Parallel ()
63
+ ctx := testutil .Context (t , testutil .WaitShort )
58
64
ptty := ptytest .New (t )
59
65
var buf bytes.Buffer
60
66
61
67
// Copy all data written out to a buffer. When we close the ptty, we can
62
68
// no longer read from the ptty.Output(), but we can read what was
63
69
// written to the buffer.
64
- dataRead , doneReading := context .WithTimeout ( context . Background (), testutil . WaitShort )
70
+ dataRead , doneReading := context .WithCancel ( ctx )
65
71
go func () {
66
72
// This will throw an error sometimes. The underlying ptty
67
73
// has its own cleanup routines in t.Cleanup. Instead of
@@ -74,7 +80,7 @@ func TestPrompt(t *testing.T) {
74
80
75
81
doneChan := make (chan string )
76
82
go func () {
77
- resp , err := newPrompt (ptty , cliui.PromptOptions {
83
+ resp , err := newPrompt (ctx , ptty , cliui.PromptOptions {
78
84
Text : "ShouldNotSeeThis" ,
79
85
IsConfirm : true ,
80
86
}, func (inv * serpent.Invocation ) {
@@ -85,7 +91,8 @@ func TestPrompt(t *testing.T) {
85
91
doneChan <- resp
86
92
}()
87
93
88
- require .Equal (t , "yes" , <- doneChan )
94
+ resp := testutil .RequireRecvCtx (ctx , t , doneChan )
95
+ require .Equal (t , "yes" , resp )
89
96
// Close the reader to end the io.Copy
90
97
require .NoError (t , ptty .Close (), "close eof reader" )
91
98
// Wait for the IO copy to finish
@@ -96,42 +103,47 @@ func TestPrompt(t *testing.T) {
96
103
})
97
104
t .Run ("JSON" , func (t * testing.T ) {
98
105
t .Parallel ()
106
+ ctx := testutil .Context (t , testutil .WaitShort )
99
107
ptty := ptytest .New (t )
100
108
doneChan := make (chan string )
101
109
go func () {
102
- resp , err := newPrompt (ptty , cliui.PromptOptions {
110
+ resp , err := newPrompt (ctx , ptty , cliui.PromptOptions {
103
111
Text : "Example" ,
104
112
}, nil )
105
113
assert .NoError (t , err )
106
114
doneChan <- resp
107
115
}()
108
116
ptty .ExpectMatch ("Example" )
109
117
ptty .WriteLine ("{}" )
110
- require .Equal (t , "{}" , <- doneChan )
118
+ resp := testutil .RequireRecvCtx (ctx , t , doneChan )
119
+ require .Equal (t , "{}" , resp )
111
120
})
112
121
113
122
t .Run ("BadJSON" , func (t * testing.T ) {
114
123
t .Parallel ()
124
+ ctx := testutil .Context (t , testutil .WaitShort )
115
125
ptty := ptytest .New (t )
116
126
doneChan := make (chan string )
117
127
go func () {
118
- resp , err := newPrompt (ptty , cliui.PromptOptions {
128
+ resp , err := newPrompt (ctx , ptty , cliui.PromptOptions {
119
129
Text : "Example" ,
120
130
}, nil )
121
131
assert .NoError (t , err )
122
132
doneChan <- resp
123
133
}()
124
134
ptty .ExpectMatch ("Example" )
125
135
ptty .WriteLine ("{a" )
126
- require .Equal (t , "{a" , <- doneChan )
136
+ resp := testutil .RequireRecvCtx (ctx , t , doneChan )
137
+ require .Equal (t , "{a" , resp )
127
138
})
128
139
129
140
t .Run ("MultilineJSON" , func (t * testing.T ) {
130
141
t .Parallel ()
142
+ ctx := testutil .Context (t , testutil .WaitShort )
131
143
ptty := ptytest .New (t )
132
144
doneChan := make (chan string )
133
145
go func () {
134
- resp , err := newPrompt (ptty , cliui.PromptOptions {
146
+ resp , err := newPrompt (ctx , ptty , cliui.PromptOptions {
135
147
Text : "Example" ,
136
148
}, nil )
137
149
assert .NoError (t , err )
@@ -141,11 +153,37 @@ func TestPrompt(t *testing.T) {
141
153
ptty .WriteLine (`{
142
154
"test": "wow"
143
155
}` )
144
- require .Equal (t , `{"test":"wow"}` , <- doneChan )
156
+ resp := testutil .RequireRecvCtx (ctx , t , doneChan )
157
+ require .Equal (t , `{"test":"wow"}` , resp )
158
+ })
159
+
160
+ t .Run ("InvalidValid" , func (t * testing.T ) {
161
+ t .Parallel ()
162
+ ctx := testutil .Context (t , testutil .WaitShort )
163
+ ptty := ptytest .New (t )
164
+ doneChan := make (chan string )
165
+ go func () {
166
+ resp , err := newPrompt (ctx , ptty , cliui.PromptOptions {
167
+ Text : "Example" ,
168
+ Validate : func (s string ) error {
169
+ t .Logf ("validate: %q" , s )
170
+ if s != "valid" {
171
+ return xerrors .New ("invalid" )
172
+ }
173
+ return nil
174
+ },
175
+ }, nil )
176
+ assert .NoError (t , err )
177
+ doneChan <- resp
178
+ }()
179
+ ptty .ExpectMatch ("Example" )
180
+ ptty .WriteLine ("foo\n bar\n baz\n \n \n valid\n " )
181
+ resp := testutil .RequireRecvCtx (ctx , t , doneChan )
182
+ require .Equal (t , "valid" , resp )
145
183
})
146
184
}
147
185
148
- func newPrompt (ptty * ptytest.PTY , opts cliui.PromptOptions , invOpt func (inv * serpent.Invocation )) (string , error ) {
186
+ func newPrompt (ctx context. Context , ptty * ptytest.PTY , opts cliui.PromptOptions , invOpt func (inv * serpent.Invocation )) (string , error ) {
149
187
value := ""
150
188
cmd := & serpent.Command {
151
189
Handler : func (inv * serpent.Invocation ) error {
@@ -163,7 +201,7 @@ func newPrompt(ptty *ptytest.PTY, opts cliui.PromptOptions, invOpt func(inv *ser
163
201
inv .Stdout = ptty .Output ()
164
202
inv .Stderr = ptty .Output ()
165
203
inv .Stdin = ptty .Input ()
166
- return value , inv .WithContext (context . Background () ).Run ()
204
+ return value , inv .WithContext (ctx ).Run ()
167
205
}
168
206
169
207
func TestPasswordTerminalState (t * testing.T ) {
0 commit comments