package starnet import ( "os" "testing" "time" ) // 这些测试使用 httpbin.org 作为测试服务 // 可以通过环境变量 STARNET_INTEGRATION_TEST=1 来启用 func skipIfNoIntegration(t *testing.T) { if os.Getenv("STARNET_INTEGRATION_TEST") != "1" { t.Skip("Skipping integration test. Set STARNET_INTEGRATION_TEST=1 to run") } } func TestIntegrationHTTPBinGet(t *testing.T) { skipIfNoIntegration(t) resp, err := Get("https://httpbin.org/get", WithQuery("name", "starnet"), WithQuery("version", "1.0")) if err != nil { t.Fatalf("Get() error: %v", err) } defer resp.Close() if resp.StatusCode != 200 { t.Errorf("StatusCode = %v; want 200", resp.StatusCode) } var result map[string]interface{} err = resp.Body().JSON(&result) if err != nil { t.Fatalf("JSON() error: %v", err) } args, ok := result["args"].(map[string]interface{}) if !ok { t.Fatal("args not found in response") } if args["name"] != "starnet" { t.Errorf("args[name] = %v; want starnet", args["name"]) } } func TestIntegrationHTTPBinPost(t *testing.T) { skipIfNoIntegration(t) type PostData struct { Name string `json:"name"` Email string `json:"email"` } data := PostData{ Name: "John Doe", Email: "john@example.com", } resp, err := Post("https://httpbin.org/post", WithJSON(data)) if err != nil { t.Fatalf("Post() error: %v", err) } defer resp.Close() if resp.StatusCode != 200 { t.Errorf("StatusCode = %v; want 200", resp.StatusCode) } var result map[string]interface{} err = resp.Body().JSON(&result) if err != nil { t.Fatalf("JSON() error: %v", err) } jsonData, ok := result["json"].(map[string]interface{}) if !ok { t.Fatal("json not found in response") } if jsonData["name"] != data.Name { t.Errorf("name = %v; want %v", jsonData["name"], data.Name) } } func TestIntegrationHTTPBinHeaders(t *testing.T) { skipIfNoIntegration(t) resp, err := Get("https://httpbin.org/headers", WithHeader("X-Custom-Header", "test-value"), WithUserAgent("Starnet-Test/1.0")) if err != nil { t.Fatalf("Get() error: %v", err) } defer resp.Close() var result map[string]interface{} err = resp.Body().JSON(&result) if err != nil { t.Fatalf("JSON() error: %v", err) } headers, ok := result["headers"].(map[string]interface{}) if !ok { t.Fatal("headers not found in response") } if headers["X-Custom-Header"] != "test-value" { t.Errorf("X-Custom-Header = %v; want test-value", headers["X-Custom-Header"]) } } func TestIntegrationHTTPBinBasicAuth(t *testing.T) { skipIfNoIntegration(t) resp, err := Get("https://httpbin.org/basic-auth/user/passwd", WithBasicAuth("user", "passwd")) if err != nil { t.Fatalf("Get() error: %v", err) } defer resp.Close() if resp.StatusCode != 200 { t.Errorf("StatusCode = %v; want 200", resp.StatusCode) } var result map[string]interface{} err = resp.Body().JSON(&result) if err != nil { t.Fatalf("JSON() error: %v", err) } if result["authenticated"] != true { t.Error("authenticated should be true") } } func TestIntegrationHTTPBinDelay(t *testing.T) { skipIfNoIntegration(t) // Test timeout start := time.Now() _, err := Get("https://httpbin.org/delay/3", WithTimeout(1*time.Second)) elapsed := time.Since(start) if err == nil { t.Error("Expected timeout error, got nil") } if elapsed > 2*time.Second { t.Errorf("Timeout took too long: %v", elapsed) } } func TestIntegrationHTTPBinRedirect(t *testing.T) { skipIfNoIntegration(t) // Test with redirect enabled client := NewClientNoErr() resp, err := client.Get("https://httpbin.org/redirect/2") if err != nil { t.Fatalf("Get() error: %v", err) } defer resp.Close() if resp.StatusCode != 200 { t.Errorf("StatusCode = %v; want 200 (after redirect)", resp.StatusCode) } // Test with redirect disabled client.DisableRedirect() resp2, err := client.Get("https://httpbin.org/redirect/2") if err != nil { t.Fatalf("Get() error: %v", err) } defer resp2.Close() if resp2.StatusCode != 302 { t.Errorf("StatusCode = %v; want 302 (redirect disabled)", resp2.StatusCode) } } func TestIntegrationHTTPBinCookies(t *testing.T) { skipIfNoIntegration(t) // 创建一个禁用重定向的 Client client := NewClientNoErr() client.DisableRedirect() resp, err := client.Get("https://httpbin.org/cookies/set?name=value") if err != nil { t.Fatalf("Get() error: %v", err) } defer resp.Close() // 现在应该能获取到 Set-Cookie cookies := resp.Cookies() if len(cookies) == 0 { t.Error("Expected cookies in response") } // 验证 cookie found := false for _, cookie := range cookies { if cookie.Name == "name" && cookie.Value == "value" { found = true break } } if !found { t.Error("Expected cookie 'name=value' not found") } } func TestIntegrationHTTPBinUserAgent(t *testing.T) { skipIfNoIntegration(t) customUA := "Starnet-Integration-Test/1.0" resp, err := Get("https://httpbin.org/user-agent", WithUserAgent(customUA)) if err != nil { t.Fatalf("Get() error: %v", err) } defer resp.Close() var result map[string]interface{} err = resp.Body().JSON(&result) if err != nil { t.Fatalf("JSON() error: %v", err) } if result["user-agent"] != customUA { t.Errorf("user-agent = %v; want %v", result["user-agent"], customUA) } } func TestIntegrationHTTPBinGzip(t *testing.T) { skipIfNoIntegration(t) resp, err := Get("https://httpbin.org/gzip") if err != nil { t.Fatalf("Get() error: %v", err) } defer resp.Close() var result map[string]interface{} err = resp.Body().JSON(&result) if err != nil { t.Fatalf("JSON() error: %v", err) } if result["gzipped"] != true { t.Error("Response should be gzipped") } }