Regression test cases — Children and rooming¶
Audience: QA. Scope: camp-level child admission, the per-room age floor, room occupancy counting and its three-bucket adult/child arithmetic, the children-alone-in-a-room path, the two overrides, and the partner API's child-age validation.
Every case cites the microflow and node it derives from, so expected results can be re-derived
rather than trusted. Mechanism detail:
docs/deep-dives/children-and-rooming.md.
Priority: P1 blocks release, P2 must pass before sign-off, P3 when time allows.
None of these cases have been executed. They state what the system currently does, derived from its decision logic. A pass means unchanged, not correct.
Several cases assert defective or surprising behaviour — A6, B1, C4, D3, F3 and G2. Each is written as the system behaves today and cross-referenced to the deep dive, so a fix shows up as a deliberate change rather than a broken test.
What to assert on¶
| Thing | Where it lives |
|---|---|
| admission verdict | availability status No_Children, caption "Age restrictions apply" |
| room counts | Booking.RequiredRoom.Adults, .Children, .Staff and their *Enum twins |
| guest links | Booking.RequiredRoom_Guest |
| capacity source | Availability.RoomTypes.NormalAdults, .NormalChildren, .GuestNormal, .GuestMax |
| age bands | BookingMasterData.Policy.InfantAgeFrom/To, ChildAgeFrom/To, AdultAgeFrom/To, reached by BookingMasterData.Option_Policy |
| overrides | Booking.AvailableRoomConfig.ChildPolicyOverride, Booking.BookingLine.OverrideChildPolicy |
| audit | Booking.LogEvent entries, object type Booking.Object_Type.Room_allocation |
Two fixture notes that decide most of these cases: a guest is a child by
Administration.Guest.IsChild and has an Age, and the policy record reached from the option
may be blank, which is a distinct case from zero-aged guests.
A. Camp admission¶
| ID | Case | Preconditions | Steps | Expected | Pri | Source |
|---|---|---|---|---|---|---|
| A1 | No children camp refuses a 10-year-old | Supplier.ChildPolicy = NoChildren, guest aged 10 flagged IsChild |
Select the camp | Availability status No_Children, caption "Age restrictions apply" |
P1 | UpdateAvailabilityStatusForAccom_X [29], API.CheckPveRequired [19] |
| A2 | The boundary is 16 inclusive | Same camp, guest aged 16 | Select | Refused — Get_ChildrenByAgeLimit(16, 0, …) counts Age <= 16 |
P1 | Get_ChildrenByAgeLimit [4] |
| A3 | 17 is not a child for admission | Same camp, guest aged 17 | Select | Not refused on the child rule | P1 | Get_ChildrenByAgeLimit [4] |
| A4 | Teens-allowed camp tests the 6-12 band | ChildPolicy = Teens_allowed, guest aged 8 |
Select | The 6-12 branch fires | P1 | UpdateAvailabilityStatusForAccom_X [32],[33] |
| A5 | Infant-friendly camp counts under 6 | ChildPolicy = InfantFriendly, guest aged 3 |
Select | The under-6 count is taken | P2 | …Accom_X [27],[30] |
| A6 | Sole use bypasses admission (trap C7) | ChildPolicy = NoChildren, AvailableRoomConfig.SoleUse = true, guest aged 4 |
Select | No refusal — the whole check is skipped | P1 | …Accom_X [25] |
| A7 | No child in the party, no check | Party of adults only | Select a NoChildren camp |
No refusal, no child branch entered | P2 | …Accom_X [24],[25] |
| A8 | The API ladder agrees with the UI (trap C10) | Same fixture as A1 through API.CreateWindowBooking |
Create | Same refusal, same status | P1 | API.CheckPveRequired [6-13] |
| A9 | Configured age bands do not move admission (trap C3) | Policy.ChildAgeTo = 12 on the option, ChildPolicy = NoChildren, guest aged 15 |
Select | Still refused — admission ignores the configured bands | P2 | …Accom_X [28] |
B. Counting the room: three buckets¶
Fixture: one required room, NormalAdults = 2, NormalChildren = 2, GuestNormal = 4,
GuestMax = 5, reached through the room-selection screen ($KeepRooming = false).
| ID | Case | Preconditions | Expected | Pri | Source |
|---|---|---|---|---|---|
| B1 | Blank policy makes every child an adult (defect C1) | Policy record with AdultAgeFrom = 0; 2 adults + 1 child aged 4 |
The child lands in children_asAdults, so 3 count against NormalAdults = 2 → "Too many adults in the room." |
P1 | RoomingChecks [17],[18],[70] |
| B2 | A configured adult age keeps a young child a child | AdultAgeFrom = 12; 2 adults + 1 child aged 4 |
Child counts in children, adults stay at 2, no adult warning |
P1 | RoomingChecks [19] |
| B3 | A child at the adult age is recounted | AdultAgeFrom = 12; 1 adult + 1 child aged 12 |
children_asAdults = 1; the message names it: "Please be aware 1 of the children in this room are considered adults at this supplier" |
P1 | RoomingChecks [17],[70] |
| B4 | Guest count must match the typed rooming | 3 guests linked, rooming typed as 2 adults | "You have not roomed your guests correctly, there are 3 guests allocated to the room but you have indicated rooming for 2 guests", returns false, nothing else checked | P1 | RoomingChecks [13],[92],[93] |
| B5 | Over normal children, within max guests | AdultAgeFrom = 12, 1 adult + 3 children aged 5 |
"Exceeded normal children." | P1 | RoomingChecks [26],[67] |
| B6 | Over normal children and over max guests | 2 adults + 4 children aged 5 | "Exceeded normal children and max guests." | P1 | RoomingChecks [62],[63] |
| B7 | No room type attached | RequiredRoom with no room type |
Logs "There is no room type attached to the required room" at severity Error, returns false | P2 | RoomingChecks [4],[94],[95] |
| B8 | Botswana and ABU001 have their own branches | Fixture in Botswana; then at supplier ABU001 |
Both take a distinct path through the guest-count ladder | P3 | RoomingChecks [38],[50] |
C. What failure does to the room¶
| ID | Case | Preconditions | Expected | Pri | Source |
|---|---|---|---|---|---|
| C1 | Step 2 empties the room, not just refuses (trap C11) | B1's fixture, MaxPaxAllowed = false, via Booking.CheckRoomSelection |
Adults = 0, AdultsEnum empty, guest links cleared |
P1 | RoomingChecks [73], caller [41] |
| C2 | Over max guests clears everything | B6's fixture, MaxPaxAllowed = false |
Adults, children, staff and all three enums cleared, guests unlinked | P1 | RoomingChecks [66],[78] |
| C3 | Max pax allowed downgrades to a warning | Same, MaxPaxAllowed = true |
Counts survive; a Warning log entry exists |
P1 | RoomingChecks [69],[70] |
| C4 | Quote time keeps the rooming (by design) | Same fixture via Booking.CheckRooming ($KeepRooming = true) |
Warnings only, nothing cleared | P1 | CheckRooming [10] |
| C5 | The quote sweep covers every room | Booking with three BookThis configurations |
RoomingChecks runs per required room, policy resolved per option |
P2 | CheckRooming [3-10] |
D. A child alone in a room¶
| ID | Case | Preconditions | Expected | Pri | Source |
|---|---|---|---|---|---|
| D1 | Non-Wish camp warns only | Room with one child aged 8, no adults, BookingMethod ≠ Wish |
"Please be aware, that on the ground, children may not be allowed in a room on their own."; room unchanged | P1 | RoomingChecks [81],[82] |
| D2 | Wish camp allowing triples assumes space | Same, BookingMethod = Wish, Option.AllowTriples = true |
"…we assume there is space in another room for this child (not already using max pax)."; room unchanged | P1 | RoomingChecks [84],[89] |
| D3 | Wish camp without triples removes the children (trap C4) | Same, AllowTriples = false, $Quote and $KeepRooming both false |
"…we cannot assume this child will be allowed in another room as this supplier does not allow triples.", then Children = 0, ChildrenEnum = no_children, guests unlinked |
P1 | RoomingChecks [85],[88] |
| D4 | Every case is audited | Each of D1-D3 | A Booking.LogEvent entry exists with object type Room_allocation |
P2 | RoomingChecks [83],[90] |
| D5 | A child counted as an adult is not "alone" | Room with one child aged 14, AdultAgeFrom = 12 |
The alone path is not entered — adults + children_asAdults > 0 |
P1 | RoomingChecks [22] |
E. The age floor per room¶
| ID | Case | Preconditions | Expected | Pri | Source |
|---|---|---|---|---|---|
| E1 | Below the child age is refused | ChildAgeFrom = 6, AdultAgeFrom = 12, ChildAgeTo and InfantAgeTo set; youngest child aged 4 |
"You have a child that is younger than the allowed age policy for this room. You may not be allowed to book this room, unless you get special permission…", returns false, and RoomingChecks logs "Child below age limit and no permission." at severity Error |
P1 | CheckYoungestChild [10],[12],[13]; RoomingChecks [91] |
| E2 | At the child age is allowed | Same, youngest aged 6 | Returns true | P1 | CheckYoungestChild [10],[11] |
| E3 | Blank adult age disables the rule (defect C2) | AdultAgeFrom = 0, child aged 1 |
Returns true — no message | P1 | CheckYoungestChild [5] |
| E4 | Blank infant age disables the rule | AdultAgeFrom = 12, InfantAgeTo = 0, child aged 1 |
Returns true | P1 | CheckYoungestChild [8],[9] |
| E5 | Override skips the floor | E1's fixture plus ChildPolicyOverride = true |
Returns true, no message | P1 | CheckYoungestChild [6] |
| E6 | Sole use skips the floor | E1's fixture plus SoleUse = true |
Returns true | P2 | CheckYoungestChild [6] |
| E7 | No children, no check | Adults only | ValidateChildrenAllowed returns true immediately |
P2 | ValidateChildrenAllowed [3],[4] |
| E8 | The youngest child decides | Children aged 4 and 15, floor at 6 | Refused on the 4-year-old — the list is sorted ascending and only the head is tested | P1 | CheckYoungestChild [2],[3] |
F. Overrides¶
| ID | Case | Steps | Expected | Pri | Source |
|---|---|---|---|---|---|
| F1 | Room-configuration override toggles | Press the override button twice | ChildPolicyOverride true, then false — the same button withdraws it |
P1 | IVK_OverrideChildPolicy_Ac [2] |
| F2 | Both are logged with the wording of the action | As F1 | Booking events "Child policy overridden" and "Child policy override removed" | P2 | IVK_OverrideChildPolicy_Ac [4] |
| F3 | Booking-line override is one-way (trap C8) | Set the line-level override, then try to withdraw it | BookingLine.OverrideChildPolicy stays true; no live flow writes false |
P1 | IVK_OverrideChildPolicy_BL [2] |
| F4 | An override survives a booking copy | Override, then copy the booking to a draft | The copy's AvailableRoomConfig.ChildPolicyOverride is true |
P2 | Sub_CopyBookingToDraft [152] |
| F5 | No role check in the logic | Override as a non-manager, if the page allows it | The microflow does not refuse; record what page security does | P1 | IVK_OverrideChildPolicy_Ac, _BL |
G. Partner API¶
| ID | Case | Preconditions | Expected | Pri | Source |
|---|---|---|---|---|---|
| G1 | Missing age is rejected | ChildPax = 2, ChildAge1 = 8, ChildAge2 empty |
ValidateChildAges returns false; the booking is not created |
P1 | API.ValidateChildAges [11],[20],[21] |
| G2 | Six children silently lose the sixth (defect C6) | ChildPax = 6, ages 1-5 supplied |
Accepted; no validation of a sixth age and only five API.Child objects created |
P1 | API.ValidateChildAges [22-24], API.CreateChildrenGuests [7-20] |
| G3 | Zero age is not a valid age | ChildPax = 1, ChildAge1 = 0 |
Rejected | P1 | API.ValidateChildAges [9] |
| G4 | Rooms without children skip the check | ChildPax = 0 |
Loop continues, $ChildAgesValid unchanged |
P2 | API.ValidateChildAges [5],[6] |
| G5 | One child object per supplied age | ChildPax = 3, ages 4, 7, 11 |
Three API.Child records with those ages |
P2 | API.CreateChildrenGuests [7-14] |
| G6 | The API rooming path still runs the UI checks | Booking with children via API.SetAccommodationToBooked |
Booking.CheckRoomSelection and therefore RoomingChecks run |
P1 | call_graph, dst = Booking.CheckRoomSelection |
H. Not covered here¶
The templated-trip and availability-search variants of these flows, rooming lists (the guest-name
document sent to camps), Tourplan rooming lines, rate-sheet child OPD generation, and the charging
behaviour behind Option.P_* — all listed with reasons in
deep dive §12. Note
in particular that P_ChildMustShareWithAdults is a pricing flag: there is no occupancy test
for it to fail, so it has no case here.