Sub2API v1.0 - AI API 网关(二开初始版本,基于上游 Wei-Shaw/sub2api)
Release / update-version (push) Has been cancelled
Release / build-frontend (push) Has been cancelled
Release / release (push) Has been cancelled
Release / sync-version-file (push) Has been cancelled
CI / shell (push) Canceled after 0s
CI / test (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
Security Scan / backend-security (push) Canceled after 0s
Security Scan / frontend-security (push) Canceled after 0s
Release / update-version (push) Has been cancelled
Release / build-frontend (push) Has been cancelled
Release / release (push) Has been cancelled
Release / sync-version-file (push) Has been cancelled
CI / shell (push) Canceled after 0s
CI / test (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
Security Scan / backend-security (push) Canceled after 0s
Security Scan / frontend-security (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestDingTalkClient_ExchangeCodeForUserToken_Success(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
require.Equal(t, "POST", r.Method)
|
||||
require.Equal(t, "/v1.0/oauth2/userAccessToken", r.URL.Path)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"accessToken":"USER_TOKEN_X","expireIn":7200,"refreshToken":"R","corpId":"dingABC"}`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
cli := &DingTalkClient{
|
||||
cfg: dingTalkClientConfig{
|
||||
ClientID: "k", ClientSecret: "s",
|
||||
TokenURL: server.URL + "/v1.0/oauth2/userAccessToken",
|
||||
},
|
||||
httpClient: server.Client(),
|
||||
}
|
||||
resp, err := cli.ExchangeCodeForUserToken(context.Background(), "AUTH_CODE")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "USER_TOKEN_X", resp.AccessToken)
|
||||
require.Equal(t, "dingABC", resp.CorpID)
|
||||
}
|
||||
|
||||
func TestDingTalkClient_GetUnionIdByUserToken_Success(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
require.Equal(t, "USER_TOKEN_X", r.Header.Get("x-acs-dingtalk-access-token"))
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"nick":"张三","unionId":"UID_AAA","openId":"OPEN","avatarUrl":"http://x"}`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
cli := &DingTalkClient{
|
||||
cfg: dingTalkClientConfig{UserInfoURL: server.URL + "/v1.0/contact/users/me"},
|
||||
httpClient: server.Client(),
|
||||
}
|
||||
unionID, nick, err := cli.GetUnionIdByUserToken(context.Background(), "USER_TOKEN_X")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "UID_AAA", unionID)
|
||||
require.Equal(t, "张三", nick)
|
||||
}
|
||||
|
||||
func TestDingTalkClient_GetAppToken_Cached(t *testing.T) {
|
||||
callCount := 0
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
callCount++
|
||||
_, _ = w.Write([]byte(`{"accessToken":"APP_TKN","expireIn":7200}`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
cli := &DingTalkClient{
|
||||
cfg: dingTalkClientConfig{ClientID: "k", ClientSecret: "s", TokenURL: server.URL + "/gettoken"},
|
||||
httpClient: server.Client(),
|
||||
}
|
||||
t1, err := cli.GetAppToken(context.Background())
|
||||
require.NoError(t, err)
|
||||
t2, err := cli.GetAppToken(context.Background())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, t1, t2)
|
||||
require.Equal(t, 1, callCount, "second call should hit cache")
|
||||
}
|
||||
|
||||
func TestDingTalkClient_GetUserIdByUnionId_60011(t *testing.T) {
|
||||
appTokenServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
_, _ = w.Write([]byte(`{"accessToken":"APP_TKN","expireIn":7200}`))
|
||||
}))
|
||||
defer appTokenServer.Close()
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"errcode":60011,"errmsg":"not in directory"}`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
cli := &DingTalkClient{
|
||||
cfg: dingTalkClientConfig{TokenURL: appTokenServer.URL + "/gettoken"},
|
||||
httpClient: server.Client(),
|
||||
}
|
||||
cli.appToken = "APP_TKN"
|
||||
cli.appTokenExp = time.Now().Add(time.Hour)
|
||||
cli.cfg.UserInfoURL = server.URL + "/v1.0/contact/users/byUnionId"
|
||||
|
||||
_, err := cli.GetUserIdByUnionId(context.Background(), "UID_AAA")
|
||||
require.Error(t, err)
|
||||
apiErr, ok := err.(*DingTalkAPIError)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, "60011", apiErr.Code)
|
||||
}
|
||||
|
||||
// TestDingTalkClient_GetDeptInfo_Success 验证 GetDeptInfo 正常情况返回部门信息。
|
||||
func TestDingTalkClient_GetDeptInfo_Success(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"errcode":0,"errmsg":"ok","result":{"dept_id":42,"name":"AI数据","parent_id":1}}`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
cli := &DingTalkClient{
|
||||
cfg: dingTalkClientConfig{
|
||||
UserInfoURL: server.URL + "/stub", // 不含 /contact/users/me,走 test stub 路径
|
||||
},
|
||||
httpClient: server.Client(),
|
||||
}
|
||||
cli.appToken = "APP_TKN"
|
||||
cli.appTokenExp = time.Now().Add(time.Hour)
|
||||
|
||||
info, err := cli.GetDeptInfo(context.Background(), 42)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(42), info.DeptID)
|
||||
require.Equal(t, "AI数据", info.Name)
|
||||
require.Equal(t, int64(1), info.ParentID)
|
||||
}
|
||||
|
||||
// TestDingTalkClient_GetDeptInfo_ErrCode60003 验证 errcode=60003(部门不存在)时返回错误。
|
||||
func TestDingTalkClient_GetDeptInfo_ErrCode60003(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"errcode":60003,"errmsg":"dept not found"}`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
cli := &DingTalkClient{
|
||||
cfg: dingTalkClientConfig{UserInfoURL: server.URL + "/stub"},
|
||||
httpClient: server.Client(),
|
||||
}
|
||||
cli.appToken = "APP_TKN"
|
||||
cli.appTokenExp = time.Now().Add(time.Hour)
|
||||
|
||||
_, err := cli.GetDeptInfo(context.Background(), 999)
|
||||
require.Error(t, err)
|
||||
apiErr, ok := err.(*DingTalkAPIError)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, "60003", apiErr.Code)
|
||||
}
|
||||
Reference in New Issue
Block a user