package harness import ( "encoding/json" "net/http" "net/http/httptest" "strings" "testing" ) // LobbyStub answers the single Lobby internal request the start // service performs ([`internal/adapters/lobbyclient`]). The start // service treats this response as ancillary diagnostics — the start // envelope already carries `image_ref` — so the stub returns a // deterministic 200 OK and lets the runtime ignore the payload. // // The stub only validates that the runtime configuration treats the // Lobby URL as required (so it cannot regress to nil-out the // ancillary fetch); the response body itself is unused by the // integration assertions. type LobbyStub struct { Server *httptest.Server } // NewLobbyStub returns a started httptest.Server. The caller registers // `t.Cleanup(stub.Close)` themselves through the runtime helper so the // stub follows the same lifecycle as the rest of the per-test wiring. func NewLobbyStub(t testing.TB) *LobbyStub { t.Helper() mux := http.NewServeMux() mux.HandleFunc("GET /api/v1/internal/games/{game_id}", func(w http.ResponseWriter, r *http.Request) { gameID := strings.TrimSpace(r.PathValue("game_id")) if gameID == "" { writeStubError(w, http.StatusBadRequest, "invalid_request", "game_id is required") return } w.Header().Set("Content-Type", "application/json; charset=utf-8") w.WriteHeader(http.StatusOK) _ = json.NewEncoder(w).Encode(map[string]string{ "game_id": gameID, "status": "running", "target_engine_version": "1.0.0", }) }) server := httptest.NewServer(mux) t.Cleanup(server.Close) return &LobbyStub{Server: server} } // URL returns the base URL of the running stub. func (stub *LobbyStub) URL() string { return stub.Server.URL } func writeStubError(w http.ResponseWriter, status int, code, message string) { w.Header().Set("Content-Type", "application/json; charset=utf-8") w.WriteHeader(status) _ = json.NewEncoder(w).Encode(map[string]any{ "error": map[string]string{"code": code, "message": message}, }) }