223 lines
7.1 KiB
Dart
223 lines
7.1 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:hidalyx_drluiscastro/core/widgets/medical_modal.dart';
|
|
import 'package:hidalyx_drluiscastro/features/patient_search/data/models/patient_search_item_model.dart';
|
|
import 'package:hidalyx_drluiscastro/features/patient_search/data/services/patient_search_service.dart';
|
|
import 'package:hidalyx_drluiscastro/features/patient_search/presentation/store/patient_search_store.dart';
|
|
import 'package:hidalyx_drluiscastro/features/patient_search/presentation/widgets/search_input_bar.dart';
|
|
|
|
class MockPatientSearchService extends PatientSearchService {
|
|
@override
|
|
Future<List<PatientSearchItemModel>> searchPatients(String rawQuery, {int limit = 25}) async {
|
|
if (rawQuery == 'error') {
|
|
throw Exception('Simulated network error');
|
|
}
|
|
if (rawQuery == 'Carlos') {
|
|
return [
|
|
const PatientSearchItemModel(
|
|
id: 13717,
|
|
nombre: 'CARLOS JUAN',
|
|
apellido: 'ARIAS GOMEZ',
|
|
cedula: '001-1234567-8',
|
|
telefono: '809-555-0101',
|
|
edad: '45',
|
|
sexo: 'M',
|
|
fecUltcon: '15/09/2026',
|
|
seguro: 'SENASA',
|
|
motCons: 'Control Rutinario',
|
|
),
|
|
];
|
|
}
|
|
return [];
|
|
}
|
|
}
|
|
|
|
void main() {
|
|
group('PatientSearchItemModel', () {
|
|
test('correctly parses JSON and provides full name', () {
|
|
final json = {
|
|
'id': '123',
|
|
'nombre': 'JUAN',
|
|
'apellido': 'PEREZ',
|
|
'cedula': '001-0000000-0',
|
|
'telefono': '8090000000',
|
|
'edad': '30',
|
|
'sexo': 'M',
|
|
'fec_ultcon': '01/01/2026',
|
|
'seguro': 'HUMANO',
|
|
'mot_cons': 'Chequeo',
|
|
};
|
|
|
|
final model = PatientSearchItemModel.fromJson(json);
|
|
expect(model.id, equals(123));
|
|
expect(model.fullName, equals('JUAN PEREZ'));
|
|
expect(model.cedula, equals('001-0000000-0'));
|
|
});
|
|
});
|
|
|
|
group('PatientSearchStore', () {
|
|
test('successful search populates results and updates hasSearched', () async {
|
|
final store = PatientSearchStore(searchService: MockPatientSearchService());
|
|
expect(store.hasSearched, isFalse);
|
|
expect(store.resultsCount, equals(0));
|
|
|
|
await store.search('Carlos');
|
|
|
|
expect(store.hasSearched, isTrue);
|
|
expect(store.isLoading, isFalse);
|
|
expect(store.errorMessage, isNull);
|
|
expect(store.resultsCount, equals(1));
|
|
expect(store.results.first.fullName, equals('CARLOS JUAN ARIAS GOMEZ'));
|
|
});
|
|
|
|
test('error handling updates errorMessage', () async {
|
|
final store = PatientSearchStore(searchService: MockPatientSearchService());
|
|
await store.search('error');
|
|
|
|
expect(store.hasSearched, isTrue);
|
|
expect(store.isLoading, isFalse);
|
|
expect(store.errorMessage, contains('Simulated network error'));
|
|
expect(store.resultsCount, equals(0));
|
|
});
|
|
|
|
test('clear resets the store state', () async {
|
|
final store = PatientSearchStore(searchService: MockPatientSearchService());
|
|
await store.search('Carlos');
|
|
expect(store.resultsCount, equals(1));
|
|
|
|
store.clear();
|
|
expect(store.resultsCount, equals(0));
|
|
expect(store.hasSearched, isFalse);
|
|
expect(store.query, isEmpty);
|
|
});
|
|
});
|
|
|
|
group('SearchInputBar widget', () {
|
|
testWidgets('triggers onSearch ONLY when Enter is pressed or Buscar is clicked', (tester) async {
|
|
String? searchedQuery;
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: Scaffold(
|
|
body: SearchInputBar(
|
|
onSearch: (q) => searchedQuery = q,
|
|
onClear: () {},
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
// Typing alone should not trigger search
|
|
await tester.enterText(find.byType(TextField), 'Carlos Arias');
|
|
await tester.pump();
|
|
expect(searchedQuery, isNull);
|
|
|
|
// Submitting via Enter key
|
|
await tester.testTextInput.receiveAction(TextInputAction.search);
|
|
await tester.pump();
|
|
expect(searchedQuery, equals('Carlos Arias'));
|
|
});
|
|
});
|
|
|
|
group('MedicalModalDialog and showMedicalModal behavior', () {
|
|
testWidgets('modal does NOT close when tapping outside (barrierDismissible is false)', (tester) async {
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: Scaffold(
|
|
body: Builder(
|
|
builder: (context) => ElevatedButton(
|
|
onPressed: () {
|
|
showMedicalModal(
|
|
context: context,
|
|
builder: (_) => const Text('Modal Body'),
|
|
);
|
|
},
|
|
child: const Text('Open Modal'),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.tap(find.text('Open Modal'));
|
|
await tester.pumpAndSettle();
|
|
expect(find.text('Modal Body'), findsOneWidget);
|
|
|
|
// Tap on the outside barrier (top-left corner outside dialog)
|
|
await tester.tapAt(const Offset(5, 5));
|
|
await tester.pumpAndSettle();
|
|
|
|
// Modal MUST still be present
|
|
expect(find.text('Modal Body'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('modal closes when close icon (X) button is clicked', (tester) async {
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: Scaffold(
|
|
body: Builder(
|
|
builder: (context) => ElevatedButton(
|
|
onPressed: () {
|
|
showMedicalModal(
|
|
context: context,
|
|
builder: (_) => const MedicalModalDialog(
|
|
title: 'Test Modal',
|
|
child: Text('Content'),
|
|
),
|
|
);
|
|
},
|
|
child: const Text('Open Modal'),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.tap(find.text('Open Modal'));
|
|
await tester.pumpAndSettle();
|
|
expect(find.text('Test Modal'), findsOneWidget);
|
|
|
|
// Click the top-right close button (X)
|
|
await tester.tap(find.byTooltip('Cerrar (Esc)'));
|
|
await tester.pumpAndSettle();
|
|
|
|
// Modal must be closed
|
|
expect(find.text('Test Modal'), findsNothing);
|
|
});
|
|
|
|
testWidgets('modal closes when ESC key is pressed', (tester) async {
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: Scaffold(
|
|
body: Builder(
|
|
builder: (context) => ElevatedButton(
|
|
onPressed: () {
|
|
showMedicalModal(
|
|
context: context,
|
|
builder: (_) => const MedicalModalDialog(
|
|
title: 'Test Modal',
|
|
child: Text('Content'),
|
|
),
|
|
);
|
|
},
|
|
child: const Text('Open Modal'),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.tap(find.text('Open Modal'));
|
|
await tester.pumpAndSettle();
|
|
expect(find.text('Test Modal'), findsOneWidget);
|
|
|
|
// Send ESC key
|
|
await tester.sendKeyEvent(LogicalKeyboardKey.escape);
|
|
await tester.pumpAndSettle();
|
|
|
|
// Modal must be closed
|
|
expect(find.text('Test Modal'), findsNothing);
|
|
});
|
|
});
|
|
}
|