Files
gochat/internal/handler/api/v1/contact_inbox_handler_test.go
T
2026-06-04 15:44:48 +08:00

223 lines
6.6 KiB
Go

package v1
import (
"encoding/json"
"net/http"
"net/http/httptest"
"fmt"
"testing"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/suite"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"github.com/gochat/gochat/internal/model"
"github.com/gochat/gochat/internal/repository"
"github.com/gochat/gochat/internal/service"
)
// ContactInboxHandlerTestSuite tests ContactInboxHandler with real SQLite DB.
type ContactInboxHandlerTestSuite struct {
suite.Suite
db *gorm.DB
router *gin.Engine
handler *ContactInboxHandler
}
func (s *ContactInboxHandlerTestSuite) SetupSuite() {
gin.SetMode(gin.TestMode)
db, err := gorm.Open(sqlite.Open("file::memory:"), &gorm.Config{
Logger: logger.Default.LogMode(logger.Silent),
})
s.Require().NoError(err, "failed to open SQLite test database")
// Auto-migrate required models (including FK dependencies)
s.Require().NoError(db.AutoMigrate(
&model.Account{},
&model.Inbox{},
&model.Contact{},
&model.ContactInbox{},
), "failed to auto-migrate models")
s.db = db
repo := repository.NewContactInboxRepo(db)
svc := service.NewContactInboxService(repo)
s.handler = NewContactInboxHandler(svc)
r := gin.New()
s.router = r
accounts := r.Group("/api/v1/accounts/:id")
{
accounts.GET("/contact_inboxes/filter", s.handler.Filter)
}
}
func (s *ContactInboxHandlerTestSuite) TearDownSuite() {
sqlDB, err := s.db.DB()
if err == nil {
sqlDB.Close()
}
}
func (s *ContactInboxHandlerTestSuite) SetupTest() {
s.db.Exec("DELETE FROM contact_inboxes")
s.db.Exec("DELETE FROM contacts")
s.db.Exec("DELETE FROM inboxes")
s.db.Exec("DELETE FROM accounts")
}
// helper: create an account
func (s *ContactInboxHandlerTestSuite) createAccount(name string) *model.Account {
a := &model.Account{Name: name}
s.Require().NoError(s.db.Create(a).Error)
return a
}
// helper: create an inbox scoped to an account
func (s *ContactInboxHandlerTestSuite) createInbox(accountID uint, name string) *model.Inbox {
i := &model.Inbox{AccountID: accountID, Name: name, ChannelType: "channel_email"}
s.Require().NoError(s.db.Create(i).Error)
return i
}
// helper: create a contact scoped to an account
func (s *ContactInboxHandlerTestSuite) createContact(accountID uint, name string) *model.Contact {
c := &model.Contact{AccountID: accountID, Name: name}
s.Require().NoError(s.db.Create(c).Error)
return c
}
// helper: create a contact_inbox record directly via DB
func (s *ContactInboxHandlerTestSuite) createContactInbox(contactID, inboxID uint, sourceID string) *model.ContactInbox {
ci := &model.ContactInbox{
ContactID: contactID,
InboxID: inboxID,
SourceID: sourceID,
HMACToken: "test_hmac",
PubsubToken: "test_pubsub",
}
s.Require().NoError(s.db.Create(ci).Error)
return ci
}
// --- Filter tests ---
func (s *ContactInboxHandlerTestSuite) TestFilter_InvalidAccountID() {
w := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/api/v1/accounts/abc/contact_inboxes/filter", nil)
s.router.ServeHTTP(w, req)
s.Equal(http.StatusBadRequest, w.Code)
var body map[string]interface{}
s.NoError(json.Unmarshal(w.Body.Bytes(), &body))
s.Contains(body, "error")
}
func (s *ContactInboxHandlerTestSuite) TestFilter_EmptyResult() {
a := s.createAccount("TestAccount")
w := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet,
"/api/v1/accounts/"+fmt.Sprintf("%d", a.ID)+"/contact_inboxes/filter", nil)
s.router.ServeHTTP(w, req)
s.Equal(http.StatusOK, w.Code)
var body map[string]interface{}
s.NoError(json.Unmarshal(w.Body.Bytes(), &body))
s.NotNil(body["contact_inboxes"])
cis := body["contact_inboxes"].([]interface{})
s.Len(cis, 0)
}
func (s *ContactInboxHandlerTestSuite) TestFilter_WithResults() {
a := s.createAccount("TestAccount")
i := s.createInbox(a.ID, "TestInbox")
c := s.createContact(a.ID, "TestContact")
s.createContactInbox(c.ID, i.ID, "src123")
w := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet,
"/api/v1/accounts/"+fmt.Sprintf("%d", a.ID)+"/contact_inboxes/filter", nil)
s.router.ServeHTTP(w, req)
s.Equal(http.StatusOK, w.Code)
var body map[string]interface{}
s.NoError(json.Unmarshal(w.Body.Bytes(), &body))
s.NotNil(body["contact_inboxes"])
}
func (s *ContactInboxHandlerTestSuite) TestFilter_WithInboxIDFilter() {
a := s.createAccount("TestAccount")
i1 := s.createInbox(a.ID, "Inbox1")
i2 := s.createInbox(a.ID, "Inbox2")
c := s.createContact(a.ID, "TestContact")
s.createContactInbox(c.ID, i1.ID, "src1")
s.createContactInbox(c.ID, i2.ID, "src2")
w := httptest.NewRecorder()
url := "/api/v1/accounts/" + fmt.Sprintf("%d", a.ID) +
"/contact_inboxes/filter?inbox_id=" + fmt.Sprintf("%d", i1.ID)
req := httptest.NewRequest(http.MethodGet, url, nil)
s.router.ServeHTTP(w, req)
s.Equal(http.StatusOK, w.Code)
}
func (s *ContactInboxHandlerTestSuite) TestFilter_WithContactIDFilter() {
a := s.createAccount("TestAccount")
i := s.createInbox(a.ID, "Inbox")
c1 := s.createContact(a.ID, "Contact1")
c2 := s.createContact(a.ID, "Contact2")
s.createContactInbox(c1.ID, i.ID, "src1")
s.createContactInbox(c2.ID, i.ID, "src2")
w := httptest.NewRecorder()
url := "/api/v1/accounts/" + fmt.Sprintf("%d", a.ID) +
"/contact_inboxes/filter?contact_id=" + fmt.Sprintf("%d", c1.ID)
req := httptest.NewRequest(http.MethodGet, url, nil)
s.router.ServeHTTP(w, req)
s.Equal(http.StatusOK, w.Code)
}
func (s *ContactInboxHandlerTestSuite) TestFilter_WithSourceIDFilter() {
a := s.createAccount("TestAccount")
i := s.createInbox(a.ID, "Inbox")
c := s.createContact(a.ID, "Contact")
s.createContactInbox(c.ID, i.ID, "special_source")
w := httptest.NewRecorder()
url := "/api/v1/accounts/" + fmt.Sprintf("%d", a.ID) +
"/contact_inboxes/filter?source_id=special_source"
req := httptest.NewRequest(http.MethodGet, url, nil)
s.router.ServeHTTP(w, req)
s.Equal(http.StatusOK, w.Code)
}
func (s *ContactInboxHandlerTestSuite) TestFilter_Pagination() {
a := s.createAccount("TestAccount")
i := s.createInbox(a.ID, "Inbox")
c := s.createContact(a.ID, "Contact")
for j := 0; j < 5; j++ {
s.createContactInbox(c.ID, i.ID, "src"+fmt.Sprintf("%d", j))
}
w := httptest.NewRecorder()
url := "/api/v1/accounts/" + fmt.Sprintf("%d", a.ID) +
"/contact_inboxes/filter?page=1&page_size=2"
req := httptest.NewRequest(http.MethodGet, url, nil)
s.router.ServeHTTP(w, req)
s.Equal(http.StatusOK, w.Code)
var body map[string]interface{}
s.NoError(json.Unmarshal(w.Body.Bytes(), &body))
meta := body["meta"].(map[string]interface{})
s.Equal(float64(5), meta["count"])
}
func TestContactInboxHandlerTestSuite(t *testing.T) {
suite.Run(t, new(ContactInboxHandlerTestSuite))
}