feat: backend service
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
package testenv
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Pilot bundles a registered Session with its resolved user_id and a
|
||||
// pre-built BackendUserClient so tests do not have to repeat the
|
||||
// resolution dance for each redeem call.
|
||||
type Pilot struct {
|
||||
Session *Session
|
||||
UserID string
|
||||
HTTP *BackendUserClient
|
||||
RaceName string
|
||||
}
|
||||
|
||||
// EnrollPilots registers `count` pilots with synthetic
|
||||
// `Player01..PlayerNN` race names and the matching
|
||||
// `playerNN+suffix@example.com` emails, then has owner issue an
|
||||
// invite for each one and the pilot redeem it. The game must be in
|
||||
// `enrollment_open` (or any state that accepts invites + redeem).
|
||||
//
|
||||
// The helper exists because the engine's `/api/v1/admin/init` enforces
|
||||
// `len(races) >= 10`, so any runtime-driven scenario needs at least
|
||||
// ten enrolled members. Using it from tests keeps each pilot a real
|
||||
// authenticated user, exactly mirroring how operators would seed a
|
||||
// production game.
|
||||
func EnrollPilots(t *testing.T, plat *Platform, ownerHTTP *BackendUserClient, gameID string, count int, suffix string) []*Pilot {
|
||||
t.Helper()
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
pilots := make([]*Pilot, 0, count)
|
||||
for i := 1; i <= count; i++ {
|
||||
raceName := fmt.Sprintf("Player%02d", i)
|
||||
email := fmt.Sprintf("player%02d+%s@example.com", i, suffix)
|
||||
|
||||
sess := RegisterSession(t, plat, email)
|
||||
userID, err := sess.LookupUserID(ctx, plat)
|
||||
if err != nil {
|
||||
t.Fatalf("pilot %s: resolve user_id: %v", raceName, err)
|
||||
}
|
||||
|
||||
raw, resp, err := ownerHTTP.Do(ctx, http.MethodPost, "/api/v1/user/lobby/games/"+gameID+"/invites", map[string]any{
|
||||
"invited_user_id": userID,
|
||||
"race_name": raceName,
|
||||
})
|
||||
if err != nil || resp.StatusCode != http.StatusCreated {
|
||||
t.Fatalf("pilot %s: issue invite: err=%v status=%d body=%s", raceName, err, resp.StatusCode, string(raw))
|
||||
}
|
||||
var invite struct {
|
||||
InviteID string `json:"invite_id"`
|
||||
}
|
||||
if err := json.Unmarshal(raw, &invite); err != nil {
|
||||
t.Fatalf("pilot %s: decode invite: %v", raceName, err)
|
||||
}
|
||||
|
||||
pilotHTTP := NewBackendUserClient(plat.Backend.HTTPURL, userID)
|
||||
raw, resp, err = pilotHTTP.Do(ctx, http.MethodPost, "/api/v1/user/lobby/games/"+gameID+"/invites/"+invite.InviteID+"/redeem", nil)
|
||||
if err != nil || resp.StatusCode/100 != 2 {
|
||||
t.Fatalf("pilot %s: redeem: err=%v status=%d body=%s", raceName, err, resp.StatusCode, string(raw))
|
||||
}
|
||||
|
||||
pilots = append(pilots, &Pilot{
|
||||
Session: sess,
|
||||
UserID: userID,
|
||||
HTTP: pilotHTTP,
|
||||
RaceName: raceName,
|
||||
})
|
||||
}
|
||||
return pilots
|
||||
}
|
||||
Reference in New Issue
Block a user