250 lines
7.5 KiB
Go
250 lines
7.5 KiB
Go
package accountapiimp_test
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/tech/sendico/pkg/model"
|
|
"github.com/tech/sendico/server/interface/api/srequest"
|
|
"github.com/testcontainers/testcontainers-go"
|
|
"github.com/testcontainers/testcontainers-go/modules/mongodb"
|
|
"github.com/testcontainers/testcontainers-go/wait"
|
|
"go.mongodb.org/mongo-driver/mongo"
|
|
"go.mongodb.org/mongo-driver/mongo/options"
|
|
)
|
|
|
|
// Helper function to create string pointers
|
|
func stringPtr(s string) *string {
|
|
return &s
|
|
}
|
|
|
|
// TestSignupRequestSerialization tests JSON marshaling/unmarshaling with real MongoDB
|
|
func TestSignupRequestSerialization(t *testing.T) {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
|
|
defer cancel()
|
|
|
|
mongoContainer, err := mongodb.Run(ctx,
|
|
"mongo:latest",
|
|
mongodb.WithUsername("root"),
|
|
mongodb.WithPassword("password"),
|
|
testcontainers.WithWaitStrategy(wait.ForLog("Waiting for connections")),
|
|
)
|
|
require.NoError(t, err, "failed to start MongoDB container")
|
|
defer func() {
|
|
err := mongoContainer.Terminate(ctx)
|
|
require.NoError(t, err, "failed to terminate MongoDB container")
|
|
}()
|
|
|
|
mongoURI, err := mongoContainer.ConnectionString(ctx)
|
|
require.NoError(t, err, "failed to get MongoDB connection string")
|
|
|
|
clientOptions := options.Client().ApplyURI(mongoURI)
|
|
client, err := mongo.Connect(ctx, clientOptions)
|
|
require.NoError(t, err, "failed to connect to MongoDB")
|
|
defer func() {
|
|
err := client.Disconnect(ctx)
|
|
require.NoError(t, err, "failed to disconnect from MongoDB")
|
|
}()
|
|
|
|
db := client.Database("test_signup")
|
|
collection := db.Collection("signup_requests")
|
|
|
|
t.Run("StoreAndRetrieveSignupRequest", func(t *testing.T) {
|
|
signupRequest := srequest.Signup{
|
|
Account: model.AccountData{
|
|
LoginData: model.LoginData{
|
|
UserDataBase: model.UserDataBase{
|
|
Login: "test@example.com",
|
|
},
|
|
Password: "TestPassword123!",
|
|
},
|
|
Name: "Test User",
|
|
},
|
|
OrganizationName: "Test Organization",
|
|
OrganizationTimeZone: "UTC",
|
|
DefaultPriorityGroup: srequest.CreatePriorityGroup{
|
|
Description: model.Describable{
|
|
Name: "Default Priority Group",
|
|
},
|
|
Priorities: []model.Colorable{
|
|
{
|
|
Describable: model.Describable{Name: "High"},
|
|
Color: stringPtr("#FF0000"),
|
|
},
|
|
{
|
|
Describable: model.Describable{Name: "Medium"},
|
|
Color: stringPtr("#FFFF00"),
|
|
},
|
|
{
|
|
Describable: model.Describable{Name: "Low"},
|
|
Color: stringPtr("#00FF00"),
|
|
},
|
|
},
|
|
},
|
|
AnonymousUser: model.Describable{
|
|
Name: "Anonymous User",
|
|
},
|
|
OwnerRole: model.Describable{
|
|
Name: "Owner",
|
|
},
|
|
AnonymousRole: model.Describable{
|
|
Name: "Anonymous",
|
|
},
|
|
}
|
|
|
|
// Store in MongoDB
|
|
result, err := collection.InsertOne(ctx, signupRequest)
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, result.InsertedID)
|
|
|
|
// Retrieve from MongoDB
|
|
var retrieved srequest.Signup
|
|
err = collection.FindOne(ctx, map[string]interface{}{"_id": result.InsertedID}).Decode(&retrieved)
|
|
require.NoError(t, err)
|
|
|
|
// Verify data integrity
|
|
assert.Equal(t, signupRequest.Account.Login, retrieved.Account.Login)
|
|
assert.Equal(t, signupRequest.Account.Name, retrieved.Account.Name)
|
|
assert.Equal(t, signupRequest.OrganizationName, retrieved.OrganizationName)
|
|
assert.Equal(t, signupRequest.OrganizationTimeZone, retrieved.OrganizationTimeZone)
|
|
assert.Equal(t, len(signupRequest.DefaultPriorityGroup.Priorities), len(retrieved.DefaultPriorityGroup.Priorities))
|
|
|
|
// Verify priorities
|
|
for i, priority := range signupRequest.DefaultPriorityGroup.Priorities {
|
|
assert.Equal(t, priority.Name, retrieved.DefaultPriorityGroup.Priorities[i].Name)
|
|
if priority.Color != nil && retrieved.DefaultPriorityGroup.Priorities[i].Color != nil {
|
|
assert.Equal(t, *priority.Color, *retrieved.DefaultPriorityGroup.Priorities[i].Color)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
// TestSignupHTTPSerialization tests HTTP request/response serialization
|
|
func TestSignupHTTPSerialization(t *testing.T) {
|
|
signupRequest := srequest.Signup{
|
|
Account: model.AccountData{
|
|
LoginData: model.LoginData{
|
|
UserDataBase: model.UserDataBase{
|
|
Login: "test@example.com",
|
|
},
|
|
Password: "TestPassword123!",
|
|
},
|
|
Name: "Test User",
|
|
},
|
|
OrganizationName: "Test Organization",
|
|
OrganizationTimeZone: "UTC",
|
|
DefaultPriorityGroup: srequest.CreatePriorityGroup{
|
|
Description: model.Describable{
|
|
Name: "Default Priority Group",
|
|
},
|
|
Priorities: []model.Colorable{
|
|
{
|
|
Describable: model.Describable{Name: "High"},
|
|
Color: stringPtr("#FF0000"),
|
|
},
|
|
},
|
|
},
|
|
AnonymousUser: model.Describable{
|
|
Name: "Anonymous User",
|
|
},
|
|
OwnerRole: model.Describable{
|
|
Name: "Owner",
|
|
},
|
|
AnonymousRole: model.Describable{
|
|
Name: "Anonymous",
|
|
},
|
|
}
|
|
|
|
t.Run("ValidJSONRequest", func(t *testing.T) {
|
|
// Serialize to JSON
|
|
reqBody, err := json.Marshal(signupRequest)
|
|
require.NoError(t, err)
|
|
|
|
// Create HTTP request
|
|
req := httptest.NewRequest(http.MethodPost, "/signup", bytes.NewBuffer(reqBody))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
// Parse the request body
|
|
var parsedRequest srequest.Signup
|
|
err = json.NewDecoder(req.Body).Decode(&parsedRequest)
|
|
require.NoError(t, err)
|
|
|
|
// Verify parsing
|
|
assert.Equal(t, signupRequest.Account.Login, parsedRequest.Account.Login)
|
|
assert.Equal(t, signupRequest.Account.Name, parsedRequest.Account.Name)
|
|
assert.Equal(t, signupRequest.OrganizationName, parsedRequest.OrganizationName)
|
|
})
|
|
|
|
t.Run("UnicodeCharacters", func(t *testing.T) {
|
|
unicodeRequest := signupRequest
|
|
unicodeRequest.Account.Name = "Test 用户 Üser"
|
|
unicodeRequest.OrganizationName = "测试 Organization"
|
|
|
|
// Serialize to JSON
|
|
reqBody, err := json.Marshal(unicodeRequest)
|
|
require.NoError(t, err)
|
|
|
|
// Parse back
|
|
var parsedRequest srequest.Signup
|
|
err = json.Unmarshal(reqBody, &parsedRequest)
|
|
require.NoError(t, err)
|
|
|
|
// Verify unicode characters are preserved
|
|
assert.Equal(t, "Test 用户 Üser", parsedRequest.Account.Name)
|
|
assert.Equal(t, "测试 Organization", parsedRequest.OrganizationName)
|
|
})
|
|
|
|
t.Run("InvalidJSONRequest", func(t *testing.T) {
|
|
invalidJSON := `{"account": {"login": "test@example.com", "password": "invalid json structure`
|
|
|
|
req := httptest.NewRequest(http.MethodPost, "/signup", bytes.NewBufferString(invalidJSON))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
var parsedRequest srequest.Signup
|
|
err := json.NewDecoder(req.Body).Decode(&parsedRequest)
|
|
assert.Error(t, err, "Should fail to parse invalid JSON")
|
|
})
|
|
}
|
|
|
|
// TestAccountDataConversion tests conversion between request and model types
|
|
func TestAccountDataConversion(t *testing.T) {
|
|
accountData := model.AccountData{
|
|
LoginData: model.LoginData{
|
|
UserDataBase: model.UserDataBase{
|
|
Login: "test@example.com",
|
|
},
|
|
Password: "TestPassword123!",
|
|
},
|
|
Name: "Test User",
|
|
}
|
|
|
|
t.Run("ToAccount", func(t *testing.T) {
|
|
account := accountData.ToAccount()
|
|
|
|
assert.Equal(t, accountData.Login, account.Login)
|
|
assert.Equal(t, accountData.Password, account.Password)
|
|
assert.Equal(t, accountData.Name, account.Name)
|
|
|
|
// Verify the account has proper structure
|
|
assert.NotNil(t, account)
|
|
assert.IsType(t, &model.Account{}, account)
|
|
})
|
|
|
|
t.Run("PasswordHandling", func(t *testing.T) {
|
|
account := accountData.ToAccount()
|
|
|
|
// Original password should be preserved before validation
|
|
assert.Equal(t, "TestPassword123!", account.Password)
|
|
|
|
// Verify password is not empty
|
|
assert.NotEmpty(t, account.Password)
|
|
})
|
|
}
|