77 lines
2.5 KiB
Go
77 lines
2.5 KiB
Go
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
|
|
}
|