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.
This commit is contained in:
Spike Curtis
2026-06-02 08:05:26 -04:00
committed by GitHub
parent bfa6ce32a6
commit 93b067f5f2
7 changed files with 184 additions and 141 deletions
+30 -18
View File
@@ -14,14 +14,16 @@ import (
"github.com/coder/coder/v2/coderd/database" "github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/provisioner/echo" "github.com/coder/coder/v2/provisioner/echo"
"github.com/coder/coder/v2/provisionersdk/proto" "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"
"github.com/coder/coder/v2/testutil/expecter"
) )
func TestCliTemplateCreate(t *testing.T) { func TestCliTemplateCreate(t *testing.T) {
t.Parallel() t.Parallel()
t.Run("Create", func(t *testing.T) { t.Run("Create", func(t *testing.T) {
t.Parallel() t.Parallel()
logger := testutil.Logger(t)
ctx := testutil.Context(t, testutil.WaitMedium)
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
coderdtest.CreateFirstUser(t, client) coderdtest.CreateFirstUser(t, client)
source := clitest.CreateTemplateVersionSource(t, completeWithAgent()) source := clitest.CreateTemplateVersionSource(t, completeWithAgent())
@@ -35,7 +37,8 @@ func TestCliTemplateCreate(t *testing.T) {
} }
inv, root := clitest.New(t, args...) inv, root := clitest.New(t, args...)
clitest.SetupConfig(t, client, root) 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) clitest.Start(t, inv)
@@ -49,14 +52,16 @@ func TestCliTemplateCreate(t *testing.T) {
{match: "Confirm create?", write: "yes"}, {match: "Confirm create?", write: "yes"},
} }
for _, m := range matches { for _, m := range matches {
pty.ExpectMatch(m.match) stdout.ExpectMatchContext(ctx, m.match)
if len(m.write) > 0 { if len(m.write) > 0 {
pty.WriteLine(m.write) stdin.WriteLine(m.write)
} }
} }
}) })
t.Run("CreateNoLockfile", func(t *testing.T) { t.Run("CreateNoLockfile", func(t *testing.T) {
t.Parallel() t.Parallel()
logger := testutil.Logger(t)
ctx := testutil.Context(t, testutil.WaitMedium)
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
coderdtest.CreateFirstUser(t, client) coderdtest.CreateFirstUser(t, client)
source := clitest.CreateTemplateVersionSource(t, completeWithAgent()) source := clitest.CreateTemplateVersionSource(t, completeWithAgent())
@@ -71,7 +76,8 @@ func TestCliTemplateCreate(t *testing.T) {
} }
inv, root := clitest.New(t, args...) inv, root := clitest.New(t, args...)
clitest.SetupConfig(t, client, root) 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) execDone := make(chan error)
go func() { go func() {
@@ -86,9 +92,9 @@ func TestCliTemplateCreate(t *testing.T) {
{match: "Upload", write: "no"}, {match: "Upload", write: "no"},
} }
for _, m := range matches { for _, m := range matches {
pty.ExpectMatch(m.match) stdout.ExpectMatchContext(ctx, m.match)
if len(m.write) > 0 { 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.Run("CreateNoLockfileIgnored", func(t *testing.T) {
t.Parallel() t.Parallel()
logger := testutil.Logger(t)
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
coderdtest.CreateFirstUser(t, client) coderdtest.CreateFirstUser(t, client)
source := clitest.CreateTemplateVersionSource(t, completeWithAgent()) source := clitest.CreateTemplateVersionSource(t, completeWithAgent())
@@ -112,7 +119,8 @@ func TestCliTemplateCreate(t *testing.T) {
} }
inv, root := clitest.New(t, args...) inv, root := clitest.New(t, args...)
clitest.SetupConfig(t, client, root) 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) execDone := make(chan error)
go func() { go func() {
@@ -123,8 +131,8 @@ func TestCliTemplateCreate(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitMedium) ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitMedium)
defer cancel() defer cancel()
pty.ExpectNoMatchBefore(ctx, "No .terraform.lock.hcl file found", "Upload") stdout.ExpectNoMatchBefore(ctx, "No .terraform.lock.hcl file found", "Upload")
pty.WriteLine("no") stdin.WriteLine("no")
} }
// cmd should error once we say no. // cmd should error once we say no.
@@ -148,9 +156,7 @@ func TestCliTemplateCreate(t *testing.T) {
} }
inv, root := clitest.New(t, args...) inv, root := clitest.New(t, args...)
clitest.SetupConfig(t, client, root) clitest.SetupConfig(t, client, root)
pty := ptytest.New(t)
inv.Stdin = bytes.NewReader(source) inv.Stdin = bytes.NewReader(source)
inv.Stdout = pty.Output()
require.NoError(t, inv.Run()) require.NoError(t, inv.Run())
}) })
@@ -199,6 +205,8 @@ func TestCliTemplateCreate(t *testing.T) {
t.Run("WithVariablesFileWithTheRequiredValue", func(t *testing.T) { t.Run("WithVariablesFileWithTheRequiredValue", func(t *testing.T) {
t.Parallel() t.Parallel()
logger := testutil.Logger(t)
ctx := testutil.Context(t, testutil.WaitMedium)
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
coderdtest.CreateFirstUser(t, client) coderdtest.CreateFirstUser(t, client)
@@ -227,7 +235,8 @@ func TestCliTemplateCreate(t *testing.T) {
_, _ = variablesFile.WriteString(`first_variable: foobar`) _, _ = 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()) 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) 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) clitest.Start(t, inv)
@@ -239,15 +248,17 @@ func TestCliTemplateCreate(t *testing.T) {
{match: "Confirm create?", write: "yes"}, {match: "Confirm create?", write: "yes"},
} }
for _, m := range matches { for _, m := range matches {
pty.ExpectMatch(m.match) stdout.ExpectMatchContext(ctx, m.match)
if len(m.write) > 0 { if len(m.write) > 0 {
pty.WriteLine(m.write) stdin.WriteLine(m.write)
} }
} }
}) })
t.Run("WithVariableOption", func(t *testing.T) { t.Run("WithVariableOption", func(t *testing.T) {
t.Parallel() t.Parallel()
logger := testutil.Logger(t)
ctx := testutil.Context(t, testutil.WaitMedium)
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
coderdtest.CreateFirstUser(t, client) coderdtest.CreateFirstUser(t, client)
@@ -264,7 +275,8 @@ func TestCliTemplateCreate(t *testing.T) {
createEchoResponsesWithTemplateVariables(templateVariables)) createEchoResponsesWithTemplateVariables(templateVariables))
inv, root := clitest.New(t, "templates", "create", "my-template", "--directory", source, "--test.provisioner", string(database.ProvisionerTypeEcho), "--variable", "first_variable=foobar") 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) 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) clitest.Start(t, inv)
@@ -276,9 +288,9 @@ func TestCliTemplateCreate(t *testing.T) {
{match: "Confirm create?", write: "yes"}, {match: "Confirm create?", write: "yes"},
} }
for _, m := range matches { for _, m := range matches {
pty.ExpectMatch(m.match) stdout.ExpectMatchContext(ctx, m.match)
if len(m.write) > 0 { if len(m.write) > 0 {
pty.WriteLine(m.write) stdin.WriteLine(m.write)
} }
} }
}) })
+19 -9
View File
@@ -13,7 +13,8 @@ import (
"github.com/coder/coder/v2/coderd/coderdtest" "github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/coderd/rbac" "github.com/coder/coder/v2/coderd/rbac"
"github.com/coder/coder/v2/codersdk" "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" "github.com/coder/pretty"
) )
@@ -23,6 +24,8 @@ func TestTemplateDelete(t *testing.T) {
t.Run("Ok", func(t *testing.T) { t.Run("Ok", func(t *testing.T) {
t.Parallel() t.Parallel()
logger := testutil.Logger(t)
ctx := testutil.Context(t, testutil.WaitMedium)
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) 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) inv, root := clitest.New(t, "templates", "delete", template.Name)
clitest.SetupConfig(t, templateAdmin, root) 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) execDone := make(chan error)
go func() { go func() {
execDone <- inv.Run() execDone <- inv.Run()
}() }()
pty.ExpectMatch(fmt.Sprintf("Delete these templates: %s?", pretty.Sprint(cliui.DefaultStyles.Code, template.Name))) stdout.ExpectMatchContext(ctx, fmt.Sprintf("Delete these templates: %s?", pretty.Sprint(cliui.DefaultStyles.Code, template.Name)))
pty.WriteLine("yes") stdin.WriteLine("yes")
require.NoError(t, <-execDone) require.NoError(t, <-execDone)
@@ -78,6 +82,8 @@ func TestTemplateDelete(t *testing.T) {
t.Run("Multiple prompted", func(t *testing.T) { t.Run("Multiple prompted", func(t *testing.T) {
t.Parallel() t.Parallel()
logger := testutil.Logger(t)
ctx := testutil.Context(t, testutil.WaitMedium)
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) 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...)...) inv, root := clitest.New(t, append([]string{"templates", "delete"}, templateNames...)...)
clitest.SetupConfig(t, templateAdmin, root) 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) execDone := make(chan error)
go func() { go func() {
execDone <- inv.Run() execDone <- inv.Run()
}() }()
pty.ExpectMatch(fmt.Sprintf("Delete these templates: %s?", pretty.Sprint(cliui.DefaultStyles.Code, strings.Join(templateNames, ", ")))) stdout.ExpectMatchContext(ctx,
pty.WriteLine("yes") fmt.Sprintf("Delete these templates: %s?",
pretty.Sprint(cliui.DefaultStyles.Code, strings.Join(templateNames, ", "))))
stdin.WriteLine("yes")
require.NoError(t, <-execDone) require.NoError(t, <-execDone)
@@ -114,6 +123,7 @@ func TestTemplateDelete(t *testing.T) {
t.Run("Selector", func(t *testing.T) { t.Run("Selector", func(t *testing.T) {
t.Parallel() t.Parallel()
logger := testutil.Logger(t)
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) 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") inv, root := clitest.New(t, "templates", "delete")
clitest.SetupConfig(t, templateAdmin, root) clitest.SetupConfig(t, templateAdmin, root)
pty := ptytest.New(t).Attach(inv) stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv)
execDone := make(chan error) execDone := make(chan error)
go func() { go func() {
execDone <- inv.Run() execDone <- inv.Run()
}() }()
pty.WriteLine("yes") stdin.WriteLine("yes")
require.NoError(t, <-execDone) require.NoError(t, <-execDone)
_, err := client.Template(context.Background(), template.ID) _, err := client.Template(context.Background(), template.ID)
-4
View File
@@ -7,7 +7,6 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/coder/coder/v2/cli/clitest" "github.com/coder/coder/v2/cli/clitest"
"github.com/coder/coder/v2/pty/ptytest"
) )
func TestTemplateInit(t *testing.T) { func TestTemplateInit(t *testing.T) {
@@ -16,7 +15,6 @@ func TestTemplateInit(t *testing.T) {
t.Parallel() t.Parallel()
tempDir := t.TempDir() tempDir := t.TempDir()
inv, _ := clitest.New(t, "templates", "init", tempDir) inv, _ := clitest.New(t, "templates", "init", tempDir)
ptytest.New(t).Attach(inv)
clitest.Run(t, inv) clitest.Run(t, inv)
files, err := os.ReadDir(tempDir) files, err := os.ReadDir(tempDir)
require.NoError(t, err) require.NoError(t, err)
@@ -27,7 +25,6 @@ func TestTemplateInit(t *testing.T) {
t.Parallel() t.Parallel()
tempDir := t.TempDir() tempDir := t.TempDir()
inv, _ := clitest.New(t, "templates", "init", "--id", "docker", tempDir) inv, _ := clitest.New(t, "templates", "init", "--id", "docker", tempDir)
ptytest.New(t).Attach(inv)
clitest.Run(t, inv) clitest.Run(t, inv)
files, err := os.ReadDir(tempDir) files, err := os.ReadDir(tempDir)
require.NoError(t, err) require.NoError(t, err)
@@ -38,7 +35,6 @@ func TestTemplateInit(t *testing.T) {
t.Parallel() t.Parallel()
tempDir := t.TempDir() tempDir := t.TempDir()
inv, _ := clitest.New(t, "templates", "init", "--id", "thistemplatedoesnotexist", tempDir) inv, _ := clitest.New(t, "templates", "init", "--id", "thistemplatedoesnotexist", tempDir)
ptytest.New(t).Attach(inv)
err := inv.Run() err := inv.Run()
require.ErrorContains(t, err, "invalid choice: thistemplatedoesnotexist, should be one of") require.ErrorContains(t, err, "invalid choice: thistemplatedoesnotexist, should be one of")
files, err := os.ReadDir(tempDir) files, err := os.ReadDir(tempDir)
+6 -8
View File
@@ -13,8 +13,8 @@ import (
"github.com/coder/coder/v2/coderd/coderdtest" "github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/coderd/rbac" "github.com/coder/coder/v2/coderd/rbac"
"github.com/coder/coder/v2/codersdk" "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"
"github.com/coder/coder/v2/testutil/expecter"
) )
func TestTemplateList(t *testing.T) { func TestTemplateList(t *testing.T) {
@@ -35,7 +35,7 @@ func TestTemplateList(t *testing.T) {
inv, root := clitest.New(t, "templates", "list") inv, root := clitest.New(t, "templates", "list")
clitest.SetupConfig(t, templateAdmin, root) clitest.SetupConfig(t, templateAdmin, root)
pty := ptytest.New(t).Attach(inv) stdout := expecter.NewAttachedToInvocation(t, inv)
ctx, cancelFunc := context.WithTimeout(context.Background(), testutil.WaitLong) ctx, cancelFunc := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancelFunc() defer cancelFunc()
@@ -52,7 +52,7 @@ func TestTemplateList(t *testing.T) {
require.NoError(t, <-errC) require.NoError(t, <-errC)
for _, name := range templatesList { for _, name := range templatesList {
pty.ExpectMatch(name) stdout.ExpectMatchContext(ctx, name)
} }
}) })
t.Run("ListTemplatesJSON", func(t *testing.T) { t.Run("ListTemplatesJSON", func(t *testing.T) {
@@ -93,9 +93,7 @@ func TestTemplateList(t *testing.T) {
inv, root := clitest.New(t, "templates", "list") inv, root := clitest.New(t, "templates", "list")
clitest.SetupConfig(t, templateAdmin, root) clitest.SetupConfig(t, templateAdmin, root)
pty := ptytest.New(t) stdout := expecter.NewAttachedToInvocation(t, inv)
inv.Stdin = pty.Input()
inv.Stderr = pty.Output()
ctx, cancelFunc := context.WithTimeout(context.Background(), testutil.WaitLong) ctx, cancelFunc := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancelFunc() defer cancelFunc()
@@ -107,7 +105,7 @@ func TestTemplateList(t *testing.T) {
require.NoError(t, <-errC) require.NoError(t, <-errC)
pty.ExpectMatch("No templates found") stdout.ExpectMatchContext(ctx, "No templates found")
pty.ExpectMatch("Create one:") stdout.ExpectMatchContext(ctx, "Create one:")
}) })
} }
+15 -13
View File
@@ -14,8 +14,8 @@ import (
"github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/provisioner/echo" "github.com/coder/coder/v2/provisioner/echo"
"github.com/coder/coder/v2/provisionersdk/proto" "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"
"github.com/coder/coder/v2/testutil/expecter"
) )
func TestTemplatePresets(t *testing.T) { func TestTemplatePresets(t *testing.T) {
@@ -24,6 +24,7 @@ func TestTemplatePresets(t *testing.T) {
t.Run("NoPresets", func(t *testing.T) { t.Run("NoPresets", func(t *testing.T) {
t.Parallel() t.Parallel()
ctx := testutil.Context(t, testutil.WaitMedium)
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
member, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID) 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) inv, root := clitest.New(t, "templates", "presets", "list", template.Name)
clitest.SetupConfig(t, member, root) clitest.SetupConfig(t, member, root)
pty := ptytest.New(t).Attach(inv) stdout := expecter.NewAttachedToInvocation(t, inv)
doneChan := make(chan struct{}) doneChan := make(chan struct{})
var runErr error var runErr error
go func() { 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. // 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) 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.Run("ListsPresetsForDefaultTemplateVersion", func(t *testing.T) {
t.Parallel() t.Parallel()
ctx := testutil.Context(t, testutil.WaitMedium)
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
member, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID) 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) inv, root := clitest.New(t, "templates", "presets", "list", template.Name)
clitest.SetupConfig(t, member, root) clitest.SetupConfig(t, member, root)
pty := ptytest.New(t).Attach(inv) stdout := expecter.NewAttachedToInvocation(t, inv)
doneChan := make(chan struct{}) doneChan := make(chan struct{})
var runErr error var runErr error
go func() { go func() {
@@ -117,11 +119,11 @@ func TestTemplatePresets(t *testing.T) {
// Should: return the active version's presets sorted by name // 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) message := fmt.Sprintf("Showing presets for template %q and template version %q.", template.Name, version.Name)
pty.ExpectMatch(message) stdout.ExpectMatchContext(ctx, message)
pty.ExpectRegexMatch(`preset-default\s+k1=v2\s+true\s+0`) 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 // 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+-`) stdout.ExpectRegexMatchContext(ctx, `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-prebuilds\s+Preset without parameters and 2 prebuild instances.\s+\s+false\s+2`)
}) })
t.Run("ListsPresetsForSpecifiedTemplateVersion", func(t *testing.T) { 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) inv, root := clitest.New(t, "templates", "presets", "list", updatedTemplate.Name, "--template-version", version.Name)
clitest.SetupConfig(t, member, root) clitest.SetupConfig(t, member, root)
pty := ptytest.New(t).Attach(inv) stdout := expecter.NewAttachedToInvocation(t, inv)
doneChan := make(chan struct{}) doneChan := make(chan struct{})
var runErr error var runErr error
go func() { go func() {
@@ -209,11 +211,11 @@ func TestTemplatePresets(t *testing.T) {
// Should: return the specified version's presets sorted by name // 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) message := fmt.Sprintf("Showing presets for template %q and template version %q.", template.Name, version.Name)
pty.ExpectMatch(message) stdout.ExpectMatchContext(ctx, message)
pty.ExpectRegexMatch(`preset-default\s+k1=v2\s+true\s+0`) 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 // 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+-`) stdout.ExpectRegexMatchContext(ctx, `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-prebuilds\s+Preset without parameters and 2 prebuild instances.\s+\s+false\s+2`)
}) })
t.Run("ListsPresetsJSON", func(t *testing.T) { t.Run("ListsPresetsJSON", func(t *testing.T) {
+8 -6
View File
@@ -21,7 +21,8 @@ import (
"github.com/coder/coder/v2/provisioner/echo" "github.com/coder/coder/v2/provisioner/echo"
"github.com/coder/coder/v2/provisionersdk" "github.com/coder/coder/v2/provisionersdk"
"github.com/coder/coder/v2/provisionersdk/proto" "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. // 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) inv, root := clitest.New(t, "templates", "pull", template.Name, actualDest)
clitest.SetupConfig(t, templateAdmin, root) clitest.SetupConfig(t, templateAdmin, root)
ptytest.New(t).Attach(inv)
require.NoError(t, inv.Run()) require.NoError(t, inv.Run())
// Validate behavior of choosing template name in the absence of an output path argument. // 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) { func TestTemplatePull_FolderConflict(t *testing.T) {
t.Parallel() t.Parallel()
logger := testutil.Logger(t)
ctx := testutil.Context(t, testutil.WaitMedium)
client := coderdtest.New(t, &coderdtest.Options{ client := coderdtest.New(t, &coderdtest.Options{
IncludeProvisionerDaemon: true, IncludeProvisionerDaemon: true,
}) })
@@ -389,12 +390,13 @@ func TestTemplatePull_FolderConflict(t *testing.T) {
inv, root := clitest.New(t, "templates", "pull", template.Name, conflictDest) inv, root := clitest.New(t, "templates", "pull", template.Name, conflictDest)
clitest.SetupConfig(t, templateAdmin, root) 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) waiter := clitest.StartWithWaiter(t, inv)
pty.ExpectMatch("not empty") stdout.ExpectMatchContext(ctx, "not empty")
pty.WriteLine("no") stdin.WriteLine("no")
waiter.RequireError() waiter.RequireError()
+106 -83
View File
@@ -26,8 +26,8 @@ import (
"github.com/coder/coder/v2/provisioner/terraform/tfparse" "github.com/coder/coder/v2/provisioner/terraform/tfparse"
"github.com/coder/coder/v2/provisionersdk" "github.com/coder/coder/v2/provisionersdk"
"github.com/coder/coder/v2/provisionersdk/proto" "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"
"github.com/coder/coder/v2/testutil/expecter"
) )
func TestTemplatePush(t *testing.T) { func TestTemplatePush(t *testing.T) {
@@ -35,6 +35,7 @@ func TestTemplatePush(t *testing.T) {
t.Run("OK", func(t *testing.T) { t.Run("OK", func(t *testing.T) {
t.Parallel() t.Parallel()
logger := testutil.Logger(t)
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) 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") inv, root := clitest.New(t, "templates", "push", template.Name, "--directory", source, "--test.provisioner", string(database.ProvisionerTypeEcho), "--name", "example")
clitest.SetupConfig(t, templateAdmin, root) 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) ctx := testutil.Context(t, testutil.WaitMedium)
inv = inv.WithContext(ctx) inv = inv.WithContext(ctx)
@@ -63,8 +65,8 @@ func TestTemplatePush(t *testing.T) {
{match: "Upload", write: "yes"}, {match: "Upload", write: "yes"},
} }
for _, m := range matches { for _, m := range matches {
pty.ExpectMatchContext(ctx, m.match) stdout.ExpectMatchContext(ctx, m.match)
pty.WriteLine(m.write) stdin.WriteLine(m.write)
} }
w.RequireSuccess() 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") 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) clitest.SetupConfig(t, templateAdmin, root)
pty := ptytest.New(t).Attach(inv) stdout := expecter.NewAttachedToInvocation(t, inv)
ctx := testutil.Context(t, testutil.WaitMedium) ctx := testutil.Context(t, testutil.WaitMedium)
inv = inv.WithContext(ctx) inv = inv.WithContext(ctx)
w := clitest.StartWithWaiter(t, inv) 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() w.RequireSuccess()
@@ -146,13 +148,13 @@ func TestTemplatePush(t *testing.T) {
"--yes", "--yes",
) )
clitest.SetupConfig(t, templateAdmin, root) clitest.SetupConfig(t, templateAdmin, root)
pty := ptytest.New(t).Attach(inv) stdout := expecter.NewAttachedToInvocation(t, inv)
ctx := testutil.Context(t, testutil.WaitMedium) ctx := testutil.Context(t, testutil.WaitMedium)
inv = inv.WithContext(ctx) inv = inv.WithContext(ctx)
w := clitest.StartWithWaiter(t, inv) w := clitest.StartWithWaiter(t, inv)
pty.ExpectMatchContext(ctx, tt.wantMatch) stdout.ExpectMatchContext(ctx, tt.wantMatch)
w.RequireSuccess() w.RequireSuccess()
@@ -170,6 +172,7 @@ func TestTemplatePush(t *testing.T) {
t.Run("NoLockfile", func(t *testing.T) { t.Run("NoLockfile", func(t *testing.T) {
t.Parallel() t.Parallel()
logger := testutil.Logger(t)
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin())
@@ -191,7 +194,8 @@ func TestTemplatePush(t *testing.T) {
"--name", "example", "--name", "example",
) )
clitest.SetupConfig(t, templateAdmin, root) 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) ctx := testutil.Context(t, testutil.WaitMedium)
inv = inv.WithContext(ctx) inv = inv.WithContext(ctx)
@@ -205,9 +209,9 @@ func TestTemplatePush(t *testing.T) {
{match: "Upload", write: "no"}, {match: "Upload", write: "no"},
} }
for _, m := range matches { for _, m := range matches {
pty.ExpectMatchContext(ctx, m.match) stdout.ExpectMatchContext(ctx, m.match)
if m.write != "" { 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.Run("NoLockfileIgnored", func(t *testing.T) {
t.Parallel() t.Parallel()
logger := testutil.Logger(t)
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin())
@@ -239,7 +244,8 @@ func TestTemplatePush(t *testing.T) {
"--ignore-lockfile", "--ignore-lockfile",
) )
clitest.SetupConfig(t, templateAdmin, root) 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) ctx := testutil.Context(t, testutil.WaitMedium)
inv = inv.WithContext(ctx) inv = inv.WithContext(ctx)
@@ -248,8 +254,8 @@ func TestTemplatePush(t *testing.T) {
{ {
ctx := testutil.Context(t, testutil.WaitMedium) ctx := testutil.Context(t, testutil.WaitMedium)
pty.ExpectNoMatchBefore(ctx, "No .terraform.lock.hcl file found", "Upload") stdout.ExpectNoMatchBefore(ctx, "No .terraform.lock.hcl file found", "Upload")
pty.WriteLine("no") stdin.WriteLine("no")
} }
// cmd should error once we say 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.Run("PushInactiveTemplateVersion", func(t *testing.T) {
t.Parallel() t.Parallel()
logger := testutil.Logger(t)
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin())
@@ -278,7 +285,8 @@ func TestTemplatePush(t *testing.T) {
"--name", "example", "--name", "example",
) )
clitest.SetupConfig(t, templateAdmin, root) 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) ctx := testutil.Context(t, testutil.WaitMedium)
inv = inv.WithContext(ctx) inv = inv.WithContext(ctx)
w := clitest.StartWithWaiter(t, inv) w := clitest.StartWithWaiter(t, inv)
@@ -290,8 +298,8 @@ func TestTemplatePush(t *testing.T) {
{match: "Upload", write: "yes"}, {match: "Upload", write: "yes"},
} }
for _, m := range matches { for _, m := range matches {
pty.ExpectMatchContext(ctx, m.match) stdout.ExpectMatchContext(ctx, m.match)
pty.WriteLine(m.write) stdin.WriteLine(m.write)
} }
w.RequireSuccess() w.RequireSuccess()
@@ -309,11 +317,11 @@ func TestTemplatePush(t *testing.T) {
t.Run("UseWorkingDir", func(t *testing.T) { t.Run("UseWorkingDir", func(t *testing.T) {
t.Parallel() t.Parallel()
if runtime.GOOS == "windows" { 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"`) 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}) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin())
@@ -339,7 +347,8 @@ func TestTemplatePush(t *testing.T) {
"--force-tty", "--force-tty",
) )
clitest.SetupConfig(t, templateAdmin, root) 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) ctx := testutil.Context(t, testutil.WaitMedium)
inv = inv.WithContext(ctx) inv = inv.WithContext(ctx)
@@ -352,8 +361,8 @@ func TestTemplatePush(t *testing.T) {
{match: "Upload", write: "yes"}, {match: "Upload", write: "yes"},
} }
for _, m := range matches { for _, m := range matches {
pty.ExpectMatchContext(ctx, m.match) stdout.ExpectMatchContext(ctx, m.match)
pty.WriteLine(m.write) stdin.WriteLine(m.write)
} }
w.RequireSuccess() w.RequireSuccess()
@@ -390,9 +399,7 @@ func TestTemplatePush(t *testing.T) {
template.Name, template.Name,
) )
clitest.SetupConfig(t, templateAdmin, root) clitest.SetupConfig(t, templateAdmin, root)
pty := ptytest.New(t)
inv.Stdin = bytes.NewReader(source) inv.Stdin = bytes.NewReader(source)
inv.Stdout = pty.Output()
execDone := make(chan error) execDone := make(chan error)
go func() { go func() {
@@ -539,7 +546,7 @@ func TestTemplatePush(t *testing.T) {
inv, root := clitest.New(t, "templates", "push", templateName, "-d", tempDir, "--yes") inv, root := clitest.New(t, "templates", "push", templateName, "-d", tempDir, "--yes")
clitest.SetupConfig(t, templateAdmin, root) clitest.SetupConfig(t, templateAdmin, root)
pty := ptytest.New(t).Attach(inv) stdout := expecter.NewAttachedToInvocation(t, inv)
setupCtx := testutil.Context(t, testutil.WaitMedium) setupCtx := testutil.Context(t, testutil.WaitMedium)
now := dbtime.Now() now := dbtime.Now()
@@ -561,7 +568,7 @@ func TestTemplatePush(t *testing.T) {
}, testutil.WaitShort, testutil.IntervalFast) }, testutil.WaitShort, testutil.IntervalFast)
if tt.expectOutput != "" { 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.Run("ChangeTags", func(t *testing.T) {
t.Parallel() t.Parallel()
logger := testutil.Logger(t)
// Start the first provisioner // Start the first provisioner
client, provisionerDocker, api := coderdtest.NewWithAPI(t, &coderdtest.Options{ client, provisionerDocker, api := coderdtest.NewWithAPI(t, &coderdtest.Options{
IncludeProvisionerDaemon: true, 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, inv, root := clitest.New(t, "templates", "push", template.Name, "--directory", source, "--test.provisioner", string(database.ProvisionerTypeEcho), "--name", template.Name,
"--provisioner-tag", "foobar=foobaz") "--provisioner-tag", "foobar=foobaz")
clitest.SetupConfig(t, templateAdmin, root) 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) ctx := testutil.Context(t, testutil.WaitMedium)
inv = inv.WithContext(ctx) inv = inv.WithContext(ctx)
@@ -618,8 +627,8 @@ func TestTemplatePush(t *testing.T) {
{match: "Upload", write: "yes"}, {match: "Upload", write: "yes"},
} }
for _, m := range matches { for _, m := range matches {
pty.ExpectMatchContext(ctx, m.match) stdout.ExpectMatchContext(ctx, m.match)
pty.WriteLine(m.write) stdin.WriteLine(m.write)
} }
w.RequireSuccess() w.RequireSuccess()
@@ -636,6 +645,7 @@ func TestTemplatePush(t *testing.T) {
t.Run("DeleteTags", func(t *testing.T) { t.Run("DeleteTags", func(t *testing.T) {
t.Parallel() t.Parallel()
logger := testutil.Logger(t)
// Start the first provisioner with no tags. // Start the first provisioner with no tags.
client, provisionerDocker, api := coderdtest.NewWithAPI(t, &coderdtest.Options{ client, provisionerDocker, api := coderdtest.NewWithAPI(t, &coderdtest.Options{
IncludeProvisionerDaemon: true, 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=\"-\"") 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) 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) ctx := testutil.Context(t, testutil.WaitMedium)
inv = inv.WithContext(ctx) inv = inv.WithContext(ctx)
@@ -684,8 +695,8 @@ func TestTemplatePush(t *testing.T) {
{match: "Upload", write: "yes"}, {match: "Upload", write: "yes"},
} }
for _, m := range matches { for _, m := range matches {
pty.ExpectMatchContext(ctx, m.match) stdout.ExpectMatchContext(ctx, m.match)
pty.WriteLine(m.write) stdin.WriteLine(m.write)
} }
w.RequireSuccess() w.RequireSuccess()
@@ -702,6 +713,7 @@ func TestTemplatePush(t *testing.T) {
t.Run("DoNotChangeTags", func(t *testing.T) { t.Run("DoNotChangeTags", func(t *testing.T) {
t.Parallel() t.Parallel()
logger := testutil.Logger(t)
// Start the tagged provisioner // Start the tagged provisioner
client := coderdtest.New(t, &coderdtest.Options{ client := coderdtest.New(t, &coderdtest.Options{
IncludeProvisionerDaemon: true, 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) inv, root := clitest.New(t, "templates", "push", template.Name, "--directory", source, "--test.provisioner", string(database.ProvisionerTypeEcho), "--name", template.Name)
clitest.SetupConfig(t, templateAdmin, root) 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) ctx := testutil.Context(t, testutil.WaitMedium)
inv = inv.WithContext(ctx) inv = inv.WithContext(ctx)
@@ -741,8 +754,8 @@ func TestTemplatePush(t *testing.T) {
{match: "Upload", write: "yes"}, {match: "Upload", write: "yes"},
} }
for _, m := range matches { for _, m := range matches {
pty.ExpectMatchContext(ctx, m.match) stdout.ExpectMatchContext(ctx, m.match)
pty.WriteLine(m.write) stdin.WriteLine(m.write)
} }
w.RequireSuccess() w.RequireSuccess()
@@ -773,6 +786,7 @@ func TestTemplatePush(t *testing.T) {
t.Run("VariableIsRequired", func(t *testing.T) { t.Run("VariableIsRequired", func(t *testing.T) {
t.Parallel() t.Parallel()
logger := testutil.Logger(t)
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin())
@@ -803,9 +817,8 @@ func TestTemplatePush(t *testing.T) {
"--variables-file", variablesFile.Name(), "--variables-file", variablesFile.Name(),
) )
clitest.SetupConfig(t, templateAdmin, root) clitest.SetupConfig(t, templateAdmin, root)
pty := ptytest.New(t) stdout := expecter.NewAttachedToInvocation(t, inv)
inv.Stdin = pty.Input() stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv)
inv.Stdout = pty.Output()
ctx := testutil.Context(t, testutil.WaitMedium) ctx := testutil.Context(t, testutil.WaitMedium)
inv = inv.WithContext(ctx) inv = inv.WithContext(ctx)
@@ -818,8 +831,8 @@ func TestTemplatePush(t *testing.T) {
{match: "Upload", write: "yes"}, {match: "Upload", write: "yes"},
} }
for _, m := range matches { for _, m := range matches {
pty.ExpectMatchContext(ctx, m.match) stdout.ExpectMatchContext(ctx, m.match)
pty.WriteLine(m.write) stdin.WriteLine(m.write)
} }
w.RequireSuccess() w.RequireSuccess()
@@ -842,6 +855,7 @@ func TestTemplatePush(t *testing.T) {
t.Run("VariableIsOptionalButNotProvided", func(t *testing.T) { t.Run("VariableIsOptionalButNotProvided", func(t *testing.T) {
t.Parallel() t.Parallel()
logger := testutil.Logger(t)
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin())
@@ -868,9 +882,8 @@ func TestTemplatePush(t *testing.T) {
"--name", "example", "--name", "example",
) )
clitest.SetupConfig(t, templateAdmin, root) clitest.SetupConfig(t, templateAdmin, root)
pty := ptytest.New(t) stdout := expecter.NewAttachedToInvocation(t, inv)
inv.Stdin = pty.Input() stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv)
inv.Stdout = pty.Output()
ctx := testutil.Context(t, testutil.WaitMedium) ctx := testutil.Context(t, testutil.WaitMedium)
inv = inv.WithContext(ctx) inv = inv.WithContext(ctx)
@@ -883,8 +896,8 @@ func TestTemplatePush(t *testing.T) {
{match: "Upload", write: "yes"}, {match: "Upload", write: "yes"},
} }
for _, m := range matches { for _, m := range matches {
pty.ExpectMatchContext(ctx, m.match) stdout.ExpectMatchContext(ctx, m.match)
pty.WriteLine(m.write) stdin.WriteLine(m.write)
} }
w.RequireSuccess() w.RequireSuccess()
@@ -908,6 +921,7 @@ func TestTemplatePush(t *testing.T) {
t.Run("WithVariableOption", func(t *testing.T) { t.Run("WithVariableOption", func(t *testing.T) {
t.Parallel() t.Parallel()
logger := testutil.Logger(t)
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin())
@@ -935,9 +949,8 @@ func TestTemplatePush(t *testing.T) {
"--variable", "second_variable=foobar", "--variable", "second_variable=foobar",
) )
clitest.SetupConfig(t, templateAdmin, root) clitest.SetupConfig(t, templateAdmin, root)
pty := ptytest.New(t) stdout := expecter.NewAttachedToInvocation(t, inv)
inv.Stdin = pty.Input() stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv)
inv.Stdout = pty.Output()
ctx := testutil.Context(t, testutil.WaitMedium) ctx := testutil.Context(t, testutil.WaitMedium)
inv = inv.WithContext(ctx) inv = inv.WithContext(ctx)
@@ -950,8 +963,8 @@ func TestTemplatePush(t *testing.T) {
{match: "Upload", write: "yes"}, {match: "Upload", write: "yes"},
} }
for _, m := range matches { for _, m := range matches {
pty.ExpectMatchContext(ctx, m.match) stdout.ExpectMatchContext(ctx, m.match)
pty.WriteLine(m.write) stdin.WriteLine(m.write)
} }
w.RequireSuccess() w.RequireSuccess()
@@ -974,6 +987,7 @@ func TestTemplatePush(t *testing.T) {
t.Run("CreateTemplate", func(t *testing.T) { t.Run("CreateTemplate", func(t *testing.T) {
t.Parallel() t.Parallel()
logger := testutil.Logger(t)
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin())
@@ -989,7 +1003,8 @@ func TestTemplatePush(t *testing.T) {
} }
inv, root := clitest.New(t, args...) inv, root := clitest.New(t, args...)
clitest.SetupConfig(t, templateAdmin, root) 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) ctx := testutil.Context(t, testutil.WaitMedium)
inv = inv.WithContext(ctx) inv = inv.WithContext(ctx)
@@ -1003,9 +1018,9 @@ func TestTemplatePush(t *testing.T) {
{match: "template has been created"}, {match: "template has been created"},
} }
for _, m := range matches { for _, m := range matches {
pty.ExpectMatchContext(ctx, m.match) stdout.ExpectMatchContext(ctx, m.match)
if m.write != "" { 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.Run("PromptForDifferentRequiredTypes", func(t *testing.T) {
t.Parallel() t.Parallel()
logger := testutil.Logger(t)
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin())
@@ -1091,37 +1107,39 @@ func TestTemplatePush(t *testing.T) {
source := clitest.CreateTemplateVersionSource(t, createEchoResponsesWithTemplateVariables(templateVariables)) source := clitest.CreateTemplateVersionSource(t, createEchoResponsesWithTemplateVariables(templateVariables))
inv, root := clitest.New(t, "templates", "push", "test-template", "--directory", source, "--test.provisioner", string(database.ProvisionerTypeEcho)) inv, root := clitest.New(t, "templates", "push", "test-template", "--directory", source, "--test.provisioner", string(database.ProvisionerTypeEcho))
clitest.SetupConfig(t, templateAdmin, root) 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) ctx := testutil.Context(t, testutil.WaitMedium)
inv = inv.WithContext(ctx) inv = inv.WithContext(ctx)
w := clitest.StartWithWaiter(t, inv) w := clitest.StartWithWaiter(t, inv)
// Select "Yes" for the "Upload <template_path>" prompt // Select "Yes" for the "Upload <template_path>" prompt
pty.ExpectMatchContext(ctx, "Upload") stdout.ExpectMatchContext(ctx, "Upload")
pty.WriteLine("yes") stdin.WriteLine("yes")
// Variables are prompted in alphabetical order. // Variables are prompted in alphabetical order.
// Boolean variable automatically selects the first option ("true") // 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") stdout.ExpectMatchContext(ctx, "var.number_var")
pty.ExpectMatchContext(ctx, "Enter value:") stdout.ExpectMatchContext(ctx, "Enter value:")
pty.WriteLine("42") stdin.WriteLine("42")
pty.ExpectMatchContext(ctx, "var.sensitive_var") stdout.ExpectMatchContext(ctx, "var.sensitive_var")
pty.ExpectMatchContext(ctx, "Enter value:") stdout.ExpectMatchContext(ctx, "Enter value:")
pty.WriteLine("secret-value") stdin.WriteLine("secret-value")
pty.ExpectMatchContext(ctx, "var.string_var") stdout.ExpectMatchContext(ctx, "var.string_var")
pty.ExpectMatchContext(ctx, "Enter value:") stdout.ExpectMatchContext(ctx, "Enter value:")
pty.WriteLine("test-string") stdin.WriteLine("test-string")
w.RequireSuccess() w.RequireSuccess()
}) })
t.Run("ValidateNumberInput", func(t *testing.T) { t.Run("ValidateNumberInput", func(t *testing.T) {
t.Parallel() t.Parallel()
logger := testutil.Logger(t)
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin())
@@ -1138,28 +1156,30 @@ func TestTemplatePush(t *testing.T) {
source := clitest.CreateTemplateVersionSource(t, createEchoResponsesWithTemplateVariables(templateVariables)) source := clitest.CreateTemplateVersionSource(t, createEchoResponsesWithTemplateVariables(templateVariables))
inv, root := clitest.New(t, "templates", "push", "test-template", "--directory", source, "--test.provisioner", string(database.ProvisionerTypeEcho)) inv, root := clitest.New(t, "templates", "push", "test-template", "--directory", source, "--test.provisioner", string(database.ProvisionerTypeEcho))
clitest.SetupConfig(t, templateAdmin, root) 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) ctx := testutil.Context(t, testutil.WaitMedium)
inv = inv.WithContext(ctx) inv = inv.WithContext(ctx)
w := clitest.StartWithWaiter(t, inv) w := clitest.StartWithWaiter(t, inv)
// Select "Yes" for the "Upload <template_path>" prompt // Select "Yes" for the "Upload <template_path>" prompt
pty.ExpectMatchContext(ctx, "Upload") stdout.ExpectMatchContext(ctx, "Upload")
pty.WriteLine("yes") stdin.WriteLine("yes")
pty.ExpectMatchContext(ctx, "var.number_var") stdout.ExpectMatchContext(ctx, "var.number_var")
pty.WriteLine("not-a-number") stdin.WriteLine("not-a-number")
pty.ExpectMatchContext(ctx, "must be a valid number") stdout.ExpectMatchContext(ctx, "must be a valid number")
pty.WriteLine("123.45") stdin.WriteLine("123.45")
w.RequireSuccess() w.RequireSuccess()
}) })
t.Run("DontPromptForDefaultValues", func(t *testing.T) { t.Run("DontPromptForDefaultValues", func(t *testing.T) {
t.Parallel() t.Parallel()
logger := testutil.Logger(t)
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin())
@@ -1181,24 +1201,26 @@ func TestTemplatePush(t *testing.T) {
source := clitest.CreateTemplateVersionSource(t, createEchoResponsesWithTemplateVariables(templateVariables)) source := clitest.CreateTemplateVersionSource(t, createEchoResponsesWithTemplateVariables(templateVariables))
inv, root := clitest.New(t, "templates", "push", "test-template", "--directory", source, "--test.provisioner", string(database.ProvisionerTypeEcho)) inv, root := clitest.New(t, "templates", "push", "test-template", "--directory", source, "--test.provisioner", string(database.ProvisionerTypeEcho))
clitest.SetupConfig(t, templateAdmin, root) 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) ctx := testutil.Context(t, testutil.WaitMedium)
inv = inv.WithContext(ctx) inv = inv.WithContext(ctx)
w := clitest.StartWithWaiter(t, inv) w := clitest.StartWithWaiter(t, inv)
// Select "Yes" for the "Upload <template_path>" prompt // Select "Yes" for the "Upload <template_path>" prompt
pty.ExpectMatchContext(ctx, "Upload") stdout.ExpectMatchContext(ctx, "Upload")
pty.WriteLine("yes") stdin.WriteLine("yes")
pty.ExpectMatchContext(ctx, "var.without_default") stdout.ExpectMatchContext(ctx, "var.without_default")
pty.WriteLine("test-value") stdin.WriteLine("test-value")
w.RequireSuccess() w.RequireSuccess()
}) })
t.Run("VariableSourcesPriority", func(t *testing.T) { t.Run("VariableSourcesPriority", func(t *testing.T) {
t.Parallel() t.Parallel()
logger := testutil.Logger(t)
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) 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", "--variable", "cli_overrides_file_var=from-cli-override",
) )
clitest.SetupConfig(t, templateAdmin, root) 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) ctx := testutil.Context(t, testutil.WaitMedium)
inv = inv.WithContext(ctx) inv = inv.WithContext(ctx)
w := clitest.StartWithWaiter(t, inv) w := clitest.StartWithWaiter(t, inv)
// Select "Yes" for the "Upload <template_path>" prompt // Select "Yes" for the "Upload <template_path>" prompt
pty.ExpectMatchContext(ctx, "Upload") stdout.ExpectMatchContext(ctx, "Upload")
pty.WriteLine("yes") stdin.WriteLine("yes")
// Only check for prompt_var, other variables should not prompt // Only check for prompt_var, other variables should not prompt
pty.ExpectMatchContext(ctx, "var.prompt_var") stdout.ExpectMatchContext(ctx, "var.prompt_var")
pty.ExpectMatchContext(ctx, "Enter value:") stdout.ExpectMatchContext(ctx, "Enter value:")
pty.WriteLine("from-prompt") stdin.WriteLine("from-prompt")
w.RequireSuccess() w.RequireSuccess()