-
Notifications
You must be signed in to change notification settings - Fork 560
Improve test quality for pkg/console/confirm_test.go #51434
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,22 +3,52 @@ | |
| package console | ||
|
|
||
| import ( | ||
| "os" | ||
| "strings" | ||
| "testing" | ||
|
|
||
| "github.com/stretchr/testify/assert" | ||
| "github.com/stretchr/testify/require" | ||
| ) | ||
|
|
||
| func TestConfirmAction(t *testing.T) { | ||
| // Note: This test can't fully test the interactive behavior without mocking | ||
| // the terminal input, but we can verify the function signature and basic setup | ||
| // TestConfirmAction_NonTTY verifies that ConfirmAction falls back to the | ||
| // text-based confirmation prompt when stderr is not a terminal (as is the | ||
| // case in `go test` runs), reading the response from os.Stdin. | ||
| func TestConfirmAction_NonTTY(t *testing.T) { | ||
| tests := []struct { | ||
| name string | ||
| input string | ||
| wantResult bool | ||
| wantErr bool | ||
| }{ | ||
| {name: "yes", input: "y\n", wantResult: true}, | ||
| {name: "no", input: "n\n", wantResult: false}, | ||
| {name: "invalid", input: "maybe\n", wantErr: true}, | ||
| } | ||
|
|
||
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t *testing.T) { | ||
| oldStdin := os.Stdin | ||
| r, w, err := os.Pipe() | ||
| require.NoError(t, err) | ||
| t.Cleanup(func() { os.Stdin = oldStdin }) | ||
| t.Cleanup(func() { r.Close() }) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [/tdd] 💡 Fix: swap registration orderRegister restore-stdin after r.Close so LIFO runs restore first: t.Cleanup(func() { r.Close() }) // registered 1st → called 2nd
t.Cleanup(func() { os.Stdin = oldStdin }) // registered 2nd → called 1stCurrently harmless (ConfirmAction has returned by cleanup time), but the ordering will silently cause problems if cleanup logic ever changes. @copilot please address this. |
||
| os.Stdin = r | ||
|
Comment on lines
+31
to
+36
|
||
|
|
||
| go func() { | ||
| _, _ = w.WriteString(tt.input) | ||
| w.Close() | ||
| }() | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor: The write-end of the pipe t.Cleanup(func() { w.Close() })@copilot please address this. |
||
| t.Run("function signature", func(t *testing.T) { | ||
| // This test just verifies the function exists and has the right signature | ||
| // Actual interactive testing would require a mock terminal | ||
| _ = ConfirmAction | ||
| }) | ||
| result, err := ConfirmAction("Delete all workflows?", "Yes, delete", "Cancel") | ||
| if tt.wantErr { | ||
| require.Error(t, err) | ||
| } else { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [/tdd] The goroutine writing to 💡 Use a done channel or write synchronously for short inputsFor short inputs you can write and close synchronously before calling ConfirmAction, since os.Pipe has a kernel buffer large enough for a few bytes: _, _ = w.WriteString(tt.input)
w.Close()
result, err := ConfirmAction(...)If async writing is truly needed, track the goroutine with a WaitGroup and wait in a cleanup. @copilot please address this. |
||
| require.NoError(t, err) | ||
| assert.Equal(t, tt.wantResult, result) | ||
| } | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| func TestShowTextConfirm(t *testing.T) { | ||
|
|
@@ -37,7 +67,11 @@ func TestShowTextConfirm(t *testing.T) { | |
| {name: "NO uppercase", input: "NO\n", wantResult: false}, | ||
| {name: "no full", input: "no\n", wantResult: false}, | ||
| {name: "2 for negative", input: "2\n", wantResult: false}, | ||
| {name: "single letter uppercase Y", input: "Y\n", wantResult: true}, | ||
| {name: "single letter uppercase N", input: "N\n", wantResult: false}, | ||
| {name: "whitespace padded yes", input: " y \n", wantResult: true}, | ||
| {name: "invalid input", input: "maybe\n", wantErr: true, errContains: "invalid input"}, | ||
| {name: "empty input EOF", input: "", wantErr: true, errContains: "invalid input"}, | ||
| } | ||
|
|
||
| for _, tt := range tests { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[/tdd]
TestConfirmAction_NonTTYis missing an empty/EOF case analogous to the one added toTestShowTextConfirm. SinceConfirmActiondelegates toshowTextConfirm, the same EOF path is reachable here.💡 Add an EOF test case
{name: "empty input EOF", input: "", wantErr: true},This rounds out the table and ensures the EOF error surfaces through the
ConfirmActionwrapper too.@copilot please address this.