Files
GoMembership/internal/controllers/user_controller_test.go
2024-09-29 20:58:42 +02:00

887 lines
29 KiB
Go

package controllers
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"net/http/httptest"
"net/url"
"path/filepath"
"regexp"
"strconv"
"strings"
"testing"
"time"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"GoMembership/internal/config"
"GoMembership/internal/constants"
"GoMembership/internal/middlewares"
"GoMembership/internal/models"
"GoMembership/internal/utils"
"GoMembership/pkg/logger"
"github.com/golang-jwt/jwt/v5"
)
type RegisterUserTest struct {
WantDBData map[string]interface{}
Name string
Input string
WantResponse int
Assert bool
}
var jwtSigningMethod = jwt.SigningMethodHS256
func (rt *RegisterUserTest) SetupContext() (*gin.Context, *httptest.ResponseRecorder, *gin.Engine) {
return GetMockedJSONContext([]byte(rt.Input), "register")
}
func (rt *RegisterUserTest) RunHandler(c *gin.Context, router *gin.Engine) {
Uc.RegisterUser(c)
}
func (rt *RegisterUserTest) ValidateResponse(w *httptest.ResponseRecorder) error {
if w.Code != rt.WantResponse {
responseBody, _ := io.ReadAll(w.Body)
return fmt.Errorf("Register User: Didn't get the expected response code: got: %v; expected: %v. Context: %#v", w.Code, rt.WantResponse, string(responseBody))
}
return nil
}
func (rt *RegisterUserTest) ValidateResult() error {
return validateUser(rt.Assert, rt.WantDBData)
}
func testUserController(t *testing.T) {
tests := getTestUsers()
for _, tt := range tests {
logger.Error.Print("==============================================================")
logger.Error.Printf("Register User Testing : %v", tt.Name)
logger.Error.Print("==============================================================")
t.Run(tt.Name, func(t *testing.T) {
if err := runSingleTest(&tt); err != nil {
t.Fatalf("Test failed: %v", err.Error())
}
})
}
loginEmail, loginCookie := testLoginHandler(t)
logoutCookie := testCurrentUserHandler(t, loginEmail, loginCookie)
testUpdateUser(t, loginEmail, loginCookie)
testLogoutHandler(t, logoutCookie)
}
func testLogoutHandler(t *testing.T, loginCookie http.Cookie) {
tests := []struct {
name string
setupCookie func(*http.Request)
expectedStatus int
}{
{
name: "Logout with valid cookie",
setupCookie: func(req *http.Request) {
req.AddCookie(&loginCookie)
},
expectedStatus: http.StatusOK,
},
{
name: "Logout without cookie",
setupCookie: func(req *http.Request) {},
expectedStatus: http.StatusOK, // Logout should still succeed even without a cookie
},
}
for _, tt := range tests {
logger.Error.Print("==============================================================")
logger.Error.Printf("Logout User Testing : %v", tt.name)
logger.Error.Print("==============================================================")
t.Run(tt.name, func(t *testing.T) {
gin.SetMode(gin.TestMode)
router := gin.New()
router.POST("/logout", Uc.LogoutHandler)
w := httptest.NewRecorder()
req, _ := http.NewRequest("POST", "/logout", nil)
tt.setupCookie(req)
router.ServeHTTP(w, req)
assert.Equal(t, tt.expectedStatus, w.Code)
var response map[string]string
err := json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
assert.Equal(t, "Logged out successfully", response["message"])
// Check if the cookie has been cleared
var logoutCookie *http.Cookie
for _, cookie := range w.Result().Cookies() {
if cookie.Name == "jwt" {
logoutCookie = cookie
break
}
}
assert.NotNil(t, logoutCookie, "Logout should set a clearing cookie")
assert.Equal(t, "", logoutCookie.Value, "Logout cookie should have empty value")
assert.True(t, logoutCookie.Expires.Before(time.Now()), "Logout cookie should be expired")
// Verify that the user can no longer access protected routes
w = httptest.NewRecorder()
req, _ = http.NewRequest("GET", "/current", nil)
if logoutCookie != nil {
req.AddCookie(logoutCookie)
}
router.GET("/current", middlewares.AuthMiddleware(), Uc.CurrentUserHandler)
router.ServeHTTP(w, req)
assert.Equal(t, http.StatusUnauthorized, w.Code, "User should not be able to access protected routes after logout")
})
}
}
func testLoginHandler(t *testing.T) (string, http.Cookie) {
// This test should run after the user registration test
var loginCookie http.Cookie
var loginInput loginInput
t.Run("LoginHandler", func(t *testing.T) {
// Test cases
tests := []struct {
name string
input string
wantStatusCode int
wantToken bool
}{
{
name: "Valid login",
input: `{
"email": "john.doe@example.com",
"password": "password123"
}`,
wantStatusCode: http.StatusOK,
wantToken: true,
},
{
name: "Invalid email",
input: `{
"email": "nonexistent@example.com",
"password": "password123"
}`,
wantStatusCode: http.StatusNotFound,
wantToken: false,
},
{
name: "Invalid password",
input: `{
"email": "john.doe@example.com",
"password": "wrongpassword"
}`,
wantStatusCode: http.StatusNotAcceptable,
wantToken: false,
},
}
for _, tt := range tests {
logger.Error.Print("==============================================================")
logger.Error.Printf("Testing : %v", tt.name)
logger.Error.Print("==============================================================")
t.Run(tt.name, func(t *testing.T) {
// Setup
c, w, _ := GetMockedJSONContext([]byte(tt.input), "/login")
// Execute
Uc.LoginHandler(c)
// Assert
assert.Equal(t, tt.wantStatusCode, w.Code)
var response map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
if tt.wantToken {
assert.Contains(t, response, "message")
assert.Equal(t, "Login successful", response["message"])
for _, cookie := range w.Result().Cookies() {
if cookie.Name == "jwt" {
loginCookie = *cookie
err = json.Unmarshal([]byte(tt.input), &loginInput)
assert.NoError(t, err, "Failed to unmarshal input JSON")
break
}
}
assert.NotEmpty(t, loginCookie)
} else {
assert.Contains(t, response, "error")
assert.NotEmpty(t, response["error"])
}
})
}
})
return loginInput.Email, loginCookie
}
func testCurrentUserHandler(t *testing.T, loginEmail string, loginCookie http.Cookie) http.Cookie {
// This test should run after the user login test
invalidCookie := http.Cookie{
Name: "jwt",
Value: "invalid.token.here",
}
tests := []struct {
name string
setupCookie func(*http.Request)
expectedUserMail string
expectedStatus int
expectNewCookie bool
}{
{
name: "With valid cookie",
setupCookie: func(req *http.Request) {
req.AddCookie(&loginCookie)
},
expectedUserMail: loginEmail,
expectedStatus: http.StatusOK,
},
{
name: "With valid expired cookie",
setupCookie: func(req *http.Request) {
sessionID := "test-session"
token := jwt.NewWithClaims(jwtSigningMethod, jwt.MapClaims{
"user_id": 1,
"role_id": 0,
"session_id": sessionID,
"exp": time.Now().Add(-time.Hour).Unix(), // Expired 1 hour ago
})
tokenString, _ := token.SignedString([]byte(config.Auth.JWTSecret))
req.AddCookie(&http.Cookie{Name: "jwt", Value: tokenString})
middlewares.UpdateSession(sessionID, 1) // Add a valid session
},
expectedUserMail: config.Recipients.AdminEmail,
expectedStatus: http.StatusOK,
expectNewCookie: true,
},
{
name: "Without cookie",
setupCookie: func(req *http.Request) {},
expectedStatus: http.StatusUnauthorized,
},
{
name: "With invalid cookie",
setupCookie: func(req *http.Request) {
req.AddCookie(&invalidCookie)
},
expectedStatus: http.StatusUnauthorized,
},
}
for _, tt := range tests {
logger.Error.Print("==============================================================")
logger.Error.Printf("Testing : %v", tt.name)
logger.Error.Print("==============================================================")
t.Run(tt.name, func(t *testing.T) {
gin.SetMode(gin.TestMode)
router := gin.New()
router.Use(middlewares.AuthMiddleware())
router.GET("/current", Uc.CurrentUserHandler)
w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/current", nil)
tt.setupCookie(req)
router.ServeHTTP(w, req)
assert.Equal(t, tt.expectedStatus, w.Code)
if tt.expectedStatus == http.StatusOK {
var response models.User
err := json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
assert.Equal(t, tt.expectedUserMail, response.Email)
var newCookie *http.Cookie
for _, cookie := range w.Result().Cookies() {
if cookie.Name == "jwt" {
newCookie = cookie
break
}
}
if tt.expectNewCookie {
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.True(t, newCookie.MaxAge > 0, "New cookie should not be expired")
} else {
assert.Nil(t, newCookie, "No new cookie should be set for non-expired token")
}
} else {
// For unauthorized requests, check for an error message
var errorResponse map[string]string
err := json.Unmarshal(w.Body.Bytes(), &errorResponse)
assert.NoError(t, err)
assert.Contains(t, errorResponse, "error")
assert.NotEmpty(t, errorResponse["error"])
}
})
}
return loginCookie
}
func validateUser(assert bool, wantDBData map[string]interface{}) error {
users, err := Uc.Service.GetUsers(wantDBData)
if err != nil {
return fmt.Errorf("Error in database ops: %#v", err)
}
if assert != (len(*users) != 0) {
return fmt.Errorf("User entry query didn't met expectation: %v != %#v", assert, *users)
}
if assert {
//check for email delivery
messages := utils.SMTPGetMessages()
for _, message := range messages {
mail, err := utils.DecodeMail(message.MsgRequest())
if err != nil {
logger.Error.Printf("Error in validateUser: %#v", err)
return err
}
if strings.Contains(mail.Subject, constants.MailRegistrationSubject) {
if err := checkRegistrationMail(mail, &(*users)[0]); err != nil {
logger.Error.Printf("Error in checkRegistrationMail: %#v", err)
return err
}
} else if strings.Contains(mail.Subject, constants.MailVerificationSubject) {
if err := checkVerificationMail(mail, &(*users)[0]); err != nil {
logger.Error.Printf("Error in checkVerificationMail: %#v", err)
return err
}
verifiedUsers, err := Uc.Service.GetUsers(wantDBData)
if err != nil {
logger.Error.Printf("Error in GetUsers: %#v", err)
return err
}
if (*verifiedUsers)[0].Status != constants.VerifiedStatus {
return fmt.Errorf("Users(%v) status isn't verified after email verification. Status is: %v", (*verifiedUsers)[0].Email, (*verifiedUsers)[0].Status)
}
} else {
return fmt.Errorf("Subject not expected: %v", mail.Subject)
}
}
}
return nil
}
func testUpdateUser(t *testing.T, loginEmail string, loginCookie http.Cookie) {
invalidCookie := http.Cookie{
Name: "jwt",
Value: "invalid.token.here",
}
// Get the user we just created
users, err := Uc.Service.GetUsers(map[string]interface{}{"email": "john.doe@example.com"})
if err != nil || len(*users) == 0 {
t.Fatalf("Failed to get test user: %v", err)
}
user := (*users)[0]
tests := []struct {
name string
setupCookie func(*http.Request)
updateFunc func(*models.User)
expectedStatus int
expectedError string
}{
{
name: "Valid Update",
setupCookie: func(req *http.Request) {
req.AddCookie(&loginCookie)
},
updateFunc: func(u *models.User) {
u.Password = ""
u.FirstName = "John Updated"
u.LastName = "Doe Updated"
u.Phone = "01738484994"
},
expectedStatus: http.StatusAccepted,
},
{
name: "Password Update",
setupCookie: func(req *http.Request) {
req.AddCookie(&loginCookie)
},
updateFunc: func(u *models.User) {
u.Password = "NewPassword"
},
expectedStatus: http.StatusAccepted,
},
{
name: "Valid Update, invalid cookie",
setupCookie: func(req *http.Request) {
req.AddCookie(&invalidCookie)
},
updateFunc: func(u *models.User) {
u.Password = ""
u.FirstName = "John Updated"
u.LastName = "Doe Updated"
u.Phone = "01738484994"
},
expectedStatus: http.StatusUnauthorized,
expectedError: "Auth token invalid",
},
{
name: "Invalid Email Update",
setupCookie: func(req *http.Request) {
req.AddCookie(&loginCookie)
},
updateFunc: func(u *models.User) {
u.Password = ""
u.Email = "invalid-email"
},
expectedStatus: http.StatusBadRequest,
expectedError: "Invalid user data",
},
{
name: "User ID mismatch while not admin",
setupCookie: func(req *http.Request) {
req.AddCookie(&loginCookie)
},
updateFunc: func(u *models.User) {
u.Password = ""
u.ID = 1
u.FirstName = "John Missing ID"
},
expectedStatus: http.StatusForbidden,
expectedError: "You are not authorized to update this user",
},
// {
// name: "Non-existent User",
// setupCookie: func(req *http.Request) {
// req.AddCookie(&loginCookie)
// },
// updateFunc: func(u *models.User) {
// u.Password = ""
// u.ID = 99999
// u.FirstName = "Non-existent"
// },
// expectedStatus: http.StatusNotFound,
// expectedError: "User not found",
// },
}
for _, tt := range tests {
logger.Error.Print("==============================================================")
logger.Error.Printf("Update Testing : %v", tt.name)
logger.Error.Print("==============================================================")
t.Run(tt.name, func(t *testing.T) {
// Create a copy of the user and apply the updates
updatedUser := user
tt.updateFunc(&updatedUser)
// Convert user to JSON
jsonData, err := json.Marshal(updatedUser)
if err != nil {
t.Fatalf("Failed to marshal user data: %v", err)
}
// Create request
req, _ := http.NewRequest("PUT", "/users/"+strconv.FormatUint(uint64(user.ID), 10), bytes.NewBuffer(jsonData))
req.Header.Set("Content-Type", "application/json")
tt.setupCookie(req)
// Create response recorder
w := httptest.NewRecorder()
// Set up router and add middleware
router := gin.New()
router.Use(middlewares.AuthMiddleware())
router.PUT("/users/:id", Uc.UpdateHandler)
// Perform request
router.ServeHTTP(w, req)
// Check status code
assert.Equal(t, tt.expectedStatus, w.Code)
// Parse response
var response map[string]interface{}
err = json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
if tt.expectedError != "" {
assert.Equal(t, tt.expectedError, response["error"])
} else {
assert.Equal(t, "User updated successfully", response["message"])
// Verify the update in the database
updatedUserFromDB, err := Uc.Service.GetUserByID(user.ID)
updatedUserFromDB.UpdatedAt = updatedUser.UpdatedAt
updatedUserFromDB.Membership.UpdatedAt = updatedUser.Membership.UpdatedAt
updatedUserFromDB.BankAccount.UpdatedAt = updatedUser.BankAccount.UpdatedAt
updatedUserFromDB.Verification.UpdatedAt = updatedUser.Verification.UpdatedAt
updatedUserFromDB.Membership.SubscriptionModel.UpdatedAt = updatedUser.Membership.SubscriptionModel.UpdatedAt
if updatedUser.Password == "" {
assert.Equal(t, user.Password, (*updatedUserFromDB).Password)
} else {
assert.NotEqual(t, user.Password, (*updatedUserFromDB).Password)
updatedUser.Password = ""
}
updatedUserFromDB.Password = ""
assert.NoError(t, err)
assert.Equal(t, updatedUser, *updatedUserFromDB, "Updated user in DB does not match expected user")
}
})
}
}
func checkWelcomeMail(message *utils.Email, user *models.User) error {
if !strings.Contains(message.To, user.Email) {
return fmt.Errorf("Registration Information didn't reach the user! Recipient was: %v instead of %v", message.To, user.Email)
}
if !strings.Contains(message.From, config.SMTP.User) {
return fmt.Errorf("Registration Information was sent from unexpected address! Sender was: %v instead of %v", message.From, config.SMTP.User)
}
//Check if all the relevant data has been passed to the mail.
if !strings.Contains(message.Body, user.FirstName) {
return fmt.Errorf("User first name(%v) has not been rendered in registration mail.", user.FirstName)
}
if !strings.Contains(message.Body, fmt.Sprintf("Preis/Monat</strong>: %v", user.Membership.SubscriptionModel.MonthlyFee)) {
return fmt.Errorf("Users monthly subscription fee(%v) has not been rendered in registration mail.", user.Membership.SubscriptionModel.MonthlyFee)
}
if !strings.Contains(message.Body, fmt.Sprintf("Preis/h</strong>: %v", user.Membership.SubscriptionModel.HourlyRate)) {
return fmt.Errorf("Users hourly subscription fee(%v) has not been rendered in registration mail.", user.Membership.SubscriptionModel.HourlyRate)
}
if user.Company != "" && !strings.Contains(message.Body, user.Company) {
return fmt.Errorf("Users Company(%v) has not been rendered in registration mail.", user.Company)
}
if !strings.Contains(message.Body, fmt.Sprintf("Mitgliedsnummer</strong>: %v", user.Membership.ID)) {
return fmt.Errorf("Users membership Id(%v) has not been rendered in registration mail.", user.Membership.ID)
}
if !strings.Contains(message.Body, config.Site.BaseURL) {
return fmt.Errorf("Base Url (%v) has not been rendered in registration mail.", config.Site.BaseURL)
}
if !strings.Contains(message.Body, config.Site.BaseURL+config.Templates.LogoURI) {
return fmt.Errorf("Logo Url (%v) has not been rendered in registration mail.", config.Site.BaseURL+config.Site.WebsiteTitle)
}
if !strings.Contains(message.Body, config.Site.WebsiteTitle) {
return fmt.Errorf("Website title (%v) has not been rendered in registration mail.", config.Site.WebsiteTitle)
}
return nil
}
func checkRegistrationMail(message *utils.Email, user *models.User) error {
if !strings.Contains(message.To, config.Recipients.UserRegistration) {
return fmt.Errorf("Registration Information didn't reach admin! Recipient was: %v instead of %v", message.To, config.Recipients.UserRegistration)
}
if !strings.Contains(message.From, config.SMTP.User) {
return fmt.Errorf("Registration Information was sent from unexpected address! Sender was: %v instead of %v", message.From, config.SMTP.User)
}
//Check if all the relevant data has been passed to the mail.
if !strings.Contains(message.Body, user.FirstName+" "+user.LastName) {
return fmt.Errorf("User first and last name(%v) has not been rendered in registration mail.", user.FirstName+" "+user.LastName)
}
if !strings.Contains(message.Body, fmt.Sprintf("Preis/Monat</strong>: %v", user.Membership.SubscriptionModel.MonthlyFee)) {
return fmt.Errorf("Users monthly subscription fee(%v) has not been rendered in registration mail.", user.Membership.SubscriptionModel.MonthlyFee)
}
if !strings.Contains(message.Body, fmt.Sprintf("Preis/h</strong>: %v", user.Membership.SubscriptionModel.HourlyRate)) {
return fmt.Errorf("Users hourly subscription fee(%v) has not been rendered in registration mail.", user.Membership.SubscriptionModel.HourlyRate)
}
if user.Company != "" && !strings.Contains(message.Body, user.Company) {
return fmt.Errorf("Users Company(%v) has not been rendered in registration mail.", user.Company)
}
if !strings.Contains(message.Body, fmt.Sprintf("Mitgliedsnr:</strong> %v", user.Membership.ID)) {
return fmt.Errorf("Users membership Id(%v) has not been rendered in registration mail.", user.Membership.ID)
}
if !strings.Contains(message.Body, user.Address+","+user.ZipCode) {
return fmt.Errorf("Users address(%v) has not been rendered in registration mail.", user.Address+" sv,"+user.ZipCode)
}
if !strings.Contains(message.Body, user.City) {
return fmt.Errorf("Users city(%v) has not been rendered in registration mail.", user.City)
}
if !strings.Contains(message.Body, user.DateOfBirth.Format("20060102")) {
return fmt.Errorf("Users birthday(%v) has not been rendered in registration mail.", user.DateOfBirth.Format("20060102"))
}
if !strings.Contains(message.Body, "Email:</strong> "+user.Email) {
return fmt.Errorf("Users email(%v) has not been rendered in registration mail.", user.Email)
}
if !strings.Contains(message.Body, user.Phone) {
return fmt.Errorf("Users phone(%v) has not been rendered in registration mail.", user.Phone)
}
if !strings.Contains(message.Body, user.BankAccount.IBAN) {
return fmt.Errorf("Users IBAN(%v) has not been rendered in registration mail.", user.BankAccount.IBAN)
}
if !strings.Contains(message.Body, config.Site.BaseURL) {
return fmt.Errorf("Base Url (%v) has not been rendered in registration mail.", config.Site.BaseURL)
}
return nil
}
func checkVerificationMail(message *utils.Email, user *models.User) error {
if !strings.Contains(message.To, user.Email) {
return fmt.Errorf("Registration Information didn't reach client! Recipient was: %v instead of %v", message.To, user.Email)
}
verificationURL, err := getVerificationURL(message.Body)
if err != nil {
return fmt.Errorf("Error parsing verification URL: %#v", err.Error())
}
if !strings.Contains(verificationURL, user.Verification.VerificationToken) {
return fmt.Errorf("Users Verification link token(%v) has not been rendered in email verification mail. %v", user.Verification.VerificationToken, verificationURL)
}
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)
}
// open the provided link:
if err := verifyMail(verificationURL); err != nil {
return err
}
messages := utils.SMTPGetMessages()
for _, message := range messages {
mail, err := utils.DecodeMail(message.MsgRequest())
if err != nil {
return err
}
if err := checkWelcomeMail(mail, user); err != nil {
return err
}
}
return nil
}
func verifyMail(verificationURL string) error {
gin.SetMode(gin.TestMode)
router := gin.New()
router.LoadHTMLGlob(filepath.Join(config.Templates.HTMLPath, "*"))
router.GET("/users/verify", Uc.VerifyMailHandler)
wv := httptest.NewRecorder()
cv, _ := gin.CreateTestContext(wv)
var err error
cv.Request, err = http.NewRequest("GET", verificationURL, nil)
if err != nil {
return fmt.Errorf("Failed to create new GET Request: %v", err.Error())
}
router.ServeHTTP(wv, cv.Request)
if wv.Code != 200 {
responseBody, _ := io.ReadAll(wv.Body)
return fmt.Errorf("VerifyMail: Didn't get the expected response code: got: %v; expected: %v Context: %#v", wv.Code, 200, string(responseBody))
}
return nil
}
func getVerificationURL(mailBody string) (string, error) {
re := regexp.MustCompile(`"([^"]*verify[^"]*)"`)
// Find the matching URL in the email content
match := re.FindStringSubmatch(mailBody)
if len(match) == 0 {
return "", fmt.Errorf("No mail verification link found in email body: %#v", mailBody)
}
verificationURL, err := url.QueryUnescape(match[1])
if err != nil {
return "", fmt.Errorf("Error decoding URL: %v", err)
}
logger.Info.Printf("VerificationURL: %#v", verificationURL)
return verificationURL, nil
}
// TEST DATA:
func customizeInput(customize func(models.User) models.User) *RegistrationData {
user := getBaseUser()
user = customize(user) // Apply the customization
return &RegistrationData{User: user}
}
func getTestUsers() []RegisterUserTest {
return []RegisterUserTest{
{
Name: "birthday < 18 should fail",
WantResponse: http.StatusNotAcceptable,
WantDBData: map[string]interface{}{"email": "john.doe@example.com"},
Assert: false,
Input: GenerateInputJSON(customizeInput(func(user models.User) models.User {
user.DateOfBirth = time.Date(2020, time.January, 1, 0, 0, 0, 0, time.UTC)
return user
})),
},
{
Name: "FirstName empty, should fail",
WantResponse: http.StatusNotAcceptable,
WantDBData: map[string]interface{}{"email": "john.doe@example.com"},
Assert: false,
Input: GenerateInputJSON(customizeInput(func(user models.User) models.User {
user.FirstName = ""
return user
})),
},
{
Name: "LastName Empty should fail",
WantResponse: http.StatusNotAcceptable,
WantDBData: map[string]interface{}{"email": "john.doe@example.com"},
Assert: false,
Input: GenerateInputJSON(customizeInput(func(user models.User) models.User {
user.LastName = ""
return user
})),
},
{
Name: "EMail wrong format should fail",
WantResponse: http.StatusNotAcceptable,
WantDBData: map[string]interface{}{"email": "johnexample.com"},
Assert: false,
Input: GenerateInputJSON(customizeInput(func(user models.User) models.User {
user.Email = "johnexample.com"
return user
})),
},
{
Name: "Missing Zip Code should fail",
WantResponse: http.StatusNotAcceptable,
WantDBData: map[string]interface{}{"email": "john.doe@example.com"},
Assert: false,
Input: GenerateInputJSON(customizeInput(func(user models.User) models.User {
user.ZipCode = ""
return user
})),
},
{
Name: "Missing Address should fail",
WantResponse: http.StatusNotAcceptable,
WantDBData: map[string]interface{}{"email": "john.doe@example.com"},
Assert: false,
Input: GenerateInputJSON(customizeInput(func(user models.User) models.User {
user.Address = ""
return user
})),
},
{
Name: "Missing City should fail",
WantResponse: http.StatusNotAcceptable,
WantDBData: map[string]interface{}{"email": "john.doe@example.com"},
Assert: false,
Input: GenerateInputJSON(customizeInput(func(user models.User) models.User {
user.City = ""
return user
})),
},
{
Name: "Missing IBAN should fail",
WantResponse: http.StatusNotAcceptable,
WantDBData: map[string]interface{}{"email": "john.doe@example.com"},
Assert: false,
Input: GenerateInputJSON(customizeInput(func(user models.User) models.User {
user.BankAccount.IBAN = ""
return user
})),
},
{
Name: "Invalid IBAN should fail",
WantResponse: http.StatusNotAcceptable,
WantDBData: map[string]interface{}{"email": "john.doe@example.com"},
Assert: false,
Input: GenerateInputJSON(customizeInput(func(user models.User) models.User {
user.BankAccount.IBAN = "DE1234234123134"
return user
})),
},
{
Name: "Missing subscription plan should fail",
WantResponse: http.StatusNotAcceptable,
WantDBData: map[string]interface{}{"email": "john.doe@example.com"},
Assert: false,
Input: GenerateInputJSON(customizeInput(func(user models.User) models.User {
user.Membership.SubscriptionModel.Name = ""
return user
})),
},
{
Name: "Invalid subscription plan should fail",
WantResponse: http.StatusNotFound,
WantDBData: map[string]interface{}{"email": "john.doe@example.com"},
Assert: false,
Input: GenerateInputJSON(customizeInput(func(user models.User) models.User {
user.Membership.SubscriptionModel.Name = "NOTEXISTENTPLAN"
return user
})),
},
{
Name: "Correct Entry should pass",
WantResponse: http.StatusCreated,
WantDBData: map[string]interface{}{"Email": "john.doe@example.com"},
Assert: true,
Input: GenerateInputJSON(customizeInput(func(user models.User) models.User { return user })),
},
{
Name: "Email duplicate should fail",
WantResponse: http.StatusConflict,
WantDBData: map[string]interface{}{"first_name": "Jane"},
Assert: false,
Input: GenerateInputJSON(customizeInput(func(user models.User) models.User {
user.FirstName = "Jane"
return user
})),
},
{
Name: "Company present should pass",
WantResponse: http.StatusCreated,
WantDBData: map[string]interface{}{"Email": "john.doe2@example.com"},
Assert: true,
Input: GenerateInputJSON(customizeInput(func(user models.User) models.User {
user.Email = "john.doe2@example.com"
user.Company = "ACME"
return user
})),
},
{
Name: "Subscription constraints not entered; should fail",
WantResponse: http.StatusNotAcceptable,
WantDBData: map[string]interface{}{"Email": "john.junior.doe@example.com"},
Assert: false,
Input: GenerateInputJSON(customizeInput(func(user models.User) models.User {
user.Email = "john.junior.doe@example.com"
user.Membership.SubscriptionModel.Name = "additional"
return user
})),
},
{
Name: "Subscription constraints wrong; should fail",
WantResponse: http.StatusNotAcceptable,
WantDBData: map[string]interface{}{"Email": "john.junior.doe@example.com"},
Assert: false,
Input: GenerateInputJSON(customizeInput(func(user models.User) models.User {
user.Email = "john.junior.doe@example.com"
user.Membership.ParentMembershipID = 200
user.Membership.SubscriptionModel.Name = "additional"
return user
})),
},
{
Name: "Subscription constraints correct, should pass",
WantResponse: http.StatusCreated,
WantDBData: map[string]interface{}{"Email": "john.junior.doe@example.com"},
Assert: true,
Input: GenerateInputJSON(customizeInput(func(user models.User) models.User {
user.Email = "john.junior.doe@example.com"
user.Membership.ParentMembershipID = 1
user.Membership.SubscriptionModel.Name = "additional"
return user
})),
},
}
}