package v1 import ( "bytes" "fmt" "net/http" "net/http/httptest" "testing" "github.com/gin-gonic/gin" "github.com/stretchr/testify/suite" "gorm.io/driver/sqlite" "gorm.io/gorm" "github.com/gochat/gochat/internal/model" "github.com/gochat/gochat/internal/repository" "github.com/gochat/gochat/internal/service" ) type CustomAttributeValueHandlerTestSuite struct { suite.Suite db *gorm.DB handler *CustomAttributeValueHandler router *gin.Engine account *model.Account } func (s *CustomAttributeValueHandlerTestSuite) SetupSuite() { s.db, _ = gorm.Open(sqlite.Open(":memory:"), &gorm.Config{}) s.db.AutoMigrate(&model.CustomAttributeDefinition{}, &model.Account{}, &model.Conversation{}, &model.Contact{}, &model.Inbox{}, &model.User{}) defRepo := repository.NewCustomAttributeDefinitionRepo(s.db) convRepo := repository.NewConversationRepo(s.db) contactRepo := repository.NewContactRepo(s.db) svc := service.NewCustomAttributeValueService(defRepo, convRepo, contactRepo) s.handler = NewCustomAttributeValueHandler(svc) gin.SetMode(gin.TestMode) r := gin.New() accountGroup := r.Group("/api/v1/accounts/:account_id") convGroup := accountGroup.Group("/conversations/:conversation_id") convGroup.POST("/custom_attributes", s.handler.SetConversationAttribute) convGroup.DELETE("/custom_attributes/:attribute_name", s.handler.RemoveConversationAttribute) contactGroup := accountGroup.Group("/contacts/:contact_id") contactGroup.POST("/custom_attributes", s.handler.SetContactAttribute) contactGroup.DELETE("/custom_attributes/:attribute_name", s.handler.RemoveContactAttribute) s.router = r s.account = &model.Account{Name: "TestAccount"} s.db.Create(s.account) // Create attribute definition for conversations s.db.Create(&model.CustomAttributeDefinition{ AccountID: s.account.ID, AttributeName: "priority", AttributeType: "text", AttributeModel: "conversation", }) // Create attribute definition for contacts s.db.Create(&model.CustomAttributeDefinition{ AccountID: s.account.ID, AttributeName: "company", AttributeType: "text", AttributeModel: "contact", }) } func (s *CustomAttributeValueHandlerTestSuite) TearDownSuite() { s.db.Exec("DELETE FROM custom_attribute_definitions") s.db.Exec("DELETE FROM conversations") s.db.Exec("DELETE FROM contacts") s.db.Exec("DELETE FROM accounts") } func (s *CustomAttributeValueHandlerTestSuite) SetupTest() { s.db.Exec("DELETE FROM conversations") s.db.Exec("DELETE FROM contacts") } func TestCustomAttributeValueHandlerTestSuite(t *testing.T) { suite.Run(t, new(CustomAttributeValueHandlerTestSuite)) } func (s *CustomAttributeValueHandlerTestSuite) TestSetConversationAttribute_InvalidAccountID() { w := httptest.NewRecorder() req := httptest.NewRequest(http.MethodPost, "/api/v1/accounts/abc/conversations/1/custom_attributes", bytes.NewBufferString(`{"attribute_name":"priority","value":"high"}`)) req.Header.Set("Content-Type", "application/json") s.router.ServeHTTP(w, req) s.Equal(http.StatusBadRequest, w.Code) } func (s *CustomAttributeValueHandlerTestSuite) TestSetConversationAttribute_InvalidConversationID() { w := httptest.NewRecorder() req := httptest.NewRequest(http.MethodPost, "/api/v1/accounts/1/conversations/abc/custom_attributes", bytes.NewBufferString(`{"attribute_name":"priority","value":"high"}`)) req.Header.Set("Content-Type", "application/json") s.router.ServeHTTP(w, req) s.Equal(http.StatusBadRequest, w.Code) } func (s *CustomAttributeValueHandlerTestSuite) TestSetConversationAttribute_InvalidJSON() { w := httptest.NewRecorder() req := httptest.NewRequest(http.MethodPost, fmt.Sprintf("/api/v1/accounts/%d/conversations/1/custom_attributes", s.account.ID), bytes.NewBufferString(`{invalid`)) req.Header.Set("Content-Type", "application/json") s.router.ServeHTTP(w, req) s.Equal(http.StatusBadRequest, w.Code) } func (s *CustomAttributeValueHandlerTestSuite) TestSetConversationAttribute_Success() { conv := &model.Conversation{AccountID: s.account.ID} s.db.Create(conv) body := `{"attribute_name":"priority","value":"high"}` w := httptest.NewRecorder() req := httptest.NewRequest(http.MethodPost, fmt.Sprintf("/api/v1/accounts/%d/conversations/%d/custom_attributes", s.account.ID, conv.ID), bytes.NewBufferString(body)) req.Header.Set("Content-Type", "application/json") s.router.ServeHTTP(w, req) s.Equal(http.StatusOK, w.Code) } func (s *CustomAttributeValueHandlerTestSuite) TestRemoveConversationAttribute_InvalidAccountID() { w := httptest.NewRecorder() req := httptest.NewRequest(http.MethodDelete, "/api/v1/accounts/abc/conversations/1/custom_attributes/priority", nil) s.router.ServeHTTP(w, req) s.Equal(http.StatusBadRequest, w.Code) } func (s *CustomAttributeValueHandlerTestSuite) TestRemoveConversationAttribute_Success() { conv := &model.Conversation{AccountID: s.account.ID} s.db.Create(conv) w := httptest.NewRecorder() req := httptest.NewRequest(http.MethodDelete, fmt.Sprintf("/api/v1/accounts/%d/conversations/%d/custom_attributes/priority", s.account.ID, conv.ID), nil) s.router.ServeHTTP(w, req) s.Equal(http.StatusOK, w.Code) } func (s *CustomAttributeValueHandlerTestSuite) TestSetContactAttribute_InvalidAccountID() { w := httptest.NewRecorder() req := httptest.NewRequest(http.MethodPost, "/api/v1/accounts/abc/contacts/1/custom_attributes", bytes.NewBufferString(`{"attribute_name":"company","value":"acme"}`)) req.Header.Set("Content-Type", "application/json") s.router.ServeHTTP(w, req) s.Equal(http.StatusBadRequest, w.Code) } func (s *CustomAttributeValueHandlerTestSuite) TestSetContactAttribute_InvalidContactID() { w := httptest.NewRecorder() req := httptest.NewRequest(http.MethodPost, "/api/v1/accounts/1/contacts/abc/custom_attributes", bytes.NewBufferString(`{"attribute_name":"company","value":"acme"}`)) req.Header.Set("Content-Type", "application/json") s.router.ServeHTTP(w, req) s.Equal(http.StatusBadRequest, w.Code) } func (s *CustomAttributeValueHandlerTestSuite) TestSetContactAttribute_Success() { contact := &model.Contact{AccountID: s.account.ID, Name: "TestContact"} s.db.Create(contact) body := `{"attribute_name":"company","value":"acme"}` w := httptest.NewRecorder() req := httptest.NewRequest(http.MethodPost, fmt.Sprintf("/api/v1/accounts/%d/contacts/%d/custom_attributes", s.account.ID, contact.ID), bytes.NewBufferString(body)) req.Header.Set("Content-Type", "application/json") s.router.ServeHTTP(w, req) s.Equal(http.StatusOK, w.Code) } func (s *CustomAttributeValueHandlerTestSuite) TestRemoveContactAttribute_Success() { contact := &model.Contact{AccountID: s.account.ID, Name: "TestContact"} s.db.Create(contact) w := httptest.NewRecorder() req := httptest.NewRequest(http.MethodDelete, fmt.Sprintf("/api/v1/accounts/%d/contacts/%d/custom_attributes/company", s.account.ID, contact.ID), nil) s.router.ServeHTTP(w, req) s.Equal(http.StatusOK, w.Code) }