316 lines
9.9 KiB
Dart
316 lines
9.9 KiB
Dart
import 'package:flutter/services.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
/// Configuration globale pour les tests
|
|
///
|
|
/// Cette classe configure l'environnement de test pour
|
|
/// garantir des conditions cohérentes et reproductibles.
|
|
class TestConfig {
|
|
static bool _initialized = false;
|
|
|
|
/// Initialise l'environnement de test
|
|
static Future<void> initialize() async {
|
|
if (_initialized) return;
|
|
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
|
|
// Configuration des SharedPreferences pour les tests
|
|
SharedPreferences.setMockInitialValues({});
|
|
|
|
// Configuration des canaux de méthodes pour les tests
|
|
_setupMethodChannels();
|
|
|
|
// Configuration des polices pour les tests de widgets
|
|
_setupFonts();
|
|
|
|
_initialized = true;
|
|
}
|
|
|
|
/// Configure les canaux de méthodes mockés
|
|
static void _setupMethodChannels() {
|
|
// Canal pour les permissions
|
|
const MethodChannel('flutter.baseflow.com/permissions/methods')
|
|
.setMockMethodCallHandler((MethodCall methodCall) async {
|
|
switch (methodCall.method) {
|
|
case 'checkPermissionStatus':
|
|
return 1; // PermissionStatus.granted
|
|
case 'requestPermissions':
|
|
return {0: 1}; // Permission granted
|
|
default:
|
|
return null;
|
|
}
|
|
});
|
|
|
|
// Canal pour la géolocalisation
|
|
const MethodChannel('flutter.baseflow.com/geolocator')
|
|
.setMockMethodCallHandler((MethodCall methodCall) async {
|
|
switch (methodCall.method) {
|
|
case 'getCurrentPosition':
|
|
return {
|
|
'latitude': 5.3600,
|
|
'longitude': -4.0083,
|
|
'timestamp': DateTime.now().millisecondsSinceEpoch,
|
|
'accuracy': 10.0,
|
|
'altitude': 0.0,
|
|
'heading': 0.0,
|
|
'speed': 0.0,
|
|
'speedAccuracy': 0.0,
|
|
};
|
|
case 'getLocationAccuracy':
|
|
return 1; // LocationAccuracy.best
|
|
default:
|
|
return null;
|
|
}
|
|
});
|
|
|
|
// Canal pour le partage de fichiers
|
|
const MethodChannel('plugins.flutter.io/share')
|
|
.setMockMethodCallHandler((MethodCall methodCall) async {
|
|
switch (methodCall.method) {
|
|
case 'share':
|
|
return null; // Succès silencieux
|
|
default:
|
|
return null;
|
|
}
|
|
});
|
|
|
|
// Canal pour l'ouverture d'URLs
|
|
const MethodChannel('plugins.flutter.io/url_launcher')
|
|
.setMockMethodCallHandler((MethodCall methodCall) async {
|
|
switch (methodCall.method) {
|
|
case 'launch':
|
|
return true; // URL ouverte avec succès
|
|
case 'canLaunch':
|
|
return true; // URL peut être ouverte
|
|
default:
|
|
return null;
|
|
}
|
|
});
|
|
|
|
// Canal pour la sélection de fichiers
|
|
const MethodChannel('miguelruivo.flutter.plugins.filepicker')
|
|
.setMockMethodCallHandler((MethodCall methodCall) async {
|
|
switch (methodCall.method) {
|
|
case 'any':
|
|
return {
|
|
'files': [
|
|
{
|
|
'name': 'test_document.pdf',
|
|
'path': '/mock/path/test_document.pdf',
|
|
'size': 1024000,
|
|
'bytes': null,
|
|
}
|
|
]
|
|
};
|
|
default:
|
|
return null;
|
|
}
|
|
});
|
|
}
|
|
|
|
/// Configure les polices pour les tests de widgets
|
|
static void _setupFonts() {
|
|
// Chargement des polices Material Design
|
|
final binding = TestWidgetsFlutterBinding.ensureInitialized();
|
|
binding.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(
|
|
const StandardMethodCodec(),
|
|
(dynamic message) async {
|
|
if (message is Map && message['method'] == 'SystemChrome.setApplicationSwitcherDescription') {
|
|
return null;
|
|
}
|
|
return null;
|
|
},
|
|
);
|
|
}
|
|
|
|
/// Nettoie l'environnement de test après chaque test
|
|
static Future<void> cleanup() async {
|
|
// Réinitialiser les SharedPreferences
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.clear();
|
|
|
|
// Nettoyer les canaux de méthodes
|
|
_clearMethodChannels();
|
|
}
|
|
|
|
/// Nettoie les canaux de méthodes
|
|
static void _clearMethodChannels() {
|
|
const MethodChannel('flutter.baseflow.com/permissions/methods')
|
|
.setMockMethodCallHandler(null);
|
|
const MethodChannel('flutter.baseflow.com/geolocator')
|
|
.setMockMethodCallHandler(null);
|
|
const MethodChannel('plugins.flutter.io/share')
|
|
.setMockMethodCallHandler(null);
|
|
const MethodChannel('plugins.flutter.io/url_launcher')
|
|
.setMockMethodCallHandler(null);
|
|
const MethodChannel('miguelruivo.flutter.plugins.filepicker')
|
|
.setMockMethodCallHandler(null);
|
|
}
|
|
}
|
|
|
|
/// Classe utilitaire pour les données de test
|
|
class TestData {
|
|
/// Données de test pour une demande d'aide
|
|
static Map<String, dynamic> get demandeAideJson => {
|
|
'id': 'demande-test-123',
|
|
'numeroReference': 'REF-TEST-001',
|
|
'titre': 'Test Aide Médicale',
|
|
'description': 'Description de test pour aide médicale',
|
|
'typeAide': 'AIDE_FINANCIERE_MEDICALE',
|
|
'statut': 'BROUILLON',
|
|
'priorite': 'NORMALE',
|
|
'estUrgente': false,
|
|
'montantDemande': 100000.0,
|
|
'dateCreation': '2024-01-15T10:00:00Z',
|
|
'dateModification': '2024-01-15T10:00:00Z',
|
|
'organisationId': 'org-test',
|
|
'demandeurId': 'user-test',
|
|
'nomDemandeur': 'Test User',
|
|
'emailDemandeur': 'test@example.com',
|
|
'telephoneDemandeur': '+225123456789',
|
|
'beneficiaires': [],
|
|
'evaluations': [],
|
|
'commentairesInternes': [],
|
|
'historiqueStatuts': [],
|
|
'piecesJustificatives': [],
|
|
'tags': ['test'],
|
|
'metadonnees': {},
|
|
};
|
|
|
|
/// Données de test pour une proposition d'aide
|
|
static Map<String, dynamic> get propositionAideJson => {
|
|
'id': 'proposition-test-123',
|
|
'titre': 'Test Proposition Aide',
|
|
'description': 'Description de test pour proposition',
|
|
'typeAide': 'AIDE_FINANCIERE_MEDICALE',
|
|
'statut': 'ACTIVE',
|
|
'montantMaximum': 200000.0,
|
|
'dateCreation': '2024-01-15T10:00:00Z',
|
|
'organisationId': 'org-test',
|
|
'proposantId': 'proposant-test',
|
|
'nomProposant': 'Test Proposant',
|
|
'emailProposant': 'proposant@example.com',
|
|
'telephoneProposant': '+225987654321',
|
|
'capacites': [],
|
|
'disponibilites': [],
|
|
'criteres': [],
|
|
'statistiques': {},
|
|
'metadonnees': {},
|
|
};
|
|
|
|
/// Données de test pour une évaluation
|
|
static Map<String, dynamic> get evaluationAideJson => {
|
|
'id': 'evaluation-test-123',
|
|
'demandeId': 'demande-test-123',
|
|
'evaluateurId': 'evaluateur-test',
|
|
'nomEvaluateur': 'Test Evaluateur',
|
|
'typeEvaluateur': 'ADMINISTRATEUR',
|
|
'dateEvaluation': '2024-01-16T10:00:00Z',
|
|
'noteGlobale': 4.0,
|
|
'criteres': {
|
|
'urgence': 4.0,
|
|
'legitimite': 4.0,
|
|
'faisabilite': 4.0,
|
|
'impact': 4.0,
|
|
},
|
|
'decision': 'APPROUVE',
|
|
'commentaires': 'Évaluation de test',
|
|
'recommandations': 'Recommandations de test',
|
|
'piecesJustificativesValidees': true,
|
|
'signalements': [],
|
|
'metadonnees': {},
|
|
};
|
|
}
|
|
|
|
/// Classe utilitaire pour les assertions personnalisées
|
|
class TestAssertions {
|
|
/// Vérifie qu'une demande d'aide a les propriétés attendues
|
|
static void assertDemandeAideValid(dynamic demande) {
|
|
expect(demande.id, isNotEmpty);
|
|
expect(demande.titre, isNotEmpty);
|
|
expect(demande.description, isNotEmpty);
|
|
expect(demande.typeAide, isNotNull);
|
|
expect(demande.statut, isNotNull);
|
|
expect(demande.priorite, isNotNull);
|
|
expect(demande.dateCreation, isNotNull);
|
|
expect(demande.organisationId, isNotEmpty);
|
|
expect(demande.demandeurId, isNotEmpty);
|
|
expect(demande.nomDemandeur, isNotEmpty);
|
|
expect(demande.emailDemandeur, isNotEmpty);
|
|
}
|
|
|
|
/// Vérifie qu'une proposition d'aide a les propriétés attendues
|
|
static void assertPropositionAideValid(dynamic proposition) {
|
|
expect(proposition.id, isNotEmpty);
|
|
expect(proposition.titre, isNotEmpty);
|
|
expect(proposition.description, isNotEmpty);
|
|
expect(proposition.typeAide, isNotNull);
|
|
expect(proposition.statut, isNotNull);
|
|
expect(proposition.dateCreation, isNotNull);
|
|
expect(proposition.organisationId, isNotEmpty);
|
|
expect(proposition.proposantId, isNotEmpty);
|
|
expect(proposition.nomProposant, isNotEmpty);
|
|
}
|
|
|
|
/// Vérifie qu'une évaluation a les propriétés attendues
|
|
static void assertEvaluationValid(dynamic evaluation) {
|
|
expect(evaluation.id, isNotEmpty);
|
|
expect(evaluation.demandeId, isNotEmpty);
|
|
expect(evaluation.evaluateurId, isNotEmpty);
|
|
expect(evaluation.nomEvaluateur, isNotEmpty);
|
|
expect(evaluation.typeEvaluateur, isNotNull);
|
|
expect(evaluation.dateEvaluation, isNotNull);
|
|
expect(evaluation.noteGlobale, greaterThanOrEqualTo(0.0));
|
|
expect(evaluation.noteGlobale, lessThanOrEqualTo(5.0));
|
|
expect(evaluation.decision, isNotNull);
|
|
}
|
|
}
|
|
|
|
/// Classe utilitaire pour les mocks
|
|
class TestMocks {
|
|
/// Crée un mock de réponse HTTP réussie
|
|
static Map<String, dynamic> createSuccessResponse(dynamic data) {
|
|
return {
|
|
'success': true,
|
|
'data': data,
|
|
'message': 'Opération réussie',
|
|
'timestamp': DateTime.now().toIso8601String(),
|
|
};
|
|
}
|
|
|
|
/// Crée un mock de réponse HTTP d'erreur
|
|
static Map<String, dynamic> createErrorResponse(String message, {int code = 500}) {
|
|
return {
|
|
'success': false,
|
|
'error': {
|
|
'code': code,
|
|
'message': message,
|
|
'details': null,
|
|
},
|
|
'timestamp': DateTime.now().toIso8601String(),
|
|
};
|
|
}
|
|
|
|
/// Crée un mock de réponse paginée
|
|
static Map<String, dynamic> createPagedResponse(List<dynamic> content, {
|
|
int page = 0,
|
|
int size = 20,
|
|
int totalElements = 0,
|
|
int totalPages = 0,
|
|
}) {
|
|
return {
|
|
'content': content,
|
|
'page': {
|
|
'number': page,
|
|
'size': size,
|
|
'totalElements': totalElements ?? content.length,
|
|
'totalPages': totalPages ?? ((totalElements ?? content.length) / size).ceil(),
|
|
},
|
|
'first': page == 0,
|
|
'last': page >= (totalPages - 1),
|
|
'empty': content.isEmpty,
|
|
};
|
|
}
|
|
}
|