summaryrefslogtreecommitdiff
path: root/player-android/test/json_helpers_test.dart
blob: a0596e2f7bb0937baca10ab2206fd71b40d5b652 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// Unit tests for json_helpers.dart.
//
// `dateTimeFromJson` is the shared deserialization helper used by every
// model that has a nullable DateTime field. These tests pin down its
// defensive contract: only well-formed ISO-8601 strings produce a
// DateTime; everything else (null, non-string, empty string, malformed
// string) silently degrades to null without throwing.
//
// The malformed-string case is the regression guard for the original
// crash bug: prior to the fix, `DateTime.parse('not a date')` propagated
// a FormatException out of fromJson() and crashed the app.

import 'package:flutter_test/flutter_test.dart';
import 'package:player_android/models/json_helpers.dart';

void main() {
  group('dateTimeFromJson', () {
    test('returns null for null input', () {
      expect(dateTimeFromJson(null), isNull);
    });

    test('returns null for empty string', () {
      expect(dateTimeFromJson(''), isNull);
    });

    test('returns null for non-string input (int)', () {
      expect(dateTimeFromJson(12345), isNull);
    });

    test('returns null for non-string input (bool)', () {
      expect(dateTimeFromJson(true), isNull);
    });

    test('parses a valid ISO-8601 UTC string', () {
      final dt = dateTimeFromJson('2026-05-20T12:34:56.000Z');
      expect(dt, isNotNull);
      expect(dt!.toUtc().year, 2026);
      expect(dt.toUtc().month, 5);
      expect(dt.toUtc().day, 20);
      expect(dt.toUtc().hour, 12);
      expect(dt.toUtc().minute, 34);
      expect(dt.toUtc().second, 56);
    });

    test('parses a valid ISO-8601 date-only string', () {
      final dt = dateTimeFromJson('2026-01-15');
      expect(dt, isNotNull);
      expect(dt!.year, 2026);
      expect(dt.month, 1);
      expect(dt.day, 15);
    });

    test('returns null for malformed string instead of throwing', () {
      // Regression guard: this used to throw FormatException and crash
      // the entire model deserialization.
      expect(() => dateTimeFromJson('not a date'), returnsNormally);
      expect(dateTimeFromJson('not a date'), isNull);
    });

    test('returns null for ISO-like string with non-numeric junk', () {
      // DateTime.parse is surprisingly tolerant of out-of-range numeric
      // components (it rolls them over), so we use a clearly non-numeric
      // value to force a FormatException.
      expect(dateTimeFromJson('2026-XX-YYTzz:zz:zzZ'), isNull);
    });

    test('returns null for garbage tokens', () {
      expect(dateTimeFromJson('@@@'), isNull);
    });
  });

  group('dateTimeToJson', () {
    test('returns null for null input', () {
      expect(dateTimeToJson(null), isNull);
    });

    test('serializes DateTime to ISO-8601 string', () {
      final dt = DateTime.utc(2026, 5, 20, 12, 34, 56);
      expect(dateTimeToJson(dt), '2026-05-20T12:34:56.000Z');
    });
  });
}