Commit Graph
23 Commits
Author SHA1 Message Date
John O'Keefe 7d88ec5184 fix(tests): test-created devices and fixture dirs now meet the cleanup contract
Test suites that attach devices to the SHARED admin (testuser, the live
dev account) escaped the harness sweeps whenever their names lacked
"test": createContractDeviceNamed named its devices by surface type
("koreader" — the web progress push adopts the device name as sync
source, so conflict tests drive a second named source without a
separate account), the reinstall regression test uses the web flow's
real "Reinstall Device" label, and opds_test.go's folders test named
its device "OPDS Folders Device". None had self-cleanup either, so
every suite run left 3 more rows on the dev account's device grid —
476 by the time anyone looked. TestDeviceSetup.CreateDevice also never
cleanup-registered, so any CURRENT or future helper-created device was
one rename away from the same leak.

Changes:
- TestDeviceSetup.CreateDevice self-deletes its row at test end
  (t.Cleanup): callers owe nothing to name hygiene any more.
- createContractDeviceNamed self-deletes likewise (contract-% prefix).
- device_test.go: core via cleanupDeviceByIdentifier on every device it
  attaches to the admin ("Reinstall Device" by unique identifier —
  the NAME is user-facing-labeled, sweeps must never torch it).
- Harness setup-time admin-device sweep gains the unambiguous harness
  patterns (dev_contract_* tokens, contract-%/opds-%/repro-reinstall-%
  identifiers) as the drift net; ran once with the rebuilt tests image
  and that sweep alone already purged the existing 476 rows.
