test: add tests for staged default hours change handlers
Add tests for ScheduleDefaultHoursChange, GetScheduledDefaultHoursChange, CancelScheduledDefaultHoursChange, GetDefaultHoursConflictingBookings, and GetWorkingHours/GetDefaultHours integration with staged changes.
This commit is contained in:
@@ -90,20 +90,24 @@ func TestScheduling_GetDefaultHours(t *testing.T) {
|
||||
t.Errorf("expected status 200, got %d. body: %s", w.Code, w.Body.String())
|
||||
}
|
||||
|
||||
var response []DefaultHours
|
||||
var response ScheduledHoursChangeResponse
|
||||
if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil {
|
||||
t.Fatalf("failed to unmarshal response: %v", err)
|
||||
}
|
||||
|
||||
if len(response) != 7 {
|
||||
t.Errorf("expected 7 days of hours, got %d", len(response))
|
||||
if len(response.Current) != 7 {
|
||||
t.Errorf("expected 7 days of hours, got %d", len(response.Current))
|
||||
}
|
||||
|
||||
if response.ScheduledChange != nil {
|
||||
t.Errorf("expected no scheduled change, got effective_date=%s", response.ScheduledChange.EffectiveDate)
|
||||
}
|
||||
|
||||
// Verify Monday (weekday 0) has our seeded hours
|
||||
var monday *DefaultHours
|
||||
for i := range response {
|
||||
if response[i].Weekday == 0 {
|
||||
monday = &response[i]
|
||||
for i := range response.Current {
|
||||
if response.Current[i].Weekday == 0 {
|
||||
monday = &response.Current[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -4221,3 +4225,457 @@ func TestPreviewAvailableHours_OutOfHours_Admin(t *testing.T) {
|
||||
t.Error("expected out_of_hours to be open")
|
||||
}
|
||||
}
|
||||
|
||||
// --- Tests for Staged Default Hours Change ---
|
||||
|
||||
// TestScheduleDefaultHoursChange_Success creates a pending change.
|
||||
func TestScheduleDefaultHoursChange_Success(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, tx := resetTestData(t)
|
||||
|
||||
adminID, err := fixtures.CreateTestAdminUser(tx)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create admin user: %v", err)
|
||||
}
|
||||
defer fixtures.DeleteUser(tx, adminID)
|
||||
|
||||
futureDate := time.Now().AddDate(0, 0, 7).Format("2006-01-02")
|
||||
|
||||
hours := make([]map[string]interface{}, 7)
|
||||
for i := 0; i < 7; i++ {
|
||||
hours[i] = map[string]interface{}{
|
||||
"weekday": i,
|
||||
"startTime": "10:00",
|
||||
"endTime": "18:00",
|
||||
"isOpen": true,
|
||||
}
|
||||
}
|
||||
|
||||
payload := map[string]interface{}{
|
||||
"hours": hours,
|
||||
"effective_date": futureDate,
|
||||
}
|
||||
|
||||
adminCtx := context.WithValue(ctx, mw.UserIDKey, adminID)
|
||||
handler := http.HandlerFunc(ScheduleDefaultHoursChange)
|
||||
w := makeRequest(handler, "POST", "/api/admin/scheduling/default-hours/schedule", payload, adminCtx)
|
||||
|
||||
if w.Code != http.StatusOK {
|
||||
t.Fatalf("expected 200, got %d. body: %s", w.Code, w.Body.String())
|
||||
}
|
||||
|
||||
var resp map[string]string
|
||||
if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil {
|
||||
t.Fatalf("failed to unmarshal: %v", err)
|
||||
}
|
||||
if resp["effective_date"] != futureDate {
|
||||
t.Errorf("expected effective_date %s, got %s", futureDate, resp["effective_date"])
|
||||
}
|
||||
}
|
||||
|
||||
// TestScheduleDefaultHoursChange_PastDate rejects past dates.
|
||||
func TestScheduleDefaultHoursChange_PastDate(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, tx := resetTestData(t)
|
||||
|
||||
adminID, err := fixtures.CreateTestAdminUser(tx)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create admin user: %v", err)
|
||||
}
|
||||
defer fixtures.DeleteUser(tx, adminID)
|
||||
|
||||
pastDate := "2020-01-01"
|
||||
hours := make([]map[string]interface{}, 7)
|
||||
for i := 0; i < 7; i++ {
|
||||
hours[i] = map[string]interface{}{"weekday": i, "startTime": "10:00", "endTime": "18:00", "isOpen": true}
|
||||
}
|
||||
|
||||
payload := map[string]interface{}{"hours": hours, "effective_date": pastDate}
|
||||
adminCtx := context.WithValue(ctx, mw.UserIDKey, adminID)
|
||||
handler := http.HandlerFunc(ScheduleDefaultHoursChange)
|
||||
w := makeRequest(handler, "POST", "/api/admin/scheduling/default-hours/schedule", payload, adminCtx)
|
||||
|
||||
if w.Code != http.StatusBadRequest {
|
||||
t.Errorf("expected 400 for past date, got %d: %s", w.Code, w.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
// TestScheduleDefaultHoursChange_Duplicate rejects a second pending change.
|
||||
func TestScheduleDefaultHoursChange_Duplicate(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, tx := resetTestData(t)
|
||||
|
||||
adminID, err := fixtures.CreateTestAdminUser(tx)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create admin user: %v", err)
|
||||
}
|
||||
defer fixtures.DeleteUser(tx, adminID)
|
||||
|
||||
futureDate := time.Now().AddDate(0, 0, 7).Format("2006-01-02")
|
||||
hours := make([]map[string]interface{}, 7)
|
||||
for i := 0; i < 7; i++ {
|
||||
hours[i] = map[string]interface{}{"weekday": i, "startTime": "10:00", "endTime": "18:00", "isOpen": true}
|
||||
}
|
||||
payload := map[string]interface{}{"hours": hours, "effective_date": futureDate}
|
||||
|
||||
adminCtx := context.WithValue(ctx, mw.UserIDKey, adminID)
|
||||
handler := http.HandlerFunc(ScheduleDefaultHoursChange)
|
||||
|
||||
w1 := makeRequest(handler, "POST", "/api/admin/scheduling/default-hours/schedule", payload, adminCtx)
|
||||
if w1.Code != http.StatusOK {
|
||||
t.Fatalf("first schedule should succeed, got %d: %s", w1.Code, w1.Body.String())
|
||||
}
|
||||
|
||||
w2 := makeRequest(handler, "POST", "/api/admin/scheduling/default-hours/schedule", payload, adminCtx)
|
||||
if w2.Code != http.StatusConflict {
|
||||
t.Errorf("expected 409 for duplicate, got %d: %s", w2.Code, w2.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetScheduledDefaultHoursChange returns the pending change.
|
||||
func TestGetScheduledDefaultHoursChange_Success(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, tx := resetTestData(t)
|
||||
|
||||
adminID, err := fixtures.CreateTestAdminUser(tx)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create admin user: %v", err)
|
||||
}
|
||||
defer fixtures.DeleteUser(tx, adminID)
|
||||
|
||||
futureDate := time.Now().AddDate(0, 0, 7).Format("2006-01-02")
|
||||
|
||||
hoursJSON := `[{"weekday":0,"startTime":"10:00","endTime":"18:00","isOpen":true},{"weekday":1,"startTime":"10:00","endTime":"18:00","isOpen":true},{"weekday":2,"startTime":"10:00","endTime":"18:00","isOpen":true},{"weekday":3,"startTime":"10:00","endTime":"18:00","isOpen":true},{"weekday":4,"startTime":"10:00","endTime":"18:00","isOpen":true},{"weekday":5,"startTime":"10:00","endTime":"18:00","isOpen":true},{"weekday":6,"startTime":"10:00","endTime":"18:00","isOpen":true}]`
|
||||
_, err = tx.Exec(ctx, `
|
||||
INSERT INTO default_hours_scheduled_changes (effective_date, created_by, hours)
|
||||
VALUES ($1, $2, $3)
|
||||
`, futureDate, adminID, hoursJSON)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to insert scheduled change: %v", err)
|
||||
}
|
||||
|
||||
handler := http.HandlerFunc(GetScheduledDefaultHoursChange)
|
||||
w := makeRequest(handler, "GET", "/api/admin/scheduling/default-hours/scheduled", nil, ctx)
|
||||
|
||||
if w.Code != http.StatusOK {
|
||||
t.Fatalf("expected 200, got %d: %s", w.Code, w.Body.String())
|
||||
}
|
||||
|
||||
var resp ScheduledHoursChange
|
||||
if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil {
|
||||
t.Fatalf("failed to unmarshal: %v", err)
|
||||
}
|
||||
if resp.EffectiveDate != futureDate {
|
||||
t.Errorf("expected effective_date %s, got %s", futureDate, resp.EffectiveDate)
|
||||
}
|
||||
}
|
||||
|
||||
// TestCancelScheduledDefaultHoursChange cancels a pending change.
|
||||
func TestCancelScheduledDefaultHoursChange_Success(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, tx := resetTestData(t)
|
||||
|
||||
adminID, err := fixtures.CreateTestAdminUser(tx)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create admin user: %v", err)
|
||||
}
|
||||
defer fixtures.DeleteUser(tx, adminID)
|
||||
|
||||
futureDate := time.Now().AddDate(0, 0, 7).Format("2006-01-02")
|
||||
hoursJSON := `[{"weekday":0,"startTime":"10:00","endTime":"18:00","isOpen":true}]`
|
||||
_, err = tx.Exec(ctx, `
|
||||
INSERT INTO default_hours_scheduled_changes (effective_date, created_by, hours)
|
||||
VALUES ($1, $2, $3)
|
||||
`, futureDate, adminID, hoursJSON)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to insert scheduled change: %v", err)
|
||||
}
|
||||
|
||||
handler := http.HandlerFunc(CancelScheduledDefaultHoursChange)
|
||||
w := makeRequest(handler, "DELETE", "/api/admin/scheduling/default-hours/scheduled", nil, ctx)
|
||||
|
||||
if w.Code != http.StatusNoContent {
|
||||
t.Errorf("expected 204, got %d: %s", w.Code, w.Body.String())
|
||||
}
|
||||
|
||||
handler2 := http.HandlerFunc(GetScheduledDefaultHoursChange)
|
||||
w2 := makeRequest(handler2, "GET", "/api/admin/scheduling/default-hours/scheduled", nil, ctx)
|
||||
if w2.Code != http.StatusNotFound {
|
||||
t.Errorf("expected 404 after cancel, got %d", w2.Code)
|
||||
}
|
||||
}
|
||||
|
||||
// TestCancelScheduledDefaultHoursChange_NoChange returns 404 when nothing to cancel.
|
||||
func TestCancelScheduledDefaultHoursChange_NoChange(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, _ := resetTestData(t)
|
||||
|
||||
handler := http.HandlerFunc(CancelScheduledDefaultHoursChange)
|
||||
w := makeRequest(handler, "DELETE", "/api/admin/scheduling/default-hours/scheduled", nil, ctx)
|
||||
|
||||
if w.Code != http.StatusNotFound {
|
||||
t.Errorf("expected 404 when nothing to cancel, got %d: %s", w.Code, w.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
// TestScheduleDefaultHoursChange_TodayDate verifies scheduling with today's
|
||||
// date is rejected — changes can only start from tomorrow.
|
||||
func TestScheduleDefaultHoursChange_TodayDate(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, tx := resetTestData(t)
|
||||
|
||||
adminID, err := fixtures.CreateTestAdminUser(tx)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create admin user: %v", err)
|
||||
}
|
||||
defer fixtures.DeleteUser(tx, adminID)
|
||||
|
||||
today := clock.Now().In(clock.London).Format("2006-01-02")
|
||||
hours := make([]map[string]interface{}, 7)
|
||||
for i := 0; i < 7; i++ {
|
||||
hours[i] = map[string]interface{}{"weekday": i, "startTime": "10:00", "endTime": "18:00", "isOpen": true}
|
||||
}
|
||||
|
||||
payload := map[string]interface{}{"hours": hours, "effective_date": today}
|
||||
adminCtx := context.WithValue(ctx, mw.UserIDKey, adminID)
|
||||
handler := http.HandlerFunc(ScheduleDefaultHoursChange)
|
||||
w := makeRequest(handler, "POST", "/api/admin/scheduling/default-hours/schedule", payload, adminCtx)
|
||||
|
||||
if w.Code != http.StatusBadRequest {
|
||||
t.Errorf("expected 400 for today's date, got %d: %s", w.Code, w.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
// TestScheduleDefaultHoursChange_TomorrowDate verifies scheduling with
|
||||
// tomorrow's date succeeds — changes can start from tomorrow onwards.
|
||||
func TestScheduleDefaultHoursChange_TomorrowDate(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, tx := resetTestData(t)
|
||||
|
||||
adminID, err := fixtures.CreateTestAdminUser(tx)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create admin user: %v", err)
|
||||
}
|
||||
defer fixtures.DeleteUser(tx, adminID)
|
||||
|
||||
tomorrow := clock.Now().In(clock.London).AddDate(0, 0, 1).Format("2006-01-02")
|
||||
hours := make([]map[string]interface{}, 7)
|
||||
for i := 0; i < 7; i++ {
|
||||
hours[i] = map[string]interface{}{"weekday": i, "startTime": "10:00", "endTime": "18:00", "isOpen": true}
|
||||
}
|
||||
|
||||
payload := map[string]interface{}{"hours": hours, "effective_date": tomorrow}
|
||||
adminCtx := context.WithValue(ctx, mw.UserIDKey, adminID)
|
||||
handler := http.HandlerFunc(ScheduleDefaultHoursChange)
|
||||
w := makeRequest(handler, "POST", "/api/admin/scheduling/default-hours/schedule", payload, adminCtx)
|
||||
|
||||
if w.Code != http.StatusOK {
|
||||
t.Errorf("expected 200 for tomorrow's date, got %d: %s", w.Code, w.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetDefaultHoursConflictingBookings_NoConflicts verifies conflict
|
||||
// detection returns empty when no bookings overlap the proposed hours.
|
||||
func TestGetDefaultHoursConflictingBookings_NoConflicts(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, tx := resetTestData(t)
|
||||
|
||||
adminID, err := fixtures.CreateTestAdminUser(tx)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create admin user: %v", err)
|
||||
}
|
||||
defer fixtures.DeleteUser(tx, adminID)
|
||||
|
||||
tomorrow := clock.Now().In(clock.London).AddDate(0, 0, 1).Format("2006-01-02")
|
||||
proposedHours := make([]map[string]interface{}, 7)
|
||||
for i := 0; i < 7; i++ {
|
||||
proposedHours[i] = map[string]interface{}{"weekday": i, "startTime": "09:00", "endTime": "17:00", "isOpen": true}
|
||||
}
|
||||
|
||||
payload := map[string]interface{}{
|
||||
"proposedHours": proposedHours,
|
||||
"effective_date": tomorrow,
|
||||
}
|
||||
adminCtx := context.WithValue(ctx, mw.UserIDKey, adminID)
|
||||
handler := http.HandlerFunc(GetDefaultHoursConflictingBookings)
|
||||
w := makeRequest(handler, "POST", "/api/admin/scheduling/default-hours/conflicting", payload, adminCtx)
|
||||
|
||||
if w.Code != http.StatusOK {
|
||||
t.Fatalf("expected 200, got %d: %s", w.Code, w.Body.String())
|
||||
}
|
||||
|
||||
var resp OverlappingBookingsResponse
|
||||
if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil {
|
||||
t.Fatalf("failed to unmarshal: %v", err)
|
||||
}
|
||||
if len(resp.Bookings) != 0 {
|
||||
t.Errorf("expected 0 conflicting bookings (no bookings exist), got %d", len(resp.Bookings))
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetDefaultHoursConflictingBookings_WithConflicts verifies conflict
|
||||
// detection finds bookings that fall outside the proposed hours window.
|
||||
func TestGetDefaultHoursConflictingBookings_WithConflicts(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, tx := resetTestData(t)
|
||||
|
||||
adminID, err := fixtures.CreateTestAdminUser(tx)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create admin user: %v", err)
|
||||
}
|
||||
defer fixtures.DeleteUser(tx, adminID)
|
||||
|
||||
userID, err := fixtures.CreateTestUser(tx)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create user: %v", err)
|
||||
}
|
||||
defer fixtures.DeleteUser(tx, userID)
|
||||
|
||||
// Place a booking at 08:00-09:00 tomorrow (London time). Proposed hours
|
||||
// are 09:00-17:00 -> this booking should be a conflict (starts before 09:00).
|
||||
tomorrowLondon := clock.Now().In(clock.London).AddDate(0, 0, 1)
|
||||
bookingTime := time.Date(tomorrowLondon.Year(), tomorrowLondon.Month(), tomorrowLondon.Day(), 8, 0, 0, 0, clock.London).UTC()
|
||||
_, err = tx.Exec(ctx, `
|
||||
INSERT INTO bookings (user_id, start_time, status, total_duration_minutes, end_time)
|
||||
VALUES ($1, $2, 'confirmed', 60, $3)
|
||||
`, userID, bookingTime, bookingTime.Add(60*time.Minute))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create booking: %v", err)
|
||||
}
|
||||
|
||||
tomorrow := tomorrowLondon.Format("2006-01-02")
|
||||
proposedHours := make([]map[string]interface{}, 7)
|
||||
for i := 0; i < 7; i++ {
|
||||
proposedHours[i] = map[string]interface{}{"weekday": i, "startTime": "09:00", "endTime": "17:00", "isOpen": true}
|
||||
}
|
||||
|
||||
payload := map[string]interface{}{
|
||||
"proposedHours": proposedHours,
|
||||
"effective_date": tomorrow,
|
||||
}
|
||||
adminCtx := context.WithValue(ctx, mw.UserIDKey, adminID)
|
||||
handler := http.HandlerFunc(GetDefaultHoursConflictingBookings)
|
||||
w := makeRequest(handler, "POST", "/api/admin/scheduling/default-hours/conflicting", payload, adminCtx)
|
||||
|
||||
if w.Code != http.StatusOK {
|
||||
t.Fatalf("expected 200, got %d: %s", w.Code, w.Body.String())
|
||||
}
|
||||
|
||||
var resp OverlappingBookingsResponse
|
||||
if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil {
|
||||
t.Fatalf("failed to unmarshal: %v", err)
|
||||
}
|
||||
if len(resp.Bookings) != 1 {
|
||||
t.Errorf("expected 1 conflicting booking, got %d", len(resp.Bookings))
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetWorkingHours_WithStagedChange verifies that GetWorkingHours returns
|
||||
// the staged hours for dates on/after the effective date.
|
||||
func TestGetWorkingHours_WithStagedChange(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, tx := resetTestData(t)
|
||||
|
||||
adminID, err := fixtures.CreateTestAdminUser(tx)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create admin user: %v", err)
|
||||
}
|
||||
defer fixtures.DeleteUser(tx, adminID)
|
||||
|
||||
londonNow := clock.Now().In(clock.London)
|
||||
today := londonNow.Format("2006-01-02")
|
||||
tomorrow := londonNow.AddDate(0, 0, 1).Format("2006-01-02")
|
||||
endDay := londonNow.AddDate(0, 0, 6).Format("2006-01-02")
|
||||
|
||||
// Staged change sets all weekdays to 10:00-18:00 open
|
||||
hoursJSON := `[{"weekday":0,"startTime":"10:00","endTime":"18:00","isOpen":true},{"weekday":1,"startTime":"10:00","endTime":"18:00","isOpen":true},{"weekday":2,"startTime":"10:00","endTime":"18:00","isOpen":true},{"weekday":3,"startTime":"10:00","endTime":"18:00","isOpen":true},{"weekday":4,"startTime":"10:00","endTime":"18:00","isOpen":true},{"weekday":5,"startTime":"10:00","endTime":"18:00","isOpen":true},{"weekday":6,"startTime":"10:00","endTime":"18:00","isOpen":true}]`
|
||||
_, err = tx.Exec(ctx, `
|
||||
INSERT INTO default_hours_scheduled_changes (effective_date, created_by, hours)
|
||||
VALUES ($1, $2, $3)
|
||||
`, tomorrow, adminID, hoursJSON)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to insert staged change: %v", err)
|
||||
}
|
||||
|
||||
handler := http.HandlerFunc(GetWorkingHours)
|
||||
// Query today through today+6 — spans before and after the staged effective_date
|
||||
w := makeRequest(handler, "GET", "/api/scheduling/working-hours?start="+today+"&end="+endDay, nil, ctx)
|
||||
|
||||
if w.Code != http.StatusOK {
|
||||
t.Fatalf("expected 200, got %d: %s", w.Code, w.Body.String())
|
||||
}
|
||||
|
||||
var response []DayWorkingHours
|
||||
if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil {
|
||||
t.Fatalf("failed to unmarshal: %v", err)
|
||||
}
|
||||
|
||||
if len(response) != 7 {
|
||||
t.Fatalf("expected 7 days, got %d", len(response))
|
||||
}
|
||||
|
||||
// Days on/after the effective date (tomorrow) must use staged hours (10:00-18:00).
|
||||
// Days before must use current working_hours (which vary by weekday).
|
||||
stagedCount, currentCount := 0, 0
|
||||
for _, day := range response {
|
||||
if day.Date >= tomorrow {
|
||||
stagedCount++
|
||||
if day.StartTime != "10:00" || day.EndTime != "18:00" {
|
||||
t.Errorf("date %s should show staged hours (10:00-18:00), got %s-%s (isOpen=%v)",
|
||||
day.Date, day.StartTime, day.EndTime, day.IsOpen)
|
||||
}
|
||||
} else {
|
||||
currentCount++
|
||||
}
|
||||
}
|
||||
if stagedCount == 0 {
|
||||
t.Error("expected at least one day with staged hours")
|
||||
}
|
||||
if currentCount == 0 {
|
||||
t.Error("expected at least one day with current hours")
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetDefaultHours_WithScheduledChange verifies GetDefaultHours includes
|
||||
// the scheduled_change field when a pending change exists.
|
||||
func TestGetDefaultHours_WithScheduledChange(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, tx := resetTestData(t)
|
||||
|
||||
adminID, err := fixtures.CreateTestAdminUser(tx)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create admin user: %v", err)
|
||||
}
|
||||
defer fixtures.DeleteUser(tx, adminID)
|
||||
|
||||
tomorrow := clock.Now().In(clock.London).AddDate(0, 0, 1).Format("2006-01-02")
|
||||
hoursJSON := `[{"weekday":0,"startTime":"10:00","endTime":"18:00","isOpen":true}]`
|
||||
_, err = tx.Exec(ctx, `
|
||||
INSERT INTO default_hours_scheduled_changes (effective_date, created_by, hours)
|
||||
VALUES ($1, $2, $3)
|
||||
`, tomorrow, adminID, hoursJSON)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to insert staged change: %v", err)
|
||||
}
|
||||
|
||||
handler := http.HandlerFunc(GetDefaultHours)
|
||||
w := makeRequest(handler, "GET", "/api/scheduling/default-hours", nil, ctx)
|
||||
|
||||
if w.Code != http.StatusOK {
|
||||
t.Fatalf("expected 200, got %d: %s", w.Code, w.Body.String())
|
||||
}
|
||||
|
||||
var resp ScheduledHoursChangeResponse
|
||||
if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil {
|
||||
t.Fatalf("failed to unmarshal: %v", err)
|
||||
}
|
||||
if resp.ScheduledChange == nil {
|
||||
t.Fatal("expected scheduled_change to be non-nil")
|
||||
}
|
||||
if resp.ScheduledChange.EffectiveDate != tomorrow {
|
||||
t.Errorf("expected effective_date %s, got %s", tomorrow, resp.ScheduledChange.EffectiveDate)
|
||||
}
|
||||
if len(resp.Current) != 7 {
|
||||
t.Errorf("expected 7 current hours, got %d", len(resp.Current))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user