import 'package:flutter_test/flutter_test.dart'; import 'package:nearle_pos/core/utils/formatters.dart'; /// The fault these cover was found in live data, not in a test. /// /// Bill INV-2608-T5EDD-00116 carried `billedat 2026-08-05T12:49:28.245Z` beside /// `receivedat 2026-08-05T07:19:28.586Z` — the bill appearing to have been rung /// five and a half hours *after* the back office received it. Exactly the IST /// offset, every time. /// /// Nothing was lying. `DateTime.toIso8601String()` on a local time emits no /// zone marker at all, Go's `time.Parse` fills that silence with UTC, and the /// till's wall clock was recorded as though it had been read in London. void main() { group('a timestamp says which zone it was read in', () { test('carries an explicit offset', () { final iso = Formatters.isoWithOffset(DateTime(2026, 8, 5, 12, 49, 28)); expect( iso, matches(r'^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.*[+-]\d{2}:\d{2}$'), reason: 'without an offset the receiver has to guess, and guesses UTC', ); }); test('round-trips back to the same instant', () { // The whole point. The old form parsed to a different moment than the one // the cashier rang the bill at. final rung = DateTime(2026, 8, 5, 12, 49, 28, 245); final parsed = DateTime.parse(Formatters.isoWithOffset(rung)); expect( parsed.toUtc(), rung.toUtc(), reason: 'the instant must survive the trip to the back office', ); }); test('keeps the wall clock the till actually showed', () { // Load-bearing for businessdate. The back office derives a day's takings // from the wall clock, so a bill rung at 12:49 must still read 12:49 — // converting to UTC before sending would have moved it to 07:19 and put // late-evening sales on the previous day. final iso = Formatters.isoWithOffset(DateTime(2026, 8, 5, 12, 49, 28)); expect(iso, startsWith('2026-08-05T12:49:28')); }); test('does not drop a half-hour offset', () { // India is +05:30. An implementation that formatted only whole hours // would produce +05:00 here and be wrong by thirty minutes — the kind of // error that survives review because it looks almost right. final offset = DateTime.now().timeZoneOffset; final iso = Formatters.isoWithOffset(DateTime(2026, 8, 5, 12, 0)); final minutes = offset.abs().inMinutes % 60; expect( iso.substring(iso.length - 2), minutes.toString().padLeft(2, '0'), reason: 'the minutes component must come from the real offset', ); }); test('a UTC input is converted, not relabelled', () { // Passing an already-UTC DateTime must not stamp it with the local // offset while leaving the UTC wall clock in place — that would recreate // the original bug in reverse. final instant = DateTime.utc(2026, 8, 5, 7, 19, 28); final parsed = DateTime.parse(Formatters.isoWithOffset(instant)); expect(parsed.toUtc(), instant); }); }); }