Skip to content

Commit

Permalink
Add integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
maxsokolovsky committed Feb 29, 2024
1 parent 5fa33ae commit 514c2ec
Show file tree
Hide file tree
Showing 8 changed files with 393 additions and 22 deletions.
6 changes: 3 additions & 3 deletions commands/env/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@ func handleGetAllEnvironments(c client.Client) error {
}

var data [][]string
for _, d := range r.Data {
data = append(data, display.FormattedEnvironment(&d.Environment)...)
for i := range r.Data {
data = append(data, display.FormattedEnvironment(&r.Data[i])...)
}
columns := []string{"App", "UUID", "Ready", "Repo", "PR#", "URL"}
display.RenderTable(os.Stdout, columns, data)
Expand Down Expand Up @@ -180,7 +180,7 @@ func handleGetEnvironmentByID(c client.Client, id string) error {
return err
}

data := display.FormattedEnvironment(&r.Data.Environment)
data := display.FormattedEnvironment(&r.Data)
columns := []string{"App", "UUID", "Ready", "Repo", "PR#", "URL"}
display.RenderTable(os.Stdout, columns, data)
return nil
Expand Down
10 changes: 3 additions & 7 deletions pkg/types/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,12 @@ func UnmarshalOrgs(body []byte) (*OrgsResponse, error) {
}

type Response struct {
Data struct {
Environment
} `json:"data"`
Data Environment `json:"data"`
}

type RespManyEnvs struct {
Data []struct {
Environment
} `json:"data"`
Links Links `json:"links"`
Data []Environment `json:"data"`
Links Links `json:"links"`
}

type UUIDResponse struct {
Expand Down
25 changes: 13 additions & 12 deletions pkg/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,21 @@ type Service struct {
}

type Environment struct {
Attributes struct {
Name string `json:"name"`
URL string `json:"url"`
Ready bool `json:"ready"`

Projects []struct {
PullRequestNumber int `json:"pull_request_number"`
RepoName string `json:"repo_name"`
} `json:"projects"`
ID string `json:"id"`
Attributes EnvironmentAttributes `json:"attributes"`
}

Services []Service `json:"services"`
} `json:"attributes"`
type Project struct {
PullRequestNumber int `json:"pull_request_number"`
RepoName string `json:"repo_name"`
}

ID string `json:"id"`
type EnvironmentAttributes struct {
Name string `json:"name"`
URL string `json:"url"`
Ready bool `json:"ready"`
Projects []Project `json:"projects"`
Services []Service `json:"services"`
}

type Volume struct {
Expand Down
223 changes: 223 additions & 0 deletions tests/cli_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
package tests

import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"os/exec"
"testing"
"time"

"github.com/google/go-cmp/cmp"

"github.com/shipyard/shipyard-cli/pkg/types"
"github.com/shipyard/shipyard-cli/tests/server"
)

func TestMain(m *testing.M) {
cmd := exec.Command("go", "build", "-o", "shipyard", "..")
var stderr bytes.Buffer
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
fmt.Printf("Setup failure: %s", stderr.String())
os.Exit(1)
}
srv := &http.Server{
Addr: ":8000",
ReadHeaderTimeout: time.Second,
Handler: server.NewHandler(),
}
go func() {
if err := srv.ListenAndServe(); err != nil {
log.Fatalf("Could not start server: %v\n", err)
}
}()

code := m.Run()
if err := os.Remove("shipyard"); err != nil {
fmt.Printf("Cleanup failure: %v", err)
}
os.Exit(code)
}

func TestGetAllEnvironments(t *testing.T) {
t.Parallel()
tests := []struct {
name string
args []string
ids []string
output string
}{
{
name: "default org",
args: []string{"get", "envs", "--json"},
ids: []string{"default-1", "default-2"},
},
{
name: "non default org",
args: []string{"get", "envs", "--org", "pugs", "--json"},
ids: []string{"pug-1", "pug-2"},
},
{
name: "non existent org",
args: []string{"get", "envs", "--org", "cats"},
output: "Command error: user org not found\n",
},
}
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
t.Parallel()
c := newCmd(test.args)
if err := c.cmd.Run(); err != nil {
if diff := cmp.Diff(c.stdErr.String(), test.output); diff != "" {
t.Error(diff)
}
return
}
var resp types.RespManyEnvs
if err := json.Unmarshal(c.stdOut.Bytes(), &resp); err != nil {
t.Fatal(err)
}
var ids []string
for i := range resp.Data {
ids = append(ids, resp.Data[i].ID)
}
want := test.ids
if !cmp.Equal(ids, want) {
t.Error(cmp.Diff(ids, want))
}
})
}
}

