Files
hidalyx-drluiscastro/test/features/config_test.dart
T
2026-09-21 16:33:51 -04:00

352 lines
12 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/config/data/services/config_service.dart';
import 'package:hidalyx_drluiscastro/features/config/presentation/store/config_store.dart';
import 'package:hidalyx_drluiscastro/features/config/presentation/views/config_modal_view.dart';
import 'package:hidalyx_drluiscastro/features/dashboard/data/models/doctor_info_model.dart';
class MockConfigService extends ConfigService {
DoctorInfoModel currentConfig;
bool shouldThrowOnSave = false;
bool shouldThrowOnLoad = false;
MockConfigService({
DoctorInfoModel? initialConfig,
}) : currentConfig = initialConfig ??
const DoctorInfoModel(
id: 1,
nombreDoctor: 'Dr. Luis A. Castro Sosa',
especialidad: 'Cirujano Urólogo',
descripEspecialidad: 'Enfermedades Vías Urinarias, Riñones',
descripGeneral: 'Santiago, R.D. Tel: 809-583-2394',
);
@override
Future<DoctorInfoModel> getConfig() async {
if (shouldThrowOnLoad) {
throw Exception('Error al cargar configuración de prueba');
}
return currentConfig;
}
@override
Future<DoctorInfoModel> updateConfig(DoctorInfoModel model) async {
if (shouldThrowOnSave) {
throw Exception('Error al guardar configuración de prueba');
}
currentConfig = model.copyWith(id: 1);
return currentConfig;
}
}
void main() {
group('DoctorInfoModel Serialization & Immutability', () {
test('serializes and deserializes properly from Directus format', () {
final json = {
'id': 1,
'nombre_doctor': 'Dr. Luis A. Castro Sosa',
'especialidad': 'Cirujano Urólogo',
'descrip_especialidad': 'Urología Oncológica y Laparoscopía',
'descrip_general': 'Consultorio 204, Santiago. Tel: 809-555-0100',
};
final model = DoctorInfoModel.fromJson(json);
expect(model.id, equals(1));
expect(model.nombreDoctor, equals('Dr. Luis A. Castro Sosa'));
expect(model.especialidad, equals('Cirujano Urólogo'));
expect(model.descripEspecialidad, equals('Urología Oncológica y Laparoscopía'));
expect(model.descripGeneral, equals('Consultorio 204, Santiago. Tel: 809-555-0100'));
// toJson without ID for Directus PATCH singleton
final jsonWithoutId = model.toJson();
expect(jsonWithoutId.containsKey('id'), isFalse);
expect(jsonWithoutId['nombre_doctor'], equals('Dr. Luis A. Castro Sosa'));
expect(jsonWithoutId['especialidad'], equals('Cirujano Urólogo'));
// toJson with ID
final jsonWithId = model.toJson(includeId: true);
expect(jsonWithId['id'], equals(1));
});
test('copyWith properly modifies target fields while preserving others', () {
const original = DoctorInfoModel(
id: 1,
nombreDoctor: 'Dr. Luis Castro',
especialidad: 'Urólogo',
descripEspecialidad: 'General',
descripGeneral: 'Santiago',
);
final updated = original.copyWith(
especialidad: 'Urología Robótica',
);
expect(updated.id, equals(1));
expect(updated.nombreDoctor, equals('Dr. Luis Castro'));
expect(updated.especialidad, equals('Urología Robótica'));
expect(updated.descripEspecialidad, equals('General'));
expect(updated.descripGeneral, equals('Santiago'));
});
});
group('ConfigStore State Management & Validation', () {
test('validation requires nombreDoctor and especialidad', () {
final mockService = MockConfigService();
final store = ConfigStore(configService: mockService);
expect(store.isValid, isFalse);
store.nombreDoctor = 'Dr. Luis Castro';
expect(store.isValid, isFalse);
store.especialidad = 'Cirujano Urólogo';
expect(store.isValid, isTrue);
store.nombreDoctor = ' ';
expect(store.isValid, isFalse);
});
test('loadConfig successfully loads data into store observables', () async {
final mockService = MockConfigService();
final store = ConfigStore(configService: mockService);
expect(store.isLoading, isFalse);
final loadFuture = store.loadConfig();
expect(store.isLoading, isTrue);
await loadFuture;
expect(store.isLoading, isFalse);
expect(store.id, equals(1));
expect(store.nombreDoctor, equals('Dr. Luis A. Castro Sosa'));
expect(store.especialidad, equals('Cirujano Urólogo'));
expect(store.errorMessage, isNull);
});
test('loadConfig sets errorMessage on failure', () async {
final mockService = MockConfigService()..shouldThrowOnLoad = true;
final store = ConfigStore(configService: mockService);
await store.loadConfig();
expect(store.isLoading, isFalse);
expect(store.errorMessage, isNotNull);
expect(store.errorMessage, contains('Error al cargar configuración'));
});
test('saveConfig validates and updates via service', () async {
final mockService = MockConfigService();
final store = ConfigStore(configService: mockService);
// Attempt save with invalid state
final invalidResult = await store.saveConfig();
expect(invalidResult, isNull);
expect(store.errorMessage, isNotNull);
// Set valid state and save
store.nombreDoctor = 'Dr. Juan Perez';
store.especialidad = 'Cardiólogo';
store.descripEspecialidad = 'Arritmias y Marcapasos';
store.descripGeneral = 'Clínica Corominas';
final savedResult = await store.saveConfig();
expect(savedResult, isNotNull);
expect(savedResult!.nombreDoctor, equals('Dr. Juan Perez'));
expect(savedResult.especialidad, equals('Cardiólogo'));
expect(store.successMessage, isNotNull);
expect(store.isSaving, isFalse);
expect(store.errorMessage, isNull);
});
test('saveConfig handles service error gracefully', () async {
final mockService = MockConfigService()..shouldThrowOnSave = true;
final store = ConfigStore(configService: mockService);
store.nombreDoctor = 'Dr. Luis Castro';
store.especialidad = 'Urología';
final result = await store.saveConfig();
expect(result, isNull);
expect(store.isSaving, isFalse);
expect(store.errorMessage, contains('Error al guardar configuración'));
});
});
group('ConfigModalView Widget Tests', () {
testWidgets('renders all fields and sections properly', (tester) async {
final mockService = MockConfigService();
final store = ConfigStore(configService: mockService);
await store.loadConfig();
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: ConfigModalView(
store: store,
),
),
),
);
await tester.pumpAndSettle();
// Check titles & subtitles
expect(find.text('Configuración del Consultorio'), findsOneWidget);
expect(find.text('Identidad del Profesional'), findsOneWidget);
expect(find.text('Áreas de Enfoque y Subespecialidades'), findsOneWidget);
expect(find.text('Datos del Consultorio y Contacto'), findsOneWidget);
// Check buttons and footer elements
expect(find.text('Cancelar'), findsOneWidget);
expect(find.text('Guardar Configuración'), findsOneWidget);
expect(find.text('ESC para salir'), findsOneWidget);
// Check populated initial values
expect(find.text('Dr. Luis A. Castro Sosa'), findsOneWidget);
expect(find.text('Cirujano Urólogo'), findsOneWidget);
});
testWidgets('footer container has established padding separating buttons from extremities', (tester) async {
final mockService = MockConfigService();
final store = ConfigStore(configService: mockService);
await store.loadConfig();
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: ConfigModalView(
store: store,
),
),
),
);
await tester.pumpAndSettle();
// Find the footer Container that holds the buttons and ESC hint
final footerFinder = find.ancestor(
of: find.text('Guardar Configuración'),
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('cancels and closes when Cancelar button is pressed', (tester) async {
final mockService = MockConfigService();
final store = ConfigStore(configService: mockService);
await store.loadConfig();
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: Builder(
builder: (ctx) => ElevatedButton(
onPressed: () => showMedicalModal(
context: ctx,
builder: (_) => ConfigModalView(store: store),
),
child: const Text('Abrir Modal'),
),
),
),
),
);
// Open modal
await tester.tap(find.text('Abrir Modal'));
await tester.pumpAndSettle();
expect(find.text('Configuración del Consultorio'), findsOneWidget);
// Tap Cancelar
await tester.tap(find.text('Cancelar'));
await tester.pumpAndSettle();
// Modal is dismissed
expect(find.text('Configuración del Consultorio'), findsNothing);
});
testWidgets('closes modal when ESC key is pressed', (tester) async {
final mockService = MockConfigService();
final store = ConfigStore(configService: mockService);
await store.loadConfig();
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: Builder(
builder: (ctx) => ElevatedButton(
onPressed: () => showMedicalModal(
context: ctx,
builder: (_) => ConfigModalView(store: store),
),
child: const Text('Abrir Modal'),
),
),
),
),
);
// Open modal
await tester.tap(find.text('Abrir Modal'));
await tester.pumpAndSettle();
expect(find.text('Configuración del Consultorio'), findsOneWidget);
// Simulate ESC key
await tester.sendKeyEvent(LogicalKeyboardKey.escape);
await tester.pumpAndSettle();
// Modal must be dismissed via ESC
expect(find.text('Configuración del Consultorio'), findsNothing);
});
testWidgets('saves modified configuration and triggers onSaved callback', (tester) async {
final mockService = MockConfigService();
final store = ConfigStore(configService: mockService);
await store.loadConfig();
DoctorInfoModel? savedModel;
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: Builder(
builder: (ctx) => ElevatedButton(
onPressed: () => showMedicalModal(
context: ctx,
builder: (_) => ConfigModalView(
store: store,
onSaved: (m) => savedModel = m,
),
),
child: const Text('Abrir Modal'),
),
),
),
),
);
// Open modal
await tester.tap(find.text('Abrir Modal'));
await tester.pumpAndSettle();
// Enter updated doctor name
final nameField = find.widgetWithText(TextField, 'Dr. Luis A. Castro Sosa');
await tester.enterText(nameField, 'Dr. Luis Alberto Castro');
await tester.pumpAndSettle();
// Tap Guardar
await tester.tap(find.text('Guardar Configuración'));
await tester.pumpAndSettle();
// Verify callback was called with updated name and modal closed
expect(savedModel, isNotNull);
expect(savedModel!.nombreDoctor, equals('Dr. Luis Alberto Castro'));
expect(find.text('Configuración del Consultorio'), findsNothing);
expect(find.text('Configuración del consultorio guardada correctamente'), findsOneWidget);
});
});
}