From 93b067f5f21b3c2fd366a3919bb69700ed3b6684 Mon Sep 17 00:00:00 2001 From: Spike Curtis Date: Tue, 2 Jun 2026 08:05:26 -0400 Subject: [PATCH] test: batch 03 of refactoring CLI tests not to use PTY (#25935) Part of [coder/internal#1400](https://github.com/coder/internal/issues/1400) Batch of refactored CLI tests to avoid creating PTYs. --- cli/templatecreate_test.go | 48 +++++---- cli/templatedelete_test.go | 28 ++++-- cli/templateinit_test.go | 4 - cli/templatelist_test.go | 14 ++- cli/templatepresets_test.go | 28 +++--- cli/templatepull_test.go | 14 +-- cli/templatepush_test.go | 189 ++++++++++++++++++++---------------- 7 files changed, 184 insertions(+), 141 deletions(-) diff --git a/cli/templatecreate_test.go b/cli/templatecreate_test.go index 093ca6e0cc..bd0f9db0bf 100644 --- a/cli/templatecreate_test.go +++ b/cli/templatecreate_test.go @@ -14,14 +14,16 @@ import ( "github.com/coder/coder/v2/coderd/database" "github.com/coder/coder/v2/provisioner/echo" "github.com/coder/coder/v2/provisionersdk/proto" - "github.com/coder/coder/v2/pty/ptytest" "github.com/coder/coder/v2/testutil" + "github.com/coder/coder/v2/testutil/expecter" ) func TestCliTemplateCreate(t *testing.T) { t.Parallel() t.Run("Create", func(t *testing.T) { t.Parallel() + logger := testutil.Logger(t) + ctx := testutil.Context(t, testutil.WaitMedium) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) coderdtest.CreateFirstUser(t, client) source := clitest.CreateTemplateVersionSource(t, completeWithAgent()) @@ -35,7 +37,8 @@ func TestCliTemplateCreate(t *testing.T) { } inv, root := clitest.New(t, args...) clitest.SetupConfig(t, client, root) - pty := ptytest.New(t).Attach(inv) + stdout := expecter.NewAttachedToInvocation(t, inv) + stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv) clitest.Start(t, inv) @@ -49,14 +52,16 @@ func TestCliTemplateCreate(t *testing.T) { {match: "Confirm create?", write: "yes"}, } for _, m := range matches { - pty.ExpectMatch(m.match) + stdout.ExpectMatchContext(ctx, m.match) if len(m.write) > 0 { - pty.WriteLine(m.write) + stdin.WriteLine(m.write) } } }) t.Run("CreateNoLockfile", func(t *testing.T) { t.Parallel() + logger := testutil.Logger(t) + ctx := testutil.Context(t, testutil.WaitMedium) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) coderdtest.CreateFirstUser(t, client) source := clitest.CreateTemplateVersionSource(t, completeWithAgent()) @@ -71,7 +76,8 @@ func TestCliTemplateCreate(t *testing.T) { } inv, root := clitest.New(t, args...) clitest.SetupConfig(t, client, root) - pty := ptytest.New(t).Attach(inv) + stdout := expecter.NewAttachedToInvocation(t, inv) + stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv) execDone := make(chan error) go func() { @@ -86,9 +92,9 @@ func TestCliTemplateCreate(t *testing.T) { {match: "Upload", write: "no"}, } for _, m := range matches { - pty.ExpectMatch(m.match) + stdout.ExpectMatchContext(ctx, m.match) if len(m.write) > 0 { - pty.WriteLine(m.write) + stdin.WriteLine(m.write) } } @@ -97,6 +103,7 @@ func TestCliTemplateCreate(t *testing.T) { }) t.Run("CreateNoLockfileIgnored", func(t *testing.T) { t.Parallel() + logger := testutil.Logger(t) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) coderdtest.CreateFirstUser(t, client) source := clitest.CreateTemplateVersionSource(t, completeWithAgent()) @@ -112,7 +119,8 @@ func TestCliTemplateCreate(t *testing.T) { } inv, root := clitest.New(t, args...) clitest.SetupConfig(t, client, root) - pty := ptytest.New(t).Attach(inv) + stdout := expecter.NewAttachedToInvocation(t, inv) + stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv) execDone := make(chan error) go func() { @@ -123,8 +131,8 @@ func TestCliTemplateCreate(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitMedium) defer cancel() - pty.ExpectNoMatchBefore(ctx, "No .terraform.lock.hcl file found", "Upload") - pty.WriteLine("no") + stdout.ExpectNoMatchBefore(ctx, "No .terraform.lock.hcl file found", "Upload") + stdin.WriteLine("no") } // cmd should error once we say no. @@ -148,9 +156,7 @@ func TestCliTemplateCreate(t *testing.T) { } inv, root := clitest.New(t, args...) clitest.SetupConfig(t, client, root) - pty := ptytest.New(t) inv.Stdin = bytes.NewReader(source) - inv.Stdout = pty.Output() require.NoError(t, inv.Run()) }) @@ -199,6 +205,8 @@ func TestCliTemplateCreate(t *testing.T) { t.Run("WithVariablesFileWithTheRequiredValue", func(t *testing.T) { t.Parallel() + logger := testutil.Logger(t) + ctx := testutil.Context(t, testutil.WaitMedium) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) coderdtest.CreateFirstUser(t, client) @@ -227,7 +235,8 @@ func TestCliTemplateCreate(t *testing.T) { _, _ = variablesFile.WriteString(`first_variable: foobar`) inv, root := clitest.New(t, "templates", "create", "my-template", "--directory", source, "--test.provisioner", string(database.ProvisionerTypeEcho), "--variables-file", variablesFile.Name()) clitest.SetupConfig(t, client, root) - pty := ptytest.New(t).Attach(inv) + stdout := expecter.NewAttachedToInvocation(t, inv) + stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv) clitest.Start(t, inv) @@ -239,15 +248,17 @@ func TestCliTemplateCreate(t *testing.T) { {match: "Confirm create?", write: "yes"}, } for _, m := range matches { - pty.ExpectMatch(m.match) + stdout.ExpectMatchContext(ctx, m.match) if len(m.write) > 0 { - pty.WriteLine(m.write) + stdin.WriteLine(m.write) } } }) t.Run("WithVariableOption", func(t *testing.T) { t.Parallel() + logger := testutil.Logger(t) + ctx := testutil.Context(t, testutil.WaitMedium) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) coderdtest.CreateFirstUser(t, client) @@ -264,7 +275,8 @@ func TestCliTemplateCreate(t *testing.T) { createEchoResponsesWithTemplateVariables(templateVariables)) inv, root := clitest.New(t, "templates", "create", "my-template", "--directory", source, "--test.provisioner", string(database.ProvisionerTypeEcho), "--variable", "first_variable=foobar") clitest.SetupConfig(t, client, root) - pty := ptytest.New(t).Attach(inv) + stdout := expecter.NewAttachedToInvocation(t, inv) + stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv) clitest.Start(t, inv) @@ -276,9 +288,9 @@ func TestCliTemplateCreate(t *testing.T) { {match: "Confirm create?", write: "yes"}, } for _, m := range matches { - pty.ExpectMatch(m.match) + stdout.ExpectMatchContext(ctx, m.match) if len(m.write) > 0 { - pty.WriteLine(m.write) + stdin.WriteLine(m.write) } } }) diff --git a/cli/templatedelete_test.go b/cli/templatedelete_test.go index 1472fc5331..a98be32e29 100644 --- a/cli/templatedelete_test.go +++ b/cli/templatedelete_test.go @@ -13,7 +13,8 @@ import ( "github.com/coder/coder/v2/coderd/coderdtest" "github.com/coder/coder/v2/coderd/rbac" "github.com/coder/coder/v2/codersdk" - "github.com/coder/coder/v2/pty/ptytest" + "github.com/coder/coder/v2/testutil" + "github.com/coder/coder/v2/testutil/expecter" "github.com/coder/pretty" ) @@ -23,6 +24,8 @@ func TestTemplateDelete(t *testing.T) { t.Run("Ok", func(t *testing.T) { t.Parallel() + logger := testutil.Logger(t) + ctx := testutil.Context(t, testutil.WaitMedium) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) owner := coderdtest.CreateFirstUser(t, client) templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) @@ -33,15 +36,16 @@ func TestTemplateDelete(t *testing.T) { inv, root := clitest.New(t, "templates", "delete", template.Name) clitest.SetupConfig(t, templateAdmin, root) - pty := ptytest.New(t).Attach(inv) + stdout := expecter.NewAttachedToInvocation(t, inv) + stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv) execDone := make(chan error) go func() { execDone <- inv.Run() }() - pty.ExpectMatch(fmt.Sprintf("Delete these templates: %s?", pretty.Sprint(cliui.DefaultStyles.Code, template.Name))) - pty.WriteLine("yes") + stdout.ExpectMatchContext(ctx, fmt.Sprintf("Delete these templates: %s?", pretty.Sprint(cliui.DefaultStyles.Code, template.Name))) + stdin.WriteLine("yes") require.NoError(t, <-execDone) @@ -78,6 +82,8 @@ func TestTemplateDelete(t *testing.T) { t.Run("Multiple prompted", func(t *testing.T) { t.Parallel() + logger := testutil.Logger(t) + ctx := testutil.Context(t, testutil.WaitMedium) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) owner := coderdtest.CreateFirstUser(t, client) templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) @@ -93,15 +99,18 @@ func TestTemplateDelete(t *testing.T) { inv, root := clitest.New(t, append([]string{"templates", "delete"}, templateNames...)...) clitest.SetupConfig(t, templateAdmin, root) - pty := ptytest.New(t).Attach(inv) + stdout := expecter.NewAttachedToInvocation(t, inv) + stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv) execDone := make(chan error) go func() { execDone <- inv.Run() }() - pty.ExpectMatch(fmt.Sprintf("Delete these templates: %s?", pretty.Sprint(cliui.DefaultStyles.Code, strings.Join(templateNames, ", ")))) - pty.WriteLine("yes") + stdout.ExpectMatchContext(ctx, + fmt.Sprintf("Delete these templates: %s?", + pretty.Sprint(cliui.DefaultStyles.Code, strings.Join(templateNames, ", ")))) + stdin.WriteLine("yes") require.NoError(t, <-execDone) @@ -114,6 +123,7 @@ func TestTemplateDelete(t *testing.T) { t.Run("Selector", func(t *testing.T) { t.Parallel() + logger := testutil.Logger(t) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) owner := coderdtest.CreateFirstUser(t, client) templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) @@ -124,14 +134,14 @@ func TestTemplateDelete(t *testing.T) { inv, root := clitest.New(t, "templates", "delete") clitest.SetupConfig(t, templateAdmin, root) - pty := ptytest.New(t).Attach(inv) + stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv) execDone := make(chan error) go func() { execDone <- inv.Run() }() - pty.WriteLine("yes") + stdin.WriteLine("yes") require.NoError(t, <-execDone) _, err := client.Template(context.Background(), template.ID) diff --git a/cli/templateinit_test.go b/cli/templateinit_test.go index f8172df25f..b878ef7813 100644 --- a/cli/templateinit_test.go +++ b/cli/templateinit_test.go @@ -7,7 +7,6 @@ import ( "github.com/stretchr/testify/require" "github.com/coder/coder/v2/cli/clitest" - "github.com/coder/coder/v2/pty/ptytest" ) func TestTemplateInit(t *testing.T) { @@ -16,7 +15,6 @@ func TestTemplateInit(t *testing.T) { t.Parallel() tempDir := t.TempDir() inv, _ := clitest.New(t, "templates", "init", tempDir) - ptytest.New(t).Attach(inv) clitest.Run(t, inv) files, err := os.ReadDir(tempDir) require.NoError(t, err) @@ -27,7 +25,6 @@ func TestTemplateInit(t *testing.T) { t.Parallel() tempDir := t.TempDir() inv, _ := clitest.New(t, "templates", "init", "--id", "docker", tempDir) - ptytest.New(t).Attach(inv) clitest.Run(t, inv) files, err := os.ReadDir(tempDir) require.NoError(t, err) @@ -38,7 +35,6 @@ func TestTemplateInit(t *testing.T) { t.Parallel() tempDir := t.TempDir() inv, _ := clitest.New(t, "templates", "init", "--id", "thistemplatedoesnotexist", tempDir) - ptytest.New(t).Attach(inv) err := inv.Run() require.ErrorContains(t, err, "invalid choice: thistemplatedoesnotexist, should be one of") files, err := os.ReadDir(tempDir) diff --git a/cli/templatelist_test.go b/cli/templatelist_test.go index 6818b81ca9..60e6c7a346 100644 --- a/cli/templatelist_test.go +++ b/cli/templatelist_test.go @@ -13,8 +13,8 @@ import ( "github.com/coder/coder/v2/coderd/coderdtest" "github.com/coder/coder/v2/coderd/rbac" "github.com/coder/coder/v2/codersdk" - "github.com/coder/coder/v2/pty/ptytest" "github.com/coder/coder/v2/testutil" + "github.com/coder/coder/v2/testutil/expecter" ) func TestTemplateList(t *testing.T) { @@ -35,7 +35,7 @@ func TestTemplateList(t *testing.T) { inv, root := clitest.New(t, "templates", "list") clitest.SetupConfig(t, templateAdmin, root) - pty := ptytest.New(t).Attach(inv) + stdout := expecter.NewAttachedToInvocation(t, inv) ctx, cancelFunc := context.WithTimeout(context.Background(), testutil.WaitLong) defer cancelFunc() @@ -52,7 +52,7 @@ func TestTemplateList(t *testing.T) { require.NoError(t, <-errC) for _, name := range templatesList { - pty.ExpectMatch(name) + stdout.ExpectMatchContext(ctx, name) } }) t.Run("ListTemplatesJSON", func(t *testing.T) { @@ -93,9 +93,7 @@ func TestTemplateList(t *testing.T) { inv, root := clitest.New(t, "templates", "list") clitest.SetupConfig(t, templateAdmin, root) - pty := ptytest.New(t) - inv.Stdin = pty.Input() - inv.Stderr = pty.Output() + stdout := expecter.NewAttachedToInvocation(t, inv) ctx, cancelFunc := context.WithTimeout(context.Background(), testutil.WaitLong) defer cancelFunc() @@ -107,7 +105,7 @@ func TestTemplateList(t *testing.T) { require.NoError(t, <-errC) - pty.ExpectMatch("No templates found") - pty.ExpectMatch("Create one:") + stdout.ExpectMatchContext(ctx, "No templates found") + stdout.ExpectMatchContext(ctx, "Create one:") }) } diff --git a/cli/templatepresets_test.go b/cli/templatepresets_test.go index 4b324692b8..893c37b0ea 100644 --- a/cli/templatepresets_test.go +++ b/cli/templatepresets_test.go @@ -14,8 +14,8 @@ import ( "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/provisioner/echo" "github.com/coder/coder/v2/provisionersdk/proto" - "github.com/coder/coder/v2/pty/ptytest" "github.com/coder/coder/v2/testutil" + "github.com/coder/coder/v2/testutil/expecter" ) func TestTemplatePresets(t *testing.T) { @@ -24,6 +24,7 @@ func TestTemplatePresets(t *testing.T) { t.Run("NoPresets", func(t *testing.T) { t.Parallel() + ctx := testutil.Context(t, testutil.WaitMedium) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) owner := coderdtest.CreateFirstUser(t, client) member, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID) @@ -37,7 +38,7 @@ func TestTemplatePresets(t *testing.T) { inv, root := clitest.New(t, "templates", "presets", "list", template.Name) clitest.SetupConfig(t, member, root) - pty := ptytest.New(t).Attach(inv) + stdout := expecter.NewAttachedToInvocation(t, inv) doneChan := make(chan struct{}) var runErr error go func() { @@ -49,12 +50,13 @@ func TestTemplatePresets(t *testing.T) { // Should return a message when no presets are found for the given template and version. notFoundMessage := fmt.Sprintf("No presets found for template %q and template-version %q.", template.Name, version.Name) - pty.ExpectRegexMatch(notFoundMessage) + stdout.ExpectRegexMatchContext(ctx, notFoundMessage) }) t.Run("ListsPresetsForDefaultTemplateVersion", func(t *testing.T) { t.Parallel() + ctx := testutil.Context(t, testutil.WaitMedium) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) owner := coderdtest.CreateFirstUser(t, client) member, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID) @@ -104,7 +106,7 @@ func TestTemplatePresets(t *testing.T) { inv, root := clitest.New(t, "templates", "presets", "list", template.Name) clitest.SetupConfig(t, member, root) - pty := ptytest.New(t).Attach(inv) + stdout := expecter.NewAttachedToInvocation(t, inv) doneChan := make(chan struct{}) var runErr error go func() { @@ -117,11 +119,11 @@ func TestTemplatePresets(t *testing.T) { // Should: return the active version's presets sorted by name message := fmt.Sprintf("Showing presets for template %q and template version %q.", template.Name, version.Name) - pty.ExpectMatch(message) - pty.ExpectRegexMatch(`preset-default\s+k1=v2\s+true\s+0`) + stdout.ExpectMatchContext(ctx, message) + stdout.ExpectRegexMatchContext(ctx, `preset-default\s+k1=v2\s+true\s+0`) // The parameter order is not guaranteed in the output, so we match both possible orders - pty.ExpectRegexMatch(`preset-multiple-params\s+(k1=v1,k2=v2)|(k2=v2,k1=v1)\s+false\s+-`) - pty.ExpectRegexMatch(`preset-prebuilds\s+Preset without parameters and 2 prebuild instances.\s+\s+false\s+2`) + stdout.ExpectRegexMatchContext(ctx, `preset-multiple-params\s+(k1=v1,k2=v2)|(k2=v2,k1=v1)\s+false\s+-`) + stdout.ExpectRegexMatchContext(ctx, `preset-prebuilds\s+Preset without parameters and 2 prebuild instances.\s+\s+false\s+2`) }) t.Run("ListsPresetsForSpecifiedTemplateVersion", func(t *testing.T) { @@ -196,7 +198,7 @@ func TestTemplatePresets(t *testing.T) { inv, root := clitest.New(t, "templates", "presets", "list", updatedTemplate.Name, "--template-version", version.Name) clitest.SetupConfig(t, member, root) - pty := ptytest.New(t).Attach(inv) + stdout := expecter.NewAttachedToInvocation(t, inv) doneChan := make(chan struct{}) var runErr error go func() { @@ -209,11 +211,11 @@ func TestTemplatePresets(t *testing.T) { // Should: return the specified version's presets sorted by name message := fmt.Sprintf("Showing presets for template %q and template version %q.", template.Name, version.Name) - pty.ExpectMatch(message) - pty.ExpectRegexMatch(`preset-default\s+k1=v2\s+true\s+0`) + stdout.ExpectMatchContext(ctx, message) + stdout.ExpectRegexMatchContext(ctx, `preset-default\s+k1=v2\s+true\s+0`) // The parameter order is not guaranteed in the output, so we match both possible orders - pty.ExpectRegexMatch(`preset-multiple-params\s+(k1=v1,k2=v2)|(k2=v2,k1=v1)\s+false\s+-`) - pty.ExpectRegexMatch(`preset-prebuilds\s+Preset without parameters and 2 prebuild instances.\s+\s+false\s+2`) + stdout.ExpectRegexMatchContext(ctx, `preset-multiple-params\s+(k1=v1,k2=v2)|(k2=v2,k1=v1)\s+false\s+-`) + stdout.ExpectRegexMatchContext(ctx, `preset-prebuilds\s+Preset without parameters and 2 prebuild instances.\s+\s+false\s+2`) }) t.Run("ListsPresetsJSON", func(t *testing.T) { diff --git a/cli/templatepull_test.go b/cli/templatepull_test.go index 5d999de15e..5495bf0637 100644 --- a/cli/templatepull_test.go +++ b/cli/templatepull_test.go @@ -21,7 +21,8 @@ import ( "github.com/coder/coder/v2/provisioner/echo" "github.com/coder/coder/v2/provisionersdk" "github.com/coder/coder/v2/provisionersdk/proto" - "github.com/coder/coder/v2/pty/ptytest" + "github.com/coder/coder/v2/testutil" + "github.com/coder/coder/v2/testutil/expecter" ) // dirSum calculates a checksum of the files in a directory. @@ -320,8 +321,6 @@ func TestTemplatePull_ToDir(t *testing.T) { inv, root := clitest.New(t, "templates", "pull", template.Name, actualDest) clitest.SetupConfig(t, templateAdmin, root) - ptytest.New(t).Attach(inv) - require.NoError(t, inv.Run()) // Validate behavior of choosing template name in the absence of an output path argument. @@ -343,6 +342,8 @@ func TestTemplatePull_ToDir(t *testing.T) { func TestTemplatePull_FolderConflict(t *testing.T) { t.Parallel() + logger := testutil.Logger(t) + ctx := testutil.Context(t, testutil.WaitMedium) client := coderdtest.New(t, &coderdtest.Options{ IncludeProvisionerDaemon: true, }) @@ -389,12 +390,13 @@ func TestTemplatePull_FolderConflict(t *testing.T) { inv, root := clitest.New(t, "templates", "pull", template.Name, conflictDest) clitest.SetupConfig(t, templateAdmin, root) - pty := ptytest.New(t).Attach(inv) + stdout := expecter.NewAttachedToInvocation(t, inv) + stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv) waiter := clitest.StartWithWaiter(t, inv) - pty.ExpectMatch("not empty") - pty.WriteLine("no") + stdout.ExpectMatchContext(ctx, "not empty") + stdin.WriteLine("no") waiter.RequireError() diff --git a/cli/templatepush_test.go b/cli/templatepush_test.go index 55123f8890..d93dc1d7ce 100644 --- a/cli/templatepush_test.go +++ b/cli/templatepush_test.go @@ -26,8 +26,8 @@ import ( "github.com/coder/coder/v2/provisioner/terraform/tfparse" "github.com/coder/coder/v2/provisionersdk" "github.com/coder/coder/v2/provisionersdk/proto" - "github.com/coder/coder/v2/pty/ptytest" "github.com/coder/coder/v2/testutil" + "github.com/coder/coder/v2/testutil/expecter" ) func TestTemplatePush(t *testing.T) { @@ -35,6 +35,7 @@ func TestTemplatePush(t *testing.T) { t.Run("OK", func(t *testing.T) { t.Parallel() + logger := testutil.Logger(t) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) owner := coderdtest.CreateFirstUser(t, client) templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) @@ -50,7 +51,8 @@ func TestTemplatePush(t *testing.T) { }) inv, root := clitest.New(t, "templates", "push", template.Name, "--directory", source, "--test.provisioner", string(database.ProvisionerTypeEcho), "--name", "example") clitest.SetupConfig(t, templateAdmin, root) - pty := ptytest.New(t).Attach(inv) + stdout := expecter.NewAttachedToInvocation(t, inv) + stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv) ctx := testutil.Context(t, testutil.WaitMedium) inv = inv.WithContext(ctx) @@ -63,8 +65,8 @@ func TestTemplatePush(t *testing.T) { {match: "Upload", write: "yes"}, } for _, m := range matches { - pty.ExpectMatchContext(ctx, m.match) - pty.WriteLine(m.write) + stdout.ExpectMatchContext(ctx, m.match) + stdin.WriteLine(m.write) } w.RequireSuccess() @@ -97,13 +99,13 @@ func TestTemplatePush(t *testing.T) { inv, root := clitest.New(t, "templates", "push", template.Name, "--directory", source, "--test.provisioner", string(database.ProvisionerTypeEcho), "--name", "example", "--message", wantMessage, "--yes") clitest.SetupConfig(t, templateAdmin, root) - pty := ptytest.New(t).Attach(inv) + stdout := expecter.NewAttachedToInvocation(t, inv) ctx := testutil.Context(t, testutil.WaitMedium) inv = inv.WithContext(ctx) w := clitest.StartWithWaiter(t, inv) - pty.ExpectNoMatchBefore(ctx, "Template message is longer than 72 characters", "Updated version at") + stdout.ExpectNoMatchBefore(ctx, "Template message is longer than 72 characters", "Updated version at") w.RequireSuccess() @@ -146,13 +148,13 @@ func TestTemplatePush(t *testing.T) { "--yes", ) clitest.SetupConfig(t, templateAdmin, root) - pty := ptytest.New(t).Attach(inv) + stdout := expecter.NewAttachedToInvocation(t, inv) ctx := testutil.Context(t, testutil.WaitMedium) inv = inv.WithContext(ctx) w := clitest.StartWithWaiter(t, inv) - pty.ExpectMatchContext(ctx, tt.wantMatch) + stdout.ExpectMatchContext(ctx, tt.wantMatch) w.RequireSuccess() @@ -170,6 +172,7 @@ func TestTemplatePush(t *testing.T) { t.Run("NoLockfile", func(t *testing.T) { t.Parallel() + logger := testutil.Logger(t) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) owner := coderdtest.CreateFirstUser(t, client) templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) @@ -191,7 +194,8 @@ func TestTemplatePush(t *testing.T) { "--name", "example", ) clitest.SetupConfig(t, templateAdmin, root) - pty := ptytest.New(t).Attach(inv) + stdout := expecter.NewAttachedToInvocation(t, inv) + stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv) ctx := testutil.Context(t, testutil.WaitMedium) inv = inv.WithContext(ctx) @@ -205,9 +209,9 @@ func TestTemplatePush(t *testing.T) { {match: "Upload", write: "no"}, } for _, m := range matches { - pty.ExpectMatchContext(ctx, m.match) + stdout.ExpectMatchContext(ctx, m.match) if m.write != "" { - pty.WriteLine(m.write) + stdin.WriteLine(m.write) } } @@ -217,6 +221,7 @@ func TestTemplatePush(t *testing.T) { t.Run("NoLockfileIgnored", func(t *testing.T) { t.Parallel() + logger := testutil.Logger(t) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) owner := coderdtest.CreateFirstUser(t, client) templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) @@ -239,7 +244,8 @@ func TestTemplatePush(t *testing.T) { "--ignore-lockfile", ) clitest.SetupConfig(t, templateAdmin, root) - pty := ptytest.New(t).Attach(inv) + stdout := expecter.NewAttachedToInvocation(t, inv) + stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv) ctx := testutil.Context(t, testutil.WaitMedium) inv = inv.WithContext(ctx) @@ -248,8 +254,8 @@ func TestTemplatePush(t *testing.T) { { ctx := testutil.Context(t, testutil.WaitMedium) - pty.ExpectNoMatchBefore(ctx, "No .terraform.lock.hcl file found", "Upload") - pty.WriteLine("no") + stdout.ExpectNoMatchBefore(ctx, "No .terraform.lock.hcl file found", "Upload") + stdin.WriteLine("no") } // cmd should error once we say no. @@ -258,6 +264,7 @@ func TestTemplatePush(t *testing.T) { t.Run("PushInactiveTemplateVersion", func(t *testing.T) { t.Parallel() + logger := testutil.Logger(t) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) owner := coderdtest.CreateFirstUser(t, client) templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) @@ -278,7 +285,8 @@ func TestTemplatePush(t *testing.T) { "--name", "example", ) clitest.SetupConfig(t, templateAdmin, root) - pty := ptytest.New(t).Attach(inv) + stdout := expecter.NewAttachedToInvocation(t, inv) + stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv) ctx := testutil.Context(t, testutil.WaitMedium) inv = inv.WithContext(ctx) w := clitest.StartWithWaiter(t, inv) @@ -290,8 +298,8 @@ func TestTemplatePush(t *testing.T) { {match: "Upload", write: "yes"}, } for _, m := range matches { - pty.ExpectMatchContext(ctx, m.match) - pty.WriteLine(m.write) + stdout.ExpectMatchContext(ctx, m.match) + stdin.WriteLine(m.write) } w.RequireSuccess() @@ -309,11 +317,11 @@ func TestTemplatePush(t *testing.T) { t.Run("UseWorkingDir", func(t *testing.T) { t.Parallel() - if runtime.GOOS == "windows" { t.Skip(`On Windows this test flakes with: "The process cannot access the file because it is being used by another process"`) } + logger := testutil.Logger(t) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) owner := coderdtest.CreateFirstUser(t, client) templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) @@ -339,7 +347,8 @@ func TestTemplatePush(t *testing.T) { "--force-tty", ) clitest.SetupConfig(t, templateAdmin, root) - pty := ptytest.New(t).Attach(inv) + stdout := expecter.NewAttachedToInvocation(t, inv) + stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv) ctx := testutil.Context(t, testutil.WaitMedium) inv = inv.WithContext(ctx) @@ -352,8 +361,8 @@ func TestTemplatePush(t *testing.T) { {match: "Upload", write: "yes"}, } for _, m := range matches { - pty.ExpectMatchContext(ctx, m.match) - pty.WriteLine(m.write) + stdout.ExpectMatchContext(ctx, m.match) + stdin.WriteLine(m.write) } w.RequireSuccess() @@ -390,9 +399,7 @@ func TestTemplatePush(t *testing.T) { template.Name, ) clitest.SetupConfig(t, templateAdmin, root) - pty := ptytest.New(t) inv.Stdin = bytes.NewReader(source) - inv.Stdout = pty.Output() execDone := make(chan error) go func() { @@ -539,7 +546,7 @@ func TestTemplatePush(t *testing.T) { inv, root := clitest.New(t, "templates", "push", templateName, "-d", tempDir, "--yes") clitest.SetupConfig(t, templateAdmin, root) - pty := ptytest.New(t).Attach(inv) + stdout := expecter.NewAttachedToInvocation(t, inv) setupCtx := testutil.Context(t, testutil.WaitMedium) now := dbtime.Now() @@ -561,7 +568,7 @@ func TestTemplatePush(t *testing.T) { }, testutil.WaitShort, testutil.IntervalFast) if tt.expectOutput != "" { - pty.ExpectMatchContext(ctx, tt.expectOutput) + stdout.ExpectMatchContext(ctx, tt.expectOutput) } }) } @@ -570,6 +577,7 @@ func TestTemplatePush(t *testing.T) { t.Run("ChangeTags", func(t *testing.T) { t.Parallel() + logger := testutil.Logger(t) // Start the first provisioner client, provisionerDocker, api := coderdtest.NewWithAPI(t, &coderdtest.Options{ IncludeProvisionerDaemon: true, @@ -605,7 +613,8 @@ func TestTemplatePush(t *testing.T) { inv, root := clitest.New(t, "templates", "push", template.Name, "--directory", source, "--test.provisioner", string(database.ProvisionerTypeEcho), "--name", template.Name, "--provisioner-tag", "foobar=foobaz") clitest.SetupConfig(t, templateAdmin, root) - pty := ptytest.New(t).Attach(inv) + stdout := expecter.NewAttachedToInvocation(t, inv) + stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv) ctx := testutil.Context(t, testutil.WaitMedium) inv = inv.WithContext(ctx) @@ -618,8 +627,8 @@ func TestTemplatePush(t *testing.T) { {match: "Upload", write: "yes"}, } for _, m := range matches { - pty.ExpectMatchContext(ctx, m.match) - pty.WriteLine(m.write) + stdout.ExpectMatchContext(ctx, m.match) + stdin.WriteLine(m.write) } w.RequireSuccess() @@ -636,6 +645,7 @@ func TestTemplatePush(t *testing.T) { t.Run("DeleteTags", func(t *testing.T) { t.Parallel() + logger := testutil.Logger(t) // Start the first provisioner with no tags. client, provisionerDocker, api := coderdtest.NewWithAPI(t, &coderdtest.Options{ IncludeProvisionerDaemon: true, @@ -671,7 +681,8 @@ func TestTemplatePush(t *testing.T) { }) inv, root := clitest.New(t, "templates", "push", template.Name, "--directory", source, "--test.provisioner", string(database.ProvisionerTypeEcho), "--name", template.Name, "--provisioner-tag=\"-\"") clitest.SetupConfig(t, templateAdmin, root) - pty := ptytest.New(t).Attach(inv) + stdout := expecter.NewAttachedToInvocation(t, inv) + stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv) ctx := testutil.Context(t, testutil.WaitMedium) inv = inv.WithContext(ctx) @@ -684,8 +695,8 @@ func TestTemplatePush(t *testing.T) { {match: "Upload", write: "yes"}, } for _, m := range matches { - pty.ExpectMatchContext(ctx, m.match) - pty.WriteLine(m.write) + stdout.ExpectMatchContext(ctx, m.match) + stdin.WriteLine(m.write) } w.RequireSuccess() @@ -702,6 +713,7 @@ func TestTemplatePush(t *testing.T) { t.Run("DoNotChangeTags", func(t *testing.T) { t.Parallel() + logger := testutil.Logger(t) // Start the tagged provisioner client := coderdtest.New(t, &coderdtest.Options{ IncludeProvisionerDaemon: true, @@ -728,7 +740,8 @@ func TestTemplatePush(t *testing.T) { }) inv, root := clitest.New(t, "templates", "push", template.Name, "--directory", source, "--test.provisioner", string(database.ProvisionerTypeEcho), "--name", template.Name) clitest.SetupConfig(t, templateAdmin, root) - pty := ptytest.New(t).Attach(inv) + stdout := expecter.NewAttachedToInvocation(t, inv) + stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv) ctx := testutil.Context(t, testutil.WaitMedium) inv = inv.WithContext(ctx) @@ -741,8 +754,8 @@ func TestTemplatePush(t *testing.T) { {match: "Upload", write: "yes"}, } for _, m := range matches { - pty.ExpectMatchContext(ctx, m.match) - pty.WriteLine(m.write) + stdout.ExpectMatchContext(ctx, m.match) + stdin.WriteLine(m.write) } w.RequireSuccess() @@ -773,6 +786,7 @@ func TestTemplatePush(t *testing.T) { t.Run("VariableIsRequired", func(t *testing.T) { t.Parallel() + logger := testutil.Logger(t) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) owner := coderdtest.CreateFirstUser(t, client) templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) @@ -803,9 +817,8 @@ func TestTemplatePush(t *testing.T) { "--variables-file", variablesFile.Name(), ) clitest.SetupConfig(t, templateAdmin, root) - pty := ptytest.New(t) - inv.Stdin = pty.Input() - inv.Stdout = pty.Output() + stdout := expecter.NewAttachedToInvocation(t, inv) + stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv) ctx := testutil.Context(t, testutil.WaitMedium) inv = inv.WithContext(ctx) @@ -818,8 +831,8 @@ func TestTemplatePush(t *testing.T) { {match: "Upload", write: "yes"}, } for _, m := range matches { - pty.ExpectMatchContext(ctx, m.match) - pty.WriteLine(m.write) + stdout.ExpectMatchContext(ctx, m.match) + stdin.WriteLine(m.write) } w.RequireSuccess() @@ -842,6 +855,7 @@ func TestTemplatePush(t *testing.T) { t.Run("VariableIsOptionalButNotProvided", func(t *testing.T) { t.Parallel() + logger := testutil.Logger(t) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) owner := coderdtest.CreateFirstUser(t, client) templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) @@ -868,9 +882,8 @@ func TestTemplatePush(t *testing.T) { "--name", "example", ) clitest.SetupConfig(t, templateAdmin, root) - pty := ptytest.New(t) - inv.Stdin = pty.Input() - inv.Stdout = pty.Output() + stdout := expecter.NewAttachedToInvocation(t, inv) + stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv) ctx := testutil.Context(t, testutil.WaitMedium) inv = inv.WithContext(ctx) @@ -883,8 +896,8 @@ func TestTemplatePush(t *testing.T) { {match: "Upload", write: "yes"}, } for _, m := range matches { - pty.ExpectMatchContext(ctx, m.match) - pty.WriteLine(m.write) + stdout.ExpectMatchContext(ctx, m.match) + stdin.WriteLine(m.write) } w.RequireSuccess() @@ -908,6 +921,7 @@ func TestTemplatePush(t *testing.T) { t.Run("WithVariableOption", func(t *testing.T) { t.Parallel() + logger := testutil.Logger(t) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) owner := coderdtest.CreateFirstUser(t, client) templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) @@ -935,9 +949,8 @@ func TestTemplatePush(t *testing.T) { "--variable", "second_variable=foobar", ) clitest.SetupConfig(t, templateAdmin, root) - pty := ptytest.New(t) - inv.Stdin = pty.Input() - inv.Stdout = pty.Output() + stdout := expecter.NewAttachedToInvocation(t, inv) + stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv) ctx := testutil.Context(t, testutil.WaitMedium) inv = inv.WithContext(ctx) @@ -950,8 +963,8 @@ func TestTemplatePush(t *testing.T) { {match: "Upload", write: "yes"}, } for _, m := range matches { - pty.ExpectMatchContext(ctx, m.match) - pty.WriteLine(m.write) + stdout.ExpectMatchContext(ctx, m.match) + stdin.WriteLine(m.write) } w.RequireSuccess() @@ -974,6 +987,7 @@ func TestTemplatePush(t *testing.T) { t.Run("CreateTemplate", func(t *testing.T) { t.Parallel() + logger := testutil.Logger(t) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) owner := coderdtest.CreateFirstUser(t, client) templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) @@ -989,7 +1003,8 @@ func TestTemplatePush(t *testing.T) { } inv, root := clitest.New(t, args...) clitest.SetupConfig(t, templateAdmin, root) - pty := ptytest.New(t).Attach(inv) + stdout := expecter.NewAttachedToInvocation(t, inv) + stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv) ctx := testutil.Context(t, testutil.WaitMedium) inv = inv.WithContext(ctx) @@ -1003,9 +1018,9 @@ func TestTemplatePush(t *testing.T) { {match: "template has been created"}, } for _, m := range matches { - pty.ExpectMatchContext(ctx, m.match) + stdout.ExpectMatchContext(ctx, m.match) if m.write != "" { - pty.WriteLine(m.write) + stdin.WriteLine(m.write) } } @@ -1056,6 +1071,7 @@ func TestTemplatePush(t *testing.T) { t.Run("PromptForDifferentRequiredTypes", func(t *testing.T) { t.Parallel() + logger := testutil.Logger(t) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) owner := coderdtest.CreateFirstUser(t, client) templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) @@ -1091,37 +1107,39 @@ func TestTemplatePush(t *testing.T) { source := clitest.CreateTemplateVersionSource(t, createEchoResponsesWithTemplateVariables(templateVariables)) inv, root := clitest.New(t, "templates", "push", "test-template", "--directory", source, "--test.provisioner", string(database.ProvisionerTypeEcho)) clitest.SetupConfig(t, templateAdmin, root) - pty := ptytest.New(t).Attach(inv) + stdout := expecter.NewAttachedToInvocation(t, inv) + stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv) ctx := testutil.Context(t, testutil.WaitMedium) inv = inv.WithContext(ctx) w := clitest.StartWithWaiter(t, inv) // Select "Yes" for the "Upload " prompt - pty.ExpectMatchContext(ctx, "Upload") - pty.WriteLine("yes") + stdout.ExpectMatchContext(ctx, "Upload") + stdin.WriteLine("yes") // Variables are prompted in alphabetical order. // Boolean variable automatically selects the first option ("true") - pty.ExpectMatchContext(ctx, "var.bool_var") + stdout.ExpectMatchContext(ctx, "var.bool_var") - pty.ExpectMatchContext(ctx, "var.number_var") - pty.ExpectMatchContext(ctx, "Enter value:") - pty.WriteLine("42") + stdout.ExpectMatchContext(ctx, "var.number_var") + stdout.ExpectMatchContext(ctx, "Enter value:") + stdin.WriteLine("42") - pty.ExpectMatchContext(ctx, "var.sensitive_var") - pty.ExpectMatchContext(ctx, "Enter value:") - pty.WriteLine("secret-value") + stdout.ExpectMatchContext(ctx, "var.sensitive_var") + stdout.ExpectMatchContext(ctx, "Enter value:") + stdin.WriteLine("secret-value") - pty.ExpectMatchContext(ctx, "var.string_var") - pty.ExpectMatchContext(ctx, "Enter value:") - pty.WriteLine("test-string") + stdout.ExpectMatchContext(ctx, "var.string_var") + stdout.ExpectMatchContext(ctx, "Enter value:") + stdin.WriteLine("test-string") w.RequireSuccess() }) t.Run("ValidateNumberInput", func(t *testing.T) { t.Parallel() + logger := testutil.Logger(t) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) owner := coderdtest.CreateFirstUser(t, client) templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) @@ -1138,28 +1156,30 @@ func TestTemplatePush(t *testing.T) { source := clitest.CreateTemplateVersionSource(t, createEchoResponsesWithTemplateVariables(templateVariables)) inv, root := clitest.New(t, "templates", "push", "test-template", "--directory", source, "--test.provisioner", string(database.ProvisionerTypeEcho)) clitest.SetupConfig(t, templateAdmin, root) - pty := ptytest.New(t).Attach(inv) + stdout := expecter.NewAttachedToInvocation(t, inv) + stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv) ctx := testutil.Context(t, testutil.WaitMedium) inv = inv.WithContext(ctx) w := clitest.StartWithWaiter(t, inv) // Select "Yes" for the "Upload " prompt - pty.ExpectMatchContext(ctx, "Upload") - pty.WriteLine("yes") + stdout.ExpectMatchContext(ctx, "Upload") + stdin.WriteLine("yes") - pty.ExpectMatchContext(ctx, "var.number_var") + stdout.ExpectMatchContext(ctx, "var.number_var") - pty.WriteLine("not-a-number") - pty.ExpectMatchContext(ctx, "must be a valid number") + stdin.WriteLine("not-a-number") + stdout.ExpectMatchContext(ctx, "must be a valid number") - pty.WriteLine("123.45") + stdin.WriteLine("123.45") w.RequireSuccess() }) t.Run("DontPromptForDefaultValues", func(t *testing.T) { t.Parallel() + logger := testutil.Logger(t) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) owner := coderdtest.CreateFirstUser(t, client) templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) @@ -1181,24 +1201,26 @@ func TestTemplatePush(t *testing.T) { source := clitest.CreateTemplateVersionSource(t, createEchoResponsesWithTemplateVariables(templateVariables)) inv, root := clitest.New(t, "templates", "push", "test-template", "--directory", source, "--test.provisioner", string(database.ProvisionerTypeEcho)) clitest.SetupConfig(t, templateAdmin, root) - pty := ptytest.New(t).Attach(inv) + stdout := expecter.NewAttachedToInvocation(t, inv) + stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv) ctx := testutil.Context(t, testutil.WaitMedium) inv = inv.WithContext(ctx) w := clitest.StartWithWaiter(t, inv) // Select "Yes" for the "Upload " prompt - pty.ExpectMatchContext(ctx, "Upload") - pty.WriteLine("yes") + stdout.ExpectMatchContext(ctx, "Upload") + stdin.WriteLine("yes") - pty.ExpectMatchContext(ctx, "var.without_default") - pty.WriteLine("test-value") + stdout.ExpectMatchContext(ctx, "var.without_default") + stdin.WriteLine("test-value") w.RequireSuccess() }) t.Run("VariableSourcesPriority", func(t *testing.T) { t.Parallel() + logger := testutil.Logger(t) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) owner := coderdtest.CreateFirstUser(t, client) templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) @@ -1250,20 +1272,21 @@ cli_overrides_file_var: from-file`) "--variable", "cli_overrides_file_var=from-cli-override", ) clitest.SetupConfig(t, templateAdmin, root) - pty := ptytest.New(t).Attach(inv) + stdout := expecter.NewAttachedToInvocation(t, inv) + stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv) ctx := testutil.Context(t, testutil.WaitMedium) inv = inv.WithContext(ctx) w := clitest.StartWithWaiter(t, inv) // Select "Yes" for the "Upload " prompt - pty.ExpectMatchContext(ctx, "Upload") - pty.WriteLine("yes") + stdout.ExpectMatchContext(ctx, "Upload") + stdin.WriteLine("yes") // Only check for prompt_var, other variables should not prompt - pty.ExpectMatchContext(ctx, "var.prompt_var") - pty.ExpectMatchContext(ctx, "Enter value:") - pty.WriteLine("from-prompt") + stdout.ExpectMatchContext(ctx, "var.prompt_var") + stdout.ExpectMatchContext(ctx, "Enter value:") + stdin.WriteLine("from-prompt") w.RequireSuccess()