test: repair integration harness — wire SettingsRegistry, reuse preserved dev admin

Two pre-existing harness breaks found while running the device tests:

- RegisterRoutes dereferences cfg.Settings (auth rate limit) but
  setupTestServer never set it — every integration test nil-panicked at
  route registration. Wire database.NewSettingsRegistry(queries) the
  same way main.go does.
- The cleanup deliberately PRESERVES testuser@tests.bookhoard.internal
  (shared dev admin), but setup then blindly re-INSERTed that user, so
  every run after the first failed on users_email_key. Reuse the user
  when it exists; default collections are created only for a NEW user
  (the preserved admin already has its set).

Also documented the offline runner used on slow links: build the test
binary on the host (CGO_ENABLED=0 go test -c) and execute it inside the
bookhoard-tests image against the compose network — no in-container
module downloads, no image rebuild.
This commit is contained in:
John O'Keefe
2026-09-18 16:06:14 -04:00
parent 5cdfe5a8dd
commit 4faa217822
+28 -14
View File
@@ -544,6 +544,10 @@ func setupTestServer(t *testing.T) *TestServerSetup {
AnnotationService: annotationService,
DeviceAuthMiddleware: deviceAuthMiddleware,
LoginTracker: loginAttemptTracker,
// RegisterRoutes dereferences Settings for the auth rate limit;
// the main binary wires database.NewSettingsRegistry(queries) —
// the test harness must too or route registration nil-panics.
Settings: database.NewSettingsRegistry(queries),
}
router.RegisterRoutes(routerConfig)
@@ -588,21 +592,31 @@ func setupTestServer(t *testing.T) *TestServerSetup {
}
}
// Create fresh admin test user
// The admin test user doubles as the shared dev admin and is
// deliberately PRESERVED by the cleanup above — reuse it when it
// already exists instead of re-creating (a blind INSERT hits
// users_email_key on every run after the first).
passwordHash := "$2a$10$JjAtK7PPa1WexQC3AUGe8OXLeuseZ/haN1Mz7emMo6CfOvMiTVXWq"
adminUser, err := queries.CreateUser(ctx, database.CreateUserParams{
Email: "testuser@tests.bookhoard.internal",
Username: "testuser",
PasswordHash: passwordHash,
FirstName: pgtype.Text{String: "Test", Valid: true},
LastName: pgtype.Text{String: "User", Valid: true},
Role: "admin",
})
require.NoError(t, err, "Failed to create admin test user")
adminUUID, err := uuid.FromBytes(adminUser.ID.Bytes[:])
require.NoError(t, err, "Failed to parse admin user UUID")
createDefaultCollectionsForUser(t, queries, pgtype.UUID{Bytes: adminUUID, Valid: true})
var adminUUID uuid.UUID
if existing, gerr := queries.GetUserByEmail(ctx, "testuser@tests.bookhoard.internal"); gerr == nil {
adminUUID, err = uuid.FromBytes(existing.ID.Bytes[:])
require.NoError(t, err, "Failed to parse admin user UUID")
} else {
adminUser, cerr := queries.CreateUser(ctx, database.CreateUserParams{
Email: "testuser@tests.bookhoard.internal",
Username: "testuser",
PasswordHash: passwordHash,
FirstName: pgtype.Text{String: "Test", Valid: true},
LastName: pgtype.Text{String: "User", Valid: true},
Role: "admin",
})
require.NoError(t, cerr, "Failed to create admin test user")
adminUUID, err = uuid.FromBytes(adminUser.ID.Bytes[:])
require.NoError(t, err, "Failed to parse admin user UUID")
// Default collections are created exactly once per user; the
// preserved dev admin already has its set from the first run.
createDefaultCollectionsForUser(t, queries, pgtype.UUID{Bytes: adminUUID, Valid: true})
}
// Create fresh regular test user
regularUser, err := queries.CreateUser(ctx, database.CreateUserParams{