tests: implemented go user api tests
This commit is contained in:
parent
48aae18736
commit
f8933bee15
@ -3,10 +3,14 @@ module actatempus_backend
|
|||||||
go 1.23.2
|
go 1.23.2
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/gin-gonic/gin v1.10.0
|
||||||
|
github.com/golang-jwt/jwt/v5 v5.2.1
|
||||||
|
github.com/google/uuid v1.6.0
|
||||||
github.com/joho/godotenv v1.5.1
|
github.com/joho/godotenv v1.5.1
|
||||||
github.com/shopspring/decimal v1.4.0
|
github.com/shopspring/decimal v1.4.0
|
||||||
github.com/spf13/viper v1.19.0
|
github.com/spf13/viper v1.19.0
|
||||||
github.com/steebchen/prisma-client-go v0.45.0
|
github.com/steebchen/prisma-client-go v0.45.0
|
||||||
|
github.com/stretchr/testify v1.10.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@ -14,27 +18,22 @@ require (
|
|||||||
github.com/bytedance/sonic/loader v0.2.1 // indirect
|
github.com/bytedance/sonic/loader v0.2.1 // indirect
|
||||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.7 // indirect
|
github.com/gabriel-vasile/mimetype v1.4.7 // indirect
|
||||||
github.com/gin-contrib/sse v1.0.0 // indirect
|
github.com/gin-contrib/sse v1.0.0 // indirect
|
||||||
github.com/gin-gonic/gin v1.10.0 // indirect
|
|
||||||
github.com/go-playground/locales v0.14.1 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.23.0 // indirect
|
github.com/go-playground/validator/v10 v10.23.0 // indirect
|
||||||
github.com/goccy/go-json v0.10.4 // indirect
|
github.com/goccy/go-json v0.10.4 // indirect
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
|
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
|
||||||
github.com/leodido/go-urn v1.4.0 // indirect
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||||
github.com/urfave/cli/v2 v2.27.5 // indirect
|
|
||||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
|
|
||||||
golang.org/x/arch v0.12.0 // indirect
|
golang.org/x/arch v0.12.0 // indirect
|
||||||
golang.org/x/crypto v0.31.0 // indirect
|
golang.org/x/crypto v0.31.0 // indirect
|
||||||
golang.org/x/net v0.33.0 // indirect
|
golang.org/x/net v0.33.0 // indirect
|
||||||
|
@ -9,8 +9,6 @@ github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/
|
|||||||
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||||
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
||||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
|
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||||
@ -25,6 +23,8 @@ github.com/gin-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E
|
|||||||
github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0=
|
github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0=
|
||||||
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||||
|
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||||
|
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||||
@ -74,8 +74,6 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
|
|||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
|
||||||
github.com/sagikazarmark/locafero v0.6.0 h1:ON7AQg37yzcRPU69mt7gwhFEBwxI6P9T4Qu3N51bwOk=
|
github.com/sagikazarmark/locafero v0.6.0 h1:ON7AQg37yzcRPU69mt7gwhFEBwxI6P9T4Qu3N51bwOk=
|
||||||
github.com/sagikazarmark/locafero v0.6.0/go.mod h1:77OmuIc6VTraTXKXIs/uvUxKGUXjE1GbemJYHqdNjX0=
|
github.com/sagikazarmark/locafero v0.6.0/go.mod h1:77OmuIc6VTraTXKXIs/uvUxKGUXjE1GbemJYHqdNjX0=
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
||||||
@ -112,10 +110,6 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS
|
|||||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||||
github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w=
|
|
||||||
github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
|
|
||||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
|
|
||||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
|
|
||||||
go.mongodb.org/mongo-driver/v2 v2.0.0 h1:Jfd7XpdZa9yk3eY774bO7SWVb30noLSirL9nKTpavhI=
|
go.mongodb.org/mongo-driver/v2 v2.0.0 h1:Jfd7XpdZa9yk3eY774bO7SWVb30noLSirL9nKTpavhI=
|
||||||
go.mongodb.org/mongo-driver/v2 v2.0.0/go.mod h1:nSjmNq4JUstE8IRZKTktLgMHM4F1fccL6HGX1yh+8RA=
|
go.mongodb.org/mongo-driver/v2 v2.0.0/go.mod h1:nSjmNq4JUstE8IRZKTktLgMHM4F1fccL6HGX1yh+8RA=
|
||||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||||
@ -144,4 +138,3 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
|||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
package services_test
|
|
||||||
|
|
||||||
import "testing"
|
|
||||||
|
|
||||||
|
|
||||||
func TestCreateUserService(t *testing.T) {
|
|
||||||
mockRepo := mocks.NewMockUserRepository()
|
|
||||||
service := services.NewUserService(mockRepo)
|
|
||||||
|
|
||||||
user := entities.UserCreate{
|
|
||||||
Email: "service@test.com",
|
|
||||||
Name: "Jane Doe",
|
|
||||||
Password: "securepassword",
|
|
||||||
}
|
|
||||||
|
|
||||||
result := service.CreateUser(context.Background(), user)
|
|
||||||
|
|
||||||
assert.True(t, result.IsRight(), "Expected service to create user")
|
|
||||||
result.Map(func(user entities.User) {
|
|
||||||
assert.Equal(t, "service@test.com", user.Email)
|
|
||||||
assert.Equal(t, "Jane Doe", user.Name)
|
|
||||||
})
|
|
||||||
}
|
|
37
backend-go/tests/mocks/mock_auth_repository.go
Normal file
37
backend-go/tests/mocks/mock_auth_repository.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package mocks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"actatempus_backend/internal/domain/repository"
|
||||||
|
"context"
|
||||||
|
|
||||||
|
E "github.com/IBM/fp-go/either"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockAuthRepository is a mock implementation of AuthRepository.
|
||||||
|
type MockAuthRepository struct{}
|
||||||
|
|
||||||
|
// NewMockAuthRepository creates a new instance of MockAuthRepository.
|
||||||
|
func NewMockAuthRepository() repository.AuthRepository {
|
||||||
|
return &MockAuthRepository{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateToken always returns a successful token generation.
|
||||||
|
func (m *MockAuthRepository) GenerateToken(ctx context.Context) func(userID string) E.Either[error, string] {
|
||||||
|
return func(userID string) E.Either[error, string] {
|
||||||
|
return E.Right[error]("mocked-token")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateToken always validates a token successfully.
|
||||||
|
func (m *MockAuthRepository) ValidateToken(ctx context.Context) func(token string) E.Either[error, string] {
|
||||||
|
return func(token string) E.Either[error, string] {
|
||||||
|
return E.Right[error]("mocked-user-id")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RevokeToken always revokes a token successfully.
|
||||||
|
func (m *MockAuthRepository) RevokeToken(ctx context.Context) func(token string) E.Either[error, string] {
|
||||||
|
return func(token string) E.Either[error, string] {
|
||||||
|
return E.Right[error]("mocked-user-id")
|
||||||
|
}
|
||||||
|
}
|
@ -15,13 +15,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type MockProjectDataSource struct {
|
type MockProjectDataSource struct {
|
||||||
store map[string]*entities.Project
|
Store map[string]*entities.Project
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMockProjectDataSource() data.ProjectDataSource {
|
func NewMockProjectDataSource() data.ProjectDataSource {
|
||||||
return &MockProjectDataSource{
|
return &MockProjectDataSource{
|
||||||
store: make(map[string]*entities.Project),
|
Store: make(map[string]*entities.Project),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ func (ds *MockProjectDataSource) Create(ctx context.Context, project entities.Pr
|
|||||||
ClientID: project.ClientID,
|
ClientID: project.ClientID,
|
||||||
}
|
}
|
||||||
|
|
||||||
ds.store[id] = &newProject
|
ds.Store[id] = &newProject
|
||||||
|
|
||||||
return E.Right[error](newProject)
|
return E.Right[error](newProject)
|
||||||
}
|
}
|
||||||
@ -50,7 +50,7 @@ func (ds *MockProjectDataSource) FindByID(ctx context.Context, id string) E.Eith
|
|||||||
defer ds.mu.RUnlock()
|
defer ds.mu.RUnlock()
|
||||||
|
|
||||||
return F.Pipe2(
|
return F.Pipe2(
|
||||||
O.FromNillable(ds.store[id]),
|
O.FromNillable(ds.Store[id]),
|
||||||
E.FromOption[*entities.Project](F.Constant(fmt.Errorf("project with ID %s not found", id))),
|
E.FromOption[*entities.Project](F.Constant(fmt.Errorf("project with ID %s not found", id))),
|
||||||
E.Chain(impl.TryDereference[entities.Project]),
|
E.Chain(impl.TryDereference[entities.Project]),
|
||||||
)
|
)
|
||||||
@ -61,7 +61,7 @@ func (ds *MockProjectDataSource) Update(ctx context.Context, project entities.Pr
|
|||||||
ds.mu.Lock()
|
ds.mu.Lock()
|
||||||
defer ds.mu.Unlock()
|
defer ds.mu.Unlock()
|
||||||
|
|
||||||
existing, found := ds.store[project.ID]
|
existing, found := ds.Store[project.ID]
|
||||||
if !found {
|
if !found {
|
||||||
return E.Left[entities.Project](fmt.Errorf("project with ID %s not found", project.ID))
|
return E.Left[entities.Project](fmt.Errorf("project with ID %s not found", project.ID))
|
||||||
}
|
}
|
||||||
@ -87,12 +87,12 @@ func (ds *MockProjectDataSource) Delete(ctx context.Context, id string) E.Either
|
|||||||
ds.mu.Lock()
|
ds.mu.Lock()
|
||||||
defer ds.mu.Unlock()
|
defer ds.mu.Unlock()
|
||||||
|
|
||||||
existing, found := ds.store[id]
|
existing, found := ds.Store[id]
|
||||||
if !found {
|
if !found {
|
||||||
return E.Left[entities.Project](fmt.Errorf("project with ID %s not found", id))
|
return E.Left[entities.Project](fmt.Errorf("project with ID %s not found", id))
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(ds.store, id)
|
delete(ds.Store, id)
|
||||||
return E.Right[error](*existing)
|
return E.Right[error](*existing)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,8 +101,8 @@ func (ds *MockProjectDataSource) FindAll(ctx context.Context) E.Either[error, []
|
|||||||
ds.mu.RLock()
|
ds.mu.RLock()
|
||||||
defer ds.mu.RUnlock()
|
defer ds.mu.RUnlock()
|
||||||
|
|
||||||
projects := make([]entities.Project, 0, len(ds.store))
|
projects := make([]entities.Project, 0, len(ds.Store))
|
||||||
for _, project := range ds.store {
|
for _, project := range ds.Store {
|
||||||
projects = append(projects, *project)
|
projects = append(projects, *project)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,7 +115,7 @@ func (ds *MockProjectDataSource) FindByUserID(ctx context.Context, userID string
|
|||||||
defer ds.mu.RUnlock()
|
defer ds.mu.RUnlock()
|
||||||
|
|
||||||
projects := make([]entities.Project, 0)
|
projects := make([]entities.Project, 0)
|
||||||
for _, project := range ds.store {
|
for _, project := range ds.Store {
|
||||||
if project.UserID == userID {
|
if project.UserID == userID {
|
||||||
projects = append(projects, *project)
|
projects = append(projects, *project)
|
||||||
}
|
}
|
||||||
@ -123,3 +123,9 @@ func (ds *MockProjectDataSource) FindByUserID(ctx context.Context, userID string
|
|||||||
|
|
||||||
return E.Right[error](projects)
|
return E.Right[error](projects)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ds *MockProjectDataSource) Clear() {
|
||||||
|
ds.mu.Lock()
|
||||||
|
defer ds.mu.Unlock()
|
||||||
|
ds.Store = make(map[string]*entities.Project)
|
||||||
|
}
|
@ -14,13 +14,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type MockProjectTaskDataSource struct {
|
type MockProjectTaskDataSource struct {
|
||||||
store map[string]*entities.ProjectTask
|
Store map[string]*entities.ProjectTask
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMockProjectTaskDataSource() data.ProjectTaskDataSource {
|
func NewMockProjectTaskDataSource() data.ProjectTaskDataSource {
|
||||||
return &MockProjectTaskDataSource{
|
return &MockProjectTaskDataSource{
|
||||||
store: make(map[string]*entities.ProjectTask),
|
Store: make(map[string]*entities.ProjectTask),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ func (ds *MockProjectTaskDataSource) Create(ctx context.Context, task entities.P
|
|||||||
Description: task.Description,
|
Description: task.Description,
|
||||||
}
|
}
|
||||||
|
|
||||||
ds.store[id] = &newTask
|
ds.Store[id] = &newTask
|
||||||
|
|
||||||
return E.Right[error](newTask)
|
return E.Right[error](newTask)
|
||||||
}
|
}
|
||||||
@ -48,7 +48,7 @@ func (ds *MockProjectTaskDataSource) FindByID(ctx context.Context, id string) E.
|
|||||||
defer ds.mu.RUnlock()
|
defer ds.mu.RUnlock()
|
||||||
|
|
||||||
return F.Pipe2(
|
return F.Pipe2(
|
||||||
O.FromNillable(ds.store[id]),
|
O.FromNillable(ds.Store[id]),
|
||||||
E.FromOption[*entities.ProjectTask](F.Constant(fmt.Errorf("project task with ID %s not found", id))),
|
E.FromOption[*entities.ProjectTask](F.Constant(fmt.Errorf("project task with ID %s not found", id))),
|
||||||
E.Chain(impl.TryDereference[entities.ProjectTask]),
|
E.Chain(impl.TryDereference[entities.ProjectTask]),
|
||||||
)
|
)
|
||||||
@ -59,7 +59,7 @@ func (ds *MockProjectTaskDataSource) Update(ctx context.Context, task entities.P
|
|||||||
ds.mu.Lock()
|
ds.mu.Lock()
|
||||||
defer ds.mu.Unlock()
|
defer ds.mu.Unlock()
|
||||||
|
|
||||||
existing, found := ds.store[task.ID]
|
existing, found := ds.Store[task.ID]
|
||||||
if !found {
|
if !found {
|
||||||
return E.Left[entities.ProjectTask](fmt.Errorf("project task with ID %s not found", task.ID))
|
return E.Left[entities.ProjectTask](fmt.Errorf("project task with ID %s not found", task.ID))
|
||||||
}
|
}
|
||||||
@ -82,12 +82,12 @@ func (ds *MockProjectTaskDataSource) Delete(ctx context.Context, id string) E.Ei
|
|||||||
ds.mu.Lock()
|
ds.mu.Lock()
|
||||||
defer ds.mu.Unlock()
|
defer ds.mu.Unlock()
|
||||||
|
|
||||||
existing, found := ds.store[id]
|
existing, found := ds.Store[id]
|
||||||
if !found {
|
if !found {
|
||||||
return E.Left[entities.ProjectTask](fmt.Errorf("project task with ID %s not found", id))
|
return E.Left[entities.ProjectTask](fmt.Errorf("project task with ID %s not found", id))
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(ds.store, id)
|
delete(ds.Store, id)
|
||||||
return E.Right[error](*existing)
|
return E.Right[error](*existing)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,8 +96,8 @@ func (ds *MockProjectTaskDataSource) FindAll(ctx context.Context) E.Either[error
|
|||||||
ds.mu.RLock()
|
ds.mu.RLock()
|
||||||
defer ds.mu.RUnlock()
|
defer ds.mu.RUnlock()
|
||||||
|
|
||||||
tasks := make([]entities.ProjectTask, 0, len(ds.store))
|
tasks := make([]entities.ProjectTask, 0, len(ds.Store))
|
||||||
for _, task := range ds.store {
|
for _, task := range ds.Store {
|
||||||
tasks = append(tasks, *task)
|
tasks = append(tasks, *task)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +110,7 @@ func (ds *MockProjectTaskDataSource) FindByProjectID(ctx context.Context, projec
|
|||||||
defer ds.mu.RUnlock()
|
defer ds.mu.RUnlock()
|
||||||
|
|
||||||
tasks := make([]entities.ProjectTask, 0)
|
tasks := make([]entities.ProjectTask, 0)
|
||||||
for _, task := range ds.store {
|
for _, task := range ds.Store {
|
||||||
if task.ProjectID == projectID {
|
if task.ProjectID == projectID {
|
||||||
tasks = append(tasks, *task)
|
tasks = append(tasks, *task)
|
||||||
}
|
}
|
||||||
@ -118,3 +118,9 @@ func (ds *MockProjectTaskDataSource) FindByProjectID(ctx context.Context, projec
|
|||||||
|
|
||||||
return E.Right[error](tasks)
|
return E.Right[error](tasks)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ds *MockProjectTaskDataSource) Clear() {
|
||||||
|
ds.mu.Lock()
|
||||||
|
defer ds.mu.Unlock()
|
||||||
|
ds.Store = make(map[string]*entities.ProjectTask)
|
||||||
|
}
|
@ -3,7 +3,6 @@ package mocks
|
|||||||
import (
|
import (
|
||||||
impl "actatempus_backend/internal/infrastructure/data"
|
impl "actatempus_backend/internal/infrastructure/data"
|
||||||
|
|
||||||
"actatempus_backend/internal/domain/data"
|
|
||||||
"actatempus_backend/internal/domain/entities"
|
"actatempus_backend/internal/domain/entities"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -15,13 +14,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type MockTimeEntryDataSource struct {
|
type MockTimeEntryDataSource struct {
|
||||||
store map[string]*entities.TimeEntry
|
Store map[string]*entities.TimeEntry
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMockTimeEntryDataSource() data.TimeEntryDataSource {
|
func NewMockTimeEntryDataSource() *MockTimeEntryDataSource {
|
||||||
return &MockTimeEntryDataSource{
|
return &MockTimeEntryDataSource{
|
||||||
store: make(map[string]*entities.TimeEntry),
|
Store: make(map[string]*entities.TimeEntry),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,7 +39,7 @@ func (ds *MockTimeEntryDataSource) Create(ctx context.Context, entry entities.Ti
|
|||||||
ProjectID: entry.ProjectID,
|
ProjectID: entry.ProjectID,
|
||||||
}
|
}
|
||||||
|
|
||||||
ds.store[id] = &newEntry
|
ds.Store[id] = &newEntry
|
||||||
|
|
||||||
return E.Right[error](newEntry)
|
return E.Right[error](newEntry)
|
||||||
}
|
}
|
||||||
@ -51,7 +50,7 @@ func (ds *MockTimeEntryDataSource) FindByID(ctx context.Context, id string) E.Ei
|
|||||||
defer ds.mu.RUnlock()
|
defer ds.mu.RUnlock()
|
||||||
|
|
||||||
return F.Pipe2(
|
return F.Pipe2(
|
||||||
O.FromNillable(ds.store[id]),
|
O.FromNillable(ds.Store[id]),
|
||||||
E.FromOption[*entities.TimeEntry](F.Constant(fmt.Errorf("time entry with ID %s not found", id))),
|
E.FromOption[*entities.TimeEntry](F.Constant(fmt.Errorf("time entry with ID %s not found", id))),
|
||||||
E.Chain(impl.TryDereference[entities.TimeEntry]),
|
E.Chain(impl.TryDereference[entities.TimeEntry]),
|
||||||
)
|
)
|
||||||
@ -62,7 +61,7 @@ func (ds *MockTimeEntryDataSource) Update(ctx context.Context, entry entities.Ti
|
|||||||
ds.mu.Lock()
|
ds.mu.Lock()
|
||||||
defer ds.mu.Unlock()
|
defer ds.mu.Unlock()
|
||||||
|
|
||||||
existing, found := ds.store[entry.ID]
|
existing, found := ds.Store[entry.ID]
|
||||||
if !found {
|
if !found {
|
||||||
return E.Left[entities.TimeEntry](fmt.Errorf("time entry with ID %s not found", entry.ID))
|
return E.Left[entities.TimeEntry](fmt.Errorf("time entry with ID %s not found", entry.ID))
|
||||||
}
|
}
|
||||||
@ -91,12 +90,12 @@ func (ds *MockTimeEntryDataSource) Delete(ctx context.Context, id string) E.Eith
|
|||||||
ds.mu.Lock()
|
ds.mu.Lock()
|
||||||
defer ds.mu.Unlock()
|
defer ds.mu.Unlock()
|
||||||
|
|
||||||
existing, found := ds.store[id]
|
existing, found := ds.Store[id]
|
||||||
if !found {
|
if !found {
|
||||||
return E.Left[entities.TimeEntry](fmt.Errorf("time entry with ID %s not found", id))
|
return E.Left[entities.TimeEntry](fmt.Errorf("time entry with ID %s not found", id))
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(ds.store, id)
|
delete(ds.Store, id)
|
||||||
return E.Right[error](*existing)
|
return E.Right[error](*existing)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,8 +104,8 @@ func (ds *MockTimeEntryDataSource) FindAll(ctx context.Context) E.Either[error,
|
|||||||
ds.mu.RLock()
|
ds.mu.RLock()
|
||||||
defer ds.mu.RUnlock()
|
defer ds.mu.RUnlock()
|
||||||
|
|
||||||
entries := make([]entities.TimeEntry, 0, len(ds.store))
|
entries := make([]entities.TimeEntry, 0, len(ds.Store))
|
||||||
for _, entry := range ds.store {
|
for _, entry := range ds.Store {
|
||||||
entries = append(entries, *entry)
|
entries = append(entries, *entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +118,7 @@ func (ds *MockTimeEntryDataSource) FindByUserID(ctx context.Context, userID stri
|
|||||||
defer ds.mu.RUnlock()
|
defer ds.mu.RUnlock()
|
||||||
|
|
||||||
entries := make([]entities.TimeEntry, 0)
|
entries := make([]entities.TimeEntry, 0)
|
||||||
for _, entry := range ds.store {
|
for _, entry := range ds.Store {
|
||||||
if entry.UserID == userID {
|
if entry.UserID == userID {
|
||||||
entries = append(entries, *entry)
|
entries = append(entries, *entry)
|
||||||
}
|
}
|
||||||
@ -134,7 +133,7 @@ func (ds *MockTimeEntryDataSource) FindByProjectID(ctx context.Context, projectI
|
|||||||
defer ds.mu.RUnlock()
|
defer ds.mu.RUnlock()
|
||||||
|
|
||||||
entries := make([]entities.TimeEntry, 0)
|
entries := make([]entities.TimeEntry, 0)
|
||||||
for _, entry := range ds.store {
|
for _, entry := range ds.Store {
|
||||||
if entry.ProjectID == projectID {
|
if entry.ProjectID == projectID {
|
||||||
entries = append(entries, *entry)
|
entries = append(entries, *entry)
|
||||||
}
|
}
|
||||||
@ -142,3 +141,9 @@ func (ds *MockTimeEntryDataSource) FindByProjectID(ctx context.Context, projectI
|
|||||||
|
|
||||||
return E.Right[error](entries)
|
return E.Right[error](entries)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ds *MockTimeEntryDataSource) Clear() {
|
||||||
|
ds.mu.Lock()
|
||||||
|
defer ds.mu.Unlock()
|
||||||
|
ds.Store = make(map[string]*entities.TimeEntry)
|
||||||
|
}
|
@ -1,7 +1,6 @@
|
|||||||
package mocks
|
package mocks
|
||||||
|
|
||||||
import (
|
import (
|
||||||
domain "actatempus_backend/internal/domain/data"
|
|
||||||
"actatempus_backend/internal/domain/entities"
|
"actatempus_backend/internal/domain/entities"
|
||||||
impl "actatempus_backend/internal/infrastructure/data"
|
impl "actatempus_backend/internal/infrastructure/data"
|
||||||
"context"
|
"context"
|
||||||
@ -14,13 +13,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type MockUserDataSource struct {
|
type MockUserDataSource struct {
|
||||||
store map[string]*entities.User
|
Store map[string]*entities.User
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMockUserDataSource() domain.UserDataSource {
|
func NewMockUserDataSource() *MockUserDataSource {
|
||||||
return &MockUserDataSource{
|
return &MockUserDataSource{
|
||||||
store: make(map[string]*entities.User),
|
Store: make(map[string]*entities.User),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +35,7 @@ func (ds *MockUserDataSource) Create(ctx context.Context, user entities.UserCrea
|
|||||||
Password: impl.GenerateSecureHash(user.Password),
|
Password: impl.GenerateSecureHash(user.Password),
|
||||||
}
|
}
|
||||||
|
|
||||||
ds.store[id] = &newUser
|
ds.Store[id] = &newUser
|
||||||
|
|
||||||
return E.Right[error](newUser)
|
return E.Right[error](newUser)
|
||||||
}
|
}
|
||||||
@ -45,7 +44,7 @@ func (ds *MockUserDataSource) FindByID(ctx context.Context, id string) E.Either[
|
|||||||
ds.mu.RLock()
|
ds.mu.RLock()
|
||||||
defer ds.mu.RUnlock()
|
defer ds.mu.RUnlock()
|
||||||
return F.Pipe2(
|
return F.Pipe2(
|
||||||
O.FromNillable(ds.store[id]),
|
O.FromNillable(ds.Store[id]),
|
||||||
E.FromOption[*entities.User](F.Constant(fmt.Errorf("user with ID %s not found", id))),
|
E.FromOption[*entities.User](F.Constant(fmt.Errorf("user with ID %s not found", id))),
|
||||||
E.Chain(
|
E.Chain(
|
||||||
impl.TryDereference[entities.User],
|
impl.TryDereference[entities.User],
|
||||||
@ -57,7 +56,7 @@ func (ds *MockUserDataSource) FindByEmail(ctx context.Context, email string) E.E
|
|||||||
ds.mu.RLock()
|
ds.mu.RLock()
|
||||||
defer ds.mu.RUnlock()
|
defer ds.mu.RUnlock()
|
||||||
|
|
||||||
for _, user := range ds.store {
|
for _, user := range ds.Store {
|
||||||
if user.Email == email {
|
if user.Email == email {
|
||||||
return E.Right[error](*user)
|
return E.Right[error](*user)
|
||||||
}
|
}
|
||||||
@ -69,7 +68,7 @@ func (ds *MockUserDataSource) Update(ctx context.Context, user entities.UserUpda
|
|||||||
ds.mu.Lock()
|
ds.mu.Lock()
|
||||||
defer ds.mu.Unlock()
|
defer ds.mu.Unlock()
|
||||||
|
|
||||||
existing, found := ds.store[user.ID]
|
existing, found := ds.Store[user.ID]
|
||||||
if !found {
|
if !found {
|
||||||
return E.Left[entities.User](fmt.Errorf("user with ID %s not found", user.ID))
|
return E.Left[entities.User](fmt.Errorf("user with ID %s not found", user.ID))
|
||||||
}
|
}
|
||||||
@ -91,12 +90,12 @@ func (ds *MockUserDataSource) Delete(ctx context.Context, id string) E.Either[er
|
|||||||
ds.mu.Lock()
|
ds.mu.Lock()
|
||||||
defer ds.mu.Unlock()
|
defer ds.mu.Unlock()
|
||||||
|
|
||||||
existing, found := ds.store[id]
|
existing, found := ds.Store[id]
|
||||||
if !found {
|
if !found {
|
||||||
return E.Left[entities.User](fmt.Errorf("user with ID %s not found", id))
|
return E.Left[entities.User](fmt.Errorf("user with ID %s not found", id))
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(ds.store, id)
|
delete(ds.Store, id)
|
||||||
return E.Right[error](*existing)
|
return E.Right[error](*existing)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,10 +103,16 @@ func (ds *MockUserDataSource) FindAll(ctx context.Context) E.Either[error, []ent
|
|||||||
ds.mu.RLock()
|
ds.mu.RLock()
|
||||||
defer ds.mu.RUnlock()
|
defer ds.mu.RUnlock()
|
||||||
|
|
||||||
users := make([]entities.User, 0, len(ds.store))
|
users := make([]entities.User, 0, len(ds.Store))
|
||||||
for _, user := range ds.store {
|
for _, user := range ds.Store {
|
||||||
users = append(users, *user)
|
users = append(users, *user)
|
||||||
}
|
}
|
||||||
|
|
||||||
return E.Right[error](users)
|
return E.Right[error](users)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ds *MockUserDataSource) Clear() {
|
||||||
|
ds.mu.Lock()
|
||||||
|
defer ds.mu.Unlock()
|
||||||
|
ds.Store = make(map[string]*entities.User)
|
||||||
|
}
|
6
backend-go/tests/services/helper.go
Normal file
6
backend-go/tests/services/helper.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package services_test
|
||||||
|
|
||||||
|
// StringPtr returns a pointer to the string value passed in
|
||||||
|
func StringPtr(s string) *string {
|
||||||
|
return &s
|
||||||
|
}
|
171
backend-go/tests/services/user_service_test.go
Normal file
171
backend-go/tests/services/user_service_test.go
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
package services_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"actatempus_backend/internal/application/repository"
|
||||||
|
"actatempus_backend/internal/application/services"
|
||||||
|
"actatempus_backend/internal/application/services/dto"
|
||||||
|
"actatempus_backend/internal/domain/entities"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
|
"actatempus_backend/tests/mocks"
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
E "github.com/IBM/fp-go/either"
|
||||||
|
F "github.com/IBM/fp-go/function"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestUserService(t *testing.T) {
|
||||||
|
// Setup
|
||||||
|
gin.SetMode(gin.TestMode)
|
||||||
|
//mockAuthRepo := repository.NewInMemoryAuthRepositoryImpl("secret")
|
||||||
|
mockAuthRepo := mocks.NewMockAuthRepository()
|
||||||
|
userDS := mocks.NewMockUserDataSource()
|
||||||
|
userRepo := repository.NewUserRepository(userDS)
|
||||||
|
userService := services.NewUserService(mockAuthRepo, userRepo)
|
||||||
|
|
||||||
|
router := gin.Default()
|
||||||
|
router.RedirectTrailingSlash = false
|
||||||
|
api := router.Group("/api/users")
|
||||||
|
userService.RegisterRoutes(api)
|
||||||
|
|
||||||
|
t.Run("CreateUser - Success", func(t *testing.T) {
|
||||||
|
userCreateDTO := dto.UserCreateDTO{
|
||||||
|
Name: "John Doe",
|
||||||
|
Email: "john.doe@example.com",
|
||||||
|
Password: "password123",
|
||||||
|
}
|
||||||
|
|
||||||
|
body, _ := json.Marshal(userCreateDTO)
|
||||||
|
req := httptest.NewRequest(http.MethodPost, "/api/users/", bytes.NewBuffer(body))
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
rec := httptest.NewRecorder()
|
||||||
|
|
||||||
|
router.ServeHTTP(rec, req)
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusCreated, rec.Code)
|
||||||
|
var response dto.UserDTO
|
||||||
|
err := json.Unmarshal(rec.Body.Bytes(), &response)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, userCreateDTO.Name, response.Name)
|
||||||
|
assert.Equal(t, userCreateDTO.Email, response.Email)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("GetUserByID - Success", func(t *testing.T) {
|
||||||
|
// Prepopulate mock data
|
||||||
|
user := entities.UserCreate{
|
||||||
|
Name: "John Doe",
|
||||||
|
Email: "john.doe@example.com",
|
||||||
|
Password: "hashed_password",
|
||||||
|
}
|
||||||
|
|
||||||
|
newUser, _ := E.Unwrap(F.Pipe1(
|
||||||
|
user,
|
||||||
|
userRepo.Create(context.Background()),
|
||||||
|
))
|
||||||
|
|
||||||
|
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/api/users/%s", newUser.ID), nil)
|
||||||
|
req.Header.Set("Cookie", "session_token=fake_test_token")
|
||||||
|
rec := httptest.NewRecorder()
|
||||||
|
|
||||||
|
router.ServeHTTP(rec, req)
|
||||||
|
print(rec.Body.String())
|
||||||
|
assert.Equal(t, http.StatusOK, rec.Code)
|
||||||
|
var response dto.UserDTO
|
||||||
|
err := json.Unmarshal(rec.Body.Bytes(), &response)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, user.Name, response.Name)
|
||||||
|
assert.Equal(t, user.Email, response.Email)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("GetAllUsers - Success", func(t *testing.T) {
|
||||||
|
userDS.Clear()
|
||||||
|
// Prepopulate mock data
|
||||||
|
userRepo.Create(context.Background())(entities.UserCreate{
|
||||||
|
Name: "John Doe",
|
||||||
|
Email: "john.doe@example.com",
|
||||||
|
Password: "hashed_password",
|
||||||
|
})
|
||||||
|
userRepo.Create(context.Background())(entities.UserCreate{
|
||||||
|
Name: "Jane Smith",
|
||||||
|
Email: "jane.smith@example.com",
|
||||||
|
Password: "hashed_password",
|
||||||
|
})
|
||||||
|
|
||||||
|
req := httptest.NewRequest(http.MethodGet, "/api/users/", nil)
|
||||||
|
req.Header.Set("Cookie", "session_token=fake_test_token")
|
||||||
|
rec := httptest.NewRecorder()
|
||||||
|
|
||||||
|
router.ServeHTTP(rec, req)
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusOK, rec.Code)
|
||||||
|
var response []dto.UserDTO
|
||||||
|
err := json.Unmarshal(rec.Body.Bytes(), &response)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, response, 2)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("UpdateUser - Success", func(t *testing.T) {
|
||||||
|
// Prepopulate mock data
|
||||||
|
|
||||||
|
newUser, _ := E.Unwrap(F.Pipe1(
|
||||||
|
entities.UserCreate{
|
||||||
|
Name: "John Doe",
|
||||||
|
Email: "john.doe@example.com",
|
||||||
|
Password: "hashed_password",
|
||||||
|
},
|
||||||
|
userRepo.Create(context.Background()),
|
||||||
|
))
|
||||||
|
|
||||||
|
userUpdateDTO := dto.UserUpdateDTO{
|
||||||
|
Name: StringPtr("John Updated"),
|
||||||
|
Email: StringPtr("john.updated@example.com"),
|
||||||
|
}
|
||||||
|
|
||||||
|
body, _ := json.Marshal(userUpdateDTO)
|
||||||
|
req := httptest.NewRequest(http.MethodPut, fmt.Sprintf("/api/users/%s", newUser.ID), bytes.NewBuffer(body))
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
req.Header.Set("Cookie", "session_token=fake_test_token")
|
||||||
|
rec := httptest.NewRecorder()
|
||||||
|
|
||||||
|
router.ServeHTTP(rec, req)
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusOK, rec.Code)
|
||||||
|
var response dto.UserDTO
|
||||||
|
err := json.Unmarshal(rec.Body.Bytes(), &response)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, *userUpdateDTO.Name, response.Name)
|
||||||
|
assert.Equal(t, *userUpdateDTO.Email, response.Email)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("DeleteUser - Success", func(t *testing.T) {
|
||||||
|
// Prepopulate mock data
|
||||||
|
newUser, _ := E.Unwrap(F.Pipe1(
|
||||||
|
entities.UserCreate{
|
||||||
|
Name: "John Doe",
|
||||||
|
Email: "john.doe@example.com",
|
||||||
|
Password: "hashed_password",
|
||||||
|
},
|
||||||
|
userRepo.Create(context.Background()),
|
||||||
|
))
|
||||||
|
|
||||||
|
req := httptest.NewRequest(http.MethodDelete, fmt.Sprintf("/api/users/%s", newUser.ID), nil)
|
||||||
|
req.Header.Set("Cookie", "session_token=fake_test_token")
|
||||||
|
rec := httptest.NewRecorder()
|
||||||
|
|
||||||
|
router.ServeHTTP(rec, req)
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusOK, rec.Code)
|
||||||
|
var response dto.UserDTO
|
||||||
|
err := json.Unmarshal(rec.Body.Bytes(), &response)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "John Doe", response.Name)
|
||||||
|
})
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user