mirror of
https://wget.la/https://github.com/leookun/cursor-byok
synced 2026-08-18 03:57:06 +08:00
- Deleted the CursorAccountCard.vue component, which handled user account login and status. - Removed associated localization entries from catalog.json and various language files. - Updated Home.vue to eliminate references to the removed component. - Refactored clientApi.js to remove unused account-related API functions.
139 lines
5.4 KiB
Go
139 lines
5.4 KiB
Go
package upstream
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"cursor/gen/aiserverv1"
|
|
"cursor/internal/backend/server"
|
|
|
|
"google.golang.org/protobuf/proto"
|
|
)
|
|
|
|
func TestMockDevSessionTokenActionSupportsCursorDevLoginModes(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
query string
|
|
plan string
|
|
trial bool
|
|
}{
|
|
{name: "default", query: "", plan: "ultra"},
|
|
{name: "free", query: "?plan=free", plan: "free"},
|
|
{name: "pro trial", query: "?plan=pro&trial=true", plan: "pro", trial: true},
|
|
{name: "pro", query: "?plan=pro", plan: "pro"},
|
|
{name: "pro plus trial", query: "?plan=pro_plus&trial=true", plan: "pro_plus", trial: true},
|
|
{name: "pro plus", query: "?plan=pro_plus", plan: "pro_plus"},
|
|
{name: "ultra", query: "?plan=ultra", plan: "ultra"},
|
|
{name: "enterprise", query: "?plan=enterprise", plan: "enterprise"},
|
|
}
|
|
|
|
for _, testCase := range testCases {
|
|
t.Run(testCase.name, func(t *testing.T) {
|
|
request := httptest.NewRequest(http.MethodGet, "http://local/auth/cursor_dev_session_token"+testCase.query, nil)
|
|
recorder := httptest.NewRecorder()
|
|
handler := MockDevSessionTokenAction(Dependencies{}, CompatRouteConfig{Name: "dev_login", StatusCode: http.StatusOK})
|
|
if err := handler(&server.Context{Writer: recorder, Request: request}); err != nil {
|
|
t.Fatalf("dev login handler: %v", err)
|
|
}
|
|
if recorder.Code != http.StatusOK {
|
|
t.Fatalf("status: got %d, want %d; body=%s", recorder.Code, http.StatusOK, recorder.Body.String())
|
|
}
|
|
|
|
var response struct {
|
|
AccessToken string `json:"accessToken"`
|
|
RefreshToken string `json:"refreshToken"`
|
|
AuthID string `json:"authId"`
|
|
}
|
|
if err := json.Unmarshal(recorder.Body.Bytes(), &response); err != nil {
|
|
t.Fatalf("decode response: %v", err)
|
|
}
|
|
if response.AccessToken == "" || response.RefreshToken != response.AccessToken {
|
|
t.Fatalf("unexpected tokens: access=%q refresh=%q", response.AccessToken, response.RefreshToken)
|
|
}
|
|
claims, ok := localDevClaimsFromAuthorization("Bearer " + response.AccessToken)
|
|
if !ok {
|
|
t.Fatal("response access token is not a local dev JWT")
|
|
}
|
|
if claims.Plan != testCase.plan || claims.Trial != testCase.trial {
|
|
t.Fatalf("claims: got plan=%q trial=%v, want plan=%q trial=%v", claims.Plan, claims.Trial, testCase.plan, testCase.trial)
|
|
}
|
|
if response.AuthID != claims.Subject || claims.ExpiresAt <= time.Now().Unix() {
|
|
t.Fatalf("unexpected identity claims: response=%+v claims=%+v", response, claims)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMockDevSessionTokenActionUsesRequestedEmail(t *testing.T) {
|
|
request := httptest.NewRequest(http.MethodGet, "http://local/auth/cursor_dev_session_token?plan=pro&email=dev%2Bcursor%40example.com", nil)
|
|
recorder := httptest.NewRecorder()
|
|
handler := MockDevSessionTokenAction(Dependencies{}, CompatRouteConfig{Name: "dev_login", StatusCode: http.StatusOK})
|
|
if err := handler(&server.Context{Writer: recorder, Request: request}); err != nil {
|
|
t.Fatalf("dev login handler: %v", err)
|
|
}
|
|
|
|
var response map[string]string
|
|
if err := json.Unmarshal(recorder.Body.Bytes(), &response); err != nil {
|
|
t.Fatalf("decode response: %v", err)
|
|
}
|
|
claims, ok := localDevClaimsFromAuthorization(response["accessToken"])
|
|
if !ok || claims.Email != "dev+cursor@example.com" {
|
|
t.Fatalf("unexpected email claims: %+v", claims)
|
|
}
|
|
}
|
|
|
|
func TestMockDevSessionTokenActionRejectsUnsupportedOptions(t *testing.T) {
|
|
for _, query := range []string{"?plan=business", "?plan=ultra&trial=true", "?plan=pro&trial=maybe"} {
|
|
request := httptest.NewRequest(http.MethodGet, "http://local/auth/cursor_dev_session_token"+query, nil)
|
|
recorder := httptest.NewRecorder()
|
|
handler := MockDevSessionTokenAction(Dependencies{}, CompatRouteConfig{Name: "dev_login", StatusCode: http.StatusOK})
|
|
if err := handler(&server.Context{Writer: recorder, Request: request}); err != nil {
|
|
t.Fatalf("dev login handler for %q: %v", query, err)
|
|
}
|
|
if recorder.Code != http.StatusBadRequest {
|
|
t.Fatalf("status for %q: got %d, want %d", query, recorder.Code, http.StatusBadRequest)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestEnterpriseDevSessionProvidesBillableTeam(t *testing.T) {
|
|
token, _, err := buildLocalDevSessionToken("enterprise", false, "enterprise@example.com", time.Now())
|
|
if err != nil {
|
|
t.Fatalf("build token: %v", err)
|
|
}
|
|
reqCtx := authRequestContext(http.MethodPost, "/aiserver.v1.DashboardService/GetTeams", "", token)
|
|
payload, err := buildDashboardTeamsPayload(reqCtx)
|
|
if err != nil {
|
|
t.Fatalf("build teams: %v", err)
|
|
}
|
|
encoded, err := encodeMockProto("aiserver.v1.GetTeamsResponse", payload)
|
|
if err != nil {
|
|
t.Fatalf("encode teams: %v", err)
|
|
}
|
|
response := &aiserverv1.GetTeamsResponse{}
|
|
if err := proto.Unmarshal(encoded, response); err != nil {
|
|
t.Fatalf("decode teams: %v", err)
|
|
}
|
|
if len(response.Teams) != 1 || !response.Teams[0].GetHasBilling() || response.Teams[0].GetSeats() == 0 || !response.Teams[0].GetIsEnterprise() {
|
|
t.Fatalf("unexpected enterprise teams: %+v", response.Teams)
|
|
}
|
|
}
|
|
|
|
func authRequestContext(method string, path string, body string, token string) *RequestContext {
|
|
request := httptest.NewRequest(method, "http://local"+path, strings.NewReader(body))
|
|
if token != "" {
|
|
request.Header.Set("Authorization", "Bearer "+token)
|
|
}
|
|
return &RequestContext{
|
|
ResponseWriter: httptest.NewRecorder(),
|
|
Request: request,
|
|
Method: method,
|
|
Headers: request.Header.Clone(),
|
|
RequestBody: []byte(body),
|
|
}
|
|
}
|