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
This commit is contained in:
2026-02-24 23:42:40 +00:00
parent c6fe9e92a7
commit ea1a80dbda
5 changed files with 32 additions and 28 deletions
+1
View File
@@ -59,6 +59,7 @@ frontend/static/portfolio/*
# Composer dependencies # Composer dependencies
sabredav/vendor/ sabredav/vendor/
composer.lock
# ------------------------------------ # ------------------------------------
# 5. Local Tools and Notes # 5. Local Tools and Notes
+16 -8
View File
@@ -857,8 +857,9 @@ func TestAdminBookings_Create_DuringHolidayHours_Rejected(t *testing.T) {
} }
defer fixtures.DeleteService(db.DB, serviceID) defer fixtures.DeleteService(db.DB, serviceID)
// Create an exceptional (holiday) hours group for tomorrow // Create an exceptional (holiday) hours group for a fixed date (Thursday)
tomorrowDate := time.Now().AddDate(0, 0, 1) // 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 var groupID int
err = db.DB.QueryRow(context.Background(), ` err = db.DB.QueryRow(context.Background(), `
INSERT INTO exceptional_working_hours_groups (name, description) 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) 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(), ` _, err = db.DB.Exec(context.Background(), `
INSERT INTO exceptional_working_hours (group_id, weekday, start_time, end_time, is_open) INSERT INTO exceptional_working_hours (group_id, weekday, start_time, end_time, is_open)
VALUES ($1, $2, $3, $4, $5) 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 { if err != nil {
t.Fatalf("failed to create holiday hours: %v", err) 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(), ` _, err = db.DB.Exec(context.Background(), `
INSERT INTO exceptional_group_applications (group_id, week_start) INSERT INTO exceptional_group_applications (group_id, week_start)
VALUES ($1, $2) VALUES ($1, $2)
`, groupID, tomorrowDate) `, groupID, mondayOfWeek)
if err != nil { if err != nil {
t.Fatalf("failed to create holiday application: %v", err) t.Fatalf("failed to create holiday application: %v", err)
} }
// Try to create booking during holiday - should fail // 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{ req := bookings.AdminCreateBookingForUserRequest{
UserID: userID, UserID: userID,
StartTime: tomorrowTime, StartTime: targetTime,
ServiceIDs: []string{serviceID}, ServiceIDs: []string{serviceID},
} }
-1
View File
@@ -541,7 +541,6 @@ func AdminCreateBookingForUserHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
tx, err := db.DB.Begin(r.Context()) tx, err := db.DB.Begin(r.Context())
if err != nil { if err != nil {
log.Printf("Failed to start transaction: %v", err) log.Printf("Failed to start transaction: %v", err)
-8
View File
@@ -162,14 +162,6 @@ CREATE TABLE patch_tests (
expiry_months INT NOT NULL DEFAULT 6, expiry_months INT NOT NULL DEFAULT 6,
service_ids CHAR(12)[] DEFAULT '{}' 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); CREATE INDEX idx_patch_tests_name ON patch_tests(name);
+15 -11
View File
@@ -14,12 +14,7 @@ C_GREEN=$'\033[32m'
C_RED=$'\033[31m' C_RED=$'\033[31m'
C_BLUE=$'\033[34m' C_BLUE=$'\033[34m'
C_YELLOW=$'\033[33m' 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_info() { echo "🔹 $1" }
log_success() { echo "$1" } log_success() { echo "$1" }
log_error() { echo "$1" } log_error() { echo "$1" }
@@ -84,6 +79,7 @@ sleep 2
log_step "Seeding test database schema..." 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 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" log_success "Test database schema seeded"
# --- 3d. Verify test database is ready --- # --- 3d. Verify test database is ready ---
log_step "Verifying test database readiness..." log_step "Verifying test database readiness..."
MAX_ATTEMPTS=10 MAX_ATTEMPTS=10
@@ -101,12 +97,21 @@ if [ $ATTEMPT -eq $MAX_ATTEMPTS ]; then
exit 1 exit 1
fi fi
# --- 3d. Rustfs (don't wipe data, just restart) --- # --- 3e. Rustfs (wipe data for fresh start) ---
log_step "Restarting Rustfs (S3-compatible storage)..." log_step "Wiping Rustfs (S3 storage)..."
docker compose restart rustfs > /dev/null 2>&1 docker compose stop rustfs > /dev/null 2>&1 || true
log_success "Rustfs restarted" 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 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 --- # --- 4. Tmux Session Setup ---
if tmux has-session -t $SESSION_NAME 2>/dev/null; then if tmux has-session -t $SESSION_NAME 2>/dev/null; then
log_info "Killing existing tmux session..." log_info "Killing existing tmux session..."
@@ -179,7 +184,6 @@ C_YELLOW=$'\033[33m'
# --- Global for ID Capture --- # --- Global for ID Capture ---
LAST_BOOKING_ID="" LAST_BOOKING_ID=""
# --- Helper: API Request ---
# --- Helper: API Request --- # --- Helper: API Request ---
api_post() { api_post() {
local url="$1" local url="$1"