259 lines
5.6 KiB
Go
259 lines
5.6 KiB
Go
|
|
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")
|
||
|
|
}
|
||
|
|
}
|