mirror of
https://github.com/hmalik144/Weather-apps.git
synced 2025-12-10 02:05:20 +00:00
- Tests passed
- Weather API successfully replaces
This commit is contained in:
@@ -18,8 +18,8 @@ android {
|
|||||||
applicationId "com.appttude.h_mal.atlas_weather"
|
applicationId "com.appttude.h_mal.atlas_weather"
|
||||||
minSdkVersion MIN_SDK_VERSION
|
minSdkVersion MIN_SDK_VERSION
|
||||||
targetSdkVersion TARGET_SDK_VERSION
|
targetSdkVersion TARGET_SDK_VERSION
|
||||||
versionCode 5
|
versionCode 6
|
||||||
versionName "3.0"
|
versionName "3.1"
|
||||||
testInstrumentationRunner "com.appttude.h_mal.atlas_weather.application.TestRunner"
|
testInstrumentationRunner "com.appttude.h_mal.atlas_weather.application.TestRunner"
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
|
|
||||||
@@ -32,6 +32,10 @@ android {
|
|||||||
buildConfigField "String", "ParamOne", System.getenv('WEATHER_API')
|
buildConfigField "String", "ParamOne", System.getenv('WEATHER_API')
|
||||||
buildConfigField "String", "ParamTwo", System.getenv('SEARCH_API')
|
buildConfigField "String", "ParamTwo", System.getenv('SEARCH_API')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
packagingOptions {
|
||||||
|
resources.excludes.add("META-INF/*")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
android {
|
android {
|
||||||
sourceSets {
|
sourceSets {
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"cod": 401,
|
|
||||||
"message": "Invalid API key. Please see http://openweathermap.org/faq#error401 for more info."
|
|
||||||
}
|
|
||||||
1
app/src/androidTest/assets/invalid_api_key_response.txt
Normal file
1
app/src/androidTest/assets/invalid_api_key_response.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
No account found with API key 'wrong api key'
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
10603
app/src/androidTest/assets/valid_response_with_alert.json
Normal file
10603
app/src/androidTest/assets/valid_response_with_alert.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -67,7 +67,7 @@ open class BaseTest<A : Activity>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
testApp =
|
testApp =
|
||||||
InstrumentationRegistry.getInstrumentation().targetContext.applicationContext
|
InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as TestAppClass
|
||||||
runBlocking {
|
runBlocking {
|
||||||
beforeLaunch()
|
beforeLaunch()
|
||||||
}
|
}
|
||||||
@@ -80,8 +80,8 @@ open class BaseTest<A : Activity>(
|
|||||||
afterLaunch()
|
afterLaunch()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun stubEndpoint(url: String, stub: Stubs, code: Int = 200) {
|
fun stubEndpoint(url: String, stub: Stubs, code: Int = 200, extension: String = ".json") {
|
||||||
testApp.stubUrl(url, stub.id, code)
|
testApp.stubUrl(url, stub.id, code, extension)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun unstubEndpoint(url: String) {
|
fun unstubEndpoint(url: String) {
|
||||||
@@ -125,7 +125,6 @@ open class BaseTest<A : Activity>(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
fun checkToastMessage(message: String) {
|
fun checkToastMessage(message: String) {
|
||||||
Espresso.onView(ViewMatchers.withText(message)).inRoot(withDecorView(Matchers.not(decorView)))
|
Espresso.onView(ViewMatchers.withText(message)).inRoot(withDecorView(Matchers.not(decorView)))
|
||||||
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
|
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
|
||||||
|
|||||||
@@ -17,7 +17,12 @@ import androidx.test.espresso.action.ViewActions.swipeDown
|
|||||||
import androidx.test.espresso.assertion.ViewAssertions.matches
|
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||||
import androidx.test.espresso.contrib.PickerActions
|
import androidx.test.espresso.contrib.PickerActions
|
||||||
import androidx.test.espresso.contrib.RecyclerViewActions
|
import androidx.test.espresso.contrib.RecyclerViewActions
|
||||||
import androidx.test.espresso.matcher.ViewMatchers.*
|
import androidx.test.espresso.matcher.ViewMatchers.hasDescendant
|
||||||
|
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
|
||||||
|
import androidx.test.espresso.matcher.ViewMatchers.isRoot
|
||||||
|
import androidx.test.espresso.matcher.ViewMatchers.withClassName
|
||||||
|
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||||
|
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||||
import com.appttude.h_mal.atlas_weather.helpers.EspressoHelper.waitForView
|
import com.appttude.h_mal.atlas_weather.helpers.EspressoHelper.waitForView
|
||||||
import com.appttude.h_mal.atlas_weather.helpers.checkErrorMessage
|
import com.appttude.h_mal.atlas_weather.helpers.checkErrorMessage
|
||||||
import com.appttude.h_mal.atlas_weather.helpers.checkImage
|
import com.appttude.h_mal.atlas_weather.helpers.checkImage
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ class MockingNetworkInterceptor(
|
|||||||
override fun intercept(chain: Interceptor.Chain): Response {
|
override fun intercept(chain: Interceptor.Chain): Response {
|
||||||
idlingResource.increment()
|
idlingResource.increment()
|
||||||
val original = chain.request()
|
val original = chain.request()
|
||||||
val originalHttpUrl = original.url.toString().split("?")[0]
|
val originalHttpUrl = original.url.toString()
|
||||||
|
|
||||||
feedMap[originalHttpUrl]?.let { responsePair ->
|
feedMap[feedMap.keys.first { originalHttpUrl.contains(it) }]?.let { responsePair ->
|
||||||
val code = responsePair.second
|
val code = responsePair.second
|
||||||
val jsonBody = responsePair.first
|
val jsonBody = responsePair.first
|
||||||
|
|
||||||
|
|||||||
@@ -9,5 +9,4 @@ enum class Stubs(
|
|||||||
WrongLocation("wrong_location_response"),
|
WrongLocation("wrong_location_response"),
|
||||||
InvalidKey("invalid_api_key_response"),
|
InvalidKey("invalid_api_key_response"),
|
||||||
Sydney("valid_response_metric_sydney"),
|
Sydney("valid_response_metric_sydney"),
|
||||||
New("new_response")
|
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,7 @@ import androidx.test.platform.app.InstrumentationRegistry
|
|||||||
import com.appttude.h_mal.atlas_weather.data.location.LocationProvider
|
import com.appttude.h_mal.atlas_weather.data.location.LocationProvider
|
||||||
import com.appttude.h_mal.atlas_weather.data.location.MockLocationProvider
|
import com.appttude.h_mal.atlas_weather.data.location.MockLocationProvider
|
||||||
import com.appttude.h_mal.atlas_weather.data.network.NetworkModule
|
import com.appttude.h_mal.atlas_weather.data.network.NetworkModule
|
||||||
import com.appttude.h_mal.atlas_weather.data.network.NewWeatherApi
|
import com.appttude.h_mal.atlas_weather.data.network.WeatherApi
|
||||||
import com.appttude.h_mal.atlas_weather.data.network.interceptors.MockingNetworkInterceptor
|
import com.appttude.h_mal.atlas_weather.data.network.interceptors.MockingNetworkInterceptor
|
||||||
import com.appttude.h_mal.atlas_weather.data.network.interceptors.NetworkConnectionInterceptor
|
import com.appttude.h_mal.atlas_weather.data.network.interceptors.NetworkConnectionInterceptor
|
||||||
import com.appttude.h_mal.atlas_weather.data.network.interceptors.QueryParamsInterceptor
|
import com.appttude.h_mal.atlas_weather.data.network.interceptors.QueryParamsInterceptor
|
||||||
@@ -28,8 +28,8 @@ class TestAppClass : AppClass() {
|
|||||||
IdlingRegistry.getInstance().register(idlingResources)
|
IdlingRegistry.getInstance().register(idlingResources)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createNetworkModule(): NewWeatherApi {
|
override fun createNetworkModule(): WeatherApi {
|
||||||
return NetworkModule().invoke<NewWeatherApi>(
|
return NetworkModule().invoke<WeatherApi>(
|
||||||
mockingNetworkInterceptor,
|
mockingNetworkInterceptor,
|
||||||
NetworkConnectionInterceptor(this),
|
NetworkConnectionInterceptor(this),
|
||||||
QueryParamsInterceptor(),
|
QueryParamsInterceptor(),
|
||||||
@@ -49,9 +49,9 @@ class TestAppClass : AppClass() {
|
|||||||
return database
|
return database
|
||||||
}
|
}
|
||||||
|
|
||||||
fun stubUrl(url: String, rawPath: String, code: Int = 200) {
|
fun stubUrl(url: String, rawPath: String, code: Int = 200, extension: String = ".json") {
|
||||||
val iStream =
|
val iStream =
|
||||||
InstrumentationRegistry.getInstrumentation().context.assets.open("$rawPath.json")
|
InstrumentationRegistry.getInstrumentation().context.assets.open("$rawPath$extension")
|
||||||
val data = iStream.bufferedReader().use(BufferedReader::readText)
|
val data = iStream.bufferedReader().use(BufferedReader::readText)
|
||||||
mockingNetworkInterceptor.addUrlStub(url = url, data = data, code = code)
|
mockingNetworkInterceptor.addUrlStub(url = url, data = data, code = code)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import com.appttude.h_mal.atlas_weather.BaseTestRobot
|
|||||||
import com.appttude.h_mal.atlas_weather.R
|
import com.appttude.h_mal.atlas_weather.R
|
||||||
import com.appttude.h_mal.atlas_weather.helpers.EspressoHelper.waitForView
|
import com.appttude.h_mal.atlas_weather.helpers.EspressoHelper.waitForView
|
||||||
import com.appttude.h_mal.atlas_weather.model.types.UnitType
|
import com.appttude.h_mal.atlas_weather.model.types.UnitType
|
||||||
|
import com.appttude.h_mal.atlas_weather.model.types.UnitType.Companion.getLabel
|
||||||
|
|
||||||
|
|
||||||
fun settingsScreen(func: SettingsScreen.() -> Unit) = SettingsScreen().apply { func() }
|
fun settingsScreen(func: SettingsScreen.() -> Unit) = SettingsScreen().apply { func() }
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import com.appttude.h_mal.atlas_weather.utils.Stubs
|
|||||||
import com.appttude.h_mal.atlas_weather.robot.furtherInfoScreen
|
import com.appttude.h_mal.atlas_weather.robot.furtherInfoScreen
|
||||||
import com.appttude.h_mal.atlas_weather.robot.settingsScreen
|
import com.appttude.h_mal.atlas_weather.robot.settingsScreen
|
||||||
import com.appttude.h_mal.atlas_weather.robot.weatherScreen
|
import com.appttude.h_mal.atlas_weather.robot.weatherScreen
|
||||||
|
import com.appttude.h_mal.atlas_weather.utils.baseUrl
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import tools.fastlane.screengrab.Screengrab
|
import tools.fastlane.screengrab.Screengrab
|
||||||
|
|
||||||
@@ -17,7 +18,7 @@ import tools.fastlane.screengrab.Screengrab
|
|||||||
class SnapshotCaptureTest : BaseTest<MainActivity>(MainActivity::class.java) {
|
class SnapshotCaptureTest : BaseTest<MainActivity>(MainActivity::class.java) {
|
||||||
|
|
||||||
override fun beforeLaunch() {
|
override fun beforeLaunch() {
|
||||||
stubEndpoint("https://api.openweathermap.org/data/2.5/onecall", Stubs.Metric)
|
stubEndpoint(baseUrl, Stubs.Metric)
|
||||||
stubLocation("London", 51.51, -0.13)
|
stubLocation("London", 51.51, -0.13)
|
||||||
clearPrefs()
|
clearPrefs()
|
||||||
}
|
}
|
||||||
@@ -50,7 +51,7 @@ class SnapshotCaptureTest : BaseTest<MainActivity>(MainActivity::class.java) {
|
|||||||
openMenuItem()
|
openMenuItem()
|
||||||
}
|
}
|
||||||
settingsScreen {
|
settingsScreen {
|
||||||
stubEndpoint("https://api.openweathermap.org/data/2.5/onecall", Stubs.Imperial)
|
stubEndpoint(baseUrl, Stubs.Imperial)
|
||||||
Screengrab.screenshot("SettingsScreen")
|
Screengrab.screenshot("SettingsScreen")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +1,27 @@
|
|||||||
package com.appttude.h_mal.atlas_weather.tests
|
package com.appttude.h_mal.atlas_weather.tests
|
||||||
|
|
||||||
import com.appttude.h_mal.atlas_weather.BaseTest
|
import com.appttude.h_mal.atlas_weather.BaseTest
|
||||||
|
import com.appttude.h_mal.atlas_weather.robot.homeScreen
|
||||||
import com.appttude.h_mal.atlas_weather.ui.MainActivity
|
import com.appttude.h_mal.atlas_weather.ui.MainActivity
|
||||||
import com.appttude.h_mal.atlas_weather.utils.Stubs
|
import com.appttude.h_mal.atlas_weather.utils.Stubs
|
||||||
import com.appttude.h_mal.atlas_weather.robot.homeScreen
|
import com.appttude.h_mal.atlas_weather.utils.baseUrl
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
class HomePageNoDataUITest : BaseTest<MainActivity>(MainActivity::class.java) {
|
class HomePageNoDataUITest : BaseTest<MainActivity>(MainActivity::class.java) {
|
||||||
|
|
||||||
override fun beforeLaunch() {
|
override fun beforeLaunch() {
|
||||||
stubEndpoint("https://api.openweathermap.org/data/2.5/onecall", Stubs.InvalidKey, 400)
|
stubEndpoint(baseUrl, Stubs.InvalidKey, 400, ".txt")
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun loadApp_invalidKeyWeatherResponse_returnsEmptyViewPage() {
|
|
||||||
homeScreen {
|
|
||||||
waitFor(2000)
|
|
||||||
// verify empty
|
|
||||||
verifyUnableToRetrieve()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun invalidKeyWeatherResponse_swipeToRefresh_returnsValidPage() {
|
fun invalidKeyWeatherResponse_swipeToRefresh_returnsValidPage() {
|
||||||
homeScreen {
|
homeScreen {
|
||||||
waitFor(2000)
|
|
||||||
// verify empty
|
// verify empty
|
||||||
verifyUnableToRetrieve()
|
verifyUnableToRetrieve()
|
||||||
|
|
||||||
stubEndpoint("https://api.openweathermap.org/data/2.5/onecall", Stubs.Metric)
|
stubEndpoint(baseUrl, Stubs.Metric)
|
||||||
refresh()
|
refresh()
|
||||||
verifyCurrentTemperature(2)
|
verifyCurrentTemperature(13)
|
||||||
verifyCurrentLocation("Mock Location")
|
verifyCurrentLocation("Mock Location")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,19 +5,20 @@ import com.appttude.h_mal.atlas_weather.BaseTest
|
|||||||
import com.appttude.h_mal.atlas_weather.robot.homeScreen
|
import com.appttude.h_mal.atlas_weather.robot.homeScreen
|
||||||
import com.appttude.h_mal.atlas_weather.ui.MainActivity
|
import com.appttude.h_mal.atlas_weather.ui.MainActivity
|
||||||
import com.appttude.h_mal.atlas_weather.utils.Stubs
|
import com.appttude.h_mal.atlas_weather.utils.Stubs
|
||||||
|
import com.appttude.h_mal.atlas_weather.utils.baseUrl
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
class HomePageUITest : BaseTest<MainActivity>(MainActivity::class.java) {
|
class HomePageUITest : BaseTest<MainActivity>(MainActivity::class.java) {
|
||||||
|
|
||||||
override fun beforeLaunch() {
|
override fun beforeLaunch() {
|
||||||
stubEndpoint("https://api.openweathermap.org/data/2.5/onecall", Stubs.Metric)
|
stubEndpoint(baseUrl, Stubs.Metric)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun loadApp_validWeatherResponse_returnsValidPage() {
|
fun loadApp_validWeatherResponse_returnsValidPage() {
|
||||||
homeScreen {
|
homeScreen {
|
||||||
isDisplayed()
|
isDisplayed()
|
||||||
verifyCurrentTemperature(2)
|
verifyCurrentTemperature(13)
|
||||||
verifyCurrentLocation("Mock Location")
|
verifyCurrentLocation("Mock Location")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import androidx.test.platform.app.InstrumentationRegistry
|
|||||||
import com.appttude.h_mal.atlas_weather.data.location.LocationProvider
|
import com.appttude.h_mal.atlas_weather.data.location.LocationProvider
|
||||||
import com.appttude.h_mal.atlas_weather.data.location.MockLocationProvider
|
import com.appttude.h_mal.atlas_weather.data.location.MockLocationProvider
|
||||||
import com.appttude.h_mal.atlas_weather.data.network.NetworkModule
|
import com.appttude.h_mal.atlas_weather.data.network.NetworkModule
|
||||||
import com.appttude.h_mal.atlas_weather.data.network.NewWeatherApi
|
import com.appttude.h_mal.atlas_weather.data.network.WeatherApi
|
||||||
import com.appttude.h_mal.atlas_weather.data.network.interceptors.MockingNetworkInterceptor
|
import com.appttude.h_mal.atlas_weather.data.network.interceptors.MockingNetworkInterceptor
|
||||||
import com.appttude.h_mal.atlas_weather.data.network.interceptors.NetworkConnectionInterceptor
|
import com.appttude.h_mal.atlas_weather.data.network.interceptors.NetworkConnectionInterceptor
|
||||||
import com.appttude.h_mal.atlas_weather.data.network.interceptors.QueryParamsInterceptor
|
import com.appttude.h_mal.atlas_weather.data.network.interceptors.QueryParamsInterceptor
|
||||||
@@ -18,7 +18,6 @@ import org.kodein.di.LazyKodein
|
|||||||
import java.io.BufferedReader
|
import java.io.BufferedReader
|
||||||
|
|
||||||
class TestAppClass : AppClass() {
|
class TestAppClass : AppClass() {
|
||||||
|
|
||||||
override val kodein: LazyKodein = super.kodein
|
override val kodein: LazyKodein = super.kodein
|
||||||
|
|
||||||
private val idlingResources = CountingIdlingResource("Data_loader")
|
private val idlingResources = CountingIdlingResource("Data_loader")
|
||||||
@@ -32,13 +31,13 @@ class TestAppClass : AppClass() {
|
|||||||
IdlingRegistry.getInstance().register(idlingResources)
|
IdlingRegistry.getInstance().register(idlingResources)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createNetworkModule(): NewWeatherApi {
|
override fun createNetworkModule(): WeatherApi {
|
||||||
return NetworkModule().invoke<NewWeatherApi>(
|
return NetworkModule().invoke<WeatherApi>(
|
||||||
mockingNetworkInterceptor,
|
mockingNetworkInterceptor,
|
||||||
NetworkConnectionInterceptor(this),
|
NetworkConnectionInterceptor(this),
|
||||||
QueryParamsInterceptor(),
|
QueryParamsInterceptor(),
|
||||||
loggingInterceptor
|
loggingInterceptor
|
||||||
) as NewWeatherApi
|
) as WeatherApi
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createLocationModule(): LocationProvider {
|
override fun createLocationModule(): LocationProvider {
|
||||||
@@ -53,9 +52,9 @@ class TestAppClass : AppClass() {
|
|||||||
return database
|
return database
|
||||||
}
|
}
|
||||||
|
|
||||||
fun stubUrl(url: String, rawPath: String, code: Int = 200) {
|
fun stubUrl(url: String, rawPath: String, code: Int = 200, extension: String = ".json") {
|
||||||
val iStream =
|
val iStream =
|
||||||
InstrumentationRegistry.getInstrumentation().context.assets.open("$rawPath.json")
|
InstrumentationRegistry.getInstrumentation().context.assets.open("$rawPath$extension")
|
||||||
val data = iStream.bufferedReader().use(BufferedReader::readText)
|
val data = iStream.bufferedReader().use(BufferedReader::readText)
|
||||||
mockingNetworkInterceptor.addUrlStub(url = url, data = data, code = code)
|
mockingNetworkInterceptor.addUrlStub(url = url, data = data, code = code)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import com.appttude.h_mal.atlas_weather.utils.baseUrl
|
|||||||
import com.appttude.h_mal.monoWeather.robot.furtherInfoScreen
|
import com.appttude.h_mal.monoWeather.robot.furtherInfoScreen
|
||||||
import com.appttude.h_mal.monoWeather.robot.settingsScreen
|
import com.appttude.h_mal.monoWeather.robot.settingsScreen
|
||||||
import com.appttude.h_mal.monoWeather.robot.weatherScreen
|
import com.appttude.h_mal.monoWeather.robot.weatherScreen
|
||||||
import org.junit.Ignore
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import tools.fastlane.screengrab.Screengrab
|
import tools.fastlane.screengrab.Screengrab
|
||||||
|
|
||||||
@@ -19,7 +18,7 @@ import tools.fastlane.screengrab.Screengrab
|
|||||||
class SnapshotCaptureTest : BaseTest<MainActivity>(MainActivity::class.java) {
|
class SnapshotCaptureTest : BaseTest<MainActivity>(MainActivity::class.java) {
|
||||||
|
|
||||||
override fun beforeLaunch() {
|
override fun beforeLaunch() {
|
||||||
stubEndpoint(baseUrl, Stubs.New)
|
stubEndpoint(baseUrl, Stubs.Metric)
|
||||||
stubLocation("London", 51.5064, -0.12721)
|
stubLocation("London", 51.5064, -0.12721)
|
||||||
clearPrefs()
|
clearPrefs()
|
||||||
}
|
}
|
||||||
@@ -53,7 +52,7 @@ class SnapshotCaptureTest : BaseTest<MainActivity>(MainActivity::class.java) {
|
|||||||
openMenuItem()
|
openMenuItem()
|
||||||
}
|
}
|
||||||
settingsScreen {
|
settingsScreen {
|
||||||
stubEndpoint("https://api.openweathermap.org/data/2.5/onecall", Stubs.Imperial)
|
stubEndpoint(baseUrl, Stubs.Imperial)
|
||||||
Screengrab.screenshot("SettingsScreen")
|
Screengrab.screenshot("SettingsScreen")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package com.appttude.h_mal.monoWeather.robot
|
|||||||
import com.appttude.h_mal.atlas_weather.BaseTestRobot
|
import com.appttude.h_mal.atlas_weather.BaseTestRobot
|
||||||
import com.appttude.h_mal.atlas_weather.R
|
import com.appttude.h_mal.atlas_weather.R
|
||||||
import com.appttude.h_mal.monoWeather.ui.home.adapter.forecastDaily.ViewHolderForecastDaily
|
import com.appttude.h_mal.monoWeather.ui.home.adapter.forecastDaily.ViewHolderForecastDaily
|
||||||
import com.appttude.h_mal.monoWeather.ui.home.adapter.further.ViewHolderFurtherDetails
|
|
||||||
|
|
||||||
fun weatherScreen(func: WeatherScreen.() -> Unit) = WeatherScreen().apply { func() }
|
fun weatherScreen(func: WeatherScreen.() -> Unit) = WeatherScreen().apply { func() }
|
||||||
class WeatherScreen : BaseTestRobot() {
|
class WeatherScreen : BaseTestRobot() {
|
||||||
|
|||||||
@@ -4,36 +4,30 @@ package com.appttude.h_mal.monoWeather.tests
|
|||||||
import com.appttude.h_mal.atlas_weather.BaseTest
|
import com.appttude.h_mal.atlas_weather.BaseTest
|
||||||
import com.appttude.h_mal.atlas_weather.ui.MainActivity
|
import com.appttude.h_mal.atlas_weather.ui.MainActivity
|
||||||
import com.appttude.h_mal.atlas_weather.utils.Stubs
|
import com.appttude.h_mal.atlas_weather.utils.Stubs
|
||||||
|
import com.appttude.h_mal.atlas_weather.utils.baseUrl
|
||||||
import com.appttude.h_mal.monoWeather.robot.weatherScreen
|
import com.appttude.h_mal.monoWeather.robot.weatherScreen
|
||||||
import org.junit.Ignore
|
import org.junit.FixMethodOrder
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
import org.junit.runners.MethodSorters
|
||||||
|
|
||||||
|
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||||
class HomePageNoDataUITest : BaseTest<MainActivity>(MainActivity::class.java) {
|
class HomePageNoDataUITest : BaseTest<MainActivity>(MainActivity::class.java) {
|
||||||
|
|
||||||
override fun beforeLaunch() {
|
override fun beforeLaunch() {
|
||||||
// Todo: change this
|
stubEndpoint(baseUrl, Stubs.InvalidKey, 400, ".txt")
|
||||||
stubEndpoint("https://api.openweathermap.org/data/2.5/onecall", Stubs.InvalidKey, 400)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
fun loadApp_invalidKeyWeatherResponse_returnsEmptyViewPage() {
|
|
||||||
weatherScreen {
|
|
||||||
// verify empty
|
|
||||||
verifyUnableToRetrieve()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore("Test is flakey - must investigate")
|
|
||||||
@Test
|
@Test
|
||||||
fun invalidKeyWeatherResponse_swipeToRefresh_returnsValidPage() {
|
fun invalidKeyWeatherResponse_swipeToRefresh_returnsValidPage() {
|
||||||
weatherScreen {
|
weatherScreen {
|
||||||
// verify empty
|
// verify empty
|
||||||
verifyUnableToRetrieve()
|
verifyUnableToRetrieve()
|
||||||
|
|
||||||
stubEndpoint("https://api.openweathermap.org/data/2.5/onecall", Stubs.Metric)
|
stubEndpoint(baseUrl, Stubs.Metric)
|
||||||
refresh()
|
refresh()
|
||||||
verifyCurrentTemperature(2)
|
verifyCurrentTemperature(13)
|
||||||
verifyCurrentLocation("Mock Location")
|
verifyCurrentLocation("Mock Location")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,19 +2,17 @@ package com.appttude.h_mal.monoWeather.tests
|
|||||||
|
|
||||||
|
|
||||||
import com.appttude.h_mal.atlas_weather.BaseTest
|
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.ui.MainActivity
|
||||||
import com.appttude.h_mal.atlas_weather.utils.Stubs
|
import com.appttude.h_mal.atlas_weather.utils.Stubs
|
||||||
import com.appttude.h_mal.atlas_weather.utils.baseUrl
|
import com.appttude.h_mal.atlas_weather.utils.baseUrl
|
||||||
import com.appttude.h_mal.monoWeather.robot.furtherInfoScreen
|
import com.appttude.h_mal.monoWeather.robot.furtherInfoScreen
|
||||||
import com.appttude.h_mal.monoWeather.robot.settingsScreen
|
|
||||||
import com.appttude.h_mal.monoWeather.robot.weatherScreen
|
import com.appttude.h_mal.monoWeather.robot.weatherScreen
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
class HomePageUITest : BaseTest<MainActivity>(MainActivity::class.java) {
|
class HomePageUITest : BaseTest<MainActivity>(MainActivity::class.java) {
|
||||||
|
|
||||||
override fun beforeLaunch() {
|
override fun beforeLaunch() {
|
||||||
stubEndpoint(baseUrl, Stubs.New)
|
stubEndpoint(baseUrl, Stubs.Metric)
|
||||||
clearPrefs()
|
clearPrefs()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,7 +20,7 @@ class HomePageUITest : BaseTest<MainActivity>(MainActivity::class.java) {
|
|||||||
fun loadApp_validWeatherResponse_returnsValidPage() {
|
fun loadApp_validWeatherResponse_returnsValidPage() {
|
||||||
weatherScreen {
|
weatherScreen {
|
||||||
isDisplayed()
|
isDisplayed()
|
||||||
verifyCurrentTemperature(2)
|
verifyCurrentTemperature(13)
|
||||||
verifyCurrentLocation("Mock Location")
|
verifyCurrentLocation("Mock Location")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -31,35 +29,15 @@ class HomePageUITest : BaseTest<MainActivity>(MainActivity::class.java) {
|
|||||||
fun loadApp_validWeatherResponse_viewFurtherDetailsPage() {
|
fun loadApp_validWeatherResponse_viewFurtherDetailsPage() {
|
||||||
weatherScreen {
|
weatherScreen {
|
||||||
isDisplayed()
|
isDisplayed()
|
||||||
verifyCurrentTemperature(2)
|
verifyCurrentTemperature(13)
|
||||||
verifyCurrentLocation("Mock Location")
|
verifyCurrentLocation("Mock Location")
|
||||||
tapDayInformationByPosition(4)
|
tapDayInformationByPosition(4)
|
||||||
}
|
}
|
||||||
furtherInfoScreen {
|
furtherInfoScreen {
|
||||||
isDisplayed()
|
isDisplayed()
|
||||||
verifyMaxTemperature(12)
|
verifyMaxTemperature(15)
|
||||||
verifyAverageTemperature(9)
|
verifyAverageTemperature(11)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@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")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
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.atlas_weather.utils.baseUrl
|
||||||
|
import com.appttude.h_mal.monoWeather.robot.settingsScreen
|
||||||
|
import com.appttude.h_mal.monoWeather.robot.weatherScreen
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class SettingsPageUITest : BaseTest<MainActivity>(MainActivity::class.java) {
|
||||||
|
|
||||||
|
override fun beforeLaunch() {
|
||||||
|
stubEndpoint(baseUrl, Stubs.Metric)
|
||||||
|
clearPrefs()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun loadApp_changeToImperial_returnsValidPage() {
|
||||||
|
weatherScreen {
|
||||||
|
isDisplayed()
|
||||||
|
verifyCurrentTemperature(13)
|
||||||
|
verifyCurrentLocation("Mock Location")
|
||||||
|
stubEndpoint(baseUrl, Stubs.Imperial)
|
||||||
|
openMenuItem()
|
||||||
|
}
|
||||||
|
settingsScreen {
|
||||||
|
selectWeatherUnits(UnitType.IMPERIAL)
|
||||||
|
goBack()
|
||||||
|
}
|
||||||
|
weatherScreen {
|
||||||
|
isDisplayed()
|
||||||
|
refresh()
|
||||||
|
verifyCurrentTemperature(56)
|
||||||
|
verifyCurrentLocation("Mock Location")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,8 +15,8 @@ import org.junit.Test
|
|||||||
class WorldPageUITest : BaseTest<MainActivity>(MainActivity::class.java) {
|
class WorldPageUITest : BaseTest<MainActivity>(MainActivity::class.java) {
|
||||||
|
|
||||||
override fun beforeLaunch() {
|
override fun beforeLaunch() {
|
||||||
stubEndpoint(baseUrl, Stubs.New)
|
stubEndpoint(baseUrl, Stubs.Metric)
|
||||||
stubLocation("London", 51.5064, -0.12721)
|
stubLocation("London", 51.5064,-0.12721)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -28,9 +28,8 @@ class WorldPageUITest : BaseTest<MainActivity>(MainActivity::class.java) {
|
|||||||
clickFab()
|
clickFab()
|
||||||
}
|
}
|
||||||
addLocation {
|
addLocation {
|
||||||
// Todo: change this
|
stubEndpoint(baseUrl, Stubs.Sydney)
|
||||||
stubEndpoint("https://api.openweathermap.org/data/2.5/onecall", Stubs.Sydney)
|
stubLocation("Sydney",-33.8696,151.207)
|
||||||
stubLocation("Sydney", -33.89, -151.12)
|
|
||||||
setLocation("Sydney")
|
setLocation("Sydney")
|
||||||
submit()
|
submit()
|
||||||
}
|
}
|
||||||
@@ -39,7 +38,7 @@ class WorldPageUITest : BaseTest<MainActivity>(MainActivity::class.java) {
|
|||||||
}
|
}
|
||||||
weatherScreen {
|
weatherScreen {
|
||||||
isDisplayed()
|
isDisplayed()
|
||||||
verifyCurrentTemperature(12)
|
verifyCurrentTemperature(16)
|
||||||
verifyCurrentLocation("Sydney")
|
verifyCurrentLocation("Sydney")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package com.appttude.h_mal.atlas_weather.application
|
|||||||
import com.appttude.h_mal.atlas_weather.data.location.LocationProvider
|
import com.appttude.h_mal.atlas_weather.data.location.LocationProvider
|
||||||
import com.appttude.h_mal.atlas_weather.data.location.LocationProviderImpl
|
import com.appttude.h_mal.atlas_weather.data.location.LocationProviderImpl
|
||||||
import com.appttude.h_mal.atlas_weather.data.network.NetworkModule
|
import com.appttude.h_mal.atlas_weather.data.network.NetworkModule
|
||||||
import com.appttude.h_mal.atlas_weather.data.network.NewWeatherApi
|
import com.appttude.h_mal.atlas_weather.data.network.WeatherApi
|
||||||
import com.appttude.h_mal.atlas_weather.data.network.interceptors.NetworkConnectionInterceptor
|
import com.appttude.h_mal.atlas_weather.data.network.interceptors.NetworkConnectionInterceptor
|
||||||
import com.appttude.h_mal.atlas_weather.data.network.interceptors.QueryParamsInterceptor
|
import com.appttude.h_mal.atlas_weather.data.network.interceptors.QueryParamsInterceptor
|
||||||
import com.appttude.h_mal.atlas_weather.data.network.networkUtils.loggingInterceptor
|
import com.appttude.h_mal.atlas_weather.data.network.networkUtils.loggingInterceptor
|
||||||
@@ -11,12 +11,12 @@ import com.appttude.h_mal.atlas_weather.data.room.AppDatabase
|
|||||||
|
|
||||||
open class AppClass : BaseAppClass() {
|
open class AppClass : BaseAppClass() {
|
||||||
|
|
||||||
override fun createNetworkModule(): NewWeatherApi {
|
override fun createNetworkModule(): WeatherApi {
|
||||||
return NetworkModule().invoke<NewWeatherApi>(
|
return NetworkModule().invoke<WeatherApi>(
|
||||||
NetworkConnectionInterceptor(this),
|
NetworkConnectionInterceptor(this),
|
||||||
QueryParamsInterceptor(),
|
QueryParamsInterceptor(),
|
||||||
loggingInterceptor
|
loggingInterceptor
|
||||||
) as NewWeatherApi
|
) as WeatherApi
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createLocationModule(): LocationProvider = LocationProviderImpl(this)
|
override fun createLocationModule(): LocationProvider = LocationProviderImpl(this)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import android.app.Application
|
|||||||
import com.appttude.h_mal.atlas_weather.data.WeatherSource
|
import com.appttude.h_mal.atlas_weather.data.WeatherSource
|
||||||
import com.appttude.h_mal.atlas_weather.data.location.LocationProvider
|
import com.appttude.h_mal.atlas_weather.data.location.LocationProvider
|
||||||
import com.appttude.h_mal.atlas_weather.data.network.Api
|
import com.appttude.h_mal.atlas_weather.data.network.Api
|
||||||
|
import com.appttude.h_mal.atlas_weather.data.network.WeatherApi
|
||||||
import com.appttude.h_mal.atlas_weather.data.prefs.PreferenceProvider
|
import com.appttude.h_mal.atlas_weather.data.prefs.PreferenceProvider
|
||||||
import com.appttude.h_mal.atlas_weather.data.repository.RepositoryImpl
|
import com.appttude.h_mal.atlas_weather.data.repository.RepositoryImpl
|
||||||
import com.appttude.h_mal.atlas_weather.data.repository.SettingsRepositoryImpl
|
import com.appttude.h_mal.atlas_weather.data.repository.SettingsRepositoryImpl
|
||||||
@@ -28,7 +29,7 @@ abstract class BaseAppClass : Application(), KodeinAware {
|
|||||||
val parentModule = Kodein.Module("Parent Module", allowSilentOverride = true) {
|
val parentModule = Kodein.Module("Parent Module", allowSilentOverride = true) {
|
||||||
import(androidXModule(this@BaseAppClass))
|
import(androidXModule(this@BaseAppClass))
|
||||||
|
|
||||||
bind() from singleton { createNetworkModule() }
|
bind() from singleton { createNetworkModule() as WeatherApi }
|
||||||
bind() from singleton { createLocationModule() }
|
bind() from singleton { createLocationModule() }
|
||||||
|
|
||||||
bind() from singleton { Gson() }
|
bind() from singleton { Gson() }
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
package com.appttude.h_mal.atlas_weather.data.network
|
package com.appttude.h_mal.atlas_weather.data.network
|
||||||
|
|
||||||
import org.json.JSONException
|
import retrofit2.HttpException
|
||||||
import org.json.JSONObject
|
|
||||||
import retrofit2.Response
|
import retrofit2.Response
|
||||||
import java.io.IOException
|
|
||||||
|
|
||||||
abstract class ResponseUnwrap {
|
abstract class ResponseUnwrap {
|
||||||
|
|
||||||
@@ -15,18 +13,7 @@ abstract class ResponseUnwrap {
|
|||||||
if (response.isSuccessful) {
|
if (response.isSuccessful) {
|
||||||
return response.body()!!
|
return response.body()!!
|
||||||
} else {
|
} else {
|
||||||
val error = response.errorBody()?.string()
|
throw HttpException(response)
|
||||||
|
|
||||||
val errorMessage = error?.let {
|
|
||||||
try {
|
|
||||||
JSONObject(it).getString("message")
|
|
||||||
} catch (e: JSONException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
null
|
|
||||||
}
|
|
||||||
} ?: "Error Code: ${response.code()}"
|
|
||||||
|
|
||||||
throw IOException(errorMessage)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,13 +7,13 @@ import retrofit2.http.Path
|
|||||||
import retrofit2.http.Query
|
import retrofit2.http.Query
|
||||||
|
|
||||||
|
|
||||||
interface NewWeatherApi : Api {
|
interface WeatherApi : Api {
|
||||||
|
|
||||||
@GET("{location}")
|
@GET("{location}")
|
||||||
suspend fun getFromApi(
|
suspend fun getFromApi(
|
||||||
|
@Path("location") location: String,
|
||||||
@Query("contentType") exclude: String = "json",
|
@Query("contentType") exclude: String = "json",
|
||||||
@Query("unitGroup") units: String = "uk",
|
@Query("unitGroup") units: String = "metric"
|
||||||
@Path("location") location: String
|
|
||||||
): Response<WeatherApiResponse>
|
): Response<WeatherApiResponse>
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.appttude.h_mal.atlas_weather.data.network.response.weather
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
data class Alerts(
|
||||||
|
@SerializedName("event") var event: String? = null,
|
||||||
|
@SerializedName("headline") var headline: String? = null,
|
||||||
|
@SerializedName("ends") var ends: String? = null,
|
||||||
|
@SerializedName("endsEpoch") var endsEpoch: Int? = null,
|
||||||
|
@SerializedName("onset") var onset: String? = null,
|
||||||
|
@SerializedName("onsetEpoch") var onsetEpoch: Int? = null,
|
||||||
|
@SerializedName("id") var id: String? = null,
|
||||||
|
@SerializedName("language") var language: String? = null,
|
||||||
|
@SerializedName("link") var link: String? = null,
|
||||||
|
@SerializedName("description") var description: String? = null,
|
||||||
|
)
|
||||||
@@ -18,7 +18,7 @@ data class WeatherApiResponse(
|
|||||||
@SerializedName("tzoffset") var tzoffset: Int? = null,
|
@SerializedName("tzoffset") var tzoffset: Int? = null,
|
||||||
@SerializedName("description") var description: String? = null,
|
@SerializedName("description") var description: String? = null,
|
||||||
@SerializedName("days") var days: ArrayList<Days> = arrayListOf(),
|
@SerializedName("days") var days: ArrayList<Days> = arrayListOf(),
|
||||||
@SerializedName("alerts") var alerts: ArrayList<String> = arrayListOf(),
|
@SerializedName("alerts") var alerts: ArrayList<Alerts> = arrayListOf(),
|
||||||
@SerializedName("currentConditions") var currentConditions: CurrentConditions? = CurrentConditions()
|
@SerializedName("currentConditions") var currentConditions: CurrentConditions? = CurrentConditions()
|
||||||
): DataMapper<FullWeather> {
|
): DataMapper<FullWeather> {
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.appttude.h_mal.atlas_weather.data.repository
|
package com.appttude.h_mal.atlas_weather.data.repository
|
||||||
|
|
||||||
import com.appttude.h_mal.atlas_weather.data.network.NewWeatherApi
|
|
||||||
import com.appttude.h_mal.atlas_weather.data.network.ResponseUnwrap
|
import com.appttude.h_mal.atlas_weather.data.network.ResponseUnwrap
|
||||||
|
import com.appttude.h_mal.atlas_weather.data.network.WeatherApi
|
||||||
import com.appttude.h_mal.atlas_weather.data.network.response.weather.WeatherApiResponse
|
import com.appttude.h_mal.atlas_weather.data.network.response.weather.WeatherApiResponse
|
||||||
import com.appttude.h_mal.atlas_weather.data.prefs.LOCATION_CONST
|
import com.appttude.h_mal.atlas_weather.data.prefs.LOCATION_CONST
|
||||||
import com.appttude.h_mal.atlas_weather.data.prefs.PreferenceProvider
|
import com.appttude.h_mal.atlas_weather.data.prefs.PreferenceProvider
|
||||||
@@ -12,7 +12,7 @@ import com.appttude.h_mal.atlas_weather.utils.FALLBACK_TIME
|
|||||||
|
|
||||||
|
|
||||||
class RepositoryImpl(
|
class RepositoryImpl(
|
||||||
private val api: NewWeatherApi,
|
private val api: WeatherApi,
|
||||||
private val db: AppDatabase,
|
private val db: AppDatabase,
|
||||||
private val prefs: PreferenceProvider
|
private val prefs: PreferenceProvider
|
||||||
) : Repository, ResponseUnwrap() {
|
) : Repository, ResponseUnwrap() {
|
||||||
@@ -21,7 +21,8 @@ class RepositoryImpl(
|
|||||||
lat: String,
|
lat: String,
|
||||||
long: String
|
long: String
|
||||||
): WeatherApiResponse {
|
): WeatherApiResponse {
|
||||||
return responseUnwrap { api.getFromApi(location = lat + long) }
|
val unit = if (prefs.getUnitsType() == UnitType.METRIC) "metric" else "us"
|
||||||
|
return responseUnwrap { api.getFromApi(location = "$lat,$long", units = unit) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun saveCurrentWeatherToRoom(entityItem: EntityItem) {
|
override suspend fun saveCurrentWeatherToRoom(entityItem: EntityItem) {
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ class ServicesHelper(
|
|||||||
|
|
||||||
val list = mutableListOf<InnerWidgetCellData>()
|
val list = mutableListOf<InnerWidgetCellData>()
|
||||||
|
|
||||||
result.weather.daily?.drop(1)?.dropLast(2)?.forEach { dailyWeather ->
|
result.weather.daily?.drop(1)?.dropLast(1)?.forEach { dailyWeather ->
|
||||||
val day = dailyWeather.dt?.toSmallDayName()
|
val day = dailyWeather.dt?.toSmallDayName()
|
||||||
val icon = dailyWeather.icon
|
val icon = dailyWeather.icon
|
||||||
val temp = dailyWeather.max?.toInt().toString()
|
val temp = dailyWeather.max?.toInt().toString()
|
||||||
@@ -220,7 +220,7 @@ class ServicesHelper(
|
|||||||
|
|
||||||
val list = mutableListOf<InnerWidgetCellData>()
|
val list = mutableListOf<InnerWidgetCellData>()
|
||||||
|
|
||||||
result.weather.daily?.drop(1)?.dropLast(2)?.forEach { dailyWeather ->
|
result.weather.daily?.drop(1)?.dropLast(1)?.forEach { dailyWeather ->
|
||||||
val day = dailyWeather.dt?.toSmallDayName()
|
val day = dailyWeather.dt?.toSmallDayName()
|
||||||
val icon = dailyWeather.icon
|
val icon = dailyWeather.icon
|
||||||
val temp = dailyWeather.max?.toInt().toString()
|
val temp = dailyWeather.max?.toInt().toString()
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.appttude.h_mal.atlas_weather.data.repository
|
package com.appttude.h_mal.atlas_weather.data.repository
|
||||||
|
|
||||||
import com.appttude.h_mal.atlas_weather.data.network.NewWeatherApi
|
import com.appttude.h_mal.atlas_weather.data.network.WeatherApi
|
||||||
import com.appttude.h_mal.atlas_weather.data.network.response.weather.WeatherApiResponse
|
import com.appttude.h_mal.atlas_weather.data.network.response.weather.WeatherApiResponse
|
||||||
import com.appttude.h_mal.atlas_weather.data.prefs.LOCATION_CONST
|
import com.appttude.h_mal.atlas_weather.data.prefs.LOCATION_CONST
|
||||||
import com.appttude.h_mal.atlas_weather.data.prefs.PreferenceProvider
|
import com.appttude.h_mal.atlas_weather.data.prefs.PreferenceProvider
|
||||||
@@ -18,7 +18,8 @@ import kotlinx.coroutines.runBlocking
|
|||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.mockito.ArgumentMatchers.anyDouble
|
import org.mockito.ArgumentMatchers.anyDouble
|
||||||
import java.io.IOException
|
import org.mockito.ArgumentMatchers.anyString
|
||||||
|
import retrofit2.HttpException
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertFailsWith
|
import kotlin.test.assertFailsWith
|
||||||
import kotlin.test.assertIs
|
import kotlin.test.assertIs
|
||||||
@@ -30,7 +31,7 @@ class RepositoryImplTest : BaseTest() {
|
|||||||
|
|
||||||
lateinit var repository: RepositoryImpl
|
lateinit var repository: RepositoryImpl
|
||||||
|
|
||||||
@MockK lateinit var api: NewWeatherApi
|
@MockK lateinit var api: WeatherApi
|
||||||
|
|
||||||
@MockK
|
@MockK
|
||||||
lateinit var db: AppDatabase
|
lateinit var db: AppDatabase
|
||||||
@@ -93,7 +94,7 @@ class RepositoryImplTest : BaseTest() {
|
|||||||
//Act
|
//Act
|
||||||
//create a successful retrofit response
|
//create a successful retrofit response
|
||||||
every { prefs.getUnitsType() } returns (UnitType.METRIC)
|
every { prefs.getUnitsType() } returns (UnitType.METRIC)
|
||||||
coEvery { api.getFromApi(location = lat + long) }.returns(mockResponse)
|
coEvery { api.getFromApi(location = "$lat,$long") }.returns(mockResponse)
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
runBlocking {
|
runBlocking {
|
||||||
@@ -105,20 +106,25 @@ class RepositoryImplTest : BaseTest() {
|
|||||||
@Test
|
@Test
|
||||||
fun getWeatherFromApi_validLatLong_invalidResponse() {
|
fun getWeatherFromApi_validLatLong_invalidResponse() {
|
||||||
//Arrange
|
//Arrange
|
||||||
val mockResponse = createErrorRetrofitMock<WeatherApiResponse>()
|
val errorMessage = "Why dont you have a valid api key?"
|
||||||
|
val mockResponse = createErrorRetrofitMock<WeatherApiResponse>(errorMessage)
|
||||||
|
val lat = anyString()
|
||||||
|
val long = anyString()
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
//create a successful retrofit response
|
//create a successful retrofit response
|
||||||
every { prefs.getUnitsType() } returns (UnitType.METRIC)
|
every { prefs.getUnitsType() } returns (UnitType.METRIC)
|
||||||
coEvery { api.getFromApi(location = any()) } returns (mockResponse)
|
coEvery { api.getFromApi(location = "$lat,$long") } returns (mockResponse)
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
val ioExceptionReturned = assertFailsWith<IOException> {
|
val ioExceptionReturned = assertFailsWith<HttpException> {
|
||||||
runBlocking {
|
runBlocking {
|
||||||
repository.getWeatherFromApi("", "")
|
repository.getWeatherFromApi(lat, long)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assertEquals(ioExceptionReturned.message, "Error Code: 400")
|
|
||||||
|
assertEquals(ioExceptionReturned.code(), 400)
|
||||||
|
assertEquals(ioExceptionReturned.message(), "Why dont you have a valid api key?")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ import com.google.gson.Gson
|
|||||||
import com.google.gson.reflect.TypeToken
|
import com.google.gson.reflect.TypeToken
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
import okhttp3.ResponseBody
|
import okhttp3.ResponseBody
|
||||||
|
import okhttp3.ResponseBody.Companion.toResponseBody
|
||||||
import retrofit2.Response
|
import retrofit2.Response
|
||||||
|
|
||||||
|
|
||||||
@@ -29,9 +31,17 @@ open class BaseTest {
|
|||||||
|
|
||||||
fun <T: Any> createErrorRetrofitMock(code: Int = 400): Response<T> {
|
fun <T: Any> createErrorRetrofitMock(code: Int = 400): Response<T> {
|
||||||
val responseBody = mockk<ResponseBody>(relaxed = true)
|
val responseBody = mockk<ResponseBody>(relaxed = true)
|
||||||
val rawResponse = mockk<okhttp3.Response>().also {
|
|
||||||
every { it.code } returns code
|
|
||||||
}
|
|
||||||
return Response.error<T>(code, responseBody)
|
return Response.error<T>(code, responseBody)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <T: Any> createErrorRetrofitMock(errorMessage: String, code: Int = 400): Response<T> {
|
||||||
|
val responseBody = errorMessage.toResponseBody("application/json".toMediaType())
|
||||||
|
val rawResponse = mockk<okhttp3.Response>(relaxed = true).also {
|
||||||
|
every { it.code } returns code
|
||||||
|
every { it.isSuccessful } returns false
|
||||||
|
every { it.body } returns responseBody
|
||||||
|
every { it.message } returns errorMessage
|
||||||
|
}
|
||||||
|
return Response.error<T>(responseBody, rawResponse)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -40,7 +40,7 @@ RETROFIT_VERSION = 2.9.0
|
|||||||
OKHTTP_VERSION = 4.9.0
|
OKHTTP_VERSION = 4.9.0
|
||||||
MOKITO_INLINE_VERSION = 2.13.0
|
MOKITO_INLINE_VERSION = 2.13.0
|
||||||
CORE_TEST_VERSION = 2.2.0
|
CORE_TEST_VERSION = 2.2.0
|
||||||
MOCKK_VERSION = 1.10.5
|
MOCKK_VERSION = 1.13.12
|
||||||
TEST_JUNIT_VERSION = 1.2.0
|
TEST_JUNIT_VERSION = 1.2.0
|
||||||
TEST_RUNNER_VERSION = 1.5.2
|
TEST_RUNNER_VERSION = 1.5.2
|
||||||
ESPRESSO_VERSION = 3.6.0
|
ESPRESSO_VERSION = 3.6.0
|
||||||
|
|||||||
Reference in New Issue
Block a user