tests for GetRecipesHandler
This commit is contained in:
parent
606cc3763a
commit
0b91ea5ba9
|
@ -117,7 +117,7 @@ func TestGetRecipeHandler(t *testing.T) {
|
|||
}
|
||||
// create handler
|
||||
handler := recipe.New(slogdiscard.NewDiscardLogger(), recipeProviderMock)
|
||||
//
|
||||
// create input
|
||||
input := fmt.Sprintf(tc.inputJsonPattern, 1)
|
||||
// http request
|
||||
req, err := http.NewRequest(http.MethodGet, "/recipe", bytes.NewReader([]byte(input)))
|
||||
|
|
|
@ -27,7 +27,7 @@ type RecipesProvider interface {
|
|||
GetRecipes(ctx context.Context, offset, limit int) ([]models.Recipe, error)
|
||||
}
|
||||
|
||||
const getRecipesLimit int = 16
|
||||
const GetRecipesLimit int = 16
|
||||
|
||||
func New(log *slog.Logger, recipesProvider RecipesProvider) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -56,7 +56,7 @@ func New(log *slog.Logger, recipesProvider RecipesProvider) http.HandlerFunc {
|
|||
return
|
||||
}
|
||||
// get from storage
|
||||
recipes, err := recipesProvider.GetRecipes(r.Context(), getRecipesLimit*(int(req.Page)-1), getRecipesLimit)
|
||||
recipes, err := recipesProvider.GetRecipes(r.Context(), GetRecipesLimit*(int(req.Page)-1), GetRecipesLimit)
|
||||
if err != nil {
|
||||
log.Error("failed to get recipes from storage", sl.Err(err))
|
||||
render.JSON(w, r, resp.Error("failed to get recipes"))
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
package recipes_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"recipes/internal/domain/models"
|
||||
"recipes/internal/http-server/handlers/recipes"
|
||||
"recipes/internal/http-server/handlers/recipes/mocks"
|
||||
"recipes/internal/lib/logger/handlers/slogdiscard"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGetRecipesHandler(t *testing.T) {
|
||||
// cases
|
||||
cases := []struct {
|
||||
name string // name of test
|
||||
page uint // number of page to get
|
||||
inputBody string // input json
|
||||
wantBody string // expected output json
|
||||
wantRespError string // expected error
|
||||
wantRespStatus string // expected status
|
||||
storageMockError error // mock error to return
|
||||
storageTimes int // count of storage calls
|
||||
recipes []models.Recipe // returned data
|
||||
}{
|
||||
{
|
||||
name: "Success",
|
||||
page: 1,
|
||||
inputBody: `{"page": 1}`,
|
||||
wantBody: "{\"status\":\"OK\",\"recipes\":[{\"id\":1,\"title\":\"title 1\",\"img\":\"1.jpg\",\"ctime\":\"1 час\",\"cal\":\"100 kCal\"},{\"id\":2,\"title\":\"title 2\",\"img\":\"2.jpg\",\"ctime\":\"2 час\",\"cal\":\"200 kCal\"}]}\n",
|
||||
wantRespStatus: "OK",
|
||||
storageTimes: 1,
|
||||
recipes: []models.Recipe{
|
||||
{
|
||||
ID: 1,
|
||||
Title: "title 1",
|
||||
Image: "1.jpg",
|
||||
CookingTime: "1 час",
|
||||
Calories: "100 kCal",
|
||||
},
|
||||
{
|
||||
ID: 2,
|
||||
Title: "title 2",
|
||||
Image: "2.jpg",
|
||||
CookingTime: "2 час",
|
||||
Calories: "200 kCal",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Empty page",
|
||||
page: 10,
|
||||
inputBody: `{"page": 10}`,
|
||||
wantBody: "{\"status\":\"OK\",\"recipes\":null}\n",
|
||||
wantRespStatus: "OK",
|
||||
storageTimes: 1,
|
||||
},
|
||||
{
|
||||
name: "Bad data",
|
||||
inputBody: `{"page": 0}`,
|
||||
wantBody: "{\"status\":\"Error\",\"error\":\"field Page is a required field\"}\n",
|
||||
wantRespStatus: "Error",
|
||||
wantRespError: "field Page is a required field",
|
||||
storageTimes: 0,
|
||||
},
|
||||
{
|
||||
name: "Broken JSON",
|
||||
inputBody: `{"page" 1}`,
|
||||
wantBody: "{\"status\":\"Error\",\"error\":\"failed to decode request\"}\n",
|
||||
wantRespError: "failed to decode request",
|
||||
wantRespStatus: "Error",
|
||||
storageTimes: 0,
|
||||
},
|
||||
{
|
||||
name: "Storage error",
|
||||
inputBody: `{"page": 1}`,
|
||||
page: 1,
|
||||
wantBody: "{\"status\":\"Error\",\"error\":\"failed to get recipes\"}\n",
|
||||
wantRespError: "failed to get recipes",
|
||||
wantRespStatus: "Error",
|
||||
storageMockError: errors.New("SOME ERROR"),
|
||||
storageTimes: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// create storage mock
|
||||
recipeProviderMock := mocks.NewRecipesProvider(t)
|
||||
if tc.storageTimes > 0 {
|
||||
recipeProviderMock.On("GetRecipes", context.Background(), recipes.GetRecipesLimit*(int(tc.page)-1), recipes.GetRecipesLimit).Return(tc.recipes, tc.storageMockError).Times(tc.storageTimes)
|
||||
}
|
||||
// create handler
|
||||
handler := recipes.New(slogdiscard.NewDiscardLogger(), recipeProviderMock)
|
||||
// http request
|
||||
req, err := http.NewRequest(http.MethodGet, "/recipes_page", bytes.NewReader([]byte(tc.inputBody)))
|
||||
require.NoError(t, err)
|
||||
// create request
|
||||
rr := httptest.NewRecorder()
|
||||
handler.ServeHTTP(rr, req)
|
||||
// compare expected and actual
|
||||
assert.Equal(t, http.StatusOK, rr.Code)
|
||||
|
||||
body := rr.Body.String()
|
||||
assert.Equal(t, tc.wantBody, body)
|
||||
|
||||
var resp recipes.Response
|
||||
require.NoError(t, json.Unmarshal([]byte(body), &resp))
|
||||
assert.Equal(t, tc.wantRespError, resp.Error)
|
||||
assert.Equal(t, tc.wantRespStatus, resp.Status)
|
||||
assert.Equal(t, tc.recipes, resp.Recipes)
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue