// memPairingExchanger 的單元測試(DB-on FK 收尾,問題 #2)。 // // 不帶 build tag:屬於預設 `go test ./...` 範圍(無需 Docker)。 // 驗證 in-memory exchanger 自建 device + 建 session token、且 session token 綁到該 device, // 與 pairing_exchange_db_test.go 的 Postgres dbtest 對齊行為。 package api import ( "context" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "visiona-backend/internal/auth" "visiona-backend/internal/device" ) func TestMemExchange_ProvisionCreatesDeviceAndSession(t *testing.T) { ctx := context.Background() devRepo := device.NewInMemoryRepository() sessions := auth.NewInMemorySessionTokenStore() exchanger := NewInMemoryPairingExchanger(devRepo, sessions) res, err := exchanger.Provision(ctx, "owner-1", "parent-hash", auth.SessionTokenTTL) require.NoError(t, err) require.NotEmpty(t, res.DeviceID) require.NotEmpty(t, res.SessionPlaintext) require.NotNil(t, res.SessionInfo) // device 自建、owner 對齊 dev, err := devRepo.Get(ctx, res.DeviceID) require.NoError(t, err) assert.Equal(t, "owner-1", dev.OwnerUserID) assert.Equal(t, defaultPairedDeviceName, dev.Name) assert.Equal(t, defaultPairedDeviceType, dev.DeviceType) assert.NotNil(t, dev.PairedAt) // session token 綁到自建 device tok, err := sessions.Get(ctx, res.SessionPlaintext) require.NoError(t, err) assert.Equal(t, res.DeviceID, tok.DeviceID, "session token 應綁到自建 device") assert.Equal(t, "owner-1", tok.UserID) assert.Equal(t, "parent-hash", tok.ParentTokenHash) } func TestMemExchange_Provision_DistinctDevices(t *testing.T) { ctx := context.Background() exchanger := NewInMemoryPairingExchanger( device.NewInMemoryRepository(), auth.NewInMemorySessionTokenStore()) res1, err := exchanger.Provision(ctx, "owner-1", "", auth.SessionTokenTTL) require.NoError(t, err) res2, err := exchanger.Provision(ctx, "owner-1", "", auth.SessionTokenTTL) require.NoError(t, err) assert.NotEqual(t, res1.DeviceID, res2.DeviceID) assert.NotEqual(t, res1.SessionPlaintext, res2.SessionPlaintext) }