Files
gochat/backend/internal/handler/api/v1/social_authorization_test.go
T

119 lines
4.6 KiB
Go

package v1
import (
"encoding/json"
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt/v5"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func setupSocialAuthorizationRouter() *gin.Engine {
gin.SetMode(gin.TestMode)
r := gin.New()
r.RedirectTrailingSlash = false
instagramHandler := NewInstagramChannelHandler(nil, nil, nil, nil)
tiktokHandler := NewTikTokChannelHandler(nil, nil, nil, nil)
r.POST("/api/v1/accounts/:account_id/instagram/authorization", instagramHandler.ChatwootAuthorization)
r.POST("/api/v1/accounts/:account_id/tiktok/authorization", tiktokHandler.ChatwootAuthorization)
return r
}
func TestInstagramAuthorization_ReturnsChatwootPayload(t *testing.T) {
t.Setenv("FRONTEND_URL", "https://app.example.test/")
r := setupSocialAuthorizationRouter()
w := httptest.NewRecorder()
req, _ := http.NewRequest(http.MethodPost, "/api/v1/accounts/42/instagram/authorization", strings.NewReader(`{"return_to":"onboarding","app_id":"instagram-client","app_secret":"instagram-secret"}`))
req.Header.Set("Content-Type", "application/json")
r.ServeHTTP(w, req)
assert.Equal(t, http.StatusOK, w.Code)
var resp map[string]interface{}
require.NoError(t, json.Unmarshal(w.Body.Bytes(), &resp))
assert.Equal(t, true, resp["success"])
parsed, err := url.Parse(resp["url"].(string))
require.NoError(t, err)
assert.Equal(t, "https://api.instagram.com/oauth/authorize", parsed.Scheme+"://"+parsed.Host+parsed.Path)
query := parsed.Query()
assert.Equal(t, "instagram-client", query.Get("client_id"))
assert.Equal(t, "https://app.example.test/instagram/callback", query.Get("redirect_uri"))
assert.Equal(t, "instagram_business_basic,instagram_business_manage_messages", query.Get("scope"))
assert.Equal(t, "0", query.Get("enable_fb_login"))
assert.Equal(t, "1", query.Get("force_authentication"))
assert.Equal(t, "code", query.Get("response_type"))
assertSocialSignedState(t, query.Get("state"), "instagram-secret", 42, "onboarding")
}
func TestTikTokAuthorization_ReturnsChatwootPayload(t *testing.T) {
t.Setenv("FRONTEND_URL", "https://app.example.test")
r := setupSocialAuthorizationRouter()
w := httptest.NewRecorder()
req, _ := http.NewRequest(http.MethodPost, "/api/v1/accounts/42/tiktok/authorization?return_to=onboarding", strings.NewReader(`{"app_id":"tiktok-client","app_secret":"tiktok-secret","return_to":"body-target"}`))
req.Header.Set("Content-Type", "application/json")
r.ServeHTTP(w, req)
assert.Equal(t, http.StatusOK, w.Code)
var resp map[string]interface{}
require.NoError(t, json.Unmarshal(w.Body.Bytes(), &resp))
assert.Equal(t, true, resp["success"])
parsed, err := url.Parse(resp["url"].(string))
require.NoError(t, err)
assert.Equal(t, "https://www.tiktok.com/v2/auth/authorize", parsed.Scheme+"://"+parsed.Host+parsed.Path)
query := parsed.Query()
assert.Equal(t, "tiktok-client", query.Get("client_id"))
assert.Equal(t, "tiktok-client", query.Get("client_key"))
assert.Equal(t, "https://app.example.test/tiktok/callback", query.Get("redirect_uri"))
assert.Equal(t, tiktokAuthorizationScope, query.Get("scope"))
assert.Equal(t, "code", query.Get("response_type"))
assertSocialSignedState(t, query.Get("state"), "tiktok-secret", 42, "onboarding")
}
func TestSocialAuthorization_BadAccountID(t *testing.T) {
r := setupSocialAuthorizationRouter()
w := httptest.NewRecorder()
req, _ := http.NewRequest(http.MethodPost, "/api/v1/accounts/abc/instagram/authorization", nil)
r.ServeHTTP(w, req)
assert.Equal(t, http.StatusBadRequest, w.Code)
var resp map[string]interface{}
require.NoError(t, json.Unmarshal(w.Body.Bytes(), &resp))
errBody := resp["error"].(map[string]interface{})
assert.Contains(t, errBody["message"], "invalid account_id")
}
func TestSocialAuthorization_NotConfigured(t *testing.T) {
t.Setenv("INSTAGRAM_APP_ID", "")
t.Setenv("INSTAGRAM_APP_SECRET", "")
r := setupSocialAuthorizationRouter()
w := httptest.NewRecorder()
req, _ := http.NewRequest(http.MethodPost, "/api/v1/accounts/42/instagram/authorization", nil)
r.ServeHTTP(w, req)
assert.Equal(t, http.StatusUnprocessableEntity, w.Code)
var resp map[string]interface{}
require.NoError(t, json.Unmarshal(w.Body.Bytes(), &resp))
assert.Equal(t, false, resp["success"])
}
func assertSocialSignedState(t *testing.T, state string, secret string, accountID float64, returnTo string) {
t.Helper()
claims := jwt.MapClaims{}
token, err := jwt.ParseWithClaims(state, claims, func(token *jwt.Token) (any, error) {
return []byte(secret), nil
})
require.NoError(t, err)
require.True(t, token.Valid)
assert.Equal(t, accountID, claims["sub"])
assert.Equal(t, returnTo, claims["return_to"])
}