test: batch 07 of refactoring CLI tests not to use PTY

This commit is contained in:
Spike Curtis
2026-06-02 20:00:22 +00:00
parent b49344519b
commit 905e6dfab8
22 changed files with 216 additions and 334 deletions
-37
View File
@@ -10,7 +10,6 @@ import (
"cdr.dev/slog/v3/sloggers/slogtest"
"github.com/coder/coder/v2/cli/clitest"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
)
@@ -56,10 +55,6 @@ func TestScaleTestCreateWorkspaces(t *testing.T) {
"--max-failures", "1",
)
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t)
inv.Stdout = pty.Output()
inv.Stderr = pty.Output()
err := inv.WithContext(ctx).Run()
require.ErrorContains(t, err, "could not find template \"doesnotexist\" in any organization")
}
@@ -91,10 +86,6 @@ func TestScaleTestWorkspaceTraffic(t *testing.T) {
"--ssh",
)
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t)
inv.Stdout = pty.Output()
inv.Stderr = pty.Output()
err := inv.WithContext(ctx).Run()
require.ErrorContains(t, err, "no scaletest workspaces exist")
}
@@ -120,10 +111,6 @@ func TestScaleTestWorkspaceTraffic_Template(t *testing.T) {
"--template", "doesnotexist",
)
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t)
inv.Stdout = pty.Output()
inv.Stderr = pty.Output()
err := inv.WithContext(ctx).Run()
require.ErrorContains(t, err, "could not find template \"doesnotexist\" in any organization")
}
@@ -149,10 +136,6 @@ func TestScaleTestWorkspaceTraffic_TargetWorkspaces(t *testing.T) {
"--target-workspaces", "0:0",
)
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t)
inv.Stdout = pty.Output()
inv.Stderr = pty.Output()
err := inv.WithContext(ctx).Run()
require.ErrorContains(t, err, "invalid target workspaces \"0:0\": start and end cannot be equal")
}
@@ -178,10 +161,6 @@ func TestScaleTestCleanup_Template(t *testing.T) {
"--template", "doesnotexist",
)
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t)
inv.Stdout = pty.Output()
inv.Stderr = pty.Output()
err := inv.WithContext(ctx).Run()
require.ErrorContains(t, err, "could not find template \"doesnotexist\" in any organization")
}
@@ -208,10 +187,6 @@ func TestScaleTestDashboard(t *testing.T) {
"--interval", "0s",
)
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t)
inv.Stdout = pty.Output()
inv.Stderr = pty.Output()
err := inv.WithContext(ctx).Run()
require.ErrorContains(t, err, "--interval must be greater than zero")
})
@@ -232,10 +207,6 @@ func TestScaleTestDashboard(t *testing.T) {
"--jitter", "1s",
)
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t)
inv.Stdout = pty.Output()
inv.Stderr = pty.Output()
err := inv.WithContext(ctx).Run()
require.ErrorContains(t, err, "--jitter must be less than --interval")
})
@@ -260,10 +231,6 @@ func TestScaleTestDashboard(t *testing.T) {
"--rand-seed", "1234567890",
)
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t)
inv.Stdout = pty.Output()
inv.Stderr = pty.Output()
err := inv.WithContext(ctx).Run()
require.NoError(t, err, "")
})
@@ -283,10 +250,6 @@ func TestScaleTestDashboard(t *testing.T) {
"--target-users", "0:0",
)
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t)
inv.Stdout = pty.Output()
inv.Stderr = pty.Output()
err := inv.WithContext(ctx).Run()
require.ErrorContains(t, err, "invalid target users \"0:0\": start and end cannot be equal")
})
+11 -10
View File
@@ -10,13 +10,15 @@ import (
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/coderd/httpapi"
"github.com/coder/coder/v2/codersdk/agentsdk"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
"github.com/coder/coder/v2/testutil/expecter"
)
func TestExternalAuth(t *testing.T) {
t.Parallel()
t.Run("CanceledWithURL", func(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitMedium)
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
httpapi.Write(context.Background(), w, http.StatusOK, agentsdk.ExternalAuthResponse{
URL: "https://github.com",
@@ -25,14 +27,14 @@ func TestExternalAuth(t *testing.T) {
t.Cleanup(srv.Close)
url := srv.URL
inv, _ := clitest.New(t, "--agent-url", url, "--agent-token", "foo", "external-auth", "access-token", "github")
pty := ptytest.New(t)
inv.Stdout = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, inv)
waiter := clitest.StartWithWaiter(t, inv)
pty.ExpectMatch("https://github.com")
stdout.ExpectMatchContext(ctx, "https://github.com")
waiter.RequireIs(cliui.ErrCanceled)
})
t.Run("SuccessWithToken", func(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitMedium)
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
httpapi.Write(context.Background(), w, http.StatusOK, agentsdk.ExternalAuthResponse{
AccessToken: "bananas",
@@ -41,10 +43,9 @@ func TestExternalAuth(t *testing.T) {
t.Cleanup(srv.Close)
url := srv.URL
inv, _ := clitest.New(t, "--agent-url", url, "--agent-token", "foo", "external-auth", "access-token", "github")
pty := ptytest.New(t)
inv.Stdout = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, inv)
clitest.Start(t, inv)
pty.ExpectMatch("bananas")
stdout.ExpectMatchContext(ctx, "bananas")
})
t.Run("NoArgs", func(t *testing.T) {
t.Parallel()
@@ -61,6 +62,7 @@ func TestExternalAuth(t *testing.T) {
})
t.Run("SuccessWithExtra", func(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitMedium)
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
httpapi.Write(context.Background(), w, http.StatusOK, agentsdk.ExternalAuthResponse{
AccessToken: "bananas",
@@ -72,9 +74,8 @@ func TestExternalAuth(t *testing.T) {
t.Cleanup(srv.Close)
url := srv.URL
inv, _ := clitest.New(t, "--agent-url", url, "--agent-token", "foo", "external-auth", "access-token", "github", "--extra", "hey")
pty := ptytest.New(t)
inv.Stdout = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, inv)
clitest.Start(t, inv)
pty.ExpectMatch("there")
stdout.ExpectMatchContext(ctx, "there")
})
}
+14 -16
View File
@@ -15,14 +15,15 @@ import (
"github.com/coder/coder/v2/coderd/httpapi"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/agentsdk"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
"github.com/coder/coder/v2/testutil/expecter"
)
func TestGitAskpass(t *testing.T) {
t.Parallel()
t.Run("UsernameAndPassword", func(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitMedium)
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
httpapi.Write(context.Background(), w, http.StatusOK, agentsdk.ExternalAuthResponse{
Username: "something",
@@ -34,22 +35,21 @@ func TestGitAskpass(t *testing.T) {
inv, _ := clitest.New(t, "--agent-url", url, "Username for 'https://github.com':")
inv.Environ.Set("GIT_PREFIX", "/")
inv.Environ.Set("CODER_AGENT_TOKEN", "fake-token")
pty := ptytest.New(t)
inv.Stdout = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, inv)
clitest.Start(t, inv)
pty.ExpectMatch("something")
stdout.ExpectMatchContext(ctx, "something")
inv, _ = clitest.New(t, "--agent-url", url, "Password for 'https://potato@github.com':")
inv.Environ.Set("GIT_PREFIX", "/")
inv.Environ.Set("CODER_AGENT_TOKEN", "fake-token")
pty = ptytest.New(t)
inv.Stdout = pty.Output()
stdout = expecter.NewAttachedToInvocation(t, inv)
clitest.Start(t, inv)
pty.ExpectMatch("bananas")
stdout.ExpectMatchContext(ctx, "bananas")
})
t.Run("NoHost", func(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitMedium)
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
httpapi.Write(context.Background(), w, http.StatusNotFound, codersdk.Response{
Message: "Nope!",
@@ -60,11 +60,10 @@ func TestGitAskpass(t *testing.T) {
inv, _ := clitest.New(t, "--agent-url", url, "--no-open", "Username for 'https://github.com':")
inv.Environ.Set("GIT_PREFIX", "/")
inv.Environ.Set("CODER_AGENT_TOKEN", "fake-token")
pty := ptytest.New(t)
inv.Stderr = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, inv)
err := inv.Run()
require.ErrorIs(t, err, cliui.ErrCanceled)
pty.ExpectMatch("Nope!")
stdout.ExpectMatchContext(ctx, "Nope!")
})
t.Run("Poll", func(t *testing.T) {
@@ -92,20 +91,19 @@ func TestGitAskpass(t *testing.T) {
inv, _ := clitest.New(t, "--agent-url", url, "--no-open", "Username for 'https://github.com':")
inv.Environ.Set("GIT_PREFIX", "/")
inv.Environ.Set("CODER_AGENT_TOKEN", "fake-token")
stdout := ptytest.New(t)
inv.Stdout = stdout.Output()
stderr := ptytest.New(t)
inv.Stderr = stderr.Output()
var stdout, stderr *expecter.Expecter
stdout, inv.Stdout = expecter.NewPiped(t)
stderr, inv.Stderr = expecter.NewPiped(t)
go func() {
err := inv.Run()
assert.NoError(t, err)
}()
testutil.RequireReceive(ctx, t, poll)
stderr.ExpectMatch("Open the following URL to authenticate")
stderr.ExpectMatchContext(ctx, "Open the following URL to authenticate")
resp.Store(&agentsdk.ExternalAuthResponse{
Username: "username",
Password: "password",
})
stdout.ExpectMatch("username")
stdout.ExpectMatchContext(ctx, "username")
})
}
-6
View File
@@ -27,7 +27,6 @@ import (
"github.com/coder/coder/v2/coderd/database/dbfake"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/agentsdk"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
)
@@ -194,7 +193,6 @@ func TestGitSSH(t *testing.T) {
}, "\n")), 0o600)
require.NoError(t, err)
pty := ptytest.New(t)
cmdArgs := []string{
"gitssh",
"--agent-url", client.SDK.URL.String(),
@@ -205,8 +203,6 @@ func TestGitSSH(t *testing.T) {
}
// Test authentication via local private key.
inv, _ := clitest.New(t, cmdArgs...)
inv.Stdout = pty.Output()
inv.Stderr = pty.Output()
// This occasionally times out at 15s on Windows CI runners. Use a
// longer timeout to reduce flakes.
ctx := testutil.Context(t, testutil.WaitSuperLong)
@@ -225,8 +221,6 @@ func TestGitSSH(t *testing.T) {
// With the local file deleted, the coder key should be used.
inv, _ = clitest.New(t, cmdArgs...)
inv.Stdout = pty.Output()
inv.Stderr = pty.Output()
// This occasionally times out at 15s on Windows CI runners. Use a
// longer timeout to reduce flakes.
ctx = testutil.Context(t, testutil.WaitSuperLong) // Reset context for second cmd test.
+51 -51
View File
@@ -17,7 +17,8 @@ import (
"github.com/coder/coder/v2/cli/sessionstore"
"github.com/coder/coder/v2/cli/sessionstore/testhelpers"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
"github.com/coder/coder/v2/testutil/expecter"
"github.com/coder/serpent"
)
@@ -66,13 +67,12 @@ func TestUseKeyring(t *testing.T) {
t.Skip("keyring is not supported on this OS")
}
logger := testutil.Logger(t)
ctx := testutil.Context(t, testutil.WaitMedium)
// Create a test server
client := coderdtest.New(t, nil)
coderdtest.CreateFirstUser(t, client)
// Create a pty for interactive prompts
pty := ptytest.New(t)
// Create CLI invocation which defaults to using the keyring
env := setupKeyringTestEnv(t, client.URL.String(),
"login",
@@ -80,8 +80,8 @@ func TestUseKeyring(t *testing.T) {
"--no-open",
client.URL.String())
inv := env.inv
inv.Stdin = pty.Input()
inv.Stdout = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, inv)
stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv)
// Run login in background
doneChan := make(chan struct{})
@@ -92,9 +92,9 @@ func TestUseKeyring(t *testing.T) {
}()
// Provide the token when prompted
pty.ExpectMatch("Paste your token here:")
pty.WriteLine(client.SessionToken())
pty.ExpectMatch("Welcome to Coder")
stdout.ExpectMatchContext(ctx, "Paste your token here:")
stdin.WriteLine(client.SessionToken())
stdout.ExpectMatchContext(ctx, "Welcome to Coder")
<-doneChan
// Verify that session file was NOT created (using keyring instead)
@@ -115,13 +115,12 @@ func TestUseKeyring(t *testing.T) {
t.Skip("keyring is not supported on this OS")
}
logger := testutil.Logger(t)
ctx := testutil.Context(t, testutil.WaitMedium)
// Create a test server
client := coderdtest.New(t, nil)
coderdtest.CreateFirstUser(t, client)
// Create a pty for interactive prompts
pty := ptytest.New(t)
// First, login with the keyring (default)
env := setupKeyringTestEnv(t, client.URL.String(),
"login",
@@ -130,8 +129,8 @@ func TestUseKeyring(t *testing.T) {
client.URL.String(),
)
loginInv := env.inv
loginInv.Stdin = pty.Input()
loginInv.Stdout = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, loginInv)
stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), loginInv)
doneChan := make(chan struct{})
go func() {
@@ -140,9 +139,9 @@ func TestUseKeyring(t *testing.T) {
assert.NoError(t, err)
}()
pty.ExpectMatch("Paste your token here:")
pty.WriteLine(client.SessionToken())
pty.ExpectMatch("Welcome to Coder")
stdout.ExpectMatchContext(ctx, "Paste your token here:")
stdin.WriteLine(client.SessionToken())
stdout.ExpectMatchContext(ctx, "Welcome to Coder")
<-doneChan
// Verify credential exists in OS keyring
@@ -181,13 +180,12 @@ func TestUseKeyring(t *testing.T) {
t.Skip("file storage is the default for Linux")
}
logger := testutil.Logger(t)
ctx := testutil.Context(t, testutil.WaitMedium)
// Create a test server
client := coderdtest.New(t, nil)
coderdtest.CreateFirstUser(t, client)
// Create a pty for interactive prompts
pty := ptytest.New(t)
env := setupKeyringTestEnv(t, client.URL.String(),
"login",
"--force-tty",
@@ -195,8 +193,8 @@ func TestUseKeyring(t *testing.T) {
client.URL.String(),
)
inv := env.inv
inv.Stdin = pty.Input()
inv.Stdout = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, inv)
stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv)
doneChan := make(chan struct{})
go func() {
@@ -205,9 +203,9 @@ func TestUseKeyring(t *testing.T) {
assert.NoError(t, err)
}()
pty.ExpectMatch("Paste your token here:")
pty.WriteLine(client.SessionToken())
pty.ExpectMatch("Welcome to Coder")
stdout.ExpectMatchContext(ctx, "Paste your token here:")
stdin.WriteLine(client.SessionToken())
stdout.ExpectMatchContext(ctx, "Welcome to Coder")
<-doneChan
// Verify that session file WAS created (not using keyring)
@@ -224,13 +222,12 @@ func TestUseKeyring(t *testing.T) {
t.Run("EnvironmentVariable", func(t *testing.T) {
t.Parallel()
logger := testutil.Logger(t)
ctx := testutil.Context(t, testutil.WaitMedium)
// Create a test server
client := coderdtest.New(t, nil)
coderdtest.CreateFirstUser(t, client)
// Create a pty for interactive prompts
pty := ptytest.New(t)
// Login using CODER_USE_KEYRING environment variable set to disable keyring usage,
// which should have the same behavior on all platforms.
env := setupKeyringTestEnv(t, client.URL.String(),
@@ -240,8 +237,8 @@ func TestUseKeyring(t *testing.T) {
client.URL.String(),
)
inv := env.inv
inv.Stdin = pty.Input()
inv.Stdout = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, inv)
stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv)
inv.Environ.Set("CODER_USE_KEYRING", "false")
doneChan := make(chan struct{})
@@ -251,9 +248,9 @@ func TestUseKeyring(t *testing.T) {
assert.NoError(t, err)
}()
pty.ExpectMatch("Paste your token here:")
pty.WriteLine(client.SessionToken())
pty.ExpectMatch("Welcome to Coder")
stdout.ExpectMatchContext(ctx, "Paste your token here:")
stdin.WriteLine(client.SessionToken())
stdout.ExpectMatchContext(ctx, "Welcome to Coder")
<-doneChan
// Verify that session file WAS created (not using keyring)
@@ -270,9 +267,10 @@ func TestUseKeyring(t *testing.T) {
t.Run("DisableKeyringWithFlag", func(t *testing.T) {
t.Parallel()
logger := testutil.Logger(t)
ctx := testutil.Context(t, testutil.WaitMedium)
client := coderdtest.New(t, nil)
coderdtest.CreateFirstUser(t, client)
pty := ptytest.New(t)
// Login with --use-keyring=false to explicitly disable keyring usage, which
// should have the same behavior on all platforms.
@@ -284,8 +282,8 @@ func TestUseKeyring(t *testing.T) {
client.URL.String(),
)
inv := env.inv
inv.Stdin = pty.Input()
inv.Stdout = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, inv)
stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv)
doneChan := make(chan struct{})
go func() {
@@ -294,9 +292,9 @@ func TestUseKeyring(t *testing.T) {
assert.NoError(t, err)
}()
pty.ExpectMatch("Paste your token here:")
pty.WriteLine(client.SessionToken())
pty.ExpectMatch("Welcome to Coder")
stdout.ExpectMatchContext(ctx, "Paste your token here:")
stdin.WriteLine(client.SessionToken())
stdout.ExpectMatchContext(ctx, "Welcome to Coder")
<-doneChan
// Verify that session file WAS created (not using keyring)
@@ -324,9 +322,10 @@ func TestUseKeyringUnsupportedOS(t *testing.T) {
t.Run("LoginWithDefaultKeyring", func(t *testing.T) {
t.Parallel()
logger := testutil.Logger(t)
ctx := testutil.Context(t, testutil.WaitMedium)
client := coderdtest.New(t, nil)
coderdtest.CreateFirstUser(t, client)
pty := ptytest.New(t)
env := setupKeyringTestEnv(t, client.URL.String(),
"login",
@@ -335,8 +334,8 @@ func TestUseKeyringUnsupportedOS(t *testing.T) {
client.URL.String(),
)
inv := env.inv
inv.Stdin = pty.Input()
inv.Stdout = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, inv)
stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv)
doneChan := make(chan struct{})
go func() {
@@ -345,9 +344,9 @@ func TestUseKeyringUnsupportedOS(t *testing.T) {
assert.NoError(t, err)
}()
pty.ExpectMatch("Paste your token here:")
pty.WriteLine(client.SessionToken())
pty.ExpectMatch("Welcome to Coder")
stdout.ExpectMatchContext(ctx, "Paste your token here:")
stdin.WriteLine(client.SessionToken())
stdout.ExpectMatchContext(ctx, "Welcome to Coder")
<-doneChan
// Verify that session file WAS created (automatic fallback to file storage)
@@ -363,9 +362,10 @@ func TestUseKeyringUnsupportedOS(t *testing.T) {
t.Run("LogoutWithDefaultKeyring", func(t *testing.T) {
t.Parallel()
logger := testutil.Logger(t)
ctx := testutil.Context(t, testutil.WaitMedium)
client := coderdtest.New(t, nil)
coderdtest.CreateFirstUser(t, client)
pty := ptytest.New(t)
// First login to create a session (will use file storage due to automatic fallback)
env := setupKeyringTestEnv(t, client.URL.String(),
@@ -375,8 +375,8 @@ func TestUseKeyringUnsupportedOS(t *testing.T) {
client.URL.String(),
)
loginInv := env.inv
loginInv.Stdin = pty.Input()
loginInv.Stdout = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, loginInv)
stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), loginInv)
doneChan := make(chan struct{})
go func() {
@@ -385,9 +385,9 @@ func TestUseKeyringUnsupportedOS(t *testing.T) {
assert.NoError(t, err)
}()
pty.ExpectMatch("Paste your token here:")
pty.WriteLine(client.SessionToken())
pty.ExpectMatch("Welcome to Coder")
stdout.ExpectMatchContext(ctx, "Paste your token here:")
stdin.WriteLine(client.SessionToken())
stdout.ExpectMatchContext(ctx, "Welcome to Coder")
<-doneChan
// Verify session file exists
+32 -31
View File
@@ -1,6 +1,7 @@
package cli_test
import (
"context"
"fmt"
"os"
"runtime"
@@ -12,7 +13,8 @@ import (
"github.com/coder/coder/v2/cli/clitest"
"github.com/coder/coder/v2/cli/config"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
"github.com/coder/coder/v2/testutil/expecter"
)
func TestLogout(t *testing.T) {
@@ -20,8 +22,9 @@ func TestLogout(t *testing.T) {
t.Run("Logout", func(t *testing.T) {
t.Parallel()
pty := ptytest.New(t)
config := login(t, pty)
ctx := testutil.Context(t, testutil.WaitMedium)
logger := testutil.Logger(t)
config := login(ctx, t)
// Ensure session files exist.
require.FileExists(t, string(config.URL()))
@@ -29,8 +32,8 @@ func TestLogout(t *testing.T) {
logoutChan := make(chan struct{})
logout, _ := clitest.New(t, "logout", "--global-config", string(config))
logout.Stdin = pty.Input()
logout.Stdout = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, logout)
stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), logout)
go func() {
defer close(logoutChan)
@@ -40,16 +43,16 @@ func TestLogout(t *testing.T) {
assert.NoFileExists(t, string(config.Session()))
}()
pty.ExpectMatch("Are you sure you want to log out?")
pty.WriteLine("yes")
pty.ExpectMatch("You are no longer logged in. You can log in using 'coder login <url>'.")
stdout.ExpectMatchContext(ctx, "Are you sure you want to log out?")
stdin.WriteLine("yes")
stdout.ExpectMatchContext(ctx, "You are no longer logged in. You can log in using 'coder login <url>'.")
<-logoutChan
})
t.Run("SkipPrompt", func(t *testing.T) {
t.Parallel()
pty := ptytest.New(t)
config := login(t, pty)
ctx := testutil.Context(t, testutil.WaitMedium)
config := login(ctx, t)
// Ensure session files exist.
require.FileExists(t, string(config.URL()))
@@ -57,8 +60,7 @@ func TestLogout(t *testing.T) {
logoutChan := make(chan struct{})
logout, _ := clitest.New(t, "logout", "--global-config", string(config), "-y")
logout.Stdin = pty.Input()
logout.Stdout = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, logout)
go func() {
defer close(logoutChan)
@@ -68,14 +70,14 @@ func TestLogout(t *testing.T) {
assert.NoFileExists(t, string(config.Session()))
}()
pty.ExpectMatch("You are no longer logged in. You can log in using 'coder login <url>'.")
stdout.ExpectMatchContext(ctx, "You are no longer logged in. You can log in using 'coder login <url>'.")
<-logoutChan
})
t.Run("NoURLFile", func(t *testing.T) {
t.Parallel()
pty := ptytest.New(t)
config := login(t, pty)
ctx := testutil.Context(t, testutil.WaitMedium)
config := login(ctx, t)
// Ensure session files exist.
require.FileExists(t, string(config.URL()))
@@ -87,9 +89,6 @@ func TestLogout(t *testing.T) {
logoutChan := make(chan struct{})
logout, _ := clitest.New(t, "logout", "--global-config", string(config))
logout.Stdin = pty.Input()
logout.Stdout = pty.Output()
executable, err := os.Executable()
require.NoError(t, err)
require.NotEqual(t, "", executable)
@@ -105,8 +104,9 @@ func TestLogout(t *testing.T) {
t.Run("CannotDeleteFiles", func(t *testing.T) {
t.Parallel()
pty := ptytest.New(t)
config := login(t, pty)
ctx := testutil.Context(t, testutil.WaitMedium)
logger := testutil.Logger(t)
config := login(ctx, t)
// Ensure session files exist.
require.FileExists(t, string(config.URL()))
@@ -144,12 +144,12 @@ func TestLogout(t *testing.T) {
logout, _ := clitest.New(t, "logout", "--global-config", string(config))
logout.Stdin = pty.Input()
logout.Stdout = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, logout)
stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), logout)
go func() {
pty.ExpectMatch("Are you sure you want to log out?")
pty.WriteLine("yes")
stdout.ExpectMatchContext(ctx, "Are you sure you want to log out?")
stdin.WriteLine("yes")
}()
err = logout.Run()
require.Error(t, err)
@@ -166,26 +166,27 @@ func TestLogout(t *testing.T) {
})
}
func login(t *testing.T, pty *ptytest.PTY) config.Root {
func login(ctx context.Context, t *testing.T) config.Root {
t.Helper()
logger := testutil.Logger(t)
client := coderdtest.New(t, nil)
coderdtest.CreateFirstUser(t, client)
doneChan := make(chan struct{})
root, cfg := clitest.New(t, "login", "--force-tty", client.URL.String(), "--no-open")
root.Stdin = pty.Input()
root.Stdout = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, root)
stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), root)
go func() {
defer close(doneChan)
err := root.Run()
assert.NoError(t, err)
}()
pty.ExpectMatch("Paste your token here:")
pty.WriteLine(client.SessionToken())
pty.ExpectMatch("Welcome to Coder")
<-doneChan
stdout.ExpectMatchContext(ctx, "Paste your token here:")
stdin.WriteLine(client.SessionToken())
stdout.ExpectMatchContext(ctx, "Welcome to Coder")
testutil.TryReceive(ctx, t, doneChan)
return cfg
}
+3 -3
View File
@@ -9,14 +9,14 @@ import (
"github.com/coder/coder/v2/cli/clitest"
"github.com/coder/coder/v2/codersdk/healthsdk"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
)
func TestNetcheck(t *testing.T) {
t.Parallel()
pty := ptytest.New(t)
config := login(t, pty)
ctx := testutil.Context(t, testutil.WaitMedium)
config := login(ctx, t)
var out bytes.Buffer
inv, _ := clitest.New(t, "netcheck", "--global-config", string(config))
+10 -29
View File
@@ -24,8 +24,8 @@ import (
"github.com/coder/coder/v2/coderd/database/dbtime"
"github.com/coder/coder/v2/codersdk"
"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 TestOpenVSCode(t *testing.T) {
@@ -120,9 +120,8 @@ func TestOpenVSCode(t *testing.T) {
inv, root := clitest.New(t, append([]string{"open", "vscode"}, tt.args...)...)
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t)
inv.Stdin = pty.Input()
inv.Stdout = pty.Output()
var stdout *expecter.Expecter
stdout, inv.Stdout = expecter.NewPiped(t)
ctx := testutil.Context(t, testutil.WaitLong)
inv = inv.WithContext(ctx)
@@ -140,7 +139,7 @@ func TestOpenVSCode(t *testing.T) {
me, err := client.User(ctx, codersdk.Me)
require.NoError(t, err)
line := pty.ReadLine(ctx)
line := stdout.ReadLine(ctx)
u, err := url.ParseRequestURI(line)
require.NoError(t, err, "line: %q", line)
@@ -246,9 +245,8 @@ func TestOpenVSCode_NoAgentDirectory(t *testing.T) {
inv, root := clitest.New(t, append([]string{"open", "vscode"}, tt.args...)...)
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t)
inv.Stdin = pty.Input()
inv.Stdout = pty.Output()
var stdout *expecter.Expecter
stdout, inv.Stdout = expecter.NewPiped(t)
ctx := testutil.Context(t, testutil.WaitLong)
inv = inv.WithContext(ctx)
@@ -266,7 +264,7 @@ func TestOpenVSCode_NoAgentDirectory(t *testing.T) {
me, err := client.User(ctx, codersdk.Me)
require.NoError(t, err)
line := pty.ReadLine(ctx)
line := stdout.ReadLine(ctx)
u, err := url.ParseRequestURI(line)
require.NoError(t, err, "line: %q", line)
@@ -570,10 +568,8 @@ func TestOpenVSCodeDevContainer(t *testing.T) {
inv, root := clitest.New(t, append([]string{"open", "vscode"}, tt.args...)...)
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t)
inv.Stdin = pty.Input()
inv.Stdout = pty.Output()
var stdout *expecter.Expecter
stdout, inv.Stdout = expecter.NewPiped(t)
ctx := testutil.Context(t, testutil.WaitLong)
inv = inv.WithContext(ctx)
@@ -592,7 +588,7 @@ func TestOpenVSCodeDevContainer(t *testing.T) {
me, err := client.User(ctx, codersdk.Me)
require.NoError(t, err)
line := pty.ReadLine(ctx)
line := stdout.ReadLine(ctx)
u, err := url.ParseRequestURI(line)
require.NoError(t, err, "line: %q", line)
@@ -640,9 +636,6 @@ func TestOpenApp(t *testing.T) {
inv, root := clitest.New(t, "open", "app", ws.Name, "app1", "--test.open-error")
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t)
inv.Stdin = pty.Input()
inv.Stdout = pty.Output()
w := clitest.StartWithWaiter(t, inv)
w.RequireError()
@@ -671,9 +664,6 @@ func TestOpenApp(t *testing.T) {
client, _, _ := setupWorkspaceForAgent(t)
inv, root := clitest.New(t, "open", "app", "not-a-workspace", "app1")
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t)
inv.Stdin = pty.Input()
inv.Stdout = pty.Output()
w := clitest.StartWithWaiter(t, inv)
w.RequireError()
w.RequireContains("Resource not found or you do not have access to this resource")
@@ -686,9 +676,6 @@ func TestOpenApp(t *testing.T) {
inv, root := clitest.New(t, "open", "app", ws.Name, "app1")
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t)
inv.Stdin = pty.Input()
inv.Stdout = pty.Output()
w := clitest.StartWithWaiter(t, inv)
w.RequireError()
@@ -710,9 +697,6 @@ func TestOpenApp(t *testing.T) {
inv, root := clitest.New(t, "open", "app", ws.Name, "app1", "--region", "bad-region")
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t)
inv.Stdin = pty.Input()
inv.Stdout = pty.Output()
w := clitest.StartWithWaiter(t, inv)
w.RequireError()
@@ -734,9 +718,6 @@ func TestOpenApp(t *testing.T) {
})
inv, root := clitest.New(t, "open", "app", ws.Name, "app1", "--test.open-error")
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t)
inv.Stdin = pty.Input()
inv.Stdout = pty.Output()
w := clitest.StartWithWaiter(t, inv)
w.RequireError()
+7 -16
View File
@@ -9,8 +9,8 @@ import (
"github.com/coder/coder/v2/agent/agenttest"
"github.com/coder/coder/v2/cli/clitest"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
"github.com/coder/coder/v2/testutil/expecter"
)
func TestPing(t *testing.T) {
@@ -22,10 +22,7 @@ func TestPing(t *testing.T) {
client, workspace, agentToken := setupWorkspaceForAgent(t)
inv, root := clitest.New(t, "ping", workspace.Name)
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t)
inv.Stdin = pty.Input()
inv.Stderr = pty.Output()
inv.Stdout = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, inv)
_ = agenttest.New(t, client.URL, agentToken)
_ = coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID)
@@ -38,7 +35,7 @@ func TestPing(t *testing.T) {
assert.NoError(t, err)
})
pty.ExpectMatch("pong from " + workspace.Name)
stdout.ExpectMatchContext(ctx, "pong from "+workspace.Name)
cancel()
<-cmdDone
})
@@ -49,10 +46,7 @@ func TestPing(t *testing.T) {
client, workspace, agentToken := setupWorkspaceForAgent(t)
inv, root := clitest.New(t, "ping", "-n", "1", workspace.Name)
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t)
inv.Stdin = pty.Input()
inv.Stderr = pty.Output()
inv.Stdout = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, inv)
_ = agenttest.New(t, client.URL, agentToken)
_ = coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID)
@@ -65,7 +59,7 @@ func TestPing(t *testing.T) {
assert.NoError(t, err)
})
pty.ExpectMatch("pong from " + workspace.Name)
stdout.ExpectMatchContext(ctx, "pong from "+workspace.Name)
cancel()
<-cmdDone
})
@@ -93,10 +87,7 @@ func TestPing(t *testing.T) {
inv, root := clitest.New(t, args...)
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t)
inv.Stdin = pty.Input()
inv.Stderr = pty.Output()
inv.Stdout = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, inv)
_ = agenttest.New(t, client.URL, agentToken)
_ = coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID)
@@ -119,7 +110,7 @@ func TestPing(t *testing.T) {
rfc3339 += `(?:Z|[+-]\d{2}:\d{2})`
}
pty.ExpectRegexMatch(`\[` + rfc3339 + `\] pong from ` + workspace.Name)
stdout.ExpectRegexMatchContext(ctx, `\[`+rfc3339+`\] pong from `+workspace.Name)
cancel()
<-cmdDone
})
+6 -6
View File
@@ -12,8 +12,8 @@ import (
"github.com/coder/coder/v2/cli/clitest"
"github.com/coder/coder/v2/coderd/database/dbtestutil"
"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"
)
// nolint:paralleltest
@@ -31,6 +31,7 @@ func TestResetPassword(t *testing.T) {
const oldPassword = "MyOldPassword!"
const newPassword = "MyNewPassword!"
logger := testutil.Logger(t)
// start postgres and coder server processes
connectionURL, err := dbtestutil.Open(t)
require.NoError(t, err)
@@ -69,9 +70,8 @@ func TestResetPassword(t *testing.T) {
resetinv, cmdCfg := clitest.New(t, "reset-password", "--postgres-url", connectionURL, username)
clitest.SetupConfig(t, client, cmdCfg)
cmdDone := make(chan struct{})
pty := ptytest.New(t)
resetinv.Stdin = pty.Input()
resetinv.Stdout = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, resetinv)
stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), resetinv)
go func() {
defer close(cmdDone)
err = resetinv.Run()
@@ -86,8 +86,8 @@ func TestResetPassword(t *testing.T) {
{"Confirm", newPassword},
}
for _, match := range matches {
pty.ExpectMatch(match.output)
pty.WriteLine(match.input)
stdout.ExpectMatchContext(ctx, match.output)
stdin.WriteLine(match.input)
}
<-cmdDone
+3 -6
View File
@@ -22,8 +22,8 @@ import (
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/agentsdk"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
"github.com/coder/coder/v2/testutil/expecter"
"github.com/coder/serpent"
)
@@ -275,10 +275,7 @@ func TestDERPHeaders(t *testing.T) {
}
inv, root := clitest.New(t, args...)
clitest.SetupConfig(t, member, root)
pty := ptytest.New(t)
inv.Stdin = pty.Input()
inv.Stderr = pty.Output()
inv.Stdout = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, inv)
ctx := testutil.Context(t, testutil.WaitLong)
cmdDone := tGo(t, func() {
@@ -286,7 +283,7 @@ func TestDERPHeaders(t *testing.T) {
assert.NoError(t, err)
})
pty.ExpectMatch("pong from " + workspace.Name)
stdout.ExpectMatchContext(ctx, "pong from "+workspace.Name)
<-cmdDone
require.Greater(t, derpCalled.Load(), int64(0), "expected /derp to be called at least once")
+5 -8
View File
@@ -19,7 +19,6 @@ import (
"github.com/coder/coder/v2/coderd/rbac"
"github.com/coder/coder/v2/coderd/userpassword"
"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"
)
@@ -163,15 +162,13 @@ func TestServerCreateAdminUser(t *testing.T) {
inv.Environ.Set("CODER_EMAIL", email)
inv.Environ.Set("CODER_PASSWORD", password)
pty := ptytest.New(t)
inv.Stdout = pty.Output()
inv.Stderr = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, inv)
clitest.Start(t, inv)
pty.ExpectMatchContext(ctx, "User created successfully.")
pty.ExpectMatchContext(ctx, username)
pty.ExpectMatchContext(ctx, email)
pty.ExpectMatchContext(ctx, "****")
stdout.ExpectMatchContext(ctx, "User created successfully.")
stdout.ExpectMatchContext(ctx, username)
stdout.ExpectMatchContext(ctx, email)
stdout.ExpectMatchContext(ctx, "****")
verifyUser(t, connectionURL, username, email, password)
})
+13 -17
View File
@@ -11,8 +11,8 @@ import (
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/database/dbgen"
"github.com/coder/coder/v2/coderd/database/dbtestutil"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
"github.com/coder/coder/v2/testutil/expecter"
)
func TestRegenerateVapidKeypair(t *testing.T) {
@@ -39,16 +39,14 @@ func TestRegenerateVapidKeypair(t *testing.T) {
inv, _ := clitest.New(t, "server", "regenerate-vapid-keypair", "--postgres-url", connectionURL, "--yes")
pty := ptytest.New(t)
inv.Stdout = pty.Output()
inv.Stderr = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, inv)
clitest.Start(t, inv)
pty.ExpectMatchContext(ctx, "Regenerating VAPID keypair...")
pty.ExpectMatchContext(ctx, "This will delete all existing webpush subscriptions.")
pty.ExpectMatchContext(ctx, "Are you sure you want to continue? (y/N)")
pty.WriteLine("y")
pty.ExpectMatchContext(ctx, "VAPID keypair regenerated successfully.")
stdout.ExpectMatchContext(ctx, "Regenerating VAPID keypair...")
stdout.ExpectMatchContext(ctx, "This will delete all existing webpush subscriptions.")
stdout.ExpectMatchContext(ctx, "Are you sure you want to continue? (y/N)")
// don't need to write to stdin because we passed --yes
stdout.ExpectMatchContext(ctx, "VAPID keypair regenerated successfully.")
// Ensure the VAPID keypair was created.
keys, err := db.GetWebpushVAPIDKeys(ctx)
@@ -84,16 +82,14 @@ func TestRegenerateVapidKeypair(t *testing.T) {
inv, _ := clitest.New(t, "server", "regenerate-vapid-keypair", "--postgres-url", connectionURL, "--yes")
pty := ptytest.New(t)
inv.Stdout = pty.Output()
inv.Stderr = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, inv)
clitest.Start(t, inv)
pty.ExpectMatchContext(ctx, "Regenerating VAPID keypair...")
pty.ExpectMatchContext(ctx, "This will delete all existing webpush subscriptions.")
pty.ExpectMatchContext(ctx, "Are you sure you want to continue? (y/N)")
pty.WriteLine("y")
pty.ExpectMatchContext(ctx, "VAPID keypair regenerated successfully.")
stdout.ExpectMatchContext(ctx, "Regenerating VAPID keypair...")
stdout.ExpectMatchContext(ctx, "This will delete all existing webpush subscriptions.")
stdout.ExpectMatchContext(ctx, "Are you sure you want to continue? (y/N)")
// don't need to write to stdin because we passed --yes
stdout.ExpectMatchContext(ctx, "VAPID keypair regenerated successfully.")
// Ensure the VAPID keypair was created.
keys, err := db.GetWebpushVAPIDKeys(ctx)
-4
View File
@@ -14,7 +14,6 @@ import (
"github.com/coder/coder/v2/cli/clitest"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
)
@@ -43,9 +42,6 @@ func TestSpeedtest(t *testing.T) {
inv, root := clitest.New(t, "speedtest", workspace.Name)
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t)
inv.Stdout = pty.Output()
inv.Stderr = pty.Output()
ctx, cancel = context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()
+5 -4
View File
@@ -13,7 +13,8 @@ import (
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/enterprise/coderd/coderdenttest"
"github.com/coder/coder/v2/enterprise/coderd/license"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
"github.com/coder/coder/v2/testutil/expecter"
"github.com/coder/pretty"
)
@@ -40,13 +41,13 @@ func TestCreateGroup(t *testing.T) {
"--avatar-url", avatarURL,
)
pty := ptytest.New(t)
inv.Stdout = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, inv)
clitest.SetupConfig(t, anotherClient, conf)
ctx := testutil.Context(t, testutil.WaitMedium)
err := inv.Run()
require.NoError(t, err)
pty.ExpectMatch(fmt.Sprintf("Successfully created group %s!", pretty.Sprint(cliui.DefaultStyles.Keyword, groupName)))
stdout.ExpectMatchContext(ctx, fmt.Sprintf("Successfully created group %s!", pretty.Sprint(cliui.DefaultStyles.Keyword, groupName)))
})
}
+5 -5
View File
@@ -13,7 +13,8 @@ import (
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/enterprise/coderd/coderdenttest"
"github.com/coder/coder/v2/enterprise/coderd/license"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
"github.com/coder/coder/v2/testutil/expecter"
"github.com/coder/pretty"
)
@@ -36,15 +37,14 @@ func TestGroupDelete(t *testing.T) {
"groups", "delete", group.Name,
)
pty := ptytest.New(t)
inv.Stdout = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, inv)
ctx := testutil.Context(t, testutil.WaitMedium)
clitest.SetupConfig(t, anotherClient, conf)
err := inv.Run()
require.NoError(t, err)
pty.ExpectMatch(fmt.Sprintf("Successfully deleted group %s", pretty.Sprint(cliui.DefaultStyles.Keyword, group.Name)))
stdout.ExpectMatchContext(ctx, fmt.Sprintf("Successfully deleted group %s", pretty.Sprint(cliui.DefaultStyles.Keyword, group.Name)))
})
t.Run("NoArg", func(t *testing.T) {
+5 -5
View File
@@ -13,7 +13,8 @@ import (
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/enterprise/coderd/coderdenttest"
"github.com/coder/coder/v2/enterprise/coderd/license"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
"github.com/coder/coder/v2/testutil/expecter"
"github.com/coder/pretty"
)
@@ -48,15 +49,14 @@ func TestGroupEdit(t *testing.T) {
"-r", user3.ID.String(),
)
pty := ptytest.New(t)
inv.Stdout = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, inv)
clitest.SetupConfig(t, anotherClient, conf)
ctx := testutil.Context(t, testutil.WaitMedium)
err := inv.Run()
require.NoError(t, err)
pty.ExpectMatch(fmt.Sprintf("Successfully patched group %s", pretty.Sprint(cliui.DefaultStyles.Keyword, expectedName)))
stdout.ExpectMatchContext(ctx, fmt.Sprintf("Successfully patched group %s", pretty.Sprint(cliui.DefaultStyles.Keyword, expectedName)))
})
t.Run("InvalidUserInput", func(t *testing.T) {
+8 -10
View File
@@ -14,7 +14,8 @@ import (
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/enterprise/coderd/coderdenttest"
"github.com/coder/coder/v2/enterprise/coderd/license"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
"github.com/coder/coder/v2/testutil/expecter"
)
func TestGroupList(t *testing.T) {
@@ -41,11 +42,9 @@ func TestGroupList(t *testing.T) {
inv, conf := newCLI(t, "groups", "list")
pty := ptytest.New(t)
inv.Stdout = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, inv)
clitest.SetupConfig(t, anotherClient, conf)
ctx := testutil.Context(t, testutil.WaitMedium)
err := inv.Run()
require.NoError(t, err)
@@ -56,7 +55,7 @@ func TestGroupList(t *testing.T) {
}
for _, match := range matches {
pty.ExpectMatch(match)
stdout.ExpectMatchContext(ctx, match)
}
})
@@ -72,9 +71,8 @@ func TestGroupList(t *testing.T) {
inv, conf := newCLI(t, "groups", "list")
pty := ptytest.New(t)
inv.Stdout = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, inv)
ctx := testutil.Context(t, testutil.WaitMedium)
clitest.SetupConfig(t, anotherClient, conf)
err := inv.Run()
@@ -86,7 +84,7 @@ func TestGroupList(t *testing.T) {
}
for _, match := range matches {
pty.ExpectMatch(match)
stdout.ExpectMatchContext(ctx, match)
}
})
+20 -26
View File
@@ -20,8 +20,8 @@ import (
"github.com/coder/coder/v2/coderd/httpapi"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/enterprise/coderd/coderdenttest"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
"github.com/coder/coder/v2/testutil/expecter"
"github.com/coder/serpent"
)
@@ -37,41 +37,42 @@ func TestLicensesAddFake(t *testing.T) {
t.Run("LFlag", func(t *testing.T) {
t.Parallel()
inv := setupFakeLicenseServerTest(t, "licenses", "add", "-l", fakeLicenseJWT)
pty := attachPty(t, inv)
stdout := expecter.NewAttachedToInvocation(t, inv)
clitest.Start(t, inv)
pty.ExpectMatch("License with ID 1 added")
ctx := testutil.Context(t, testutil.WaitMedium)
stdout.ExpectMatchContext(ctx, "License with ID 1 added")
})
t.Run("Prompt", func(t *testing.T) {
t.Parallel()
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()
logger := testutil.Logger(t)
ctx := testutil.Context(t, testutil.WaitLong)
inv := setupFakeLicenseServerTest(t, "license", "add")
pty := attachPty(t, inv)
stdout := expecter.NewAttachedToInvocation(t, inv)
stdin := testutil.NewWriterAttachedToInvocation(t, logger.Named("stdin"), inv)
errC := make(chan error)
go func() {
errC <- inv.WithContext(ctx).Run()
}()
pty.ExpectMatch("Paste license:")
pty.WriteLine(fakeLicenseJWT)
stdout.ExpectMatchContext(ctx, "Paste license:")
stdin.WriteLine(fakeLicenseJWT)
require.NoError(t, <-errC)
pty.ExpectMatch("License with ID 1 added")
stdout.ExpectMatchContext(ctx, "License with ID 1 added")
})
t.Run("File", func(t *testing.T) {
t.Parallel()
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()
ctx := testutil.Context(t, testutil.WaitLong)
dir := t.TempDir()
filename := filepath.Join(dir, "license.jwt")
err := os.WriteFile(filename, []byte(fakeLicenseJWT), 0o600)
require.NoError(t, err)
inv := setupFakeLicenseServerTest(t, "license", "add", "-f", filename)
pty := attachPty(t, inv)
stdout := expecter.NewAttachedToInvocation(t, inv)
errC := make(chan error)
go func() {
errC <- inv.WithContext(ctx).Run()
}()
require.NoError(t, <-errC)
pty.ExpectMatch("License with ID 1 added")
stdout.ExpectMatchContext(ctx, "License with ID 1 added")
})
t.Run("StdIn", func(t *testing.T) {
t.Parallel()
@@ -100,16 +101,15 @@ func TestLicensesAddFake(t *testing.T) {
})
t.Run("DebugOutput", func(t *testing.T) {
t.Parallel()
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()
ctx := testutil.Context(t, testutil.WaitLong)
inv := setupFakeLicenseServerTest(t, "licenses", "add", "-l", fakeLicenseJWT, "--debug")
pty := attachPty(t, inv)
stdout := expecter.NewAttachedToInvocation(t, inv)
errC := make(chan error)
go func() {
errC <- inv.WithContext(ctx).Run()
}()
require.NoError(t, <-errC)
pty.ExpectMatch("\"f2\": 2")
stdout.ExpectMatchContext(ctx, "\"f2\": 2")
})
}
@@ -201,10 +201,11 @@ func TestLicensesDeleteFake(t *testing.T) {
t.Parallel()
inv := setupFakeLicenseServerTest(t, "licenses", "delete", "55")
pty := attachPty(t, inv)
stdout := expecter.NewAttachedToInvocation(t, inv)
clitest.Start(t, inv)
pty.ExpectMatch("License with ID 55 deleted")
ctx := testutil.Context(t, testutil.WaitMedium)
stdout.ExpectMatchContext(ctx, "License with ID 55 deleted")
})
}
@@ -240,13 +241,6 @@ func setupFakeLicenseServerTest(t *testing.T, args ...string) *serpent.Invocatio
return inv
}
func attachPty(t *testing.T, inv *serpent.Invocation) *ptytest.PTY {
pty := ptytest.New(t)
inv.Stdin = pty.Input()
inv.Stdout = pty.Output()
return pty
}
func newFakeLicenseAPI(t *testing.T) http.Handler {
r := chi.NewRouter()
a := &fakeLicenseAPI{t: t, r: r}
+12 -17
View File
@@ -13,8 +13,8 @@ import (
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/enterprise/coderd/coderdenttest"
"github.com/coder/coder/v2/enterprise/coderd/license"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
"github.com/coder/coder/v2/testutil/expecter"
)
func TestProvisionerKeys(t *testing.T) {
@@ -39,19 +39,18 @@ func TestProvisionerKeys(t *testing.T) {
"provisioner", "keys", "create", name, "--tag", "foo=bar", "--tag", "my=way",
)
pty := ptytest.New(t)
inv.Stdout = pty.Output()
stdout := expecter.NewAttachedToInvocation(t, inv)
clitest.SetupConfig(t, orgAdminClient, conf)
err := inv.WithContext(ctx).Run()
require.NoError(t, err)
line := pty.ReadLine(ctx)
line := stdout.ReadLine(ctx)
require.Contains(t, line, "Successfully created provisioner key")
require.Contains(t, line, strings.ToLower(name))
// empty line
_ = pty.ReadLine(ctx)
key := pty.ReadLine(ctx)
_ = stdout.ReadLine(ctx)
key := stdout.ReadLine(ctx)
require.NotEmpty(t, key)
require.NoError(t, provisionerkey.Validate(key))
@@ -59,17 +58,16 @@ func TestProvisionerKeys(t *testing.T) {
t,
"provisioner", "keys", "ls",
)
pty = ptytest.New(t)
inv.Stdout = pty.Output()
stdout = expecter.NewAttachedToInvocation(t, inv)
clitest.SetupConfig(t, orgAdminClient, conf)
err = inv.WithContext(ctx).Run()
require.NoError(t, err)
line = pty.ReadLine(ctx)
line = stdout.ReadLine(ctx)
require.Contains(t, line, "NAME")
require.Contains(t, line, "CREATED AT")
require.Contains(t, line, "TAGS")
line = pty.ReadLine(ctx)
line = stdout.ReadLine(ctx)
require.Contains(t, line, strings.ToLower(name))
require.Contains(t, line, "foo=bar my=way")
@@ -78,13 +76,12 @@ func TestProvisionerKeys(t *testing.T) {
"provisioner", "keys", "delete", "-y", name,
)
pty = ptytest.New(t)
inv.Stdout = pty.Output()
stdout = expecter.NewAttachedToInvocation(t, inv)
clitest.SetupConfig(t, orgAdminClient, conf)
err = inv.WithContext(ctx).Run()
require.NoError(t, err)
line = pty.ReadLine(ctx)
line = stdout.ReadLine(ctx)
require.Contains(t, line, "Successfully deleted provisioner key")
require.Contains(t, line, strings.ToLower(name))
@@ -92,14 +89,12 @@ func TestProvisionerKeys(t *testing.T) {
t,
"provisioner", "keys", "ls",
)
pty = ptytest.New(t)
inv.Stdout = pty.Output()
inv.Stderr = pty.Output()
stdout = expecter.NewAttachedToInvocation(t, inv)
clitest.SetupConfig(t, orgAdminClient, conf)
err = inv.WithContext(ctx).Run()
require.NoError(t, err)
line = pty.ReadLine(ctx)
line = stdout.ReadLine(ctx)
require.Contains(t, line, "No provisioner keys found")
})
}
-17
View File
@@ -18,7 +18,6 @@ import (
"github.com/coder/coder/v2/coderd/database/dbtestutil"
"github.com/coder/coder/v2/enterprise/cli"
"github.com/coder/coder/v2/enterprise/dbcrypt"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
)
@@ -72,11 +71,8 @@ func TestServerDBCrypt(t *testing.T) {
"--new-key", base64.StdEncoding.EncodeToString([]byte(keyA)),
"--yes",
)
pty := ptytest.New(t)
inv.Stdout = pty.Output()
err = inv.Run()
require.NoError(t, err)
require.NoError(t, pty.Close())
// Validate that all existing data has been encrypted with cipher A.
for _, usr := range users {
@@ -95,11 +91,8 @@ func TestServerDBCrypt(t *testing.T) {
"--old-keys", base64.StdEncoding.EncodeToString([]byte(keyA)),
"--yes",
)
pty = ptytest.New(t)
inv.Stdout = pty.Output()
err = inv.Run()
require.NoError(t, err)
require.NoError(t, pty.Close())
// Validate that all data has been re-encrypted with cipher B.
for _, usr := range users {
@@ -137,11 +130,8 @@ func TestServerDBCrypt(t *testing.T) {
"--keys", base64.StdEncoding.EncodeToString([]byte(keyB)),
"--yes",
)
pty = ptytest.New(t)
inv.Stdout = pty.Output()
err = inv.Run()
require.NoError(t, err)
require.NoError(t, pty.Close())
// Validate that both keys have been revoked.
keys, err = db.GetDBCryptKeys(ctx)
@@ -167,12 +157,8 @@ func TestServerDBCrypt(t *testing.T) {
"--new-key", base64.StdEncoding.EncodeToString([]byte(keyC)),
"--yes",
)
pty = ptytest.New(t)
inv.Stdout = pty.Output()
err = inv.Run()
require.NoError(t, err)
require.NoError(t, pty.Close())
// Validate that all data has been re-encrypted with cipher C.
for _, usr := range users {
@@ -186,11 +172,8 @@ func TestServerDBCrypt(t *testing.T) {
"--external-token-encryption-keys", base64.StdEncoding.EncodeToString([]byte(keyC)),
"--yes",
)
pty = ptytest.New(t)
inv.Stdout = pty.Output()
err = inv.Run()
require.NoError(t, err)
require.NoError(t, pty.Close())
// Assert that no user links remain.
for _, usr := range users {
+6 -10
View File
@@ -11,8 +11,8 @@ import (
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/enterprise/coderd/coderdenttest"
"github.com/coder/coder/v2/enterprise/coderd/license"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
"github.com/coder/coder/v2/testutil/expecter"
)
func Test_ProxyCRUD(t *testing.T) {
@@ -40,14 +40,14 @@ func Test_ProxyCRUD(t *testing.T) {
"--only-token",
)
pty := ptytest.New(t)
inv.Stdout = pty.Output()
var stdout *expecter.Expecter
stdout, inv.Stdout = expecter.NewPiped(t)
clitest.SetupConfig(t, client, conf) //nolint:gocritic // create wsproxy requires owner
err := inv.WithContext(ctx).Run()
require.NoError(t, err)
line := pty.ReadLine(ctx)
line := stdout.ReadLine(ctx)
parts := strings.Split(line, ":")
require.Len(t, parts, 2, "expected 2 parts")
_, err = uuid.Parse(parts[0])
@@ -59,13 +59,12 @@ func Test_ProxyCRUD(t *testing.T) {
"wsproxy", "ls",
)
pty = ptytest.New(t)
inv.Stdout = pty.Output()
stdout, inv.Stdout = expecter.NewPiped(t)
clitest.SetupConfig(t, client, conf) //nolint:gocritic // requires owner
err = inv.WithContext(ctx).Run()
require.NoError(t, err)
pty.ExpectMatch(expectedName)
stdout.ExpectMatchContext(ctx, expectedName)
// Also check via the api
proxies, err := client.WorkspaceProxies(ctx) //nolint:gocritic // requires owner
@@ -104,9 +103,6 @@ func Test_ProxyCRUD(t *testing.T) {
t,
"wsproxy", "delete", "-y", expectedName,
)
pty := ptytest.New(t)
inv.Stdout = pty.Output()
clitest.SetupConfig(t, client, conf) //nolint:gocritic // requires owner
err = inv.WithContext(ctx).Run()