// package api handles launcher-specific API calls to the backend. package api import ( "encoding/json" "net/http" "net/http/httptest" "testing" "time" "gitea.mrixs.me/Mrixs/MrixsCraft-launcher/internal/ui/screens" "github.com/stretchr/testify/require" ) func TestFetchServerList_Success(t *testing.T) { // Arrange - create mock server response serverResp := ServerResponse{ Servers: []ServerInfo{ {Slug: "hitech", Name: "HiTech 1.21", Version: "1.21", IP: "192.168.1.100"}, {Slug: "vanilla", Name: "Vanilla 1.20", Version: "1.20", IP: "192.168.1.101"}, }, } // Create test server with mock response testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/api/servers.json" { t.Errorf("unexpected path: %s", r.URL.Path) w.WriteHeader(http.StatusNotFound) return } if r.Method != http.MethodGet { t.Errorf("unexpected method: %s", r.Method) w.WriteHeader(http.StatusMethodNotAllowed) return } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(serverResp) })) defer testServer.Close() // Act - call FetchServerList with test server URL modpacks, err := FetchServerList(testServer.URL) require.NoError(t, err) // Assert - check results require.Len(t, modpacks, 2) require.Equal(t, screens.Modpack{Slug: "hitech", Name: "HiTech 1.21"}, modpacks[0]) require.Equal(t, screens.Modpack{Slug: "vanilla", Name: "Vanilla 1.20"}, modpacks[1]) } func TestFetchServerList_EmptyList(t *testing.T) { // Arrange - create mock server with empty servers list serverResp := ServerResponse{Servers: []ServerInfo{}} // Create test server with mock response testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/api/servers.json" { t.Errorf("unexpected path: %s", r.URL.Path) w.WriteHeader(http.StatusNotFound) return } if r.Method != http.MethodGet { t.Errorf("unexpected method: %s", r.Method) w.WriteHeader(http.StatusMethodNotAllowed) return } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(serverResp) })) defer testServer.Close() // Act - call FetchServerList with test server URL modpacks, err := FetchServerList(testServer.URL) require.NoError(t, err) // Assert - should return empty slice require.Empty(t, modpacks) } func TestFetchServerList_NetworkError(t *testing.T) { // Act - call FetchServerList with invalid URL that will fail to connect modpacks, err := FetchServerList("http://localhost:12345/api/servers.json") // Assuming no server on this port // Assert - should return error require.Error(t, err) require.Nil(t, modpacks) require.Contains(t, err.Error(), "making request") } func TestFetchServerList_HTTPError(t *testing.T) { // Arrange - create test server that returns 500 error testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusInternalServerError) })) defer testServer.Close() // Act - call FetchServerList with test server URL modpacks, err := FetchServerList(testServer.URL) require.Error(t, err) require.Nil(t, modpacks) require.Contains(t, err.Error(), "unexpected status code: 500") } func TestFetchServerList_InvalidJSON(t *testing.T) { // Arrange - create test server that returns invalid JSON testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") w.Write([]byte(`{"invalid": json}`)) })) defer testServer.Close() // Act - call FetchServerList with test server URL modpacks, err := FetchServerList(testServer.URL) require.Error(t, err) require.Nil(t, modpacks) require.Contains(t, err.Error(), "decoding JSON") } func TestFetchServerList_Timeout(t *testing.T) { // Arrange - create test server that delays response to trigger timeout testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Sleep longer than our timeout to trigger timeout error time.Sleep(15 * time.Second) })) defer testServer.Close() // Act - call FetchServerList with test server URL modpacks, err := FetchServerList(testServer.URL) require.Error(t, err) require.Nil(t, modpacks) require.Contains(t, err.Error(), "context deadline exceeded") require.Contains(t, err.Error(), "making request") }