From 0a477fd288d064d265395c88dbd0f261b723804e Mon Sep 17 00:00:00 2001 From: spiperac Date: Mon, 15 Jun 2026 06:42:13 +0200 Subject: Initial release --- internal/store/history_test.go | 190 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 internal/store/history_test.go (limited to 'internal/store/history_test.go') diff --git a/internal/store/history_test.go b/internal/store/history_test.go new file mode 100644 index 0000000..d3a8e99 --- /dev/null +++ b/internal/store/history_test.go @@ -0,0 +1,190 @@ +package store_test + +import ( + "fmt" + "net/http" + "testing" + "time" + + "github.com/shiv/internal/store" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func makeTx(method, host, url string, status int) store.Transaction { + return store.Transaction{ + Timestamp: time.Now().UTC(), + Host: host, + Method: method, + URL: url, + ReqHeaders: http.Header{"Content-Type": []string{"text/plain"}}, + ReqBody: []byte("request body"), + StatusCode: status, + RespHeaders: http.Header{"Content-Type": []string{"text/html"}}, + RespBody: []byte("response body"), + DurationMs: 10, + TLS: false, + InScope: true, + } +} + +func TestLog_Insert(t *testing.T) { + st := newTestStore(t) + + tx := makeTx("GET", "example.com", "https://example.com/", 200) + require.NoError(t, st.Log(tx)) + + txs, err := st.AllTransactions() + require.NoError(t, err) + require.Len(t, txs, 1) + assert.Equal(t, "GET", txs[0].Method) + assert.Equal(t, "example.com", txs[0].Host) + assert.Equal(t, 200, txs[0].StatusCode) + assert.True(t, txs[0].InScope) +} + +func TestLog_NoDedup_SameMethodHostURLStatus(t *testing.T) { + st := newTestStore(t) + + tx := makeTx("GET", "example.com", "https://example.com/", 200) + require.NoError(t, st.Log(tx)) + require.NoError(t, st.Log(tx)) + + txs, err := st.AllTransactions() + require.NoError(t, err) + assert.Len(t, txs, 2, "no dedup — every request is a unique row") +} + +func TestLog_NoDedupOnDifferentStatus(t *testing.T) { + st := newTestStore(t) + + require.NoError(t, st.Log(makeTx("GET", "example.com", "https://example.com/", 200))) + require.NoError(t, st.Log(makeTx("GET", "example.com", "https://example.com/", 404))) + + txs, err := st.AllTransactions() + require.NoError(t, err) + assert.Len(t, txs, 2) +} + +func TestLog_NoDedupOnDifferentMethod(t *testing.T) { + st := newTestStore(t) + + require.NoError(t, st.Log(makeTx("GET", "example.com", "https://example.com/", 200))) + require.NoError(t, st.Log(makeTx("POST", "example.com", "https://example.com/", 200))) + + txs, err := st.AllTransactions() + require.NoError(t, err) + assert.Len(t, txs, 2) +} + +func TestLog_NoDedupOnDifferentURL(t *testing.T) { + st := newTestStore(t) + + require.NoError(t, st.Log(makeTx("GET", "example.com", "https://example.com/a", 200))) + require.NoError(t, st.Log(makeTx("GET", "example.com", "https://example.com/b", 200))) + + txs, err := st.AllTransactions() + require.NoError(t, err) + assert.Len(t, txs, 2) +} + +func TestLog_TLSFlagPersisted(t *testing.T) { + st := newTestStore(t) + + tx := makeTx("GET", "example.com", "https://example.com/", 200) + tx.TLS = true + require.NoError(t, st.Log(tx)) + + txs, err := st.AllTransactions() + require.NoError(t, err) + require.Len(t, txs, 1) + assert.True(t, txs[0].TLS) +} + +func TestAllTransactions_OrderedByIDDesc(t *testing.T) { + st := newTestStore(t) + + require.NoError(t, st.Log(makeTx("GET", "first.com", "https://first.com/", 200))) + require.NoError(t, st.Log(makeTx("GET", "second.com", "https://second.com/", 200))) + require.NoError(t, st.Log(makeTx("GET", "third.com", "https://third.com/", 200))) + + txs, err := st.AllTransactions() + require.NoError(t, err) + require.Len(t, txs, 3) + assert.Equal(t, "third.com", txs[0].Host) + assert.Equal(t, "second.com", txs[1].Host) + assert.Equal(t, "first.com", txs[2].Host) +} + +func TestAllTransactions_CappedAt500(t *testing.T) { + st := newTestStore(t) + + for i := 0; i < 510; i++ { + url := fmt.Sprintf("https://example.com/path/%d", i) + require.NoError(t, st.Log(makeTx("GET", "example.com", url, 200))) + } + + txs, err := st.AllTransactions() + require.NoError(t, err) + assert.LessOrEqual(t, len(txs), 500) +} + +func TestGetTransaction_ReturnsFullBodies(t *testing.T) { + st := newTestStore(t) + + tx := makeTx("POST", "example.com", "https://example.com/api", 201) + tx.ReqBody = []byte(`{"input":"data"}`) + tx.RespBody = []byte(`{"output":"result"}`) + require.NoError(t, st.Log(tx)) + + txs, err := st.AllTransactions() + require.NoError(t, err) + require.Len(t, txs, 1) + + full, err := st.GetTransaction(txs[0].ID) + require.NoError(t, err) + assert.Equal(t, []byte(`{"input":"data"}`), full.ReqBody) + assert.Equal(t, []byte(`{"output":"result"}`), full.RespBody) + assert.Equal(t, "POST", full.Method) + assert.Equal(t, 201, full.StatusCode) +} + +func TestGetTransaction_HeadersDeserialized(t *testing.T) { + st := newTestStore(t) + + tx := makeTx("GET", "example.com", "https://example.com/", 200) + tx.ReqHeaders = http.Header{"X-Request-Id": []string{"req-123"}} + tx.RespHeaders = http.Header{"X-Trace-Id": []string{"trace-456"}} + require.NoError(t, st.Log(tx)) + + txs, err := st.AllTransactions() + require.NoError(t, err) + + full, err := st.GetTransaction(txs[0].ID) + require.NoError(t, err) + assert.Equal(t, "req-123", full.ReqHeaders.Get("X-Request-Id")) + assert.Equal(t, "trace-456", full.RespHeaders.Get("X-Trace-Id")) +} + +func TestGetTransaction_NotFound(t *testing.T) { + st := newTestStore(t) + _, err := st.GetTransaction(99999) + assert.Error(t, err) +} + +func TestClearHistory_RemovesAllRows(t *testing.T) { + st := newTestStore(t) + + require.NoError(t, st.Log(makeTx("GET", "a.com", "https://a.com/", 200))) + require.NoError(t, st.Log(makeTx("GET", "b.com", "https://b.com/", 200))) + require.NoError(t, st.ClearHistory()) + + txs, err := st.AllTransactions() + require.NoError(t, err) + assert.Empty(t, txs) +} + +func TestClearHistory_EmptyStoreNoError(t *testing.T) { + st := newTestStore(t) + assert.NoError(t, st.ClearHistory()) +} -- cgit v1.2.3