Skip to content

Commit

Permalink
Merge branch 'feature/506399-MostrarHorarioGasolinera' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
HERRERA99 committed Nov 6, 2024
2 parents deda6ca + 6ece3a8 commit 06ae220
Show file tree
Hide file tree
Showing 14 changed files with 616 additions and 164 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package es.unican.gasolineras.activities.common;

import static androidx.test.espresso.Espresso.onData;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;


import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.anything;
import static org.hamcrest.CoreMatchers.is;
import static org.mockito.Mockito.when;
import static es.unican.gasolineras.utils.Matchers.withTextColor;
import static es.unican.gasolineras.utils.MockRepositories.getTestRepository;

import android.content.Context;

import androidx.test.espresso.DataInteraction;
import androidx.test.ext.junit.rules.ActivityScenarioRule;
import androidx.test.platform.app.InstrumentationRegistry;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.time.LocalDateTime;

import dagger.hilt.android.testing.BindValue;
import dagger.hilt.android.testing.HiltAndroidRule;
import dagger.hilt.android.testing.HiltAndroidTest;
import dagger.hilt.android.testing.UninstallModules;
import es.unican.gasolineras.R;
import es.unican.gasolineras.activities.main.MainView;
import es.unican.gasolineras.common.TimeProvider;
import es.unican.gasolineras.injection.RepositoriesModule;
import es.unican.gasolineras.repository.IGasolinerasRepository;

