package api import ( "testing" "time" ) func ptr(b bool) *bool { return &b } // The state this was written for. Two cameras read "Connected", in green, on // the live estate thirty-four minutes after the shop computer had stopped // being able to see either of them - because the agent correctly reports // nothing when it cannot reach the engine, and the last value it sent stays // in the database looking current. func TestAStaleReportIsNotAConnectedCamera(t *testing.T) { now := time.Date(2026, 9, 30, 11, 13, 0, 0, time.UTC) c := Camera{Connected: ptr(true), LastSeenAt: now.Add(-34 * time.Minute).Format(time.RFC3339)} c.CameraState(now) if c.State != CameraStale { t.Errorf("state = %q, want %q", c.State, CameraStale) } // Cleared, not merely overruled. A stale true left in place stays // available to every client that reads the field directly, and leaves two // fields on one object disagreeing. if c.Connected != nil { t.Errorf("connected = %v, want null - nobody currently knows", *c.Connected) } if c.StateNote == "" { t.Error("a stale camera said nothing about what to do") } } // One missed report is a dropped packet. Warning on it would put an alarm on a // healthy estate every few minutes, and an indicator that cries wolf is one // people learn to ignore. func TestOneMissedReportIsStillConnected(t *testing.T) { now := time.Now() c := Camera{Connected: ptr(true), LastSeenAt: now.Add(-90 * time.Second).Format(time.RFC3339)} c.CameraState(now) if c.State != CameraConnected { t.Errorf("state = %q after 90s, want %q", c.State, CameraConnected) } if c.Connected == nil || !*c.Connected { t.Error("a fresh report lost its connected flag") } } // "Nobody has ever told us" and "nobody has told us lately" need different // sentences: the first is a camera head office added a minute ago and the // shop computer has not picked up, the second is a shop computer that has // stopped. Sending an installer to the wrong one wastes a journey. func TestNeverReportedIsNotTheSameAsStopped(t *testing.T) { now := time.Now() var never Camera never.CameraState(now) if never.State != CameraWaiting { t.Errorf("state = %q, want %q", never.State, CameraWaiting) } stopped := Camera{LastSeenAt: now.Add(-time.Hour).Format(time.RFC3339)} stopped.CameraState(now) if stopped.State == never.State { t.Fatal("a camera nobody has reported and one that stopped read the same") } if stopped.StateNote == never.StateNote { t.Error("two states that need different actions gave the same advice") } } // A camera the shop computer CAN see and cannot open is the one case where // "check the cabling" is the right advice, and it must stay distinguishable // from the three where it is not. func TestAFreshFailureSaysCheckTheCamera(t *testing.T) { now := time.Now() c := Camera{Connected: ptr(false), LastSeenAt: now.Format(time.RFC3339)} c.CameraState(now) if c.State != CameraNotConnect { t.Errorf("state = %q, want %q", c.State, CameraNotConnect) } if c.Connected == nil || *c.Connected { t.Error("a reported failure must stay false, not become unknown") } } // An unparseable timestamp is not a working camera. It should not be possible, // which is exactly why it must not fall through to "connected". func TestAnUnreadableTimestampIsStale(t *testing.T) { c := Camera{Connected: ptr(true), LastSeenAt: "not a time"} c.CameraState(time.Now()) if c.State != CameraStale || c.Connected != nil { t.Errorf("state = %q connected = %v, want stale and unknown", c.State, c.Connected) } }