diff --git a/internal/api/impl.go b/internal/api/impl.go index 81675a6..f73bbe9 100644 --- a/internal/api/impl.go +++ b/internal/api/impl.go @@ -14,8 +14,19 @@ type ServerImpl struct { Dal dal.DAL } -func (*ServerImpl) GetBanks(ctx echo.Context) error { - return echo.NewHTTPError(http.StatusNotImplemented) +func (pf *ServerImpl) GetBanks(ctx echo.Context) error { + log.Printf("GetBanks") + + banks, err := pf.Dal.Banks() + if err != nil { + return ctx.NoContent(http.StatusInternalServerError) + } + + if len(banks) == 0 { + return ctx.NoContent(http.StatusNoContent) + } + + return ctx.JSON(http.StatusOK, convertBanks(banks)) } func (*ServerImpl) GetBankById(ctx echo.Context, bankId int64) error { diff --git a/internal/api/impl_test.go b/internal/api/impl_test.go index c268d23..467290d 100644 --- a/internal/api/impl_test.go +++ b/internal/api/impl_test.go @@ -10,6 +10,7 @@ import ( "git.rosemyrtle.work/personal-finance/server/internal/dal" "git.rosemyrtle.work/personal-finance/server/internal/entity" "git.rosemyrtle.work/personal-finance/server/internal/mock" + "github.com/google/uuid" "github.com/labstack/echo/v4" "github.com/shopspring/decimal" "github.com/stretchr/testify/assert" @@ -17,26 +18,48 @@ import ( ) func TestServerImpl_GetBanks(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + mock_dal := mock.NewMockDAL(ctrl) + type fields struct { Dal dal.DAL } - type args struct { - ctx echo.Context - } tests := []struct { name string fields fields - args args wantErr bool + mocks entity.Banks }{ - // TODO: Add test cases. + { + "200", + fields{mock_dal}, + false, + entity.Banks{ + {Id: "Bank A", Name: "Bank A", NordigenId: uuid.New()}, + {Id: "Bank B", Name: "Bank B", NordigenId: uuid.New()}, + }, + }, + { + "204", + fields{mock_dal}, + false, + entity.Banks{}, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { s := &ServerImpl{ Dal: tt.fields.Dal, } - if err := s.GetBanks(tt.args.ctx); (err != nil) != tt.wantErr { + + req := httptest.NewRequest(http.MethodGet, "/banks", nil) + rec := httptest.NewRecorder() + ctx := echo.New().NewContext(req, rec) + + mock_dal.EXPECT().Banks().Return(tt.mocks, nil).Times(1) + + if err := s.GetBanks(ctx); (err != nil) != tt.wantErr { t.Errorf("ServerImpl.GetBanks() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/internal/dal/impl.go b/internal/dal/impl.go index 67e09fa..5207d04 100644 --- a/internal/dal/impl.go +++ b/internal/dal/impl.go @@ -49,6 +49,17 @@ func (*DalImpl) Bank() (entity.Bank, error) { return entity.Bank{}, errors.New("not implemented") } -func (*DalImpl) Banks() (entity.Banks, error) { - return entity.Banks{}, errors.New("not implemented") +func (dal *DalImpl) Banks() (entity.Banks, error) { + log.Printf("DAL::Banks") + + if dal.Db == nil { + log.Panic("database not available") + } + + rows, err := dal.Db.Query("SELECT b.name, b.name, n.requisition_id FROM pfbudget.banks b JOIN pfbudget.banks_nordigen n ON b.name = n.name") + if err != nil { + return entity.Banks{}, err + } + + return convert[entity.Bank](rows), nil } diff --git a/internal/dal/impl_test.go b/internal/dal/impl_test.go index 717fac0..2b012e8 100644 --- a/internal/dal/impl_test.go +++ b/internal/dal/impl_test.go @@ -9,6 +9,7 @@ import ( "git.rosemyrtle.work/personal-finance/server/internal/entity" "github.com/DATA-DOG/go-sqlmock" + "github.com/google/uuid" "github.com/shopspring/decimal" ) @@ -167,22 +168,56 @@ func TestDalImpl_Bank(t *testing.T) { } func TestDalImpl_Banks(t *testing.T) { + db, mock, err := sqlmock.New() + if err != nil { + t.Fatal(err) + } + + uuid := uuid.New() + type fields struct { Db *sql.DB } + type args struct { + rows [][]driver.Value + } tests := []struct { name string fields fields + args args want entity.Banks wantErr bool }{ - // TODO: Add test cases. + { + "200", + fields{db}, + args{[][]driver.Value{ + {"Bank A", "Bank A", uuid.String()}, + {"Bank B", "Bank B", uuid.String()}, + }}, + entity.Banks{ + {Id: "Bank A", Name: "Bank A", NordigenId: uuid}, + {Id: "Bank B", Name: "Bank B", NordigenId: uuid}, + }, + false, + }, + {"404", fields{db}, args{}, nil, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { d := &DalImpl{ Db: tt.fields.Db, } + + mock. + ExpectQuery("^SELECT .* FROM .*banks b JOIN .*banks_nordigen n ON b.name = n.name$"). + WithoutArgs(). + WillReturnRows( + mock. + NewRows([]string{"name", "name", "requisition_id"}). + AddRows(tt.args.rows...), + ) + got, err := d.Banks() if (err != nil) != tt.wantErr { t.Errorf("DalImpl.Banks() error = %v, wantErr %v", err, tt.wantErr)