test: add guest booking, reservation, and anonymization tests

New tests: guest user creation (success, duplicate email, registered collision),
guest booking flow (success, missing user_id, non-guest user_id, deposit bypass),
reservation lifecycle (logged-in, anonymous, replace, validation, conflict detection,
dual cleanup), anonymization (6mo threshold, pending exclusion).

Fixes: deposit advance rule 48h→24h (stale test), time-based test flakiness
(2h→72h offsets), handler confusion in no-show tests, enum type casting for
booking status.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-04-30 11:45:08 +01:00
co-authored by Sisyphus
parent 4f173b04dc
commit 52ca9b425b
3 changed files with 386 additions and 58 deletions
@@ -21,6 +21,7 @@ import (
"fmt"
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
@@ -698,3 +699,68 @@ func TestCleanupOldReservations(t *testing.T) {
// Ensure pool is used to avoid unused import error
var _ = pgxpool.Pool{}
var _ = bytes.Buffer{}
func TestAnonymizeStaleGuestAccounts(t *testing.T) {
cleanup := setupTimeBlockersTestDB(t)
defer cleanup()
ctx := context.Background()
// Guest 1: last booking 7 months ago — should be anonymized
guest1ID, _ := fixtures.CreateTestUser(db.DB)
db.DB.Exec(ctx, `UPDATE users SET account_role = 'guest' WHERE id = $1`, guest1ID)
db.DB.Exec(ctx, `
INSERT INTO bookings (user_id, start_time, status, deposit_required)
VALUES ($1, NOW() - INTERVAL '7 months', 'completed', false)
`, guest1ID)
// Guest 2: last booking 3 months ago — should NOT be anonymized
guest2ID, _ := fixtures.CreateTestUser(db.DB)
db.DB.Exec(ctx, `UPDATE users SET account_role = 'guest' WHERE id = $1`, guest2ID)
db.DB.Exec(ctx, `
INSERT INTO bookings (user_id, start_time, status, deposit_required)
VALUES ($1, NOW() - INTERVAL '3 months', 'completed', false)
`, guest2ID)
// Guest 3: has a pending booking — should NOT be anonymized (regardless of booking age)
guest3ID, _ := fixtures.CreateTestUser(db.DB)
db.DB.Exec(ctx, `UPDATE users SET account_role = 'guest' WHERE id = $1`, guest3ID)
db.DB.Exec(ctx, `
INSERT INTO bookings (user_id, start_time, status, deposit_required)
VALUES ($1, NOW() + INTERVAL '2 days', 'pending', false)
`, guest3ID)
// Run anonymization
err := AnonymizeStaleGuestAccounts(ctx)
if err != nil {
t.Fatalf("AnonymizeStaleGuestAccounts failed: %v", err)
}
// Guest 1 should be anonymized
var g1Name string
db.DB.QueryRow(ctx, `SELECT n_first_name FROM users WHERE id = $1`, guest1ID).Scan(&g1Name)
if g1Name != "Guest" {
t.Errorf("expected guest 1 to be anonymized, got first_name='%s'", g1Name)
}
// Guest 2 should NOT be anonymized
var g2Name string
db.DB.QueryRow(ctx, `SELECT n_first_name FROM users WHERE id = $1`, guest2ID).Scan(&g2Name)
if g2Name == "Guest" {
t.Error("expected guest 2 to NOT be anonymized (booking too recent)")
}
// Guest 3 should NOT be anonymized (has pending booking)
var g3Name string
db.DB.QueryRow(ctx, `SELECT n_first_name FROM users WHERE id = $1`, guest3ID).Scan(&g3Name)
if g3Name == "Guest" {
t.Error("expected guest 3 to NOT be anonymized (has pending booking)")
}
// Verify guest 1's email was anonymized
var g1Email string
db.DB.QueryRow(ctx, `SELECT email FROM users WHERE id = $1`, guest1ID).Scan(&g1Email)
if !strings.HasPrefix(g1Email, "anon-") {
t.Errorf("expected guest 1 email to start with 'anon-', got '%s'", g1Email)
}
}