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
136 changes: 14 additions & 122 deletions application/article/getArticle/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,71 +3,33 @@ package getarticle
import (
"time"

"github.com/khanzadimahdi/testproject/application/element"
"github.com/khanzadimahdi/testproject/domain/article"
"github.com/khanzadimahdi/testproject/domain/element"
"github.com/khanzadimahdi/testproject/domain/element/component"
)

type Response struct {
UUID string `json:"uuid"`
Cover string `json:"cover"`
Video string `json:"video"`
Title string `json:"title"`
Excerpt string `json:"excerpt"`
Body string `json:"body"`
PublishedAt string `json:"published_at"`
Author authorResponse `json:"avatar"`
Tags []string `json:"tags"`
ViewCount uint `json:"view_count"`
Elements []elementResponse `json:"elements"`
UUID string `json:"uuid"`
Cover string `json:"cover"`
Video string `json:"video"`
Title string `json:"title"`
Excerpt string `json:"excerpt"`
Body string `json:"body"`
PublishedAt string `json:"published_at"`
Author authorResponse `json:"avatar"`
Tags []string `json:"tags"`
ViewCount uint `json:"view_count"`
Elements []element.Response `json:"elements"`
}

type authorResponse struct {
Name string `json:"name"`
Avatar string `json:"avatar"`
}

type articleResponse struct {
UUID string `json:"uuid"`
Cover string `json:"cover"`
Title string `json:"title"`
Author authorResponse `json:"author"`
PublishedAt string `json:"published_at"`
Excerpt string `json:"excerpt"`
Tags []string `json:"tags"`
}

type elementResponse struct {
Type string `json:"type"`
Body any `json:"body"`
}

type itemComponentResponse struct {
Type string `json:"type"`
Body any `json:"body"`
}

type featuredComponentResponse struct {
Main itemComponentResponse `json:"main"`
Aside []itemComponentResponse `json:"aside"`
}

type jumbotronComponentResponse struct {
itemComponentResponse
}

func NewResponse(a article.Article, e []element.Element, elementsContent []article.Article) *Response {
func NewResponse(a article.Article, elementsResponse []element.Response) *Response {
tags := make([]string, len(a.Tags))
copy(tags, a.Tags)

elements := make([]elementResponse, len(e))
for i := range e {
elements[i] = elementResponse{
Type: e[i].Type,
Body: toComponentResponse(e[i], elementsContent),
}
}

return &Response{
UUID: a.UUID,
Cover: a.Cover,
Expand All @@ -82,76 +44,6 @@ func NewResponse(a article.Article, e []element.Element, elementsContent []artic
},
Tags: tags,
ViewCount: a.ViewCount,
Elements: elements,
}
}

func toComponentResponse(e element.Element, elementsContent []article.Article) any {
var c any

if e.Type == "jumbotron" {
c = toJumbotronResponse(e.Body.(component.Jumbotron), elementsContent)
Elements: elementsResponse,
}

if e.Type == "featured" {
c = toFeaturedResponse(e.Body.(component.Featured), elementsContent)
}

if e.Type == "item" {
c = toItemResponse(e.Body.(component.Item), elementsContent)
}

return c
}

func toJumbotronResponse(c component.Jumbotron, elementsContent []article.Article) jumbotronComponentResponse {
return jumbotronComponentResponse{
itemComponentResponse: toItemResponse(c.Item, elementsContent),
}
}

func toFeaturedResponse(c component.Featured, elementsContent []article.Article) featuredComponentResponse {
aside := make([]itemComponentResponse, len(c.Aside))

for i := range c.Aside {
aside[i] = toItemResponse(c.Aside[i], elementsContent)
}

return featuredComponentResponse{
Main: toItemResponse(c.Main, elementsContent),
Aside: aside,
}
}

func toItemResponse(c component.Item, elementsContent []article.Article) itemComponentResponse {
var body any
for i := range elementsContent {
if elementsContent[i].UUID == c.UUID {
body = toArticleResponse([]article.Article{elementsContent[i]})[0]
break
}
}

return itemComponentResponse{
Type: c.Type,
Body: body,
}
}

func toArticleResponse(a []article.Article) []articleResponse {
items := make([]articleResponse, len(a))

for i := range a {
items[i].UUID = a[i].UUID
items[i].Cover = a[i].Cover
items[i].Title = a[i].Title
items[i].Excerpt = a[i].Excerpt
items[i].Tags = a[i].Tags
items[i].PublishedAt = a[i].PublishedAt.Format(time.RFC3339)

items[i].Author.Name = a[i].Author.Name
items[i].Author.Avatar = a[i].Author.Avatar
}

return items
}
36 changes: 6 additions & 30 deletions application/article/getArticle/usecase.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,22 @@ package getarticle
import (
"fmt"

"github.com/khanzadimahdi/testproject/application/element"
"github.com/khanzadimahdi/testproject/domain/article"
"github.com/khanzadimahdi/testproject/domain/element"
"github.com/khanzadimahdi/testproject/domain/element/component"
)

type UseCase struct {
articleRepository article.Repository
elementRepository element.Repository
elementRetriever *element.Retriever
}

func NewUseCase(
articleRepository article.Repository,
elementRepository element.Repository,
elementRetriever *element.Retriever,
) *UseCase {
return &UseCase{
articleRepository: articleRepository,
elementRepository: elementRepository,
elementRetriever: elementRetriever,
}
}

Expand All @@ -29,35 +28,12 @@ func (uc *UseCase) Execute(UUID string) (*Response, error) {
return nil, err
}

elements, articles, err := uc.elements(a.UUID)
elementsResponse, err := uc.elementRetriever.RetrieveByVenues([]string{fmt.Sprintf("articles/%s", UUID)})
if err != nil {
return nil, err
}

defer uc.articleRepository.IncreaseView(a.UUID, 1)

return NewResponse(a, elements, articles), nil
}

