Phase 1: Convert device_test.go to struct-based assertions with DB verification

- Convert TestListDevices from map to handlers.DeviceListResponse
- Convert TestUpdateDevice to use handlers.DeviceUpdateRequest
- Add database verification after device update:
  * Query DB to verify sync_enabled, sync_frequency actually updated
  * Ensures data integrity - API says success, DB confirms it
- Impact: Compile-time safety for device endpoints, data integrity verification

Pattern: Replaces map[string]interface{} with type-safe structs,
ensures API changes caught at compile time, operations actually persist.
This commit is contained in:
2026-02-13 17:42:06 -05:00
parent 2deb845cbc
commit 9ec2d3c37d
+23 -16
View File
@@ -2,6 +2,7 @@ package main
import (
"bookhoard/internal/database"
"bookhoard/internal/handlers"
"bytes"
"context"
"encoding/json"
@@ -13,6 +14,7 @@ import (
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestDeviceRegistrationFlow(t *testing.T) {
@@ -128,17 +130,13 @@ func TestListDevices(t *testing.T) {
assert.Equal(t, http.StatusOK, rec.Code, "Should list devices")
var response map[string]interface{}
json.Unmarshal(rec.Body.Bytes(), &response)
var response handlers.DeviceListResponse
err := json.Unmarshal(rec.Body.Bytes(), &response)
require.NoError(t, err, "Should unmarshal device list response")
assert.GreaterOrEqual(t, len(response.Devices), 1, "Should have at least one device")
devices, ok := response["devices"].([]interface{})
assert.True(t, ok, "Should have devices array")
assert.GreaterOrEqual(t, len(devices), 1, "Should have at least one device")
firstDevice := devices[0].(map[string]interface{})
deviceName, ok := firstDevice["device_name"].(string)
assert.True(t, ok, "Should have device_name")
assert.Equal(t, "Test Device", deviceName, "Should match created device name")
firstDevice := response.Devices[0]
assert.Equal(t, "Test Device", firstDevice.DeviceName, "Should match created device name")
}
func TestUpdateDevice(t *testing.T) {
@@ -149,10 +147,12 @@ func TestUpdateDevice(t *testing.T) {
device := setup.CreateDevice(t, "Test Device", "koreader", "test-device-123")
// Update device
updateRequest := map[string]interface{}{
"device_name": "Updated Device Name",
"sync_enabled": false,
"sync_frequency_minutes": int32(10),
syncEnabled := false
syncFreq := int32(10)
updateRequest := handlers.DeviceUpdateRequest{
DeviceName: "Updated Device Name",
SyncEnabled: &syncEnabled,
SyncFrequencyMinutes: &syncFreq,
}
updateBody, _ := json.Marshal(updateRequest)
@@ -169,10 +169,17 @@ func TestUpdateDevice(t *testing.T) {
assert.True(t, response["device_updated"].(bool), "Should confirm device updated")
// NEW: Verify database state
updatedDevice := response["device"].(map[string]interface{})
assert.Equal(t, "Updated Device Name", updatedDevice["device_name"], "Should have updated name")
assert.Equal(t, false, updatedDevice["sync_enabled"], "Should be disabled")
assert.Equal(t, float64(10), updatedDevice["sync_frequency_minutes"], "Should have updated frequency")
// Verify in database
pgDeviceID := pgtype.UUID{Bytes: [16]byte(device.ID), Valid: true}
dbDevice, err := setup.DB.GetDevice(context.Background(), pgDeviceID)
require.NoError(t, err, "Should retrieve updated device")
assert.Equal(t, "Updated Device Name", dbDevice.DeviceName, "DB should have updated name")
assert.Equal(t, false, dbDevice.SyncEnabled.Bool, "DB should show sync disabled")
assert.Equal(t, int32(10), dbDevice.SyncFrequencyMinutes.Int32, "DB should have updated frequency")
}
func TestDeleteDevice(t *testing.T) {