| 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 |
| } |
|
|
| |
| 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{} |
| 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) { |
| |
| |
| 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()) |
| } |
| } |
|
|