add: company; tests

This commit is contained in:
$(pass /github/name)
2024-07-16 17:52:37 +02:00
parent a1a43f1f32
commit eeeabd5ad3
4 changed files with 284 additions and 14 deletions

9
go.mod
View File

@@ -4,6 +4,9 @@ go 1.22.2
require ( require (
github.com/gin-gonic/gin v1.10.0 github.com/gin-gonic/gin v1.10.0
github.com/go-playground/validator/v10 v10.22.0
github.com/jbub/banking v0.8.0
github.com/stretchr/testify v1.9.0
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
gorm.io/driver/sqlite v1.5.6 gorm.io/driver/sqlite v1.5.6
gorm.io/gorm v1.25.10 gorm.io/gorm v1.25.10
@@ -14,13 +17,12 @@ require (
github.com/bytedance/sonic/loader v0.1.1 // indirect github.com/bytedance/sonic/loader v0.1.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/gabriel-vasile/mimetype v1.4.4 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gabriel-vasile/mimetype v1.4.4 // in
github.com/gin-contrib/sse v0.1.0 // indirect github.com/gin-contrib/sse v0.1.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.22.0 // indirect
github.com/goccy/go-json v0.10.3 // indirect github.com/goccy/go-json v0.10.3 // indirect
github.com/jbub/banking v0.8.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect github.com/jinzhu/now v1.1.5 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
@@ -31,6 +33,7 @@ require (
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/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // 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
golang.org/x/arch v0.8.0 // indirect golang.org/x/arch v0.8.0 // indirect

View File

@@ -0,0 +1,277 @@
package controllers
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"os"
"testing"
"time"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"reflect"
"GoMembership/internal/config"
"GoMembership/internal/database"
"GoMembership/internal/models"
"GoMembership/internal/repositories"
"GoMembership/internal/services"
"GoMembership/pkg/logger"
)
type keyValuePair struct {
value interface{}
key string
}
type test struct {
name string
wantResponse uint16
userEmail string
wantDBData []keyValuePair
assert bool
input string
}
func TestUserController(t *testing.T) {
err := database.InitDB("test.db")
if err != nil {
t.Errorf("Failed to create DB: %#v", err)
}
cfg := config.LoadConfig()
emailService := services.NewEmailService(cfg.SMTP.Host, cfg.SMTP.Port, cfg.SMTP.User, cfg.SMTP.Password, cfg.SMTP.AdminEmail)
var consentRepo repositories.ConsentRepositoryInterface = &repositories.ConsentRepository{}
consentService := &services.ConsentService{Repo: consentRepo}
var bankAccountRepo repositories.BankAccountRepositoryInterface = &repositories.BankAccountRepository{}
bankAccountService := &services.BankAccountService{Repo: bankAccountRepo}
var membershipRepo repositories.MembershipRepositoryInterface = &repositories.MembershipRepository{}
var subscriptionRepo repositories.SubscriptionModelsRepositoryInterface = &repositories.SubscriptionModelsRepository{}
membershipService := &services.MembershipService{Repo: membershipRepo, SubscriptionRepo: subscriptionRepo}
var userRepo repositories.UserRepositoryInterface = &repositories.UserRepository{}
userService := &services.UserService{Repo: userRepo}
uc := UserController{Service: userService, EmailService: emailService, ConsentService: consentService, BankAccountService: bankAccountService, MembershipService: membershipService}
if err := initSubscriptionPlans(); err != nil {
t.Errorf("Failed to init Susbcription plans: %#v", err)
}
tests := getTestUsers()
for _, tt := range tests {
c, _ := getMockedContext([]byte(tt.input))
t.Run(tt.name, func(t *testing.T) {
uc.RegisterUser(c)
user, err := userRepo.FindUserByEmail(tt.userEmail)
if err == gorm.ErrRecordNotFound && !tt.assert {
//pass
} else if err == nil && tt.assert {
// check value:
if tt.wantDBData != nil {
for _, kvp := range tt.wantDBData {
/* dbValue, err := getFieldValue(*user, kvp.key)
if err != nil {
t.Errorf("getFieldValue failed: %#v", err)
} */
dbValue, err := getAttr(&user, kvp.key)
if err != nil {
t.Errorf("Couldn't get Attribute: %#v", err)
}
if kvp.value != dbValue {
// fail
t.Errorf("Value is not expected: %v != %v", kvp.value, dbValue)
}
}
}
} else {
// fail
t.Errorf("FindUserByEmail failed: %#v", err)
}
})
}
if err := deleteTestDB("test.db"); err != nil {
t.Errorf("Failed to tear down DB: %#v", err)
}
}
func initSubscriptionPlans() error {
subscription := models.SubscriptionModel{
Name: "basic",
}
result := database.DB.Create(&subscription)
if result.Error != nil {
return result.Error
}
return nil
}
func getMockedContext(jsonStr []byte) (*gin.Context, *httptest.ResponseRecorder) {
gin.SetMode(gin.TestMode)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "/register", bytes.NewBuffer(jsonStr))
c.Request.Header.Set("Content-Type", "application/json")
return c, w
}
func getAttr(obj interface{}, fieldName string) (interface{}, error) {
pointToStruct := reflect.ValueOf(obj) // addressable
curStruct := pointToStruct.Elem()
if curStruct.Kind() != reflect.Struct {
return nil, fmt.Errorf("expected a struct, but got %v", curStruct.Kind())
}
curField := curStruct.FieldByName(fieldName) // type: reflect.Value
if !curField.IsValid() {
return nil, fmt.Errorf("no such field: %s in user", fieldName)
}
return curField.Interface(), nil
}
/* func getFieldValue(user models.User, fieldName string) (interface{}, error) {
v := reflect.ValueOf(user)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() != reflect.Struct {
return nil, fmt.Errorf("expected a struct, but got %v", v.Kind())
}
fieldVal := v.FieldByName(fieldName)
if !fieldVal.IsValid() {
return nil, fmt.Errorf("no such field: %s in user", fieldName)
}
return fieldVal.Interface(), nil
} */
func deleteTestDB(dbPath string) error {
err := os.Remove(dbPath)
if err != nil {
return err
}
return nil
}
// TEST DATA:
func generateUserJSON(user models.User) string {
data, err := json.Marshal(user)
if err != nil {
logger.Error.Printf("couldn't generate Json from Uer: %#v\nERROR: %#v", user, err)
return ""
}
return string(data)
}
func getTestUsers() []test {
return []test{
{
name: "birthday < 18 should fail",
wantResponse: http.StatusNotAcceptable,
wantDBData: []keyValuePair{
{
key: "Email",
value: "john.doe@example.com"},
},
assert: false,
input: generateUserJSON(
models.User{
DateOfBirth: time.Date(2020, time.January, 1, 0, 0, 0, 0, time.UTC),
FirstName: "John",
LastName: "Doe",
Email: "john.doe@example.com",
Address: "123 Main St",
ZipCode: "12345",
City: "Cityville",
Phone: "123-456-7890",
BankAccount: models.BankAccount{IBAN: "DE89370400440532013000"},
Membership: models.Membership{SubscriptionModel: models.SubscriptionModel{Name: "Basic"}},
ProfilePicture: "http://example.com/profile.jpg",
Company: nil,
Notes: nil,
Password: "password123",
ID: 1,
PaymentStatus: 1,
Status: 1,
RoleID: 1,
}),
},
{
name: "FirstName empty, should fail",
wantResponse: http.StatusNotAcceptable,
wantDBData: []keyValuePair{
{
key: "Email",
value: "john.doe@example.com"},
},
assert: false,
input: generateUserJSON(
models.User{
DateOfBirth: time.Date(1990, time.January, 1, 0, 0, 0, 0, time.UTC),
FirstName: "",
LastName: "Doe",
Email: "john.doe@example.com",
Address: "123 Main St",
ZipCode: "12345",
City: "Cityville",
Phone: "123-456-7890",
BankAccount: models.BankAccount{IBAN: "DE89370400440532013000"},
Membership: models.Membership{SubscriptionModel: models.SubscriptionModel{Name: "Basic"}},
ProfilePicture: "http://example.com/profile.jpg",
Company: nil,
Notes: nil,
Password: "password123",
ID: 1,
PaymentStatus: 1,
Status: 1,
RoleID: 1,
}),
},
/* Vjjjjjjjj
models.User {
DateOfBirth: time.Date(1985, time.March, 15, 0, 0, 0, 0, time.UTC),
FirstName: "Jane",
LastName: "Smith",
Email: "jane.smith@example.com",
Address: "456 Oak St",
ZipCode: "67890",
City: "Townsville",
Phone: "098-765-4321",
BankAccount: models.BankAccount{IBAN: "FR7630006000011234567890189"},
Membership: models.Membership{SubscriptionModel: SubscriptionModel{Name: "Premium", Details: "Premium Subscription", Conditions: "None", MonthlyFee: 19.99, HourlyRate: 25.00}},
ProfilePicture: "http://example.com/profile2.jpg",
Company: stringPtr("ExampleCorp"),
Notes: stringPtr("Important client"),
Password: "securepassword456",
ID: 2,
PaymentStatus: 0,
Status: 2,
RoleID: 2,
},
{
DateOfBirth: time.Date(2000, time.July, 30, 0, 0, 0, 0, time.UTC),
FirstName: "Alice",
LastName: "Brown",
Email: "alice.brown@example.com",
Address: "789 Pine St",
ZipCode: "11223",
City: "Villageville",
Phone: "555-555-5555",
BankAccount: models.BankAccount{IBAN: "GB29NWBK60161331926819"},
Membership: models.Membership{SubscriptionModel: SubscriptionModel{Name: "Standard", Details: "Standard Subscription", Conditions: "None", MonthlyFee: 14.99, HourlyRate: 20.00}},
ProfilePicture: "",
Company: stringPtr("AnotherCorp"),
Notes: nil,
Password: "mypassword789",
ID: 3,
PaymentStatus: 1,
Status: 1,
RoleID: 3,
}, */
}
}

View File

@@ -1,11 +0,0 @@
package handlers
import (
"net/http"
"GoMembership/internal/controllers"
)
func RegisterUserHandler(controller *controllers.UserController) http.Handler {
return http.HandlerFunc(controller.RegisterUser)
}

View File

@@ -11,6 +11,7 @@ type User struct {
DateOfBirth time.Time `gorm:"not null" json:"date_of_birth" validate:"required,age"` DateOfBirth time.Time `gorm:"not null" json:"date_of_birth" validate:"required,age"`
CreatedAt time.Time CreatedAt time.Time
Salt *string `json:"-"` Salt *string `json:"-"`
Company *string `json:"company" validate:"omitempty,omitnil"`
Phone string `json:"phone" validate:"omitempty,omitnil"` Phone string `json:"phone" validate:"omitempty,omitnil"`
Notes *string `json:"notes"` Notes *string `json:"notes"`
FirstName string `gorm:"not null" json:"first_name" validate:"required"` FirstName string `gorm:"not null" json:"first_name" validate:"required"`