From 6c84163963472d8cd906608a13691843fca20f1c Mon Sep 17 00:00:00 2001 From: pauhull <22707808+pauhull@users.noreply.github.com> Date: Thu, 4 Jan 2024 14:48:15 +0100 Subject: [PATCH] test: add tests for --quiet flag --- internal/cmd/base/create_test.go | 155 ++++++++++++++++++++ internal/cmd/base/delete_test.go | 80 ++++++++++ internal/cmd/base/describe.go | 8 + internal/cmd/base/describe_test.go | 159 ++++++++++++++++++++ internal/cmd/base/list_test.go | 228 +++++++++++++++++++++++++++++ 5 files changed, 630 insertions(+) create mode 100644 internal/cmd/base/create_test.go create mode 100644 internal/cmd/base/delete_test.go create mode 100644 internal/cmd/base/describe_test.go create mode 100644 internal/cmd/base/list_test.go diff --git a/internal/cmd/base/create_test.go b/internal/cmd/base/create_test.go new file mode 100644 index 00000000..797f11f4 --- /dev/null +++ b/internal/cmd/base/create_test.go @@ -0,0 +1,155 @@ +package base_test + +import ( + "testing" + + "github.com/spf13/cobra" + "github.com/stretchr/testify/assert" + + "github.com/hetznercloud/cli/internal/cli" + "github.com/hetznercloud/cli/internal/cmd/base" + "github.com/hetznercloud/cli/internal/cmd/util" + "github.com/hetznercloud/cli/internal/hcapi2" + "github.com/hetznercloud/cli/internal/state" + "github.com/hetznercloud/cli/internal/testutil" +) + +type fakeResource struct { + ID int `json:"id"` + Name string `json:"name"` +} + +var commandCalled bool + +var fakeCreateCmd = base.CreateCmd{ + BaseCobraCommand: func(client hcapi2.Client) *cobra.Command { + return &cobra.Command{ + Use: "create", + } + }, + Run: func(s state.State, cmd *cobra.Command, strings []string) (any, any, error) { + cmd.Println("Creating fake resource") + commandCalled = true + + resource := &fakeResource{ + ID: 123, + Name: "test", + } + + return resource, util.Wrap("resource", resource), nil + }, +} + +func TestCreate(t *testing.T) { + commandCalled = false + + fx := testutil.NewFixture(t) + defer fx.Finish() + + cmd := cli.NewRootCommand(fx.State()) + fx.ExpectEnsureToken() + + cmd.AddCommand(fakeCreateCmd.CobraCommand(fx.State())) + + out, errOut, err := fx.Run(cmd, []string{"create"}) + + assert.Equal(t, true, commandCalled) + assert.NoError(t, err) + assert.Equal(t, "Creating fake resource\n", out) + assert.Empty(t, errOut) +} + +func TestCreateJSON(t *testing.T) { + commandCalled = false + + fx := testutil.NewFixture(t) + defer fx.Finish() + + cmd := cli.NewRootCommand(fx.State()) + fx.ExpectEnsureToken() + + cmd.AddCommand(fakeCreateCmd.CobraCommand(fx.State())) + + out, errOut, err := fx.Run(cmd, []string{"create", "-o=json"}) + + assert.Equal(t, true, commandCalled) + assert.NoError(t, err) + assert.JSONEq(t, `{"resource": {"id": 123, "name": "test"}}`, out) + assert.Equal(t, "Creating fake resource\n", errOut) +} + +func TestCreateYAML(t *testing.T) { + commandCalled = false + + fx := testutil.NewFixture(t) + defer fx.Finish() + + cmd := cli.NewRootCommand(fx.State()) + fx.ExpectEnsureToken() + + cmd.AddCommand(fakeCreateCmd.CobraCommand(fx.State())) + + out, errOut, err := fx.Run(cmd, []string{"create", "-o=yaml"}) + + assert.Equal(t, true, commandCalled) + assert.NoError(t, err) + assert.YAMLEq(t, `{"resource": {"id": 123, "name": "test"}}`, out) + assert.Equal(t, "Creating fake resource\n", errOut) +} + +func TestCreateQuiet(t *testing.T) { + commandCalled = false + + fx := testutil.NewFixture(t) + defer fx.Finish() + + cmd := cli.NewRootCommand(fx.State()) + fx.ExpectEnsureToken() + + cmd.AddCommand(fakeCreateCmd.CobraCommand(fx.State())) + + out, errOut, err := fx.Run(cmd, []string{"create", "--quiet"}) + + assert.Equal(t, true, commandCalled) + assert.NoError(t, err) + assert.Empty(t, out) + assert.Empty(t, errOut) +} + +func TestCreateJSONQuiet(t *testing.T) { + commandCalled = false + + fx := testutil.NewFixture(t) + defer fx.Finish() + + cmd := cli.NewRootCommand(fx.State()) + fx.ExpectEnsureToken() + + cmd.AddCommand(fakeCreateCmd.CobraCommand(fx.State())) + + out, errOut, err := fx.Run(cmd, []string{"create", "-o=json", "--quiet"}) + + assert.Equal(t, true, commandCalled) + assert.NoError(t, err) + assert.JSONEq(t, `{"resource": {"id": 123, "name": "test"}}`, out) + assert.Empty(t, errOut) +} + +func TestCreateYAMLQuiet(t *testing.T) { + commandCalled = false + + fx := testutil.NewFixture(t) + defer fx.Finish() + + cmd := cli.NewRootCommand(fx.State()) + fx.ExpectEnsureToken() + + cmd.AddCommand(fakeCreateCmd.CobraCommand(fx.State())) + + out, errOut, err := fx.Run(cmd, []string{"create", "-o=yaml", "--quiet"}) + + assert.Equal(t, true, commandCalled) + assert.NoError(t, err) + assert.YAMLEq(t, `{"resource": {"id": 123, "name": "test"}}`, out) + assert.Empty(t, errOut) +} diff --git a/internal/cmd/base/delete_test.go b/internal/cmd/base/delete_test.go new file mode 100644 index 00000000..80ca8ecb --- /dev/null +++ b/internal/cmd/base/delete_test.go @@ -0,0 +1,80 @@ +package base_test + +import ( + "testing" + + "github.com/spf13/cobra" + "github.com/stretchr/testify/assert" + + "github.com/hetznercloud/cli/internal/cli" + "github.com/hetznercloud/cli/internal/cmd/base" + "github.com/hetznercloud/cli/internal/hcapi2" + "github.com/hetznercloud/cli/internal/state" + "github.com/hetznercloud/cli/internal/testutil" + "github.com/hetznercloud/hcloud-go/v2/hcloud" +) + +var fakeDeleteCmd = base.DeleteCmd{ + ResourceNameSingular: "Fake resource", + Delete: func(s state.State, cmd *cobra.Command, resource interface{}) error { + cmd.Println("Deleting fake resource") + commandCalled = true + return nil + }, + + Fetch: func(s state.State, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) { + cmd.Println("Fetching fake resource") + + resource := &fakeResource{ + ID: 123, + Name: "test", + } + + return resource, nil, nil + }, + + NameSuggestions: func(client hcapi2.Client) func() []string { + return nil + }, +} + +func TestDelete(t *testing.T) { + commandCalled = false + + fx := testutil.NewFixture(t) + defer fx.Finish() + + cmd := cli.NewRootCommand(fx.State()) + fx.ExpectEnsureToken() + + cmd.AddCommand(fakeDeleteCmd.CobraCommand(fx.State())) + + out, errOut, err := fx.Run(cmd, []string{"delete", "123"}) + + assert.Equal(t, true, commandCalled) + assert.NoError(t, err) + assert.Equal(t, `Fetching fake resource +Deleting fake resource +Fake resource 123 deleted +`, out) + assert.Empty(t, errOut) +} + +func TestDeleteQuiet(t *testing.T) { + commandCalled = false + + fx := testutil.NewFixture(t) + defer fx.Finish() + + cmd := cli.NewRootCommand(fx.State()) + fx.ExpectEnsureToken() + + cmd.AddCommand(fakeDeleteCmd.CobraCommand(fx.State())) + + out, errOut, err := fx.Run(cmd, []string{"delete", "123", "--quiet"}) + + assert.Equal(t, true, commandCalled) + assert.NoError(t, err) + assert.Empty(t, out) + assert.Empty(t, errOut) +} diff --git a/internal/cmd/base/describe.go b/internal/cmd/base/describe.go index 5d50faf1..2edb556d 100644 --- a/internal/cmd/base/describe.go +++ b/internal/cmd/base/describe.go @@ -2,6 +2,7 @@ package base import ( "fmt" + "os" "reflect" "strings" @@ -54,6 +55,13 @@ func (dc *DescribeCmd) CobraCommand(s state.State) *cobra.Command { func (dc *DescribeCmd) Run(s state.State, cmd *cobra.Command, args []string) error { outputFlags := output.FlagsForCommand(cmd) + quiet, _ := cmd.Flags().GetBool("quiet") + + isSchema := outputFlags.IsSet("json") || outputFlags.IsSet("yaml") + if isSchema && !quiet { + cmd.SetOut(os.Stderr) + } + idOrName := args[0] resource, schema, err := dc.Fetch(s, cmd, idOrName) if err != nil { diff --git a/internal/cmd/base/describe_test.go b/internal/cmd/base/describe_test.go new file mode 100644 index 00000000..755bce5f --- /dev/null +++ b/internal/cmd/base/describe_test.go @@ -0,0 +1,159 @@ +package base_test + +import ( + "testing" + + "github.com/spf13/cobra" + "github.com/stretchr/testify/assert" + + "github.com/hetznercloud/cli/internal/cli" + "github.com/hetznercloud/cli/internal/cmd/base" + "github.com/hetznercloud/cli/internal/cmd/util" + "github.com/hetznercloud/cli/internal/hcapi2" + "github.com/hetznercloud/cli/internal/state" + "github.com/hetznercloud/cli/internal/testutil" +) + +var fakeDescribeCmd = base.DescribeCmd{ + ResourceNameSingular: "Fake resource", + + Fetch: func(s state.State, cmd *cobra.Command, idOrName string) (interface{}, interface{}, error) { + cmd.Println("Fetching fake resource") + commandCalled = true + + resource := &fakeResource{ + ID: 123, + Name: "test", + } + + return resource, util.Wrap("resource", resource), nil + }, + + PrintText: func(s state.State, cmd *cobra.Command, resource interface{}) error { + rsc := resource.(*fakeResource) + cmd.Printf("ID: %d\n", rsc.ID) + cmd.Printf("Name: %s\n", rsc.Name) + return nil + }, + + NameSuggestions: func(client hcapi2.Client) func() []string { + return nil + }, +} + +func TestDescribe(t *testing.T) { + commandCalled = false + + fx := testutil.NewFixture(t) + defer fx.Finish() + + cmd := cli.NewRootCommand(fx.State()) + fx.ExpectEnsureToken() + + cmd.AddCommand(fakeDescribeCmd.CobraCommand(fx.State())) + + out, errOut, err := fx.Run(cmd, []string{"describe", "123"}) + + assert.Equal(t, true, commandCalled) + assert.NoError(t, err) + assert.Equal(t, `Fetching fake resource +ID: 123 +Name: test +`, out) + assert.Empty(t, errOut) +} + +func TestDescribeJSON(t *testing.T) { + commandCalled = false + + fx := testutil.NewFixture(t) + defer fx.Finish() + + cmd := cli.NewRootCommand(fx.State()) + fx.ExpectEnsureToken() + + cmd.AddCommand(fakeDescribeCmd.CobraCommand(fx.State())) + + out, errOut, err := fx.Run(cmd, []string{"describe", "123", "-o=json"}) + + assert.Equal(t, true, commandCalled) + assert.NoError(t, err) + assert.JSONEq(t, `{"resource": {"id": 123, "name": "test"}}`, out) + assert.Equal(t, "Fetching fake resource\n", errOut) +} + +func TestDescribeYAML(t *testing.T) { + commandCalled = false + + fx := testutil.NewFixture(t) + defer fx.Finish() + + cmd := cli.NewRootCommand(fx.State()) + fx.ExpectEnsureToken() + + cmd.AddCommand(fakeDescribeCmd.CobraCommand(fx.State())) + + out, errOut, err := fx.Run(cmd, []string{"describe", "123", "-o=yaml"}) + + assert.Equal(t, true, commandCalled) + assert.NoError(t, err) + assert.YAMLEq(t, `{"resource": {"id": 123, "name": "test"}}`, out) + assert.Equal(t, "Fetching fake resource\n", errOut) +} + +func TestDescribeQuiet(t *testing.T) { + commandCalled = false + + fx := testutil.NewFixture(t) + defer fx.Finish() + + cmd := cli.NewRootCommand(fx.State()) + fx.ExpectEnsureToken() + + cmd.AddCommand(fakeDescribeCmd.CobraCommand(fx.State())) + + out, errOut, err := fx.Run(cmd, []string{"describe", "123", "--quiet"}) + + assert.Equal(t, true, commandCalled) + assert.NoError(t, err) + assert.Empty(t, out) + assert.Empty(t, errOut) +} + +func TestDescribeJSONQuiet(t *testing.T) { + commandCalled = false + + fx := testutil.NewFixture(t) + defer fx.Finish() + + cmd := cli.NewRootCommand(fx.State()) + fx.ExpectEnsureToken() + + cmd.AddCommand(fakeDescribeCmd.CobraCommand(fx.State())) + + out, errOut, err := fx.Run(cmd, []string{"describe", "123", "-o=json", "--quiet"}) + + assert.Equal(t, true, commandCalled) + assert.NoError(t, err) + assert.JSONEq(t, `{"resource": {"id": 123, "name": "test"}}`, out) + assert.Empty(t, errOut) +} + +func TestDescribeYAMLQuiet(t *testing.T) { + commandCalled = false + + fx := testutil.NewFixture(t) + defer fx.Finish() + + cmd := cli.NewRootCommand(fx.State()) + fx.ExpectEnsureToken() + + cmd.AddCommand(fakeDescribeCmd.CobraCommand(fx.State())) + + out, errOut, err := fx.Run(cmd, []string{"describe", "123", "-o=yaml", "--quiet"}) + + assert.Equal(t, true, commandCalled) + assert.NoError(t, err) + assert.YAMLEq(t, `{"resource": {"id": 123, "name": "test"}}`, out) + assert.Empty(t, errOut) +} diff --git a/internal/cmd/base/list_test.go b/internal/cmd/base/list_test.go new file mode 100644 index 00000000..d5b9321a --- /dev/null +++ b/internal/cmd/base/list_test.go @@ -0,0 +1,228 @@ +package base_test + +import ( + "fmt" + "testing" + + "github.com/spf13/pflag" + "github.com/stretchr/testify/assert" + + "github.com/hetznercloud/cli/internal/cli" + "github.com/hetznercloud/cli/internal/cmd/base" + "github.com/hetznercloud/cli/internal/cmd/output" + "github.com/hetznercloud/cli/internal/hcapi2" + "github.com/hetznercloud/cli/internal/state" + "github.com/hetznercloud/cli/internal/testutil" + "github.com/hetznercloud/hcloud-go/v2/hcloud" +) + +var fakeListCmd = base.ListCmd{ + ResourceNamePlural: "Fake resources", + + Schema: func(i []interface{}) interface{} { + return i + }, + + OutputTable: func(client hcapi2.Client) *output.Table { + return output.NewTable(). + AddAllowedFields(hcloud.Firewall{}). + AddFieldFn("id", func(obj interface{}) string { + rsc := obj.(*fakeResource) + return fmt.Sprintf("%d", rsc.ID) + }). + AddFieldFn("name", func(obj interface{}) string { + rsc := obj.(*fakeResource) + return rsc.Name + }) + }, + + DefaultColumns: []string{"id", "name"}, + + Fetch: func(s state.State, set *pflag.FlagSet, opts hcloud.ListOpts, strings []string) ([]interface{}, error) { + commandCalled = true + return []interface{}{ + &fakeResource{ + ID: 123, + Name: "test", + }, + &fakeResource{ + ID: 321, + Name: "test2", + }, + &fakeResource{ + ID: 42, + Name: "test3", + }, + }, nil + }, +} + +func TestList(t *testing.T) { + commandCalled = false + + fx := testutil.NewFixture(t) + defer fx.Finish() + + cmd := cli.NewRootCommand(fx.State()) + fx.ExpectEnsureToken() + + cmd.AddCommand(fakeListCmd.CobraCommand(fx.State())) + + out, errOut, err := fx.Run(cmd, []string{"list"}) + + assert.Equal(t, true, commandCalled) + assert.NoError(t, err) + assert.Equal(t, "ID NAME\n123 test\n321 test2\n42 test3\n", out) + assert.Empty(t, errOut) +} + +func TestListJSON(t *testing.T) { + commandCalled = false + + fx := testutil.NewFixture(t) + defer fx.Finish() + + cmd := cli.NewRootCommand(fx.State()) + fx.ExpectEnsureToken() + + cmd.AddCommand(fakeListCmd.CobraCommand(fx.State())) + + out, errOut, err := fx.Run(cmd, []string{"list", "-o=json"}) + + assert.Equal(t, true, commandCalled) + assert.NoError(t, err) + assert.JSONEq(t, ` +[ + { + "id": 123, + "name": "test" + }, + { + "id": 321, + "name": "test2" + }, + { + "id": 42, + "name": "test3" + } +]`, out) + assert.Empty(t, errOut) +} + +func TestListYAML(t *testing.T) { + commandCalled = false + + fx := testutil.NewFixture(t) + defer fx.Finish() + + cmd := cli.NewRootCommand(fx.State()) + fx.ExpectEnsureToken() + + cmd.AddCommand(fakeListCmd.CobraCommand(fx.State())) + + out, errOut, err := fx.Run(cmd, []string{"list", "-o=json"}) + + assert.Equal(t, true, commandCalled) + assert.NoError(t, err) + assert.YAMLEq(t, ` +[ + { + "id": 123, + "name": "test" + }, + { + "id": 321, + "name": "test2" + }, + { + "id": 42, + "name": "test3" + } +]`, out) + assert.Empty(t, errOut) +} + +func TestListQuiet(t *testing.T) { + commandCalled = false + + fx := testutil.NewFixture(t) + defer fx.Finish() + + cmd := cli.NewRootCommand(fx.State()) + fx.ExpectEnsureToken() + + cmd.AddCommand(fakeListCmd.CobraCommand(fx.State())) + + out, errOut, err := fx.Run(cmd, []string{"list", "--quiet"}) + + assert.Equal(t, true, commandCalled) + assert.NoError(t, err) + assert.Equal(t, "ID NAME\n123 test\n321 test2\n42 test3\n", out) + assert.Empty(t, errOut) +} + +func TestListJSONQuiet(t *testing.T) { + commandCalled = false + + fx := testutil.NewFixture(t) + defer fx.Finish() + + cmd := cli.NewRootCommand(fx.State()) + fx.ExpectEnsureToken() + + cmd.AddCommand(fakeListCmd.CobraCommand(fx.State())) + + out, errOut, err := fx.Run(cmd, []string{"list", "-o=json", "--quiet"}) + + assert.Equal(t, true, commandCalled) + assert.NoError(t, err) + assert.JSONEq(t, ` +[ + { + "id": 123, + "name": "test" + }, + { + "id": 321, + "name": "test2" + }, + { + "id": 42, + "name": "test3" + } +]`, out) + assert.Empty(t, errOut) +} + +func TestListYAMLQuiet(t *testing.T) { + commandCalled = false + + fx := testutil.NewFixture(t) + defer fx.Finish() + + cmd := cli.NewRootCommand(fx.State()) + fx.ExpectEnsureToken() + + cmd.AddCommand(fakeListCmd.CobraCommand(fx.State())) + + out, errOut, err := fx.Run(cmd, []string{"list", "-o=json", "--quiet"}) + + assert.Equal(t, true, commandCalled) + assert.NoError(t, err) + assert.YAMLEq(t, ` +[ + { + "id": 123, + "name": "test" + }, + { + "id": 321, + "name": "test2" + }, + { + "id": 42, + "name": "test3" + } +]`, out) + assert.Empty(t, errOut) +}