first commit
This commit is contained in:
@@ -0,0 +1,272 @@
|
||||
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/dashboard/data/models/patient_summary_model.dart';
|
||||
import 'package:hidalyx_drluiscastro/features/dashboard/data/services/dashboard_service.dart';
|
||||
import 'package:hidalyx_drluiscastro/features/dashboard/presentation/views/appointments_modal_view.dart';
|
||||
import 'package:hidalyx_drluiscastro/features/dashboard/presentation/widgets/today_appointments_card.dart';
|
||||
|
||||
class MockDashboardService extends DashboardService {
|
||||
final Map<String, List<PatientSummaryModel>> appointmentsByDate;
|
||||
|
||||
MockDashboardService({Map<String, List<PatientSummaryModel>>? data})
|
||||
: appointmentsByDate = data ?? {};
|
||||
|
||||
String _formatKey(DateTime d) {
|
||||
final day = d.day.toString().padLeft(2, '0');
|
||||
final month = d.month.toString().padLeft(2, '0');
|
||||
final year = d.year.toString();
|
||||
return '$day/$month/$year';
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<PatientSummaryModel>> getAppointmentsByDate(DateTime date, {int limit = 100}) async {
|
||||
final key = _formatKey(date);
|
||||
return appointmentsByDate[key] ?? [];
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<PatientSummaryModel>> getTodayAppointments({int limit = 5}) async {
|
||||
return getAppointmentsByDate(DateTime.now(), limit: limit);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
group('AppointmentsModalView Tests', () {
|
||||
final now = DateTime.now();
|
||||
final todayDay = now.day.toString().padLeft(2, '0');
|
||||
final todayMonth = now.month.toString().padLeft(2, '0');
|
||||
final todayKey = '$todayDay/$todayMonth/${now.year}';
|
||||
|
||||
final List<PatientSummaryModel> mockTodayPatients = [
|
||||
const PatientSummaryModel(
|
||||
id: 101,
|
||||
nombre: 'CARLOS',
|
||||
apellido: 'MARTINEZ',
|
||||
cedula: '001-9999999-1',
|
||||
telefono: '809-555-1122',
|
||||
fecReg: '20/09/2026',
|
||||
fecProxCita: '20/09/2026',
|
||||
seguro: 'Sí',
|
||||
motCons: 'Seguimiento postquirúrgico',
|
||||
),
|
||||
const PatientSummaryModel(
|
||||
id: 102,
|
||||
nombre: 'ANA',
|
||||
apellido: 'PERDOMO',
|
||||
cedula: '402-8888888-2',
|
||||
telefono: '809-555-3344',
|
||||
fecReg: '20/09/2026',
|
||||
fecProxCita: '20/09/2026',
|
||||
seguro: 'No',
|
||||
motCons: 'Chequeo urológico anual',
|
||||
),
|
||||
];
|
||||
|
||||
final otherDate = DateTime(2026, 10, 25);
|
||||
const otherDateKey = '25/10/2026';
|
||||
final List<PatientSummaryModel> mockOtherPatients = [
|
||||
const PatientSummaryModel(
|
||||
id: 201,
|
||||
nombre: 'RAMON',
|
||||
apellido: 'VALDEZ',
|
||||
cedula: '001-7777777-3',
|
||||
telefono: '809-555-5566',
|
||||
fecReg: '25/10/2026',
|
||||
fecProxCita: '25/10/2026',
|
||||
seguro: 'Sí',
|
||||
motCons: 'Control de litiasis renal',
|
||||
),
|
||||
];
|
||||
|
||||
late MockDashboardService mockService;
|
||||
|
||||
setUp(() {
|
||||
mockService = MockDashboardService(data: {
|
||||
todayKey: mockTodayPatients,
|
||||
otherDateKey: mockOtherPatients,
|
||||
});
|
||||
});
|
||||
|
||||
testWidgets('renders modal header, footer, and active filter indicator as "Hoy"', (tester) async {
|
||||
tester.view.physicalSize = const Size(1280, 900);
|
||||
tester.view.devicePixelRatio = 1.0;
|
||||
addTearDown(() => tester.view.resetPhysicalSize());
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Scaffold(
|
||||
body: AppointmentsModalView(
|
||||
service: mockService,
|
||||
initialDate: now,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Check titles & subtitles
|
||||
expect(find.text('Agenda de Citas Médicas'), findsOneWidget);
|
||||
expect(find.text('Consulte y gestione los pacientes citados por fecha de consulta'), findsOneWidget);
|
||||
|
||||
// Verify that when filtered by today, it displays "Hoy (DD/MM/YYYY)"
|
||||
expect(find.textContaining('Hoy ($todayKey)'), findsOneWidget);
|
||||
|
||||
// Verify patient records for today are rendered
|
||||
expect(find.text('CARLOS MARTINEZ'), findsOneWidget);
|
||||
expect(find.text('ANA PERDOMO'), findsOneWidget);
|
||||
expect(find.text('Seguimiento postquirúrgico'), findsOneWidget);
|
||||
expect(find.text('Chequeo urológico anual'), findsOneWidget);
|
||||
|
||||
// Verify footer buttons & chip
|
||||
expect(find.text('ESC para salir'), findsOneWidget);
|
||||
expect(find.text('Cerrar'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('displays specific date filter when viewing date other than today', (tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Scaffold(
|
||||
body: AppointmentsModalView(
|
||||
service: mockService,
|
||||
initialDate: otherDate,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Should show the specific date without "Hoy" in the filter badge
|
||||
expect(find.textContaining('Filtro: 25/10/2026'), findsOneWidget);
|
||||
expect(find.textContaining('Hoy'), findsWidgets); // The "Hoy" quick button is present, but the filter text is 25/10/2026
|
||||
|
||||
// Verify patient for that specific date
|
||||
expect(find.text('RAMON VALDEZ'), findsOneWidget);
|
||||
expect(find.text('Control de litiasis renal'), findsOneWidget);
|
||||
expect(find.text('CARLOS MARTINEZ'), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('navigation buttons change date and "Hoy" button resets to current day', (tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Scaffold(
|
||||
body: AppointmentsModalView(
|
||||
service: mockService,
|
||||
initialDate: otherDate,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.textContaining('Filtro: 25/10/2026'), findsOneWidget);
|
||||
|
||||
// Tap Día siguiente chevron
|
||||
await tester.tap(find.byTooltip('Día siguiente'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.textContaining('Filtro: 26/10/2026'), findsOneWidget);
|
||||
expect(find.text('No hay citas registradas para el 26/10/2026'), findsOneWidget);
|
||||
|
||||
// Tap Día anterior chevron twice
|
||||
await tester.tap(find.byTooltip('Día anterior'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.textContaining('Filtro: 25/10/2026'), findsOneWidget);
|
||||
|
||||
// Tap "Hoy" button to return to today
|
||||
await tester.tap(find.text('Hoy'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Must now show "Hoy (DD/MM/YYYY)" again
|
||||
expect(find.textContaining('Filtro: Hoy ($todayKey)'), findsOneWidget);
|
||||
expect(find.text('CARLOS MARTINEZ'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('footer container adheres to institutional padding (horizontal: 20, vertical: 12)', (tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Scaffold(
|
||||
body: AppointmentsModalView(
|
||||
service: mockService,
|
||||
initialDate: now,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final footerFinder = find.ancestor(
|
||||
of: find.text('Cerrar'),
|
||||
matching: find.byType(Container),
|
||||
);
|
||||
expect(footerFinder, findsWidgets);
|
||||
|
||||
final footerContainer = tester.widget<Container>(footerFinder.first);
|
||||
expect(footerContainer.padding, equals(const EdgeInsets.symmetric(horizontal: 20, vertical: 12)));
|
||||
});
|
||||
|
||||
testWidgets('closes modal with Cerrar button and with ESC key', (tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Scaffold(
|
||||
body: Builder(
|
||||
builder: (ctx) => ElevatedButton(
|
||||
onPressed: () => showMedicalModal(
|
||||
context: ctx,
|
||||
builder: (_) => AppointmentsModalView(
|
||||
service: mockService,
|
||||
initialDate: now,
|
||||
),
|
||||
),
|
||||
child: const Text('Abrir Citas'),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// 1. Open modal and close via Cerrar button
|
||||
await tester.tap(find.text('Abrir Citas'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Agenda de Citas Médicas'), findsOneWidget);
|
||||
|
||||
await tester.tap(find.text('Cerrar'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Agenda de Citas Médicas'), findsNothing);
|
||||
|
||||
// 2. Open modal and close via ESC key
|
||||
await tester.tap(find.text('Abrir Citas'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Agenda de Citas Médicas'), findsOneWidget);
|
||||
|
||||
await tester.sendKeyEvent(LogicalKeyboardKey.escape);
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Agenda de Citas Médicas'), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('TodayAppointmentsCard item tap invokes onPatientTap callback', (tester) async {
|
||||
PatientSummaryModel? tappedPatient;
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Scaffold(
|
||||
body: TodayAppointmentsCard(
|
||||
appointments: mockTodayPatients,
|
||||
onPatientTap: (p) => tappedPatient = p,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('CARLOS MARTINEZ'), findsOneWidget);
|
||||
|
||||
await tester.tap(find.text('CARLOS MARTINEZ'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(tappedPatient, isNotNull);
|
||||
expect(tappedPatient!.id, equals(101));
|
||||
expect(tappedPatient!.nombre, equals('CARLOS'));
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user