Skip to content

Commit

Permalink
render email templates
Browse files Browse the repository at this point in the history
  • Loading branch information
khanzadimahdi committed Aug 20, 2024
1 parent da60fe1 commit a7dca97
Show file tree
Hide file tree
Showing 12 changed files with 321 additions and 19 deletions.
2 changes: 1 addition & 1 deletion backend/application/article/getArticle/usecase_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ func TestUseCase_Execute(t *testing.T) {
assert.ErrorIs(t, err, expectedErr)
})

t.Run("error on increasing view count is not reflected on response", func(t *testing.T) {
t.Run("error on increasing template count is not reflected on response", func(t *testing.T) {
var (
articlesRepository articles.MockArticlesRepository
elementsRepository elements.MockElementsRepository
Expand Down
11 changes: 10 additions & 1 deletion backend/application/auth/forgetpassword/usecase.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,32 @@ import (
"github.com/khanzadimahdi/testproject/infrastructure/jwt"
)

const (
templateName = "resources/template/mail/auth/reset-password"
resetPasswordURL = "https://tarhche.com/auth/reset-password?token="
)

type UseCase struct {
userRepository user.Repository
jwt *jwt.JWT
mailer domain.Mailer
mailFrom string
template domain.Renderer
}

func NewUseCase(
userRepository user.Repository,
JWT *jwt.JWT,
mailer domain.Mailer,
mailFrom string,
template domain.Renderer,
) *UseCase {
return &UseCase{
userRepository: userRepository,
jwt: JWT,
mailer: mailer,
mailFrom: mailFrom,
template: template,
}
}

Expand All @@ -52,7 +60,8 @@ func (uc *UseCase) Execute(request Request) (*Response, error) {
resetPasswordToken = base64.URLEncoding.EncodeToString([]byte(resetPasswordToken))

var msg bytes.Buffer
if _, err := msg.WriteString(resetPasswordToken); err != nil {
viewData := map[string]string{"resetPasswordURL": resetPasswordURL + resetPasswordToken}
if err := uc.template.Render(&msg, templateName, viewData); err != nil {
return nil, err
}

Expand Down
53 changes: 49 additions & 4 deletions backend/application/auth/forgetpassword/usecase_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/khanzadimahdi/testproject/infrastructure/email"
"github.com/khanzadimahdi/testproject/infrastructure/jwt"
"github.com/khanzadimahdi/testproject/infrastructure/repository/mocks/users"
"github.com/khanzadimahdi/testproject/infrastructure/template"
)

func TestUseCase_Execute(t *testing.T) {
Expand All @@ -27,6 +28,7 @@ func TestUseCase_Execute(t *testing.T) {
var (
userRepository users.MockUsersRepository
mailer email.MockMailer
renderer template.MockRenderer

request = Request{
Identity: "[email protected]",
Expand All @@ -41,10 +43,13 @@ func TestUseCase_Execute(t *testing.T) {
userRepository.On("GetOneByIdentity", request.Identity).Once().Return(u, nil)
defer userRepository.AssertExpectations(t)

renderer.On("Render", mock.Anything, templateName, mock.Anything).Once().Return(nil)
defer renderer.AssertExpectations(t)

mailer.On("SendMail", mailFrom, u.Email, "Reset Password", mock.AnythingOfType("[]uint8")).Once().Return(nil)
defer mailer.AssertExpectations(t)

response, err := NewUseCase(&userRepository, j, &mailer, mailFrom).Execute(request)
response, err := NewUseCase(&userRepository, j, &mailer, mailFrom, &renderer).Execute(request)
assert.NoError(t, err)
assert.NotNil(t, response)
})
Expand All @@ -53,6 +58,7 @@ func TestUseCase_Execute(t *testing.T) {
var (
userRepository users.MockUsersRepository
mailer email.MockMailer
renderer template.MockRenderer

request = Request{}
expectedResponse = Response{
Expand All @@ -62,9 +68,10 @@ func TestUseCase_Execute(t *testing.T) {
}
)

response, err := NewUseCase(&userRepository, j, &mailer, mailFrom).Execute(request)
response, err := NewUseCase(&userRepository, j, &mailer, mailFrom, &renderer).Execute(request)

userRepository.AssertNotCalled(t, "GetOneByIdentity")
renderer.AssertNotCalled(t, "Render")
mailer.AssertNotCalled(t, "SendMail")

assert.NoError(t, err)
Expand All @@ -76,6 +83,7 @@ func TestUseCase_Execute(t *testing.T) {
var (
userRepository users.MockUsersRepository
mailer email.MockMailer
renderer template.MockRenderer

request = Request{
Identity: "[email protected]",
Expand All @@ -87,7 +95,40 @@ func TestUseCase_Execute(t *testing.T) {
userRepository.On("GetOneByIdentity", request.Identity).Once().Return(user.User{}, expectedErr)
defer userRepository.AssertExpectations(t)

response, err := NewUseCase(&userRepository, j, &mailer, mailFrom).Execute(request)
response, err := NewUseCase(&userRepository, j, &mailer, mailFrom, &renderer).Execute(request)

renderer.AssertNotCalled(t, "Render")
mailer.AssertNotCalled(t, "SendMail")

assert.ErrorIs(t, expectedErr, err)
assert.Nil(t, response)
})

t.Run("error on rendering template", func(t *testing.T) {
var (
userRepository users.MockUsersRepository
mailer email.MockMailer
renderer template.MockRenderer

request = Request{
Identity: "[email protected]",
}

u = user.User{
UUID: "user-uuid",
Email: request.Identity,
}

expectedErr = errors.New("something bad happened")
)

userRepository.On("GetOneByIdentity", request.Identity).Once().Return(u, nil)
defer userRepository.AssertExpectations(t)

renderer.On("Render", mock.Anything, templateName, mock.Anything).Once().Return(expectedErr)
defer renderer.AssertExpectations(t)

response, err := NewUseCase(&userRepository, j, &mailer, mailFrom, &renderer).Execute(request)

mailer.AssertNotCalled(t, "SendMail")

Expand All @@ -99,6 +140,7 @@ func TestUseCase_Execute(t *testing.T) {
var (
userRepository users.MockUsersRepository
mailer email.MockMailer
renderer template.MockRenderer

request = Request{
Identity: "[email protected]",
Expand All @@ -115,10 +157,13 @@ func TestUseCase_Execute(t *testing.T) {
userRepository.On("GetOneByIdentity", request.Identity).Once().Return(u, nil)
defer userRepository.AssertExpectations(t)

renderer.On("Render", mock.Anything, templateName, mock.Anything).Once().Return(nil)
defer renderer.AssertExpectations(t)

mailer.On("SendMail", mailFrom, u.Email, "Reset Password", mock.AnythingOfType("[]uint8")).Once().Return(expectedErr)
defer mailer.AssertExpectations(t)

response, err := NewUseCase(&userRepository, j, &mailer, mailFrom).Execute(request)
response, err := NewUseCase(&userRepository, j, &mailer, mailFrom, &renderer).Execute(request)
assert.ErrorIs(t, expectedErr, err)
assert.Nil(t, response)
})
Expand Down
15 changes: 12 additions & 3 deletions backend/application/auth/register/usecase.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,32 @@ import (
"github.com/khanzadimahdi/testproject/infrastructure/jwt"
)

const (
templateName = "resources/template/mail/auth/register"
registrationURL = "https://tarhche.com/auth/reset-password?token="
)

type UseCase struct {
userRepository user.Repository
jwt *jwt.JWT
mailer domain.Mailer
mailFrom string
template domain.Renderer
}

func NewUseCase(
userRepository user.Repository,
JWT *jwt.JWT,
mailer domain.Mailer,
mailFrom string,
template domain.Renderer,
) *UseCase {
return &UseCase{
userRepository: userRepository,
jwt: JWT,
mailer: mailer,
mailFrom: mailFrom,
template: template,
}
}

Expand All @@ -50,15 +58,16 @@ func (uc *UseCase) Execute(request Request) (*Response, error) {
}, nil
}

resetPasswordToken, err := uc.registrationToken(request.Identity)
registrationToken, err := uc.registrationToken(request.Identity)
if err != nil {
return nil, err
}

resetPasswordToken = base64.URLEncoding.EncodeToString([]byte(resetPasswordToken))
registrationToken = base64.URLEncoding.EncodeToString([]byte(registrationToken))

var msg bytes.Buffer
if _, err := msg.WriteString(resetPasswordToken); err != nil {
viewData := map[string]string{"registrationURL": registrationURL + registrationToken}
if err := uc.template.Render(&msg, templateName, viewData); err != nil {
return nil, err
}

Expand Down
52 changes: 47 additions & 5 deletions backend/application/auth/register/usecase_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/khanzadimahdi/testproject/infrastructure/email"
"github.com/khanzadimahdi/testproject/infrastructure/jwt"
"github.com/khanzadimahdi/testproject/infrastructure/repository/mocks/users"
"github.com/khanzadimahdi/testproject/infrastructure/template"
)

func TestUseCase_Execute(t *testing.T) {
Expand All @@ -28,6 +29,7 @@ func TestUseCase_Execute(t *testing.T) {
var (
userRepository users.MockUsersRepository
mailer email.MockMailer
renderer template.MockRenderer

r = Request{
Identity: "[email protected]",
Expand All @@ -37,10 +39,13 @@ func TestUseCase_Execute(t *testing.T) {
userRepository.On("GetOneByIdentity", r.Identity).Once().Return(user.User{}, nil)
defer userRepository.AssertExpectations(t)

renderer.On("Render", mock.Anything, templateName, mock.Anything).Once().Return(nil)
defer renderer.AssertExpectations(t)

mailer.On("SendMail", mailFrom, r.Identity, "Registration", mock.AnythingOfType("[]uint8")).Once().Return(nil)
defer mailer.AssertExpectations(t)

response, err := NewUseCase(&userRepository, j, &mailer, mailFrom).Execute(r)
response, err := NewUseCase(&userRepository, j, &mailer, mailFrom, &renderer).Execute(r)

assert.NoError(t, err)
assert.NotNil(t, response)
Expand All @@ -51,15 +56,17 @@ func TestUseCase_Execute(t *testing.T) {
var (
userRepository users.MockUsersRepository
mailer email.MockMailer
renderer template.MockRenderer

r = Request{
Identity: "somethingForTest",
}
)

response, err := NewUseCase(&userRepository, j, &mailer, mailFrom).Execute(r)
response, err := NewUseCase(&userRepository, j, &mailer, mailFrom, &renderer).Execute(r)

userRepository.AssertNotCalled(t, "GetOneByIdentity")
renderer.AssertNotCalled(t, "Render")
mailer.AssertNotCalled(t, "SendMail")

assert.NoError(t, err)
Expand All @@ -71,6 +78,7 @@ func TestUseCase_Execute(t *testing.T) {
var (
userRepository users.MockUsersRepository
mailer email.MockMailer
renderer template.MockRenderer

r = Request{
Identity: "[email protected]",
Expand All @@ -90,8 +98,9 @@ func TestUseCase_Execute(t *testing.T) {
userRepository.On("GetOneByIdentity", r.Identity).Once().Return(u, nil)
defer userRepository.AssertExpectations(t)

response, err := NewUseCase(&userRepository, j, &mailer, mailFrom).Execute(r)
response, err := NewUseCase(&userRepository, j, &mailer, mailFrom, &renderer).Execute(r)

renderer.AssertNotCalled(t, "Render")
mailer.AssertNotCalled(t, "SendMail")

assert.NoError(t, err)
Expand All @@ -103,6 +112,7 @@ func TestUseCase_Execute(t *testing.T) {
var (
userRepository users.MockUsersRepository
mailer email.MockMailer
renderer template.MockRenderer

r = Request{
Identity: "[email protected]",
Expand All @@ -118,7 +128,35 @@ func TestUseCase_Execute(t *testing.T) {
userRepository.On("GetOneByIdentity", r.Identity).Once().Return(u, expectedError)
defer userRepository.AssertExpectations(t)

response, err := NewUseCase(&userRepository, j, &mailer, mailFrom).Execute(r)
response, err := NewUseCase(&userRepository, j, &mailer, mailFrom, &renderer).Execute(r)

renderer.AssertNotCalled(t, "Render")
mailer.AssertNotCalled(t, "SendMail")

assert.ErrorIs(t, err, expectedError)
assert.Nil(t, response)
})

t.Run("error on rendering template", func(t *testing.T) {
var (
userRepository users.MockUsersRepository
mailer email.MockMailer
renderer template.MockRenderer

r = Request{
Identity: "[email protected]",
}

expectedError = errors.New("some error")
)

userRepository.On("GetOneByIdentity", r.Identity).Once().Return(user.User{}, domain.ErrNotExists)
defer userRepository.AssertExpectations(t)

renderer.On("Render", mock.Anything, templateName, mock.Anything).Once().Return(expectedError)
defer renderer.AssertExpectations(t)

response, err := NewUseCase(&userRepository, j, &mailer, mailFrom, &renderer).Execute(r)

mailer.AssertNotCalled(t, "SendMail")

Expand All @@ -130,6 +168,7 @@ func TestUseCase_Execute(t *testing.T) {
var (
userRepository users.MockUsersRepository
mailer email.MockMailer
renderer template.MockRenderer

r = Request{
Identity: "[email protected]",
Expand All @@ -141,10 +180,13 @@ func TestUseCase_Execute(t *testing.T) {
userRepository.On("GetOneByIdentity", r.Identity).Once().Return(user.User{}, domain.ErrNotExists)
defer userRepository.AssertExpectations(t)

renderer.On("Render", mock.Anything, templateName, mock.Anything).Once().Return(nil)
defer renderer.AssertExpectations(t)

mailer.On("SendMail", mailFrom, r.Identity, "Registration", mock.AnythingOfType("[]uint8")).Once().Return(expectedError)
defer mailer.AssertExpectations(t)

response, err := NewUseCase(&userRepository, j, &mailer, mailFrom).Execute(r)
response, err := NewUseCase(&userRepository, j, &mailer, mailFrom, &renderer).Execute(r)

assert.ErrorIs(t, err, expectedError)
assert.Nil(t, response)
Expand Down
7 changes: 7 additions & 0 deletions backend/domain/renderer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package domain

import "io"

type Renderer interface {
Render(writer io.Writer, templateName string, data any) error
}
21 changes: 21 additions & 0 deletions backend/infrastructure/template/mock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package template

import (
"io"

"github.com/stretchr/testify/mock"

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

type MockRenderer struct {
mock.Mock
}

var _ domain.Renderer = &MockRenderer{}

func (r *MockRenderer) Render(writer io.Writer, templateName string, data any) error {
args := r.Mock.Called(writer, templateName, data)

return args.Error(0)
}
Loading

0 comments on commit a7dca97

Please sign in to comment.