func (uc *UseCase) elements(UUID string) ([]element.Element, []article.Article, error) {
elements, err := uc.elementRepository.GetByVenues([]string{fmt.Sprintf("articles/%s", UUID)})
if err != nil {
return nil, nil, err
}

items := make([]component.Item, 0, len(elements))
for i := range elements {
items = append(items, elements[i].Body.Items()...)
}

uuids := make([]string, len(items))
for i := range items {
uuids[i] = items[i].UUID
}
articles, err := uc.articleRepository.GetByUUIDs(uuids)
if err != nil {
return nil, nil, err
}

return elements, articles, nil
return NewResponse(a, elementsResponse), nil
}
62 changes: 35 additions & 27 deletions application/article/getArticle/usecase_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import (

"github.com/stretchr/testify/assert"

"github.com/khanzadimahdi/testproject/application/element"
"github.com/khanzadimahdi/testproject/domain"
"github.com/khanzadimahdi/testproject/domain/article"
"github.com/khanzadimahdi/testproject/domain/element"
domainElement "github.com/khanzadimahdi/testproject/domain/element"
"github.com/khanzadimahdi/testproject/domain/element/component"
"github.com/khanzadimahdi/testproject/infrastructure/repository/mocks/articles"
"github.com/khanzadimahdi/testproject/infrastructure/repository/mocks/elements"
Expand All @@ -31,14 +32,14 @@ func TestUseCase_Execute(t *testing.T) {
{UUID: "test-article-2"},
}
i = []component.Item{
{UUID: va[0].UUID},
{UUID: va[1].UUID},
{UUID: "not-exist-article-uuid"},
{ContentUUID: va[0].UUID},
{ContentUUID: va[1].UUID},
{ContentUUID: "not-exist-article-uuid"},
}
u = []string{
i[0].UUID,
i[1].UUID,
i[2].UUID,
i[0].ContentUUID,
i[1].ContentUUID,
i[2].ContentUUID,
}
)

