Skip to content
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
12 changes: 10 additions & 2 deletions cloud/handler/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import (
"gofr.dev/pkg/gofr"
)

const successMessage = "Successfully Imported!"
const (
successMessage = "Successfully Imported!"
maxNameLength = 20
)

type Handler struct {
accountService AccountImporter
Expand All @@ -33,6 +36,7 @@ func (h *Handler) Import(ctx *gofr.Context) (any, error) {
return successMessage, nil
}

// List is a handler for listing all cloud accounts.
func (h *Handler) List(ctx *gofr.Context) (any, error) {
accounts, err := h.accountGetter.GetAccounts(ctx)
if err != nil {
Expand All @@ -48,8 +52,12 @@ func (h *Handler) List(ctx *gofr.Context) (any, error) {
rows := ""

for _, account := range accounts {
if len(account.Name) > maxNameLength {
account.Name = account.Name[:17] + "..."
}

rows += fmt.Sprintf("%-20s %-20s %-20s %-20s %-20s\n",
account.Name[:17]+"...", account.Provider, account.ProviderID, account.UpdatedAt, account.CreatedAt)
account.Name, account.Provider, account.ProviderID, account.UpdatedAt, account.CreatedAt)
}

return header + rows, nil
Expand Down
91 changes: 90 additions & 1 deletion cloud/handler/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@ import (
"errors"
"testing"

"github.com/stretchr/testify/assert"
"go.uber.org/mock/gomock"
"gofr.dev/pkg/gofr"
"gofr.dev/pkg/gofr/container"
"gofr.dev/pkg/gofr/logging"

"zop.dev/cli/zop/cloud/service/list"
)

var (
errTest = errors.New("import error")
errTest = errors.New("import error")
errFailedToFetchAccounts = errors.New("failed to fetch accounts")
)

func TestImport_Success(t *testing.T) {
Expand Down Expand Up @@ -58,3 +62,88 @@ func TestImport_Failure(t *testing.T) {
t.Errorf("expected 'import error', got %v", err.Error())
}
}

func TestHandler_List(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

mockAccGetter := NewMockAccountGetter(ctrl)

tests := []struct {
name string
accounts []*list.CloudAccountResponse
expectedResp string
expectedErr error
mocks []*gomock.Call
}{
{
name: "No accounts",
accounts: []*list.CloudAccountResponse{},
expectedResp: "No accounts found",
expectedErr: nil,
mocks: []*gomock.Call{
mockAccGetter.EXPECT().GetAccounts(gomock.Any()).Return([]*list.CloudAccountResponse{}, nil),
},
},
{
name: "Single account",
accounts: []*list.CloudAccountResponse{
{Name: "Account1", Provider: "AWS", ProviderID: "12345", UpdatedAt: "2024-01-01", CreatedAt: "2023-01-01"},
},
expectedResp: "Name Provider ProviderID UpdateAt CreatedAt \n" +
"Account1 AWS 12345 2024-01-01 2023-01-01 \n",
expectedErr: nil,
mocks: []*gomock.Call{
mockAccGetter.EXPECT().GetAccounts(gomock.Any()).Return([]*list.CloudAccountResponse{
{Name: "Account1", Provider: "AWS", ProviderID: "12345", UpdatedAt: "2024-01-01", CreatedAt: "2023-01-01"},
}, nil),
},
},
{
name: "Multiple accounts with truncation",
accounts: []*list.CloudAccountResponse{
{Name: "ThisIsAVeryLongAccountNameThatShouldBeTruncated",
Provider: "GCP", ProviderID: "67890", UpdatedAt: "2024-02-02", CreatedAt: "2023-02-02"},
{Name: "Account2", Provider: "Azure",
ProviderID: "11111", UpdatedAt: "2024-03-03", CreatedAt: "2023-03-03"},
},
expectedResp: "Name Provider ProviderID UpdateAt CreatedAt \n" +
"ThisIsAVeryLongAc... GCP 67890 2024-02-02 2023-02-02 \n" +
"Account2 Azure 11111 2024-03-03 2023-03-03 \n",
expectedErr: nil,
mocks: []*gomock.Call{
mockAccGetter.EXPECT().GetAccounts(gomock.Any()).Return([]*list.CloudAccountResponse{
{Name: "ThisIsAVeryLongAccountNameThatShouldBeTruncated",
Provider: "GCP", ProviderID: "67890", UpdatedAt: "2024-02-02", CreatedAt: "2023-02-02"},
{Name: "Account2", Provider: "Azure", ProviderID: "11111", UpdatedAt: "2024-03-03", CreatedAt: "2023-03-03"},
}, nil),
},
},
{
name: "Error from GetAccounts",
accounts: nil,
expectedResp: "",
expectedErr: errFailedToFetchAccounts,
mocks: []*gomock.Call{
mockAccGetter.EXPECT().GetAccounts(gomock.Any()).Return(nil, errFailedToFetchAccounts),
},
},
}

handler := New(nil, mockAccGetter)

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := &gofr.Context{}

resp, err := handler.List(ctx)

if tt.expectedErr != nil {
assert.EqualError(t, err, tt.expectedErr.Error())
} else {
assert.NoError(t, err)
assert.Equal(t, tt.expectedResp, resp)
}
})
}
}
6 changes: 4 additions & 2 deletions cloud/handler/mock_interface.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

