package integration_test import ( "context" "io" "net/http" "strings" "testing" "time" "galaxy/integration/testenv" ) // TestAdminConsole_ThroughGateway verifies the full operator-console pipe: // the edge gateway reverse-proxies `/_gm/*` to the backend, the backend // enforces the admin Basic Auth and relays its 401 challenge unchanged, and an // authenticated request renders the server-side dashboard. func TestAdminConsole_ThroughGateway(t *testing.T) { plat := testenv.Bootstrap(t, testenv.BootstrapOptions{}) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() base := plat.Gateway.HTTPURL client := &http.Client{Timeout: 10 * time.Second} // Unauthenticated: the backend's 401 + Basic challenge must reach the client // through the gateway. req, err := http.NewRequestWithContext(ctx, http.MethodGet, base+"/_gm/", nil) if err != nil { t.Fatalf("build request: %v", err) } resp, err := client.Do(req) if err != nil { t.Fatalf("GET /_gm/ (no auth): %v", err) } body, _ := io.ReadAll(resp.Body) resp.Body.Close() if resp.StatusCode != http.StatusUnauthorized { t.Fatalf("no-auth status = %d, want 401; body=%s", resp.StatusCode, body) } if !strings.Contains(resp.Header.Get("WWW-Authenticate"), "Basic") { t.Fatalf("WWW-Authenticate = %q, want a Basic challenge", resp.Header.Get("WWW-Authenticate")) } // Authenticated with the bootstrap operator: the dashboard renders. req, err = http.NewRequestWithContext(ctx, http.MethodGet, base+"/_gm/", nil) if err != nil { t.Fatalf("build request: %v", err) } req.SetBasicAuth(plat.Backend.AdminUser, plat.Backend.AdminPassword) resp, err = client.Do(req) if err != nil { t.Fatalf("GET /_gm/ (auth): %v", err) } body, _ = io.ReadAll(resp.Body) resp.Body.Close() if resp.StatusCode != http.StatusOK { t.Fatalf("authenticated status = %d, want 200; body=%s", resp.StatusCode, body) } if !strings.Contains(string(body), "Dashboard") { t.Fatalf("dashboard body missing the heading; got: %s", body) } }