template-monorepo/test/e2e/auth_test.go

97 lines
3.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//go:build e2e
package e2e
import (
"encoding/json"
"net/http"
"testing"
"github.com/stretchr/testify/require"
)
// TestZZZ_AuthTokenRefreshAndLogout runs last (separate go test invocation).
// It uses an isolated refresh so seed tokens used by member/permission stay valid.
func TestZZZ_AuthTokenRefreshAndLogout(t *testing.T) {
e2eStep(t, "A-10/A-11", "POST", "/api/v1/auth/{token/refresh,logout}", "刷新 token → 用新 access 打 /me → logout → 黑名單後再打 /me=401")
c := isolatedAuthClient(t)
refreshEnv := c.DoExpectOK(t, http.MethodPost, "/api/v1/auth/token/refresh", map[string]string{
"refresh_token": c.Fixture.RefreshToken,
}, false)
var pair struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
UID string `json:"uid"`
}
require.NoError(t, json.Unmarshal(refreshEnv.Data, &pair))
require.Equal(t, c.Fixture.UID, pair.UID)
c.Fixture.AccessToken = pair.AccessToken
c.Fixture.RefreshToken = pair.RefreshToken
c.DoExpectOK(t, http.MethodGet, "/api/v1/members/me", nil, true)
c.DoExpectOK(t, http.MethodPost, "/api/v1/auth/logout", nil, true)
resp, env := c.Do(t, http.MethodGet, "/api/v1/members/me", nil, true)
require.Equal(t, http.StatusUnauthorized, resp.StatusCode)
require.NotEqual(t, int64(successCode), env.Code)
}
func TestAuth_MissingBearer_401(t *testing.T) {
e2eStep(t, "A-12", "GET", "/api/v1/members/me", "未帶 Bearer → 401AuthJWT middleware")
c := NewClient(t)
resp, env := c.Do(t, http.MethodGet, "/api/v1/members/me", nil, false)
require.Equal(t, http.StatusUnauthorized, resp.StatusCode)
require.NotEqual(t, int64(successCode), env.Code)
}
func TestAuth_PublicValidationErrors(t *testing.T) {
e2eStep(t, "A-13", "POST", "/api/v1/auth/*", "公開 Auth 端點輸入驗證錯誤 → 400 + Facade scope")
c := NewClient(t)
cases := []struct {
name string
path string
body any
}{
{
name: "register missing required fields",
path: "/api/v1/auth/register",
body: map[string]any{},
},
{
name: "login invalid email and password",
path: "/api/v1/auth/login",
body: map[string]any{
"tenant_slug": c.Fixture.TenantSlug,
"email": "not-an-email",
"password": "short",
},
},
{
name: "token refresh missing token",
path: "/api/v1/auth/token/refresh",
body: map[string]any{},
},
{
name: "social login invalid provider",
path: "/api/v1/auth/login/social/start",
body: map[string]any{
"tenant_slug": c.Fixture.TenantSlug,
"provider": "github",
"redirect_uri": "http://127.0.0.1/callback",
},
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
env := c.DoExpectHTTP(t, http.MethodPost, tc.path, tc.body, false, http.StatusBadRequest)
require.NotEqual(t, int64(successCode), env.Code)
// Facade scope 10101000 = InputInvalidFormatgateway parse / validate 進入點)
require.Equal(t, int64(10), env.Code/1_000_000, "expected Facade scope, got code=%d", env.Code)
})
}
}