mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Temporarily fix yahoo weather API issue and add unit test. (#10737)
* Temporarily fix yahoo weather API issue and add unit test. * Add test data.
This commit is contained in:
parent
f2dea4615f
commit
47183ce02e
@ -594,7 +594,6 @@ omit =
|
||||
homeassistant/components/sensor/worldtidesinfo.py
|
||||
homeassistant/components/sensor/worxlandroid.py
|
||||
homeassistant/components/sensor/xbox_live.py
|
||||
homeassistant/components/sensor/yweather.py
|
||||
homeassistant/components/sensor/zamg.py
|
||||
homeassistant/components/shiftr.py
|
||||
homeassistant/components/spc.py
|
||||
|
@ -160,13 +160,15 @@ class YahooWeatherSensor(Entity):
|
||||
self._code = self._data.yahoo.Forecast[self._forecast]['code']
|
||||
self._state = self._data.yahoo.Forecast[self._forecast]['high']
|
||||
elif self._type == 'wind_speed':
|
||||
self._state = self._data.yahoo.Wind['speed']
|
||||
self._state = round(float(self._data.yahoo.Wind['speed'])/1.61, 2)
|
||||
elif self._type == 'humidity':
|
||||
self._state = self._data.yahoo.Atmosphere['humidity']
|
||||
elif self._type == 'pressure':
|
||||
self._state = self._data.yahoo.Atmosphere['pressure']
|
||||
self._state = round(
|
||||
float(self._data.yahoo.Atmosphere['pressure'])/33.8637526, 2)
|
||||
elif self._type == 'visibility':
|
||||
self._state = self._data.yahoo.Atmosphere['visibility']
|
||||
self._state = round(
|
||||
float(self._data.yahoo.Atmosphere['visibility'])/1.61, 2)
|
||||
|
||||
|
||||
class YahooWeatherData(object):
|
||||
|
247
tests/components/sensor/test_yweather.py
Normal file
247
tests/components/sensor/test_yweather.py
Normal file
@ -0,0 +1,247 @@
|
||||
"""The tests for the Yahoo weather sensor component."""
|
||||
import json
|
||||
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
from homeassistant.setup import setup_component
|
||||
|
||||
from tests.common import (get_test_home_assistant, load_fixture,
|
||||
MockDependency)
|
||||
|
||||
VALID_CONFIG_MINIMAL = {
|
||||
'sensor': {
|
||||
'platform': 'yweather',
|
||||
'monitored_conditions': [
|
||||
'weather',
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
VALID_CONFIG_ALL = {
|
||||
'sensor': {
|
||||
'platform': 'yweather',
|
||||
'monitored_conditions': [
|
||||
'weather',
|
||||
'weather_current',
|
||||
'temperature',
|
||||
'temp_min',
|
||||
'temp_max',
|
||||
'wind_speed',
|
||||
'pressure',
|
||||
'visibility',
|
||||
'humidity',
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
BAD_CONF_RAW = {
|
||||
'sensor': {
|
||||
'platform': 'yweather',
|
||||
'woeid': '12345',
|
||||
'monitored_conditions': [
|
||||
'weather',
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
BAD_CONF_DATA = {
|
||||
'sensor': {
|
||||
'platform': 'yweather',
|
||||
'woeid': '111',
|
||||
'monitored_conditions': [
|
||||
'weather',
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def _yql_queryMock(yql): # pylint: disable=invalid-name
|
||||
"""Mock yahoo query language query."""
|
||||
return ('{"query": {"count": 1, "created": "2017-11-17T13:40:47Z", '
|
||||
'"lang": "en-US", "results": {"place": {"woeid": "23511632"}}}}')
|
||||
|
||||
|
||||
def get_woeidMock(lat, lon): # pylint: disable=invalid-name
|
||||
"""Mock get woeid Where On Earth Identifiers."""
|
||||
return '23511632'
|
||||
|
||||
|
||||
def get_woeidNoneMock(lat, lon): # pylint: disable=invalid-name
|
||||
"""Mock get woeid Where On Earth Identifiers."""
|
||||
return None
|
||||
|
||||
|
||||
class YahooWeatherMock():
|
||||
"""Mock class for the YahooWeather object."""
|
||||
|
||||
def __init__(self, woeid, temp_unit):
|
||||
"""Initialize Telnet object."""
|
||||
self.woeid = woeid
|
||||
self.temp_unit = temp_unit
|
||||
self._data = json.loads(load_fixture('yahooweather.json'))
|
||||
|
||||
# pylint: disable=no-self-use
|
||||
def updateWeather(self): # pylint: disable=invalid-name
|
||||
"""Return sample values."""
|
||||
return True
|
||||
|
||||
@property
|
||||
def RawData(self): # pylint: disable=invalid-name
|
||||
"""Raw Data."""
|
||||
if self.woeid == '12345':
|
||||
return json.loads('[]')
|
||||
return self._data
|
||||
|
||||
@property
|
||||
def Units(self): # pylint: disable=invalid-name
|
||||
"""Return dict with units."""
|
||||
return self._data['query']['results']['channel']['units']
|
||||
|
||||
@property
|
||||
def Now(self): # pylint: disable=invalid-name
|
||||
"""Current weather data."""
|
||||
if self.woeid == '111':
|
||||
raise ValueError
|
||||
return self._data['query']['results']['channel']['item']['condition']
|
||||
|
||||
@property
|
||||
def Atmosphere(self): # pylint: disable=invalid-name
|
||||
"""Atmosphere weather data."""
|
||||
return self._data['query']['results']['channel']['atmosphere']
|
||||
|
||||
@property
|
||||
def Wind(self): # pylint: disable=invalid-name
|
||||
"""Wind weather data."""
|
||||
return self._data['query']['results']['channel']['wind']
|
||||
|
||||
@property
|
||||
def Forecast(self): # pylint: disable=invalid-name
|
||||
"""Forecast data 0-5 Days."""
|
||||
return self._data['query']['results']['channel']['item']['forecast']
|
||||
|
||||
def getWeatherImage(self, code): # pylint: disable=invalid-name
|
||||
"""Create a link to weather image from yahoo code."""
|
||||
return "https://l.yimg.com/a/i/us/we/52/{}.gif".format(code)
|
||||
|
||||
|
||||
class TestWeather(unittest.TestCase):
|
||||
"""Test the Yahoo weather component."""
|
||||
|
||||
def setUp(self):
|
||||
"""Setup things to be run when tests are started."""
|
||||
self.hass = get_test_home_assistant()
|
||||
|
||||
def tearDown(self):
|
||||
"""Stop down everything that was started."""
|
||||
self.hass.stop()
|
||||
|
||||
@MockDependency('yahooweather')
|
||||
@patch('yahooweather._yql_query', new=_yql_queryMock)
|
||||
@patch('yahooweather.get_woeid', new=get_woeidMock)
|
||||
@patch('yahooweather.YahooWeather', new=YahooWeatherMock)
|
||||
def test_setup_minimal(self, mock_yahooweather):
|
||||
"""Test for minimal weather sensor config."""
|
||||
assert setup_component(self.hass, 'sensor', VALID_CONFIG_MINIMAL)
|
||||
|
||||
state = self.hass.states.get('sensor.yweather_condition')
|
||||
assert state is not None
|
||||
|
||||
assert state.state == 'Mostly Cloudy'
|
||||
self.assertEqual(state.attributes.get('friendly_name'),
|
||||
'Yweather Condition')
|
||||
|
||||
@MockDependency('yahooweather')
|
||||
@patch('yahooweather._yql_query', new=_yql_queryMock)
|
||||
@patch('yahooweather.get_woeid', new=get_woeidMock)
|
||||
@patch('yahooweather.YahooWeather', new=YahooWeatherMock)
|
||||
def test_setup_all(self, mock_yahooweather):
|
||||
"""Test for all weather data attributes."""
|
||||
assert setup_component(self.hass, 'sensor', VALID_CONFIG_ALL)
|
||||
|
||||
state = self.hass.states.get('sensor.yweather_condition')
|
||||
assert state is not None
|
||||
self.assertEqual(state.state, 'Mostly Cloudy')
|
||||
self.assertEqual(state.attributes.get('friendly_name'),
|
||||
'Yweather Condition')
|
||||
|
||||
state = self.hass.states.get('sensor.yweather_current')
|
||||
assert state is not None
|
||||
self.assertEqual(state.state, 'Cloudy')
|
||||
self.assertEqual(state.attributes.get('friendly_name'),
|
||||
'Yweather Current')
|
||||
|
||||
state = self.hass.states.get('sensor.yweather_temperature')
|
||||
assert state is not None
|
||||
self.assertEqual(state.state, '18')
|
||||
self.assertEqual(state.attributes.get('friendly_name'),
|
||||
'Yweather Temperature')
|
||||
|
||||
state = self.hass.states.get('sensor.yweather_temperature_max')
|
||||
assert state is not None
|
||||
self.assertEqual(state.state, '23')
|
||||
self.assertEqual(state.attributes.get('friendly_name'),
|
||||
'Yweather Temperature max')
|
||||
|
||||
state = self.hass.states.get('sensor.yweather_temperature_min')
|
||||
assert state is not None
|
||||
self.assertEqual(state.state, '16')
|
||||
self.assertEqual(state.attributes.get('friendly_name'),
|
||||
'Yweather Temperature min')
|
||||
|
||||
state = self.hass.states.get('sensor.yweather_wind_speed')
|
||||
assert state is not None
|
||||
self.assertEqual(state.state, '3.94')
|
||||
self.assertEqual(state.attributes.get('friendly_name'),
|
||||
'Yweather Wind speed')
|
||||
|
||||
state = self.hass.states.get('sensor.yweather_pressure')
|
||||
assert state is not None
|
||||
self.assertEqual(state.state, '1000.0')
|
||||
self.assertEqual(state.attributes.get('friendly_name'),
|
||||
'Yweather Pressure')
|
||||
|
||||
state = self.hass.states.get('sensor.yweather_visibility')
|
||||
assert state is not None
|
||||
self.assertEqual(state.state, '14.23')
|
||||
self.assertEqual(state.attributes.get('friendly_name'),
|
||||
'Yweather Visibility')
|
||||
|
||||
state = self.hass.states.get('sensor.yweather_humidity')
|
||||
assert state is not None
|
||||
self.assertEqual(state.state, '71')
|
||||
self.assertEqual(state.attributes.get('friendly_name'),
|
||||
'Yweather Humidity')
|
||||
|
||||
@MockDependency('yahooweather')
|
||||
@patch('yahooweather._yql_query', new=_yql_queryMock)
|
||||
@patch('yahooweather.get_woeid', new=get_woeidNoneMock)
|
||||
@patch('yahooweather.YahooWeather', new=YahooWeatherMock)
|
||||
def test_setup_bad_woied(self, mock_yahooweather):
|
||||
"""Test for bad woeid."""
|
||||
assert setup_component(self.hass, 'sensor', VALID_CONFIG_MINIMAL)
|
||||
|
||||
state = self.hass.states.get('sensor.yweather_condition')
|
||||
assert state is None
|
||||
|
||||
@MockDependency('yahooweather')
|
||||
@patch('yahooweather._yql_query', new=_yql_queryMock)
|
||||
@patch('yahooweather.get_woeid', new=get_woeidMock)
|
||||
@patch('yahooweather.YahooWeather', new=YahooWeatherMock)
|
||||
def test_setup_bad_raw(self, mock_yahooweather):
|
||||
"""Test for bad RawData."""
|
||||
assert setup_component(self.hass, 'sensor', BAD_CONF_RAW)
|
||||
|
||||
state = self.hass.states.get('sensor.yweather_condition')
|
||||
assert state is not None
|
||||
|
||||
@MockDependency('yahooweather')
|
||||
@patch('yahooweather._yql_query', new=_yql_queryMock)
|
||||
@patch('yahooweather.get_woeid', new=get_woeidMock)
|
||||
@patch('yahooweather.YahooWeather', new=YahooWeatherMock)
|
||||
def test_setup_bad_data(self, mock_yahooweather):
|
||||
"""Test for bad data."""
|
||||
assert setup_component(self.hass, 'sensor', BAD_CONF_DATA)
|
||||
|
||||
state = self.hass.states.get('sensor.yweather_condition')
|
||||
assert state is None
|
138
tests/fixtures/yahooweather.json
vendored
Normal file
138
tests/fixtures/yahooweather.json
vendored
Normal file
@ -0,0 +1,138 @@
|
||||
{
|
||||
"query": {
|
||||
"count": 1,
|
||||
"created": "2017-11-17T13:40:47Z",
|
||||
"lang": "en-US",
|
||||
"results": {
|
||||
"channel": {
|
||||
"units": {
|
||||
"distance": "km",
|
||||
"pressure": "mb",
|
||||
"speed": "km/h",
|
||||
"temperature": "C"
|
||||
},
|
||||
"title": "Yahoo! Weather - San Diego, CA, US",
|
||||
"link": "http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-23511632/",
|
||||
"description": "Yahoo! Weather for San Diego, CA, US",
|
||||
"language": "en-us",
|
||||
"lastBuildDate": "Fri, 17 Nov 2017 05:40 AM PST",
|
||||
"ttl": "60",
|
||||
"location": {
|
||||
"city": "San Diego",
|
||||
"country": "United States",
|
||||
"region": " CA"
|
||||
},
|
||||
"wind": {
|
||||
"chill": "56",
|
||||
"direction": "0",
|
||||
"speed": "6.34"
|
||||
},
|
||||
"atmosphere": {
|
||||
"humidity": "71",
|
||||
"pressure": "33863.75",
|
||||
"rising": "0",
|
||||
"visibility": "22.91"
|
||||
},
|
||||
"astronomy": {
|
||||
"sunrise": "6:21 am",
|
||||
"sunset": "4:47 pm"
|
||||
},
|
||||
"image": {
|
||||
"title": "Yahoo! Weather",
|
||||
"width": "142",
|
||||
"height": "18",
|
||||
"link": "http://weather.yahoo.com",
|
||||
"url": "http://l.yimg.com/a/i/brand/purplelogo//uh/us/news-wea.gif"
|
||||
},
|
||||
"item": {
|
||||
"title": "Conditions for San Diego, CA, US at 05:00 AM PST",
|
||||
"lat": "32.878101",
|
||||
"long": "-117.23497",
|
||||
"link": "http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-23511632/",
|
||||
"pubDate": "Fri, 17 Nov 2017 05:00 AM PST",
|
||||
"condition": {
|
||||
"code": "26",
|
||||
"date": "Fri, 17 Nov 2017 05:00 AM PST",
|
||||
"temp": "18",
|
||||
"text": "Cloudy"
|
||||
},
|
||||
"forecast": [{
|
||||
"code": "28",
|
||||
"date": "17 Nov 2017",
|
||||
"day": "Fri",
|
||||
"high": "23",
|
||||
"low": "16",
|
||||
"text": "Mostly Cloudy"
|
||||
}, {
|
||||
"code": "30",
|
||||
"date": "18 Nov 2017",
|
||||
"day": "Sat",
|
||||
"high": "22",
|
||||
"low": "13",
|
||||
"text": "Partly Cloudy"
|
||||
}, {
|
||||
"code": "30",
|
||||
"date": "19 Nov 2017",
|
||||
"day": "Sun",
|
||||
"high": "22",
|
||||
"low": "12",
|
||||
"text": "Partly Cloudy"
|
||||
}, {
|
||||
"code": "28",
|
||||
"date": "20 Nov 2017",
|
||||
"day": "Mon",
|
||||
"high": "21",
|
||||
"low": "11",
|
||||
"text": "Mostly Cloudy"
|
||||
}, {
|
||||
"code": "28",
|
||||
"date": "21 Nov 2017",
|
||||
"day": "Tue",
|
||||
"high": "24",
|
||||
"low": "14",
|
||||
"text": "Mostly Cloudy"
|
||||
}, {
|
||||
"code": "30",
|
||||
"date": "22 Nov 2017",
|
||||
"day": "Wed",
|
||||
"high": "27",
|
||||
"low": "15",
|
||||
"text": "Partly Cloudy"
|
||||
}, {
|
||||
"code": "34",
|
||||
"date": "23 Nov 2017",
|
||||
"day": "Thu",
|
||||
"high": "27",
|
||||
"low": "15",
|
||||
"text": "Mostly Sunny"
|
||||
}, {
|
||||
"code": "30",
|
||||
"date": "24 Nov 2017",
|
||||
"day": "Fri",
|
||||
"high": "23",
|
||||
"low": "16",
|
||||
"text": "Partly Cloudy"
|
||||
}, {
|
||||
"code": "30",
|
||||
"date": "25 Nov 2017",
|
||||
"day": "Sat",
|
||||
"high": "22",
|
||||
"low": "15",
|
||||
"text": "Partly Cloudy"
|
||||
}, {
|
||||
"code": "28",
|
||||
"date": "26 Nov 2017",
|
||||
"day": "Sun",
|
||||
"high": "24",
|
||||
"low": "13",
|
||||
"text": "Mostly Cloudy"
|
||||
}],
|
||||
"description": "<![CDATA[<img src=\"http://l.yimg.com/a/i/us/we/52/26.gif\"/>\n<BR />\n<b>Current Conditions:</b>\n<BR />Cloudy\n<BR />\n<BR />\n<b>Forecast:</b>\n<BR /> Fri - Mostly Cloudy. High: 23Low: 16\n<BR /> Sat - Partly Cloudy. High: 22Low: 13\n<BR /> Sun - Partly Cloudy. High: 22Low: 12\n<BR /> Mon - Mostly Cloudy. High: 21Low: 11\n<BR /> Tue - Mostly Cloudy. High: 24Low: 14\n<BR />\n<BR />\n<a href=\"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-23511632/\">Full Forecast at Yahoo! Weather</a>\n<BR />\n<BR />\n<BR />\n]]>",
|
||||
"guid": {
|
||||
"isPermaLink": "false"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user