- Remove old api and response

This commit is contained in:
2024-09-30 10:57:03 +01:00
parent 8507116e5a
commit 79c123021a
31 changed files with 236 additions and 719 deletions

View File

@@ -67,7 +67,7 @@ open class BaseTest<A : Activity>(
}
testApp =
InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as TestAppClass
InstrumentationRegistry.getInstrumentation().targetContext.applicationContext
runBlocking {
beforeLaunch()
}

View File

@@ -60,7 +60,7 @@ open class BaseTestRobot {
.atPosition(position).perform(click())
}
fun <VH : ViewHolder> scrollToRecyclerItem(recyclerId: Int, text: String): ViewInteraction? {
fun <VH : ViewHolder> scrollToRecyclerItem(recyclerId: Int, text: String): ViewInteraction {
return matchView(recyclerId)
.perform(
// scrollTo will fail the test if no item matches.
@@ -73,7 +73,7 @@ open class BaseTestRobot {
fun <VH : ViewHolder> scrollToRecyclerItem(
recyclerId: Int,
resIdForString: Int
): ViewInteraction? {
): ViewInteraction {
return matchView(recyclerId)
.perform(
// scrollTo will fail the test if no item matches.
@@ -86,7 +86,7 @@ open class BaseTestRobot {
fun <VH : ViewHolder> scrollToRecyclerItemByPosition(
recyclerId: Int,
position: Int
): ViewInteraction? {
): ViewInteraction {
return matchView(recyclerId)
.perform(
// scrollTo will fail the test if no item matches.

View File

@@ -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.MockLocationProvider
import com.appttude.h_mal.atlas_weather.data.network.NetworkModule
import com.appttude.h_mal.atlas_weather.data.network.WeatherApi
import com.appttude.h_mal.atlas_weather.data.network.NewWeatherApi
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.QueryParamsInterceptor
@@ -28,8 +28,8 @@ class TestAppClass : AppClass() {
IdlingRegistry.getInstance().register(idlingResources)
}
override fun createNetworkModule(): WeatherApi {
return NetworkModule().invoke<WeatherApi>(
override fun createNetworkModule(): NewWeatherApi {
return NetworkModule().invoke<NewWeatherApi>(
mockingNetworkInterceptor,
NetworkConnectionInterceptor(this),
QueryParamsInterceptor(),

View File

@@ -6,6 +6,7 @@ import androidx.test.filters.SmallTest
import com.appttude.h_mal.atlas_weather.BaseTest
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.furtherInfoScreen
import com.appttude.h_mal.monoWeather.robot.settingsScreen
import com.appttude.h_mal.monoWeather.robot.weatherScreen
@@ -18,8 +19,8 @@ import tools.fastlane.screengrab.Screengrab
class SnapshotCaptureTest : BaseTest<MainActivity>(MainActivity::class.java) {
override fun beforeLaunch() {
stubEndpoint("https://api.openweathermap.org/data/2.5/onecall", Stubs.Metric)
stubLocation("London", 51.51, -0.13)
stubEndpoint(baseUrl, Stubs.New)
stubLocation("London", 51.5064, -0.12721)
clearPrefs()
}

View File

@@ -11,6 +11,7 @@ import org.junit.Test
class HomePageNoDataUITest : BaseTest<MainActivity>(MainActivity::class.java) {
override fun beforeLaunch() {
// Todo: change this
stubEndpoint("https://api.openweathermap.org/data/2.5/onecall", Stubs.InvalidKey, 400)
}

View File

@@ -4,6 +4,7 @@ package com.appttude.h_mal.monoWeather.tests
import com.appttude.h_mal.atlas_weather.BaseTest
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.ContainerRobot.Tab.WORLD
import com.appttude.h_mal.monoWeather.robot.addLocation
import com.appttude.h_mal.monoWeather.robot.container
@@ -14,7 +15,8 @@ import org.junit.Test
class WorldPageUITest : BaseTest<MainActivity>(MainActivity::class.java) {
override fun beforeLaunch() {
stubEndpoint("https://api.openweathermap.org/data/2.5/onecall", Stubs.Metric)
stubEndpoint(baseUrl, Stubs.New)
stubLocation("London", 51.5064, -0.12721)
}
@Test
@@ -26,6 +28,7 @@ class WorldPageUITest : BaseTest<MainActivity>(MainActivity::class.java) {
clickFab()
}
addLocation {
// Todo: change this
stubEndpoint("https://api.openweathermap.org/data/2.5/onecall", Stubs.Sydney)
stubLocation("Sydney", -33.89, -151.12)
setLocation("Sydney")

View File

@@ -9,8 +9,6 @@ import retrofit2.http.Query
interface NewWeatherApi : Api {
// Todo: change the location
// Todo: add endpoint for lat/long
@GET("{location}")
suspend fun getFromApi(
@Query("contentType") exclude: String = "json",

View File

@@ -1,20 +0,0 @@
package com.appttude.h_mal.atlas_weather.data.network
import com.appttude.h_mal.atlas_weather.data.network.response.forecast.WeatherResponse
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Query
interface WeatherApi : Api {
@GET("onecall?")
suspend fun getFromApi(
@Query("lat") query: String,
@Query("lon") lon: String,
@Query("exclude") exclude: String = "minutely",
@Query("units") units: String = "metric"
): Response<WeatherResponse>
}

View File

@@ -1,48 +0,0 @@
package com.appttude.h_mal.atlas_weather.data.network.response.forecast
import com.google.gson.annotations.SerializedName
data class Current(
@field:SerializedName("sunrise")
val sunrise: Int? = null,
@field:SerializedName("temp")
val temp: Double? = null,
@field:SerializedName("visibility")
val visibility: Int? = null,
@field:SerializedName("uvi")
val uvi: Double? = null,
@field:SerializedName("pressure")
val pressure: Int? = null,
@field:SerializedName("clouds")
val clouds: Int? = null,
@field:SerializedName("feels_like")
val feelsLike: Double? = null,
@field:SerializedName("dt")
val dt: Int? = null,
@field:SerializedName("wind_deg")
val windDeg: Int? = null,
@field:SerializedName("dew_point")
val dewPoint: Double? = null,
@field:SerializedName("sunset")
val sunset: Int? = null,
@field:SerializedName("weather")
val weather: List<WeatherItem?>? = null,
@field:SerializedName("humidity")
val humidity: Int? = null,
@field:SerializedName("wind_speed")
val windSpeed: Double? = null
)

View File

@@ -1,51 +0,0 @@
package com.appttude.h_mal.atlas_weather.data.network.response.forecast
import com.google.gson.annotations.SerializedName
data class DailyItem(
@field:SerializedName("sunrise")
val sunrise: Int? = null,
@field:SerializedName("temp")
val temp: Temp? = null,
@field:SerializedName("uvi")
val uvi: Double? = null,
@field:SerializedName("pressure")
val pressure: Int? = null,
@field:SerializedName("clouds")
val clouds: Int? = null,
@field:SerializedName("feels_like")
val feelsLike: FeelsLike? = null,
@field:SerializedName("dt")
val dt: Int? = null,
@field:SerializedName("pop")
val pop: Double? = null,
@field:SerializedName("wind_deg")
val windDeg: Int? = null,
@field:SerializedName("dew_point")
val dewPoint: Double? = null,
@field:SerializedName("sunset")
val sunset: Int? = null,
@field:SerializedName("weather")
val weather: List<WeatherItem?>? = null,
@field:SerializedName("humidity")
val humidity: Int? = null,
@field:SerializedName("wind_speed")
val windSpeed: Double? = null,
@field:SerializedName("rain")
val rain: Double? = null
)

View File

@@ -1,18 +0,0 @@
package com.appttude.h_mal.atlas_weather.data.network.response.forecast
import com.google.gson.annotations.SerializedName
data class FeelsLike(
@field:SerializedName("eve")
val eve: Double? = null,
@field:SerializedName("night")
val night: Double? = null,
@field:SerializedName("day")
val day: Double? = null,
@field:SerializedName("morn")
val morn: Double? = null
)

View File

@@ -1,48 +0,0 @@
package com.appttude.h_mal.atlas_weather.data.network.response.forecast
import com.google.gson.annotations.SerializedName
data class Hour(
@field:SerializedName("sunrise")
val sunrise: Int? = null,
@field:SerializedName("temp")
val temp: Double? = null,
@field:SerializedName("visibility")
val visibility: Int? = null,
@field:SerializedName("uvi")
val uvi: Double? = null,
@field:SerializedName("pressure")
val pressure: Int? = null,
@field:SerializedName("clouds")
val clouds: Int? = null,
@field:SerializedName("feels_like")
val feelsLike: Double? = null,
@field:SerializedName("dt")
val dt: Int? = null,
@field:SerializedName("wind_deg")
val windDeg: Int? = null,
@field:SerializedName("dew_point")
val dewPoint: Double? = null,
@field:SerializedName("sunset")
val sunset: Int? = null,
@field:SerializedName("weather")
val weather: List<WeatherItem?>? = null,
@field:SerializedName("humidity")
val humidity: Int? = null,
@field:SerializedName("wind_speed")
val windSpeed: Double? = null
)

View File

@@ -1,24 +0,0 @@
package com.appttude.h_mal.atlas_weather.data.network.response.forecast
import com.google.gson.annotations.SerializedName
data class Response(
@field:SerializedName("current")
val current: Current? = null,
@field:SerializedName("timezone")
val timezone: String? = null,
@field:SerializedName("timezone_offset")
val timezoneOffset: Int? = null,
@field:SerializedName("daily")
val daily: List<DailyItem?>? = null,
@field:SerializedName("lon")
val lon: Double? = null,
@field:SerializedName("lat")
val lat: Double? = null
)

View File

@@ -1,24 +0,0 @@
package com.appttude.h_mal.atlas_weather.data.network.response.forecast
import com.google.gson.annotations.SerializedName
data class Temp(
@field:SerializedName("min")
val min: Double? = null,
@field:SerializedName("max")
val max: Double? = null,
@field:SerializedName("eve")
val eve: Double? = null,
@field:SerializedName("night")
val night: Double? = null,
@field:SerializedName("day")
val day: Double? = null,
@field:SerializedName("morn")
val morn: Double? = null
)

View File

@@ -1,18 +0,0 @@
package com.appttude.h_mal.atlas_weather.data.network.response.forecast
import com.google.gson.annotations.SerializedName
data class WeatherItem(
@field:SerializedName("icon")
val icon: String? = null,
@field:SerializedName("description")
val description: String? = null,
@field:SerializedName("main")
val main: String? = null,
@field:SerializedName("id")
val id: Int? = null
)

View File

@@ -1,28 +0,0 @@
package com.appttude.h_mal.atlas_weather.data.network.response.forecast
import com.google.gson.annotations.SerializedName
data class WeatherResponse(
@field:SerializedName("current")
val current: Current? = null,
@field:SerializedName("timezone")
val timezone: String? = null,
@field:SerializedName("timezone_offset")
val timezoneOffset: Int? = null,
@field:SerializedName("hourly")
val hourly: List<Hour>? = null,
@field:SerializedName("daily")
val daily: List<DailyItem>? = null,
@field:SerializedName("lon")
val lon: Double = 0.00,
@field:SerializedName("lat")
val lat: Double = 0.00
)

View File

@@ -0,0 +1,36 @@
package com.appttude.h_mal.atlas_weather.data.network.response.weather
import com.google.gson.annotations.SerializedName
data class CurrentConditions(
@SerializedName("datetime") var datetime: String? = null,
@SerializedName("datetimeEpoch") var datetimeEpoch: Int? = null,
@SerializedName("temp") var temp: Double? = null,
@SerializedName("feelslike") var feelslike: Double? = null,
@SerializedName("humidity") var humidity: Double? = null,
@SerializedName("dew") var dew: Double? = null,
@SerializedName("precip") var precip: Double? = null,
@SerializedName("precipprob") var precipprob: Double? = null,
@SerializedName("snow") var snow: Int? = null,
@SerializedName("snowdepth") var snowdepth: Int? = null,
@SerializedName("preciptype") var preciptype: ArrayList<String> = arrayListOf(),
@SerializedName("windgust") var windgust: Double? = null,
@SerializedName("windspeed") var windspeed: Double? = null,
@SerializedName("winddir") var winddir: Double? = null,
@SerializedName("pressure") var pressure: Double? = null,
@SerializedName("visibility") var visibility: Double? = null,
@SerializedName("cloudcover") var cloudcover: Double? = null,
@SerializedName("solarradiation") var solarradiation: Double? = null,
@SerializedName("solarenergy") var solarenergy: Double? = null,
@SerializedName("uvindex") var uvindex: Int? = null,
@SerializedName("conditions") var conditions: String? = null,
@SerializedName("icon") var icon: String? = null,
@SerializedName("stations") var stations: ArrayList<String> = arrayListOf(),
@SerializedName("source") var source: String? = null,
@SerializedName("sunrise") var sunrise: String? = null,
@SerializedName("sunriseEpoch") var sunriseEpoch: Int? = null,
@SerializedName("sunset") var sunset: String? = null,
@SerializedName("sunsetEpoch") var sunsetEpoch: Int? = null,
@SerializedName("moonphase") var moonphase: Double? = null
)

View File

@@ -0,0 +1,45 @@
package com.appttude.h_mal.atlas_weather.data.network.response.weather
import com.google.gson.annotations.SerializedName
data class Days(
@SerializedName("datetime") var datetime: String? = null,
@SerializedName("datetimeEpoch") var datetimeEpoch: Int? = null,
@SerializedName("tempmax") var tempmax: Double? = null,
@SerializedName("tempmin") var tempmin: Double? = null,
@SerializedName("temp") var temp: Double? = null,
@SerializedName("feelslikemax") var feelslikemax: Double? = null,
@SerializedName("feelslikemin") var feelslikemin: Double? = null,
@SerializedName("feelslike") var feelslike: Double? = null,
@SerializedName("dew") var dew: Double? = null,
@SerializedName("humidity") var humidity: Double? = null,
@SerializedName("precip") var precip: Number? = null,
@SerializedName("precipprob") var precipprob: Double? = null,
@SerializedName("precipcover") var precipcover: Double? = null,
@SerializedName("preciptype") var preciptype: ArrayList<String> = arrayListOf(),
@SerializedName("snow") var snow: Int? = null,
@SerializedName("snowdepth") var snowdepth: Int? = null,
@SerializedName("windgust") var windgust: Double? = null,
@SerializedName("windspeed") var windspeed: Double? = null,
@SerializedName("winddir") var winddir: Double? = null,
@SerializedName("pressure") var pressure: Double? = null,
@SerializedName("cloudcover") var cloudcover: Double? = null,
@SerializedName("visibility") var visibility: Double? = null,
@SerializedName("solarradiation") var solarradiation: Double? = null,
@SerializedName("solarenergy") var solarenergy: Double? = null,
@SerializedName("uvindex") var uvindex: Int? = null,
@SerializedName("severerisk") var severerisk: Int? = null,
@SerializedName("sunrise") var sunrise: String? = null,
@SerializedName("sunriseEpoch") var sunriseEpoch: Int? = null,
@SerializedName("sunset") var sunset: String? = null,
@SerializedName("sunsetEpoch") var sunsetEpoch: Int? = null,
@SerializedName("moonphase") var moonphase: Double? = null,
@SerializedName("conditions") var conditions: String? = null,
@SerializedName("description") var description: String? = null,
@SerializedName("icon") var icon: String? = null,
@SerializedName("stations") var stations: ArrayList<String> = arrayListOf(),
@SerializedName("source") var source: String? = null,
@SerializedName("hours") var hours: ArrayList<Hours> = arrayListOf()
)

View File

@@ -0,0 +1,32 @@
package com.appttude.h_mal.atlas_weather.data.network.response.weather
import com.google.gson.annotations.SerializedName
data class Hours(
@SerializedName("datetime") var datetime: String? = null,
@SerializedName("datetimeEpoch") var datetimeEpoch: Int? = null,
@SerializedName("temp") var temp: Double? = null,
@SerializedName("feelslike") var feelslike: Double? = null,
@SerializedName("humidity") var humidity: Double? = null,
@SerializedName("dew") var dew: Double? = null,
@SerializedName("precip") var precip: Number? = null,
@SerializedName("precipprob") var precipprob: Double? = null,
@SerializedName("snow") var snow: Int? = null,
@SerializedName("snowdepth") var snowdepth: Int? = null,
@SerializedName("preciptype") var preciptype: ArrayList<String> = arrayListOf(),
@SerializedName("windgust") var windgust: Double? = null,
@SerializedName("windspeed") var windspeed: Double? = null,
@SerializedName("winddir") var winddir: Double? = null,
@SerializedName("pressure") var pressure: Double? = null,
@SerializedName("visibility") var visibility: Double? = null,
@SerializedName("cloudcover") var cloudcover: Double? = null,
@SerializedName("solarradiation") var solarradiation: Double? = null,
@SerializedName("solarenergy") var solarenergy: Double? = null,
@SerializedName("uvindex") var uvindex: Int? = null,
@SerializedName("severerisk") var severerisk: Int? = null,
@SerializedName("conditions") var conditions: String? = null,
@SerializedName("icon") var icon: String? = null,
@SerializedName("stations") var stations: ArrayList<String> = arrayListOf(),
@SerializedName("source") var source: String? = null
)

View File

@@ -0,0 +1,15 @@
package com.appttude.h_mal.atlas_weather.data.network.response.weather
import com.appttude.h_mal.atlas_weather.EGLL
import com.appttude.h_mal.atlas_weather.EGWU
import com.appttude.h_mal.atlas_weather.F8628
import com.google.gson.annotations.SerializedName
data class Stations (
@SerializedName("EGWU" ) var EGWU : EGWU? = EGWU(),
@SerializedName("EGLC" ) var EGLC : EGLC? = EGLC(),
@SerializedName("EGLL" ) var EGLL : EGLL? = EGLL(),
@SerializedName("D5621" ) var D5621 : D5621? = D5621(),
@SerializedName("F8628" ) var F8628 : F8628? = F8628()
)

View File

@@ -0,0 +1,41 @@
package com.appttude.h_mal.atlas_weather.data.network.response.weather
import com.appttude.h_mal.atlas_weather.model.DataMapper
import com.appttude.h_mal.atlas_weather.model.weather.Current
import com.appttude.h_mal.atlas_weather.model.weather.DailyWeather
import com.appttude.h_mal.atlas_weather.model.weather.FullWeather
import com.google.gson.annotations.SerializedName
import com.appttude.h_mal.atlas_weather.model.weather.Hour as FullWeatherHour
data class WeatherApiResponse(
@SerializedName("queryCost") var queryCost: Int? = null,
@SerializedName("latitude") var latitude: Double? = null,
@SerializedName("longitude") var longitude: Double? = null,
@SerializedName("resolvedAddress") var resolvedAddress: String? = null,
@SerializedName("address") var address: String? = null,
@SerializedName("timezone") var timezone: String? = null,
@SerializedName("tzoffset") var tzoffset: Int? = null,
@SerializedName("description") var description: String? = null,
@SerializedName("days") var days: ArrayList<Days> = arrayListOf(),
@SerializedName("alerts") var alerts: ArrayList<String> = arrayListOf(),
// @SerializedName("stations") var stations: Stations? = Stations(),
@SerializedName("currentConditions") var currentConditions: CurrentConditions? = CurrentConditions()
): DataMapper<FullWeather> {
override fun mapData(): FullWeather {
val hours = mutableListOf(days[0].hours).apply { add(days[1].hours) }.flatten().subList(0,23).map { FullWeatherHour(it) }.toList()
val collectedDays = mutableListOf(days.subList(0,7)).flatten().map { DailyWeather(it) }.toList()
return FullWeather(
current = Current(currentConditions),
timezone = timezone,
timezoneOffset = tzoffset,
hourly = hours,
daily = collectedDays,
lat = latitude,
lon = longitude,
locationString = address,
temperatureUnit = null
)
}
}

View File

@@ -144,7 +144,7 @@ class ServicesHelper(
result.weather.let {
val bitmap = it.current?.icon
val location = locationProvider.getLocationNameFromLatLong(it.lat, it.lon)
val location = locationProvider.getLocationNameFromLatLong(it.lat!!, it.lon!!)
val temp = it.current?.temp?.toInt().toString()
WidgetData(location, bitmap, temp, epoc)
@@ -181,7 +181,7 @@ class ServicesHelper(
val widgetData = result.weather.let {
val bitmap = it.current?.icon
val location = locationProvider.getLocationNameFromLatLong(it.lat, it.lon)
val location = locationProvider.getLocationNameFromLatLong(it.lat!!, it.lon!!)
val temp = it.current?.temp?.toInt().toString()
val epoc = System.currentTimeMillis()

View File

@@ -40,8 +40,7 @@ data class Forecast(
parcel.readString(),
parcel.readString(),
parcel.readString()
) {
}
)
constructor(dailyWeather: DailyWeather) : this(
dailyWeather.dt?.toDayString(),

View File

@@ -40,8 +40,7 @@ data class WeatherDisplay(
parcel.readDouble(),
parcel.readDouble(),
parcel.readString()
) {
}
)
constructor(entity: EntityItem) : this(
entity.weather.current?.temp,
@@ -56,8 +55,8 @@ data class WeatherDisplay(
entity.weather.daily?.get(0)?.pop?.times(100)?.toInt()?.toString(),
entity.weather.current?.humidity?.toString(),
entity.weather.current?.clouds?.toString(),
entity.weather.lat,
entity.weather.lon,
entity.weather.lat!!,
entity.weather.lon!!,
entity.weather.locationString
)

View File

@@ -1,6 +1,5 @@
package com.appttude.h_mal.atlas_weather.model.weather
import com.appttude.h_mal.atlas_weather.data.network.response.forecast.Current
import com.appttude.h_mal.atlas_weather.data.network.response.weather.CurrentConditions
import com.appttude.h_mal.atlas_weather.model.IconMapper
import com.appttude.h_mal.atlas_weather.utils.generateIconUrlString
@@ -25,27 +24,7 @@ data class Current(
val windSpeed: Double? = null
) {
constructor(dailyItem: Current) : this(
dailyItem.dt,
dailyItem.sunrise,
dailyItem.sunset,
dailyItem.temp,
dailyItem.visibility,
dailyItem.uvi,
dailyItem.pressure,
dailyItem.clouds,
dailyItem.feelsLike,
dailyItem.windDeg,
dailyItem.dewPoint,
generateIconUrlString(dailyItem.weather?.getOrNull(0)?.icon),
dailyItem.weather?.get(0)?.description,
dailyItem.weather?.get(0)?.main,
dailyItem.weather?.get(0)?.id,
dailyItem.humidity,
dailyItem.windSpeed
)
constructor(currentConditions: CurrentConditions?): this(
constructor(currentConditions: CurrentConditions?) : this(
dt = currentConditions?.datetimeEpoch,
sunrise = currentConditions?.sunriseEpoch,
sunset = currentConditions?.sunsetEpoch,

View File

@@ -1,6 +1,5 @@
package com.appttude.h_mal.atlas_weather.model.weather
import com.appttude.h_mal.atlas_weather.data.network.response.forecast.DailyItem
import com.appttude.h_mal.atlas_weather.data.network.response.weather.Days
import com.appttude.h_mal.atlas_weather.model.IconMapper
import com.appttude.h_mal.atlas_weather.utils.generateIconUrlString
@@ -29,29 +28,6 @@ data class DailyWeather(
val rain: Double?
) {
constructor(dailyItem: DailyItem) : this(
dailyItem.dt,
dailyItem.sunrise,
dailyItem.sunset,
dailyItem.temp?.min,
dailyItem.temp?.max,
dailyItem.temp?.day,
dailyItem.feelsLike?.day,
dailyItem.pressure,
dailyItem.humidity,
dailyItem.dewPoint,
dailyItem.windSpeed,
dailyItem.windDeg,
generateIconUrlString(dailyItem.weather?.getOrNull(0)?.icon),
dailyItem.weather?.get(0)?.description,
dailyItem.weather?.get(0)?.main,
dailyItem.weather?.get(0)?.id,
dailyItem.clouds,
dailyItem.pop,
dailyItem.uvi,
dailyItem.rain
)
constructor(days: Days) : this(
days.datetimeEpoch,
days.sunriseEpoch,
@@ -77,5 +53,4 @@ data class DailyWeather(
days.precip?.toDouble()
)
}

View File

@@ -1,29 +1,15 @@
package com.appttude.h_mal.atlas_weather.model.weather
import com.appttude.h_mal.atlas_weather.data.network.response.forecast.WeatherResponse
data class FullWeather(
val current: Current? = null,
val timezone: String? = null,
val timezoneOffset: Int? = null,
val hourly: List<Hour>? = null,
val daily: List<DailyWeather>? = null,
val lon: Double = 0.00,
val lat: Double = 0.00,
val lon: Double? = null,
val lat: Double? = null,
var locationString: String? = null,
var temperatureUnit: String? = null
) {
constructor(weatherResponse: WeatherResponse) : this(
weatherResponse.current?.let { Current(it) },
weatherResponse.timezone,
weatherResponse.timezoneOffset,
weatherResponse.hourly?.subList(0, 23)?.map { Hour(it) },
weatherResponse.daily?.map { DailyWeather(it) },
weatherResponse.lon,
weatherResponse.lat
)
}
)

View File

@@ -4,7 +4,6 @@ import android.os.Parcel
import android.os.Parcelable
import com.appttude.h_mal.atlas_weather.model.IconMapper
import com.appttude.h_mal.atlas_weather.utils.generateIconUrlString
import com.appttude.h_mal.atlas_weather.data.network.response.forecast.Hour as ForecastHour
import com.appttude.h_mal.atlas_weather.data.network.response.weather.Hours as WeatherHour
@@ -18,15 +17,9 @@ data class Hour(
parcel.readValue(Int::class.java.classLoader) as? Int,
parcel.readValue(Double::class.java.classLoader) as? Double,
parcel.readString()
) {
}
constructor(hour: ForecastHour) : this(
hour.dt,
hour.temp,
generateIconUrlString(hour.weather?.getOrNull(0)?.icon)
)
constructor(weatherHour: WeatherHour) : this(
weatherHour.datetimeEpoch,
weatherHour.temp,

View File

@@ -17,6 +17,7 @@ import io.mockk.mockk
import kotlinx.coroutines.runBlocking
import org.junit.Before
import org.junit.Test
import org.mockito.ArgumentMatchers.anyDouble
import java.io.IOException
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
@@ -85,16 +86,18 @@ class RepositoryImplTest : BaseTest() {
@Test
fun getWeatherFromApi_validLatLong_validSearch() {
//Arrange
val lat = anyDouble().toString()
val long = anyDouble().toString()
val mockResponse = createSuccessfulRetrofitMock<WeatherApiResponse>()
//Act
//create a successful retrofit response
every { prefs.getUnitsType() } returns (UnitType.METRIC)
coEvery { api.getFromApi(location = "") }.returns(mockResponse)
coEvery { api.getFromApi(location = lat + long) }.returns(mockResponse)
// Assert
runBlocking {
val result = repository.getWeatherFromApi("", "")
val result = repository.getWeatherFromApi(lat, long)
assertIs<WeatherApiResponse>(result)
}
}

View File

@@ -3,7 +3,7 @@ package com.appttude.h_mal.atlas_weather.viewmodel
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.appttude.h_mal.atlas_weather.data.WeatherSource
import com.appttude.h_mal.atlas_weather.data.location.LocationProviderImpl
import com.appttude.h_mal.atlas_weather.data.network.response.forecast.WeatherResponse
import com.appttude.h_mal.atlas_weather.data.network.response.weather.WeatherApiResponse
import com.appttude.h_mal.atlas_weather.data.room.entity.CURRENT_LOCATION
import com.appttude.h_mal.atlas_weather.model.ViewState
import com.appttude.h_mal.atlas_weather.model.types.LocationType
@@ -21,10 +21,10 @@ import io.mockk.impl.annotations.RelaxedMockK
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mockito.ArgumentMatchers
import org.mockito.ArgumentMatchers.anyList
import org.mockito.ArgumentMatchers.anyString
import java.io.IOException
import kotlin.properties.Delegates
import kotlin.test.assertEquals
import kotlin.test.assertIs
@@ -43,12 +43,23 @@ class WorldViewModelTest : BaseTest() {
@MockK
lateinit var locationProvider: LocationProviderImpl
private lateinit var weatherResponse: WeatherResponse
private lateinit var weatherResponse: WeatherApiResponse
private var lat by Delegates.notNull<Double>()
private var long by Delegates.notNull<Double>()
private lateinit var latlon: Pair<Double, Double>
private lateinit var fullWeather: FullWeather
@Before
fun setUp() {
MockKAnnotations.init(this)
weatherResponse = getTestData("weather_sample.json", WeatherResponse::class.java)
weatherResponse = getTestData("new_response.json", WeatherApiResponse::class.java)
lat = weatherResponse.latitude!!
long = weatherResponse.longitude!!
latlon = Pair(lat, long)
fullWeather = weatherResponse.mapData().apply {
temperatureUnit = "°C"
locationString = CURRENT_LOCATION
}
}
@Test
@@ -58,13 +69,13 @@ class WorldViewModelTest : BaseTest() {
// Act
coEvery { locationProvider.getLatLongFromLocationName(CURRENT_LOCATION) } returns Pair(
weatherResponse.lat,
weatherResponse.lon
lat,
long
)
coEvery {
locationProvider.getLocationNameFromLatLong(
weatherResponse.lat,
weatherResponse.lon,
lat,
long,
LocationType.City
)
}.returns(CURRENT_LOCATION)
@@ -74,7 +85,7 @@ class WorldViewModelTest : BaseTest() {
CURRENT_LOCATION,
locationType = LocationType.City
)
} returns FullWeather(weatherResponse)
} returns fullWeather
// Assert
viewModel.fetchDataForSingleLocation(CURRENT_LOCATION)
@@ -86,17 +97,17 @@ class WorldViewModelTest : BaseTest() {
@Test
fun fetchDataForSingleLocation_failedLocation_validReturn() {
// Arrange
val errorMessage = ArgumentMatchers.anyString()
val errorMessage = anyString()
// Act
coEvery { locationProvider.getLatLongFromLocationName(CURRENT_LOCATION) } returns Pair(
weatherResponse.lat,
weatherResponse.lon
lat,
long
)
coEvery {
locationProvider.getLocationNameFromLatLong(
weatherResponse.lat,
weatherResponse.lon,
lat,
long,
LocationType.City
)
} throws IOException(errorMessage)
@@ -112,18 +123,17 @@ class WorldViewModelTest : BaseTest() {
@Test
fun fetchDataForSingleLocation_failedApi_validReturn() {
// Arrange
val latlon = Pair(weatherResponse.lat, weatherResponse.lon)
val errorMessage = ArgumentMatchers.anyString()
val errorMessage = anyString()
// Act
coEvery { locationProvider.getLatLongFromLocationName(CURRENT_LOCATION) } returns Pair(
weatherResponse.lat,
weatherResponse.lon
lat,
long
)
coEvery {
locationProvider.getLocationNameFromLatLong(
weatherResponse.lat,
weatherResponse.lon,
lat,
long,
LocationType.City
)
}.returns(CURRENT_LOCATION)
@@ -146,15 +156,14 @@ class WorldViewModelTest : BaseTest() {
@Test
fun fetchDataForSingleLocationSearch_validLocation_validReturn() {
// Arrange
val latlon = Pair(weatherResponse.lat, weatherResponse.lon)
// Act
every { weatherSource.repository.getSavedLocations() } returns anyList()
coEvery { locationProvider.getLatLongFromLocationName(CURRENT_LOCATION) } returns latlon
coEvery {
locationProvider.getLocationNameFromLatLong(
weatherResponse.lat,
weatherResponse.lon,
lat,
long,
LocationType.City
)
}.returns(CURRENT_LOCATION)
@@ -164,7 +173,7 @@ class WorldViewModelTest : BaseTest() {
CURRENT_LOCATION,
locationType = LocationType.City
)
} returns FullWeather(weatherResponse).apply { locationString = CURRENT_LOCATION }
} returns fullWeather.apply { locationString = CURRENT_LOCATION }
// Assert
viewModel.fetchDataForSingleLocationSearch(CURRENT_LOCATION)
@@ -192,7 +201,6 @@ class WorldViewModelTest : BaseTest() {
@Test
fun fetchDataForSingleLocationSearch_retrievedLocationExists_validError() {
// Arrange
val latlon = Pair(weatherResponse.lat, weatherResponse.lon)
val retrievedLocation = anyString()
// Act
@@ -200,8 +208,7 @@ class WorldViewModelTest : BaseTest() {
coEvery { locationProvider.getLatLongFromLocationName(CURRENT_LOCATION) } returns latlon
coEvery {
locationProvider.getLocationNameFromLatLong(
weatherResponse.lat,
weatherResponse.lon,
lat, long,
LocationType.City
)
}.returns(CURRENT_LOCATION)
@@ -211,7 +218,7 @@ class WorldViewModelTest : BaseTest() {
CURRENT_LOCATION,
locationType = LocationType.City
)
} returns FullWeather(weatherResponse).apply { locationString = retrievedLocation }
} returns fullWeather.apply { locationString = retrievedLocation }
// Assert
viewModel.fetchDataForSingleLocationSearch(CURRENT_LOCATION)

View File

@@ -1,317 +0,0 @@
{
"lat": 51.5,
"lon": -0.12,
"timezone": "Europe/London",
"timezone_offset": 0,
"current": {
"dt": 1608394319,
"sunrise": 1608364972,
"sunset": 1608393158,
"temp": 9.42,
"feels_like": 4.9,
"pressure": 1007,
"humidity": 91,
"dew_point": 8.03,
"uvi": 0,
"clouds": 33,
"visibility": 10000,
"wind_speed": 5.8,
"wind_deg": 215,
"weather": [
{
"id": 802,
"main": "Clouds",
"description": "scattered clouds",
"icon": "03n"
}
]
},
"daily": [
{
"dt": 1608375600,
"sunrise": 1608364972,
"sunset": 1608393158,
"temp": {
"day": 11.78,
"min": 9.1,
"max": 12.31,
"night": 9.1,
"eve": 9.8,
"morn": 10.8
},
"feels_like": {
"day": 6.46,
"night": 5.08,
"eve": 5.47,
"morn": 4.63
},
"pressure": 1005,
"humidity": 69,
"dew_point": 6.42,
"wind_speed": 6.37,
"wind_deg": 217,
"weather": [
{
"id": 500,
"main": "Rain",
"description": "light rain",
"icon": "10d"
}
],
"clouds": 97,
"pop": 0.98,
"rain": 1.55,
"uvi": 0.53
},
{
"dt": 1608462000,
"sunrise": 1608451406,
"sunset": 1608479581,
"temp": {
"day": 9.9,
"min": 7.41,
"max": 10.52,
"night": 7.41,
"eve": 8.83,
"morn": 8.59
},
"feels_like": {
"day": 4.19,
"night": 3.99,
"eve": 4.55,
"morn": 4.79
},
"pressure": 1013,
"humidity": 64,
"dew_point": 3.48,
"wind_speed": 6.12,
"wind_deg": 226,
"weather": [
{
"id": 500,
"main": "Rain",
"description": "light rain",
"icon": "10d"
}
],
"clouds": 8,
"pop": 0.58,
"rain": 0.65,
"uvi": 0.45
},
{
"dt": 1608548400,
"sunrise": 1608537838,
"sunset": 1608566008,
"temp": {
"day": 11.06,
"min": 7.01,
"max": 13.57,
"night": 13.2,
"eve": 12.68,
"morn": 8.59
},
"feels_like": {
"day": 6.32,
"night": 9.99,
"eve": 9.75,
"morn": 4.64
},
"pressure": 1005,
"humidity": 91,
"dew_point": 9.69,
"wind_speed": 6.7,
"wind_deg": 185,
"weather": [
{
"id": 501,
"main": "Rain",
"description": "moderate rain",
"icon": "10d"
}
],
"clouds": 100,
"pop": 1,
"rain": 7.85,
"uvi": 0.21
},
{
"dt": 1608634800,
"sunrise": 1608624266,
"sunset": 1608652438,
"temp": {
"day": 12.97,
"min": 11.7,
"max": 13.21,
"night": 11.7,
"eve": 12.37,
"morn": 12.93
},
"feels_like": {
"day": 11.39,
"night": 10.49,
"eve": 10.96,
"morn": 9.65
},
"pressure": 1012,
"humidity": 83,
"dew_point": 10.31,
"wind_speed": 2.38,
"wind_deg": 214,
"weather": [
{
"id": 500,
"main": "Rain",
"description": "light rain",
"icon": "10d"
}
],
"clouds": 100,
"pop": 1,
"rain": 3.25,
"uvi": 0.34
},
{
"dt": 1608721200,
"sunrise": 1608710690,
"sunset": 1608738871,
"temp": {
"day": 12.28,
"min": 10.12,
"max": 12.62,
"night": 10.12,
"eve": 10.12,
"morn": 11.73
},
"feels_like": {
"day": 7.48,
"night": 6.73,
"eve": 6.6,
"morn": 8.15
},
"pressure": 1006,
"humidity": 64,
"dew_point": 5.76,
"wind_speed": 5.45,
"wind_deg": 224,
"weather": [
{
"id": 500,
"main": "Rain",
"description": "light rain",
"icon": "10d"
}
],
"clouds": 97,
"pop": 0.94,
"rain": 2.52,
"uvi": 0.52
},
{
"dt": 1608811200,
"sunrise": 1608797112,
"sunset": 1608825307,
"temp": {
"day": 7.3,
"min": 4.66,
"max": 8.32,
"night": 4.66,
"eve": 5.76,
"morn": 5.85
},
"feels_like": {
"day": 0.36,
"night": -1.25,
"eve": -0.31,
"morn": -2.46
},
"pressure": 1020,
"humidity": 60,
"dew_point": 0.15,
"wind_speed": 7.09,
"wind_deg": 5,
"weather": [
{
"id": 500,
"main": "Rain",
"description": "light rain",
"icon": "10d"
}
],
"clouds": 85,
"pop": 0.52,
"rain": 0.6,
"uvi": 1
},
{
"dt": 1608897600,
"sunrise": 1608883530,
"sunset": 1608911747,
"temp": {
"day": 4.12,
"min": 2.2,
"max": 4.63,
"night": 2.97,
"eve": 3.44,
"morn": 2.28
},
"feels_like": {
"day": -0.33,
"night": -0.43,
"eve": -0.1,
"morn": -2.82
},
"pressure": 1033,
"humidity": 70,
"dew_point": -3.09,
"wind_speed": 3.35,
"wind_deg": 334,
"weather": [
{
"id": 800,
"main": "Clear",
"description": "clear sky",
"icon": "01d"
}
],
"clouds": 0,
"pop": 0,
"uvi": 1
},
{
"dt": 1608984000,
"sunrise": 1608969944,
"sunset": 1608998190,
"temp": {
"day": 6.03,
"min": 2.76,
"max": 6.92,
"night": 6.92,
"eve": 6.45,
"morn": 3.59
},
"feels_like": {
"day": 0.49,
"night": -0.96,
"eve": -0.28,
"morn": -0.44
},
"pressure": 1024,
"humidity": 69,
"dew_point": 0.84,
"wind_speed": 5.25,
"wind_deg": 251,
"weather": [
{
"id": 804,
"main": "Clouds",
"description": "overcast clouds",
"icon": "04d"
}
],
"clouds": 100,
"pop": 0,
"uvi": 1
}
]
}