Post merge review for Feedreader (#122327)
* remove unneccessary typing * assert type list while type checking * remove summary, since feedparser parse it already into content * add further tests
This commit is contained in:
parent
94ce02f406
commit
7e1fb88e4e
7 changed files with 91 additions and 6 deletions
|
@ -6,6 +6,7 @@ from calendar import timegm
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from time import gmtime, struct_time
|
from time import gmtime, struct_time
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
from urllib.error import URLError
|
from urllib.error import URLError
|
||||||
|
|
||||||
import feedparser
|
import feedparser
|
||||||
|
@ -120,10 +121,13 @@ class FeedReaderCoordinator(
|
||||||
len(self._feed.entries),
|
len(self._feed.entries),
|
||||||
self.url,
|
self.url,
|
||||||
)
|
)
|
||||||
if not isinstance(self._feed.entries, list):
|
if not self._feed.entries:
|
||||||
self._log_no_entries()
|
self._log_no_entries()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
assert isinstance(self._feed.entries, list)
|
||||||
|
|
||||||
self._filter_entries()
|
self._filter_entries()
|
||||||
self._publish_new_entries()
|
self._publish_new_entries()
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ async def async_setup_entry(
|
||||||
async_add_entities: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up event entities for feedreader."""
|
"""Set up event entities for feedreader."""
|
||||||
coordinator: FeedReaderCoordinator = entry.runtime_data
|
coordinator = entry.runtime_data
|
||||||
|
|
||||||
async_add_entities([FeedReaderEvent(coordinator)])
|
async_add_entities([FeedReaderEvent(coordinator)])
|
||||||
|
|
||||||
|
@ -76,8 +76,6 @@ class FeedReaderEvent(CoordinatorEntity[FeedReaderCoordinator], EventEntity):
|
||||||
if content := feed_data.get("content"):
|
if content := feed_data.get("content"):
|
||||||
if isinstance(content, list) and isinstance(content[0], dict):
|
if isinstance(content, list) and isinstance(content[0], dict):
|
||||||
content = content[0].get("value")
|
content = content[0].get("value")
|
||||||
else:
|
|
||||||
content = feed_data.get("summary")
|
|
||||||
|
|
||||||
self._trigger_event(
|
self._trigger_event(
|
||||||
EVENT_FEEDREADER,
|
EVENT_FEEDREADER,
|
||||||
|
|
|
@ -52,6 +52,18 @@ def fixture_feed_identically_timed_events(hass: HomeAssistant) -> bytes:
|
||||||
return load_fixture_bytes("feedreader6.xml")
|
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")
|
@pytest.fixture(name="events")
|
||||||
async def fixture_events(hass: HomeAssistant) -> list[Event]:
|
async def fixture_events(hass: HomeAssistant) -> list[Event]:
|
||||||
"""Fixture that catches alexa events."""
|
"""Fixture that catches alexa events."""
|
||||||
|
|
11
tests/components/feedreader/fixtures/feedreader7.xml
Normal file
11
tests/components/feedreader/fixtures/feedreader7.xml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<rss version="2.0">
|
||||||
|
<channel>
|
||||||
|
<title>RSS Sample</title>
|
||||||
|
<description>This is an example of an RSS feed</description>
|
||||||
|
<link>http://www.example.com/main.html</link>
|
||||||
|
<lastBuildDate>Mon, 30 Apr 2018 12:00:00 +1000 </lastBuildDate>
|
||||||
|
<pubDate>Mon, 30 Apr 2018 15:00:00 +1000</pubDate>
|
||||||
|
<ttl>1800</ttl>
|
||||||
|
</channel>
|
||||||
|
</rss>
|
21
tests/components/feedreader/fixtures/feedreader8.xml
Normal file
21
tests/components/feedreader/fixtures/feedreader8.xml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<rss version="2.0">
|
||||||
|
<channel>
|
||||||
|
<title>RSS Sample</title>
|
||||||
|
<description>This is an example of an RSS feed</description>
|
||||||
|
<link>http://www.example.com/main.html</link>
|
||||||
|
<lastBuildDate>Mon, 30 Apr 2018 12:00:00 +1000 </lastBuildDate>
|
||||||
|
<pubDate>Mon, 30 Apr 2018 15:00:00 +1000</pubDate>
|
||||||
|
<ttl>1800</ttl>
|
||||||
|
|
||||||
|
<item>
|
||||||
|
<title>Title 1</title>
|
||||||
|
<description>Description 1</description>
|
||||||
|
<link>http://www.example.com/link/1</link>
|
||||||
|
<guid isPermaLink="false">GUID 1</guid>
|
||||||
|
<pubDate>Mon, 30 Apr 2018 15:10:00 +1000</pubDate>
|
||||||
|
<summary>This is a summary</summary>
|
||||||
|
</item>
|
||||||
|
|
||||||
|
</channel>
|
||||||
|
</rss>
|
|
@ -18,14 +18,14 @@ from tests.common import async_fire_time_changed
|
||||||
|
|
||||||
|
|
||||||
async def test_event_entity(
|
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:
|
) -> None:
|
||||||
"""Test feed event entity."""
|
"""Test feed event entity."""
|
||||||
entry = create_mock_entry(VALID_CONFIG_DEFAULT)
|
entry = create_mock_entry(VALID_CONFIG_DEFAULT)
|
||||||
entry.add_to_hass(hass)
|
entry.add_to_hass(hass)
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.feedreader.coordinator.feedparser.http.get",
|
"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)
|
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||||
await hass.async_block_till_done()
|
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_TITLE] == "Title 2"
|
||||||
assert state.attributes[ATTR_LINK] == "http://www.example.com/link/2"
|
assert state.attributes[ATTR_LINK] == "http://www.example.com/link/2"
|
||||||
assert state.attributes[ATTR_CONTENT] == "Content 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"
|
||||||
|
|
|
@ -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(
|
async def test_feed_updates(
|
||||||
hass: HomeAssistant, events, feed_one_event, feed_two_event
|
hass: HomeAssistant, events, feed_one_event, feed_two_event
|
||||||
) -> None:
|
) -> None:
|
||||||
|
@ -247,6 +262,20 @@ async def test_feed_with_unrecognized_publication_date(
|
||||||
assert len(events) == 1
|
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:
|
async def test_feed_invalid_data(hass: HomeAssistant, events) -> None:
|
||||||
"""Test feed with invalid data."""
|
"""Test feed with invalid data."""
|
||||||
assert await async_setup_config_entry(
|
assert await async_setup_config_entry(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue