You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
138 lines
5.1 KiB
138 lines
5.1 KiB
package httpapi
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"juegoland/games2/internal/domain/catalog"
|
|
"juegoland/games2/internal/server"
|
|
)
|
|
|
|
func TestPublishedCatalogIsTheOnlyPublicCatalog(t *testing.T) {
|
|
registry := catalog.NewRegistry([]catalog.Game{
|
|
{ID: "draft", Title: "Borrador", Published: false},
|
|
{ID: "conecta4", Version: "1.0.0", Title: "Conecta 4", Summary: "Cuatro fichas en línea", MinPlayers: 2, MaxPlayers: 2, Published: true},
|
|
})
|
|
handler := NewHandler(server.NewService(registry, time.Now))
|
|
recorder := httptest.NewRecorder()
|
|
handler.ServeHTTP(recorder, httptest.NewRequest(http.MethodGet, "/api/v2/catalog", nil))
|
|
if recorder.Code != http.StatusOK {
|
|
t.Fatalf("status = %d, want 200", recorder.Code)
|
|
}
|
|
if recorder.Header().Get("Cache-Control") != "no-store" {
|
|
t.Fatal("catalog response must not be cached before audience policies exist")
|
|
}
|
|
var body struct {
|
|
RequestID string `json:"requestId"`
|
|
Data struct {
|
|
Items []struct {
|
|
ID string `json:"id"`
|
|
} `json:"items"`
|
|
} `json:"data"`
|
|
}
|
|
if err := json.Unmarshal(recorder.Body.Bytes(), &body); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if body.RequestID == "" || len(body.Data.Items) != 1 || body.Data.Items[0].ID != "conecta4" {
|
|
t.Fatalf("unexpected catalog response: %+v", body)
|
|
}
|
|
}
|
|
|
|
func TestBootstrapDoesNotAdvertiseUnavailableFeatures(t *testing.T) {
|
|
handler := NewHandler(server.NewService(catalog.NewRegistry(nil), func() time.Time {
|
|
return time.Date(2026, time.October, 5, 12, 0, 0, 0, time.UTC)
|
|
}))
|
|
recorder := httptest.NewRecorder()
|
|
handler.ServeHTTP(recorder, httptest.NewRequest(http.MethodGet, "/api/v2/bootstrap", nil))
|
|
if recorder.Code != http.StatusOK {
|
|
t.Fatalf("status = %d, want 200", recorder.Code)
|
|
}
|
|
var body struct {
|
|
Data server.Bootstrap `json:"data"`
|
|
}
|
|
if err := json.Unmarshal(recorder.Body.Bytes(), &body); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if body.Data.Features.Rooms || body.Data.Features.Chat || !body.Data.Features.Catalog {
|
|
t.Fatalf("incorrect advertised features: %+v", body.Data.Features)
|
|
}
|
|
if len(body.Data.PlatformProtocolVersions) != 0 || len(body.Data.GameProtocolVersions) != 0 {
|
|
t.Fatal("unimplemented realtime protocols must not be advertised")
|
|
}
|
|
if body.Data.DefaultLocale != "es" || len(body.Data.SupportedLocales) != 2 || body.Data.SupportedLocales[1] != "en" {
|
|
t.Fatalf("wrong locale capabilities: %+v", body.Data)
|
|
}
|
|
if body.Data.ServerTime.Format(time.RFC3339) != "2026-10-05T12:00:00Z" {
|
|
t.Fatalf("wrong server time: %s", body.Data.ServerTime)
|
|
}
|
|
}
|
|
|
|
func TestCatalogNegotiatesLanguageAndLabelsFallback(t *testing.T) {
|
|
registry := catalog.NewRegistry([]catalog.Game{
|
|
{
|
|
ID: "conecta4", Version: "1.0.0", Title: "Conecta 4", Summary: "Cuatro en línea",
|
|
DefaultLocale: "es", MinPlayers: 2, MaxPlayers: 2, Published: true,
|
|
Translations: map[string]catalog.Translation{
|
|
"en": {Title: "Connect Four", Summary: "Four in a row"},
|
|
},
|
|
},
|
|
})
|
|
handler := NewHandler(server.NewService(registry, time.Now))
|
|
request := httptest.NewRequest(http.MethodGet, "/api/v2/catalog", nil)
|
|
request.Header.Set("Accept-Language", "fr, en-GB;q=0.9, es;q=0.5")
|
|
recorder := httptest.NewRecorder()
|
|
handler.ServeHTTP(recorder, request)
|
|
var body struct {
|
|
Data struct {
|
|
Items []struct {
|
|
Title string `json:"title"`
|
|
Locale string `json:"locale"`
|
|
} `json:"items"`
|
|
} `json:"data"`
|
|
}
|
|
if err := json.Unmarshal(recorder.Body.Bytes(), &body); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(body.Data.Items) != 1 || body.Data.Items[0].Title != "Connect Four" || body.Data.Items[0].Locale != "en" {
|
|
t.Fatalf("unexpected translated catalog: %+v", body)
|
|
}
|
|
if recorder.Header().Get("Content-Language") != "en" || recorder.Header().Get("Vary") != "Accept-Language" {
|
|
t.Fatalf("missing language headers: %+v", recorder.Header())
|
|
}
|
|
|
|
request = httptest.NewRequest(http.MethodGet, "/api/v2/catalog", nil)
|
|
request.Header.Set("Accept-Language", "de, en;q=0, es;q=0.5")
|
|
recorder = httptest.NewRecorder()
|
|
handler.ServeHTTP(recorder, request)
|
|
if recorder.Header().Get("Content-Language") != "es" {
|
|
t.Fatalf("expected Spanish fallback, got %q", recorder.Header().Get("Content-Language"))
|
|
}
|
|
}
|
|
|
|
func TestCatalogDeclaresGameFallbackLanguage(t *testing.T) {
|
|
registry := catalog.NewRegistry([]catalog.Game{
|
|
{ID: "hundido", Version: "1.0.0", Title: "Hundir la flota", Summary: "Encuentra los barcos", DefaultLocale: "es", MinPlayers: 2, MaxPlayers: 2, Published: true},
|
|
})
|
|
handler := NewHandler(server.NewService(registry, time.Now))
|
|
request := httptest.NewRequest(http.MethodGet, "/api/v2/catalog", nil)
|
|
request.Header.Set("Accept-Language", "en")
|
|
recorder := httptest.NewRecorder()
|
|
handler.ServeHTTP(recorder, request)
|
|
var body struct {
|
|
Data struct {
|
|
Items []struct {
|
|
Locale string `json:"locale"`
|
|
} `json:"items"`
|
|
} `json:"data"`
|
|
}
|
|
if err := json.Unmarshal(recorder.Body.Bytes(), &body); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(body.Data.Items) != 1 || body.Data.Items[0].Locale != "es" || recorder.Header().Get("Content-Language") != "es" {
|
|
t.Fatalf("fallback language not declared: %+v, header: %q", body, recorder.Header().Get("Content-Language"))
|
|
}
|
|
}
|