// Copyright (c) Abstract Machines // SPDX-License-Identifier: Apache-2.0 package cli_test import ( "encoding/json" "fmt" "net/http" "strings" "testing" "github.com/absmach/magistrala/cli" "github.com/absmach/magistrala/internal/testsutil" "github.com/absmach/magistrala/pkg/errors" svcerr "github.com/absmach/magistrala/pkg/errors/service" mgsdk "github.com/absmach/magistrala/pkg/sdk" sdkmocks "github.com/absmach/magistrala/pkg/sdk/mocks" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) var ( clientID = testsutil.GenerateUUID(&testing.T{}) channelID = testsutil.GenerateUUID(&testing.T{}) domainID = testsutil.GenerateUUID(&testing.T{}) profileID = testsutil.GenerateUUID(&testing.T{}) bootConfig = mgsdk.BootstrapConfig{ ID: clientID, Name: "Test Bootstrap", ExternalID: "09:6:0:sb:sa", ExternalKey: "key", } bootProfile = mgsdk.BootstrapProfile{ ID: profileID, Name: "Test Profile", Description: "Test profile", ContentFormat: "go-template", ContentTemplate: "{\"device_id\":\"{{ .Device.ID }}\"}", Version: 1, } validToken = "validToken" invalidToken = "invalidToken" extraArg = "extra-arg" invalidID = "invalidID" all = "all" ) func TestCreateBootstrapConfigCmd(t *testing.T) { sdkMock := new(sdkmocks.SDK) cli.SetSDK(sdkMock) bootCmd := cli.NewBootstrapCmd() rootCmd := setFlags(bootCmd) jsonConfig := fmt.Sprintf("{\"external_id\":\"09:6:0:sb:sa\", \"external_key\":\"key\", \"name\": \"%s\"}", "Test Bootstrap") invalidJson := fmt.Sprintf("{\"external_id\":\"09:6:0:sb:sa\", \"external_key\":\"key\", \"name\": \"%s\"", "Test Bootstrap") cases := []struct { desc string args []string logType outputLog response string sdkErr errors.SDKError errLogMessage string id string }{ { desc: "create bootstrap config successfully", args: []string{ jsonConfig, domainID, validToken, }, logType: createLog, id: clientID, response: fmt.Sprintf("\ncreated: %s\n\n", clientID), }, { desc: "create bootstrap config with invald args", args: []string{ jsonConfig, domainID, validToken, extraArg, }, logType: usageLog, }, { desc: "create bootstrap config with invald json", args: []string{ invalidJson, domainID, validToken, }, sdkErr: errors.NewSDKError(errors.New("unexpected end of JSON input")), errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.New("unexpected end of JSON input")), logType: errLog, }, { desc: "create bootstrap config with invald token", args: []string{ jsonConfig, domainID, invalidToken, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized), errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized)), logType: errLog, }, } for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { sdkCall := sdkMock.On("AddBootstrap", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.id, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{createCmd}, tc.args...)...) switch tc.logType { case createLog: assert.Equal(t, tc.response, out, fmt.Sprintf("%s unexpected error response: expected %s got errLogMessage:%s", tc.desc, tc.response, out)) case errLog: assert.Equal(t, tc.errLogMessage, out, fmt.Sprintf("%s unexpected error response: expected %s got errLogMessage:%s", tc.desc, tc.errLogMessage, out)) case usageLog: assert.False(t, strings.Contains(out, rootCmd.Use), fmt.Sprintf("%s invalid usage: %s", tc.desc, out)) } sdkCall.Unset() }) } } func TestGetBootstrapConfigCmd(t *testing.T) { sdkMock := new(sdkmocks.SDK) cli.SetSDK(sdkMock) bootCmd := cli.NewBootstrapCmd() rootCmd := setFlags(bootCmd) var boot mgsdk.BootstrapConfig var page mgsdk.BootstrapPage cases := []struct { desc string args []string sdkErr errors.SDKError page mgsdk.BootstrapPage boot mgsdk.BootstrapConfig logType outputLog errLogMessage string }{ { desc: "get all bootstrap config successfully", args: []string{ all, domainID, validToken, }, page: mgsdk.BootstrapPage{ PageRes: mgsdk.PageRes{ Total: 1, Offset: 0, Limit: 10, }, Configs: []mgsdk.BootstrapConfig{bootConfig}, }, logType: entityLog, }, { desc: "get bootstrap config with id", args: []string{ channelID, domainID, validToken, }, logType: entityLog, boot: bootConfig, }, { desc: "get bootstrap config with invalid args", args: []string{ all, domainID, validToken, extraArg, }, logType: usageLog, }, { desc: "get all bootstrap config with invalid token", args: []string{ all, domainID, invalidToken, }, logType: errLog, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden)), }, { desc: "get bootstrap config with invalid id", args: []string{ invalidID, domainID, validToken, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden)), logType: errLog, }, } for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { sdkCall := sdkMock.On("ViewBootstrap", mock.Anything, tc.args[0], tc.args[1], tc.args[2]).Return(tc.boot, tc.sdkErr) sdkCall1 := sdkMock.On("Bootstraps", mock.Anything, mock.Anything, tc.args[1], tc.args[2]).Return(tc.page, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{getCmd}, tc.args...)...) switch tc.logType { case entityLog: if tc.args[0] == all { err := json.Unmarshal([]byte(out), &page) assert.Nil(t, err) assert.Equal(t, tc.page, page, fmt.Sprintf("%v unexpected response, expected: %v, got: %v", tc.desc, tc.page, page)) } else { err := json.Unmarshal([]byte(out), &boot) assert.Nil(t, err) assert.Equal(t, tc.boot, boot, fmt.Sprintf("%v unexpected response, expected: %v, got: %v", tc.desc, tc.boot, boot)) } case errLog: assert.Equal(t, tc.errLogMessage, out, fmt.Sprintf("%s unexpected error response: expected %s got errLogMessage:%s", tc.desc, tc.errLogMessage, out)) case usageLog: assert.False(t, strings.Contains(out, rootCmd.Use), fmt.Sprintf("%s invalid usage: %s", tc.desc, out)) } sdkCall.Unset() sdkCall1.Unset() }) } } func TestRemoveBootstrapConfigCmd(t *testing.T) { sdkMock := new(sdkmocks.SDK) cli.SetSDK(sdkMock) bootCmd := cli.NewBootstrapCmd() rootCmd := setFlags(bootCmd) cases := []struct { desc string args []string sdkErr errors.SDKError logType outputLog errLogMessage string }{ { desc: "remove bootstrap config successfully", args: []string{ clientID, domainID, validToken, }, logType: okLog, }, { desc: "remove bootstrap config with invalid args", args: []string{ clientID, domainID, validToken, extraArg, }, logType: usageLog, }, { desc: "remove bootstrap config with invalid client id", args: []string{ invalidID, domainID, validToken, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden)), logType: errLog, }, { desc: "remove bootstrap config with invalid token", args: []string{ clientID, domainID, invalidToken, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden)), logType: errLog, }, } for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { sdkCall := sdkMock.On("RemoveBootstrap", mock.Anything, tc.args[0], tc.args[1], tc.args[2]).Return(tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{rmCmd}, tc.args...)...) switch tc.logType { case okLog: assert.True(t, strings.Contains(out, "ok"), fmt.Sprintf("%s unexpected response: expected success message, got: %v", tc.desc, out)) case errLog: assert.Equal(t, tc.errLogMessage, out, fmt.Sprintf("%s unexpected error response: expected %s got errLogMessage:%s", tc.desc, tc.errLogMessage, out)) case usageLog: assert.False(t, strings.Contains(out, rootCmd.Use), fmt.Sprintf("%s invalid usage: %s", tc.desc, out)) } sdkCall.Unset() }) } } func TestUpdateBootstrapConfigCmd(t *testing.T) { sdkMock := new(sdkmocks.SDK) cli.SetSDK(sdkMock) bootCmd := cli.NewBootstrapCmd() rootCmd := setFlags(bootCmd) config := "config" connection := "connection" newConfigJson := "{\"name\" : \"New Bootstrap\"}" chanIDsJson := fmt.Sprintf("[\"%s\"]", channelID) cases := []struct { desc string args []string boot mgsdk.BootstrapConfig sdkErr errors.SDKError errLogMessage string logType outputLog }{ { desc: "update bootstrap config successfully", args: []string{ config, newConfigJson, domainID, validToken, }, logType: okLog, }, { desc: "update bootstrap config with invalid token", args: []string{ config, newConfigJson, domainID, invalidToken, }, logType: errLog, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden)), }, { desc: "update bootstrap connections successfully", args: []string{ connection, clientID, chanIDsJson, domainID, validToken, }, logType: okLog, }, { desc: "update bootstrap connections with invalid json", args: []string{ connection, clientID, fmt.Sprintf("[\"%s\"", clientID), domainID, validToken, }, sdkErr: errors.NewSDKError(errors.New("unexpected end of JSON input")), errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.New("unexpected end of JSON input")), logType: errLog, }, { desc: "update bootstrap connections with invalid token", args: []string{ connection, clientID, chanIDsJson, domainID, invalidToken, }, logType: errLog, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden)), }, { desc: "update bootstrap certs successfully", args: []string{ "certs", clientID, "client cert", "client key", "ca", domainID, validToken, }, boot: bootConfig, logType: entityLog, }, { desc: "update bootstrap certs with invalid token", args: []string{ "certs", clientID, "client cert", "client key", "ca", domainID, invalidToken, }, logType: errLog, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden)), }, { desc: "update bootstrap config with invalid args", args: []string{ newConfigJson, domainID, validToken, }, logType: usageLog, }, { desc: "update bootstrap config with invalid json", args: []string{ config, "{\"name\" : \"New Bootstrap\"", domainID, validToken, }, sdkErr: errors.NewSDKError(errors.New("unexpected end of JSON input")), errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.New("unexpected end of JSON input")), logType: errLog, }, { desc: "update bootstrap with invalid args", args: []string{ extraArg, extraArg, extraArg, extraArg, extraArg, }, logType: usageLog, }, } for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { var boot mgsdk.BootstrapConfig sdkCall := sdkMock.On("UpdateBootstrap", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.sdkErr) sdkCall1 := sdkMock.On("UpdateBootstrapConnection", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.sdkErr) sdkCall2 := sdkMock.On("UpdateBootstrapCerts", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.boot, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{updCmd}, tc.args...)...) switch tc.logType { case entityLog: err := json.Unmarshal([]byte(out), &boot) assert.Nil(t, err) assert.Equal(t, tc.boot, boot, fmt.Sprintf("%s unexpected response: expected: %v, got: %v", tc.desc, tc.boot, boot)) case okLog: assert.True(t, strings.Contains(out, "ok"), fmt.Sprintf("%s unexpected response: expected success message, got: %v", tc.desc, out)) case usageLog: assert.False(t, strings.Contains(out, rootCmd.Use), fmt.Sprintf("%s invalid usage: %s", tc.desc, out)) case errLog: assert.Equal(t, tc.errLogMessage, out, fmt.Sprintf("%s unexpected error response: expected %s got errLogMessage:%s", tc.desc, tc.errLogMessage, out)) } sdkCall.Unset() sdkCall1.Unset() sdkCall2.Unset() }) } } func TestWhitelistConfigCmd(t *testing.T) { sdkMock := new(sdkmocks.SDK) cli.SetSDK(sdkMock) bootCmd := cli.NewBootstrapCmd() rootCmd := setFlags(bootCmd) jsonConfig := fmt.Sprintf("{\"client_id\": \"%s\", \"status\":%d}", clientID, 1) cases := []struct { desc string args []string logType outputLog errLogMessage string sdkErr errors.SDKError }{ { desc: "whitelist config successfully", args: []string{ jsonConfig, domainID, validToken, }, logType: okLog, }, { desc: "whitelist config with invalid args", args: []string{ jsonConfig, domainID, validToken, extraArg, }, logType: usageLog, }, { desc: "whitelist config with invalid json", args: []string{ fmt.Sprintf("{\"client_id\": \"%s\", \"status\":%d", clientID, 1), domainID, validToken, }, sdkErr: errors.NewSDKError(errors.New("unexpected end of JSON input")), errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.New("unexpected end of JSON input")), logType: errLog, }, { desc: "whitelist config with invalid token", args: []string{ jsonConfig, domainID, invalidToken, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized), errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized)), logType: errLog, }, } for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { sdkCall := sdkMock.On("Whitelist", mock.Anything, mock.Anything, mock.Anything, tc.args[1], tc.args[2]).Return(tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{whitelistCmd}, tc.args...)...) switch tc.logType { case okLog: assert.True(t, strings.Contains(out, "ok"), fmt.Sprintf("%s unexpected response: expected success message, got: %v", tc.desc, out)) case usageLog: assert.False(t, strings.Contains(out, rootCmd.Use), fmt.Sprintf("%s invalid usage: %s", tc.desc, out)) case errLog: assert.Equal(t, tc.errLogMessage, out, fmt.Sprintf("%s unexpected error response: expected %s got errLogMessage:%s", tc.desc, tc.errLogMessage, out)) } sdkCall.Unset() }) } } func TestBootstrapConfigCmd(t *testing.T) { sdkMock := new(sdkmocks.SDK) cli.SetSDK(sdkMock) bootCmd := cli.NewBootstrapCmd() rootCmd := setFlags(bootCmd) var boot mgsdk.BootstrapConfig cryptoKey := "v7aT0HGxJxt2gULzr3RHwf4WIf6DusPp" invalidKey := "invalid key" cases := []struct { desc string args []string logType outputLog errLogMessage string sdkErr errors.SDKError boot mgsdk.BootstrapConfig }{ { desc: "bootstrap secure config successfully", args: []string{ "secure", bootConfig.ExternalID, bootConfig.ExternalKey, cryptoKey, }, boot: bootConfig, logType: entityLog, }, { desc: "bootstrap config successfully", args: []string{ bootConfig.ExternalID, bootConfig.ExternalKey, }, boot: bootConfig, logType: entityLog, }, { desc: "bootstrap secure config with invalid args", args: []string{ cryptoKey, }, logType: usageLog, }, { desc: "bootstrap secure config with invalid key", args: []string{ "secure", bootConfig.ExternalID, invalidKey, cryptoKey, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized), errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized)), logType: errLog, }, { desc: "bootstrap config with invalid key", args: []string{ bootConfig.ExternalID, invalidKey, }, sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized), errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized)), logType: errLog, }, } for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { sdkCall := sdkMock.On("BootstrapSecure", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.boot, tc.sdkErr) sdkCall1 := sdkMock.On("Bootstrap", mock.Anything, mock.Anything, mock.Anything).Return(tc.boot, tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{bootStrapCmd}, tc.args...)...) switch tc.logType { case entityLog: err := json.Unmarshal([]byte(out), &boot) assert.Nil(t, err) assert.Equal(t, tc.boot, boot, fmt.Sprintf("%s unexpected response: expected: %v, got: %v", tc.desc, tc.boot, boot)) case usageLog: assert.False(t, strings.Contains(out, rootCmd.Use), fmt.Sprintf("%s invalid usage: %s", tc.desc, out)) case errLog: assert.Equal(t, tc.errLogMessage, out, fmt.Sprintf("%s unexpected error response: expected %s got errLogMessage:%s", tc.desc, tc.errLogMessage, out)) } sdkCall.Unset() sdkCall1.Unset() }) } } func TestBootstrapProfilesCmd(t *testing.T) { sdkMock := new(sdkmocks.SDK) cli.SetSDK(sdkMock) bootCmd := cli.NewBootstrapCmd() rootCmd := setFlags(bootCmd) profilePayload, err := json.Marshal(bootProfile) assert.Nil(t, err) jsonProfile := string(profilePayload) cases := []struct { desc string args []string profile mgsdk.BootstrapProfile page mgsdk.BootstrapProfilesPage sdkErr errors.SDKError logType outputLog errLogMessage string }{ { desc: "create bootstrap profile successfully", args: []string{ "create", jsonProfile, domainID, validToken, }, profile: bootProfile, logType: entityLog, }, { desc: "get all bootstrap profiles successfully", args: []string{ "get", all, domainID, validToken, }, page: mgsdk.BootstrapProfilesPage{ PageRes: mgsdk.PageRes{ Total: 1, Offset: 0, Limit: 10, }, Profiles: []mgsdk.BootstrapProfile{bootProfile}, }, logType: entityLog, }, { desc: "view bootstrap profile successfully", args: []string{ "get", profileID, domainID, validToken, }, profile: bootProfile, logType: entityLog, }, { desc: "update bootstrap profile successfully", args: []string{ "update", jsonProfile, domainID, validToken, }, profile: bootProfile, logType: entityLog, }, { desc: "remove bootstrap profile successfully", args: []string{ "remove", profileID, domainID, validToken, }, logType: okLog, }, } for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { var gotProfile mgsdk.BootstrapProfile var gotPage mgsdk.BootstrapProfilesPage createCall := sdkMock.On("CreateBootstrapProfile", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.profile, tc.sdkErr) listCall := sdkMock.On("BootstrapProfiles", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.page, tc.sdkErr) viewCall := sdkMock.On("ViewBootstrapProfile", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.profile, tc.sdkErr) updateCall := sdkMock.On("UpdateBootstrapProfile", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.profile, tc.sdkErr) removeCall := sdkMock.On("RemoveBootstrapProfile", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{"profiles"}, tc.args...)...) switch tc.logType { case entityLog: if tc.args[0] == "get" && tc.args[1] == all { err := json.Unmarshal([]byte(out), &gotPage) assert.Nil(t, err) assert.Equal(t, tc.page, gotPage, fmt.Sprintf("%s unexpected response: expected: %v, got: %v", tc.desc, tc.page, gotPage)) } else { err := json.Unmarshal([]byte(out), &gotProfile) assert.Nil(t, err) assert.Equal(t, tc.profile, gotProfile, fmt.Sprintf("%s unexpected response: expected: %v, got: %v", tc.desc, tc.profile, gotProfile)) } case okLog: assert.True(t, strings.Contains(out, "ok"), fmt.Sprintf("%s unexpected response: expected success message, got: %v", tc.desc, out)) case errLog: assert.Equal(t, tc.errLogMessage, out, fmt.Sprintf("%s unexpected error response: expected %s got errLogMessage:%s", tc.desc, tc.errLogMessage, out)) case usageLog: assert.False(t, strings.Contains(out, rootCmd.Use), fmt.Sprintf("%s invalid usage: %s", tc.desc, out)) } createCall.Unset() listCall.Unset() viewCall.Unset() updateCall.Unset() removeCall.Unset() }) } } func TestBootstrapEnrollmentsCmd(t *testing.T) { sdkMock := new(sdkmocks.SDK) cli.SetSDK(sdkMock) bootCmd := cli.NewBootstrapCmd() rootCmd := setFlags(bootCmd) bindings := []mgsdk.BootstrapBindingRequest{ { Slot: "mqtt_client", Type: "client", ResourceID: clientID, }, } snapshots := []mgsdk.BootstrapBindingSnapshot{ { ConfigID: clientID, Slot: "mqtt_client", Type: "client", ResourceID: clientID, }, } jsonBindings := fmt.Sprintf("[{\"slot\":\"%s\",\"type\":\"%s\",\"resource_id\":\"%s\"}]", bindings[0].Slot, bindings[0].Type, bindings[0].ResourceID) cases := []struct { desc string args []string snapshots []mgsdk.BootstrapBindingSnapshot sdkErr errors.SDKError logType outputLog errLogMessage string }{ { desc: "assign bootstrap profile successfully", args: []string{ "assign-profile", clientID, profileID, domainID, validToken, }, logType: okLog, }, { desc: "bind bootstrap resources successfully", args: []string{ "bind", clientID, jsonBindings, domainID, validToken, }, logType: okLog, }, { desc: "get bootstrap bindings successfully", args: []string{ "get-bindings", clientID, domainID, validToken, }, snapshots: snapshots, logType: entityLog, }, { desc: "refresh bootstrap bindings successfully", args: []string{ "refresh-bindings", clientID, domainID, validToken, }, logType: okLog, }, } for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { var gotSnapshots []mgsdk.BootstrapBindingSnapshot assignCall := sdkMock.On("AssignBootstrapProfile", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.sdkErr) bindCall := sdkMock.On("BindBootstrapResources", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.sdkErr) listCall := sdkMock.On("BootstrapBindings", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.snapshots, tc.sdkErr) refreshCall := sdkMock.On("RefreshBootstrapBindings", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.sdkErr) out := executeCommand(t, rootCmd, append([]string{"enrollments"}, tc.args...)...) switch tc.logType { case entityLog: err := json.Unmarshal([]byte(out), &gotSnapshots) assert.Nil(t, err) assert.Equal(t, tc.snapshots, gotSnapshots, fmt.Sprintf("%s unexpected response: expected: %v, got: %v", tc.desc, tc.snapshots, gotSnapshots)) case okLog: assert.True(t, strings.Contains(out, "ok"), fmt.Sprintf("%s unexpected response: expected success message, got: %v", tc.desc, out)) case errLog: assert.Equal(t, tc.errLogMessage, out, fmt.Sprintf("%s unexpected error response: expected %s got errLogMessage:%s", tc.desc, tc.errLogMessage, out)) case usageLog: assert.False(t, strings.Contains(out, rootCmd.Use), fmt.Sprintf("%s invalid usage: %s", tc.desc, out)) } assignCall.Unset() bindCall.Unset() listCall.Unset() refreshCall.Unset() }) } }