fix: Fix device response fields and add missing approved confirmation

feat: Improve device test infrastructure with setupDeviceTest helper

refactor: Standardize pending registrations API response field names
This commit is contained in:
2026-02-10 09:31:35 -05:00
parent 36e03f89b6
commit 1413c75b26
3 changed files with 169 additions and 87 deletions
+140
View File
@@ -12,6 +12,7 @@ import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"os"
@@ -37,6 +38,33 @@ func (cv *CustomValidator) Validate(i interface{}) error {
return cv.validator.Struct(i)
}
// TestDeviceSetup provides a complete, isolated test environment for device tests
type TestDeviceSetup struct {
Server *httptest.Server
DB *database.Queries
Config *config.Config
User UserTestData
Device DeviceTestData
UserToken string
}
type UserTestData struct {
ID uuid.UUID
Email string
Username string
Password string
Token string
}
type DeviceTestData struct {
ID uuid.UUID
Name string
Type string
Identifier string
AuthToken string
PGType database.Devices
}
// Helper functions for testing
func containsPrefix(s, prefix string) bool {
return len(s) >= len(prefix) && s[:len(prefix)] == prefix
@@ -100,6 +128,118 @@ func getCachePath() string {
return "/app/cache/kepub"
}
// setupDeviceTest creates a complete test environment for device tests
func setupDeviceTest(t *testing.T) *TestDeviceSetup {
ts, db, cfg := setupTestServer(t)
// Create user ONCE with known credentials
user := createTestUserOnce(t, db)
// Login to get token
token := loginUserWithCredentials(t, ts, user.Email, user.Password)
return &TestDeviceSetup{
Server: ts,
DB: db,
Config: cfg,
User: user,
UserToken: token,
}
}
// createTestUserOnce creates a test user with deterministic UUID
func createTestUserOnce(t *testing.T, db *database.Queries) UserTestData {
ctx := context.Background()
// Clean up any existing test user first
existingUser, err := db.GetUserByEmail(ctx, "testuser@example.com")
if err == nil {
db.DeleteUser(ctx, existingUser.ID)
}
// Create user with known credentials
passwordHash := "$2a$10$JjAtK7PPa1WexQC3AUGe8OXLeuseZ/haN1Mz7emMo6CfOvMiTVXWq"
user, err := db.CreateUser(ctx, database.CreateUserParams{
Email: "testuser@example.com",
Username: "testuser",
PasswordHash: passwordHash,
FirstName: pgtype.Text{String: "Test", Valid: true},
LastName: pgtype.Text{String: "User", Valid: true},
Role: "admin",
})
require.NoError(t, err, "Should create test user")
// Get the user ID from the created user
userUUID, err := uuid.FromBytes(user.ID.Bytes[0:16])
require.NoError(t, err, "Should parse user UUID")
return UserTestData{
ID: userUUID,
Email: "testuser@example.com",
Username: "testuser",
Password: "Test@Pass123!",
}
}
// loginUserWithCredentials performs explicit login with provided credentials
func loginUserWithCredentials(t *testing.T, ts *httptest.Server, email, password string) string {
loginRequest := map[string]interface{}{
"login": email,
"password": password,
}
body, _ := json.Marshal(loginRequest)
req, _ := http.NewRequest("POST", ts.URL+"/api/auth/login", bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
require.NoError(t, err, "Failed to login")
defer resp.Body.Close()
require.Equal(t, http.StatusOK, resp.StatusCode, "Login should succeed")
var result map[string]interface{}
json.NewDecoder(resp.Body).Decode(&result)
token, ok := result["access_token"].(string)
require.True(t, ok, "Should have access_token")
require.NotEmpty(t, token, "Access token should not be empty")
return token
}
// CreateDevice creates a test device for the TestDeviceSetup
func (s *TestDeviceSetup) CreateDevice(t *testing.T, deviceName, deviceType, deviceIdentifier string) *DeviceTestData {
deviceToken := fmt.Sprintf("dev_%s", uuid.New().String())
pgUserID := pgtype.UUID{Bytes: [16]byte(s.User.ID), Valid: true}
device, err := s.DB.CreateDevice(context.Background(), database.CreateDeviceParams{
UserID: pgUserID,
DeviceName: deviceName,
DeviceType: deviceType,
DeviceIdentifier: deviceIdentifier,
AuthToken: deviceToken,
SyncEnabled: pgtype.Bool{Bool: true, Valid: true},
AutoSync: pgtype.Bool{Bool: true, Valid: true},
SyncFrequencyMinutes: pgtype.Int4{Int32: 5, Valid: true},
DeviceMetadata: []byte("{}"),
})
require.NoError(t, err, "Should create device")
deviceUUID, err := uuid.FromBytes(device.ID.Bytes[0:16])
require.NoError(t, err, "Should parse device ID")
return &DeviceTestData{
ID: deviceUUID,
Name: deviceName,
Type: deviceType,
Identifier: deviceIdentifier,
AuthToken: deviceToken,
PGType: device,
}
}
// setupTestServer creates a test server with a test database
// Returns: (*httptest.Server, *database.Queries, *config.Config)
func setupTestServer(t *testing.T) (*httptest.Server, *database.Queries, *config.Config) {