1
1
package cliui_test
2
2
3
3
import (
4
+ "bytes"
4
5
"context"
6
+ "io"
5
7
"os"
6
8
"os/exec"
7
9
"testing"
@@ -24,7 +26,7 @@ func TestPrompt(t *testing.T) {
24
26
go func () {
25
27
resp , err := newPrompt (ptty , cliui.PromptOptions {
26
28
Text : "Example" ,
27
- })
29
+ }, nil )
28
30
require .NoError (t , err )
29
31
msgChan <- resp
30
32
}()
@@ -41,7 +43,7 @@ func TestPrompt(t *testing.T) {
41
43
resp , err := newPrompt (ptty , cliui.PromptOptions {
42
44
Text : "Example" ,
43
45
IsConfirm : true ,
44
- })
46
+ }, nil )
45
47
require .NoError (t , err )
46
48
doneChan <- resp
47
49
}()
@@ -50,14 +52,55 @@ func TestPrompt(t *testing.T) {
50
52
require .Equal (t , "yes" , <- doneChan )
51
53
})
52
54
55
+ t .Run ("Skip" , func (t * testing.T ) {
56
+ t .Parallel ()
57
+ ptty := ptytest .New (t )
58
+ var buf bytes.Buffer
59
+
60
+ // Copy all data written out to a buffer. When we close the ptty, we can
61
+ // no longer read from the ptty.Output(), but we can read what was
62
+ // written to the buffer.
63
+ dataRead , doneReading := context .WithTimeout (context .Background (), time .Second * 2 )
64
+ go func () {
65
+ // This will throw an error sometimes. The underlying ptty
66
+ // has its own cleanup routines in t.Cleanup. Instead of
67
+ // trying to control the close perfectly, just let the ptty
68
+ // double close. This error isn't important, we just
69
+ // want to know the ptty is done sending output.
70
+ _ , _ = io .Copy (& buf , ptty .Output ())
71
+ doneReading ()
72
+ }()
73
+
74
+ doneChan := make (chan string )
75
+ go func () {
76
+ resp , err := newPrompt (ptty , cliui.PromptOptions {
77
+ Text : "ShouldNotSeeThis" ,
78
+ IsConfirm : true ,
79
+ }, func (cmd * cobra.Command ) {
80
+ cliui .AllowSkipPrompt (cmd )
81
+ cmd .SetArgs ([]string {"-y" })
82
+ })
83
+ require .NoError (t , err )
84
+ doneChan <- resp
85
+ }()
86
+
87
+ require .Equal (t , "yes" , <- doneChan )
88
+ // Close the reader to end the io.Copy
89
+ require .NoError (t , ptty .Close (), "close eof reader" )
90
+ // Wait for the IO copy to finish
91
+ <- dataRead .Done ()
92
+ // Timeout error means the output was hanging
93
+ require .ErrorIs (t , dataRead .Err (), context .Canceled , "should be canceled" )
94
+ require .Len (t , buf .Bytes (), 0 , "expect no output" )
95
+ })
53
96
t .Run ("JSON" , func (t * testing.T ) {
54
97
t .Parallel ()
55
98
ptty := ptytest .New (t )
56
99
doneChan := make (chan string )
57
100
go func () {
58
101
resp , err := newPrompt (ptty , cliui.PromptOptions {
59
102
Text : "Example" ,
60
- })
103
+ }, nil )
61
104
require .NoError (t , err )
62
105
doneChan <- resp
63
106
}()
@@ -73,7 +116,7 @@ func TestPrompt(t *testing.T) {
73
116
go func () {
74
117
resp , err := newPrompt (ptty , cliui.PromptOptions {
75
118
Text : "Example" ,
76
- })
119
+ }, nil )
77
120
require .NoError (t , err )
78
121
doneChan <- resp
79
122
}()
@@ -89,7 +132,7 @@ func TestPrompt(t *testing.T) {
89
132
go func () {
90
133
resp , err := newPrompt (ptty , cliui.PromptOptions {
91
134
Text : "Example" ,
92
- })
135
+ }, nil )
93
136
require .NoError (t , err )
94
137
doneChan <- resp
95
138
}()
@@ -101,7 +144,7 @@ func TestPrompt(t *testing.T) {
101
144
})
102
145
}
103
146
104
- func newPrompt (ptty * ptytest.PTY , opts cliui.PromptOptions ) (string , error ) {
147
+ func newPrompt (ptty * ptytest.PTY , opts cliui.PromptOptions , cmdOpt func ( cmd * cobra. Command ) ) (string , error ) {
105
148
value := ""
106
149
cmd := & cobra.Command {
107
150
RunE : func (cmd * cobra.Command , args []string ) error {
@@ -110,7 +153,12 @@ func newPrompt(ptty *ptytest.PTY, opts cliui.PromptOptions) (string, error) {
110
153
return err
111
154
},
112
155
}
113
- cmd .SetOutput (ptty .Output ())
156
+ // Optionally modify the cmd
157
+ if cmdOpt != nil {
158
+ cmdOpt (cmd )
159
+ }
160
+ cmd .SetOut (ptty .Output ())
161
+ cmd .SetErr (ptty .Output ())
114
162
cmd .SetIn (ptty .Input ())
115
163
return value , cmd .ExecuteContext (context .Background ())
116
164
}
0 commit comments