Align GoChat with Chatwoot frontend contracts

This commit is contained in:
2026-06-13 22:13:32 +08:00
parent 71abf58636
commit d884fdda0a
162 changed files with 9825 additions and 528 deletions
@@ -32,10 +32,13 @@ func setupNotificationSubscriptionHandlerTest(t *testing.T, userID uint) (*gin.E
router.POST("/api/v1/notification_subscriptions", handler.Create)
router.DELETE("/api/v1/notification_subscriptions", handler.Destroy)
router.DELETE("/api/v1/notification_subscriptions/:identifier", handler.Destroy)
router.POST("/api/v1/accounts/:account_id/notification_subscriptions/", handler.Create)
router.DELETE("/api/v1/accounts/:account_id/notification_subscriptions/", handler.Destroy)
router.DELETE("/api/v1/accounts/:account_id/notification_subscriptions/:identifier", handler.Destroy)
return router, db
}
func TestNotificationSubscriptionCreateAcceptsFrontendPayload(t *testing.T) {
func TestNotificationSubscriptionCreateAcceptsPushHelperPayload(t *testing.T) {
router, db := setupNotificationSubscriptionHandlerTest(t, 7)
body := `{"subscription_type":"browser_push","subscription_attributes":{"endpoint":"https://push.example/sub","p256dh":"key","auth":"secret"}}`
@@ -49,14 +52,54 @@ func TestNotificationSubscriptionCreateAcceptsFrontendPayload(t *testing.T) {
require.NoError(t, json.Unmarshal(w.Body.Bytes(), &payload), w.Body.String())
require.NotContains(t, payload, "success")
require.NotContains(t, payload, "data")
require.NotZero(t, payload["id"])
require.Equal(t, "https://push.example/sub", payload["identifier"])
require.Equal(t, "browser_push", payload["subscription_type"])
require.Equal(t, float64(7), payload["user_id"])
require.NotEmpty(t, payload["created_at"])
require.NotEmpty(t, payload["updated_at"])
require.Equal(t, map[string]any{
"endpoint": "https://push.example/sub",
"p256dh": "key",
"auth": "secret",
}, payload["subscription_attributes"])
var sub model.NotificationSubscription
require.NoError(t, db.First(&sub).Error)
require.Equal(t, uint(7), sub.UserID)
require.Equal(t, "https://push.example/sub", sub.Identifier)
require.Equal(t, model.NotificationSubBrowserPush, sub.SubscriptionType)
require.JSONEq(t, `{"endpoint":"https://push.example/sub","p256dh":"key","auth":"secret"}`, string(sub.SubscriptionAttributes))
}
func TestNotificationSubscriptionCreateAcceptsAccountScopedPushHelperPayload(t *testing.T) {
router, db := setupNotificationSubscriptionHandlerTest(t, 9)
body := `{"subscription_type":"browser_push","subscription_attributes":{"endpoint":"https://push.example/account-scoped","p256dh":"account-key","auth":"account-secret"}}`
req := httptest.NewRequest(http.MethodPost, "/api/v1/accounts/42/notification_subscriptions/", bytes.NewBufferString(body))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
require.Equal(t, http.StatusOK, w.Code)
var payload map[string]any
require.NoError(t, json.Unmarshal(w.Body.Bytes(), &payload), w.Body.String())
require.NotContains(t, payload, "success")
require.NotContains(t, payload, "data")
require.Equal(t, "https://push.example/account-scoped", payload["identifier"])
require.Equal(t, "browser_push", payload["subscription_type"])
require.Equal(t, float64(9), payload["user_id"])
require.Equal(t, map[string]any{
"endpoint": "https://push.example/account-scoped",
"p256dh": "account-key",
"auth": "account-secret",
}, payload["subscription_attributes"])
var sub model.NotificationSubscription
require.NoError(t, db.First(&sub).Error)
require.Equal(t, uint(9), sub.UserID)
require.Equal(t, "https://push.example/account-scoped", sub.Identifier)
require.JSONEq(t, `{"endpoint":"https://push.example/account-scoped","p256dh":"account-key","auth":"account-secret"}`, string(sub.SubscriptionAttributes))
}
func TestNotificationSubscriptionCreateAcceptsRailsWrapperAndUpdatesExisting(t *testing.T) {
@@ -103,6 +146,27 @@ func TestNotificationSubscriptionDestroyUsesPushTokenAndReturnsEmptyOK(t *testin
require.Equal(t, int64(0), count)
}
func TestNotificationSubscriptionDestroyAccountScopedUsesPushToken(t *testing.T) {
router, db := setupNotificationSubscriptionHandlerTest(t, 7)
sub := model.NotificationSubscription{
Identifier: "https://push.example/account-scoped-delete",
UserID: 7,
SubscriptionType: model.NotificationSubBrowserPush,
SubscriptionAttributes: json.RawMessage(`{"endpoint":"https://push.example/account-scoped-delete","p256dh":"key","auth":"secret"}`),
}
require.NoError(t, db.Create(&sub).Error)
req := httptest.NewRequest(http.MethodDelete, "/api/v1/accounts/42/notification_subscriptions/?push_token=https%3A%2F%2Fpush.example%2Faccount-scoped-delete", nil)
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
require.Equal(t, http.StatusOK, w.Code)
require.Empty(t, w.Body.String())
var count int64
require.NoError(t, db.Model(&model.NotificationSubscription{}).Where("id = ?", sub.ID).Count(&count).Error)
require.Equal(t, int64(0), count)
}
func TestNotificationSubscriptionDestroyMissingTokenStillOK(t *testing.T) {
router, _ := setupNotificationSubscriptionHandlerTest(t, 7)