//go:build dbtest package testsupport import ( "context" "testing" "github.com/google/uuid" "github.com/stretchr/testify/require" ) // DemoUserID 是測試共用的固定 user id,對齊雛形 demo-user 概念。 // 因 schema 的 users.id 是 UUID,這裡用一個固定 UUID 當測試 owner。 const DemoUserID = "00000000-0000-0000-0000-000000000001" // InsertUser 直接寫入一筆 users(測試 fixture)。 // // 塊 1+ 的 model / device / token repository 測試需要一個存在的 owner_user_id 來滿足 FK。 // 回傳寫入的 user id(傳入 id 為空時自動產生 UUID)。 func (tdb *TestDB) InsertUser(t *testing.T, id, email string) string { t.Helper() if id == "" { id = uuid.NewString() } if email == "" { email = id + "@test.local" } _, err := tdb.Pool.Exec(context.Background(), `INSERT INTO users (id, email) VALUES ($1, $2) ON CONFLICT (id) DO NOTHING`, id, email) require.NoError(t, err, "insert user fixture") return id } // EnsureDemoUser 確保 DemoUserID 這筆 user 存在,回傳其 id。 // 供「只需要一個合法 owner、不在意是誰」的 model / device 測試使用。 func (tdb *TestDB) EnsureDemoUser(t *testing.T) string { t.Helper() return tdb.InsertUser(t, DemoUserID, "demo@visiona.local") } // InsertDevice 直接寫入一筆 devices(測試 fixture)。 // // 塊 3 的 session_tokens 測試需要一個存在的 device_id(NOT NULL FK → devices(id))。 // ownerUserID 須先存在於 users。回傳寫入的 device id(傳入 id 為空時自動產生 UUID)。 func (tdb *TestDB) InsertDevice(t *testing.T, id, ownerUserID string) string { t.Helper() if id == "" { id = uuid.NewString() } _, err := tdb.Pool.Exec(context.Background(), `INSERT INTO devices (id, owner_user_id, name, serial_number) VALUES ($1, $2, $3, $4) ON CONFLICT (id) DO NOTHING`, id, ownerUserID, "fixture-device", "SN-"+id[:8]) require.NoError(t, err, "insert device fixture") return id } // CountRows 回傳指定 table 的列數(含或不含 soft-deleted 由呼叫端用 where 決定,此處為全表)。 // 供測試斷言「插入幾筆 / truncate 後是否歸零」。 func (tdb *TestDB) CountRows(t *testing.T, table string) int { t.Helper() var n int err := tdb.Pool.QueryRow(context.Background(), "SELECT count(*) FROM "+pgIdent(table)).Scan(&n) require.NoError(t, err, "count rows in %s", table) return n }