From ea1a80dbda90374aa0692143cdb9ca0bc88ac6f6 Mon Sep 17 00:00:00 2001 From: Stephen Adamson Date: Tue, 24 Feb 2026 23:42:40 +0000 Subject: [PATCH] fix: resolve flaky holiday hours test and clean up dev scripts - Use fixed date (Thursday Feb 26, 2026) instead of dynamic tomorrow to avoid timezone-related test flakiness - Remove orphaned SQL fragment from init-script.sql - Clean up duplicate color code definitions in local-dev-2.sh - Add Rustfs data wipe and SabreDAV startup to dev script - Add composer.lock to .gitignore --- .gitignore | 1 + backend/handlers/admin/bookings_test.go | 24 +++++++++++++++-------- backend/handlers/bookings/manage.go | 1 - init-scripts/init-script.sql | 8 -------- local-dev-2.sh | 26 ++++++++++++++----------- 5 files changed, 32 insertions(+), 28 deletions(-) diff --git a/.gitignore b/.gitignore index 9a46093..30426ca 100644 --- a/.gitignore +++ b/.gitignore @@ -59,6 +59,7 @@ frontend/static/portfolio/* # Composer dependencies sabredav/vendor/ +composer.lock # ------------------------------------ # 5. Local Tools and Notes diff --git a/backend/handlers/admin/bookings_test.go b/backend/handlers/admin/bookings_test.go index 7ad4a9e..dba13cd 100644 --- a/backend/handlers/admin/bookings_test.go +++ b/backend/handlers/admin/bookings_test.go @@ -857,8 +857,9 @@ func TestAdminBookings_Create_DuringHolidayHours_Rejected(t *testing.T) { } defer fixtures.DeleteService(db.DB, serviceID) - // Create an exceptional (holiday) hours group for tomorrow - tomorrowDate := time.Now().AddDate(0, 0, 1) + // Create an exceptional (holiday) hours group for a fixed date (Thursday) + // Using absolute date - no timezone conversions + targetDate := time.Date(2026, 2, 26, 0, 0, 0, 0, time.UTC) // Thursday Feb 26, 2026 var groupID int err = db.DB.QueryRow(context.Background(), ` INSERT INTO exceptional_working_hours_groups (name, description) @@ -870,29 +871,36 @@ func TestAdminBookings_Create_DuringHolidayHours_Rejected(t *testing.T) { } defer db.DB.Exec(context.Background(), "DELETE FROM exceptional_working_hours_groups WHERE id = $1", groupID) - // Add closed hours for tomorrow (closed all day) + // Add closed hours for targetDate (closed all day) _, err = db.DB.Exec(context.Background(), ` INSERT INTO exceptional_working_hours (group_id, weekday, start_time, end_time, is_open) VALUES ($1, $2, $3, $4, $5) - `, groupID, int(tomorrowDate.Weekday()), "00:00:00", "23:59:59", false) + `, groupID, int(targetDate.Weekday()), "00:00:00", "23:59:59", false) if err != nil { t.Fatalf("failed to create holiday hours: %v", err) } - // Apply the group to the week containing tomorrow + // Apply the group to the week containing targetDate + // Must use Monday of that week (matching handler logic) + targetWeekday := int(targetDate.Weekday()) + if targetWeekday == 0 { + targetWeekday = 7 // Sunday -> 7 + } + mondayOfWeek := targetDate.AddDate(0, 0, -targetWeekday+1) _, err = db.DB.Exec(context.Background(), ` INSERT INTO exceptional_group_applications (group_id, week_start) VALUES ($1, $2) - `, groupID, tomorrowDate) + `, groupID, mondayOfWeek) + if err != nil { t.Fatalf("failed to create holiday application: %v", err) } // Try to create booking during holiday - should fail - tomorrowTime := tomorrowDate.Add(14 * time.Hour).Truncate(time.Second) // 2 PM tomorrow + targetTime := targetDate.Add(14 * time.Hour).Truncate(time.Second) // 2 PM on targetDate req := bookings.AdminCreateBookingForUserRequest{ UserID: userID, - StartTime: tomorrowTime, + StartTime: targetTime, ServiceIDs: []string{serviceID}, } diff --git a/backend/handlers/bookings/manage.go b/backend/handlers/bookings/manage.go index 8de3db4..e7f3850 100644 --- a/backend/handlers/bookings/manage.go +++ b/backend/handlers/bookings/manage.go @@ -541,7 +541,6 @@ func AdminCreateBookingForUserHandler(w http.ResponseWriter, r *http.Request) { return } - tx, err := db.DB.Begin(r.Context()) if err != nil { log.Printf("Failed to start transaction: %v", err) diff --git a/init-scripts/init-script.sql b/init-scripts/init-script.sql index d988f6e..aa2fc6a 100644 --- a/init-scripts/init-script.sql +++ b/init-scripts/init-script.sql @@ -162,14 +162,6 @@ CREATE TABLE patch_tests ( expiry_months INT NOT NULL DEFAULT 6, service_ids CHAR(12)[] DEFAULT '{}' ); - id CHAR(12) PRIMARY KEY DEFAULT generate_service_id(), - name VARCHAR(100) NOT NULL, - description TEXT, - notice_duration_hours INT NOT NULL DEFAULT 24, - expiry_months INT NOT NULL DEFAULT 6, - service_ids CHAR(12)[] DEFAULT '{}', - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() -); CREATE INDEX idx_patch_tests_name ON patch_tests(name); diff --git a/local-dev-2.sh b/local-dev-2.sh index 3836fed..6f7e1ec 100755 --- a/local-dev-2.sh +++ b/local-dev-2.sh @@ -14,12 +14,7 @@ C_GREEN=$'\033[32m' C_RED=$'\033[31m' C_BLUE=$'\033[34m' C_YELLOW=$'\033[33m' -# Color codes for output -C_RESET=$'\033[0m' -C_GREEN=$'\033[32m' -C_RED=$'\033[31m' -C_BLUE=$'\033[34m' -C_YELLOW=$'\033[33m' + log_info() { echo "🔹 $1" } log_success() { echo "✅ $1" } log_error() { echo "❌ $1" } @@ -84,6 +79,7 @@ sleep 2 log_step "Seeding test database schema..." docker exec -i postgres psql -U myuser -d crussell_test < init-scripts/init-script.sql 2>&1 | head -5 || true log_success "Test database schema seeded" + # --- 3d. Verify test database is ready --- log_step "Verifying test database readiness..." MAX_ATTEMPTS=10 @@ -101,12 +97,21 @@ if [ $ATTEMPT -eq $MAX_ATTEMPTS ]; then exit 1 fi -# --- 3d. Rustfs (don't wipe data, just restart) --- -log_step "Restarting Rustfs (S3-compatible storage)..." -docker compose restart rustfs > /dev/null 2>&1 -log_success "Rustfs restarted" +# --- 3e. Rustfs (wipe data for fresh start) --- +log_step "Wiping Rustfs (S3 storage)..." +docker compose stop rustfs > /dev/null 2>&1 || true +docker compose rm -f rustfs > /dev/null 2>&1 || true +docker volume rm crussell_rustfs_data > /dev/null 2>&1 || true +docker compose up rustfs -d > /dev/null 2>&1 +log_success "Rustfs wiped and restarted" sleep 2 +# --- 3f. SabreDAV (start early to create tables) --- +log_step "Starting SabreDAV (CardDAV/CalDAV)..." +docker compose up sabredav -d > /dev/null 2>&1 +log_success "SabreDAV started" +sleep 3 + # --- 4. Tmux Session Setup --- if tmux has-session -t $SESSION_NAME 2>/dev/null; then log_info "Killing existing tmux session..." @@ -179,7 +184,6 @@ C_YELLOW=$'\033[33m' # --- Global for ID Capture --- LAST_BOOKING_ID="" -# --- Helper: API Request --- # --- Helper: API Request --- api_post() { local url="$1"