package repository import ( "context" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gorm.io/gorm" "github.com/gochat/gochat/internal/model" ) // setupWidgetTestDB uses the shared setupTestDB helper with widget-specific models. func setupWidgetTestDB(t *testing.T) *gorm.DB { t.Helper() return setupTestDB(t, &model.WidgetThemeConfig{}, &model.WidgetFileUpload{}, &model.PreChatForm{}, ) } // createWidgetTestAccount creates a minimal Account row so that Inbox can reference it. func createWidgetTestAccount(t *testing.T, db *gorm.DB) *model.Account { t.Helper() account := &model.Account{Name: "Widget Test Account"} err := db.Create(account).Error require.NoError(t, err, "failed to create test account") return account } // createWidgetTestInbox creates a minimal Inbox row for a given Account. func createWidgetTestInbox(t *testing.T, db *gorm.DB, accountID uint) *model.Inbox { t.Helper() inbox := &model.Inbox{ AccountID: accountID, Name: "Widget Test Inbox", ChannelType: "web_widget", ChannelID: 1, } err := db.Create(inbox).Error require.NoError(t, err, "failed to create test inbox") return inbox } // =========================================================================== // WidgetThemeConfigRepo tests // =========================================================================== func TestWidgetThemeConfigRepo_Create(t *testing.T) { db := setupWidgetTestDB(t) repo := NewWidgetThemeConfigRepo(db) ctx := context.Background() account := createWidgetTestAccount(t, db) inbox := createWidgetTestInbox(t, db, account.ID) config := &model.WidgetThemeConfig{ InboxID: inbox.ID, PrimaryColor: "#ff0000", BackgroundColor: "#ffffff", TextColor: "#333333", FontFamily: "Arial, sans-serif", WidgetPosition: "right", DarkMode: "light", } err := repo.Create(ctx, config) require.NoError(t, err, "Create should succeed") assert.NotZero(t, config.ID, "ID should be assigned after Create") assert.NotZero(t, config.InboxID, "InboxID should be preserved") assert.Equal(t, "#ff0000", config.PrimaryColor, "PrimaryColor should be preserved") } func TestWidgetThemeConfigRepo_FindByInboxID(t *testing.T) { db := setupWidgetTestDB(t) repo := NewWidgetThemeConfigRepo(db) ctx := context.Background() account := createWidgetTestAccount(t, db) inbox := createWidgetTestInbox(t, db, account.ID) config := &model.WidgetThemeConfig{ InboxID: inbox.ID, PrimaryColor: "#1f93ff", WidgetPosition: "right", } err := repo.Create(ctx, config) require.NoError(t, err) // Positive case: find by existing inbox ID found, err := repo.FindByInboxID(ctx, inbox.ID) require.NoError(t, err) assert.Equal(t, config.ID, found.ID) assert.Equal(t, inbox.ID, found.InboxID) assert.Equal(t, "#1f93ff", found.PrimaryColor) // Negative case: find by non-existing inbox ID found2, err := repo.FindByInboxID(ctx, 99999) assert.Nil(t, found2) assert.Error(t, err, "FindByInboxID with non-existing ID should return error") } func TestWidgetThemeConfigRepo_FindByID(t *testing.T) { db := setupWidgetTestDB(t) repo := NewWidgetThemeConfigRepo(db) ctx := context.Background() account := createWidgetTestAccount(t, db) inbox := createWidgetTestInbox(t, db, account.ID) config := &model.WidgetThemeConfig{ InboxID: inbox.ID, PrimaryColor: "#aabbcc", } err := repo.Create(ctx, config) require.NoError(t, err) // Positive case found, err := repo.FindByID(ctx, config.ID) require.NoError(t, err) assert.Equal(t, config.InboxID, found.InboxID) assert.Equal(t, "#aabbcc", found.PrimaryColor) // Negative case: non-existing ID found2, err := repo.FindByID(ctx, 99999) assert.Nil(t, found2) assert.Error(t, err) } func TestWidgetThemeConfigRepo_Update(t *testing.T) { db := setupWidgetTestDB(t) repo := NewWidgetThemeConfigRepo(db) ctx := context.Background() account := createWidgetTestAccount(t, db) inbox := createWidgetTestInbox(t, db, account.ID) config := &model.WidgetThemeConfig{ InboxID: inbox.ID, PrimaryColor: "#1f93ff", WidgetPosition: "right", DarkMode: "light", } err := repo.Create(ctx, config) require.NoError(t, err) // Update fields config.PrimaryColor = "#00ff00" config.WidgetPosition = "left" config.DarkMode = "dark" err = repo.Update(ctx, config) require.NoError(t, err, "Update should succeed") // Verify update found, err := repo.FindByID(ctx, config.ID) require.NoError(t, err) assert.Equal(t, "#00ff00", found.PrimaryColor, "PrimaryColor should be updated") assert.Equal(t, "left", found.WidgetPosition, "WidgetPosition should be updated") assert.Equal(t, "dark", found.DarkMode, "DarkMode should be updated") } func TestWidgetThemeConfigRepo_Delete(t *testing.T) { db := setupWidgetTestDB(t) repo := NewWidgetThemeConfigRepo(db) ctx := context.Background() account := createWidgetTestAccount(t, db) inbox := createWidgetTestInbox(t, db, account.ID) config := &model.WidgetThemeConfig{ InboxID: inbox.ID, PrimaryColor: "#1f93ff", } err := repo.Create(ctx, config) require.NoError(t, err) // Delete err = repo.Delete(ctx, config.ID) require.NoError(t, err, "Delete should succeed") // Verify soft-delete: FindByID should fail found, err := repo.FindByID(ctx, config.ID) assert.Nil(t, found) assert.Error(t, err, "FindByID after Delete should return error") } func TestWidgetThemeConfigRepo_DeleteByInboxID(t *testing.T) { db := setupWidgetTestDB(t) repo := NewWidgetThemeConfigRepo(db) ctx := context.Background() account := createWidgetTestAccount(t, db) inbox := createWidgetTestInbox(t, db, account.ID) config := &model.WidgetThemeConfig{ InboxID: inbox.ID, PrimaryColor: "#1f93ff", } err := repo.Create(ctx, config) require.NoError(t, err) // Delete by inbox ID err = repo.DeleteByInboxID(ctx, inbox.ID) require.NoError(t, err, "DeleteByInboxID should succeed") // Verify soft-delete found, err := repo.FindByInboxID(ctx, inbox.ID) assert.Nil(t, found) assert.Error(t, err, "FindByInboxID after DeleteByInboxID should return error") } func TestWidgetThemeConfigRepo_DuplicateInboxID(t *testing.T) { db := setupWidgetTestDB(t) repo := NewWidgetThemeConfigRepo(db) ctx := context.Background() account := createWidgetTestAccount(t, db) inbox := createWidgetTestInbox(t, db, account.ID) config1 := &model.WidgetThemeConfig{ InboxID: inbox.ID, PrimaryColor: "#111111", } err := repo.Create(ctx, config1) require.NoError(t, err) // Creating a second config for the same inbox should be allowed // (no unique constraint on InboxID in the model definition) config2 := &model.WidgetThemeConfig{ InboxID: inbox.ID, PrimaryColor: "#222222", } err = repo.Create(ctx, config2) require.NoError(t, err, "second config with same InboxID should be created") // FindByInboxID returns the first matching record found, err := repo.FindByInboxID(ctx, inbox.ID) require.NoError(t, err) assert.Equal(t, config1.ID, found.ID, "FindByInboxID returns first match") } func TestWidgetThemeConfigRepo_CRUDLifecycle(t *testing.T) { db := setupWidgetTestDB(t) repo := NewWidgetThemeConfigRepo(db) ctx := context.Background() account := createWidgetTestAccount(t, db) inbox := createWidgetTestInbox(t, db, account.ID) // Create config := &model.WidgetThemeConfig{ InboxID: inbox.ID, PrimaryColor: "#1f93ff", BackgroundColor: "#ffffff", TextColor: "#1f1f1f", FontFamily: "Inter, sans-serif", FontSize: "14px", WidgetPosition: "right", WidgetAlignment: "bottom", AvatarRadius: "50%", ButtonRadius: "8px", DarkMode: "auto", HideMessageBubble: false, ShowPopUpWindow: false, } err := repo.Create(ctx, config) require.NoError(t, err) assert.NotZero(t, config.ID) // Read found, err := repo.FindByID(ctx, config.ID) require.NoError(t, err) assert.Equal(t, config.InboxID, found.InboxID) assert.Equal(t, "auto", found.DarkMode) foundByInbox, err := repo.FindByInboxID(ctx, inbox.ID) require.NoError(t, err) assert.Equal(t, config.ID, foundByInbox.ID) // Update found.DarkMode = "dark" found.PrimaryColor = "#00cc00" err = repo.Update(ctx, found) require.NoError(t, err) updated, err := repo.FindByID(ctx, config.ID) require.NoError(t, err) assert.Equal(t, "dark", updated.DarkMode) assert.Equal(t, "#00cc00", updated.PrimaryColor) // Delete err = repo.Delete(ctx, config.ID) require.NoError(t, err) _, err = repo.FindByID(ctx, config.ID) assert.Error(t, err, "should not find deleted record") }