152 lines
5.9 KiB
Go
152 lines
5.9 KiB
Go
package v1
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/stretchr/testify/require"
|
|
"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"
|
|
)
|
|
|
|
func TestInboxHandler_ChatwootSerializerParity(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
|
|
db, err := gorm.Open(sqlite.Open("file:inbox_handler_parity?mode=memory&cache=shared"), &gorm.Config{
|
|
Logger: logger.Default.LogMode(logger.Silent),
|
|
})
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() {
|
|
sqlDB, dbErr := db.DB()
|
|
if dbErr == nil {
|
|
_ = sqlDB.Close()
|
|
}
|
|
})
|
|
require.NoError(t, db.AutoMigrate(&model.Account{}, &model.Inbox{}))
|
|
|
|
account := &model.Account{Name: "Inbox Parity", Locale: "en", Active: true}
|
|
require.NoError(t, db.Create(account).Error)
|
|
widget := &model.Inbox{
|
|
AccountID: account.ID,
|
|
Name: "Website",
|
|
ChannelType: "web_widget",
|
|
ChannelID: 11,
|
|
Enabled: true,
|
|
AvatarURL: "https://example.com/avatar.png",
|
|
GreetingEnabled: true,
|
|
GreetingMessage: "Welcome",
|
|
EnableEmailCollect: true,
|
|
EnableAutoAssignment: true,
|
|
AllowMessagesAfterResolved: true,
|
|
SenderNameType: "friendly_name",
|
|
BusinessName: "Example Co",
|
|
Timezone: "UTC",
|
|
ChannelConfig: `{"website_token":"web-token","hmac_token":"hmac-token","widget_color":"#1f93ff","website_url":"https://example.com","welcome_title":"Hi","welcome_tagline":"We reply fast","reply_time":"in_a_few_minutes","pre_chat_form_enabled":true,"pre_chat_form_options":{"fields":[{"name":"email"}]},"continuity_via_email":true}`,
|
|
}
|
|
require.NoError(t, db.Create(widget).Error)
|
|
apiInbox := &model.Inbox{
|
|
AccountID: account.ID,
|
|
Name: "API",
|
|
ChannelType: "api",
|
|
ChannelID: 12,
|
|
Enabled: true,
|
|
WebhookURL: "https://example.com/hook",
|
|
Secret: "api-secret",
|
|
ChannelConfig: `{"identifier":"api-identifier","hmac_token":"api-hmac","additional_attributes":{"source":"frontend"}}`,
|
|
}
|
|
require.NoError(t, db.Create(apiInbox).Error)
|
|
|
|
router := setupInboxParityRouter(db)
|
|
|
|
list := inboxParityRequest(t, router, http.MethodGet, fmt.Sprintf("/api/v1/accounts/%d/inboxes/", account.ID), nil)
|
|
require.Equal(t, http.StatusOK, list.Code, list.Body.String())
|
|
listData := inboxParityObject(t, list)
|
|
require.NotContains(t, listData, "inboxes")
|
|
payload := listData["payload"].([]any)
|
|
require.Len(t, payload, 2)
|
|
first := payload[0].(map[string]any)
|
|
require.Equal(t, "Channel::Api", first["channel_type"])
|
|
require.Equal(t, "api-secret", first["secret"])
|
|
require.Equal(t, "api-identifier", first["inbox_identifier"])
|
|
|
|
show := inboxParityRequest(t, router, http.MethodGet, fmt.Sprintf("/api/v1/accounts/%d/inboxes/%d", account.ID, widget.ID), nil)
|
|
require.Equal(t, http.StatusOK, show.Code, show.Body.String())
|
|
showData := inboxParityObject(t, show)
|
|
require.NotContains(t, showData, "payload")
|
|
require.Equal(t, "Channel::WebWidget", showData["channel_type"])
|
|
require.Equal(t, "web-token", showData["website_token"])
|
|
require.Equal(t, "hmac-token", showData["hmac_token"])
|
|
require.Equal(t, "#1f93ff", showData["widget_color"])
|
|
require.Equal(t, "https://example.com", showData["website_url"])
|
|
require.Equal(t, true, showData["pre_chat_form_enabled"])
|
|
require.IsType(t, []any{}, showData["working_hours"])
|
|
|
|
update := inboxParityRequest(t, router, http.MethodPatch, fmt.Sprintf("/api/v1/accounts/%d/inboxes/%d", account.ID, widget.ID), map[string]any{
|
|
"name": "Website Updated",
|
|
"enable_auto_assignment": false,
|
|
})
|
|
require.Equal(t, http.StatusOK, update.Code, update.Body.String())
|
|
updateData := inboxParityObject(t, update)
|
|
require.Equal(t, "Website Updated", updateData["name"])
|
|
require.Equal(t, false, updateData["enable_auto_assignment"])
|
|
|
|
deleteAvatar := inboxParityRequest(t, router, http.MethodDelete, fmt.Sprintf("/api/v1/accounts/%d/inboxes/%d/avatar", account.ID, widget.ID), nil)
|
|
require.Equal(t, http.StatusOK, deleteAvatar.Code, deleteAvatar.Body.String())
|
|
require.Empty(t, deleteAvatar.Body.String())
|
|
|
|
destroy := inboxParityRequest(t, router, http.MethodDelete, fmt.Sprintf("/api/v1/accounts/%d/inboxes/%d", account.ID, apiInbox.ID), nil)
|
|
require.Equal(t, http.StatusOK, destroy.Code, destroy.Body.String())
|
|
require.Equal(t, "Your inbox deletion request will be processed in some time.", inboxParityObject(t, destroy)["message"])
|
|
}
|
|
|
|
func setupInboxParityRouter(db *gorm.DB) *gin.Engine {
|
|
inboxSvc := service.NewInboxService(repository.NewInboxRepo(db), nil, nil, nil, nil, nil, nil)
|
|
handler := NewInboxHandler(inboxSvc)
|
|
router := gin.New()
|
|
inboxes := router.Group("/api/v1/accounts/:id/inboxes")
|
|
{
|
|
inboxes.GET("/", handler.List)
|
|
inboxes.GET("/:inbox_id", handler.Get)
|
|
inboxes.POST("/", handler.Create)
|
|
inboxes.PUT("/:inbox_id", handler.Update)
|
|
inboxes.PATCH("/:inbox_id", handler.Update)
|
|
inboxes.DELETE("/:inbox_id", handler.Delete)
|
|
inboxes.DELETE("/:inbox_id/avatar", handler.DeleteAvatar)
|
|
}
|
|
return router
|
|
}
|
|
|
|
func inboxParityRequest(t *testing.T, router *gin.Engine, method string, path string, body any) *httptest.ResponseRecorder {
|
|
t.Helper()
|
|
var reader *bytes.Reader
|
|
if body == nil {
|
|
reader = bytes.NewReader(nil)
|
|
} else {
|
|
payload, err := json.Marshal(body)
|
|
require.NoError(t, err)
|
|
reader = bytes.NewReader(payload)
|
|
}
|
|
req := httptest.NewRequest(method, path, reader)
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
return w
|
|
}
|
|
|
|
func inboxParityObject(t *testing.T, response *httptest.ResponseRecorder) map[string]any {
|
|
t.Helper()
|
|
var data map[string]any
|
|
require.NoError(t, json.Unmarshal(response.Body.Bytes(), &data), response.Body.String())
|
|
return data
|
|
}
|