mirror of
https://github.com/hmalik144/Weather-apps.git
synced 2025-12-10 02:05:20 +00:00
- Remove old api and response
This commit is contained in:
@@ -67,7 +67,7 @@ open class BaseTest<A : Activity>(
|
||||
}
|
||||
|
||||
testApp =
|
||||
InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as TestAppClass
|
||||
InstrumentationRegistry.getInstrumentation().targetContext.applicationContext
|
||||
runBlocking {
|
||||
beforeLaunch()
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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>
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
)
|
||||
@@ -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
|
||||
)
|
||||
@@ -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
|
||||
)
|
||||
@@ -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
|
||||
)
|
||||
@@ -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
|
||||
)
|
||||
@@ -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
|
||||
)
|
||||
@@ -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
|
||||
)
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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
|
||||
)
|
||||
@@ -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()
|
||||
|
||||
)
|
||||
@@ -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
|
||||
)
|
||||
@@ -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()
|
||||
)
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -40,8 +40,7 @@ data class Forecast(
|
||||
parcel.readString(),
|
||||
parcel.readString(),
|
||||
parcel.readString()
|
||||
) {
|
||||
}
|
||||
)
|
||||
|
||||
constructor(dailyWeather: DailyWeather) : this(
|
||||
dailyWeather.dt?.toDayString(),
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
|
||||
|
||||
}
|
||||
@@ -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
|
||||
)
|
||||
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user