90 changes: 90 additions & 0 deletions cloud/service/list/service_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package list

import (
"bytes"
"errors"
"io"
"net/http"
"testing"

"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
"gofr.dev/pkg/gofr"
"gofr.dev/pkg/gofr/cmd/terminal"
"gofr.dev/pkg/gofr/container"
"gofr.dev/pkg/gofr/service"
)

var (
errFailFetch = errors.New("failed to fetch")
errUnmarshall = errors.New("invalid character 'i' looking for beginning of value")
)

func Test_Service_GetAccounts(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

mockCont, mocks := container.NewMockContainer(t, func(_ *container.Container, ctrl *gomock.Controller) any {
return service.NewMockHTTP(ctrl)
})
mockCont.Services["api-service"] = mocks.HTTPService
ctx := &gofr.Context{Container: mockCont, Out: terminal.New()}

testCases := []struct {
name string
mockCalls []*gomock.Call
expResult []*CloudAccountResponse
expError error
}{
{
name: "successful GET call",
mockCalls: []*gomock.Call{
mocks.HTTPService.EXPECT().Get(ctx, "/cloud-accounts", nil).
Return(&http.Response{
Body: io.NopCloser(bytes.NewBufferString(
`{"data": [{"Name": "Account1", "Provider": "AWS", "ProviderID": "12345", "UpdatedAt": "2024-01-01", "CreatedAt": "2023-01-01"}]}`)),
}, nil),
},
expResult: []*CloudAccountResponse{
{Name: "Account1", Provider: "AWS", ProviderID: "12345", UpdatedAt: "2024-01-01", CreatedAt: "2023-01-01"},
},
expError: nil,
},
{
name: "error during GET call",
mockCalls: []*gomock.Call{
mocks.HTTPService.EXPECT().Get(ctx, "/cloud-accounts", nil).
Return(nil, errFailFetch),
},
expResult: nil,
expError: errFailFetch,
},
{
name: "invalid JSON response",
mockCalls: []*gomock.Call{
mocks.HTTPService.EXPECT().Get(ctx, "/cloud-accounts", nil).
Return(&http.Response{
Body: io.NopCloser(bytes.NewBufferString("invalid-json")),
}, nil),
},
expResult: nil,
expError: errUnmarshall,
},
}

svc := New()

for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
result, err := svc.GetAccounts(ctx)

if tt.expError != nil {
require.EqualError(t, err, tt.expError.Error())
require.Nil(t, result)
} else {
require.NoError(t, err)
require.Equal(t, tt.expResult, result)
}
})
}
}
Loading