shifts
This commit is contained in:
126
repositories/riderShift_test.go
Normal file
126
repositories/riderShift_test.go
Normal file
@@ -0,0 +1,126 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"nearle/models"
|
||||
)
|
||||
|
||||
/*
|
||||
Shift windows, which riders cannot be hired without.
|
||||
|
||||
`CreateRider` refuses a rider with no shift — correctly, because `getriders`
|
||||
joins `ridershifts` and a rider on a shift that does not exist is a rider nobody
|
||||
can see. But the table could only be READ: no endpoint, no service method, and
|
||||
no `applocationid` field on the model to write one with. A region that shipped
|
||||
without shift rows was a region no rider could ever be added to, and the console
|
||||
said "No shifts set up for this region" with nothing anybody could do about it.
|
||||
|
||||
These cover the rules that do not need a database. The two that do — the region
|
||||
must be configured, and the window must not already exist — are enforced in
|
||||
CreateRiderShift against real tables.
|
||||
*/
|
||||
|
||||
func TestATimeIsNormalisedSoOneWindowHasOneLabel(t *testing.T) {
|
||||
// The dropdown labels a shift by concatenating its two columns raw, so
|
||||
// `9:00-17:00` and `09:00-17:00` are two different labels for one window.
|
||||
// Rows inserted by hand over the years use every spelling.
|
||||
for _, tc := range []struct{ in, want string }{
|
||||
{"9:00", "09:00"},
|
||||
{"09:00", "09:00"},
|
||||
{"09:00:00", "09:00"},
|
||||
{" 9:5 ", "09:05"},
|
||||
{"23:59", "23:59"},
|
||||
{"0:00", "00:00"},
|
||||
} {
|
||||
got, err := riderShiftClock(tc.in)
|
||||
if err != nil {
|
||||
t.Fatalf("%q: %v", tc.in, err)
|
||||
}
|
||||
if got != tc.want {
|
||||
t.Fatalf("%q became %q, want %q", tc.in, got, tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSomethingThatIsNotATimeIsRefused(t *testing.T) {
|
||||
for _, bad := range []string{"", " ", "morning", "25:00", "09:60", "9", "9:00:00:00", "-1:00"} {
|
||||
if _, err := riderShiftClock(bad); err == nil {
|
||||
t.Fatalf("%q was accepted as a time", bad)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHoursAreWorkedOutRatherThanAskedFor(t *testing.T) {
|
||||
// `shifthours` feeds rider pay. It is the one field a person gets wrong and
|
||||
// nothing downstream checks, so it is computed and the request's own number
|
||||
// is discarded.
|
||||
shift, err := validateRiderShift(models.Ridershifts{
|
||||
Applocationid: 2, Starttime: "09:00", Endtime: "17:00",
|
||||
Shifthours: 4, // wrong, and sent anyway
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("a good shift was refused: %v", err)
|
||||
}
|
||||
if shift.Shifthours != 8 {
|
||||
t.Fatalf("09:00-17:00 came out as %v hours, want 8", shift.Shifthours)
|
||||
}
|
||||
}
|
||||
|
||||
func TestANightShiftCrossesMidnightRatherThanGoingNegative(t *testing.T) {
|
||||
// 22:00-06:00 is eight hours. Subtracting the clocks gives minus sixteen,
|
||||
// which would pay a night rider for a negative shift.
|
||||
if got := riderShiftHours("22:00", "06:00"); got != 8 {
|
||||
t.Fatalf("22:00-06:00 came out as %v hours, want 8", got)
|
||||
}
|
||||
if got := riderShiftHours("09:30", "17:00"); got != 7.5 {
|
||||
t.Fatalf("09:30-17:00 came out as %v hours, want 7.5", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAShiftNeedsARegion(t *testing.T) {
|
||||
// Region 0 arrives from a form field nobody filled in. A shift there would
|
||||
// be offered to nobody and joined to nothing.
|
||||
_, err := validateRiderShift(models.Ridershifts{Starttime: "09:00", Endtime: "17:00"})
|
||||
if err == nil || !strings.Contains(err.Error(), "region") {
|
||||
t.Fatalf("a shift with no region was accepted: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAShiftCannotStartAndEndAtTheSameTime(t *testing.T) {
|
||||
// Would compute as a 24-hour window under the midnight rule, which is not
|
||||
// what anybody who typed the same time twice meant.
|
||||
_, err := validateRiderShift(models.Ridershifts{
|
||||
Applocationid: 2, Starttime: "09:00", Endtime: "9:00",
|
||||
})
|
||||
if err == nil {
|
||||
t.Fatal("a zero-length window was accepted")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPayCannotBeNegative(t *testing.T) {
|
||||
for _, shift := range []models.Ridershifts{
|
||||
{Applocationid: 2, Starttime: "09:00", Endtime: "17:00", Basefare: -1},
|
||||
{Applocationid: 2, Starttime: "09:00", Endtime: "17:00", Additionalcharges: -5},
|
||||
{Applocationid: 2, Starttime: "09:00", Endtime: "17:00", Fuelcharge: -0.5},
|
||||
} {
|
||||
if _, err := validateRiderShift(shift); err == nil {
|
||||
t.Fatalf("negative pay was accepted: %+v", shift)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTheNormalisedTimesComeBackOnTheShift(t *testing.T) {
|
||||
// The caller inserts what validation returned, not what it was handed —
|
||||
// otherwise the normalising is computed and then thrown away.
|
||||
shift, err := validateRiderShift(models.Ridershifts{
|
||||
Applocationid: 2, Starttime: "9:0", Endtime: "17:00:00",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("refused: %v", err)
|
||||
}
|
||||
if shift.Starttime != "09:00" || shift.Endtime != "17:00" {
|
||||
t.Fatalf("times were not normalised on the way out: %q-%q", shift.Starttime, shift.Endtime)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user