Refactoring
This commit is contained in:
@@ -0,0 +1,441 @@
|
||||
import 'package:bloc_test/bloc_test.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
|
||||
import 'package:unionflow_mobile_apps/core/error/failures.dart';
|
||||
import 'package:unionflow_mobile_apps/features/solidarite/domain/entities/demande_aide.dart';
|
||||
import 'package:unionflow_mobile_apps/features/solidarite/domain/usecases/gerer_demandes_aide_usecase.dart';
|
||||
import 'package:unionflow_mobile_apps/features/solidarite/presentation/bloc/demandes_aide/demandes_aide_bloc.dart';
|
||||
import 'package:unionflow_mobile_apps/features/solidarite/presentation/bloc/demandes_aide/demandes_aide_event.dart';
|
||||
import 'package:unionflow_mobile_apps/features/solidarite/presentation/bloc/demandes_aide/demandes_aide_state.dart';
|
||||
|
||||
import 'demandes_aide_bloc_test.mocks.dart';
|
||||
|
||||
@GenerateMocks([
|
||||
CreerDemandeAideUseCase,
|
||||
MettreAJourDemandeAideUseCase,
|
||||
ObtenirDemandeAideUseCase,
|
||||
SoumettreDemandeAideUseCase,
|
||||
EvaluerDemandeAideUseCase,
|
||||
RechercherDemandesAideUseCase,
|
||||
ObtenirDemandesUrgentesUseCase,
|
||||
ObtenirMesDemandesUseCase,
|
||||
ValiderDemandeAideUseCase,
|
||||
CalculerPrioriteDemandeUseCase,
|
||||
])
|
||||
void main() {
|
||||
group('DemandesAideBloc', () {
|
||||
late DemandesAideBloc bloc;
|
||||
late MockCreerDemandeAideUseCase mockCreerDemandeAideUseCase;
|
||||
late MockMettreAJourDemandeAideUseCase mockMettreAJourDemandeAideUseCase;
|
||||
late MockObtenirDemandeAideUseCase mockObtenirDemandeAideUseCase;
|
||||
late MockSoumettreDemandeAideUseCase mockSoumettreDemandeAideUseCase;
|
||||
late MockEvaluerDemandeAideUseCase mockEvaluerDemandeAideUseCase;
|
||||
late MockRechercherDemandesAideUseCase mockRechercherDemandesAideUseCase;
|
||||
late MockObtenirDemandesUrgentesUseCase mockObtenirDemandesUrgentesUseCase;
|
||||
late MockObtenirMesDemandesUseCase mockObtenirMesDemandesUseCase;
|
||||
late MockValiderDemandeAideUseCase mockValiderDemandeAideUseCase;
|
||||
late MockCalculerPrioriteDemandeUseCase mockCalculerPrioriteDemandeUseCase;
|
||||
|
||||
setUp(() {
|
||||
mockCreerDemandeAideUseCase = MockCreerDemandeAideUseCase();
|
||||
mockMettreAJourDemandeAideUseCase = MockMettreAJourDemandeAideUseCase();
|
||||
mockObtenirDemandeAideUseCase = MockObtenirDemandeAideUseCase();
|
||||
mockSoumettreDemandeAideUseCase = MockSoumettreDemandeAideUseCase();
|
||||
mockEvaluerDemandeAideUseCase = MockEvaluerDemandeAideUseCase();
|
||||
mockRechercherDemandesAideUseCase = MockRechercherDemandesAideUseCase();
|
||||
mockObtenirDemandesUrgentesUseCase = MockObtenirDemandesUrgentesUseCase();
|
||||
mockObtenirMesDemandesUseCase = MockObtenirMesDemandesUseCase();
|
||||
mockValiderDemandeAideUseCase = MockValiderDemandeAideUseCase();
|
||||
mockCalculerPrioriteDemandeUseCase = MockCalculerPrioriteDemandeUseCase();
|
||||
|
||||
bloc = DemandesAideBloc(
|
||||
creerDemandeAideUseCase: mockCreerDemandeAideUseCase,
|
||||
mettreAJourDemandeAideUseCase: mockMettreAJourDemandeAideUseCase,
|
||||
obtenirDemandeAideUseCase: mockObtenirDemandeAideUseCase,
|
||||
soumettreDemandeAideUseCase: mockSoumettreDemandeAideUseCase,
|
||||
evaluerDemandeAideUseCase: mockEvaluerDemandeAideUseCase,
|
||||
rechercherDemandesAideUseCase: mockRechercherDemandesAideUseCase,
|
||||
obtenirDemandesUrgentesUseCase: mockObtenirDemandesUrgentesUseCase,
|
||||
obtenirMesDemandesUseCase: mockObtenirMesDemandesUseCase,
|
||||
validerDemandeAideUseCase: mockValiderDemandeAideUseCase,
|
||||
calculerPrioriteDemandeUseCase: mockCalculerPrioriteDemandeUseCase,
|
||||
);
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
bloc.close();
|
||||
});
|
||||
|
||||
test('état initial est DemandesAideInitial', () {
|
||||
expect(bloc.state, equals(const DemandesAideInitial()));
|
||||
});
|
||||
|
||||
group('ChargerDemandesAideEvent', () {
|
||||
final tDemandes = [
|
||||
_createTestDemandeAide('1', 'Demande 1'),
|
||||
_createTestDemandeAide('2', 'Demande 2'),
|
||||
];
|
||||
|
||||
blocTest<DemandesAideBloc, DemandesAideState>(
|
||||
'émet [DemandesAideLoading, DemandesAideLoaded] quand les données sont chargées avec succès',
|
||||
build: () {
|
||||
when(mockRechercherDemandesAideUseCase(any))
|
||||
.thenAnswer((_) async => Right(tDemandes));
|
||||
return bloc;
|
||||
},
|
||||
act: (bloc) => bloc.add(const ChargerDemandesAideEvent()),
|
||||
expect: () => [
|
||||
const DemandesAideLoading(),
|
||||
isA<DemandesAideLoaded>()
|
||||
.having((state) => state.demandes, 'demandes', tDemandes)
|
||||
.having((state) => state.demandesFiltrees, 'demandesFiltrees', tDemandes)
|
||||
.having((state) => state.hasReachedMax, 'hasReachedMax', true)
|
||||
.having((state) => state.currentPage, 'currentPage', 0)
|
||||
.having((state) => state.totalElements, 'totalElements', 2),
|
||||
],
|
||||
verify: (_) {
|
||||
verify(mockRechercherDemandesAideUseCase(
|
||||
RechercherDemandesAideParams(
|
||||
organisationId: null,
|
||||
typeAide: null,
|
||||
statut: null,
|
||||
demandeurId: null,
|
||||
urgente: null,
|
||||
page: 0,
|
||||
taille: 20,
|
||||
),
|
||||
));
|
||||
},
|
||||
);
|
||||
|
||||
blocTest<DemandesAideBloc, DemandesAideState>(
|
||||
'émet [DemandesAideLoading, DemandesAideError] quand le chargement échoue',
|
||||
build: () {
|
||||
when(mockRechercherDemandesAideUseCase(any))
|
||||
.thenAnswer((_) async => const Left(ServerFailure('Erreur serveur')));
|
||||
return bloc;
|
||||
},
|
||||
act: (bloc) => bloc.add(const ChargerDemandesAideEvent()),
|
||||
expect: () => [
|
||||
const DemandesAideLoading(),
|
||||
isA<DemandesAideError>()
|
||||
.having((state) => state.message, 'message', 'Erreur serveur. Veuillez réessayer plus tard.')
|
||||
.having((state) => state.isNetworkError, 'isNetworkError', false)
|
||||
.having((state) => state.canRetry, 'canRetry', true),
|
||||
],
|
||||
);
|
||||
|
||||
blocTest<DemandesAideBloc, DemandesAideState>(
|
||||
'émet [DemandesAideLoaded] avec isRefreshing=true quand forceRefresh=false et état déjà chargé',
|
||||
build: () {
|
||||
when(mockRechercherDemandesAideUseCase(any))
|
||||
.thenAnswer((_) async => Right(tDemandes));
|
||||
return bloc;
|
||||
},
|
||||
seed: () => DemandesAideLoaded(
|
||||
demandes: const [],
|
||||
demandesFiltrees: const [],
|
||||
lastUpdated: DateTime.now(),
|
||||
),
|
||||
act: (bloc) => bloc.add(const ChargerDemandesAideEvent()),
|
||||
expect: () => [
|
||||
isA<DemandesAideLoaded>().having((state) => state.isRefreshing, 'isRefreshing', true),
|
||||
isA<DemandesAideLoaded>()
|
||||
.having((state) => state.demandes, 'demandes', tDemandes)
|
||||
.having((state) => state.isRefreshing, 'isRefreshing', false),
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
group('CreerDemandeAideEvent', () {
|
||||
final tDemande = _createTestDemandeAide('1', 'Nouvelle demande');
|
||||
|
||||
blocTest<DemandesAideBloc, DemandesAideState>(
|
||||
'émet [DemandesAideLoading, DemandesAideOperationSuccess, DemandesAideLoading, DemandesAideLoaded] quand la création réussit',
|
||||
build: () {
|
||||
when(mockCreerDemandeAideUseCase(any))
|
||||
.thenAnswer((_) async => Right(tDemande));
|
||||
when(mockRechercherDemandesAideUseCase(any))
|
||||
.thenAnswer((_) async => Right([tDemande]));
|
||||
return bloc;
|
||||
},
|
||||
act: (bloc) => bloc.add(CreerDemandeAideEvent(demande: tDemande)),
|
||||
expect: () => [
|
||||
const DemandesAideLoading(),
|
||||
isA<DemandesAideOperationSuccess>()
|
||||
.having((state) => state.message, 'message', 'Demande d\'aide créée avec succès')
|
||||
.having((state) => state.demande, 'demande', tDemande)
|
||||
.having((state) => state.operation, 'operation', TypeOperationDemande.creation),
|
||||
const DemandesAideLoading(),
|
||||
isA<DemandesAideLoaded>(),
|
||||
],
|
||||
verify: (_) {
|
||||
verify(mockCreerDemandeAideUseCase(CreerDemandeAideParams(demande: tDemande)));
|
||||
},
|
||||
);
|
||||
|
||||
blocTest<DemandesAideBloc, DemandesAideState>(
|
||||
'émet [DemandesAideLoading, DemandesAideError] quand la création échoue',
|
||||
build: () {
|
||||
when(mockCreerDemandeAideUseCase(any))
|
||||
.thenAnswer((_) async => const Left(ValidationFailure('Données invalides')));
|
||||
return bloc;
|
||||
},
|
||||
act: (bloc) => bloc.add(CreerDemandeAideEvent(demande: tDemande)),
|
||||
expect: () => [
|
||||
const DemandesAideLoading(),
|
||||
isA<DemandesAideError>()
|
||||
.having((state) => state.message, 'message', 'Données invalides'),
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
group('FiltrerDemandesAideEvent', () {
|
||||
final tDemandes = [
|
||||
_createTestDemandeAide('1', 'Demande urgente', estUrgente: true),
|
||||
_createTestDemandeAide('2', 'Demande normale', estUrgente: false),
|
||||
];
|
||||
|
||||
blocTest<DemandesAideBloc, DemandesAideState>(
|
||||
'filtre les demandes par urgence',
|
||||
build: () => bloc,
|
||||
seed: () => DemandesAideLoaded(
|
||||
demandes: tDemandes,
|
||||
demandesFiltrees: tDemandes,
|
||||
lastUpdated: DateTime.now(),
|
||||
),
|
||||
act: (bloc) => bloc.add(const FiltrerDemandesAideEvent(urgente: true)),
|
||||
expect: () => [
|
||||
isA<DemandesAideLoaded>()
|
||||
.having((state) => state.demandesFiltrees.length, 'demandesFiltrees.length', 1)
|
||||
.having((state) => state.demandesFiltrees.first.estUrgente, 'estUrgente', true)
|
||||
.having((state) => state.filtres.urgente, 'filtres.urgente', true),
|
||||
],
|
||||
);
|
||||
|
||||
blocTest<DemandesAideBloc, DemandesAideState>(
|
||||
'filtre les demandes par mot-clé',
|
||||
build: () => bloc,
|
||||
seed: () => DemandesAideLoaded(
|
||||
demandes: tDemandes,
|
||||
demandesFiltrees: tDemandes,
|
||||
lastUpdated: DateTime.now(),
|
||||
),
|
||||
act: (bloc) => bloc.add(const FiltrerDemandesAideEvent(motCle: 'urgente')),
|
||||
expect: () => [
|
||||
isA<DemandesAideLoaded>()
|
||||
.having((state) => state.demandesFiltrees.length, 'demandesFiltrees.length', 1)
|
||||
.having((state) => state.demandesFiltrees.first.titre, 'titre', 'Demande urgente')
|
||||
.having((state) => state.filtres.motCle, 'filtres.motCle', 'urgente'),
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
group('TrierDemandesAideEvent', () {
|
||||
final tDemandes = [
|
||||
_createTestDemandeAide('1', 'B Demande', dateCreation: DateTime(2023, 1, 2)),
|
||||
_createTestDemandeAide('2', 'A Demande', dateCreation: DateTime(2023, 1, 1)),
|
||||
];
|
||||
|
||||
blocTest<DemandesAideBloc, DemandesAideState>(
|
||||
'trie les demandes par titre croissant',
|
||||
build: () => bloc,
|
||||
seed: () => DemandesAideLoaded(
|
||||
demandes: tDemandes,
|
||||
demandesFiltrees: tDemandes,
|
||||
lastUpdated: DateTime.now(),
|
||||
),
|
||||
act: (bloc) => bloc.add(const TrierDemandesAideEvent(
|
||||
critere: TriDemandes.titre,
|
||||
croissant: true,
|
||||
)),
|
||||
expect: () => [
|
||||
isA<DemandesAideLoaded>()
|
||||
.having((state) => state.demandesFiltrees.first.titre, 'premier titre', 'A Demande')
|
||||
.having((state) => state.demandesFiltrees.last.titre, 'dernier titre', 'B Demande')
|
||||
.having((state) => state.criterieTri, 'criterieTri', TriDemandes.titre)
|
||||
.having((state) => state.triCroissant, 'triCroissant', true),
|
||||
],
|
||||
);
|
||||
|
||||
blocTest<DemandesAideBloc, DemandesAideState>(
|
||||
'trie les demandes par date décroissant',
|
||||
build: () => bloc,
|
||||
seed: () => DemandesAideLoaded(
|
||||
demandes: tDemandes,
|
||||
demandesFiltrees: tDemandes,
|
||||
lastUpdated: DateTime.now(),
|
||||
),
|
||||
act: (bloc) => bloc.add(const TrierDemandesAideEvent(
|
||||
critere: TriDemandes.dateCreation,
|
||||
croissant: false,
|
||||
)),
|
||||
expect: () => [
|
||||
isA<DemandesAideLoaded>()
|
||||
.having((state) => state.demandesFiltrees.first.dateCreation, 'première date', DateTime(2023, 1, 2))
|
||||
.having((state) => state.demandesFiltrees.last.dateCreation, 'dernière date', DateTime(2023, 1, 1))
|
||||
.having((state) => state.criterieTri, 'criterieTri', TriDemandes.dateCreation)
|
||||
.having((state) => state.triCroissant, 'triCroissant', false),
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
group('SelectionnerDemandeAideEvent', () {
|
||||
final tDemandes = [
|
||||
_createTestDemandeAide('1', 'Demande 1'),
|
||||
_createTestDemandeAide('2', 'Demande 2'),
|
||||
];
|
||||
|
||||
blocTest<DemandesAideBloc, DemandesAideState>(
|
||||
'sélectionne une demande',
|
||||
build: () => bloc,
|
||||
seed: () => DemandesAideLoaded(
|
||||
demandes: tDemandes,
|
||||
demandesFiltrees: tDemandes,
|
||||
lastUpdated: DateTime.now(),
|
||||
),
|
||||
act: (bloc) => bloc.add(const SelectionnerDemandeAideEvent(
|
||||
demandeId: '1',
|
||||
selectionne: true,
|
||||
)),
|
||||
expect: () => [
|
||||
isA<DemandesAideLoaded>()
|
||||
.having((state) => state.demandesSelectionnees['1'], 'demande sélectionnée', true)
|
||||
.having((state) => state.nombreDemandesSelectionnees, 'nombre sélectionnées', 1),
|
||||
],
|
||||
);
|
||||
|
||||
blocTest<DemandesAideBloc, DemandesAideState>(
|
||||
'désélectionne une demande',
|
||||
build: () => bloc,
|
||||
seed: () => DemandesAideLoaded(
|
||||
demandes: tDemandes,
|
||||
demandesFiltrees: tDemandes,
|
||||
demandesSelectionnees: const {'1': true},
|
||||
lastUpdated: DateTime.now(),
|
||||
),
|
||||
act: (bloc) => bloc.add(const SelectionnerDemandeAideEvent(
|
||||
demandeId: '1',
|
||||
selectionne: false,
|
||||
)),
|
||||
expect: () => [
|
||||
isA<DemandesAideLoaded>()
|
||||
.having((state) => state.demandesSelectionnees.containsKey('1'), 'demande désélectionnée', false)
|
||||
.having((state) => state.nombreDemandesSelectionnees, 'nombre sélectionnées', 0),
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
group('SelectionnerToutesDemandesAideEvent', () {
|
||||
final tDemandes = [
|
||||
_createTestDemandeAide('1', 'Demande 1'),
|
||||
_createTestDemandeAide('2', 'Demande 2'),
|
||||
];
|
||||
|
||||
blocTest<DemandesAideBloc, DemandesAideState>(
|
||||
'sélectionne toutes les demandes',
|
||||
build: () => bloc,
|
||||
seed: () => DemandesAideLoaded(
|
||||
demandes: tDemandes,
|
||||
demandesFiltrees: tDemandes,
|
||||
lastUpdated: DateTime.now(),
|
||||
),
|
||||
act: (bloc) => bloc.add(const SelectionnerToutesDemandesAideEvent(selectionne: true)),
|
||||
expect: () => [
|
||||
isA<DemandesAideLoaded>()
|
||||
.having((state) => state.demandesSelectionnees.length, 'nombre sélectionnées', 2)
|
||||
.having((state) => state.toutesDemandesSelectionnees, 'toutes sélectionnées', true),
|
||||
],
|
||||
);
|
||||
|
||||
blocTest<DemandesAideBloc, DemandesAideState>(
|
||||
'désélectionne toutes les demandes',
|
||||
build: () => bloc,
|
||||
seed: () => DemandesAideLoaded(
|
||||
demandes: tDemandes,
|
||||
demandesFiltrees: tDemandes,
|
||||
demandesSelectionnees: const {'1': true, '2': true},
|
||||
lastUpdated: DateTime.now(),
|
||||
),
|
||||
act: (bloc) => bloc.add(const SelectionnerToutesDemandesAideEvent(selectionne: false)),
|
||||
expect: () => [
|
||||
isA<DemandesAideLoaded>()
|
||||
.having((state) => state.demandesSelectionnees.isEmpty, 'aucune sélectionnée', true)
|
||||
.having((state) => state.toutesDemandesSelectionnees, 'toutes désélectionnées', false),
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
group('ValiderDemandeAideEvent', () {
|
||||
final tDemande = _createTestDemandeAide('1', 'Demande à valider');
|
||||
|
||||
blocTest<DemandesAideBloc, DemandesAideState>(
|
||||
'émet DemandesAideValidation avec isValid=true quand la validation réussit',
|
||||
build: () {
|
||||
when(mockValiderDemandeAideUseCase(any))
|
||||
.thenAnswer((_) async => const Right(true));
|
||||
return bloc;
|
||||
},
|
||||
act: (bloc) => bloc.add(ValiderDemandeAideEvent(demande: tDemande)),
|
||||
expect: () => [
|
||||
isA<DemandesAideValidation>()
|
||||
.having((state) => state.isValid, 'isValid', true)
|
||||
.having((state) => state.erreurs.isEmpty, 'erreurs vides', true)
|
||||
.having((state) => state.demande, 'demande', tDemande),
|
||||
],
|
||||
);
|
||||
|
||||
blocTest<DemandesAideBloc, DemandesAideState>(
|
||||
'émet DemandesAideValidation avec erreurs quand la validation échoue',
|
||||
build: () {
|
||||
when(mockValiderDemandeAideUseCase(any))
|
||||
.thenAnswer((_) async => const Left(ValidationFailure('Titre requis')));
|
||||
return bloc;
|
||||
},
|
||||
act: (bloc) => bloc.add(ValiderDemandeAideEvent(demande: tDemande)),
|
||||
expect: () => [
|
||||
isA<DemandesAideValidation>()
|
||||
.having((state) => state.isValid, 'isValid', false)
|
||||
.having((state) => state.erreurs['general'], 'erreur générale', 'Titre requis')
|
||||
.having((state) => state.demande, 'demande', tDemande),
|
||||
],
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// Fonction utilitaire pour créer une demande d'aide de test
|
||||
DemandeAide _createTestDemandeAide(
|
||||
String id,
|
||||
String titre, {
|
||||
bool estUrgente = false,
|
||||
DateTime? dateCreation,
|
||||
}) {
|
||||
return DemandeAide(
|
||||
id: id,
|
||||
numeroReference: 'REF-$id',
|
||||
titre: titre,
|
||||
description: 'Description de la $titre',
|
||||
typeAide: TypeAide.aideFinanciereUrgente,
|
||||
statut: StatutAide.brouillon,
|
||||
priorite: PrioriteAide.normale,
|
||||
estUrgente: estUrgente,
|
||||
dateCreation: dateCreation ?? DateTime.now(),
|
||||
dateModification: dateCreation ?? DateTime.now(),
|
||||
organisationId: 'org-1',
|
||||
demandeurId: 'user-1',
|
||||
nomDemandeur: 'John Doe',
|
||||
emailDemandeur: 'john@example.com',
|
||||
telephoneDemandeur: '+225123456789',
|
||||
beneficiaires: const [],
|
||||
evaluations: const [],
|
||||
commentairesInternes: const [],
|
||||
historiqueStatuts: const [],
|
||||
piecesJustificatives: const [],
|
||||
tags: const [],
|
||||
metadonnees: const {},
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user