diff --git a/changelog/fragments/1730418510-confirm-test.yaml b/changelog/fragments/1730418510-confirm-test.yaml new file mode 100644 index 00000000000..af587eeee53 --- /dev/null +++ b/changelog/fragments/1730418510-confirm-test.yaml @@ -0,0 +1,32 @@ +# Kind can be one of: +# - breaking-change: a change to previously-documented behavior +# - deprecation: functionality that is being removed in a later release +# - bug-fix: fixes a problem in a previous version +# - enhancement: extends functionality but does not break or fix existing behavior +# - feature: new functionality +# - known-issue: problems that we are aware of in a given version +# - security: impacts on the security of a product or a user’s deployment. +# - upgrade: important information for someone upgrading from a prior version +# - other: does not fit into any of the other categories +kind: bug-fix + +# Change summary; a 80ish characters long description of the change. +summary: Allows users to enter spaces around yes/no inputs in CLI confirmation prompts. + +# Long description; in case the summary is not enough to describe the change +# this field accommodate a description without length limits. +# NOTE: This field will be rendered only for breaking-change and known-issue kinds at the moment. +#description: + +# Affected component; usually one of "elastic-agent", "fleet-server", "filebeat", "metricbeat", "auditbeat", "all", etc. +component: elastic-agent + +# PR URL; optional; the PR number that added the changeset. +# If not present is automatically filled by the tooling finding the PR where this changelog fragment has been added. +# NOTE: the tooling supports backports, so it's able to fill the original PR number instead of the backport PR number. +# Please provide it if you are adding a fragment for a different PR. +pr: https://github.com/elastic/elastic-agent/pull/5909 + +# Issue URL; optional; the GitHub issue related to this changeset (either closes or is part of). +# If not present is automatically filled by the tooling with the issue linked to the PR number. +#issue: https://github.com/owner/repo/1234 diff --git a/internal/pkg/cli/confirm.go b/internal/pkg/cli/confirm.go index 099e723622b..e77d6b14bce 100644 --- a/internal/pkg/cli/confirm.go +++ b/internal/pkg/cli/confirm.go @@ -34,7 +34,7 @@ func confirm(r io.Reader, out io.Writer, prompt string, def bool) (bool, error) if !reader.Scan() { break } - switch strings.ToLower(reader.Text()) { + switch strings.ToLower(strings.TrimSpace(reader.Text())) { case "": return def, nil case "y", "yes", "yeah": diff --git a/internal/pkg/cli/confirm_test.go b/internal/pkg/cli/confirm_test.go new file mode 100644 index 00000000000..21720f3d0fb --- /dev/null +++ b/internal/pkg/cli/confirm_test.go @@ -0,0 +1,75 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License 2.0; +// you may not use this file except in compliance with the Elastic License 2.0. + +package cli + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestConfirm(t *testing.T) { + cases := map[string]struct { + expectedResult bool + expectedErr string + }{ + "y": {true, ""}, + "y ": {true, ""}, + " y": {true, ""}, + "y\t": {true, ""}, + "\ty": {true, ""}, + "yes": {true, ""}, + "yeah": {true, ""}, + "Y": {true, ""}, + "YES": {true, ""}, + "YEAH": {true, ""}, + "Yes": {true, ""}, + "Yeah": {true, ""}, + "Yup": {false, "error reading user input"}, + "n": {false, ""}, + "n ": {false, ""}, + " n": {false, ""}, + "n\t": {false, ""}, + "\tn": {false, ""}, + "no": {false, ""}, + "N": {false, ""}, + "NO": {false, ""}, + "No": {false, ""}, + "nope": {false, "error reading user input"}, + } + + testFn := func(t *testing.T, input string, def, expectedResult bool, expectedErr string) { + inputReader := strings.NewReader(input) + var outWriter strings.Builder + result, err := confirm(inputReader, &outWriter, "prompt", def) + + prompt := "prompt " + if def { + prompt += "[Y/n]:" + } else { + prompt += "[y/N]:" + } + + require.Equal(t, expectedResult, result) + if expectedErr == "" { + require.NoError(t, err) + require.Equal(t, prompt, outWriter.String()) + } else { + expectedOut := prompt + "Please write 'y' or 'n'\n" + prompt + require.Equal(t, expectedErr, err.Error()) + require.Equal(t, expectedOut, outWriter.String()) + } + } + + for input, test := range cases { + t.Run(input+"-default-to-yes", func(t *testing.T) { + testFn(t, input, true, test.expectedResult, test.expectedErr) + }) + t.Run(input+"-default-to-no", func(t *testing.T) { + testFn(t, input, false, test.expectedResult, test.expectedErr) + }) + } +}