forked from genewildish/Mainline
feat: Add fast startup fetch and background caching
- Add for quick startup using first N feeds - Add background thread for full fetch and caching - Update to use fast fetch - Update docs and skills
This commit is contained in:
@@ -31,12 +31,12 @@ class TestFetchFeed:
|
||||
|
||||
@patch("engine.fetch.urllib.request.urlopen")
|
||||
def test_fetch_network_error(self, mock_urlopen):
|
||||
"""Network error returns None."""
|
||||
"""Network error returns tuple with None feed."""
|
||||
mock_urlopen.side_effect = Exception("Network error")
|
||||
|
||||
result = fetch_feed("http://example.com/feed")
|
||||
url, feed = fetch_feed("http://example.com/feed")
|
||||
|
||||
assert result is None
|
||||
assert feed is None
|
||||
|
||||
|
||||
class TestFetchAll:
|
||||
@@ -54,7 +54,7 @@ class TestFetchAll:
|
||||
{"title": "Headline 1", "published_parsed": (2024, 1, 1, 12, 0, 0)},
|
||||
{"title": "Headline 2", "updated_parsed": (2024, 1, 2, 12, 0, 0)},
|
||||
]
|
||||
mock_fetch_feed.return_value = mock_feed
|
||||
mock_fetch_feed.return_value = ("http://example.com", mock_feed)
|
||||
mock_skip.return_value = False
|
||||
mock_strip.side_effect = lambda x: x
|
||||
|
||||
@@ -67,7 +67,7 @@ class TestFetchAll:
|
||||
@patch("engine.fetch.boot_ln")
|
||||
def test_fetch_all_feed_error(self, mock_boot, mock_fetch_feed):
|
||||
"""Feed error increments failed count."""
|
||||
mock_fetch_feed.return_value = None
|
||||
mock_fetch_feed.return_value = ("http://example.com", None)
|
||||
|
||||
items, linked, failed = fetch_all()
|
||||
|
||||
@@ -87,7 +87,7 @@ class TestFetchAll:
|
||||
{"title": "Sports scores"},
|
||||
{"title": "Valid headline"},
|
||||
]
|
||||
mock_fetch_feed.return_value = mock_feed
|
||||
mock_fetch_feed.return_value = ("http://example.com", mock_feed)
|
||||
mock_skip.side_effect = lambda x: x == "Sports scores"
|
||||
mock_strip.side_effect = lambda x: x
|
||||
|
||||
|
||||
@@ -218,9 +218,10 @@ class TestPipelineE2EHappyPath:
|
||||
|
||||
assert result.success
|
||||
frame = display.frames.get(timeout=1)
|
||||
assert "Line A" in frame
|
||||
assert "Line B" in frame
|
||||
assert "Line C" in frame
|
||||
# Camera stage pads lines to viewport width, so check for substring match
|
||||
assert any("Line A" in line for line in frame)
|
||||
assert any("Line B" in line for line in frame)
|
||||
assert any("Line C" in line for line in frame)
|
||||
|
||||
def test_empty_source_produces_empty_buffer(self):
|
||||
"""An empty source should produce an empty (or blank) frame."""
|
||||
@@ -263,7 +264,10 @@ class TestPipelineE2EEffects:
|
||||
|
||||
assert result.success
|
||||
frame = display.frames.get(timeout=1)
|
||||
assert "[FX1]" in frame, f"Marker not found in frame: {frame}"
|
||||
# Camera stage pads lines to viewport width, so check for substring match
|
||||
assert any("[FX1]" in line for line in frame), (
|
||||
f"Marker not found in frame: {frame}"
|
||||
)
|
||||
assert "Original" in "\n".join(frame)
|
||||
|
||||
def test_effect_chain_ordering(self):
|
||||
@@ -387,7 +391,7 @@ class TestPipelineE2EStageOrder:
|
||||
# All regular (non-overlay) stages should have metrics
|
||||
assert "source" in stage_names
|
||||
assert "render" in stage_names
|
||||
assert "display" in stage_names
|
||||
assert "queue" in stage_names # Display stage is named "queue" in the test
|
||||
assert "effect_m" in stage_names
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user