Agrego frontend app

This commit is contained in:
Pablo
2026-08-22 19:08:19 -03:00
parent 824e092b29
commit 2d0797e627
254 changed files with 37231 additions and 0 deletions
@@ -0,0 +1,130 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:gimnasio_soma/features/horarios/domain/entities/alcance.dart';
import 'package:gimnasio_soma/features/horarios/domain/entities/dia_especial.dart';
import 'package:gimnasio_soma/features/horarios/domain/entities/horario_semana.dart';
import 'package:gimnasio_soma/features/horarios/domain/entities/planificacion_futura.dart';
import 'package:gimnasio_soma/features/horarios/domain/repositories/horarios_repository.dart';
import 'package:gimnasio_soma/features/horarios/presentation/providers/horarios_provider.dart';
/// Repositorio falso que cuenta cuántas veces se llama a cada operación de
/// lectura. Así verificamos que una escritura dispara una **relectura** de las
/// vistas derivadas (que es justo lo que arregla la desincronización).
class _FakeHorariosRepository implements HorariosRepository {
int obtenerSemanaCalls = 0;
int listarEspecialesCalls = 0;
int futurosCalls = 0;
@override
Future<SemanaHorarios> obtenerSemana(DateTime weekStart) async {
obtenerSemanaCalls++;
return SemanaHorarios.fromResponse(weekStart, const {});
}
@override
Future<void> guardarDia({
required DateTime fecha,
required bool esEspecial,
String? motivo,
required List<Map<String, dynamic>> bloques,
DateTime? validoDesde,
Alcance? alcance,
}) async {}
@override
Future<void> eliminarDiaEspecial(DateTime fecha) async {}
@override
Future<List<DiaEspecialResumen>> listarDiasEspeciales({int dias = 90}) async {
listarEspecialesCalls++;
return const [];
}
@override
Future<List<PlanificacionFutura>> futurosParaDiaSemana({
required int diaSemana,
required DateTime desde,
int meses = 6,
}) async {
futurosCalls++;
return const [];
}
@override
Future<int> contarHuerfanasDesde(DateTime instante) async => 0;
}
void main() {
late _FakeHorariosRepository repo;
late ProviderContainer container;
setUp(() {
repo = _FakeHorariosRepository();
container = ProviderContainer(
overrides: [horariosRepositoryProvider.overrideWithValue(repo)],
);
});
tearDown(() => container.dispose());
// Abre las dos vistas derivadas una vez. Tras esto listarEspecialesCalls == 1
// y futurosCalls == 7 (el provider de cambios consulta los 7 días de la
// semana).
Future<void> abrirVistasDerivadas() async {
container.read(diasEspecialesProvider.notifier); // dispara load()
await container.read(diasCambioProvider.future);
await Future<void>.delayed(Duration.zero); // deja resolver el load()
}
// Vuelve a leer las vistas derivadas para forzar el recómputo si fueron
// invalidadas.
Future<void> releerVistasDerivadas() async {
container.read(diasEspecialesProvider.notifier);
await container.read(diasCambioProvider.future);
await Future<void>.delayed(Duration.zero);
}
test('guardarDia invalida especiales y cambios (no solo la semana)', () async {
await container
.read(horariosProvider.notifier)
.cargarSemana(DateTime(2026, 6, 22));
await abrirVistasDerivadas();
final especialesAntes = repo.listarEspecialesCalls;
final cambiosAntes = repo.futurosCalls;
await container.read(horariosProvider.notifier).guardarDia(
fecha: DateTime(2026, 6, 22),
esEspecial: true,
bloques: const [],
);
await releerVistasDerivadas();
// Si la invalidación no se propagara, estas relecturas devolverían el valor
// cacheado y los contadores no se moverían: ese era el bug.
expect(repo.listarEspecialesCalls, greaterThan(especialesAntes),
reason: 'la lista de días especiales debería recargarse tras guardar');
expect(repo.futurosCalls, greaterThan(cambiosAntes),
reason: 'los cambios del calendario deberían recargarse tras guardar');
});
test('eliminarDiaEspecial invalida especiales y cambios', () async {
await container
.read(horariosProvider.notifier)
.cargarSemana(DateTime(2026, 6, 22));
await abrirVistasDerivadas();
final especialesAntes = repo.listarEspecialesCalls;
final cambiosAntes = repo.futurosCalls;
await container
.read(horariosProvider.notifier)
.eliminarDiaEspecial(DateTime(2026, 6, 22));
await releerVistasDerivadas();
expect(repo.listarEspecialesCalls, greaterThan(especialesAntes));
expect(repo.futurosCalls, greaterThan(cambiosAntes));
});
}