Skip to content

Commit

Permalink
Merge pull request #4 from daltemen/feature/services
Browse files Browse the repository at this point in the history
feat: rest implementation and fix where condition get all
  • Loading branch information
daltemen authored Jan 22, 2020
2 parents d6e403d + acddfa0 commit 0a03046
Show file tree
Hide file tree
Showing 7 changed files with 323 additions and 9 deletions.
35 changes: 35 additions & 0 deletions app/tasks/managers/mocks/Reader.go

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

72 changes: 72 additions & 0 deletions app/tasks/managers/mocks/Writer.go

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

2 changes: 1 addition & 1 deletion app/tasks/repositories/sql_tasks_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func (s *sqlTasksRepository) GetAll(ctx context.Context, page int, limit int) ([
var tasks []DbTask

pagination.Paging(&pagination.Param{
DB: s.Conn.Where("id > ?", 0),
DB: s.Conn.Where("id is not null"),
Page: page,
Limit: limit,
OrderBy: []string{"id desc"},
Expand Down
2 changes: 1 addition & 1 deletion app/tasks/repositories/sql_tasks_repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ var (
func (suite *sqlRepositorySuite) TestSqlTasksRepository_GetAll() {
tasksReply := getTasksDbReply()
mocket.Catcher.Reset().NewMock().
WithQuery(`SELECT * FROM "db_tasks" WHERE (id > 0) ORDER BY id desc LIMIT 1 OFFSET 0`).
WithQuery(`SELECT * FROM "db_tasks" WHERE (id is not null) ORDER BY id desc LIMIT 1 OFFSET 0`).
WithReply(tasksReply)
tasks, err := suite.repository.GetAll(suite.ctx, 1, 1)
suite.NoError(err)
Expand Down
83 changes: 76 additions & 7 deletions app/tasks/rest/rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,98 @@ import (
"fance/app/tasks/managers"
"github.com/labstack/echo/v4"
"net/http"
"strconv"
)

type Rest struct {
Reader managers.Reader
Writer managers.Writer
reader managers.Reader
writer managers.Writer
}

func NewRest(reader managers.Reader, writer managers.Writer) *Rest {
return &Rest{Reader: reader, Writer: writer}
return &Rest{reader: reader, writer: writer}
}

func (r *Rest) GetAll(c echo.Context) error {
return c.String(http.StatusOK, "Get, all!")
page, limit := r.getPageAndLimit(c)
tasks, err := r.reader.RetrieveAll(c.Request().Context(), page, limit)
if err != nil {
return err
}
return c.JSON(http.StatusOK, r.mapTasksInfoToGetAll(tasks, page, limit))
}

func (r *Rest) mapTasksInfoToGetAll(taskInfo []managers.TaskInfo, page, limit int) TasksGetAll {
result := TasksGetAll{
Page: page,
Limit: limit,
}
tasks := make([]TaskResponse, len(taskInfo))
for i, t := range taskInfo {
tasks[i] = *r.mapTaskInfoToResponse(&t)
}
result.Tasks = tasks
return result
}

func (r *Rest) getPageAndLimit(c echo.Context) (int, int) {
p := c.QueryParam("page")
l := c.QueryParam("limit")
if p == "" || l == "" {
return 1, 10
}
page, _ := strconv.Atoi(p)
limit, _ := strconv.Atoi(l)
return page, limit
}

func (r *Rest) PostTask(c echo.Context) error {
return c.String(http.StatusOK, "post, task!")
t := new(TaskRequest)
if err := c.Bind(t); err != nil {
return err
}
task, err := r.writer.Create(c.Request().Context(), r.mapRequestToTaskInfo(t))
if err != nil {
return c.JSON(http.StatusConflict, ErrorRest{Msg: err.Error()})
}
return c.JSON(http.StatusCreated, r.mapTaskInfoToResponse(task))
}

func (r *Rest) PutTask(c echo.Context) error {
return c.String(http.StatusOK, "put task!")
t := new(TaskRequest)
if err := c.Bind(t); err != nil {
return err
}
info := r.mapRequestToTaskInfo(t)
info.Id = c.Param("id")
task, err := r.writer.Update(c.Request().Context(), info)
if err != nil {
return c.JSON(http.StatusConflict, ErrorRest{Msg: err.Error()})
}
return c.JSON(http.StatusOK, r.mapTaskInfoToResponse(task))
}

func (r *Rest) DeleteTask(c echo.Context) error {
return c.String(http.StatusOK, "delete task!")
id := c.Param("id")
if err := r.writer.Delete(c.Request().Context(), id); err != nil {
return c.JSON(http.StatusConflict, ErrorRest{Msg: err.Error()})
}
return c.JSON(http.StatusNoContent, "")
}

func (r *Rest) mapRequestToTaskInfo(request *TaskRequest) *managers.TaskInfo {
return &managers.TaskInfo{
Title: request.Title,
Description: request.Description,
Status: request.Status,
}
}

func (r *Rest) mapTaskInfoToResponse(task *managers.TaskInfo) *TaskResponse {
return &TaskResponse{
Id: task.Id,
Title: task.Title,
Description: task.Description,
Status: task.Status,
}
}
114 changes: 114 additions & 0 deletions app/tasks/rest/rest_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package rest

import (
"context"
"fance/app/tasks/managers"
"fance/app/tasks/managers/mocks"
"github.com/labstack/echo/v4"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/suite"
"net/http"
"net/http/httptest"
"strings"
"testing"
)

type restSuite struct {
suite.Suite
ctx context.Context
reader *mocks.Reader
writer *mocks.Writer
rest *Rest
}

func (suite *restSuite) SetupTest() {
suite.ctx = context.Background()
suite.reader = new(mocks.Reader)
suite.writer = new(mocks.Writer)
suite.rest = NewRest(suite.reader, suite.writer)
}

func TestRestSuite(t *testing.T) {
suite.Run(t, &restSuite{})
}

var (
taskInfo0 = managers.TaskInfo{
Id: "d1b9e7b2-923d-43b2-a1b0-63a96a02663f",
Title: "My Title",
Description: "As a PM...",
Status: "DOING",
}
tasksInfo0 = []managers.TaskInfo{taskInfo0}

getAllJSON = `{"tasks":[{"id":"d1b9e7b2-923d-43b2-a1b0-63a96a02663f","title":"My Title","description":"As a PM...","status":"DOING"}],"page":1,"limit":10}
`
taskInfo1 = managers.TaskInfo{
Id: "d1b9e7b2-923d-43b2-a1b0-63a96a02663f",
Title: "Unit Tests",
Description: "As a Android developer...",
Status: "TODO",
}
taskJSON = `{ "title": "Unit Tests", "description": "As a Android developer...", "status": "TODO" }`

)

func (suite *restSuite) TestRest_GetAll() {
suite.reader.Mock.On("RetrieveAll", mock.Anything, mock.Anything, mock.Anything).Return(tasksInfo0, nil).Once()

e := echo.New()
req := httptest.NewRequest(http.MethodGet, "/api/v1/tasks", strings.NewReader(""))
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
err := suite.rest.GetAll(c)
suite.NoError(err)
suite.Equal(http.StatusOK, rec.Code)
suite.Equal(getAllJSON, rec.Body.String())
}


func (suite *restSuite) TestRest_PostTask() {
suite.writer.Mock.On("Create", mock.Anything, mock.Anything).Return(&taskInfo1, nil).Once()

e := echo.New()
req := httptest.NewRequest(http.MethodPost, "/api/v1/tasks", strings.NewReader(taskJSON))
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
err := suite.rest.PostTask(c)
expected := `{"id":"d1b9e7b2-923d-43b2-a1b0-63a96a02663f","title":"Unit Tests","description":"As a Android developer...","status":"TODO"}
`
suite.NoError(err)
suite.Equal(http.StatusCreated, rec.Code)
suite.Equal(expected, rec.Body.String())
}

func (suite *restSuite) TestRest_PutTask() {
suite.writer.Mock.On("Update", mock.Anything, mock.Anything).Return(&taskInfo1, nil).Once()

e := echo.New()
req := httptest.NewRequest(http.MethodPut, "/api/v1/tasks/" + taskInfo1.Id, strings.NewReader(taskJSON))
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
err := suite.rest.PutTask(c)
expected := `{"id":"d1b9e7b2-923d-43b2-a1b0-63a96a02663f","title":"Unit Tests","description":"As a Android developer...","status":"TODO"}
`
suite.NoError(err)
suite.Equal(http.StatusOK, rec.Code)
suite.Equal(expected, rec.Body.String())
}

func (suite *restSuite) TestRest_DeleteTask() {
suite.writer.Mock.On("Delete", mock.Anything, mock.Anything).Return(nil).Once()

e := echo.New()
req := httptest.NewRequest(http.MethodDelete, "/api/v1/tasks/" + taskInfo1.Id, strings.NewReader(""))
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
err := suite.rest.DeleteTask(c)
suite.NoError(err)
suite.Equal(http.StatusNoContent, rec.Code)
}
24 changes: 24 additions & 0 deletions app/tasks/rest/structs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package rest

type TaskRequest struct {
Title string `json:"title"`
Description string `json:"description"`
Status string `json:"status"`
}

type TaskResponse struct {
Id string `json:"id"`
Title string `json:"title"`
Description string `json:"description"`
Status string `json:"status"`
}

type ErrorRest struct {
Msg string `json:"msg"`
}

type TasksGetAll struct {
Tasks []TaskResponse `json:"tasks"`
Page int `json:"page"`
Limit int `json:"limit"`
}

0 comments on commit 0a03046

Please sign in to comment.