- metadata_write_test.go now globs ALL test-metadata-write-* dirs in
  its RemoveAll instead of only its own pid's — killed runs left root-
  owned dirs on the user's uploads bind mount (7 found, deleted).

 audits: collections/saved-filters/libraries/sync_queue are clean;
 the only "test"-named media rows left are scans of the user's own
 on-disk test files (Test/, Bookhoard Test/, embedded " test" in two
 real books' metadata) — content, not suite debris.

Verified: filtered runs (contract/OPDS/reinstall/pairing/metadata)
green, zero device residue after the run, uploads mount clean.
2026-11-02 17:39:29 -05:00
John O'Keefe 3e98fadb9f test(devices): integration coverage for the pairing-code flow
Replaces the reject-route test (behavior removed) with coverage of the
replacement flow, run against the shared dev DB per the doctrine:
fresh per-run regular user for deterministic claims, uuid-suffixed
identifiers so UNIQUE(device_identifier) stays clear across runs, and
device rows cascade away with the fresh user — testuser is untouched.

- TestPairingClaimHappyPath: lookup normalizes spaced digits, does not
  bind; claim binds to the claimer only; the device's status poll then
  delivers a token matching the stored row.
- TestPairingWrongCodeIsGenericAndNonDestructive: a miss answers the
  generic invalid-code error and leaves the real code claimable.
- TestPairingClaimBindsClaimerOnly: the admin account has no device
  row for another user's claim, and the used code answers 409.
- TestPairingReRegisterRetiresPriorCode: the old code and its
  registration UUID both die; the fresh code claims.
- TestPairingCancelByRegistrationUUID: cancel is idempotent, kills only
  its own registration (code and poll), and leaves a sibling
  registration untouched.
- TestPairingAttemptRateLimit: 13th lookup/claim attempt in a minute is
  refused with 429 (uses the fresh regular user — the limiter is
  process-global, so sibling tests sharing a token would otherwise
  pre-spend the budget).
- TestListPendingRegistrations now pins the invisibility invariant: a
  live registration appears in no account's pending list, total 0.
- TestRejectDeviceRegistrationRemoved pins the reject route's removal
  (404/405).
2026-11-02 16:11:25 -05:00
John O'Keefe 740213f0a4 fix(auth): new users inherit the system-wide default timezone
default_timezone existed as a system setting (admin-editable, exposed
via SettingsRegistry.DefaultTimezone) but nothing read it at user
creation — the CreateUser query didn't even carry the column, so every
new user got the DB default UTC regardless. Both creation paths
(public register + admin create) now seed the user's timezone from the
setting, validated with time.LoadLocation and falling back to UTC when
unwired/empty/invalid.

Test-infra fixes surfaced by the run: TestUpdateProfileSelfEdit was
self-editing the SHARED admin (renaming it past the harness cleanup's
preserve-list, leaking a second admin row that broke the last-admin
tests) — it now edits a dedicated user with a unique name; the
last-admin tests get an ensureSingleAdmin precondition helper; the
websocket collection name is run-unique (non-test names persist in the
shared DB and UNIQUE(user_id,name) 409s on rerun).
2026-10-13 13:17:12 -04:00
John O'Keefe 843f35bbfc test(server): runs leave no residue — auto-cleanup for every resource the suite creates
Symptom: repeated full-suite runs poisoned the dev database with
leaked rows (duplicate Prefs Scope libraries, colliding device names,
saved-filter name conflicts on rerun) because tests created rows but
never deleted them, and stale-binary runs left rows the new cleanup
could not match.

- test_helpers: library creation now registers t.Cleanup DELETE (the
  leak root cause — createTestLibraryWithFolder never cleaned up).
  Suite-wide cleanup passes for libraries/collections/devices/
  saved-filters run both at setup (pre-pass against legacy residue)
  and in t.Cleanup (no per-run residue). Preserve the admin's real
  libraries; delete only convention-named test rows.
- setup seeds canonical system collections every run keyed on
  query_type (idempotent — heals renames/stale tombstones), moved out
  of the preserved-admin branch so it runs for every suite start.
- dashboard_integration: scope-testing library renamed into the
  test-row convention; ordering assertions on the restored
  "Want to Read" collection preserved.
- filters_test: filter names moved into the convention (rerun-safe —
  name-uniqueness 409 no longer trips second runs); five  .(string)
  type assertions panic-proofed with require.True guards (a panic here
  used to kill the whole test process mid-run, which is why a stack of
  "never ran" failures surfaced at once later).
- device_test: device names moved into the convention (ILIKE %test%
  hit them; duplicate-device-name conflicts gone).
2026-10-09 11:04:34 -04:00
John O'Keefe 1cd8557b58 fix(devices): re-approving a known device rotates its token instead of 500
App reinstalls that preserve data (Android Studio installDebug over an
existing install) re-register with the same device_identifier, but the
devices row from the previous install still exists — device_identifier
is UNIQUE, so ApproveDevice's blind INSERT failed with a unique
violation and returned 500 'failed to create device' (reproduced via
curl: second approve with the same identifier = instant 500; the ~98s
in the original report was app-side retry/polling, not server wait).

ApproveDevice is now idempotent: look the device up by identifier
first; a row owned by the approving user gets its auth token rotated
via UpdateDeviceAuthToken (row id unchanged, so synced highlights/
bookmarks/progress anchored to it stay valid; fresh install = fresh
credentials, old token invalidated); a row owned by another user gets
409; unknown identifiers INSERT as before, with the 23505 race falling
through to the rotate path. DB failures are logged (they were silent).

Also guard the in-memory pendingRegistrations map with a mutex —
register/approve/reject/status/list all touch it from HTTP goroutines,
and a racing write is a Go runtime fatal, not an error. The approver's
credential publication and the status poller's approved-branch snapshot
now run under the lock so the token can never be read half-written.

Regression test: TestApproveDeviceReapprovalRotatesToken — register →
approve → re-register same identifier → approve (must be 200) → token
rotated, exactly one devices row, row carries the new token.
2026-09-17 23:09:02 -04:00
john-okeefe a4962a87b2 fix: replace invalid new(expression) calls with proper pointer allocation
Go's new() builtin takes a type and allocates a zero value — it cannot
wrap an expression. All instances of new(someExpression) were compile
errors. Replace each with a local variable assignment and address-of
operator.

Affected files:
- handlers/koreader.go: progress field pointers (Chapter, Page, etc.)
- handlers/kobo.go: pagesRemaining pointer
- handlers/queue.go: uuidPtrToString and timestamptzPtrToString helpers
- router/reader.go: bookmark pageNumber and chapterNumber pointers
- services/media_scanner.go: validation error message pointers
- services/worker.go: StartedAt and CompletedAt timestamps
- sync/offline.go: GetDeviceStatus return pointer
- tests/device_test.go: SyncEnabled and SyncFrequencyMinutes pointers
2026-04-23 20:39:50 -04:00
john-okeefe 7f2aa5ef2d refactor(tests): replace temporary variable pointer pattern with new() builtin
Simplify device update test by using new(false) and new(int32(10)) instead
of declaring named sync variables and taking their addresses.
2026-04-20 08:59:01 -04:00
john-okeefe 89732b041b test: update test files to use @tests.bookhoard.internal domain
Update email domain in remaining test files:
- device_cap_test.go
- device_test.go
- queue_test.go
- refresh_token_test.go
- seven_day_session_test.go

All test files now consistently use the dedicated test domain
to prevent conflicts with real user data.
2026-02-22 11:21:00 -05:00
john-okeefe f54508e4dd test: improve test isolation and setup management
Add Token and RegularToken fields to TestServerSetup for pre-authenticated
access. Update setupTestServer to create fresh users with valid tokens at
initialization time. Simplify createTestMediaItemID to use setup.Token.
Remove loginTestUser, loginRegularUser, loginAdminUser functions in favor
of setup.Token/setup.RegularToken. Update createTestUserOnce and
getTestUserID/getRegularUserID to be idempotent. Update all test files to
use setup.Token instead of calling login helpers.
2026-02-22 01:57:22 -05:00
john-okeefe 8e054bd149 fix: update test files for token handling and response parsing
- Update callers of createTestMediaItemID to not pass token
- Fix loginAdminUser to delete/recreate admin user for consistent state
- Fix TestListAllQueueItems_Admin to parse response as map with 'items' key
- Remove unused token variables from tests
- Update device_test.go with admin password hash constant
2026-02-14 00:12:28 -05:00
john-okeefe 9ec2d3c37d 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.
2026-02-13 17:42:06 -05:00
john-okeefe 527c406f75 test: add comprehensive device token regeneration tests
- Test successful token regeneration
- Verify old tokens are invalidated after regeneration
- Test unauthorized and forbidden access scenarios
- Test not found and device type-specific behavior
- Validate sync URLs contain new tokens
2026-02-13 16:37:58 -05:00
john-okeefe 5b32b59781 fix(tests): Fix edge cases in test file migration 2026-02-10 13:03:32 -05:00
john-okeefe 6c610465eb refactor(tests): Update all test files to use TestServerSetup pattern 2026-02-10 13:01:12 -05:00
john-okeefe 2b24dd9dd3 fix: Fix failing integration tests and update documentation
- Fix TestUpdateDevice: Use correct JSON field name and handle float64 type
- Fix TestRejectDeviceRegistration: Expect message response instead of boolean
- Update approve device docs: Add missing response fields
- Update reject device docs: Correct message text and format
- Update Bruno API: Fix example response for reject endpoint

Both integration tests now pass while maintaining API consistency.
2026-02-10 10:22:19 -05:00
john-okeefe 1413c75b26 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
2026-02-10 09:31:35 -05:00
john-okeefe 2ff8506718 test: update conflicts and device test signatures
- Remove handler parameter from test function calls
- Update test signatures to match new setupTestServer return values
- Fix compilation errors after test helper refactoring
- Ensure test consistency across all test files
2026-02-06 17:06:12 -05:00
john-okeefe 4e1feca124 Rename test file references: Bookmann → Bookhoard
Test file updates:
- Update import paths in test files: bookmann/internal → bookhoard/internal
- Update test helper functions and references
- Update test comments and documentation

This is part 6 of the project rename to Bookhoard.
2026-02-01 16:12:18 -05:00
john-okeefe 5a7144b98e feat: add device management and queue management routes
- Add /devices route for device management interface
- Add /conflicts route for sync conflict resolution
- Add /queue route for sync queue management
- Add comprehensive tests for device cap management
- Add test suite for queue management
2026-01-31 18:25:28 -05:00
john-okeefe a3aa9f67ac feat: add Kobo device sync support and fix device route protection
- Add Kobo sync handler with markup, bookmark, analytics, and initialization endpoints
- Add Kobo integration tests and Bruno API test collection
- Move device approve/reject routes from public to protected routes
- Enhance test infrastructure with DATABASE_URL support and helper functions
- Fix device GetDevice handler nil pointer handling
- Clean up test reports and session files
2026-01-30 23:58:34 -05:00
john-okeefe 77d683277a test: add WebSocket integration tests
Add comprehensive WebSocket test coverage:
- TestWebSocketConnection: Basic connection and JWT auth
- TestWebSocketDeviceAuth: Device token authentication
- TestWebSocketProgressBroadcast: Real-time update delivery
- TestWebSocketPingPong: Heartbeat mechanism
- TestWebSocketConnectionLimit: Multiple concurrent connections
- TestWebSocketInvalidToken: Rejection of invalid tokens
- Helper function for test media item creation

Update test helpers to create ConnectionManager for tests.
Tests verify WebSocket connection, authentication, and
real-time progress broadcast functionality.
2026-01-30 21:48:30 -05:00
john-okeefe 95fe849eeb Fix test infrastructure and device UUID handling
- Remove manual device ID generation, use database-generated IDs
- Add comprehensive test helpers (setupTestServer, loginTestUser, getTestUserID)
- Add cleanup step for existing test users in integration tests
- Fix UUID parsing from database responses
2026-01-30 20:16:19 -05:00
john-okeefe 9d32e5a0f0 Add comprehensive integration tests for Phase 2 device management
Test Files Added:
- integration_test.sh: Automated integration test script
  * Tests full user flow: register, login, library creation, scanning
  * Tests device registration and management
  * Color-coded output with pass/fail tracking
  * Generates detailed test results report

- cmd/server/tests/device_test.go: Unit tests for device endpoints
  * TestDeviceRegistrationFlow: Full registration flow test
  * TestListDevices: Device listing functionality
  * TestUpdateDevice: Device settings updates
  * TestDeleteDevice: Device removal
  * TestDeviceAuthentication: Device auth middleware test

- cmd/server/tests/phase1_integration_test.go: Phase 1 integration tests
  * Tests universal progress tracking
  * Tests format group detection
  * Tests progress conversion

Test Coverage:
- Device registration with web-based approval flow
- Device management (list, update, delete)
- Device authentication and token validation
- User authentication and authorization
- Library creation and management
- Scanner integration
- Media items listing

Notes:
- Tests designed to run against live server on localhost:8765
- Integration test script uses bash/curl for endpoint testing
- Device tests require helper functions to be implemented
2026-01-30 16:57:01 -05:00