141 lines
4.0 KiB
Go
141 lines
4.0 KiB
Go
package wecom
|
|
|
|
import (
|
|
"io"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestWeComAPIURL_DefaultBase(t *testing.T) {
|
|
p := &Platform{}
|
|
got := p.wecomAPIURL("/cgi-bin/gettoken", url.Values{
|
|
"corpid": []string{"ww-test"},
|
|
"corpsecret": []string{"sec-test"},
|
|
})
|
|
want := "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ww-test&corpsecret=sec-test"
|
|
if got != want {
|
|
t.Fatalf("url = %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestWeComAPIURL_CustomBase(t *testing.T) {
|
|
p := &Platform{apiBaseURL: "https://wecom.internal.example.com/"}
|
|
got := p.wecomAPIURL("/cgi-bin/message/send", url.Values{
|
|
"access_token": []string{"tok"},
|
|
})
|
|
want := "https://wecom.internal.example.com/cgi-bin/message/send?access_token=tok"
|
|
if got != want {
|
|
t.Fatalf("url = %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestNew_DefaultAPIBaseURL(t *testing.T) {
|
|
pf, err := New(map[string]any{
|
|
"corp_id": "ww_test",
|
|
"corp_secret": "sec_test",
|
|
"agent_id": "1000002",
|
|
"callback_token": "cb_token",
|
|
"callback_aes_key": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("New returned error: %v", err)
|
|
}
|
|
|
|
p, ok := pf.(*Platform)
|
|
if !ok {
|
|
t.Fatalf("platform type = %T, want *wecom.Platform", pf)
|
|
}
|
|
if p.apiBaseURL != defaultAPIBaseURL {
|
|
t.Fatalf("apiBaseURL = %q, want %q", p.apiBaseURL, defaultAPIBaseURL)
|
|
}
|
|
}
|
|
|
|
func TestNew_CustomAPIBaseURL_TrimTrailingSlash(t *testing.T) {
|
|
pf, err := New(map[string]any{
|
|
"corp_id": "ww_test",
|
|
"corp_secret": "sec_test",
|
|
"agent_id": "1000002",
|
|
"callback_token": "cb_token",
|
|
"callback_aes_key": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
|
|
"api_base_url": "https://wecom.internal.example.com/",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("New returned error: %v", err)
|
|
}
|
|
|
|
p, ok := pf.(*Platform)
|
|
if !ok {
|
|
t.Fatalf("platform type = %T, want *wecom.Platform", pf)
|
|
}
|
|
if p.apiBaseURL != "https://wecom.internal.example.com" {
|
|
t.Fatalf("apiBaseURL = %q, want %q", p.apiBaseURL, "https://wecom.internal.example.com")
|
|
}
|
|
}
|
|
|
|
// fakeWeComTokenRT serves a single canned /cgi-bin/gettoken response so
|
|
// getAccessToken's cache arithmetic can be exercised without network.
|
|
type fakeWeComTokenRT struct {
|
|
body string
|
|
}
|
|
|
|
func (f *fakeWeComTokenRT) RoundTrip(req *http.Request) (*http.Response, error) {
|
|
return &http.Response{
|
|
StatusCode: http.StatusOK,
|
|
Body: io.NopCloser(strings.NewReader(f.body)),
|
|
Header: make(http.Header),
|
|
Request: req,
|
|
}, nil
|
|
}
|
|
|
|
func TestGetAccessToken_ZeroExpiresIn_FallsBackToDefault(t *testing.T) {
|
|
p := &Platform{
|
|
corpID: "ww_test",
|
|
corpSecret: "sec_test",
|
|
apiBaseURL: defaultAPIBaseURL,
|
|
apiClient: &http.Client{
|
|
Transport: &fakeWeComTokenRT{body: `{"errcode":0,"errmsg":"ok","access_token":"tok-zero","expires_in":0}`},
|
|
},
|
|
}
|
|
|
|
before := time.Now()
|
|
tok, err := p.getAccessToken()
|
|
if err != nil {
|
|
t.Fatalf("getAccessToken() error = %v", err)
|
|
}
|
|
if tok != "tok-zero" {
|
|
t.Fatalf("token = %q, want %q", tok, "tok-zero")
|
|
}
|
|
|
|
// Without the fallback, expiresAt = time.Now() - 60s, so the cached
|
|
// token would be stale on the very next call and every getAccessToken
|
|
// invocation would re-fetch from /cgi-bin/gettoken.
|
|
window := p.tokenCache.expiresAt.Sub(before)
|
|
if window < time.Hour {
|
|
t.Errorf("tokenCache window for expires_in=0 = %v, want >= 1h (zero should fall back, not cache for -60s)", window)
|
|
}
|
|
}
|
|
|
|
func TestGetAccessToken_NormalExpiresIn_AppliesBuffer(t *testing.T) {
|
|
p := &Platform{
|
|
corpID: "ww_test",
|
|
corpSecret: "sec_test",
|
|
apiBaseURL: defaultAPIBaseURL,
|
|
apiClient: &http.Client{
|
|
Transport: &fakeWeComTokenRT{body: `{"errcode":0,"errmsg":"ok","access_token":"tok-7200","expires_in":7200}`},
|
|
},
|
|
}
|
|
|
|
before := time.Now()
|
|
if _, err := p.getAccessToken(); err != nil {
|
|
t.Fatalf("getAccessToken() error = %v", err)
|
|
}
|
|
// 7200 - 60 buffer = 7140s = 119 min. Allow a wide tolerance for elapsed time.
|
|
window := p.tokenCache.expiresAt.Sub(before)
|
|
if window < 110*time.Minute || window > 120*time.Minute {
|
|
t.Errorf("tokenCache window for expires_in=7200 = %v, want ~7140s (110-120min)", window)
|
|
}
|
|
}
|