diff --git a/uk_bin_collection/tests/test_lancaster_city_council.py b/uk_bin_collection/tests/test_lancaster_city_council.py
new file mode 100644
index 0000000000..b14ab93fcd
--- /dev/null
+++ b/uk_bin_collection/tests/test_lancaster_city_council.py
@@ -0,0 +1,81 @@
+"""Unit tests for the Lancaster City Council scheduled-collections parser."""
+
+from types import SimpleNamespace
+from unittest.mock import MagicMock, patch
+
+from uk_bin_collection.uk_bin_collection.councils.LancasterCityCouncil import (
+ CouncilClass,
+)
+
+MODULE_PATH = "uk_bin_collection.uk_bin_collection.councils.LancasterCityCouncil"
+
+HOME_HTML = 'Go'
+FORM_HTML = '
'
+ADDRESS_HTML = '1 Test Street'
+
+
+def collection(date: str, service: str) -> str:
+ """Return the portal markup for a single scheduled collection."""
+ return f"""
+
+ 
+ {date}
+ {service}
+
+ """
+
+
+def schedule_html(*items: tuple[str, str]) -> str:
+ """Return a scheduled-collections section containing the given collections."""
+ body = "".join(collection(date, service) for date, service in items)
+ return f''
+
+
+def parse_fixture(html: str):
+ """Run the parser with the portal requests mocked to return the given schedule."""
+ session = MagicMock()
+ session.get.side_effect = [
+ SimpleNamespace(text=HOME_HTML),
+ SimpleNamespace(text=FORM_HTML),
+ SimpleNamespace(text=html),
+ ]
+ session.post.return_value = SimpleNamespace(text=ADDRESS_HTML)
+ with patch(f"{MODULE_PATH}.requests.Session", return_value=session):
+ return CouncilClass().parse_data("", number="1", postcode="LA1 1RS")
+
+
+def test_parse_data_keeps_recycling_streams_separate():
+ """Red and Yellow recycling streams are reported as distinct bin types."""
+ result = parse_fixture(
+ schedule_html(
+ ("29/10/2026", "Domestic Waste Collection Service"),
+ ("29/10/2026", "Food Waste Collection Service"),
+ ("05/11/2026", "Recycling Red Collection Service"),
+ ("12/11/2026", "Recycling Yellow Collection Service"),
+ )
+ )
+
+ assert result == {
+ "bins": [
+ {"type": "Domestic Waste", "collectionDate": "29/10/2026"},
+ {"type": "Food Waste", "collectionDate": "29/10/2026"},
+ {"type": "Recycling Red", "collectionDate": "05/11/2026"},
+ {"type": "Recycling Yellow", "collectionDate": "12/11/2026"},
+ ]
+ }
+
+
+def test_parse_data_maps_unspecified_recycling_stream_to_recycling():
+ """The "refer to calendar for stream" wording still maps to Recycling."""
+ result = parse_fixture(
+ schedule_html(
+ (
+ "05/11/2026",
+ "Recycling Collection - refer to calendar for stream",
+ ),
+ )
+ )
+
+ assert result == {
+ "bins": [{"type": "Recycling", "collectionDate": "05/11/2026"}]
+ }
diff --git a/uk_bin_collection/uk_bin_collection/councils/LancasterCityCouncil.py b/uk_bin_collection/uk_bin_collection/councils/LancasterCityCouncil.py
index 4d18915d3a..f56961a339 100644
--- a/uk_bin_collection/uk_bin_collection/councils/LancasterCityCouncil.py
+++ b/uk_bin_collection/uk_bin_collection/councils/LancasterCityCouncil.py
@@ -7,9 +7,12 @@
from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
+# Specific recycling streams must precede the generic "Recycling" prefix.
BIN_TYPES = (
"Domestic Waste",
"Garden Waste",
+ "Recycling Red",
+ "Recycling Yellow",
"Recycling",
"Food Waste",
)
@@ -28,6 +31,7 @@ class CouncilClass(AbstractGetBinDataClass):
"""
def parse_data(self, page: str, **kwargs) -> dict:
+ """Scrape the Lancaster waste portal and return scheduled collections by bin type."""
# data to return
data = {"bins": []}