// test/features/bloodwork_tracker/models/bloodwork_test.dart import 'package:flutter_test/flutter_test.dart'; import 'package:nokken/src/features/bloodwork_tracker/models/bloodwork.dart'; void main() { group('Bloodwork Model', () { // Test constructor and validation test('should create valid bloodwork record', () { // Arrange - create a valid bloodwork object final bloodwork = Bloodwork( date: DateTime(2023, 6, 15), appointmentType: AppointmentType.bloodwork, hormoneReadings: [ HormoneReading(name: 'Estradiol', value: 120.5, unit: 'pg/mL'), HormoneReading(name: 'Testosterone', value: 30.2, unit: 'ng/dL'), ], location: 'City Hospital', doctor: 'Dr. Smith', notes: 'Regular checkup', ); // Assert - verify properties are set correctly expect(bloodwork.date, equals(DateTime(2023, 6, 15))); expect(bloodwork.appointmentType, equals(AppointmentType.bloodwork)); expect(bloodwork.hormoneReadings.length, equals(2)); expect(bloodwork.location, equals('City Hospital')); expect(bloodwork.doctor, equals('Dr. Smith')); expect(bloodwork.notes, equals('Regular checkup')); expect(bloodwork.id, isNotEmpty); // Auto-generated ID should not be empty }); test('should throw exception for negative hormone levels', () { // Arrange & Act - try to create bloodwork with negative hormone level invalidReading() => Bloodwork( date: DateTime(2023, 6, 15), appointmentType: AppointmentType.bloodwork, hormoneReadings: [ HormoneReading(name: 'Estradiol', value: -10.0, unit: 'pg/mL'), ], ); // Assert - verify exception is thrown expect(invalidReading, throwsA(isA())); }); test('should allow future dates for appointment types', () { // Arrange - future date with no hormone values final futureBloodwork = Bloodwork( date: DateTime.now().add(const Duration(days: 30)), appointmentType: AppointmentType.appointment, // Not bloodwork type location: 'City Hospital', ); // Assert - verify this is valid expect( futureBloodwork.appointmentType, equals(AppointmentType.appointment)); }); test( 'should throw exception for bloodwork type with no hormone readings on past date', () { // Past date with no hormone readings for bloodwork type should throw exception final pastDate = DateTime.now().subtract(const Duration(days: 1)); // Arrange & Act - try to create invalid bloodwork invalidBloodwork() => Bloodwork( date: pastDate, appointmentType: AppointmentType.bloodwork, hormoneReadings: [], // No readings ); // Assert - verify exception is thrown expect(invalidBloodwork, throwsA(isA())); }); // Test JSON conversion test('should convert to and from JSON correctly', () { // Arrange - create a bloodwork object final original = Bloodwork( id: 'test-id-123', date: DateTime(2023, 6, 15), appointmentType: AppointmentType.bloodwork, hormoneReadings: [ HormoneReading(name: 'Estradiol', value: 120.5, unit: 'pg/mL'), ], location: 'City Hospital', ); // Act - convert to JSON and back final json = original.toJson(); final restored = Bloodwork.fromJson(json); // Assert - verify properties match expect(restored.id, equals(original.id)); expect(restored.date.year, equals(original.date.year)); expect(restored.date.month, equals(original.date.month)); expect(restored.date.day, equals(original.date.day)); expect(restored.appointmentType, equals(original.appointmentType)); expect(restored.hormoneReadings.length, equals(original.hormoneReadings.length)); expect(restored.hormoneReadings[0].name, equals(original.hormoneReadings[0].name)); expect(restored.hormoneReadings[0].value, equals(original.hormoneReadings[0].value)); expect(restored.location, equals(original.location)); }); // Test HormoneReading test('HormoneReading should convert to and from JSON correctly', () { // Arrange - create a hormone reading final reading = HormoneReading( name: 'Estradiol', value: 120.5, unit: 'pg/mL', ); // Act - convert to JSON and back final json = reading.toJson(); final restored = HormoneReading.fromJson(json); // Assert - verify properties match expect(restored.name, equals(reading.name)); expect(restored.value, equals(reading.value)); expect(restored.unit, equals(reading.unit)); }); // Test copyWith test('copyWith should create a new instance with updated values', () { // Arrange - create a bloodwork object final original = Bloodwork( date: DateTime(2023, 6, 15), appointmentType: AppointmentType.bloodwork, hormoneReadings: [ HormoneReading(name: 'Estradiol', value: 120.5, unit: 'pg/mL'), ], ); // Act - create a copy with updated values final updated = original.copyWith( date: DateTime(2023, 7, 20), appointmentType: AppointmentType.appointment, notes: 'Updated notes', ); // Assert - verify original is unchanged and copy has updates expect(original.date, equals(DateTime(2023, 6, 15))); expect(original.appointmentType, equals(AppointmentType.bloodwork)); expect(original.notes, isNull); expect(updated.date, equals(DateTime(2023, 7, 20))); expect(updated.appointmentType, equals(AppointmentType.appointment)); expect(updated.notes, equals('Updated notes')); expect(updated.id, equals(original.id)); // ID should remain the same expect(updated.hormoneReadings, equals(original.hormoneReadings)); // Readings unchanged }); }); // Test HormoneTypes utility class group('HormoneTypes', () { test('should provide default units for hormone types', () { // Act & Assert - check a few default units expect(HormoneTypes.getDefaultUnit('Estradiol'), equals('pg/mL')); expect(HormoneTypes.getDefaultUnit('Testosterone'), equals('ng/dL')); expect(HormoneTypes.getDefaultUnit('Progesterone'), equals('ng/mL')); expect(HormoneTypes.getDefaultUnit('Unknown'), equals('')); }); test('should provide list of available hormone types', () { // Act - get the list of hormone types final types = HormoneTypes.getHormoneTypes(); // Assert - verify the list contains expected types expect(types, contains('Estradiol')); expect(types, contains('Testosterone')); expect(types, contains('Prolactin')); expect( types.length, greaterThanOrEqualTo(5)); // Should have several types }); }); }