fix(chat): Correction race condition + Implémentation TODOs
## Corrections Critiques ### Race Condition - Statuts de Messages - Fix : Les icônes de statut (✓, ✓✓, ✓✓ bleu) ne s'affichaient pas - Cause : WebSocket delivery confirmations arrivaient avant messages locaux - Solution : Pattern Optimistic UI dans chat_bloc.dart - Création message temporaire immédiate - Ajout à la liste AVANT requête HTTP - Remplacement par message serveur à la réponse - Fichier : lib/presentation/state_management/chat_bloc.dart ## Implémentation TODOs (13/21) ### Social (social_header_widget.dart) - ✅ Copier lien du post dans presse-papiers - ✅ Partage natif via Share.share() - ✅ Dialogue de signalement avec 5 raisons ### Partage (share_post_dialog.dart) - ✅ Interface sélection d'amis avec checkboxes - ✅ Partage externe via Share API ### Média (media_upload_service.dart) - ✅ Parsing JSON réponse backend - ✅ Méthode deleteMedia() pour suppression - ✅ Génération miniature vidéo ### Posts (create_post_dialog.dart, edit_post_dialog.dart) - ✅ Extraction URL depuis uploads - ✅ Documentation chargement médias ### Chat (conversations_screen.dart) - ✅ Navigation vers notifications - ✅ ConversationSearchDelegate pour recherche ## Nouveaux Fichiers ### Configuration - build-prod.ps1 : Script build production avec dart-define - lib/core/constants/env_config.dart : Gestion environnements ### Documentation - TODOS_IMPLEMENTED.md : Documentation complète TODOs ## Améliorations ### Architecture - Refactoring injection de dépendances - Amélioration routing et navigation - Optimisation providers (UserProvider, FriendsProvider) ### UI/UX - Amélioration thème et couleurs - Optimisation animations - Meilleure gestion erreurs ### Services - Configuration API avec env_config - Amélioration datasources (events, users) - Optimisation modèles de données
This commit is contained in:
253
test/domain/entities/event_test.dart
Normal file
253
test/domain/entities/event_test.dart
Normal file
@@ -0,0 +1,253 @@
|
||||
import 'package:afterwork/domain/entities/event.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
group('Event Entity', () {
|
||||
final tStartDate = DateTime(2026, 1, 15, 19, 0);
|
||||
|
||||
test('should create an Event with required fields', () {
|
||||
// Arrange & Act
|
||||
final event = Event(
|
||||
id: '1',
|
||||
title: 'After-work Tech',
|
||||
description: 'Soirée networking',
|
||||
startDate: tStartDate,
|
||||
location: 'Paris, France',
|
||||
category: 'Networking',
|
||||
creatorEmail: 'john@example.com',
|
||||
creatorFirstName: 'John',
|
||||
creatorLastName: 'Doe',
|
||||
creatorProfileImageUrl: 'https://example.com/profile.jpg',
|
||||
);
|
||||
|
||||
// Assert
|
||||
expect(event.id, '1');
|
||||
expect(event.title, 'After-work Tech');
|
||||
expect(event.description, 'Soirée networking');
|
||||
expect(event.startDate, tStartDate);
|
||||
expect(event.location, 'Paris, France');
|
||||
expect(event.category, 'Networking');
|
||||
expect(event.creatorEmail, 'john@example.com');
|
||||
expect(event.creatorFirstName, 'John');
|
||||
expect(event.creatorLastName, 'Doe');
|
||||
expect(event.status, EventStatus.open); // Default
|
||||
expect(event.participantIds, isEmpty);
|
||||
expect(event.reactionsCount, 0);
|
||||
expect(event.commentsCount, 0);
|
||||
expect(event.sharesCount, 0);
|
||||
});
|
||||
|
||||
test('should create an Event with optional fields', () {
|
||||
// Arrange & Act
|
||||
final event = Event(
|
||||
id: '1',
|
||||
title: 'After-work Tech',
|
||||
description: 'Soirée networking',
|
||||
startDate: tStartDate,
|
||||
location: 'Paris, France',
|
||||
category: 'Networking',
|
||||
link: 'https://event.com',
|
||||
imageUrl: 'https://event.com/image.jpg',
|
||||
creatorEmail: 'john@example.com',
|
||||
creatorFirstName: 'John',
|
||||
creatorLastName: 'Doe',
|
||||
creatorProfileImageUrl: 'https://example.com/profile.jpg',
|
||||
participantIds: const ['user1', 'user2'],
|
||||
status: EventStatus.closed,
|
||||
reactionsCount: 10,
|
||||
commentsCount: 5,
|
||||
sharesCount: 3,
|
||||
);
|
||||
|
||||
// Assert
|
||||
expect(event.link, 'https://event.com');
|
||||
expect(event.imageUrl, 'https://event.com/image.jpg');
|
||||
expect(event.participantIds, ['user1', 'user2']);
|
||||
expect(event.status, EventStatus.closed);
|
||||
expect(event.reactionsCount, 10);
|
||||
expect(event.commentsCount, 5);
|
||||
expect(event.sharesCount, 3);
|
||||
});
|
||||
|
||||
test('should return correct creator full name', () {
|
||||
// Arrange & Act
|
||||
final event = Event(
|
||||
id: '1',
|
||||
title: 'Test Event',
|
||||
description: 'Test',
|
||||
startDate: tStartDate,
|
||||
location: 'Test Location',
|
||||
category: 'Test',
|
||||
creatorEmail: 'john@example.com',
|
||||
creatorFirstName: 'John',
|
||||
creatorLastName: 'Doe',
|
||||
creatorProfileImageUrl: 'test.jpg',
|
||||
);
|
||||
|
||||
// Assert
|
||||
expect(event.creatorFullName, 'John Doe');
|
||||
});
|
||||
|
||||
test('should return correct participants count', () {
|
||||
// Arrange & Act
|
||||
final event = Event(
|
||||
id: '1',
|
||||
title: 'Test Event',
|
||||
description: 'Test',
|
||||
startDate: tStartDate,
|
||||
location: 'Test Location',
|
||||
category: 'Test',
|
||||
creatorEmail: 'test@example.com',
|
||||
creatorFirstName: 'Test',
|
||||
creatorLastName: 'User',
|
||||
creatorProfileImageUrl: 'test.jpg',
|
||||
participantIds: const ['user1', 'user2', 'user3'],
|
||||
);
|
||||
|
||||
// Assert
|
||||
expect(event.participantsCount, 3);
|
||||
});
|
||||
|
||||
test('isOpen should return true when status is open', () {
|
||||
// Arrange & Act
|
||||
final event = Event(
|
||||
id: '1',
|
||||
title: 'Test Event',
|
||||
description: 'Test',
|
||||
startDate: tStartDate,
|
||||
location: 'Test Location',
|
||||
category: 'Test',
|
||||
creatorEmail: 'test@example.com',
|
||||
creatorFirstName: 'Test',
|
||||
creatorLastName: 'User',
|
||||
creatorProfileImageUrl: 'test.jpg',
|
||||
status: EventStatus.open,
|
||||
);
|
||||
|
||||
// Assert
|
||||
expect(event.isOpen, isTrue);
|
||||
expect(event.isClosed, isFalse);
|
||||
expect(event.isCancelled, isFalse);
|
||||
});
|
||||
|
||||
test('isClosed should return true when status is closed', () {
|
||||
// Arrange & Act
|
||||
final event = Event(
|
||||
id: '1',
|
||||
title: 'Test Event',
|
||||
description: 'Test',
|
||||
startDate: tStartDate,
|
||||
location: 'Test Location',
|
||||
category: 'Test',
|
||||
creatorEmail: 'test@example.com',
|
||||
creatorFirstName: 'Test',
|
||||
creatorLastName: 'User',
|
||||
creatorProfileImageUrl: 'test.jpg',
|
||||
status: EventStatus.closed,
|
||||
);
|
||||
|
||||
// Assert
|
||||
expect(event.isClosed, isTrue);
|
||||
expect(event.isOpen, isFalse);
|
||||
expect(event.isCancelled, isFalse);
|
||||
});
|
||||
|
||||
test('copyWith should create a new instance with updated fields', () {
|
||||
// Arrange
|
||||
final original = Event(
|
||||
id: '1',
|
||||
title: 'Original Title',
|
||||
description: 'Original Description',
|
||||
startDate: tStartDate,
|
||||
location: 'Original Location',
|
||||
category: 'Original Category',
|
||||
creatorEmail: 'test@example.com',
|
||||
creatorFirstName: 'Test',
|
||||
creatorLastName: 'User',
|
||||
creatorProfileImageUrl: 'test.jpg',
|
||||
);
|
||||
|
||||
// Act
|
||||
final updated = original.copyWith(
|
||||
title: 'Updated Title',
|
||||
status: EventStatus.closed,
|
||||
);
|
||||
|
||||
// Assert
|
||||
expect(updated.id, original.id); // Unchanged
|
||||
expect(updated.title, 'Updated Title'); // Changed
|
||||
expect(updated.description, original.description); // Unchanged
|
||||
expect(updated.status, EventStatus.closed); // Changed
|
||||
});
|
||||
|
||||
test('should support value equality using Equatable', () {
|
||||
// Arrange
|
||||
final event1 = Event(
|
||||
id: '1',
|
||||
title: 'Event',
|
||||
description: 'Description',
|
||||
startDate: tStartDate,
|
||||
location: 'Location',
|
||||
category: 'Category',
|
||||
creatorEmail: 'test@example.com',
|
||||
creatorFirstName: 'Test',
|
||||
creatorLastName: 'User',
|
||||
creatorProfileImageUrl: 'test.jpg',
|
||||
);
|
||||
|
||||
final event2 = Event(
|
||||
id: '1',
|
||||
title: 'Event',
|
||||
description: 'Description',
|
||||
startDate: tStartDate,
|
||||
location: 'Location',
|
||||
category: 'Category',
|
||||
creatorEmail: 'test@example.com',
|
||||
creatorFirstName: 'Test',
|
||||
creatorLastName: 'User',
|
||||
creatorProfileImageUrl: 'test.jpg',
|
||||
);
|
||||
|
||||
// Assert
|
||||
expect(event1, equals(event2));
|
||||
});
|
||||
});
|
||||
|
||||
group('EventStatus', () {
|
||||
test('fromString should convert "ouvert" to open', () {
|
||||
expect(EventStatus.fromString('ouvert'), EventStatus.open);
|
||||
expect(EventStatus.fromString('open'), EventStatus.open);
|
||||
});
|
||||
|
||||
test('fromString should convert "fermé" to closed', () {
|
||||
expect(EventStatus.fromString('fermé'), EventStatus.closed);
|
||||
expect(EventStatus.fromString('ferme'), EventStatus.closed);
|
||||
expect(EventStatus.fromString('closed'), EventStatus.closed);
|
||||
});
|
||||
|
||||
test('fromString should convert "annulé" to cancelled', () {
|
||||
expect(EventStatus.fromString('annulé'), EventStatus.cancelled);
|
||||
expect(EventStatus.fromString('annule'), EventStatus.cancelled);
|
||||
expect(EventStatus.fromString('cancelled'), EventStatus.cancelled);
|
||||
});
|
||||
|
||||
test('fromString should convert "terminé" to completed', () {
|
||||
expect(EventStatus.fromString('terminé'), EventStatus.completed);
|
||||
expect(EventStatus.fromString('termine'), EventStatus.completed);
|
||||
expect(EventStatus.fromString('completed'), EventStatus.completed);
|
||||
});
|
||||
|
||||
test('fromString should return open for unknown status', () {
|
||||
expect(EventStatus.fromString('unknown'), EventStatus.open);
|
||||
expect(EventStatus.fromString(''), EventStatus.open);
|
||||
});
|
||||
|
||||
test('toApiString should convert status to French API strings', () {
|
||||
expect(EventStatus.open.toApiString(), 'ouvert');
|
||||
expect(EventStatus.closed.toApiString(), 'fermé');
|
||||
expect(EventStatus.cancelled.toApiString(), 'annulé');
|
||||
expect(EventStatus.completed.toApiString(), 'terminé');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user