device infos
This commit is contained in:
100
test/device_telemetry_test.dart
Normal file
100
test/device_telemetry_test.dart
Normal file
@@ -0,0 +1,100 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'package:miler/data/device_telemetry.dart';
|
||||
|
||||
/// ─────────────────────────────────────────────────────────────────────────
|
||||
/// THE CONSOLE'S DEVICE PANEL WAS READING AN EMPTY FIELD
|
||||
///
|
||||
/// ── What the dispatcher saw ──
|
||||
///
|
||||
/// Battery —, Connection —, GPS Accuracy —, Location Service —, Current
|
||||
/// Order —. Every column on the panel that answers *why has this rider gone
|
||||
/// quiet* was blank, on riders whose phones were reporting all of it.
|
||||
///
|
||||
/// ── Why ──
|
||||
///
|
||||
/// Not because nothing was measured. The heartbeat read the battery, the
|
||||
/// charging state, the connection type and the location-service status on every
|
||||
/// tick — and published them to **MQTT only**, in a block that ran *after* the
|
||||
/// rider log had already been posted. `POST /miler/logs` has a named field for
|
||||
/// each one and carried none of them.
|
||||
///
|
||||
/// Two lanes for one fact, and the lane the console reads was the empty one.
|
||||
/// On top of that, `location_service` was dropped a second time further down:
|
||||
/// the provider forwarded every other device field to [MilerApi.postLog] and
|
||||
/// silently skipped that one, so it could not have arrived even if the caller
|
||||
/// had sent it.
|
||||
///
|
||||
/// These pin the shape of the payload, which is the part a wrong refactor would
|
||||
/// break silently — a missing key renders as an em dash, which is exactly what
|
||||
/// it looked like before anyone noticed.
|
||||
/// ─────────────────────────────────────────────────────────────────────────
|
||||
void main() {
|
||||
group('the payload carries what the console reads', () {
|
||||
test('every field the contract names is emitted under its own name', () {
|
||||
const t = DeviceTelemetry(
|
||||
battery: 72,
|
||||
isCharging: false,
|
||||
connection: '4G',
|
||||
locationService: 'enabled',
|
||||
);
|
||||
|
||||
// The names are the wire's, from `POST /miler/logs`. A rename here is a
|
||||
// column that goes blank on the console with nothing else failing.
|
||||
expect(t.toPayload(), {
|
||||
'battery': '72',
|
||||
'is_charging': false,
|
||||
'connection': '4G',
|
||||
'location_service': 'enabled',
|
||||
});
|
||||
});
|
||||
|
||||
test('numbers go as strings, as every other numeric field does', () {
|
||||
// Documented at the top of `MilerApi`: real numbers fail to parse
|
||||
// server-side on `/logs` and `/consignments/logs`.
|
||||
const t = DeviceTelemetry(battery: 5);
|
||||
expect(t.toPayload()['battery'], isA<String>());
|
||||
expect(t.toPayload()['battery'], '5');
|
||||
});
|
||||
|
||||
test('is_charging stays a bool, because the contract says so', () {
|
||||
const t = DeviceTelemetry(isCharging: true);
|
||||
expect(t.toPayload()['is_charging'], isTrue);
|
||||
expect(t.toPayload()['is_charging'], isA<bool>());
|
||||
});
|
||||
});
|
||||
|
||||
group('unknown is absent, never a plausible number', () {
|
||||
test('a reading that failed emits no key at all', () {
|
||||
// The whole panel is read by somebody deciding whether to call a rider.
|
||||
// A `0` battery standing in for "could not ask" is a fact they would act
|
||||
// on; an absent key draws the em dash it already drew, which is true.
|
||||
const t = DeviceTelemetry();
|
||||
expect(t.toPayload(), isEmpty);
|
||||
});
|
||||
|
||||
test('a partial reading sends the half it has', () {
|
||||
// The reads are guarded individually, so a platform that will not answer
|
||||
// about the battery must not cost the connection its column too.
|
||||
const t = DeviceTelemetry(connection: 'wifi');
|
||||
expect(t.toPayload(), {'connection': 'wifi'});
|
||||
});
|
||||
|
||||
test('an empty string is treated as no answer', () {
|
||||
const t = DeviceTelemetry(connection: '', locationService: '');
|
||||
expect(t.toPayload(), isEmpty);
|
||||
});
|
||||
|
||||
test('a zero battery is a real reading and is sent', () {
|
||||
// The one number that must survive the "absent, never plausible" rule:
|
||||
// 0% is not a missing measurement, it is a rider about to disappear.
|
||||
const t = DeviceTelemetry(battery: 0);
|
||||
expect(t.toPayload()['battery'], '0');
|
||||
});
|
||||
|
||||
test('not charging is a real reading and is sent', () {
|
||||
const t = DeviceTelemetry(isCharging: false);
|
||||
expect(t.toPayload().containsKey('is_charging'), isTrue);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user