Add Apple Sign In welcome email, notification preferences on registration, and contractor sharing tests
- Send welcome email to new users who sign up via Apple Sign In - Create notification preferences (all enabled) when new accounts are created - Add comprehensive integration tests for contractor sharing: - Personal contractors only visible to creator - Residence-tied contractors visible to all users with residence access - Update/delete access control for shared contractors 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -24,15 +24,17 @@ import (
|
||||
|
||||
// TestApp holds all components for integration testing
|
||||
type TestApp struct {
|
||||
DB *gorm.DB
|
||||
Router *gin.Engine
|
||||
AuthHandler *handlers.AuthHandler
|
||||
ResidenceHandler *handlers.ResidenceHandler
|
||||
TaskHandler *handlers.TaskHandler
|
||||
UserRepo *repositories.UserRepository
|
||||
ResidenceRepo *repositories.ResidenceRepository
|
||||
TaskRepo *repositories.TaskRepository
|
||||
AuthService *services.AuthService
|
||||
DB *gorm.DB
|
||||
Router *gin.Engine
|
||||
AuthHandler *handlers.AuthHandler
|
||||
ResidenceHandler *handlers.ResidenceHandler
|
||||
TaskHandler *handlers.TaskHandler
|
||||
ContractorHandler *handlers.ContractorHandler
|
||||
UserRepo *repositories.UserRepository
|
||||
ResidenceRepo *repositories.ResidenceRepository
|
||||
TaskRepo *repositories.TaskRepository
|
||||
ContractorRepo *repositories.ContractorRepository
|
||||
AuthService *services.AuthService
|
||||
}
|
||||
|
||||
func setupIntegrationTest(t *testing.T) *TestApp {
|
||||
@@ -713,3 +715,103 @@ func TestIntegration_ResponseStructure(t *testing.T) {
|
||||
func formatID(id float64) string {
|
||||
return fmt.Sprintf("%d", uint(id))
|
||||
}
|
||||
|
||||
// setupContractorTest sets up a test environment including contractor routes
|
||||
func setupContractorTest(t *testing.T) *TestApp {
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
db := testutil.SetupTestDB(t)
|
||||
testutil.SeedLookupData(t, db)
|
||||
|
||||
// Create repositories
|
||||
userRepo := repositories.NewUserRepository(db)
|
||||
residenceRepo := repositories.NewResidenceRepository(db)
|
||||
taskRepo := repositories.NewTaskRepository(db)
|
||||
contractorRepo := repositories.NewContractorRepository(db)
|
||||
|
||||
// Create config
|
||||
cfg := &config.Config{
|
||||
Security: config.SecurityConfig{
|
||||
SecretKey: "test-secret-key-for-integration-tests",
|
||||
PasswordResetExpiry: 15 * time.Minute,
|
||||
ConfirmationExpiry: 24 * time.Hour,
|
||||
MaxPasswordResetRate: 3,
|
||||
},
|
||||
}
|
||||
|
||||
// Create services
|
||||
authService := services.NewAuthService(userRepo, cfg)
|
||||
residenceService := services.NewResidenceService(residenceRepo, userRepo, cfg)
|
||||
taskService := services.NewTaskService(taskRepo, residenceRepo)
|
||||
contractorService := services.NewContractorService(contractorRepo, residenceRepo)
|
||||
|
||||
// Create handlers
|
||||
authHandler := handlers.NewAuthHandler(authService, nil, nil)
|
||||
residenceHandler := handlers.NewResidenceHandler(residenceService, nil, nil)
|
||||
taskHandler := handlers.NewTaskHandler(taskService, nil)
|
||||
contractorHandler := handlers.NewContractorHandler(contractorService)
|
||||
|
||||
// Create router with real middleware
|
||||
router := gin.New()
|
||||
|
||||
// Public routes
|
||||
auth := router.Group("/api/auth")
|
||||
{
|
||||
auth.POST("/register", authHandler.Register)
|
||||
auth.POST("/login", authHandler.Login)
|
||||
}
|
||||
|
||||
// Protected routes
|
||||
authMiddleware := middleware.NewAuthMiddleware(db, nil)
|
||||
api := router.Group("/api")
|
||||
api.Use(authMiddleware.TokenAuth())
|
||||
{
|
||||
api.GET("/auth/me", authHandler.CurrentUser)
|
||||
api.POST("/auth/logout", authHandler.Logout)
|
||||
|
||||
residences := api.Group("/residences")
|
||||
{
|
||||
residences.GET("", residenceHandler.ListResidences)
|
||||
residences.POST("", residenceHandler.CreateResidence)
|
||||
residences.GET("/:id", residenceHandler.GetResidence)
|
||||
residences.PUT("/:id", residenceHandler.UpdateResidence)
|
||||
residences.DELETE("/:id", residenceHandler.DeleteResidence)
|
||||
residences.POST("/:id/generate-share-code", residenceHandler.GenerateShareCode)
|
||||
residences.GET("/:id/users", residenceHandler.GetResidenceUsers)
|
||||
residences.DELETE("/:id/users/:userId", residenceHandler.RemoveResidenceUser)
|
||||
}
|
||||
api.POST("/residences/join-with-code", residenceHandler.JoinWithCode)
|
||||
|
||||
tasks := api.Group("/tasks")
|
||||
{
|
||||
tasks.GET("", taskHandler.ListTasks)
|
||||
tasks.POST("", taskHandler.CreateTask)
|
||||
tasks.GET("/:id", taskHandler.GetTask)
|
||||
tasks.PUT("/:id", taskHandler.UpdateTask)
|
||||
tasks.DELETE("/:id", taskHandler.DeleteTask)
|
||||
}
|
||||
|
||||
contractors := api.Group("/contractors")
|
||||
{
|
||||
contractors.GET("", contractorHandler.ListContractors)
|
||||
contractors.POST("", contractorHandler.CreateContractor)
|
||||
contractors.GET("/:id", contractorHandler.GetContractor)
|
||||
contractors.PUT("/:id", contractorHandler.UpdateContractor)
|
||||
contractors.DELETE("/:id", contractorHandler.DeleteContractor)
|
||||
}
|
||||
}
|
||||
|
||||
return &TestApp{
|
||||
DB: db,
|
||||
Router: router,
|
||||
AuthHandler: authHandler,
|
||||
ResidenceHandler: residenceHandler,
|
||||
TaskHandler: taskHandler,
|
||||
ContractorHandler: contractorHandler,
|
||||
UserRepo: userRepo,
|
||||
ResidenceRepo: residenceRepo,
|
||||
TaskRepo: taskRepo,
|
||||
ContractorRepo: contractorRepo,
|
||||
AuthService: authService,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user