Files
hidalyx-drluiscastro/test/features/patient_search_test.dart
T

223 lines
7.1 KiB
Dart
Raw Normal View History

2026-09-21 16:33:51 -04:00
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);
});
});
}