Expand All @@ -48,16 +49,18 @@ func TestUseCase_Execute(t *testing.T) {
defer articlesRepository.AssertExpectations(t)

mockComponent.On("Items").Once().Return(i)
mockComponent.On("Type").Return(component.ComponentTypeMock)
defer mockComponent.AssertExpectations(t)

v := []element.Element{
v := []domainElement.Element{
{Body: &mockComponent},
}

elementsRepository.On("GetByVenues", venues).Once().Return(v, nil)
defer elementsRepository.AssertExpectations(t)

response, err := NewUseCase(&articlesRepository, &elementsRepository).Execute("test-uuid")
elementRetriever := element.NewRetriever(&articlesRepository, &elementsRepository)
response, err := NewUseCase(&articlesRepository, elementRetriever).Execute("test-uuid")

assert.NotNil(t, response, "unexpected response")
assert.NoError(t, err, "unexpected error")
Expand All @@ -77,7 +80,8 @@ func TestUseCase_Execute(t *testing.T) {
articlesRepository.On("GetOnePublished", articleUUID).Once().Return(a, expectedErr)
defer articlesRepository.AssertExpectations(t)

usecase := NewUseCase(&articlesRepository, &elementsRepository)
elementRetriever := element.NewRetriever(&articlesRepository, &elementsRepository)
usecase := NewUseCase(&articlesRepository, elementRetriever)
response, err := usecase.Execute("test-uuid")

elementsRepository.AssertNotCalled(t, "GetByVenues")
Expand Down Expand Up @@ -105,7 +109,8 @@ func TestUseCase_Execute(t *testing.T) {
elementsRepository.On("GetByVenues", venues).Once().Return(nil, expectedErr)
defer elementsRepository.AssertExpectations(t)

usecase := NewUseCase(&articlesRepository, &elementsRepository)
elementRetriever := element.NewRetriever(&articlesRepository, &elementsRepository)
usecase := NewUseCase(&articlesRepository, elementRetriever)
response, err := usecase.Execute("test-uuid")

articlesRepository.AssertNotCalled(t, "GetByUUIDs")
Expand All @@ -131,14 +136,14 @@ func TestUseCase_Execute(t *testing.T) {
{UUID: "test-article-2"},
}
i = []component.Item{
{UUID: va[0].UUID},
{UUID: va[1].UUID},
{UUID: "not-exist-article-uuid"},
{ContentUUID: va[0].UUID},
{ContentUUID: va[1].UUID},
{ContentUUID: "not-exist-article-uuid"},
}
u = []string{
i[0].UUID,
i[1].UUID,
i[2].UUID,
i[0].ContentUUID,
i[1].ContentUUID,
i[2].ContentUUID,
}
)

Expand All @@ -149,14 +154,15 @@ func TestUseCase_Execute(t *testing.T) {
mockComponent.On("Items").Once().Return(i)
defer mockComponent.AssertExpectations(t)

v := []element.Element{
v := []domainElement.Element{
{Body: &mockComponent},
}

elementsRepository.On("GetByVenues", venues).Once().Return(v, nil)
defer elementsRepository.AssertExpectations(t)

response, err := NewUseCase(&articlesRepository, &elementsRepository).Execute("test-uuid")
elementRetriever := element.NewRetriever(&articlesRepository, &elementsRepository)
response, err := NewUseCase(&articlesRepository, elementRetriever).Execute("test-uuid")

articlesRepository.AssertNotCalled(t, "IncreaseView")

Expand All @@ -181,14 +187,14 @@ func TestUseCase_Execute(t *testing.T) {
{UUID: "test-article-2"},
}
i = []component.Item{
{UUID: va[0].UUID},
{UUID: va[1].UUID},
{UUID: "not-exist-article-uuid"},
{ContentUUID: va[0].UUID},
{ContentUUID: va[1].UUID},
{ContentUUID: "not-exist-article-uuid"},
}
u = []string{
i[0].UUID,
i[1].UUID,
i[2].UUID,
i[0].ContentUUID,
i[1].ContentUUID,
i[2].ContentUUID,
}
)

Expand All @@ -198,16 +204,18 @@ func TestUseCase_Execute(t *testing.T) {
defer articlesRepository.AssertExpectations(t)

mockComponent.On("Items").Once().Return(i)
mockComponent.On("Type").Return(component.ComponentTypeMock)
defer mockComponent.AssertExpectations(t)

v := []element.Element{
v := []domainElement.Element{
{Body: &mockComponent},
}

elementsRepository.On("GetByVenues", venues).Once().Return(v, nil)
defer elementsRepository.AssertExpectations(t)

response, err := NewUseCase(&articlesRepository, &elementsRepository).Execute("test-uuid")
elementRetriever := element.NewRetriever(&articlesRepository, &elementsRepository)
response, err := NewUseCase(&articlesRepository, elementRetriever).Execute("test-uuid")

assert.NotNil(t, response, "unexpected response")
assert.NoError(t, err, "unexpected error")
Expand Down
2 changes: 0 additions & 2 deletions application/auth/verify/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ package verify

import "github.com/khanzadimahdi/testproject/domain"

type validationErrors map[string]string

type Request struct {
Token string `json:"token"`
Name string `json:"name"`
Expand Down
Loading
Loading