117 lines
4.1 KiB
Go
117 lines
4.1 KiB
Go
package constants
|
|
|
|
import "testing"
|
|
|
|
// The nine stage keys are a wire contract. The customer client parses them
|
|
// verbatim and silently falls back to `booked` on anything it does not
|
|
// recognise — so a renamed or misspelt key here does not fail loudly, it makes
|
|
// a moving parcel look un-started on someone's tracking screen.
|
|
|
|
func TestStageKeysAreSpeltExactlyAsTheClientParsesThem(t *testing.T) {
|
|
want := map[string]string{
|
|
CxStageBooked: "booked",
|
|
CxStageAssigned: "assigned",
|
|
CxStageOnTheWay: "on_the_way",
|
|
CxStageArrived: "arrived",
|
|
CxStagePickedUp: "picked_up",
|
|
CxStageOrderCreated: "order_created",
|
|
CxStageInTransit: "in_transit",
|
|
CxStageOutForDelivery: "out_for_delivery",
|
|
CxStageDelivered: "delivered",
|
|
}
|
|
for got, expected := range want {
|
|
if got != expected {
|
|
t.Errorf("stage key = %q, want %q", got, expected)
|
|
}
|
|
}
|
|
if len(CxStageOrder) != 9 {
|
|
t.Errorf("CxStageOrder has %d entries, want 9 — every stage the client "+
|
|
"knows must be rankable", len(CxStageOrder))
|
|
}
|
|
}
|
|
|
|
// Ranks must be strictly increasing in journey order. advanceBooking refuses to
|
|
// move a booking backwards by comparing these, so a tie or an inversion would
|
|
// let a stage silently fail to apply.
|
|
func TestStageRanksIncreaseInJourneyOrder(t *testing.T) {
|
|
ordered := []string{
|
|
CxStageBooked, CxStageAssigned, CxStageOnTheWay, CxStageArrived,
|
|
CxStagePickedUp, CxStageOrderCreated, CxStageInTransit,
|
|
CxStageOutForDelivery, CxStageDelivered,
|
|
}
|
|
for i := 1; i < len(ordered); i++ {
|
|
if CxStageRank(ordered[i]) <= CxStageRank(ordered[i-1]) {
|
|
t.Errorf("%q ranks %d, not after %q at %d",
|
|
ordered[i], CxStageRank(ordered[i]), ordered[i-1], CxStageRank(ordered[i-1]))
|
|
}
|
|
}
|
|
}
|
|
|
|
// An unknown or empty stage must rank BEHIND booked, not tie with it. A booking
|
|
// written before this surface existed has no stage at all, and a tie would stop
|
|
// it ever advancing off nothing.
|
|
func TestUnknownStageRanksBehindEverything(t *testing.T) {
|
|
if CxStageRank("") != -1 {
|
|
t.Errorf("empty stage ranks %d, want -1", CxStageRank(""))
|
|
}
|
|
if CxStageRank("teleported") != -1 {
|
|
t.Errorf("unknown stage ranks %d, want -1", CxStageRank("teleported"))
|
|
}
|
|
if CxStageRank("") >= CxStageRank(CxStageBooked) {
|
|
t.Error("an unknown stage does not rank behind booked")
|
|
}
|
|
}
|
|
|
|
// Cancellation closes after `arrived` — the contract's rule, and money depends
|
|
// on it: cancelling after pickup would mean a parcel already collected and paid
|
|
// for is marked cancelled.
|
|
func TestCancellationWindowClosesAfterArrived(t *testing.T) {
|
|
open := []string{"", CxStageBooked, CxStageAssigned, CxStageOnTheWay, CxStageArrived}
|
|
for _, stage := range open {
|
|
if !CxCancellable(stage) {
|
|
t.Errorf("stage %q should still be cancellable", stage)
|
|
}
|
|
}
|
|
|
|
closed := []string{
|
|
CxStagePickedUp, CxStageOrderCreated, CxStageInTransit,
|
|
CxStageOutForDelivery, CxStageDelivered,
|
|
}
|
|
for _, stage := range closed {
|
|
if CxCancellable(stage) {
|
|
t.Errorf("stage %q must not be cancellable — the parcel is collected", stage)
|
|
}
|
|
}
|
|
}
|
|
|
|
// The customer statuses and actor types are also on the wire.
|
|
func TestCustomerStatusAndActorValues(t *testing.T) {
|
|
pairs := map[string]string{
|
|
CxStatusActive: "active",
|
|
CxStatusCompleted: "completed",
|
|
CxStatusCancelled: "cancelled",
|
|
CxActorMiler: "miler",
|
|
CxActorOps: "ops",
|
|
CxActorCustomer: "customer",
|
|
CxActorSystem: "system",
|
|
}
|
|
for got, want := range pairs {
|
|
if got != want {
|
|
t.Errorf("constant = %q, want %q", got, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Booking source decides whether a booking gets a customer projection at all —
|
|
// cxstage returns early for anything that is not Customer_App. The stored value
|
|
// predates this work and must not be "fixed".
|
|
func TestBookingSourceValuesAreTheStoredOnes(t *testing.T) {
|
|
if BookingSourceCustomerApp != "Customer_App" {
|
|
t.Errorf("BookingSourceCustomerApp = %q, want %q", BookingSourceCustomerApp, "Customer_App")
|
|
}
|
|
if BookingSourceExpress != "CRM_Console" {
|
|
t.Errorf("BookingSourceExpress = %q — this is an existing database value, "+
|
|
"not a label to rename", BookingSourceExpress)
|
|
}
|
|
}
|