package repositories import ( "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gorm.io/driver/sqlite" "gorm.io/gorm" "gorm.io/gorm/logger" ) // setupWebhookTestDB creates an in-memory SQLite database with the // WebhookEvent table auto-migrated. This is separate from testutil.SetupTestDB // because WebhookEvent lives in the repositories package (not models/) and // only needs its own table for testing. func setupWebhookTestDB(t *testing.T) *gorm.DB { t.Helper() db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{ Logger: logger.Default.LogMode(logger.Silent), }) require.NoError(t, err) err = db.AutoMigrate(&WebhookEvent{}) require.NoError(t, err) return db } func TestWebhookEventRepo_RecordAndCheck(t *testing.T) { db := setupWebhookTestDB(t) repo := NewWebhookEventRepository(db) // Record an event err := repo.RecordEvent("apple", "evt_001", "INITIAL_BUY", "abc123hash") require.NoError(t, err) // HasProcessed should return true for the same provider + event ID processed, err := repo.HasProcessed("apple", "evt_001") require.NoError(t, err) assert.True(t, processed, "expected HasProcessed to return true for a recorded event") // HasProcessed should return false for a different event ID processed, err = repo.HasProcessed("apple", "evt_999") require.NoError(t, err) assert.False(t, processed, "expected HasProcessed to return false for an unrecorded event ID") // HasProcessed should return false for a different provider processed, err = repo.HasProcessed("google", "evt_001") require.NoError(t, err) assert.False(t, processed, "expected HasProcessed to return false for a different provider") } func TestWebhookEventRepo_DuplicateInsert(t *testing.T) { db := setupWebhookTestDB(t) repo := NewWebhookEventRepository(db) // First insert should succeed err := repo.RecordEvent("apple", "evt_dup", "RENEWAL", "hash1") require.NoError(t, err) // Second insert with the same provider + event ID should fail (unique constraint) err = repo.RecordEvent("apple", "evt_dup", "RENEWAL", "hash1") require.Error(t, err, "expected an error when inserting a duplicate provider + event_id") // Verify only one row exists var count int64 db.Model(&WebhookEvent{}).Where("provider = ? AND event_id = ?", "apple", "evt_dup").Count(&count) assert.Equal(t, int64(1), count, "expected exactly one row for the duplicated event") } func TestWebhookEventRepo_DifferentProviders(t *testing.T) { db := setupWebhookTestDB(t) repo := NewWebhookEventRepository(db) sharedEventID := "evt_shared_123" // Record event for "apple" provider err := repo.RecordEvent("apple", sharedEventID, "INITIAL_BUY", "applehash") require.NoError(t, err) // HasProcessed should return true for "apple" processed, err := repo.HasProcessed("apple", sharedEventID) require.NoError(t, err) assert.True(t, processed, "expected HasProcessed to return true for apple provider") // HasProcessed should return false for "google" with the same event ID processed, err = repo.HasProcessed("google", sharedEventID) require.NoError(t, err) assert.False(t, processed, "expected HasProcessed to return false for google provider with the same event ID") // Recording the same event ID under "google" should succeed (different provider) err = repo.RecordEvent("google", sharedEventID, "INITIAL_BUY", "googlehash") require.NoError(t, err) // Now both providers should show as processed processed, err = repo.HasProcessed("apple", sharedEventID) require.NoError(t, err) assert.True(t, processed, "expected apple to still be processed") processed, err = repo.HasProcessed("google", sharedEventID) require.NoError(t, err) assert.True(t, processed, "expected google to now be processed") }