diff --git a/homeassistant/components/feedreader/coordinator.py b/homeassistant/components/feedreader/coordinator.py index e429979b1da..6608c4312fe 100644 --- a/homeassistant/components/feedreader/coordinator.py +++ b/homeassistant/components/feedreader/coordinator.py @@ -6,6 +6,7 @@ from calendar import timegm from datetime import datetime from logging import getLogger from time import gmtime, struct_time +from typing import TYPE_CHECKING from urllib.error import URLError import feedparser @@ -120,10 +121,13 @@ class FeedReaderCoordinator( len(self._feed.entries), self.url, ) - if not isinstance(self._feed.entries, list): + if not self._feed.entries: self._log_no_entries() return None + if TYPE_CHECKING: + assert isinstance(self._feed.entries, list) + self._filter_entries() self._publish_new_entries() diff --git a/homeassistant/components/feedreader/event.py b/homeassistant/components/feedreader/event.py index c9bf39e83ca..48c18c4e70d 100644 --- a/homeassistant/components/feedreader/event.py +++ b/homeassistant/components/feedreader/event.py @@ -29,7 +29,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up event entities for feedreader.""" - coordinator: FeedReaderCoordinator = entry.runtime_data + coordinator = entry.runtime_data async_add_entities([FeedReaderEvent(coordinator)]) @@ -76,8 +76,6 @@ class FeedReaderEvent(CoordinatorEntity[FeedReaderCoordinator], EventEntity): if content := feed_data.get("content"): if isinstance(content, list) and isinstance(content[0], dict): content = content[0].get("value") - else: - content = feed_data.get("summary") self._trigger_event( EVENT_FEEDREADER, diff --git a/tests/components/feedreader/conftest.py b/tests/components/feedreader/conftest.py index 0a5342615a9..8eeb89e00cd 100644 --- a/tests/components/feedreader/conftest.py +++ b/tests/components/feedreader/conftest.py @@ -52,6 +52,18 @@ def fixture_feed_identically_timed_events(hass: HomeAssistant) -> bytes: return load_fixture_bytes("feedreader6.xml") +@pytest.fixture(name="feed_without_items") +def fixture_feed_without_items(hass: HomeAssistant) -> bytes: + """Load test feed without any items.""" + return load_fixture_bytes("feedreader7.xml") + + +@pytest.fixture(name="feed_only_summary") +def fixture_feed_only_summary(hass: HomeAssistant) -> bytes: + """Load test feed data with one event containing only a summary, no content.""" + return load_fixture_bytes("feedreader8.xml") + + @pytest.fixture(name="events") async def fixture_events(hass: HomeAssistant) -> list[Event]: """Fixture that catches alexa events.""" diff --git a/tests/components/feedreader/fixtures/feedreader7.xml b/tests/components/feedreader/fixtures/feedreader7.xml new file mode 100644 index 00000000000..0ffac8dd2ee --- /dev/null +++ b/tests/components/feedreader/fixtures/feedreader7.xml @@ -0,0 +1,11 @@ + + + + RSS Sample + This is an example of an RSS feed + http://www.example.com/main.html + Mon, 30 Apr 2018 12:00:00 +1000 + Mon, 30 Apr 2018 15:00:00 +1000 + 1800 + + diff --git a/tests/components/feedreader/fixtures/feedreader8.xml b/tests/components/feedreader/fixtures/feedreader8.xml new file mode 100644 index 00000000000..d1c167352f8 --- /dev/null +++ b/tests/components/feedreader/fixtures/feedreader8.xml @@ -0,0 +1,21 @@ + + + + RSS Sample + This is an example of an RSS feed + http://www.example.com/main.html + Mon, 30 Apr 2018 12:00:00 +1000 + Mon, 30 Apr 2018 15:00:00 +1000 + 1800 + + + Title 1 + Description 1 + http://www.example.com/link/1 + GUID 1 + Mon, 30 Apr 2018 15:10:00 +1000 + This is a summary + + + + diff --git a/tests/components/feedreader/test_event.py b/tests/components/feedreader/test_event.py index 23fec371860..5d903383c05 100644 --- a/tests/components/feedreader/test_event.py +++ b/tests/components/feedreader/test_event.py @@ -18,14 +18,14 @@ from tests.common import async_fire_time_changed async def test_event_entity( - hass: HomeAssistant, feed_one_event, feed_two_event + hass: HomeAssistant, feed_one_event, feed_two_event, feed_only_summary ) -> None: """Test feed event entity.""" entry = create_mock_entry(VALID_CONFIG_DEFAULT) entry.add_to_hass(hass) with patch( "homeassistant.components.feedreader.coordinator.feedparser.http.get", - side_effect=[feed_one_event, feed_two_event], + side_effect=[feed_one_event, feed_two_event, feed_only_summary], ): assert await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() @@ -45,3 +45,13 @@ async def test_event_entity( assert state.attributes[ATTR_TITLE] == "Title 2" assert state.attributes[ATTR_LINK] == "http://www.example.com/link/2" assert state.attributes[ATTR_CONTENT] == "Content 2" + + future = dt_util.utcnow() + timedelta(hours=2, seconds=2) + async_fire_time_changed(hass, future) + await hass.async_block_till_done(wait_background_tasks=True) + + state = hass.states.get("event.mock_title") + assert state + assert state.attributes[ATTR_TITLE] == "Title 1" + assert state.attributes[ATTR_LINK] == "http://www.example.com/link/1" + assert state.attributes[ATTR_CONTENT] == "This is a summary" diff --git a/tests/components/feedreader/test_init.py b/tests/components/feedreader/test_init.py index 61e3f13ced7..d7700d79e3b 100644 --- a/tests/components/feedreader/test_init.py +++ b/tests/components/feedreader/test_init.py @@ -165,6 +165,21 @@ async def test_feed_identical_timestamps( ) +async def test_feed_with_only_summary( + hass: HomeAssistant, events, feed_only_summary +) -> None: + """Test simple feed with only summary, no content.""" + assert await async_setup_config_entry( + hass, VALID_CONFIG_DEFAULT, return_value=feed_only_summary + ) + await hass.async_block_till_done() + + assert len(events) == 1 + assert events[0].data.title == "Title 1" + assert events[0].data.description == "Description 1" + assert events[0].data.content[0].value == "This is a summary" + + async def test_feed_updates( hass: HomeAssistant, events, feed_one_event, feed_two_event ) -> None: @@ -247,6 +262,20 @@ async def test_feed_with_unrecognized_publication_date( assert len(events) == 1 +async def test_feed_without_items( + hass: HomeAssistant, events, feed_without_items, caplog: pytest.LogCaptureFixture +) -> None: + """Test simple feed without any items.""" + assert "No new entries to be published in feed" not in caplog.text + assert await async_setup_config_entry( + hass, VALID_CONFIG_DEFAULT, return_value=feed_without_items + ) + await hass.async_block_till_done() + + assert "No new entries to be published in feed" in caplog.text + assert len(events) == 0 + + async def test_feed_invalid_data(hass: HomeAssistant, events) -> None: """Test feed with invalid data.""" assert await async_setup_config_entry(