package med.voll.api.domain.consulta.validaciones;
import jakarta.validation.ValidationException;
import med.voll.api.domain.consulta.dto.DatosAgendarConsulta;
import org.springframework.stereotype.Component;
import java.time.DayOfWeek;
@Component
public class HorarioDeFuncionamientoClinica implements ValidadorDeConsultas{
public void validar(DatosAgendarConsulta datos) {
var domingo = DayOfWeek.SUNDAY.equals(datos.fecha().getDayOfWeek());
var antesdDeApertura=datos.fecha().getHour()<7;
var despuesDeCierre=datos.fecha().getHour() >=19;
if(domingo || antesdDeApertura || despuesDeCierre){
throw new ValidationException("El horario de atención de la clínica es de lunes a sábado, de 07:00 a 19:00 horas");
}
}
}
package med.voll.api.domain.consulta.validaciones;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
import java.time.LocalDateTime;
import jakarta.validation.ValidationException;
import med.voll.api.domain.consulta.dto.DatosAgendarConsulta;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
class HorarioDeFuncionamientoClinicaTest {
private HorarioDeFuncionamientoClinica validador;
private DatosAgendarConsulta datos;
@BeforeEach
void setup() {
validador = new HorarioDeFuncionamientoClinica();
datos = mock(DatosAgendarConsulta.class); // Mockeamos el DTO de entrada
}
@Test
@DisplayName("Debería lanzar excepción antes de las 7:00 AM")
void validarEscenarioAntesApertura() {
var lunesMuyTemprano = LocalDateTime.now().with(java.time.temporal.TemporalAdjusters.next(java.time.DayOfWeek.MONDAY)).withHour(6);
when(datos.fecha()).thenReturn(lunesMuyTemprano);
assertThrows(ValidationException.class, () -> validador.validar(datos));
}
@Test
@DisplayName("Debería lanzar excepción después de las 7:00 PM")
void validarEscenarioDespuesCierre() {
var lunesMuyTarde = LocalDateTime.now().with(java.time.temporal.TemporalAdjusters.next(java.time.DayOfWeek.MONDAY)).withHour(20);
when(datos.fecha()).thenReturn(lunesMuyTarde);
assertThrows(ValidationException.class, () -> validador.validar(datos));
}
@Test
@DisplayName("Debería permitir agendar exactamente a las 07:00:00")
void validarEscenarioHoraExactaApertura() {
// Un lunes a las 07:00:00
var lunesSieteAM = LocalDateTime.now()
.with(java.time.temporal.TemporalAdjusters.next(java.time.DayOfWeek.MONDAY))
.withHour(7).withMinute(0).withSecond(0);
when(datos.fecha()).thenReturn(lunesSieteAM);
assertDoesNotThrow(() -> validador.validar(datos));
}
@Test
@DisplayName("Debería lanzar excepción si los datos o la fecha son nulos")
void validarEscenarioNulo() {
// Caso 1: Datos es null
assertThrows(NullPointerException.class, () -> validador.validar(null));
// Caso 2: La fecha dentro de datos es null
when(datos.fecha()).thenReturn(null);
assertThrows(NullPointerException.class, () -> validador.validar(datos));
}
@ParameterizedTest
@ValueSource(ints = {0, 5, 6, 20, 23}) // Horas inválidas
@DisplayName("Debería fallar para todas las horas fuera del rango 7-19")
void validarHorariosInvalidosParametrizados(int hora) {
var fechaInvalida = LocalDateTime.now()
.with(java.time.temporal.TemporalAdjusters.next(java.time.DayOfWeek.MONDAY))
.withHour(hora);
when(datos.fecha()).thenReturn(fechaInvalida);
assertThrows(ValidationException.class, () -> validador.validar(datos));
}
@Test
void verificarInteraccion() {
var fecha = LocalDateTime.now().withHour(10);
when(datos.fecha()).thenReturn(fecha);
validador.validar(datos);
// Verifica que el método fecha() fue invocado al menos una vez
verify(datos, atLeastOnce()).fecha();
}
}