mirror of
https://github.com/Sea-Haven-Industries/meal-order-manager.git
synced 2026-09-30 14:43:12 +00:00
* feat(menu): publish the weekly menu from the job worker Monday publish parses the catalog embedded in the Redefine menu page and runs on the Fargate worker, so the GitHub Actions scrape cron can go away. * fix(menu): address review feedback Use the form deadline in the Monday Slack post, and compare that message exactly so CodeQL does not treat the test as URL sanitization.
60 lines
2 KiB
Python
60 lines
2 KiB
Python
"""Parser for the catalog embedded on the Redefine menu page."""
|
|
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from scraper.parse_menu import MenuParseError, parse_menu_html
|
|
|
|
FIXTURE = Path(__file__).resolve().parent / "fixtures" / "menu_page.html"
|
|
|
|
|
|
def test_parse_menu_html_maps_catalog_fields():
|
|
page = FIXTURE.read_text()
|
|
menu = parse_menu_html(
|
|
page,
|
|
menu_url="https://www.redefinemeals.com/menu",
|
|
scraped_at="2026-09-21T07:30:00-04:00",
|
|
)
|
|
|
|
assert menu["meal_count"] == 2
|
|
assert menu["scraped_at"] == "2026-09-21T07:30:00-04:00"
|
|
korean, sale = menu["meals"]
|
|
|
|
assert korean["name"] == "Korean Steak Bowl"
|
|
assert korean["price"] == 12.49
|
|
assert korean["calories"] == 590
|
|
assert korean["protein"] == "50g"
|
|
assert korean["dietary_tags"] == ["Gluten Free", "Dairy Free"]
|
|
assert korean["image_url"] == "https://example.com/korean.png"
|
|
assert korean["is_new"] is True
|
|
assert korean["description"] == "Shaved ribeye & rice."
|
|
|
|
assert sale["name"] == "Sale Bowl"
|
|
assert sale["price"] == 9.50
|
|
assert sale["calories"] == 400
|
|
assert sale["protein"] == "30g"
|
|
assert sale["is_new"] is False
|
|
assert sale["description"] == "On sale."
|
|
|
|
|
|
def test_parse_menu_html_rejects_a_missing_catalog():
|
|
with pytest.raises(MenuParseError, match="missing :products"):
|
|
parse_menu_html("<html></html>", menu_url="https://example.com/menu")
|
|
|
|
|
|
def test_parse_menu_html_rejects_an_empty_catalog():
|
|
page = "<orders-page :products='[]' :newest-ids='[]'></orders-page>"
|
|
with pytest.raises(MenuParseError, match="empty"):
|
|
parse_menu_html(page, menu_url="https://example.com/menu")
|
|
|
|
|
|
def test_parse_menu_html_rejects_a_meal_without_a_price():
|
|
page = """
|
|
<orders-page
|
|
:products='[{"id":1,"name":"Broken","price":null,"on_sale":false,"available":true}]'
|
|
:newest-ids='[]'
|
|
></orders-page>
|
|
"""
|
|
with pytest.raises(MenuParseError, match="missing a price"):
|
|
parse_menu_html(page, menu_url="https://example.com/menu")
|