File size: 3,544 Bytes
6a7089a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | package simple
import (
"context"
"encoding/json"
"io"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/pinchtab/pinchtab/internal/config"
"github.com/pinchtab/pinchtab/internal/orchestrator"
"github.com/pinchtab/pinchtab/internal/proxy"
)
type mockRunner struct {
portAvail bool
}
func (m *mockRunner) Run(context.Context, string, []string, []string, io.Writer, io.Writer) (orchestrator.Cmd, error) {
return nil, nil
}
func (m *mockRunner) IsPortAvailable(string) bool {
return m.portAvail
}
// fakeBridge creates a test server that mimics a bridge instance.
func fakeBridge(t *testing.T) *httptest.Server {
t.Helper()
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]any{"proxied": true, "path": r.URL.Path})
}))
}
func TestProxyHTTP_ForwardsRequest(t *testing.T) {
srv := fakeBridge(t)
defer srv.Close()
req := httptest.NewRequest("GET", "/snapshot", nil)
rec := httptest.NewRecorder()
proxy.HTTP(rec, req, srv.URL+"/snapshot")
if rec.Code != 200 {
t.Errorf("expected 200, got %d: %s", rec.Code, rec.Body.String())
}
var resp map[string]any
_ = json.Unmarshal(rec.Body.Bytes(), &resp)
if resp["path"] != "/snapshot" {
t.Errorf("expected path /snapshot, got %v", resp["path"])
}
}
func TestProxyHTTP_ForwardsQueryParams(t *testing.T) {
srv := fakeBridge(t)
defer srv.Close()
req := httptest.NewRequest("GET", "/screenshot?raw=true", nil)
rec := httptest.NewRecorder()
proxy.HTTP(rec, req, srv.URL+"/screenshot")
if rec.Code != 200 {
t.Errorf("expected 200, got %d", rec.Code)
}
}
func TestProxyHTTP_UnreachableReturns502(t *testing.T) {
req := httptest.NewRequest("GET", "/snapshot", nil)
rec := httptest.NewRecorder()
proxy.HTTP(rec, req, "http://localhost:1/snapshot")
if rec.Code != 502 {
t.Errorf("expected 502, got %d", rec.Code)
}
}
func TestStrategy_Name(t *testing.T) {
s := &Strategy{}
if s.Name() != "simple" {
t.Errorf("expected 'simple', got %q", s.Name())
}
}
func TestStrategy_ProxyToFirst_NoOrch_Returns503(t *testing.T) {
s := &Strategy{} // no orchestrator
req := httptest.NewRequest("GET", "/snapshot", nil)
rec := httptest.NewRecorder()
s.proxyToFirst(rec, req)
if rec.Code != 503 {
t.Errorf("expected 503, got %d: %s", rec.Code, rec.Body.String())
}
}
func TestStrategy_HandleTabs_NoInstances(t *testing.T) {
// handleTabs with nil orch would panic — test the empty-tabs path
// by checking the JSON response format of proxyHTTP fallback.
srv := fakeBridge(t)
defer srv.Close()
req := httptest.NewRequest("GET", "/tabs", nil)
rec := httptest.NewRecorder()
proxy.HTTP(rec, req, srv.URL+"/tabs")
if rec.Code != 200 {
t.Errorf("expected 200, got %d", rec.Code)
}
}
func TestStrategy_RegisterRoutes_LocksSensitiveShorthandRoutes(t *testing.T) {
orch := orchestrator.NewOrchestratorWithRunner(t.TempDir(), &mockRunner{portAvail: true})
orch.ApplyRuntimeConfig(&config.RuntimeConfig{})
s := &Strategy{orch: orch}
mux := http.NewServeMux()
s.RegisterRoutes(mux)
req := httptest.NewRequest("POST", "/evaluate", strings.NewReader(`{"expression":"1+1"}`))
rec := httptest.NewRecorder()
mux.ServeHTTP(rec, req)
if rec.Code != 403 {
t.Fatalf("expected 403, got %d: %s", rec.Code, rec.Body.String())
}
if !strings.Contains(rec.Body.String(), "security.allowEvaluate") {
t.Fatalf("expected lock response to mention security.allowEvaluate, got %s", rec.Body.String())
}
}
|