func TestGetEnvironmentByID(t *testing.T) {
t.Parallel()
tests := []struct {
name string
args []string
id string
output string
}{
{
name: "default org",
args: []string{"get", "env", "default-1", "--json"},
id: "default-1",
},
{
name: "non default org",
args: []string{"get", "env", "pug-1", "--org", "pugs", "--json"},
id: "pug-1",
},
{
name: "non existent env",
args: []string{"get", "env", "sharpei-1", "--org", "pugs", "--json"},
output: "Command error: environment not found\n",
},
{
name: "non existent org",
args: []string{"get", "env", "cat-1", "--org", "cats"},
output: "Command error: user org not found\n",
},
}
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
t.Parallel()
c := newCmd(test.args)
if err := c.cmd.Run(); err != nil {
if diff := cmp.Diff(c.stdErr.String(), test.output); diff != "" {
t.Error(diff)
}
return
}
var resp types.Response
if err := json.Unmarshal(c.stdOut.Bytes(), &resp); err != nil {
t.Fatal(err)
}
want := test.id
got := resp.Data.ID
if !cmp.Equal(got, want) {
t.Error(cmp.Diff(got, want))
}
})
}
}

func TestRebuildEnvironment(t *testing.T) {
t.Parallel()
tests := []struct {
name string
args []string
output string
}{
{
name: "default org",
args: []string{"rebuild", "env", "default-1"},
output: "Environment queued for a rebuild.\n",
},
{
name: "non default org",
args: []string{"rebuild", "env", "pug-1", "--org", "pugs"},
output: "Environment queued for a rebuild.\n",
},
{
name: "non existent env",
args: []string{"rebuild", "env", "sharpei-1", "--org", "pugs"},
output: "Command error: environment not found\n",
},
{
name: "non existent org",
args: []string{"rebuild", "env", "pug-1", "--org", "cats"},
output: "Command error: user org not found\n",
},
}
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
t.Parallel()
c := newCmd(test.args)
err := c.cmd.Run()
if err != nil {
if diff := cmp.Diff(c.stdErr.String(), test.output); diff != "" {
t.Error(diff)
}
return
}
if diff := cmp.Diff(c.stdOut.String(), test.output); diff != "" {
t.Error(diff)
}
})
}
}

// nolint:gosec // Bad arguments can't be passed in.
func newCmd(args []string) *cmdWrapper {
c := cmdWrapper{
args: args,
}
c.cmd = exec.Command("./shipyard", commandLine(c.args)...)
c.cmd.Env = []string{"SHIPYARD_BUILD_URL=http://localhost:8000"}
stderr, stdout := new(bytes.Buffer), new(bytes.Buffer)
c.cmd.Stderr = stderr
c.cmd.Stdout = stdout
c.stdErr = stderr
c.stdOut = stdout
return &c
}

func commandLine(in []string) []string {
args := []string{"--config", "config.yaml"}
args = append(args, in...)
return args
}

type cmdWrapper struct {
cmd *exec.Cmd
args []string
stdErr *bytes.Buffer
stdOut *bytes.Buffer
}
2 changes: 2 additions & 0 deletions tests/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
api_token: test
org: default
65 changes: 65 additions & 0 deletions tests/server/handlers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package server

import (
"encoding/json"
"fmt"
"net/http"

"github.com/shipyard/shipyard-cli/pkg/types"
)

func (handler) getAllEnvironments(w http.ResponseWriter, r *http.Request) {
org := r.URL.Query().Get("org")
envs, ok := store[org]
if !ok {
orgNotFound(w)
return
}
resp := types.RespManyEnvs{Data: envs}
if err := json.NewEncoder(w).Encode(resp); err != nil {
w.WriteHeader(http.StatusInternalServerError)
_, _ = w.Write([]byte(err.Error()))
}
}

func (handler) getEnvironmentByID(w http.ResponseWriter, r *http.Request) {
env := findEnvByID(w, r)
if env != nil {
resp := types.Response{Data: *env}
if err := json.NewEncoder(w).Encode(resp); err != nil {
w.WriteHeader(http.StatusInternalServerError)
_, _ = w.Write([]byte(err.Error()))
}
}
}

func (handler) rebuildEnvironment(w http.ResponseWriter, r *http.Request) {
_ = findEnvByID(w, r)
}

func findEnvByID(w http.ResponseWriter, r *http.Request) *types.Environment {
org := r.URL.Query().Get("org")
envs, ok := store[org]
if !ok {
orgNotFound(w)
return nil
}
id := r.PathValue("id")
for i := range envs {
if envs[i].ID == id {
return &envs[i]
}
}
envNotFound(w)
return nil
}

func orgNotFound(w http.ResponseWriter) {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "user org not found")
}

func envNotFound(w http.ResponseWriter) {
w.WriteHeader(http.StatusNotFound)
fmt.Fprintf(w, "environment not found")
}
Loading

0 comments on commit 514c2ec

Please sign in to comment.