This commit is contained in:
Alex
2025-03-11 20:52:54 +01:00
parent 9d2b33f832
commit 073d353764
5 changed files with 196 additions and 94 deletions

View File

@@ -45,9 +45,11 @@ type loginInput struct {
} }
var ( var (
Uc *UserController Uc *UserController
Mc *MembershipController Mc *MembershipController
Cc *ContactController Cc *ContactController
AdminCookie *http.Cookie
MemberCookie *http.Cookie
) )
func TestMain(t *testing.T) { func TestMain(t *testing.T) {
@@ -85,7 +87,8 @@ func TestMain(t *testing.T) {
log.Fatalf("Error setting environment variable: %v", err) log.Fatalf("Error setting environment variable: %v", err)
} }
config.LoadConfig() config.LoadConfig()
if err := database.Open("test.db", config.Recipients.AdminEmail); err != nil { db, err := database.Open("test.db", config.Recipients.AdminEmail)
if err != nil {
log.Fatalf("Failed to create DB: %#v", err) log.Fatalf("Failed to create DB: %#v", err)
} }
utils.SMTPStart(Host, Port) utils.SMTPStart(Host, Port)
@@ -101,13 +104,12 @@ func TestMain(t *testing.T) {
membershipService := &services.MembershipService{Repo: membershipRepo, SubscriptionRepo: subscriptionRepo} membershipService := &services.MembershipService{Repo: membershipRepo, SubscriptionRepo: subscriptionRepo}
var licenceRepo repositories.LicenceInterface = &repositories.LicenceRepository{} var licenceRepo repositories.LicenceInterface = &repositories.LicenceRepository{}
var userRepo repositories.UserRepositoryInterface = &repositories.UserRepository{} userService := &services.UserService{DB: db, Licences: licenceRepo}
userService := &services.UserService{Repo: userRepo, Licences: licenceRepo}
licenceService := &services.LicenceService{Repo: licenceRepo} licenceService := &services.LicenceService{Repo: licenceRepo}
Uc = &UserController{Service: userService, LicenceService: licenceService, EmailService: emailService, ConsentService: consentService, BankAccountService: bankAccountService, MembershipService: membershipService} Uc = &UserController{Service: userService, LicenceService: licenceService, EmailService: emailService, ConsentService: consentService, BankAccountService: bankAccountService, MembershipService: membershipService}
Mc = &MembershipController{UserController: &MockUserController{}, Service: *membershipService} Mc = &MembershipController{UserService: userService, Service: membershipService}
Cc = &ContactController{EmailService: emailService} Cc = &ContactController{EmailService: emailService}
if err := initSubscriptionPlans(); err != nil { if err := initSubscriptionPlans(); err != nil {
@@ -132,7 +134,7 @@ func TestMain(t *testing.T) {
} }
admin.SetPassword("securepassword") admin.SetPassword("securepassword")
database.DB.Create(&admin) database.DB.Create(&admin)
validation.SetupValidators() validation.SetupValidators(db)
t.Run("userController", func(t *testing.T) { t.Run("userController", func(t *testing.T) {
testUserController(t) testUserController(t)
}) })

View File

@@ -48,7 +48,7 @@ func TestGetAllCategories_Success(t *testing.T) {
service := &services.LicenceService{Repo: mockRepo} service := &services.LicenceService{Repo: mockRepo}
// Create controller with service // Create controller with service
lc := &LicenceController{Service: *service} lc := &LicenceController{Service: service}
// Setup router and request // Setup router and request
router := gin.Default() router := gin.Default()
@@ -76,7 +76,7 @@ func TestGetAllCategories_Error(t *testing.T) {
service := &services.LicenceService{Repo: mockRepo} service := &services.LicenceService{Repo: mockRepo}
// Create controller with service // Create controller with service
lc := &LicenceController{Service: *service} lc := &LicenceController{Service: service}
// Setup router and request // Setup router and request
router := gin.Default() router := gin.Default()

View File

@@ -6,7 +6,6 @@ import (
"net/http/httptest" "net/http/httptest"
"testing" "testing"
"GoMembership/internal/constants"
"GoMembership/internal/database" "GoMembership/internal/database"
"GoMembership/internal/models" "GoMembership/internal/models"
"GoMembership/pkg/logger" "GoMembership/pkg/logger"
@@ -15,6 +14,7 @@ import (
) )
type RegisterSubscriptionTest struct { type RegisterSubscriptionTest struct {
SetupCookie func(r *http.Request)
WantDBData map[string]interface{} WantDBData map[string]interface{}
Input string Input string
Name string Name string
@@ -23,6 +23,7 @@ type RegisterSubscriptionTest struct {
} }
type UpdateSubscriptionTest struct { type UpdateSubscriptionTest struct {
SetupCookie func(r *http.Request)
WantDBData map[string]interface{} WantDBData map[string]interface{}
Input string Input string
Name string Name string
@@ -31,6 +32,7 @@ type UpdateSubscriptionTest struct {
} }
type DeleteSubscriptionTest struct { type DeleteSubscriptionTest struct {
SetupCookie func(r *http.Request)
WantDBData map[string]interface{} WantDBData map[string]interface{}
Input string Input string
Name string Name string
@@ -38,29 +40,8 @@ type DeleteSubscriptionTest struct {
Assert bool Assert bool
} }
type MockUserController struct {
UserController // Embed the UserController
}
func (m *MockUserController) ExtractUserFromContext(c *gin.Context) (*models.User, error) {
return &models.User{
ID: 1,
FirstName: "Admin",
LastName: "User",
Email: "admin@test.com",
RoleID: constants.Roles.Admin,
}, nil
}
func setupMockAuth() {
// Create and assign the mock controller
mockController := &MockUserController{}
Mc.UserController = mockController
}
func testMembershipController(t *testing.T) { func testMembershipController(t *testing.T) {
setupMockAuth()
tests := getSubscriptionRegistrationData() tests := getSubscriptionRegistrationData()
for _, tt := range tests { for _, tt := range tests {
logger.Error.Print("==============================================================") logger.Error.Print("==============================================================")
@@ -101,6 +82,7 @@ func (rt *RegisterSubscriptionTest) SetupContext() (*gin.Context, *httptest.Resp
} }
func (rt *RegisterSubscriptionTest) RunHandler(c *gin.Context, router *gin.Engine) { func (rt *RegisterSubscriptionTest) RunHandler(c *gin.Context, router *gin.Engine) {
rt.SetupCookie(c.Request)
Mc.RegisterSubscription(c) Mc.RegisterSubscription(c)
} }
@@ -131,6 +113,7 @@ func (ut *UpdateSubscriptionTest) SetupContext() (*gin.Context, *httptest.Respon
} }
func (ut *UpdateSubscriptionTest) RunHandler(c *gin.Context, router *gin.Engine) { func (ut *UpdateSubscriptionTest) RunHandler(c *gin.Context, router *gin.Engine) {
ut.SetupCookie(c.Request)
Mc.UpdateHandler(c) Mc.UpdateHandler(c)
} }
@@ -150,6 +133,7 @@ func (dt *DeleteSubscriptionTest) SetupContext() (*gin.Context, *httptest.Respon
} }
func (dt *DeleteSubscriptionTest) RunHandler(c *gin.Context, router *gin.Engine) { func (dt *DeleteSubscriptionTest) RunHandler(c *gin.Context, router *gin.Engine) {
dt.SetupCookie(c.Request)
Mc.DeleteSubscription(c) Mc.DeleteSubscription(c)
} }
@@ -183,6 +167,9 @@ func customizeSubscription(customize func(MembershipData) MembershipData) Member
func getSubscriptionRegistrationData() []RegisterSubscriptionTest { func getSubscriptionRegistrationData() []RegisterSubscriptionTest {
return []RegisterSubscriptionTest{ return []RegisterSubscriptionTest{
{ {
SetupCookie: func(req *http.Request) {
req.AddCookie(AdminCookie)
},
Name: "Missing details should fail", Name: "Missing details should fail",
WantResponse: http.StatusBadRequest, WantResponse: http.StatusBadRequest,
WantDBData: map[string]interface{}{"name": "Just a Subscription"}, WantDBData: map[string]interface{}{"name": "Just a Subscription"},
@@ -194,6 +181,9 @@ func getSubscriptionRegistrationData() []RegisterSubscriptionTest {
})), })),
}, },
{ {
SetupCookie: func(req *http.Request) {
req.AddCookie(AdminCookie)
},
Name: "Missing model name should fail", Name: "Missing model name should fail",
WantResponse: http.StatusBadRequest, WantResponse: http.StatusBadRequest,
WantDBData: map[string]interface{}{"name": ""}, WantDBData: map[string]interface{}{"name": ""},
@@ -205,6 +195,9 @@ func getSubscriptionRegistrationData() []RegisterSubscriptionTest {
})), })),
}, },
{ {
SetupCookie: func(req *http.Request) {
req.AddCookie(AdminCookie)
},
Name: "Negative monthly fee should fail", Name: "Negative monthly fee should fail",
WantResponse: http.StatusBadRequest, WantResponse: http.StatusBadRequest,
WantDBData: map[string]interface{}{"name": "Premium"}, WantDBData: map[string]interface{}{"name": "Premium"},
@@ -215,6 +208,9 @@ func getSubscriptionRegistrationData() []RegisterSubscriptionTest {
})), })),
}, },
{ {
SetupCookie: func(req *http.Request) {
req.AddCookie(AdminCookie)
},
Name: "Negative hourly rate should fail", Name: "Negative hourly rate should fail",
WantResponse: http.StatusBadRequest, WantResponse: http.StatusBadRequest,
WantDBData: map[string]interface{}{"name": "Premium"}, WantDBData: map[string]interface{}{"name": "Premium"},
@@ -225,6 +221,25 @@ func getSubscriptionRegistrationData() []RegisterSubscriptionTest {
})), })),
}, },
{ {
SetupCookie: func(req *http.Request) {
req.AddCookie(MemberCookie)
},
Name: "correct entry but not authorized",
WantResponse: http.StatusUnauthorized,
WantDBData: map[string]interface{}{"name": "Premium"},
Assert: false,
Input: GenerateInputJSON(
customizeSubscription(func(subscription MembershipData) MembershipData {
subscription.Subscription.Conditions = "Some Condition"
subscription.Subscription.IncludedPerYear = 0
subscription.Subscription.IncludedPerMonth = 1
return subscription
})),
},
{
SetupCookie: func(req *http.Request) {
req.AddCookie(AdminCookie)
},
Name: "correct entry should pass", Name: "correct entry should pass",
WantResponse: http.StatusCreated, WantResponse: http.StatusCreated,
WantDBData: map[string]interface{}{"name": "Premium"}, WantDBData: map[string]interface{}{"name": "Premium"},
@@ -238,6 +253,9 @@ func getSubscriptionRegistrationData() []RegisterSubscriptionTest {
})), })),
}, },
{ {
SetupCookie: func(req *http.Request) {
req.AddCookie(AdminCookie)
},
Name: "Duplicate subscription name should fail", Name: "Duplicate subscription name should fail",
WantResponse: http.StatusConflict, WantResponse: http.StatusConflict,
WantDBData: map[string]interface{}{"name": "Premium"}, WantDBData: map[string]interface{}{"name": "Premium"},
@@ -250,6 +268,9 @@ func getSubscriptionRegistrationData() []RegisterSubscriptionTest {
func getSubscriptionUpdateData() []UpdateSubscriptionTest { func getSubscriptionUpdateData() []UpdateSubscriptionTest {
return []UpdateSubscriptionTest{ return []UpdateSubscriptionTest{
{ {
SetupCookie: func(req *http.Request) {
req.AddCookie(AdminCookie)
},
Name: "Modified Monthly Fee, should fail", Name: "Modified Monthly Fee, should fail",
WantResponse: http.StatusBadRequest, WantResponse: http.StatusBadRequest,
WantDBData: map[string]interface{}{"name": "Premium", "monthly_fee": "12"}, WantDBData: map[string]interface{}{"name": "Premium", "monthly_fee": "12"},
@@ -261,6 +282,9 @@ func getSubscriptionUpdateData() []UpdateSubscriptionTest {
})), })),
}, },
{ {
SetupCookie: func(req *http.Request) {
req.AddCookie(AdminCookie)
},
Name: "Missing ID, should fail", Name: "Missing ID, should fail",
WantResponse: http.StatusBadRequest, WantResponse: http.StatusBadRequest,
WantDBData: map[string]interface{}{"name": "Premium"}, WantDBData: map[string]interface{}{"name": "Premium"},
@@ -272,6 +296,9 @@ func getSubscriptionUpdateData() []UpdateSubscriptionTest {
})), })),
}, },
{ {
SetupCookie: func(req *http.Request) {
req.AddCookie(AdminCookie)
},
Name: "Modified Hourly Rate, should fail", Name: "Modified Hourly Rate, should fail",
WantResponse: http.StatusBadRequest, WantResponse: http.StatusBadRequest,
WantDBData: map[string]interface{}{"name": "Premium", "hourly_rate": "14"}, WantDBData: map[string]interface{}{"name": "Premium", "hourly_rate": "14"},
@@ -283,6 +310,9 @@ func getSubscriptionUpdateData() []UpdateSubscriptionTest {
})), })),
}, },
{ {
SetupCookie: func(req *http.Request) {
req.AddCookie(AdminCookie)
},
Name: "IncludedPerYear changed, should fail", Name: "IncludedPerYear changed, should fail",
WantResponse: http.StatusBadRequest, WantResponse: http.StatusBadRequest,
WantDBData: map[string]interface{}{"name": "Premium", "included_per_year": "0"}, WantDBData: map[string]interface{}{"name": "Premium", "included_per_year": "0"},
@@ -294,6 +324,9 @@ func getSubscriptionUpdateData() []UpdateSubscriptionTest {
})), })),
}, },
{ {
SetupCookie: func(req *http.Request) {
req.AddCookie(AdminCookie)
},
Name: "IncludedPerMonth changed, should fail", Name: "IncludedPerMonth changed, should fail",
WantResponse: http.StatusBadRequest, WantResponse: http.StatusBadRequest,
WantDBData: map[string]interface{}{"name": "Premium", "included_per_month": "1"}, WantDBData: map[string]interface{}{"name": "Premium", "included_per_month": "1"},
@@ -305,6 +338,9 @@ func getSubscriptionUpdateData() []UpdateSubscriptionTest {
})), })),
}, },
{ {
SetupCookie: func(req *http.Request) {
req.AddCookie(AdminCookie)
},
Name: "Update non-existent subscription should fail", Name: "Update non-existent subscription should fail",
WantResponse: http.StatusNotFound, WantResponse: http.StatusNotFound,
WantDBData: map[string]interface{}{"name": "NonExistentSubscription"}, WantDBData: map[string]interface{}{"name": "NonExistentSubscription"},
@@ -316,6 +352,26 @@ func getSubscriptionUpdateData() []UpdateSubscriptionTest {
})), })),
}, },
{ {
SetupCookie: func(req *http.Request) {
req.AddCookie(MemberCookie)
},
Name: "Correct Update but unauthorized",
WantResponse: http.StatusUnauthorized,
WantDBData: map[string]interface{}{"name": "Premium", "details": "Altered Details"},
Assert: false,
Input: GenerateInputJSON(
customizeSubscription(func(subscription MembershipData) MembershipData {
subscription.Subscription.Details = "Altered Details"
subscription.Subscription.Conditions = "Some Condition"
subscription.Subscription.IncludedPerYear = 0
subscription.Subscription.IncludedPerMonth = 1
return subscription
})),
},
{
SetupCookie: func(req *http.Request) {
req.AddCookie(AdminCookie)
},
Name: "Correct Update should pass", Name: "Correct Update should pass",
WantResponse: http.StatusAccepted, WantResponse: http.StatusAccepted,
WantDBData: map[string]interface{}{"name": "Premium", "details": "Altered Details"}, WantDBData: map[string]interface{}{"name": "Premium", "details": "Altered Details"},
@@ -338,10 +394,11 @@ func getSubscriptionDeleteData() []DeleteSubscriptionTest {
database.DB.Where("name = ?", "Premium").First(&premiumSub) database.DB.Where("name = ?", "Premium").First(&premiumSub)
database.DB.Where("name = ?", "Basic").First(&basicSub) database.DB.Where("name = ?", "Basic").First(&basicSub)
logger.Error.Printf("premiumSub.ID: %v", premiumSub.ID)
logger.Error.Printf("basicSub.ID: %v", basicSub.ID)
return []DeleteSubscriptionTest{ return []DeleteSubscriptionTest{
{ {
SetupCookie: func(req *http.Request) {
req.AddCookie(AdminCookie)
},
Name: "Delete non-existent subscription should fail", Name: "Delete non-existent subscription should fail",
WantResponse: http.StatusNotFound, WantResponse: http.StatusNotFound,
WantDBData: map[string]interface{}{"name": "NonExistentSubscription"}, WantDBData: map[string]interface{}{"name": "NonExistentSubscription"},
@@ -354,6 +411,9 @@ func getSubscriptionDeleteData() []DeleteSubscriptionTest {
})), })),
}, },
{ {
SetupCookie: func(req *http.Request) {
req.AddCookie(AdminCookie)
},
Name: "Delete subscription without name should fail", Name: "Delete subscription without name should fail",
WantResponse: http.StatusExpectationFailed, WantResponse: http.StatusExpectationFailed,
WantDBData: map[string]interface{}{"name": ""}, WantDBData: map[string]interface{}{"name": ""},
@@ -366,6 +426,9 @@ func getSubscriptionDeleteData() []DeleteSubscriptionTest {
})), })),
}, },
{ {
SetupCookie: func(req *http.Request) {
req.AddCookie(AdminCookie)
},
Name: "Delete subscription with users should fail", Name: "Delete subscription with users should fail",
WantResponse: http.StatusExpectationFailed, WantResponse: http.StatusExpectationFailed,
WantDBData: map[string]interface{}{"name": "Basic"}, WantDBData: map[string]interface{}{"name": "Basic"},
@@ -378,6 +441,24 @@ func getSubscriptionDeleteData() []DeleteSubscriptionTest {
})), })),
}, },
{ {
SetupCookie: func(req *http.Request) {
req.AddCookie(MemberCookie)
},
Name: "Delete valid subscription should succeed",
WantResponse: http.StatusUnauthorized,
WantDBData: map[string]interface{}{"name": "Premium"},
Assert: true,
Input: GenerateInputJSON(
customizeSubscription(func(subscription MembershipData) MembershipData {
subscription.Subscription.Name = "Premium"
subscription.Subscription.ID = premiumSub.ID
return subscription
})),
},
{
SetupCookie: func(req *http.Request) {
req.AddCookie(AdminCookie)
},
Name: "Delete valid subscription should succeed", Name: "Delete valid subscription should succeed",
WantResponse: http.StatusOK, WantResponse: http.StatusOK,
WantDBData: map[string]interface{}{"name": "Premium"}, WantDBData: map[string]interface{}{"name": "Premium"},

View File

@@ -28,8 +28,8 @@ type TestContext struct {
} }
func setupTestContext() (*TestContext, error) { func setupTestContext() (*TestContext, error) {
testEmail := "john.doe@example.com"
user, err := Uc.Service.GetUserByEmail("john.doe@example.com") user, err := Uc.Service.FromEmail(&testEmail)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -39,7 +39,7 @@ func setupTestContext() (*TestContext, error) {
user: user, user: user,
}, nil }, nil
} }
func testCreatePasswordHandler(t *testing.T, loginCookie http.Cookie, adminCookie http.Cookie) { func testCreatePasswordHandler(t *testing.T) {
invalidCookie := http.Cookie{ invalidCookie := http.Cookie{
Name: "jwt", Name: "jwt",
Value: "invalid.token.here", Value: "invalid.token.here",
@@ -58,7 +58,7 @@ func testCreatePasswordHandler(t *testing.T, loginCookie http.Cookie, adminCooki
body, _ := json.Marshal(requestBody) body, _ := json.Marshal(requestBody)
t.Run("successful password creation request from admin", func(t *testing.T) { t.Run("successful password creation request from admin", func(t *testing.T) {
req, _ := http.NewRequest("POST", "/password", bytes.NewBuffer(body)) req, _ := http.NewRequest("POST", "/password", bytes.NewBuffer(body))
req.AddCookie(&adminCookie) req.AddCookie(AdminCookie)
tc.router.ServeHTTP(tc.response, req) tc.router.ServeHTTP(tc.response, req)
logger.Error.Printf("Test results for %#v", t.Name()) logger.Error.Printf("Test results for %#v", t.Name())
assert.Equal(t, http.StatusAccepted, tc.response.Code) assert.Equal(t, http.StatusAccepted, tc.response.Code)
@@ -73,11 +73,11 @@ func testCreatePasswordHandler(t *testing.T, loginCookie http.Cookie, adminCooki
tc.response = httptest.NewRecorder() tc.response = httptest.NewRecorder()
t.Run("failed password creation request from member", func(t *testing.T) { t.Run("failed password creation request from member", func(t *testing.T) {
req, _ := http.NewRequest("POST", "/password", bytes.NewBuffer(body)) req, _ := http.NewRequest("POST", "/password", bytes.NewBuffer(body))
req.AddCookie(&loginCookie) req.AddCookie(MemberCookie)
tc.router.ServeHTTP(tc.response, req) tc.router.ServeHTTP(tc.response, req)
logger.Error.Printf("Test results for %#v", t.Name()) logger.Error.Printf("Test results for %#v", t.Name())
assert.Equal(t, http.StatusForbidden, tc.response.Code) assert.Equal(t, http.StatusUnauthorized, tc.response.Code)
assert.JSONEq(t, `{"errors":[{"field":"user.user","key":"server.error.unauthorized"}]}`, tc.response.Body.String()) assert.JSONEq(t, `{"errors":[{"field":"user.user","key":"server.error.unauthorized"}]}`, tc.response.Body.String())
err = checkEmailDelivery(tc.user, false) err = checkEmailDelivery(tc.user, false)
assert.NoError(t, err) assert.NoError(t, err)
@@ -203,6 +203,7 @@ func checkPasswordMail(message *utils.Email, user *models.User) error {
if !strings.Contains(message.Body, verification.VerificationToken) { if !strings.Contains(message.Body, verification.VerificationToken) {
return fmt.Errorf("Token(%v) has not been rendered in password mail.", verification.VerificationToken) return fmt.Errorf("Token(%v) has not been rendered in password mail.", verification.VerificationToken)
} }
if strings.Trim(tokenURL, " ") != fmt.Sprintf("%v%v/auth/password/change/%v?token=%v", config.Site.BaseURL, config.Site.FrontendPath, user.ID, verification.VerificationToken) { if strings.Trim(tokenURL, " ") != fmt.Sprintf("%v%v/auth/password/change/%v?token=%v", config.Site.BaseURL, config.Site.FrontendPath, user.ID, verification.VerificationToken) {
return fmt.Errorf("Token has not been rendered correctly in password mail: %v%v/auth/password/change/%v?token=%v", config.Site.BaseURL, config.Site.FrontendPath, user.ID, verification.VerificationToken) return fmt.Errorf("Token has not been rendered correctly in password mail: %v%v/auth/password/change/%v?token=%v", config.Site.BaseURL, config.Site.FrontendPath, user.ID, verification.VerificationToken)
} }

View File

@@ -5,6 +5,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
"log"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"net/url" "net/url"
@@ -75,8 +76,8 @@ func testUserController(t *testing.T) {
} }
// activate user for login // activate user for login
database.DB.Model(&models.User{}).Where("email = ?", "john.doe@example.com").Update("status", constants.ActiveStatus) database.DB.Model(&models.User{}).Where("email = ?", "john.doe@example.com").Update("status", constants.ActiveStatus)
loginEmail, loginCookie := testLoginHandler(t) loginEmail := testLoginHandler(t)
logoutCookie := testCurrentUserHandler(t, loginEmail, loginCookie) testCurrentUserHandler(t, loginEmail)
// creating a admin cookie // creating a admin cookie
c, w, _ := GetMockedJSONContext([]byte(`{ c, w, _ := GetMockedJSONContext([]byte(`{
@@ -91,28 +92,27 @@ func testUserController(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, "Login successful", response["message"]) assert.Equal(t, "Login successful", response["message"])
var adminCookie http.Cookie
for _, cookie := range w.Result().Cookies() { for _, cookie := range w.Result().Cookies() {
if cookie.Name == "jwt" { if cookie.Name == "jwt" {
adminCookie = *cookie AdminCookie = cookie
tokenString := adminCookie.Value tokenString := AdminCookie.Value
_, claims, err := middlewares.ExtractContentFrom(tokenString) _, claims, err := middlewares.ExtractContentFrom(tokenString)
assert.NoError(t, err, "FAiled getting cookie string") assert.NoError(t, err, "Failed getting cookie string")
jwtUserID := uint((*claims)["user_id"].(float64)) jwtUserID := uint((*claims)["user_id"].(float64))
user, err := Uc.Service.GetUserByID(jwtUserID) user, err := Uc.Service.FromID(&jwtUserID)
assert.NoError(t, err, "FAiled getting cookie string") assert.NoError(t, err, "Failed getting cookie string")
logger.Error.Printf("ADMIN USER: %#v", user) logger.Error.Printf("ADMIN USER: %#v", user)
break break
} }
} }
assert.NotEmpty(t, adminCookie) assert.NotEmpty(t, AdminCookie)
testUpdateUser(t, loginCookie, adminCookie) testUpdateUser(t)
testLogoutHandler(t, logoutCookie) testLogoutHandler(t)
testCreatePasswordHandler(t, loginCookie, adminCookie) testCreatePasswordHandler(t)
} }
func testLogoutHandler(t *testing.T, loginCookie http.Cookie) { func testLogoutHandler(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
@@ -122,7 +122,7 @@ func testLogoutHandler(t *testing.T, loginCookie http.Cookie) {
{ {
name: "Logout with valid cookie", name: "Logout with valid cookie",
setupCookie: func(req *http.Request) { setupCookie: func(req *http.Request) {
req.AddCookie(&loginCookie) req.AddCookie(MemberCookie)
}, },
expectedStatus: http.StatusOK, expectedStatus: http.StatusOK,
}, },
@@ -180,9 +180,8 @@ func testLogoutHandler(t *testing.T, loginCookie http.Cookie) {
} }
} }
func testLoginHandler(t *testing.T) (string, http.Cookie) { func testLoginHandler(t *testing.T) string {
// This test should run after the user registration test // This test should run after the user registration test
var loginCookie http.Cookie
var loginInput loginInput var loginInput loginInput
t.Run("LoginHandler", func(t *testing.T) { t.Run("LoginHandler", func(t *testing.T) {
// Test cases // Test cases
@@ -244,7 +243,7 @@ func testLoginHandler(t *testing.T) (string, http.Cookie) {
assert.Equal(t, "Login successful", response["message"]) assert.Equal(t, "Login successful", response["message"])
for _, cookie := range w.Result().Cookies() { for _, cookie := range w.Result().Cookies() {
if cookie.Name == "jwt" { if cookie.Name == "jwt" {
loginCookie = *cookie MemberCookie = cookie
// tokenString := loginCookie.Value // tokenString := loginCookie.Value
// _, claims, err := middlewares.ExtractContentFrom(tokenString) // _, claims, err := middlewares.ExtractContentFrom(tokenString)
@@ -260,7 +259,7 @@ func testLoginHandler(t *testing.T) (string, http.Cookie) {
break break
} }
} }
assert.NotEmpty(t, loginCookie) assert.NotEmpty(t, MemberCookie)
} else { } else {
assert.Contains(t, response, "errors") assert.Contains(t, response, "errors")
assert.NotEmpty(t, response["errors"]) assert.NotEmpty(t, response["errors"])
@@ -269,10 +268,10 @@ func testLoginHandler(t *testing.T) (string, http.Cookie) {
} }
}) })
return loginInput.Email, loginCookie return loginInput.Email
} }
func testCurrentUserHandler(t *testing.T, loginEmail string, loginCookie http.Cookie) http.Cookie { func testCurrentUserHandler(t *testing.T, loginEmail string) http.Cookie {
// This test should run after the user login test // This test should run after the user login test
invalidCookie := http.Cookie{ invalidCookie := http.Cookie{
Name: "jwt", Name: "jwt",
@@ -289,7 +288,7 @@ func testCurrentUserHandler(t *testing.T, loginEmail string, loginCookie http.Co
{ {
name: "With valid cookie", name: "With valid cookie",
setupCookie: func(req *http.Request) { setupCookie: func(req *http.Request) {
req.AddCookie(&loginCookie) req.AddCookie(MemberCookie)
}, },
expectedUserMail: loginEmail, expectedUserMail: loginEmail,
expectedStatus: http.StatusOK, expectedStatus: http.StatusOK,
@@ -369,7 +368,7 @@ func testCurrentUserHandler(t *testing.T, loginEmail string, loginCookie http.Co
} }
if tt.expectNewCookie { if tt.expectNewCookie {
assert.NotNil(t, newCookie, "New cookie should be set for expired token") assert.NotNil(t, newCookie, "New cookie should be set for expired token")
assert.NotEqual(t, loginCookie.Value, newCookie.Value, "Cookie value should be different") assert.NotEqual(t, MemberCookie.Value, newCookie.Value, "Cookie value should be different")
assert.True(t, newCookie.MaxAge > 0, "New cookie should not be expired") assert.True(t, newCookie.MaxAge > 0, "New cookie should not be expired")
} else { } else {
assert.Nil(t, newCookie, "No new cookie should be set for non-expired token") assert.Nil(t, newCookie, "No new cookie should be set for non-expired token")
@@ -395,7 +394,7 @@ func testCurrentUserHandler(t *testing.T, loginEmail string, loginCookie http.Co
}) })
} }
return loginCookie return *MemberCookie
} }
func validateUser(assert bool, wantDBData map[string]interface{}) error { func validateUser(assert bool, wantDBData map[string]interface{}) error {
@@ -420,6 +419,11 @@ func validateUser(assert bool, wantDBData map[string]interface{}) error {
return fmt.Errorf("Mandate reference is invalid. Expected: %s, Got: %s", expected, user.BankAccount.MandateReference) return fmt.Errorf("Mandate reference is invalid. Expected: %s, Got: %s", expected, user.BankAccount.MandateReference)
} }
// Supoorter don't get mails
if user.IsSupporter() {
return nil
}
//check for email delivery //check for email delivery
messages := utils.SMTPGetMessages() messages := utils.SMTPGetMessages()
for _, message := range messages { for _, message := range messages {
@@ -454,18 +458,18 @@ func validateUser(assert bool, wantDBData map[string]interface{}) error {
return nil return nil
} }
func testUpdateUser(t *testing.T, loginCookie http.Cookie, adminCookie http.Cookie) { func testUpdateUser(t *testing.T) {
invalidCookie := http.Cookie{ invalidCookie := http.Cookie{
Name: "jwt", Name: "jwt",
Value: "invalid.token.here", Value: "invalid.token.here",
} }
// Get the user we just created // Get the user we just created
users, err := Uc.Service.GetUsers(map[string]interface{}{"email": "john.doe@example.com"}) johnsMail := "john.doe@example.com"
if err != nil || len(*users) == 0 { user, err := Uc.Service.FromEmail(&johnsMail)
if err != nil {
t.Fatalf("Failed to get test user: %v", err) t.Fatalf("Failed to get test user: %v", err)
} }
user := (*users)[0]
if user.Licence == nil { if user.Licence == nil {
user.Licence = &models.Licence{ user.Licence = &models.Licence{
Number: "Z021AB37X13", Number: "Z021AB37X13",
@@ -485,7 +489,7 @@ func testUpdateUser(t *testing.T, loginCookie http.Cookie, adminCookie http.Cook
{ {
name: "Valid Admin Update", name: "Valid Admin Update",
setupCookie: func(req *http.Request) { setupCookie: func(req *http.Request) {
req.AddCookie(&adminCookie) req.AddCookie(AdminCookie)
}, },
updateFunc: func(u *models.User) { updateFunc: func(u *models.User) {
u.Password = "" u.Password = ""
@@ -514,7 +518,7 @@ func testUpdateUser(t *testing.T, loginCookie http.Cookie, adminCookie http.Cook
{ {
name: "Invalid Email Update", name: "Invalid Email Update",
setupCookie: func(req *http.Request) { setupCookie: func(req *http.Request) {
req.AddCookie(&loginCookie) req.AddCookie(MemberCookie)
}, },
updateFunc: func(u *models.User) { updateFunc: func(u *models.User) {
u.Password = "" u.Password = ""
@@ -532,7 +536,7 @@ func testUpdateUser(t *testing.T, loginCookie http.Cookie, adminCookie http.Cook
{ {
name: "admin may change licence number", name: "admin may change licence number",
setupCookie: func(req *http.Request) { setupCookie: func(req *http.Request) {
req.AddCookie(&adminCookie) req.AddCookie(AdminCookie)
}, },
updateFunc: func(u *models.User) { updateFunc: func(u *models.User) {
u.Password = "" u.Password = ""
@@ -546,7 +550,7 @@ func testUpdateUser(t *testing.T, loginCookie http.Cookie, adminCookie http.Cook
{ {
name: "Change phone number", name: "Change phone number",
setupCookie: func(req *http.Request) { setupCookie: func(req *http.Request) {
req.AddCookie(&loginCookie) req.AddCookie(MemberCookie)
}, },
updateFunc: func(u *models.User) { updateFunc: func(u *models.User) {
u.Password = "" u.Password = ""
@@ -560,7 +564,7 @@ func testUpdateUser(t *testing.T, loginCookie http.Cookie, adminCookie http.Cook
{ {
name: "Add category", name: "Add category",
setupCookie: func(req *http.Request) { setupCookie: func(req *http.Request) {
req.AddCookie(&loginCookie) req.AddCookie(MemberCookie)
}, },
updateFunc: func(u *models.User) { updateFunc: func(u *models.User) {
u.Password = "" u.Password = ""
@@ -578,7 +582,7 @@ func testUpdateUser(t *testing.T, loginCookie http.Cookie, adminCookie http.Cook
{ {
name: "Delete 1 and add 1 category", name: "Delete 1 and add 1 category",
setupCookie: func(req *http.Request) { setupCookie: func(req *http.Request) {
req.AddCookie(&loginCookie) req.AddCookie(MemberCookie)
}, },
updateFunc: func(u *models.User) { updateFunc: func(u *models.User) {
u.Password = "" u.Password = ""
@@ -597,7 +601,7 @@ func testUpdateUser(t *testing.T, loginCookie http.Cookie, adminCookie http.Cook
{ {
name: "Delete 1 category", name: "Delete 1 category",
setupCookie: func(req *http.Request) { setupCookie: func(req *http.Request) {
req.AddCookie(&loginCookie) req.AddCookie(MemberCookie)
}, },
updateFunc: func(u *models.User) { updateFunc: func(u *models.User) {
u.Password = "" u.Password = ""
@@ -615,7 +619,7 @@ func testUpdateUser(t *testing.T, loginCookie http.Cookie, adminCookie http.Cook
{ {
name: "Delete all categories", name: "Delete all categories",
setupCookie: func(req *http.Request) { setupCookie: func(req *http.Request) {
req.AddCookie(&loginCookie) req.AddCookie(MemberCookie)
}, },
updateFunc: func(u *models.User) { updateFunc: func(u *models.User) {
u.Password = "" u.Password = ""
@@ -630,7 +634,7 @@ func testUpdateUser(t *testing.T, loginCookie http.Cookie, adminCookie http.Cook
{ {
name: "User ID mismatch while not admin", name: "User ID mismatch while not admin",
setupCookie: func(req *http.Request) { setupCookie: func(req *http.Request) {
req.AddCookie(&loginCookie) req.AddCookie(MemberCookie)
}, },
updateFunc: func(u *models.User) { updateFunc: func(u *models.User) {
u.Password = "" u.Password = ""
@@ -649,7 +653,7 @@ func testUpdateUser(t *testing.T, loginCookie http.Cookie, adminCookie http.Cook
{ {
name: "Password Update low entropy should fail", name: "Password Update low entropy should fail",
setupCookie: func(req *http.Request) { setupCookie: func(req *http.Request) {
req.AddCookie(&loginCookie) req.AddCookie(MemberCookie)
}, },
updateFunc: func(u *models.User) { updateFunc: func(u *models.User) {
u.FirstName = "John Updated" u.FirstName = "John Updated"
@@ -666,7 +670,7 @@ func testUpdateUser(t *testing.T, loginCookie http.Cookie, adminCookie http.Cook
{ {
name: "Password Update", name: "Password Update",
setupCookie: func(req *http.Request) { setupCookie: func(req *http.Request) {
req.AddCookie(&loginCookie) req.AddCookie(MemberCookie)
}, },
updateFunc: func(u *models.User) { updateFunc: func(u *models.User) {
u.FirstName = "John Updated" u.FirstName = "John Updated"
@@ -687,7 +691,7 @@ func testUpdateUser(t *testing.T, loginCookie http.Cookie, adminCookie http.Cook
{ {
name: "Admin Password Update", name: "Admin Password Update",
setupCookie: func(req *http.Request) { setupCookie: func(req *http.Request) {
req.AddCookie(&adminCookie) req.AddCookie(AdminCookie)
}, },
updateFunc: func(u *models.User) { updateFunc: func(u *models.User) {
u.LastName = "Doe Updated" u.LastName = "Doe Updated"
@@ -700,7 +704,7 @@ func testUpdateUser(t *testing.T, loginCookie http.Cookie, adminCookie http.Cook
{ {
name: "Non-existent User", name: "Non-existent User",
setupCookie: func(req *http.Request) { setupCookie: func(req *http.Request) {
req.AddCookie(&loginCookie) req.AddCookie(MemberCookie)
}, },
updateFunc: func(u *models.User) { updateFunc: func(u *models.User) {
u.Password = "" u.Password = ""
@@ -719,7 +723,7 @@ func testUpdateUser(t *testing.T, loginCookie http.Cookie, adminCookie http.Cook
logger.Error.Print("==============================================================") logger.Error.Print("==============================================================")
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
// Create a copy of the user and apply the updates // Create a copy of the user and apply the updates
updatedUser := user updatedUser := *user
// logger.Error.Printf("users licence to be updated: %+v", user.Licence) // logger.Error.Printf("users licence to be updated: %+v", user.Licence)
tt.updateFunc(&updatedUser) tt.updateFunc(&updatedUser)
@@ -784,7 +788,7 @@ func testUpdateUser(t *testing.T, loginCookie http.Cookie, adminCookie http.Cook
assert.Equal(t, "User updated successfully", message) assert.Equal(t, "User updated successfully", message)
// Verify the update in the database // Verify the update in the database
updatedUserFromDB, err := Uc.Service.GetUserByID(user.ID) updatedUserFromDB, err := Uc.Service.FromID(&user.ID)
assert.NoError(t, err) assert.NoError(t, err)
if updatedUser.Password == "" { if updatedUser.Password == "" {
@@ -823,11 +827,17 @@ func testUpdateUser(t *testing.T, loginCookie http.Cookie, adminCookie http.Cook
assert.Equal(t, updatedUser.Membership.SubscriptionModelID, updatedUserFromDB.Membership.SubscriptionModelID, "Membership.SubscriptionModelID mismatch") assert.Equal(t, updatedUser.Membership.SubscriptionModelID, updatedUserFromDB.Membership.SubscriptionModelID, "Membership.SubscriptionModelID mismatch")
assert.Equal(t, updatedUser.Membership.ParentMembershipID, updatedUserFromDB.Membership.ParentMembershipID, "Membership.ParentMembershipID mismatch") assert.Equal(t, updatedUser.Membership.ParentMembershipID, updatedUserFromDB.Membership.ParentMembershipID, "Membership.ParentMembershipID mismatch")
assert.Equal(t, updatedUser.Licence.Status, updatedUserFromDB.Licence.Status, "Licence.Status mismatch") if updatedUser.Licence == nil {
assert.Equal(t, updatedUser.Licence.Number, updatedUserFromDB.Licence.Number, "Licence.Number mismatch") assert.Nil(t, updatedUserFromDB.Licence, "database licence of user is not nil, but user.licence is nil")
assert.Equal(t, updatedUser.Licence.IssuedDate, updatedUserFromDB.Licence.IssuedDate, "Licence.IssuedDate mismatch") } else {
assert.Equal(t, updatedUser.Licence.ExpirationDate, updatedUserFromDB.Licence.ExpirationDate, "Licence.ExpirationDate mismatch") logger.Error.Printf("updatedUser licence: %#v", updatedUser.Licence)
assert.Equal(t, updatedUser.Licence.IssuingCountry, updatedUserFromDB.Licence.IssuingCountry, "Licence.IssuingCountry mismatch") logger.Error.Printf("dbUser licence: %#v", updatedUserFromDB.Licence)
assert.Equal(t, updatedUser.Licence.Status, updatedUserFromDB.Licence.Status, "Licence.Status mismatch")
assert.Equal(t, updatedUser.Licence.Number, updatedUserFromDB.Licence.Number, "Licence.Number mismatch")
assert.Equal(t, updatedUser.Licence.IssuedDate, updatedUserFromDB.Licence.IssuedDate, "Licence.IssuedDate mismatch")
assert.Equal(t, updatedUser.Licence.ExpirationDate, updatedUserFromDB.Licence.ExpirationDate, "Licence.ExpirationDate mismatch")
assert.Equal(t, updatedUser.Licence.IssuingCountry, updatedUserFromDB.Licence.IssuingCountry, "Licence.IssuingCountry mismatch")
}
// For slices or more complex nested structures, you might want to use deep equality checks // For slices or more complex nested structures, you might want to use deep equality checks
assert.ElementsMatch(t, updatedUser.Consents, updatedUserFromDB.Consents, "Consents mismatch") assert.ElementsMatch(t, updatedUser.Consents, updatedUserFromDB.Consents, "Consents mismatch")
@@ -936,15 +946,19 @@ func checkVerificationMail(message *utils.Email, user *models.User) error {
if err != nil { if err != nil {
return fmt.Errorf("Error parsing verification URL: %#v", err.Error()) return fmt.Errorf("Error parsing verification URL: %#v", err.Error())
} }
if !strings.Contains(verificationURL, user.Verification.VerificationToken) { v, err := user.GetVerification(constants.VerificationTypes.Email)
return fmt.Errorf("Users Verification link token(%v) has not been rendered in email verification mail. %v", user.Verification.VerificationToken, verificationURL) if err != nil {
return fmt.Errorf("Error getting verification token: %v", err.Error())
}
if !strings.Contains(verificationURL, v.VerificationToken) {
return fmt.Errorf("Users Verification link token(%v) has not been rendered in email verification mail. %v", v.VerificationToken, verificationURL)
} }
if !strings.Contains(message.Body, config.Site.BaseURL) { if !strings.Contains(message.Body, config.Site.BaseURL) {
return fmt.Errorf("Base Url (%v) has not been rendered in email verification mail.", config.Site.BaseURL) return fmt.Errorf("Base Url (%v) has not been rendered in email verification mail.", config.Site.BaseURL)
} }
// open the provided link: // open the provided link:
if err := verifyMail(verificationURL); err != nil { if err := verifyMail(verificationURL, user.ID); err != nil {
return err return err
} }
messages := utils.SMTPGetMessages() messages := utils.SMTPGetMessages()
@@ -961,12 +975,14 @@ func checkVerificationMail(message *utils.Email, user *models.User) error {
} }
func verifyMail(verificationURL string) error { func verifyMail(verificationURL string, user_id uint) error {
gin.SetMode(gin.TestMode) gin.SetMode(gin.TestMode)
router := gin.New() router := gin.New()
router.LoadHTMLGlob(filepath.Join(config.Templates.HTMLPath, "*")) router.LoadHTMLGlob(filepath.Join(config.Templates.HTMLPath, "*"))
router.GET("api/users/verify", Uc.VerifyMailHandler) expectedUrl := fmt.Sprintf("/api/users/verify/%v", user_id)
log.Printf("Expected URL: %v", expectedUrl)
router.GET("/api/users/verify/:id", Uc.VerifyMailHandler)
wv := httptest.NewRecorder() wv := httptest.NewRecorder()
cv, _ := gin.CreateTestContext(wv) cv, _ := gin.CreateTestContext(wv)
var err error var err error
@@ -1109,8 +1125,9 @@ func getTestUsers() []RegisterUserTest {
Assert: false, Assert: false,
Input: GenerateInputJSON(customizeInput(func(user models.User) models.User { Input: GenerateInputJSON(customizeInput(func(user models.User) models.User {
user.BankAccount.IBAN = "DE1234234123134" user.BankAccount.IBAN = "DE1234234123134"
user.RoleID = 0 user.RoleID = constants.Roles.Supporter
user.Email = "john.supporter@example.com" user.Email = "john.supporter@example.com"
user.Membership.SubscriptionModel.Name = constants.SupporterSubscriptionModelName
return user return user
})), })),
}, },
@@ -1121,8 +1138,9 @@ func getTestUsers() []RegisterUserTest {
Assert: true, Assert: true,
Input: GenerateInputJSON(customizeInput(func(user models.User) models.User { Input: GenerateInputJSON(customizeInput(func(user models.User) models.User {
user.BankAccount.IBAN = "" user.BankAccount.IBAN = ""
user.RoleID = 0 user.RoleID = constants.Roles.Supporter
user.Email = "john.supporter@example.com" user.Email = "john.supporter@example.com"
user.Membership.SubscriptionModel.Name = constants.SupporterSubscriptionModelName
return user return user
})), })),
}, },