@UninstallModules(RepositoriesModule.class)
@HiltAndroidTest
public class MostrarHorarioGasolineraUITest {
@Rule(order = 0) // the Hilt rule must execute first
public HiltAndroidRule hiltRule = new HiltAndroidRule(this);
@Rule(order = 1)
public ActivityScenarioRule<MainView> activityRule = new ActivityScenarioRule<>(MainView.class);

// I need the context to access resources, such as the json with test gas stations
final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();

// Mock repository that provides data from a JSON file instead of downloading it from the internet.
@BindValue
public final IGasolinerasRepository repository = getTestRepository(context, R.raw.gasolineras_prueba_horarios);

@Mock
private static TimeProvider mockObtenerDiaHora;

@Before
public void inicializa() {
//inicializo los mocks
MockitoAnnotations.openMocks(this);

when(mockObtenerDiaHora.obtenerDiaHora()).thenReturn(LocalDateTime.of(2024, 10, 30, 18, 0, 0));
}

@Test
public void test24H() {
//comprueba la direccion de la primera gasolinera
DataInteraction g1 = onData(anything()).inAdapterView(withId(R.id.lvStations)).atPosition(0);
g1.onChildView(withId(R.id.tvAbiertoCerrado)).check(matches(withText("Abierto")));
g1.onChildView(withId(R.id.tvHorarioGasolinera)).check(matches(withText("(24H)")));
// g1.onChildView(withId(R.id.tvHorarioGasolinera)).check(matches(withTextColor(R.color.verde)));
}

@Test
public void testAbiertaSimple() {
//comprueba la direccion de la primera gasolinera
DataInteraction g1 = onData(anything()).inAdapterView(withId(R.id.lvStations)).atPosition(1);
g1.onChildView(withId(R.id.tvAbiertoCerrado)).check(matches(withText("Abierto")));
g1.onChildView(withId(R.id.tvHorarioGasolinera)).check(matches(withText("(08:00-21:00)")));
// g1.onChildView(withId(R.id.tvHorarioGasolinera)).check(matches(withTextColor(R.color.verde)));
}

@Test
public void testAbiertaIntervalo() {
//comprueba la direccion de la primera gasolinera
DataInteraction g1 = onData(anything()).inAdapterView(withId(R.id.lvStations)).atPosition(2);
g1.onChildView(withId(R.id.tvAbiertoCerrado)).check(matches(withText("Abierto")));
g1.onChildView(withId(R.id.tvHorarioGasolinera)).check(matches(withText("(09:00-14:00 y 16:00-21:00)")));
// g1.onChildView(withId(R.id.tvHorarioGasolinera)).check(matches(withTextColor(R.color.verde)));
}

@Test
public void testCerradaTodoElDia() {
//comprueba la direccion de la primera gasolinera
DataInteraction g1 = onData(anything()).inAdapterView(withId(R.id.lvStations)).atPosition(3);
g1.onChildView(withId(R.id.tvAbiertoCerrado)).check(matches(withText("Cerrado")));
g1.onChildView(withId(R.id.tvHorarioGasolinera)).check(matches(withText("(Todo el día)")));
// g1.onChildView(withId(R.id.tvHorarioGasolinera)).check(matches(withTextColor(R.color.rojo)));
}

@Test
public void testCerradaParcial() {
//comprueba la direccion de la primera gasolinera
DataInteraction g1 = onData(anything()).inAdapterView(withId(R.id.lvStations)).atPosition(4);
g1.onChildView(withId(R.id.tvAbiertoCerrado)).check(matches(withText("Cerrado")));
g1.onChildView(withId(R.id.tvHorarioGasolinera)).check(matches(withText("(08:00-14:00 y 19:00-21:00)")));
// g1.onChildView(withId(R.id.tvHorarioGasolinera)).check(matches(withTextColor(R.color.rojo)));
}

@Test
public void testSinDetallesDeHorario() throws InterruptedException {
//comprueba la direccion de la primera gasolinera
DataInteraction g1 = onData(anything()).inAdapterView(withId(R.id.lvStations)).atPosition(5);
g1.onChildView(withId(R.id.tvAbiertoCerrado)).check(matches(withText("")));
g1.onChildView(withId(R.id.tvHorarioGasolinera)).check(matches(withText("(Sin detalles de horario)")));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import android.view.View;
import android.widget.ListView;
import android.widget.TextView;

import androidx.test.espresso.matcher.BoundedMatcher;

import org.hamcrest.Description;
import org.hamcrest.Matcher;
Expand All @@ -11,7 +14,19 @@
* Custom matchers for Espresso tests.
*/
public class Matchers {
public static Matcher<View> withTextColor(final int expectedId) {
return new BoundedMatcher<View, TextView>(TextView.class) {

@Override
protected boolean matchesSafely(TextView textView) {
return expectedId == textView.getCurrentTextColor();
}


@Override
public void describeTo(Description description) {
description.appendText("with text color: ");
description.appendValue(expectedId);
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@

import static java.util.Collections.emptyList;

import static es.unican.gasolineras.common.UtilsHorario.gasolineraAbierta;
import static es.unican.gasolineras.common.UtilsHorario.obtenerDiaActual;
import static es.unican.gasolineras.common.UtilsHorario.procesaHorario;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Color;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
Expand All @@ -15,13 +20,12 @@

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;

import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.List;

import es.unican.gasolineras.R;
import es.unican.gasolineras.common.TimeProvider;
import es.unican.gasolineras.model.Gasolinera;

/**
Expand All @@ -35,12 +39,6 @@ public class GasolinerasArrayAdapter extends BaseAdapter {
/** Context of the application */
private final Context context;

/** Constante para el color verde en el caso en el que la gasolinera este abierta. */
private static final int VERDE = 0xFF4CAF50;

/** Constante para el color rojo en el caso en el que la gasolinera este cerrada. */
private static final int ROJO = 0xFFF44336;

/**
* Constructs an adapter to handle a list of gasolineras
* @param context the application context
Expand Down Expand Up @@ -139,15 +137,20 @@ public View getView(int position, @Nullable View convertView, @NonNull ViewGroup
{
TextView tv = convertView.findViewById(R.id.tvAbiertoCerrado);
String estado;
boolean compruebaEstado = gasolineraAbierta(procesaHorario(gasolinera.getHorario()));
String textoHorario = procesaHorario(gasolinera.getHorario(), obtenerDiaActual());
boolean compruebaEstado = gasolineraAbierta(textoHorario, new TimeProvider().obtenerDiaHora().toLocalTime());
if (compruebaEstado) {
estado = "Abierto";
tv.setTextColor(VERDE);
tv.setTextColor(ContextCompat.getColor(context, R.color.verde));
tv.setText(estado);
} else {
estado = "Cerrado";
tv.setTextColor(ROJO);
if (!textoHorario.equals("Sin detalles de horario"))
{
estado = "Cerrado";
tv.setTextColor(ContextCompat.getColor(context, R.color.rojo));
tv.setText(estado);
}
}
tv.setText(estado);
}

/**
Expand All @@ -157,157 +160,13 @@ public View getView(int position, @Nullable View convertView, @NonNull ViewGroup
TextView tv = convertView.findViewById(R.id.tvHorarioGasolinera);
String textoHorario;
if (gasolinera.getHorario() == null || gasolinera.getHorario().isEmpty()) {
textoHorario = "Sin detalles de horario";
textoHorario = "(Sin detalles de horario)";
} else {
textoHorario = "(" + procesaHorario(gasolinera.getHorario()) + ")";
textoHorario = "(" + procesaHorario(gasolinera.getHorario(), obtenerDiaActual()) + ")";
}
tv.setText(textoHorario);
}

return convertView;
}

/**
* Metodo que retorna el horario del dia de hoy de la gasolinera.
*
* @param horario horario de la gasolinera.
*
* @return el horario del dia de hoy que tiene la gasolinera o
* "Horario no disponible" si en la base de datos no aparece el horario.
*/
public String procesaHorario(String horario) {
// Obtén el día actual (L, M, X, J, V, S, D)
String diaActual = obtenerDiaActual();

// Divide el horario en secciones
String[] secciones = horario.split(";");

for (String seccion : secciones) {
// Divide cada sección en días y rango horario
String[] partes = seccion.trim().split(": ");
String dias = partes[0];
String rango = partes[1];

// Divide los días para manejar rangos como "L-X" y días individuales como "D"
String[] diasSeparados = dias.split("-");

// Verifica si el día actual está en el rango
if (diasSeparados.length == 1) { // Ej. "D: 08:00-21:00"
if (diasSeparados[0].equals(diaActual)) return rango;
} else { // Ej. "L-X: 08:00-21:00"
String inicio = diasSeparados[0];
String fin = diasSeparados[1];
if (diaEstaEnRango(diaActual, inicio, fin)) return rango;
}
}
return "Horario no disponible";
}

/**
* Metodo que retorna el dia en el que estamos.
*
* @return el dia en el que estamos.
*/
private String obtenerDiaActual() {
Calendar calendario = Calendar.getInstance();
int diaSemana = calendario.get(Calendar.DAY_OF_WEEK);
switch (diaSemana) {
case Calendar.MONDAY:
return "L";
case Calendar.TUESDAY:
return "M";
case Calendar.WEDNESDAY:
return "X";
case Calendar.THURSDAY:
return "J";
case Calendar.FRIDAY:
return "V";
case Calendar.SATURDAY:
return "S";
case Calendar.SUNDAY:
return "D";
default:
return "";
}
}

// Verifica si un día está dentro del rango de días (Ej. "L-X")

/**
* Metodo que devuelve si nuestro dia actual esta o no dentro del rango de la gasolinera.
*
* @param dia dia de la semana en el que estamos.
* @param inicio inicio del horario de la gosalinera.
* @param fin fin del horario de la gasolinera.
*
* @return true si el dia de hoy esta dentro del rango de la gasolinera.
* false si el dia de hoy no esta dentro del rango de la gasolinera.
*/
private boolean diaEstaEnRango(String dia, String inicio, String fin) {
String[] diasSemana = {"L", "M", "X", "J", "V", "S", "D"};
int indiceInicio = java.util.Arrays.asList(diasSemana).indexOf(inicio);
int indiceFin = java.util.Arrays.asList(diasSemana).indexOf(fin);
int indiceDia = java.util.Arrays.asList(diasSemana).indexOf(dia);

if (indiceInicio <= indiceFin) {
return indiceDia >= indiceInicio && indiceDia <= indiceFin;
} else { // Caso especial para cuando el rango cruza el fin de semana (Ej. "V-D")
return indiceDia >= indiceInicio || indiceDia <= indiceFin;
}
}

/**
* Metodo que nos indica si la gasolinera esta habierta o no.
*
* @param horarios horarios que tiene la gasolinera a lo largo de la semana.
*
* @return true si la gasolinera esta abierta o
* false si la gasolinera esta cerrada
*/
public boolean gasolineraAbierta(String horarios) {
if ("24H".equals(horarios)) {
return true; // Siempre abierta
}
// Divide los días para manejar rangos como "L-X" y días individuales como "D"
String[] diasSeparados = horarios.split("y");
Boolean aux = false;

for (String dia : diasSeparados) {
if (!aux) {
aux = horaEnRango(dia);
} else {
break;
}
}
return aux;
}

/**
* Metodo que indica si una hora esta dentro de un rango o no.
*
* @param rango rango de horas a comprobar.
*
* @return true si el rango esta dentro o
* false si no esta dentro del rango.
*/
private static boolean horaEnRango(String rango) {
// Obtener la hora actual
LocalTime horaActual = LocalTime.now();

// Formateador para interpretar el formato HH:mm
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm");

// Separar el rango en hora de inicio y hora de fin
String[] horas = rango.split("-");
LocalTime inicio = LocalTime.parse(horas[0].trim(), formatter);
LocalTime fin = LocalTime.parse(horas[1].trim(), formatter);

// Comprobar si la hora actual está en el rango
if (inicio.isBefore(fin)) {
return !horaActual.isBefore(inicio) && !horaActual.isAfter(fin);
} else {
// Si el rango cruza la medianoche
return !horaActual.isBefore(inicio) || !horaActual.isAfter(fin);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package es.unican.gasolineras.common;

import java.time.LocalDateTime;

public class TimeProvider {
/**
* Metodo que devuelve la hora actual.
* @return la hora actual.
*/
public LocalDateTime obtenerDiaHora()
{
return LocalDateTime.now();
}
}
Loading

0 comments on commit 06ae220

Please sign in to comment.