Files
evening_detective_server/internal/app/team_registration_test.go
T
2026-10-11 16:00:18 +07:00

97 lines
5.1 KiB
Go

package app
import (
"context"
"errors"
"evening_detective_server/internal/services/game_model"
"evening_detective_server/internal/services/team_service"
"net/http"
"net/http/httptest"
"strings"
"testing"
)
func TestTeamRegistrationHandler(t *testing.T) {
valid := `{"name":"Команда","email":"captain@example.org","participantsCount":5}`
for _, tc := range []struct {
name, token, auth, gameID, deliveryID, body string
serviceErr error
want int
called bool
}{
{"success", "secret", "Bearer secret", "42", "delivery", valid, nil, 200, true},
{"disabled", "", "Bearer secret", "42", "delivery", valid, nil, 503, false},
{"no token", "secret", "", "42", "delivery", valid, nil, 401, false},
{"wrong token", "secret", "Bearer wrong", "42", "delivery", valid, nil, 401, false},
{"bad game", "secret", "Bearer secret", "0", "delivery", valid, nil, 400, false},
{"no delivery", "secret", "Bearer secret", "42", "", valid, nil, 400, false},
{"malformed", "secret", "Bearer secret", "42", "delivery", `{`, nil, 400, false},
{"extra object", "secret", "Bearer secret", "42", "delivery", valid + ` {}`, nil, 400, false},
{"unknown field", "secret", "Bearer secret", "42", "delivery", `{"extra":1}`, nil, 400, false},
{"jsonrpc", "secret", "Bearer secret", "42", "delivery", `{"jsonrpc":"2.0","method":"register","params":{"name":"Команда","email":"captain@example.org","participantsCount":5},"id":1}`, nil, 200, true},
{"jsonrpc string count", "secret", "Bearer secret", "42", "delivery", `{"jsonrpc":"2.0","method":"register","params":{"name":"Команда","email":"captain@example.org","participantsCount":"5"},"id":1}`, nil, 200, true},
{"too large", "secret", "Bearer secret", "42", "delivery", `{"name":"` + strings.Repeat("a", 17000) + `"}`, nil, 400, false},
{"invalid fields", "secret", "Bearer secret", "42", "delivery", valid, team_service.ErrInvalidRegistration, 400, true},
{"closed", "secret", "Bearer secret", "42", "delivery", valid, team_service.ErrRegistrationClosed, 409, true},
{"internal", "secret", "Bearer secret", "42", "delivery", valid, errors.New("private database detail"), 500, true},
} {
t.Run(tc.name, func(t *testing.T) {
called := false
mux := http.NewServeMux()
mux.Handle("POST /api/games/{id}/registrations", TeamRegistrationHandler(tc.token, func(ctx context.Context, gameID int, deliveryID string, registration team_service.Registration) (string, error) {
called = true
if gameID != 42 || deliveryID != "delivery" || registration.Name != "Команда" || registration.Email != "captain@example.org" || registration.ParticipantsCount != 5 {
t.Fatal("incorrect registration passed to service")
}
if _, ok := ctx.Deadline(); !ok {
t.Fatal("missing deadline")
}
return "019a1234-5678-7abc-8def-000000000007", tc.serviceErr
}))
req := httptest.NewRequest(http.MethodPost, "/api/games/"+tc.gameID+"/registrations", strings.NewReader(tc.body))
req.Header.Set("Authorization", tc.auth)
req.Header.Set("X-Delivery-Id", tc.deliveryID)
res := httptest.NewRecorder()
mux.ServeHTTP(res, req)
if res.Code != tc.want || called != tc.called {
t.Fatalf("status=%d called=%v body=%s", res.Code, called, res.Body.String())
}
if tc.name == "success" && res.Body.String() != "{\"id\":\"019a1234-5678-7abc-8def-000000000007\"}\n" {
t.Fatal(res.Body.String())
}
if strings.Contains(res.Body.String(), "private database detail") {
t.Fatal("private error exposed")
}
if tc.name == "invalid fields" && !strings.Contains(res.Body.String(), team_service.ErrInvalidRegistration.Error()) {
t.Fatalf("public validation error missing: %s", res.Body.String())
}
if tc.name == "closed" && !strings.Contains(res.Body.String(), team_service.ErrRegistrationClosed.Error()) {
t.Fatalf("public registration error missing: %s", res.Body.String())
}
if tc.name == "malformed" && !strings.Contains(res.Body.String(), "unexpected EOF") {
t.Fatalf("malformed JSON reason missing: %s", res.Body.String())
}
if tc.name == "unknown field" && !strings.Contains(res.Body.String(), "unknown field") {
t.Fatalf("unknown field reason missing: %s", res.Body.String())
}
if tc.name == "extra object" && !strings.Contains(res.Body.String(), "лишние данные") {
t.Fatalf("extra data reason missing: %s", res.Body.String())
}
if tc.name == "jsonrpc" && !strings.Contains(res.Body.String(), `"jsonrpc":"2.0"`) {
t.Fatalf("JSON-RPC response missing: %s", res.Body.String())
}
})
}
}
func TestCaptainContactOnlyInGameDetails(t *testing.T) {
team := &game_model.Team{ID: "019a1234-5678-7abc-8def-000000000001", CaptainEmail: "captain@example.org", ParticipantsCount: 5}
details := mapGame(&game_model.Game{Teams: []*game_model.Team{team}})
if details.Teams[0].CaptainEmail != team.CaptainEmail || details.Teams[0].ParticipantsCount != 5 {
t.Fatal("registration details missing from organizer view")
}
if mapTeam(team).CaptainEmail != "" {
t.Fatal("captain email exposed in shared team/results mapping")
}
}