Skip to content

Commit

Permalink
Feature/get all (#53)
Browse files Browse the repository at this point in the history
* add getAllEndpoint

* add decodeGetAllItems func

* add encodeAllItemsResponse func

* Update function name for consistency

* add getAllItemsHandlder

* Fix syntax errors

* Update changelog
  • Loading branch information
joe94 authored Sep 23, 2020
1 parent 9060cd6 commit fc293ea
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 1 deletion.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Changed
- Abstract away dynamodb dependency. [#35](https://github.com/xmidt-org/argus/pull/35)
- Add unit tests for new dynamodb abstraction changes. [#39](https://github.com/xmidt-org/argus/pull/39)
- Add encoders/decoders for GetItem Handler. [#44](https://github.com/xmidt-org/argus/pull/44)
- Add helper functions for GetItem Handler. [#44](https://github.com/xmidt-org/argus/pull/44)
- Add helper functions for DeleteItem Handler. [#52](https://github.com/xmidt-org/argus/pull/52)
- Add helper functions for GetAllItems Handler. [#53](https://github.com/xmidt-org/argus/pull/53)


## [v0.3.5]
Expand Down
12 changes: 12 additions & 0 deletions store/endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,18 @@ func NewGetEndpoint(s S) endpoint.Endpoint {
}
}

func newGetAllItemsEndpoint(s S) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
itemsRequest := request.(*getAllItemsRequest)
items, err := s.GetAll(itemsRequest.bucket)
if err != nil {
return nil, err
}

return FilterOwner(items, itemsRequest.owner), nil
}
}

func NewGetAllEndpoint(s S) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
var (
Expand Down
61 changes: 61 additions & 0 deletions store/endpoint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,64 @@ func TestDeleteItemEndpoint(t *testing.T) {
})
}
}

func TestGetAllItemsEndpoint(t *testing.T) {
t.Run("DAOFails", testGetAllItemsEndpointDAOFails)
t.Run("FilteredItems", testGetAllItemsEndpointFiltered)
}

func testGetAllItemsEndpointDAOFails(t *testing.T) {
assert := assert.New(t)
m := new(MockDAO)
itemsRequest := &getAllItemsRequest{
bucket: "sports-cars",
owner: "alfa-romeo",
}
mockedErr := errors.New("sports cars api is down")
m.On("GetAll", "sports-cars").Return(map[string]OwnableItem{}, mockedErr)

endpoint := newGetAllItemsEndpoint(m)
resp, err := endpoint(context.Background(), itemsRequest)

assert.Nil(resp)
assert.Equal(mockedErr, err)
}

func testGetAllItemsEndpointFiltered(t *testing.T) {
assert := assert.New(t)
m := new(MockDAO)
itemsRequest := &getAllItemsRequest{
bucket: "sports-cars",
owner: "alfa-romeo",
}
mockedItems := map[string]OwnableItem{
"mustang": OwnableItem{
Owner: "ford",
},
"4c-spider": OwnableItem{
Owner: "alfa-romeo",
},
"gtr": OwnableItem{
Owner: "nissan",
},
"giulia": OwnableItem{
Owner: "alfa-romeo",
},
}
m.On("GetAll", "sports-cars").Return(mockedItems, error(nil))

endpoint := newGetAllItemsEndpoint(m)
resp, err := endpoint(context.Background(), itemsRequest)

expectedItems := map[string]OwnableItem{
"4c-spider": OwnableItem{
Owner: "alfa-romeo",
},
"giulia": OwnableItem{
Owner: "alfa-romeo",
},
}

assert.Equal(expectedItems, resp)
assert.Nil(err)
}
8 changes: 8 additions & 0 deletions store/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,15 @@ func newDeleteItemHandler(s S) Handler {
encodeGetOrDeleteItemResponse,
kithttp.ServerErrorEncoder(encodeError),
)
}

func newGetAllItemsHandler(s S) Handler {
return kithttp.NewServer(
newGetAllItemsEndpoint(s),
decodeGetAllItemsRequest,
encodeGetAllItemsResponse,
kithttp.ServerErrorEncoder(encodeError),
)
}

type requestHandler struct {
Expand Down
35 changes: 35 additions & 0 deletions store/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,41 @@ type getOrDeleteItemRequest struct {
owner string
}

type getAllItemsRequest struct {
bucket string
owner string
}

func decodeGetAllItemsRequest(ctx context.Context, r *http.Request) (interface{}, error) {
vars := mux.Vars(r)
bucket, ok := vars[bucketVarKey]
if !ok {
return nil, &BadRequestErr{Message: bucketVarMissingMsg}
}
return &getAllItemsRequest{
bucket: bucket,
owner: r.Header.Get(ItemOwnerHeaderKey),
}, nil
}

func encodeGetAllItemsResponse(ctx context.Context, rw http.ResponseWriter, response interface{}) error {
items := response.(map[string]OwnableItem)
payload := map[string]model.Item{}
for k, value := range items {
if value.TTL <= 0 {
continue
}
payload[k] = value.Item
}
data, err := json.Marshal(&payload)
if err != nil {
return err
}
rw.Header().Add("Content-Type", "application/json")
rw.Write(data)
return nil
}

func decodeGetOrDeleteItemRequest(ctx context.Context, r *http.Request) (interface{}, error) {
vars := mux.Vars(r)
bucket, ok := vars[bucketVarKey]
Expand Down
61 changes: 61 additions & 0 deletions store/transport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,67 @@ func TestEncodeGetOrDeleteItemResponse(t *testing.T) {
}
}

func TestDecodeGetAllItemsRequest(t *testing.T) {
t.Run("Bucket Missing", testDecodeGetAllItemsRequestBucketMissing)
t.Run("Success", testDecodeGetAllItemsRequestSuccessful)
}

func testDecodeGetAllItemsRequestBucketMissing(t *testing.T) {
assert := assert.New(t)
r := httptest.NewRequest(http.MethodGet, "http://localhost:9030", nil)

decodedRequest, err := decodeGetAllItemsRequest(context.Background(), r)
assert.Nil(decodedRequest)
assert.Equal(&BadRequestErr{Message: bucketVarMissingMsg}, err)
}

func testDecodeGetAllItemsRequestSuccessful(t *testing.T) {
assert := assert.New(t)
r := httptest.NewRequest(http.MethodGet, "http://localhost:9030", nil)
r.Header.Set(ItemOwnerHeaderKey, "bob-ross")
r = mux.SetURLVars(r, map[string]string{bucketVarKey: "happy-little-accidents"})
expectedDecodedRequest := &getAllItemsRequest{
bucket: "happy-little-accidents",
owner: "bob-ross",
}

decodedRequest, err := decodeGetAllItemsRequest(context.Background(), r)
assert.Nil(err)
assert.Equal(expectedDecodedRequest, decodedRequest)
}

func TestEncodeGetAllItemsResponse(t *testing.T) {
assert := assert.New(t)
response := map[string]OwnableItem{
"fix-you": OwnableItem{
Item: model.Item{
Identifier: "coldplay-04",
TTL: 1,
Data: map[string]interface{}{},
},
},
"bohemian-rhapsody": OwnableItem{
Item: model.Item{
Identifier: "queen-03",
TTL: 0,
Data: map[string]interface{}{},
},
},
"don't-stop-me-know": OwnableItem{
Item: model.Item{
Identifier: "queen-02",
TTL: 0,
Data: map[string]interface{}{},
},
},
}
recorder := httptest.NewRecorder()
expectedResponseBody := `{"fix-you":{"identifier":"coldplay-04","data":{},"ttl":1}}`
err := encodeGetAllItemsResponse(context.Background(), recorder, response)
assert.Nil(err)
assert.Equal(expectedResponseBody, recorder.Body.String())
}

func transferHeaders(headers map[string][]string, r *http.Request) {
for k, values := range headers {
for _, value := range values {
Expand Down

0 comments on commit fc293ea

Please sign in to comment.