From ec17b601fe15a8e085f8cd1b306e64539c10c48e Mon Sep 17 00:00:00 2001 From: PatrickMenoti <82882574+PatrickMenoti@users.noreply.github.com> Date: Tue, 2 Jul 2024 16:04:30 -0300 Subject: [PATCH] tests: add unit tests for unlink command --- pkg/cmd/delete/edge_application/cascade.go | 4 +- .../edge_application/edge_application.go | 4 +- pkg/cmd/sync/sync.go | 4 +- pkg/cmd/sync/sync_test.go | 97 ++++++++++++++ pkg/cmd/sync/tasks.go | 2 +- pkg/cmd/unlink/unlink.go | 3 + pkg/cmd/unlink/unlink_test.go | 118 ++++++++++++++++++ pkg/cmd/unlink/utils.go | 5 +- 8 files changed, 229 insertions(+), 8 deletions(-) create mode 100644 pkg/cmd/sync/sync_test.go create mode 100644 pkg/cmd/unlink/unlink_test.go diff --git a/pkg/cmd/delete/edge_application/cascade.go b/pkg/cmd/delete/edge_application/cascade.go index da6fb38eb..3d37bc284 100644 --- a/pkg/cmd/delete/edge_application/cascade.go +++ b/pkg/cmd/delete/edge_application/cascade.go @@ -12,13 +12,13 @@ import ( "github.com/aziontech/azion-cli/pkg/output" ) -func (del *DeleteCmd) Cascade(ctx context.Context) error { +func CascadeDelete(ctx context.Context, del *DeleteCmd) error { azionJson, err := del.GetAzion(ProjectConf) if err != nil { if errors.Is(err, os.ErrNotExist) { return msg.ErrorMissingAzionJson } else { - return err //message with error + return err } } if azionJson.Application.ID == 0 { diff --git a/pkg/cmd/delete/edge_application/edge_application.go b/pkg/cmd/delete/edge_application/edge_application.go index cb8eb95bf..d4b240d87 100644 --- a/pkg/cmd/delete/edge_application/edge_application.go +++ b/pkg/cmd/delete/edge_application/edge_application.go @@ -28,6 +28,7 @@ type DeleteCmd struct { GetAzion func(confPath string) (*contracts.AzionApplicationOptions, error) f *cmdutil.Factory UpdateJson func(cmd *DeleteCmd) error + Cascade func(ctx context.Context, del *DeleteCmd) error } func NewCmd(f *cmdutil.Factory) *cobra.Command { @@ -40,6 +41,7 @@ func NewDeleteCmd(f *cmdutil.Factory) *DeleteCmd { GetAzion: utils.GetAzionJsonContent, f: f, UpdateJson: updateAzionJson, + Cascade: CascadeDelete, } } @@ -72,7 +74,7 @@ func (del *DeleteCmd) run(cmd *cobra.Command, application_id int64) error { ctx := context.Background() if cmd.Flags().Changed("cascade") { - err := del.Cascade(ctx) + err := del.Cascade(ctx, del) if err != nil { return err } diff --git a/pkg/cmd/sync/sync.go b/pkg/cmd/sync/sync.go index bc0cbf4ab..27288c27c 100644 --- a/pkg/cmd/sync/sync.go +++ b/pkg/cmd/sync/sync.go @@ -19,6 +19,7 @@ type SyncCmd struct { GetAzionJsonContent func(confPath string) (*contracts.AzionApplicationOptions, error) WriteAzionJsonContent func(conf *contracts.AzionApplicationOptions, confPath string) error F *cmdutil.Factory + SyncResources func(f *cmdutil.Factory, info contracts.SyncOpts, synch *SyncCmd) error } func NewSync(f *cmdutil.Factory) *SyncCmd { @@ -27,6 +28,7 @@ func NewSync(f *cmdutil.Factory) *SyncCmd { Io: f.IOStreams, GetAzionJsonContent: utils.GetAzionJsonContent, WriteAzionJsonContent: utils.WriteAzionJsonContent, + SyncResources: SyncLocalResources, } } @@ -92,7 +94,7 @@ func Sync(cmdFac *SyncCmd) error { Conf: conf, } - err = cmdFac.SyncResources(cmdFac.F, info) + err = cmdFac.SyncResources(cmdFac.F, info, cmdFac) if err != nil { return err } diff --git a/pkg/cmd/sync/sync_test.go b/pkg/cmd/sync/sync_test.go new file mode 100644 index 000000000..8975220f0 --- /dev/null +++ b/pkg/cmd/sync/sync_test.go @@ -0,0 +1,97 @@ +package sync + +import ( + "errors" + "fmt" + "testing" + + msg "github.com/aziontech/azion-cli/messages/sync" + "github.com/aziontech/azion-cli/pkg/cmdutil" + "github.com/aziontech/azion-cli/pkg/contracts" + "github.com/aziontech/azion-cli/pkg/httpmock" + "github.com/aziontech/azion-cli/pkg/logger" + "github.com/aziontech/azion-cli/pkg/testutils" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" +) + +func TestSync(t *testing.T) { + logger.New(zapcore.DebugLevel) + tests := []struct { + name string + mockGetContentFunc func(confPath string) (*contracts.AzionApplicationOptions, error) + mockWriteFunc func(conf *contracts.AzionApplicationOptions, confPath string) error + mockSyncResources func(f *cmdutil.Factory, info contracts.SyncOpts, synch *SyncCmd) error + expectedError error + }{ + { + name: "sync - successful synchronization", + mockGetContentFunc: func(confPath string) (*contracts.AzionApplicationOptions, error) { + return &contracts.AzionApplicationOptions{ + // Mock relevant fields + }, nil + }, + mockWriteFunc: func(conf *contracts.AzionApplicationOptions, confPath string) error { + return nil + }, + mockSyncResources: func(f *cmdutil.Factory, info contracts.SyncOpts, synch *SyncCmd) error { + // Mock synchronization logic + return nil + }, + expectedError: nil, + }, + { + name: "sync - failed to get content", + mockGetContentFunc: func(confPath string) (*contracts.AzionApplicationOptions, error) { + return nil, errors.New("Failed to synchronize local resources with remote resources: failed to get azion.json content") + }, + mockWriteFunc: func(conf *contracts.AzionApplicationOptions, confPath string) error { + return nil + }, + mockSyncResources: func(f *cmdutil.Factory, info contracts.SyncOpts, synch *SyncCmd) error { + return nil + }, + expectedError: fmt.Errorf(msg.ERRORSYNC, "failed to get azion.json content"), + }, + { + name: "sync - failed to write content", + mockGetContentFunc: func(confPath string) (*contracts.AzionApplicationOptions, error) { + return &contracts.AzionApplicationOptions{ + // Mock relevant fields + }, nil + }, + mockWriteFunc: func(conf *contracts.AzionApplicationOptions, confPath string) error { + return errors.New("failed to write azion.json content") + }, + mockSyncResources: func(f *cmdutil.Factory, info contracts.SyncOpts, synch *SyncCmd) error { + return errors.New("failed to write azion.json content") + }, + expectedError: errors.New("failed to write azion.json content"), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mock := &httpmock.Registry{} + f, _, _ := testutils.NewFactory(mock) + + syncCmd := NewSync(f) + + // Mock GetAzionJsonContent and WriteAzionJsonContent functions + syncCmd.GetAzionJsonContent = tt.mockGetContentFunc + syncCmd.WriteAzionJsonContent = tt.mockWriteFunc + + // Replace syncResources function with mock + syncCmd.SyncResources = tt.mockSyncResources + + err := Sync(syncCmd) + if tt.expectedError != nil { + require.Error(t, err) + assert.Equal(t, tt.expectedError.Error(), err.Error()) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/pkg/cmd/sync/tasks.go b/pkg/cmd/sync/tasks.go index 1082bbb5a..27a83bc94 100644 --- a/pkg/cmd/sync/tasks.go +++ b/pkg/cmd/sync/tasks.go @@ -18,7 +18,7 @@ var ( ctx context.Context = context.Background() ) -func (synch *SyncCmd) SyncResources(f *cmdutil.Factory, info contracts.SyncOpts) error { +func SyncLocalResources(f *cmdutil.Factory, info contracts.SyncOpts, synch *SyncCmd) error { opts = &contracts.ListOptions{ PageSize: 1000, Page: 1, diff --git a/pkg/cmd/unlink/unlink.go b/pkg/cmd/unlink/unlink.go index 6d375a179..580dcac6d 100644 --- a/pkg/cmd/unlink/unlink.go +++ b/pkg/cmd/unlink/unlink.go @@ -5,6 +5,7 @@ import ( "github.com/MakeNowJust/heredoc" msg "github.com/aziontech/azion-cli/messages/unlink" + app "github.com/aziontech/azion-cli/pkg/cmd/delete/edge_application" "github.com/aziontech/azion-cli/pkg/cmdutil" "github.com/aziontech/azion-cli/utils" "github.com/spf13/cobra" @@ -16,6 +17,7 @@ type UnlinkCmd struct { IsDirEmpty func(dirpath string) (bool, error) CleanDir func(dirpath string) error F *cmdutil.Factory + DeleteCmd func(f *cmdutil.Factory) *app.DeleteCmd } func NewUnlinkCmd(f *cmdutil.Factory) *UnlinkCmd { @@ -25,6 +27,7 @@ func NewUnlinkCmd(f *cmdutil.Factory) *UnlinkCmd { Clean: clean, IsDirEmpty: utils.IsDirEmpty, CleanDir: utils.CleanDirectory, + DeleteCmd: app.NewDeleteCmd, } } diff --git a/pkg/cmd/unlink/unlink_test.go b/pkg/cmd/unlink/unlink_test.go new file mode 100644 index 000000000..eec32a3d2 --- /dev/null +++ b/pkg/cmd/unlink/unlink_test.go @@ -0,0 +1,118 @@ +package unlink + +import ( + "context" + "errors" + "testing" + + app "github.com/aziontech/azion-cli/pkg/cmd/delete/edge_application" + "github.com/aziontech/azion-cli/pkg/cmdutil" + "github.com/aziontech/azion-cli/pkg/httpmock" + "github.com/aziontech/azion-cli/pkg/logger" + "github.com/aziontech/azion-cli/pkg/testutils" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" +) + +func mockDelSuccess() *app.DeleteCmd { + return &app.DeleteCmd{ + Cascade: func(ctx context.Context, del *app.DeleteCmd) error { + return nil + }, + } +} + +func mockDelFail() *app.DeleteCmd { + return &app.DeleteCmd{ + Cascade: func(ctx context.Context, del *app.DeleteCmd) error { + return errors.New("Failed to cascade delete") + }, + } +} + +func TestUnlink(t *testing.T) { + logger.New(zapcore.DebugLevel) + tests := []struct { + name string + isDirEmpty bool + cleanDirError error + expectedOutput string + expectedError string + mockDeleteCmd *app.DeleteCmd + }{ + { + name: "unlink - directory is empty", + isDirEmpty: true, + cleanDirError: nil, + expectedOutput: "Unliked successfully", + expectedError: "", + mockDeleteCmd: mockDelSuccess(), + }, + { + name: "unlink - clean directory successfully", + isDirEmpty: false, + cleanDirError: nil, + expectedOutput: "Unliked successfully", + expectedError: "", + mockDeleteCmd: mockDelSuccess(), + }, + { + name: "unlink - failed to clean directory", + isDirEmpty: false, + cleanDirError: errors.New("failed to clean directory"), + expectedOutput: "", + expectedError: "failed to clean directory", + mockDeleteCmd: mockDelSuccess(), + }, + { + name: "unlink - cascade delete fails", + isDirEmpty: false, + cleanDirError: nil, + expectedOutput: "", + expectedError: "Failed to cascade delete", + mockDeleteCmd: mockDelFail(), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mockIsDirEmpty := func(dirpath string) (bool, error) { + return tt.isDirEmpty, nil + } + + mockCleanDir := func(dirpath string) error { + return tt.cleanDirError + } + + mockDeleteCmd := tt.mockDeleteCmd + + mock := &httpmock.Registry{} + + f, out, _ := testutils.NewFactory(mock) + f.GlobalFlagAll = true // Simulate --yes flag + + unlinkCmd := &UnlinkCmd{ + F: f, + IsDirEmpty: mockIsDirEmpty, + CleanDir: mockCleanDir, + ShouldClean: shouldClean, + Clean: clean, + DeleteCmd: func(f *cmdutil.Factory) *app.DeleteCmd { + return mockDeleteCmd + }, + } + cmd := NewCobraCmd(unlinkCmd, f) + + _, err := cmd.ExecuteC() + if tt.expectedError != "" { + require.Error(t, err) + assert.Equal(t, tt.expectedError, err.Error()) + } else { + require.NoError(t, err) + assert.Equal(t, tt.expectedOutput, out.String()) + } + + }) + } +} diff --git a/pkg/cmd/unlink/utils.go b/pkg/cmd/unlink/utils.go index ca2adbda6..8d9296463 100644 --- a/pkg/cmd/unlink/utils.go +++ b/pkg/cmd/unlink/utils.go @@ -3,7 +3,6 @@ package unlink import ( "context" - app "github.com/aziontech/azion-cli/pkg/cmd/delete/edge_application" "github.com/aziontech/azion-cli/pkg/cmdutil" "github.com/aziontech/azion-cli/pkg/logger" helpers "github.com/aziontech/azion-cli/utils" @@ -27,9 +26,9 @@ func clean(f *cmdutil.Factory, cmd *UnlinkCmd) error { } if shouldCascade { - cmd := app.NewDeleteCmd(f) + delCmd := cmd.DeleteCmd(f) ctx := context.Background() - err := cmd.Cascade(ctx) + err := delCmd.Cascade(ctx, delCmd) if err != nil { return err }