package controllers import ( "testing" "doormile/models" ) // One customer pickup is ONE booking carrying N destinations. The admin list // says how many without shipping the array, and these cover the mapping that // does it — the only half of the change that can be tested without Postgres. // The queries themselves need the integration pass (docs/customer-app-api.md). func TestDestinationCountsLandOnTheRightBooking(t *testing.T) { bookings := []models.PickupBooking{ {Bookingid: 11}, {Bookingid: 22}, {Bookingid: 33}, } // Deliberately out of order and not covering every booking: the grouped // query returns rows for whichever bookings have destinations, in whatever // order the database chose. counts := []bookingDestinationCounts{ {Bookingid: 33, Destinationcount: 1, Totalpackagecount: 1}, {Bookingid: 11, Destinationcount: 3, Totalpackagecount: 4}, } applyDestinationCounts(bookings, counts) if bookings[0].Destinationcount != 3 || bookings[0].Totalpackagecount != 4 { t.Errorf("booking 11: got %d destinations / %d packages, want 3/4", bookings[0].Destinationcount, bookings[0].Totalpackagecount) } if bookings[2].Destinationcount != 1 || bookings[2].Totalpackagecount != 1 { t.Errorf("booking 33: got %d destinations / %d packages, want 1/1", bookings[2].Destinationcount, bookings[2].Totalpackagecount) } } // A console-created booking has no bookingdestinations rows at all, so the // grouped query returns nothing for it. It must report 0/0 rather than // inheriting a neighbour's counts — the console reads 0 as "no destinations // recorded" and 1 as "a single drop", and they render differently. func TestBookingWithNoDestinationsStaysZero(t *testing.T) { bookings := []models.PickupBooking{ {Bookingid: 11}, {Bookingid: 99}, // console-created: no destination rows } counts := []bookingDestinationCounts{ {Bookingid: 11, Destinationcount: 3, Totalpackagecount: 4}, } applyDestinationCounts(bookings, counts) if bookings[1].Destinationcount != 0 || bookings[1].Totalpackagecount != 0 { t.Errorf("console booking: got %d/%d, want 0/0", bookings[1].Destinationcount, bookings[1].Totalpackagecount) } } // The aggregate is keyed by booking id, so a count can never be written onto a // booking that was not on this page. Guards the map lookup against being // replaced by anything positional. func TestCountsForBookingsOutsideThePageAreIgnored(t *testing.T) { bookings := []models.PickupBooking{{Bookingid: 11}} counts := []bookingDestinationCounts{ {Bookingid: 77, Destinationcount: 9, Totalpackagecount: 9}, } applyDestinationCounts(bookings, counts) if bookings[0].Destinationcount != 0 || bookings[0].Totalpackagecount != 0 { t.Errorf("booking 11 picked up booking 77's counts: got %d/%d, want 0/0", bookings[0].Destinationcount, bookings[0].Totalpackagecount) } } // Empty inputs are the ordinary case on an empty page, not an error. func TestApplyDestinationCountsHandlesEmptyInputs(t *testing.T) { applyDestinationCounts(nil, nil) applyDestinationCounts([]models.PickupBooking{}, []bookingDestinationCounts{{Bookingid: 1}}) bookings := []models.PickupBooking{{Bookingid: 11, Destinationcount: 0}} applyDestinationCounts(bookings, nil) if bookings[0].Destinationcount != 0 { t.Errorf("no counts should leave the booking at 0, got %d", bookings[0].Destinationcount) } } // A single-destination customer booking must report 1, not 0. The console // branches on destinationcount > 1 to decide whether to show the summary line, // and 1 is what keeps a B2C row reading as it does today. func TestSingleDestinationBookingReportsOne(t *testing.T) { bookings := []models.PickupBooking{{Bookingid: 11}} counts := []bookingDestinationCounts{{Bookingid: 11, Destinationcount: 1, Totalpackagecount: 2}} applyDestinationCounts(bookings, counts) if bookings[0].Destinationcount != 1 || bookings[0].Totalpackagecount != 2 { t.Errorf("got %d/%d, want 1/2", bookings[0].Destinationcount, bookings[0].Totalpackagecount) } }