diff --git a/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/BaseTest.kt b/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/BaseTest.kt index af29076..02c3347 100644 --- a/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/BaseTest.kt +++ b/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/BaseTest.kt @@ -8,10 +8,9 @@ import android.content.Intent import android.os.Build import android.os.Bundle import android.view.View -import android.view.WindowManager import androidx.test.core.app.ActivityScenario +import androidx.test.core.app.ApplicationProvider import androidx.test.espresso.Espresso -import androidx.test.espresso.Root import androidx.test.espresso.UiController import androidx.test.espresso.ViewAction import androidx.test.espresso.assertion.ViewAssertions @@ -20,15 +19,12 @@ import androidx.test.espresso.matcher.ViewMatchers import androidx.test.platform.app.InstrumentationRegistry import androidx.test.rule.GrantPermissionRule import com.appttude.h_mal.atlas_weather.application.TestAppClass -import com.appttude.h_mal.atlas_weather.helpers.BaseCustomMatcher -import com.appttude.h_mal.atlas_weather.helpers.BaseViewAction +import com.appttude.h_mal.atlas_weather.data.prefs.PreferenceProvider import com.appttude.h_mal.atlas_weather.helpers.SnapshotRule import com.appttude.h_mal.atlas_weather.utils.Stubs import kotlinx.coroutines.runBlocking -import org.hamcrest.Description import org.hamcrest.Matcher import org.hamcrest.Matchers -import org.hamcrest.TypeSafeMatcher import org.junit.After import org.junit.Before import org.junit.Rule @@ -46,6 +42,8 @@ open class BaseTest( private lateinit var testActivity: Activity private lateinit var decorView: View + private val prefs by lazy { PreferenceProvider(ApplicationProvider.getApplicationContext()) } + @get:Rule var permissionRule = GrantPermissionRule.grant(Manifest.permission.ACCESS_COARSE_LOCATION) @@ -87,6 +85,8 @@ open class BaseTest( testApp.stubLocation(location, lat, long) } + fun clearPrefs() = prefs.clearPrefs() + fun getActivity() = testActivity @After diff --git a/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/BaseTestRobot.kt b/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/BaseTestRobot.kt index b62750f..8f367eb 100644 --- a/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/BaseTestRobot.kt +++ b/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/BaseTestRobot.kt @@ -5,6 +5,7 @@ import android.view.View import android.widget.DatePicker import androidx.annotation.StringRes import androidx.recyclerview.widget.RecyclerView.ViewHolder +import androidx.test.espresso.Espresso import androidx.test.espresso.Espresso.onData import androidx.test.espresso.Espresso.onView import androidx.test.espresso.UiController @@ -28,6 +29,8 @@ import org.hamcrest.Matcher @SuppressWarnings("unused") open class BaseTestRobot { + fun goBack() = Espresso.pressBack() + fun fillEditText(resId: Int, text: String?): ViewInteraction = onView(withId(resId)).perform( ViewActions.replaceText(text), @@ -151,4 +154,8 @@ open class BaseTestRobot { ) ) } + + fun openMenuItem() { + matchView(R.id.settings_fragment).perform(click()) + } } \ No newline at end of file diff --git a/app/src/androidTestMonoWeather/java/com/appttude/h_mal/monoWeather/robot/SettingsRobot.kt b/app/src/androidTestMonoWeather/java/com/appttude/h_mal/monoWeather/robot/SettingsRobot.kt new file mode 100644 index 0000000..ee50ee6 --- /dev/null +++ b/app/src/androidTestMonoWeather/java/com/appttude/h_mal/monoWeather/robot/SettingsRobot.kt @@ -0,0 +1,48 @@ +package com.appttude.h_mal.monoWeather.robot + +import androidx.recyclerview.widget.RecyclerView.ViewHolder +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.assertion.ViewAssertions +import androidx.test.espresso.contrib.RecyclerViewActions +import androidx.test.espresso.matcher.RootMatchers.isDialog +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import com.appttude.h_mal.atlas_weather.BaseTestRobot +import com.appttude.h_mal.atlas_weather.R +import com.appttude.h_mal.atlas_weather.model.types.UnitType + + +fun settingsScreen(func: SettingsScreen.() -> Unit) = SettingsScreen().apply { func() } +class SettingsScreen : BaseTestRobot() { + + fun selectWeatherUnits(unitType: UnitType) { + onView(withId(androidx.preference.R.id.recycler_view)) + .perform( + RecyclerViewActions.actionOnItem( + ViewMatchers.hasDescendant(withText(R.string.weather_units)), + click())) + val label = when (unitType) { + UnitType.METRIC -> "Metric" + UnitType.IMPERIAL -> "Imperial" + } + + onView(withText(label)) + .inRoot(isDialog()) + .check(ViewAssertions.matches(ViewMatchers.isDisplayed())) + .perform(click()) + } + + + fun verifyCurrentTemperature(temperature: Int) = + matchText(R.id.temp_main_4, temperature.toString()) + + fun verifyCurrentLocation(location: String) = matchText(R.id.location_main_4, location) + fun refresh() = pullToRefresh(R.id.swipe_refresh) + + fun verifyUnableToRetrieve() { + matchText(R.id.header_text, R.string.retrieve_warning) + matchText(R.id.body_text, R.string.empty_retrieve_warning) + } +} \ No newline at end of file diff --git a/app/src/androidTestMonoWeather/java/com/appttude/h_mal/monoWeather/tests/HomePageUITest.kt b/app/src/androidTestMonoWeather/java/com/appttude/h_mal/monoWeather/tests/HomePageUITest.kt index 284a7f1..1bc556e 100644 --- a/app/src/androidTestMonoWeather/java/com/appttude/h_mal/monoWeather/tests/HomePageUITest.kt +++ b/app/src/androidTestMonoWeather/java/com/appttude/h_mal/monoWeather/tests/HomePageUITest.kt @@ -2,8 +2,10 @@ package com.appttude.h_mal.monoWeather.tests import com.appttude.h_mal.atlas_weather.BaseTest +import com.appttude.h_mal.atlas_weather.model.types.UnitType import com.appttude.h_mal.atlas_weather.ui.MainActivity import com.appttude.h_mal.atlas_weather.utils.Stubs +import com.appttude.h_mal.monoWeather.robot.settingsScreen import com.appttude.h_mal.monoWeather.robot.weatherScreen import org.junit.Test @@ -11,6 +13,7 @@ class HomePageUITest : BaseTest(MainActivity::class.java) { override fun beforeLaunch() { stubEndpoint("https://api.openweathermap.org/data/2.5/onecall", Stubs.Metric) + clearPrefs() } @Test @@ -21,4 +24,25 @@ class HomePageUITest : BaseTest(MainActivity::class.java) { verifyCurrentLocation("Mock Location") } } + + @Test + fun loadApp_changeToImperial_returnsValidPage() { + weatherScreen { + isDisplayed() + verifyCurrentTemperature(2) + verifyCurrentLocation("Mock Location") + stubEndpoint("https://api.openweathermap.org/data/2.5/onecall", Stubs.Imperial) + openMenuItem() + } + settingsScreen { + selectWeatherUnits(UnitType.IMPERIAL) + goBack() + } + weatherScreen { + isDisplayed() + refresh() + verifyCurrentTemperature(58) + verifyCurrentLocation("Mock Location") + } + } } diff --git a/app/src/main/java/com/appttude/h_mal/atlas_weather/data/prefs/PreferencesProvider.kt b/app/src/main/java/com/appttude/h_mal/atlas_weather/data/prefs/PreferencesProvider.kt index e8df5ff..bbea858 100644 --- a/app/src/main/java/com/appttude/h_mal/atlas_weather/data/prefs/PreferencesProvider.kt +++ b/app/src/main/java/com/appttude/h_mal/atlas_weather/data/prefs/PreferencesProvider.kt @@ -2,6 +2,7 @@ package com.appttude.h_mal.atlas_weather.data.prefs import android.content.Context import android.content.SharedPreferences +import androidx.annotation.VisibleForTesting import androidx.preference.PreferenceManager import com.appttude.h_mal.atlas_weather.data.room.entity.CURRENT_LOCATION import com.appttude.h_mal.atlas_weather.model.types.UnitType @@ -61,4 +62,9 @@ class PreferenceProvider( return UnitType.getByName(unit) ?: UnitType.METRIC } + @VisibleForTesting + fun clearPrefs() { + preference.edit().clear().apply() + } + } \ No newline at end of file diff --git a/app/src/main/java/com/appttude/h_mal/atlas_weather/data/room/AppDatabase.kt b/app/src/main/java/com/appttude/h_mal/atlas_weather/data/room/AppDatabase.kt index a51676e..78aae7f 100644 --- a/app/src/main/java/com/appttude/h_mal/atlas_weather/data/room/AppDatabase.kt +++ b/app/src/main/java/com/appttude/h_mal/atlas_weather/data/room/AppDatabase.kt @@ -9,7 +9,7 @@ import com.appttude.h_mal.atlas_weather.data.room.entity.EntityItem @Database( entities = [EntityItem::class], - version = 2, + version = 1, exportSchema = false ) @TypeConverters(Converter::class) diff --git a/app/src/main/java/com/appttude/h_mal/atlas_weather/viewmodel/MainViewModel.kt b/app/src/main/java/com/appttude/h_mal/atlas_weather/viewmodel/MainViewModel.kt index 40effdf..489f75a 100644 --- a/app/src/main/java/com/appttude/h_mal/atlas_weather/viewmodel/MainViewModel.kt +++ b/app/src/main/java/com/appttude/h_mal/atlas_weather/viewmodel/MainViewModel.kt @@ -2,7 +2,6 @@ package com.appttude.h_mal.atlas_weather.viewmodel import android.Manifest import androidx.annotation.RequiresPermission -import androidx.lifecycle.viewModelScope import com.appttude.h_mal.atlas_weather.base.baseViewModels.BaseViewModel import com.appttude.h_mal.atlas_weather.data.WeatherSource import com.appttude.h_mal.atlas_weather.data.location.LocationProvider @@ -35,6 +34,7 @@ class MainViewModel( val latLong = locationProvider.getCurrentLatLong() weatherSource.getWeather(latLon = latLong) } catch (e: Exception) { + e.printStackTrace() onError(e.message ?: "Retrieving weather failed") } } diff --git a/app/src/main/java/com/appttude/h_mal/atlas_weather/viewmodel/SettingsViewModel.kt b/app/src/main/java/com/appttude/h_mal/atlas_weather/viewmodel/SettingsViewModel.kt index 76fc53f..c0ed835 100644 --- a/app/src/main/java/com/appttude/h_mal/atlas_weather/viewmodel/SettingsViewModel.kt +++ b/app/src/main/java/com/appttude/h_mal/atlas_weather/viewmodel/SettingsViewModel.kt @@ -6,10 +6,9 @@ import android.appwidget.AppWidgetManager import android.content.ComponentName import android.content.Intent import android.content.pm.PackageManager -import androidx.annotation.RequiresPermission import androidx.core.app.ActivityCompat import com.appttude.h_mal.atlas_weather.R -import com.appttude.h_mal.atlas_weather.application.AppClass +import com.appttude.h_mal.atlas_weather.application.BaseAppClass import com.appttude.h_mal.atlas_weather.base.baseViewModels.BaseAndroidViewModel import com.appttude.h_mal.atlas_weather.data.WeatherSource import com.appttude.h_mal.atlas_weather.data.location.LocationProvider @@ -27,7 +26,7 @@ class SettingsViewModel( private val settingsRepository: SettingsRepository ) : BaseAndroidViewModel(application) { - private fun getContext() = getApplication().applicationContext + private fun getContext() = getApplication().applicationContext fun updateWidget() { val context = getContext() @@ -63,6 +62,7 @@ class SettingsViewModel( val units = settingsRepository.getUnitType().name.lowercase(Locale.ROOT) onSuccess("Units have been changes to $units") } catch (e: Exception) { + e.printStackTrace() onError(e.message ?: "Retrieving weather failed") } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e4d2331..fdfd652 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -33,6 +33,7 @@ No weather to display Units widget_black_background + Weather units Metric diff --git a/app/src/monoWeather/res/xml/prefs_screen.xml b/app/src/monoWeather/res/xml/prefs_screen.xml index 0272a9d..81ce6f7 100644 --- a/app/src/monoWeather/res/xml/prefs_screen.xml +++ b/app/src/monoWeather/res/xml/prefs_screen.xml @@ -2,7 +2,7 @@