package models_test import ( "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gorm.io/datatypes" "rocketgit.ru/rsmon/worker/app/models" ) // TestMonitorTransferGroupSwap verifies that swapping a monitor's // group_id between two accounts correctly re-homes the monitor without // touching any other monitor data. This is the database primitive that // POST /api/v1/monitors/:id/transfer relies on. func TestMonitorTransferGroupSwap(t *testing.T) { models.Drop() models.Migrate() plan := models.Plan{Name: "test", Default: true} require.NoError(t, models.DB().Create(&plan).Error) // Two accounts, each with their own default group. accA := models.Account{Name: "A", PlanID: &plan.ID} require.NoError(t, models.DB().Create(&accA).Error) accB := models.Account{Name: "B", PlanID: &plan.ID} require.NoError(t, models.DB().Create(&accB).Error) groupA := models.Group{AccountID: accA.ID, Name: "A-default"} require.NoError(t, models.DB().Create(&groupA).Error) groupB := models.Group{AccountID: accB.ID, Name: "B-default"} require.NoError(t, models.DB().Create(&groupB).Error) // Monitor lives in account A with one HTTP check. monitor := models.Monitor{ GroupID: groupA.ID, Host: "example-a.test", } require.NoError(t, models.DB().Create(&monitor).Error) check := models.Check{ MonitorID: monitor.ID, Kind: "http", URL: ptrString("https://example-a.test/"), Interval: 300, Settings: datatypes.JSON([]byte("{}")), } require.NoError(t, models.DB().Create(&check).Error) // Simulate the controller-side update. require.NoError(t, models.DB(). Model(&models.Monitor{}). Where("id = ?", monitor.ID). Update("group_id", groupB.ID).Error) // Monitor now lives in B; check follows by FK on monitor_id. var reloaded models.Monitor require.NoError(t, models.DB().Preload("Group").First(&reloaded, monitor.ID).Error) assert.Equal(t, groupB.ID, reloaded.GroupID, "monitor group_id should now point at account B's group") assert.Equal(t, accB.ID, reloaded.Group.AccountID, "preloaded group should belong to account B") var checkCount int64 require.NoError(t, models.DB().Model(&models.Check{}). Where("monitor_id = ?", monitor.ID).Count(&checkCount).Error) assert.Equal(t, int64(1), checkCount, "check rows must follow the monitor across the move") } // TestMonitorTransferSameAccountGuard documents the early-return path: the // controller must not silently no-op when the caller picks the current // account, and the test exercises that the DB stays untouched. func TestMonitorTransferSameAccountGuard(t *testing.T) { models.Drop() models.Migrate() plan := models.Plan{Name: "test", Default: true} require.NoError(t, models.DB().Create(&plan).Error) acc := models.Account{Name: "only", PlanID: &plan.ID} require.NoError(t, models.DB().Create(&acc).Error) group := models.Group{AccountID: acc.ID, Name: "only"} require.NoError(t, models.DB().Create(&group).Error) monitor := models.Monitor{GroupID: group.ID, Host: "x.test"} require.NoError(t, models.DB().Create(&monitor).Error) // No update is issued because the controller rejects same-account moves // before the SQL UPDATE. Verify the row is unchanged. var reloaded models.Monitor require.NoError(t, models.DB().First(&reloaded, monitor.ID).Error) assert.Equal(t, group.ID, reloaded.GroupID) } func ptrString(s string) *string { return &s }