Skip to content
This repository was archived by the owner on Aug 30, 2024. It is now read-only.

chore: add auth init to unit tests #280

Merged
merged 6 commits into from
Mar 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ jobs:
uses: ./ci/image
env:
COVERALLS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CODER_URL: ${{ secrets.CODER_URL }}
CODER_EMAIL: ${{ secrets.CODER_EMAIL }}
CODER_PASSWORD: ${{ secrets.CODER_PASSWORD }}
with:
args: make -j test/coverage
gendocs:
Expand Down
142 changes: 142 additions & 0 deletions internal/cmd/cli_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package cmd

import (
"bytes"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/url"
"os"
"strings"
"testing"

"cdr.dev/slog"
"cdr.dev/slog/sloggers/slogtest"
"cdr.dev/slog/sloggers/slogtest/assert"
"golang.org/x/xerrors"

"cdr.dev/coder-cli/coder-sdk"
"cdr.dev/coder-cli/internal/config"
"cdr.dev/coder-cli/pkg/clog"
)

func init() {
tmpDir, err := ioutil.TempDir("", "coder-cli-config-dir")
if err != nil {
panic(err)
}
config.SetRoot(tmpDir)

// TODO: might need to make this a command scoped option to make assertions against its output
clog.SetOutput(ioutil.Discard)

email := os.Getenv("CODER_EMAIL")
password := os.Getenv("CODER_PASSWORD")
rawURL := os.Getenv("CODER_URL")
if email == "" || password == "" || rawURL == "" {
Comment on lines +34 to +37
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jawnsy strong feelings on this vs. flags?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally prefer flags, but whatever works I guess. The exception would be if these are standard variables that contain credentials (e.g. like KUBECONFIG) that we expect people to set, or that may be injected via the platform (e.g. if we inject tokens automatically into workspaces, so that coder-cli works out-of-the-box and is authenticated with the "owner" user credentials)

panic("CODER_EMAIL, CODER_PASSWORD, and CODER_URL are required environment variables")
}
u, err := url.Parse(rawURL)
if err != nil {
panic("invalid CODER_URL: " + err.Error())
}
client, err := coder.NewClient(coder.ClientOptions{
BaseURL: u,
Email: email,
Password: password,
})
if err != nil {
panic("new client: " + err.Error())
}
if err := config.URL.Write(rawURL); err != nil {
panic("write config url: " + err.Error())
}
if err := config.Session.Write(client.Token()); err != nil {
panic("write config token: " + err.Error())
}
}

type result struct {
outBuffer *bytes.Buffer
errBuffer *bytes.Buffer
exitErr error
}

func (r result) success(t *testing.T) {
t.Helper()
assert.Success(t, "execute command", r.exitErr)
}

//nolint
func (r result) stdoutContains(t *testing.T, substring string) {
t.Helper()
if !strings.Contains(r.outBuffer.String(), substring) {
slogtest.Fatal(t, "stdout contains substring", slog.F("substring", substring), slog.F("stdout", r.outBuffer.String()))
}
}

//nolint
func (r result) stdoutUnmarshals(t *testing.T, target interface{}) {
t.Helper()
err := json.Unmarshal(r.outBuffer.Bytes(), target)
assert.Success(t, "unmarshal json", err)
}

//nolint
func (r result) stdoutEmpty(t *testing.T) {
t.Helper()
assert.Equal(t, "stdout empty", "", r.outBuffer.String())
}

//nolint
func (r result) stderrEmpty(t *testing.T) {
t.Helper()
assert.Equal(t, "stderr empty", "", r.errBuffer.String())
}

//nolint
func (r result) stderrContains(t *testing.T, substring string) {
t.Helper()
if !strings.Contains(r.errBuffer.String(), substring) {
slogtest.Fatal(t, "stderr contains substring", slog.F("substring", substring), slog.F("stderr", r.errBuffer.String()))
}
}

//nolint
func (r result) clogError(t *testing.T) clog.CLIError {
t.Helper()
var cliErr clog.CLIError
if !xerrors.As(r.exitErr, &cliErr) {
slogtest.Fatal(t, "expected clog error, none found", slog.Error(r.exitErr), slog.F("type", fmt.Sprintf("%T", r.exitErr)))
}
slogtest.Debug(t, "clog error", slog.F("message", cliErr.String()))
return cliErr
}

func execute(t *testing.T, in io.Reader, args ...string) result {
cmd := Make()

var outStream bytes.Buffer
var errStream bytes.Buffer

cmd.SetArgs(args)

cmd.SetIn(in)
cmd.SetOut(&outStream)
cmd.SetErr(&errStream)

err := cmd.Execute()

slogtest.Debug(t, "execute command",
slog.F("out_buffer", outStream.String()),
slog.F("err_buffer", errStream.String()),
slog.F("args", args),
slog.F("execute_error", err),
)
return result{
outBuffer: &outStream,
errBuffer: &errStream,
exitErr: err,
}
}
74 changes: 8 additions & 66 deletions internal/cmd/envs_test.go
Original file line number Diff line number Diff line change
@@ -1,76 +1,18 @@
package cmd

import (
"bytes"
"fmt"
"io"
"io/ioutil"
"strings"
"testing"

"cdr.dev/slog"
"cdr.dev/slog/sloggers/slogtest"
"cdr.dev/slog/sloggers/slogtest/assert"
"golang.org/x/xerrors"

"cdr.dev/coder-cli/internal/config"
"cdr.dev/coder-cli/pkg/clog"
"cdr.dev/coder-cli/coder-sdk"
)

func init() {
tmpDir, err := ioutil.TempDir("", "coder-cli-config-dir")
if err != nil {
panic(err)
}
config.SetRoot(tmpDir)
}

func TestEnvsCommand(t *testing.T) {
res := execute(t, []string{"envs", "ls"}, nil)
assert.Error(t, "execute without auth", res.ExitErr)

err := assertClogErr(t, res.ExitErr)
assert.True(t, "login hint in error", strings.Contains(err.String(), "did you run \"coder login"))
}

type result struct {
OutBuffer *bytes.Buffer
ErrBuffer *bytes.Buffer
ExitErr error
}
func Test_envs_ls(t *testing.T) {
res := execute(t, nil, "envs", "ls")
res.success(t)

func execute(t *testing.T, args []string, in io.Reader) result {
cmd := Make()

outStream := bytes.NewBuffer(nil)
errStream := bytes.NewBuffer(nil)

cmd.SetArgs(args)

cmd.SetIn(in)
cmd.SetOut(outStream)
cmd.SetErr(errStream)

err := cmd.Execute()

slogtest.Debug(t, "execute command",
slog.F("outBuffer", outStream.String()),
slog.F("errBuffer", errStream.String()),
slog.F("args", args),
slog.F("execute_error", err),
)
return result{
OutBuffer: outStream,
ErrBuffer: errStream,
ExitErr: err,
}
}
res = execute(t, nil, "envs", "ls", "--output=json")
res.success(t)

func assertClogErr(t *testing.T, err error) clog.CLIError {
var cliErr clog.CLIError
if !xerrors.As(err, &cliErr) {
slogtest.Fatal(t, "expected clog error, none found", slog.Error(err), slog.F("type", fmt.Sprintf("%T", err)))
}
slogtest.Debug(t, "clog error", slog.F("message", cliErr.String()))
return cliErr
var envs []coder.Environment
res.stdoutUnmarshals(t, &envs)
}
10 changes: 10 additions & 0 deletions internal/cmd/providers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package cmd

import (
"testing"
)

func Test_providers_ls(t *testing.T) {
res := execute(t, nil, "providers", "ls")
res.success(t)
}