termtap/internal/proxy/integration_http_test.go
Hayden Hargreaves 002773e77f test: AI generated all of these tests
Just for the MVP of course. Need to validate the idea.
2026-04-23 19:47:04 -07:00

130 lines
3.2 KiB
Go

package proxy
import (
"io"
"net/http"
"net/http/httptest"
"net/url"
"testing"
"time"
"termtap.dev/internal/model"
)
func TestHTTPProxyE2E_WithClientProxyConfig(t *testing.T) {
configRoot := t.TempDir()
t.Setenv("XDG_CONFIG_HOME", configRoot)
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("pong"))
}))
t.Cleanup(upstream.Close)
ch := make(chan model.Event, 64)
ps, err := NewProxyServer("127.0.0.1:0", ch)
if err != nil {
t.Fatalf("NewProxyServer() error = %v", err)
}
serveDone := make(chan error, 1)
go func() {
serveDone <- ps.Server.Serve(*ps.Listener)
}()
t.Cleanup(func() {
Destroy(ps, ch)
select {
case <-serveDone:
case <-time.After(2 * time.Second):
t.Fatal("timeout waiting for proxy server to stop")
}
})
proxyURL, err := url.Parse(ps.Url)
if err != nil {
t.Fatalf("url.Parse(proxy) error = %v", err)
}
client := &http.Client{
Transport: &http.Transport{Proxy: http.ProxyURL(proxyURL)},
Timeout: 3 * time.Second,
}
resp, err := client.Get(upstream.URL + "/ping")
if err != nil {
t.Fatalf("client.Get() error = %v", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
t.Fatalf("ReadAll(response) error = %v", err)
}
if resp.StatusCode != http.StatusOK {
t.Fatalf("status = %d, want %d", resp.StatusCode, http.StatusOK)
}
if got, want := string(body), "pong"; got != want {
t.Fatalf("body = %q, want %q", got, want)
}
events := drainEvents(t, ch, 2, 2*time.Second)
if !hasEventType(events, model.EventTypeRequestStarted) {
t.Fatalf("missing %s event", model.EventTypeRequestStarted)
}
if !hasEventType(events, model.EventTypeRequestFinished) {
t.Fatalf("missing %s event", model.EventTypeRequestFinished)
}
}
func TestHTTPProxyE2E_UpstreamFailureEmitsRequestFailed(t *testing.T) {
configRoot := t.TempDir()
t.Setenv("XDG_CONFIG_HOME", configRoot)
ch := make(chan model.Event, 64)
ps, err := NewProxyServer("127.0.0.1:0", ch)
if err != nil {
t.Fatalf("NewProxyServer() error = %v", err)
}
serveDone := make(chan error, 1)
go func() {
serveDone <- ps.Server.Serve(*ps.Listener)
}()
t.Cleanup(func() {
Destroy(ps, ch)
select {
case <-serveDone:
case <-time.After(2 * time.Second):
t.Fatal("timeout waiting for proxy server to stop")
}
})
proxyURL, err := url.Parse(ps.Url)
if err != nil {
t.Fatalf("url.Parse(proxy) error = %v", err)
}
client := &http.Client{
Transport: &http.Transport{Proxy: http.ProxyURL(proxyURL)},
Timeout: 3 * time.Second,
}
resp, reqErr := client.Get("http://127.0.0.1:1/unreachable")
if reqErr != nil {
t.Fatalf("client.Get() error = %v; proxy should reply with mapped HTTP status", reqErr)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusBadGateway {
t.Fatalf("status = %d, want %d", resp.StatusCode, http.StatusBadGateway)
}
events := drainEvents(t, ch, 2, 3*time.Second)
if !hasEventType(events, model.EventTypeRequestStarted) {
t.Fatalf("missing %s event", model.EventTypeRequestStarted)
}
if !hasEventType(events, model.EventTypeRequestFailed) {
t.Fatalf("missing %s event", model.EventTypeRequestFailed)
}
}