summaryrefslogtreecommitdiff
path: root/internal/store/repeater_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/store/repeater_test.go')
-rw-r--r--internal/store/repeater_test.go265
1 files changed, 265 insertions, 0 deletions
diff --git a/internal/store/repeater_test.go b/internal/store/repeater_test.go
new file mode 100644
index 0000000..c85ad83
--- /dev/null
+++ b/internal/store/repeater_test.go
@@ -0,0 +1,265 @@
+package store_test
+
+import (
+ "testing"
+
+ "github.com/shiv/internal/store"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func makeTab(name, host string, port int, tls bool) store.RepeaterTab {
+ return store.RepeaterTab{
+ Name: name,
+ Host: host,
+ Port: port,
+ TLS: tls,
+ TabType: "http",
+ RawRequest: "GET / HTTP/1.1\r\nHost: " + host + "\r\n\r\n",
+ }
+}
+
+func makeWSTab(name, url string, tls bool) store.RepeaterTab {
+ return store.RepeaterTab{
+ Name: name,
+ Host: url,
+ Port: 0,
+ TLS: tls,
+ TabType: "websocket",
+ RawRequest: url,
+ }
+}
+
+// ── HTTP tab ──────────────────────────────────────────────────────────────────
+
+func TestSaveRepeaterTab_PersistsAllFields(t *testing.T) {
+ st := newTestStore(t)
+
+ tab := store.RepeaterTab{
+ Name: "My Tab",
+ Host: "example.com",
+ Port: 443,
+ TLS: true,
+ TabType: "http",
+ RawRequest: "GET /api HTTP/1.1\r\nHost: example.com\r\n\r\n",
+ }
+ id, err := st.SaveRepeaterTab(tab)
+ require.NoError(t, err)
+ assert.Positive(t, id)
+
+ tabs, err := st.AllRepeaterTabs()
+ require.NoError(t, err)
+ require.Len(t, tabs, 1)
+
+ got := tabs[0]
+ assert.Equal(t, id, got.ID)
+ assert.Equal(t, "My Tab", got.Name)
+ assert.Equal(t, "example.com", got.Host)
+ assert.Equal(t, 443, got.Port)
+ assert.True(t, got.TLS)
+ assert.Equal(t, "http", got.TabType)
+ assert.Equal(t, tab.RawRequest, got.RawRequest)
+}
+
+func TestSaveRepeaterTab_TLSFalse(t *testing.T) {
+ st := newTestStore(t)
+
+ id, err := st.SaveRepeaterTab(makeTab("HTTP Tab", "example.com", 80, false))
+ require.NoError(t, err)
+ assert.Positive(t, id)
+
+ tabs, err := st.AllRepeaterTabs()
+ require.NoError(t, err)
+ require.Len(t, tabs, 1)
+ assert.False(t, tabs[0].TLS)
+ assert.Equal(t, "http", tabs[0].TabType)
+}
+
+func TestSaveRepeaterTab_DefaultTabType(t *testing.T) {
+ st := newTestStore(t)
+
+ // TabType omitted — should default to "http".
+ tab := store.RepeaterTab{
+ Name: "No Type",
+ Host: "example.com",
+ Port: 80,
+ RawRequest: "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n",
+ }
+ _, err := st.SaveRepeaterTab(tab)
+ require.NoError(t, err)
+
+ tabs, err := st.AllRepeaterTabs()
+ require.NoError(t, err)
+ require.Len(t, tabs, 1)
+ assert.Equal(t, "http", tabs[0].TabType)
+}
+
+func TestAllRepeaterTabs_OrderedByPosition(t *testing.T) {
+ st := newTestStore(t)
+
+ for _, name := range []string{"First", "Second", "Third"} {
+ _, err := st.SaveRepeaterTab(makeTab(name, "example.com", 80, false))
+ require.NoError(t, err)
+ }
+
+ tabs, err := st.AllRepeaterTabs()
+ require.NoError(t, err)
+ require.Len(t, tabs, 3)
+ assert.Equal(t, "First", tabs[0].Name)
+ assert.Equal(t, "Second", tabs[1].Name)
+ assert.Equal(t, "Third", tabs[2].Name)
+}
+
+func TestAllRepeaterTabs_PositionAutoIncrements(t *testing.T) {
+ st := newTestStore(t)
+
+ _, err := st.SaveRepeaterTab(makeTab("A", "a.com", 80, false))
+ require.NoError(t, err)
+ _, err = st.SaveRepeaterTab(makeTab("B", "b.com", 80, false))
+ require.NoError(t, err)
+
+ tabs, err := st.AllRepeaterTabs()
+ require.NoError(t, err)
+ require.Len(t, tabs, 2)
+ assert.Less(t, tabs[0].Position, tabs[1].Position)
+}
+
+func TestUpdateRepeaterTab_UpdatesRequestAndResponse(t *testing.T) {
+ st := newTestStore(t)
+
+ id, err := st.SaveRepeaterTab(makeTab("Tab", "example.com", 80, false))
+ require.NoError(t, err)
+
+ newReq := "POST /submit HTTP/1.1\r\nHost: example.com\r\n\r\nbody"
+ newResp := "HTTP/1.1 200 OK\r\n\r\nok"
+ require.NoError(t, st.UpdateRepeaterTab(id, newReq, newResp))
+
+ tabs, err := st.AllRepeaterTabs()
+ require.NoError(t, err)
+ require.Len(t, tabs, 1)
+ assert.Equal(t, newReq, tabs[0].RawRequest)
+ assert.Equal(t, newResp, tabs[0].LastResponse)
+}
+
+func TestUpdateRepeaterTab_NonExistentIDNoError(t *testing.T) {
+ st := newTestStore(t)
+ assert.NoError(t, st.UpdateRepeaterTab(9999, "req", "resp"))
+}
+
+func TestRenameRepeaterTab(t *testing.T) {
+ st := newTestStore(t)
+
+ id, err := st.SaveRepeaterTab(makeTab("Old", "example.com", 80, false))
+ require.NoError(t, err)
+
+ require.NoError(t, st.RenameRepeaterTab(id, "New Name"))
+
+ tabs, err := st.AllRepeaterTabs()
+ require.NoError(t, err)
+ require.Len(t, tabs, 1)
+ assert.Equal(t, "New Name", tabs[0].Name)
+}
+
+func TestDeleteRepeaterTab(t *testing.T) {
+ st := newTestStore(t)
+
+ id, err := st.SaveRepeaterTab(makeTab("Tab", "example.com", 80, false))
+ require.NoError(t, err)
+
+ require.NoError(t, st.DeleteRepeaterTab(id))
+
+ tabs, err := st.AllRepeaterTabs()
+ require.NoError(t, err)
+ assert.Empty(t, tabs)
+}
+
+func TestDeleteRepeaterTab_NonExistent(t *testing.T) {
+ st := newTestStore(t)
+ assert.NoError(t, st.DeleteRepeaterTab(9999))
+}
+
+func TestDeleteRepeaterTab_DoesNotAffectOtherTabs(t *testing.T) {
+ st := newTestStore(t)
+
+ idKeep, err := st.SaveRepeaterTab(makeTab("Keep", "keep.com", 80, false))
+ require.NoError(t, err)
+ idDel, err := st.SaveRepeaterTab(makeTab("Delete", "del.com", 80, false))
+ require.NoError(t, err)
+
+ require.NoError(t, st.DeleteRepeaterTab(idDel))
+
+ tabs, err := st.AllRepeaterTabs()
+ require.NoError(t, err)
+ require.Len(t, tabs, 1)
+ assert.Equal(t, idKeep, tabs[0].ID)
+ assert.Equal(t, "Keep", tabs[0].Name)
+}
+
+// ── WebSocket tab ─────────────────────────────────────────────────────────────
+
+func TestSaveRepeaterTab_WebSocketType(t *testing.T) {
+ st := newTestStore(t)
+
+ tab := makeWSTab("WS Tab", "wss://echo.websocket.org:443/", true)
+ id, err := st.SaveRepeaterTab(tab)
+ require.NoError(t, err)
+ assert.Positive(t, id)
+
+ tabs, err := st.AllRepeaterTabs()
+ require.NoError(t, err)
+ require.Len(t, tabs, 1)
+ assert.Equal(t, "websocket", tabs[0].TabType)
+ assert.Equal(t, "wss://echo.websocket.org:443/", tabs[0].RawRequest)
+ assert.True(t, tabs[0].TLS)
+}
+
+func TestAllRepeaterTabs_MixedTypes(t *testing.T) {
+ st := newTestStore(t)
+
+ _, err := st.SaveRepeaterTab(makeTab("HTTP", "example.com", 80, false))
+ require.NoError(t, err)
+ _, err = st.SaveRepeaterTab(makeWSTab("WS", "wss://example.com/ws", true))
+ require.NoError(t, err)
+ _, err = st.SaveRepeaterTab(makeTab("HTTP2", "other.com", 443, true))
+ require.NoError(t, err)
+
+ tabs, err := st.AllRepeaterTabs()
+ require.NoError(t, err)
+ require.Len(t, tabs, 3)
+ assert.Equal(t, "http", tabs[0].TabType)
+ assert.Equal(t, "websocket", tabs[1].TabType)
+ assert.Equal(t, "http", tabs[2].TabType)
+}
+
+func TestSaveRepeaterTab_WebSocketPreservesURL(t *testing.T) {
+ st := newTestStore(t)
+
+ url := "wss://api.example.com:8443/realtime?token=abc123"
+ tab := makeWSTab("API WS", url, true)
+ id, err := st.SaveRepeaterTab(tab)
+ require.NoError(t, err)
+
+ full, err := st.AllRepeaterTabs()
+ require.NoError(t, err)
+ require.Len(t, full, 1)
+ assert.Equal(t, id, full[0].ID)
+ assert.Equal(t, url, full[0].RawRequest)
+ assert.Equal(t, "websocket", full[0].TabType)
+}
+
+func TestDeleteRepeaterTab_WebSocket(t *testing.T) {
+ st := newTestStore(t)
+
+ httpID, err := st.SaveRepeaterTab(makeTab("HTTP", "example.com", 80, false))
+ require.NoError(t, err)
+ wsID, err := st.SaveRepeaterTab(makeWSTab("WS", "wss://example.com/ws", true))
+ require.NoError(t, err)
+
+ require.NoError(t, st.DeleteRepeaterTab(wsID))
+
+ tabs, err := st.AllRepeaterTabs()
+ require.NoError(t, err)
+ require.Len(t, tabs, 1)
+ assert.Equal(t, httpID, tabs[0].ID)
+ assert.Equal(t, "http", tabs[0].TabType)
+}