import 'dart:convert'; import 'package:afterwork/data/models/event_model.dart'; import 'package:afterwork/domain/entities/event.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { group('EventModel', () { final tEventModel = EventModel( id: '1', title: 'After-work Tech', description: 'Soirée networking', startDate: '2026-01-15T19:00:00Z', location: 'Paris, France', category: 'Networking', link: 'https://event.com', imageUrl: 'https://event.com/image.jpg', creatorEmail: 'john@example.com', creatorFirstName: 'John', creatorLastName: 'Doe', profileImageUrl: 'https://example.com/profile.jpg', participants: ['user1', 'user2'], status: 'ouvert', reactionsCount: 10, commentsCount: 5, sharesCount: 3, ); final tEventModelJson = { 'id': '1', 'title': 'After-work Tech', 'description': 'Soirée networking', 'startDate': '2026-01-15T19:00:00Z', 'location': 'Paris, France', 'category': 'Networking', 'link': 'https://event.com', 'imageUrl': 'https://event.com/image.jpg', 'creatorEmail': 'john@example.com', 'creatorFirstName': 'John', 'creatorLastName': 'Doe', 'profileImageUrl': 'https://example.com/profile.jpg', 'participants': ['user1', 'user2'], 'status': 'ouvert', 'reactionsCount': 10, 'commentsCount': 5, 'sharesCount': 3, }; test('should be a subclass of EventModel', () { // Assert expect(tEventModel, isA()); }); group('fromJson', () { test('should return a valid EventModel from JSON', () { // Act final result = EventModel.fromJson(tEventModelJson); // Assert expect(result.id, tEventModel.id); expect(result.title, tEventModel.title); expect(result.description, tEventModel.description); expect(result.startDate, tEventModel.startDate); expect(result.location, tEventModel.location); expect(result.category, tEventModel.category); expect(result.link, tEventModel.link); expect(result.imageUrl, tEventModel.imageUrl); expect(result.creatorEmail, tEventModel.creatorEmail); expect(result.creatorFirstName, tEventModel.creatorFirstName); expect(result.creatorLastName, tEventModel.creatorLastName); expect(result.status, tEventModel.status); }); test('should use default values for missing fields', () { // Arrange final minimalJson = { 'id': '1', 'title': 'Event', 'description': 'Description', 'startDate': '2026-01-15T19:00:00Z', 'location': 'Location', 'category': 'Category', 'link': 'Link', 'creatorEmail': 'email@example.com', 'creatorFirstName': 'John', 'creatorLastName': 'Doe', 'profileImageUrl': 'profile.jpg', 'participants': [], }; // Act final result = EventModel.fromJson(minimalJson); // Assert expect(result.imageUrl, isNull); expect(result.status, 'ouvert'); // Default expect(result.reactionsCount, 0); // Default expect(result.commentsCount, 0); // Default expect(result.sharesCount, 0); // Default }); test('should handle null imageUrl', () { // Arrange final jsonWithNullImage = Map.from(tEventModelJson); jsonWithNullImage['imageUrl'] = null; // Act final result = EventModel.fromJson(jsonWithNullImage); // Assert expect(result.imageUrl, isNull); }); }); group('toJson', () { test('should return a JSON map containing proper data', () { // Act final result = tEventModel.toJson(); // Assert expect(result, isA>()); expect(result['id'], '1'); expect(result['title'], 'After-work Tech'); expect(result['description'], 'Soirée networking'); expect(result['startDate'], '2026-01-15T19:00:00Z'); expect(result['location'], 'Paris, France'); expect(result['category'], 'Networking'); expect(result['link'], 'https://event.com'); expect(result['imageUrl'], 'https://event.com/image.jpg'); expect(result['creatorEmail'], 'john@example.com'); expect(result['creatorFirstName'], 'John'); expect(result['creatorLastName'], 'Doe'); expect(result['status'], 'ouvert'); expect(result['reactionsCount'], 10); expect(result['commentsCount'], 5); expect(result['sharesCount'], 3); }); test('should be reversible (fromJson -> toJson)', () { // Act final json = tEventModel.toJson(); final model = EventModel.fromJson(json); // Assert expect(model.id, tEventModel.id); expect(model.title, tEventModel.title); expect(model.status, tEventModel.status); }); }); group('toEntity', () { test('should convert EventModel to Event entity', () { // Act final entity = tEventModel.toEntity(); // Assert expect(entity, isA()); expect(entity.id, tEventModel.id); expect(entity.title, tEventModel.title); expect(entity.description, tEventModel.description); expect(entity.location, tEventModel.location); expect(entity.category, tEventModel.category); expect(entity.link, tEventModel.link); expect(entity.imageUrl, tEventModel.imageUrl); expect(entity.creatorEmail, tEventModel.creatorEmail); expect(entity.creatorFirstName, tEventModel.creatorFirstName); expect(entity.creatorLastName, tEventModel.creatorLastName); expect(entity.reactionsCount, tEventModel.reactionsCount); expect(entity.commentsCount, tEventModel.commentsCount); expect(entity.sharesCount, tEventModel.sharesCount); }); test('should convert startDate string to DateTime', () { // Act final entity = tEventModel.toEntity(); // Assert expect(entity.startDate, isA()); expect(entity.startDate.year, 2026); expect(entity.startDate.month, 1); expect(entity.startDate.day, 15); }); test('should convert status string to EventStatus enum', () { // Arrange final openModel = EventModel( id: '1', title: 'Event', description: 'Desc', startDate: '2026-01-15T19:00:00Z', location: 'Location', category: 'Category', link: 'Link', creatorEmail: 'email@example.com', creatorFirstName: 'John', creatorLastName: 'Doe', profileImageUrl: 'profile.jpg', participants: [], status: 'ouvert', reactionsCount: 0, commentsCount: 0, sharesCount: 0, ); final closedModel = EventModel( id: '1', title: 'Event', description: 'Desc', startDate: '2026-01-15T19:00:00Z', location: 'Location', category: 'Category', link: 'Link', creatorEmail: 'email@example.com', creatorFirstName: 'John', creatorLastName: 'Doe', profileImageUrl: 'profile.jpg', participants: [], status: 'fermé', reactionsCount: 0, commentsCount: 0, sharesCount: 0, ); // Act final openEntity = openModel.toEntity(); final closedEntity = closedModel.toEntity(); // Assert expect(openEntity.status, EventStatus.open); expect(closedEntity.status, EventStatus.closed); }); test('should convert participants list to participantIds', () { // Act final entity = tEventModel.toEntity(); // Assert expect(entity.participantIds, ['user1', 'user2']); expect(entity.participantsCount, 2); }); }); group('fromEntity', () { test('should convert Event entity to EventModel', () { // Arrange final entity = Event( id: '1', title: 'Event Title', description: 'Event Description', startDate: DateTime(2026, 1, 15, 19, 0), location: 'Paris', category: 'Tech', link: 'https://link.com', imageUrl: 'https://image.com', creatorEmail: 'creator@example.com', creatorFirstName: 'Jane', creatorLastName: 'Smith', creatorProfileImageUrl: 'https://profile.jpg', participantIds: const ['p1', 'p2', 'p3'], status: EventStatus.open, reactionsCount: 15, commentsCount: 8, sharesCount: 4, ); // Act final model = EventModel.fromEntity(entity); // Assert expect(model.id, entity.id); expect(model.title, entity.title); expect(model.description, entity.description); expect(model.location, entity.location); expect(model.category, entity.category); expect(model.link, entity.link); expect(model.imageUrl, entity.imageUrl); expect(model.creatorEmail, entity.creatorEmail); expect(model.creatorFirstName, entity.creatorFirstName); expect(model.creatorLastName, entity.creatorLastName); expect(model.reactionsCount, entity.reactionsCount); expect(model.commentsCount, entity.commentsCount); expect(model.sharesCount, entity.sharesCount); }); test('should convert DateTime to ISO8601 string', () { // Arrange final entity = Event( id: '1', title: 'Event', description: 'Desc', startDate: DateTime(2026, 1, 15, 19, 0), location: 'Location', category: 'Category', creatorEmail: 'email@example.com', creatorFirstName: 'John', creatorLastName: 'Doe', creatorProfileImageUrl: 'profile.jpg', ); // Act final model = EventModel.fromEntity(entity); // Assert expect(model.startDate, contains('2026-01-15')); expect(model.startDate, contains('T')); }); test('should convert EventStatus to API string', () { // Arrange final openEntity = Event( id: '1', title: 'Event', description: 'Desc', startDate: DateTime(2026, 1, 15), location: 'Location', category: 'Category', creatorEmail: 'email@example.com', creatorFirstName: 'John', creatorLastName: 'Doe', creatorProfileImageUrl: 'profile.jpg', status: EventStatus.open, ); final closedEntity = openEntity.copyWith(status: EventStatus.closed); // Act final openModel = EventModel.fromEntity(openEntity); final closedModel = EventModel.fromEntity(closedEntity); // Assert expect(openModel.status, 'ouvert'); expect(closedModel.status, 'fermé'); }); test('should handle null link', () { // Arrange final entity = Event( id: '1', title: 'Event', description: 'Desc', startDate: DateTime(2026, 1, 15), location: 'Location', category: 'Category', creatorEmail: 'email@example.com', creatorFirstName: 'John', creatorLastName: 'Doe', creatorProfileImageUrl: 'profile.jpg', link: null, ); // Act final model = EventModel.fromEntity(entity); // Assert expect(model.link, ''); // Converted to empty string }); }); group('Entity-Model round trip', () { test('should maintain data integrity through conversions', () { // Arrange final originalEntity = Event( id: '123', title: 'Original Event', description: 'Original Description', startDate: DateTime(2026, 6, 15, 18, 30), location: 'Original Location', category: 'Original Category', link: 'https://original.com', imageUrl: 'https://original.com/image.jpg', creatorEmail: 'original@example.com', creatorFirstName: 'Original', creatorLastName: 'Creator', creatorProfileImageUrl: 'https://profile.jpg', participantIds: const ['p1', 'p2'], status: EventStatus.open, reactionsCount: 20, commentsCount: 10, sharesCount: 5, ); // Act: Entity -> Model -> Entity final model = EventModel.fromEntity(originalEntity); final finalEntity = model.toEntity(); // Assert expect(finalEntity.id, originalEntity.id); expect(finalEntity.title, originalEntity.title); expect(finalEntity.description, originalEntity.description); expect(finalEntity.location, originalEntity.location); expect(finalEntity.category, originalEntity.category); expect(finalEntity.status, originalEntity.status); expect(finalEntity.participantsCount, originalEntity.participantsCount); }); }); }); }