verstak/internal/core/bridge/bridge_test.go

157 lines
3.6 KiB
Go

package bridge
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"testing"
"time"
)
func TestServer_Ping(t *testing.T) {
s := NewServer("", nil)
port, err := s.Start(DefaultConfig())
if err != nil {
t.Fatal(err)
}
defer s.Stop()
resp, err := http.Get(fmt.Sprintf("http://127.0.0.1:%d/api/ping", port))
if err != nil {
t.Fatal(err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
t.Errorf("expected 200, got %d", resp.StatusCode)
}
var body map[string]interface{}
json.NewDecoder(resp.Body).Decode(&body)
if body["status"] != "ok" {
t.Errorf("expected status ok, got %v", body["status"])
}
}
func TestServer_Events_AuthRequired(t *testing.T) {
s := NewServer("test-secret", nil)
port, err := s.Start(Config{Secret: "test-secret"})
if err != nil {
t.Fatal(err)
}
defer s.Stop()
// Without auth header
body := EventBatch{Version: 1, DeviceID: "test", Events: []Event{{ID: "1", Type: "page_visit", URL: "https://example.com"}}}
b, _ := json.Marshal(body)
resp, err := http.Post(fmt.Sprintf("http://127.0.0.1:%d/api/events", port), "application/json", bytes.NewReader(b))
if err != nil {
t.Fatal(err)
}
if resp.StatusCode != 401 {
t.Errorf("expected 401 without auth, got %d", resp.StatusCode)
}
}
func TestServer_Events_Success(t *testing.T) {
received := make(chan []Event, 1)
s := NewServer("test-secret", func(evts []Event) {
received <- evts
})
port, err := s.Start(Config{Secret: "test-secret"})
if err != nil {
t.Fatal(err)
}
defer s.Stop()
events := []Event{
{ID: "1", Type: "page_visit", URL: "https://example.com", Title: "Example", Domain: "example.com", ActiveSeconds: 120},
}
batch := EventBatch{Version: 1, DeviceID: "test-device", Events: events}
b, _ := json.Marshal(batch)
req, _ := http.NewRequest("POST", fmt.Sprintf("http://127.0.0.1:%d/api/events", port), bytes.NewReader(b))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Verstak-Secret", "test-secret")
resp, err := http.DefaultClient.Do(req)
if err != nil {
t.Fatal(err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
t.Errorf("expected 200, got %d", resp.StatusCode)
}
select {
case evts := <-received:
if len(evts) != 1 {
t.Errorf("expected 1 event, got %d", len(evts))
}
if evts[0].ID != "1" {
t.Errorf("expected event ID '1', got %s", evts[0].ID)
}
case <-time.After(time.Second):
t.Fatal("timeout waiting for event handler")
}
}
func TestServer_Events_EmptyBatch(t *testing.T) {
s := NewServer("s", nil)
port, err := s.Start(Config{Secret: "s"})
if err != nil {
t.Fatal(err)
}
defer s.Stop()
batch := EventBatch{Version: 1, DeviceID: "test", Events: []Event{}}
b, _ := json.Marshal(batch)
req, _ := http.NewRequest("POST", fmt.Sprintf("http://127.0.0.1:%d/api/events", port), bytes.NewReader(b))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Verstak-Secret", "s")
resp, err := http.DefaultClient.Do(req)
if err != nil {
t.Fatal(err)
}
if resp.StatusCode != 204 {
t.Errorf("expected 204 for empty batch, got %d", resp.StatusCode)
}
}
func TestGenerateSecret(t *testing.T) {
s1 := GenerateSecret()
s2 := GenerateSecret()
if s1 == s2 {
t.Error("secrets should be unique")
}
if len(s1) != 32 {
t.Errorf("expected 32 chars, got %d", len(s1))
}
}
func TestServer_AutoPort(t *testing.T) {
cfg := DefaultConfig()
s := NewServer("", nil)
port, err := s.Start(cfg)
if err != nil {
t.Fatal(err)
}
defer s.Stop()
if port == 0 {
t.Error("expected non-zero port")
}
if s.Port() != port {
t.Errorf("Port() = %d, want %d", s.Port(), port)
}
if !s.Running() {
t.Error("expected server running")
}
}