mirror of
https://github.com/Sea-Haven-Industries/meal-order-manager.git
synced 2026-09-30 10:03:13 +00:00
fix(cart): account for a closed window and an empty menu
A closed page during add marks the remaining meals as not attempted, and an empty menu catalog raises the same error as the menu parser.
This commit is contained in:
parent
9462ce0966
commit
ddf150f428
4 changed files with 63 additions and 21 deletions
|
|
@ -145,7 +145,8 @@ def _fill_page(page, plan: FillPlan, menu_url: str) -> int:
|
|||
return 1
|
||||
|
||||
posted = []
|
||||
for item in plan.adds:
|
||||
page_closed = False
|
||||
for index, item in enumerate(plan.adds):
|
||||
try:
|
||||
_cart_request(
|
||||
page,
|
||||
|
|
@ -161,27 +162,37 @@ def _fill_page(page, plan: FillPlan, menu_url: str) -> int:
|
|||
failed.append(f"{item.name}: {exc}")
|
||||
print(f"Failed: {item.name}: {exc}")
|
||||
continue
|
||||
posted.append(item)
|
||||
|
||||
try:
|
||||
current = cart_lines(_cart_request(page, "GET", "/api/cart"))
|
||||
except RuntimeError as exc:
|
||||
failed.append(f"Could not read the cart: {exc}")
|
||||
print(f"Failed: Could not read the cart: {exc}")
|
||||
else:
|
||||
for item in posted:
|
||||
found = quantity_for(current, item.uuid)
|
||||
if found != item.quantity:
|
||||
message = (
|
||||
f"{item.name}: requested {item.quantity}, cart has {found}"
|
||||
)
|
||||
except PlaywrightError as exc:
|
||||
failed.append(f"{item.name}: {exc}")
|
||||
print(f"Failed: {item.name}: {exc}")
|
||||
for rest in plan.adds[index + 1 :]:
|
||||
message = f"{rest.name}: not attempted"
|
||||
failed.append(message)
|
||||
print(f"Failed: {message}")
|
||||
else:
|
||||
added += 1
|
||||
origin = _origin(page.url or menu_url)
|
||||
page.goto(f"{origin}/cart", wait_until="domcontentloaded", timeout=60000)
|
||||
ready = True
|
||||
page_closed = True
|
||||
break
|
||||
posted.append(item)
|
||||
|
||||
if not page_closed:
|
||||
try:
|
||||
current = cart_lines(_cart_request(page, "GET", "/api/cart"))
|
||||
except RuntimeError as exc:
|
||||
failed.append(f"Could not read the cart: {exc}")
|
||||
print(f"Failed: Could not read the cart: {exc}")
|
||||
else:
|
||||
for item in posted:
|
||||
found = quantity_for(current, item.uuid)
|
||||
if found != item.quantity:
|
||||
message = (
|
||||
f"{item.name}: requested {item.quantity}, cart has {found}"
|
||||
)
|
||||
failed.append(message)
|
||||
print(f"Failed: {message}")
|
||||
else:
|
||||
added += 1
|
||||
origin = _origin(page.url or menu_url)
|
||||
page.goto(f"{origin}/cart", wait_until="domcontentloaded", timeout=60000)
|
||||
ready = True
|
||||
except (RuntimeError, PlaywrightError) as exc:
|
||||
failed.append(str(exc))
|
||||
print(f"Failed: {exc}")
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ def extract_catalog_products(page: str) -> list:
|
|||
products = _extract_json_attr(page, PRODUCTS_MARKER)
|
||||
if not isinstance(products, list):
|
||||
raise MenuParseError(":products must be a JSON array")
|
||||
if not products:
|
||||
raise MenuParseError("Menu catalog is empty")
|
||||
return products
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -205,6 +205,29 @@ def test_fill_page_prints_a_summary_when_the_window_closes_mid_add(capsys):
|
|||
assert "Cart is ready" not in output
|
||||
|
||||
|
||||
def test_fill_page_counts_items_left_when_the_window_closes(capsys):
|
||||
plan = build_plan(
|
||||
"Item,Quantity\nKorean Steak Bowl,1\nSale Bowl,2\n",
|
||||
PRODUCTS,
|
||||
)
|
||||
page = _CartPage(
|
||||
[
|
||||
{"ok": True, "status": 200, "data": {"items": []}},
|
||||
PlaywrightError("Target page, context or browser has been closed"),
|
||||
]
|
||||
)
|
||||
|
||||
code = fill_redefine_cart._fill_page(
|
||||
page, plan, "https://www.redefinemeals.com/menu"
|
||||
)
|
||||
output = capsys.readouterr().out
|
||||
|
||||
assert code == 1
|
||||
assert "Korean Steak Bowl:" in output
|
||||
assert "Sale Bowl: not attempted" in output
|
||||
assert "Added 0. Failed 2. Skipped 0." in output
|
||||
|
||||
|
||||
def test_fill_page_prints_a_summary_when_the_first_cart_read_fails(capsys):
|
||||
plan = build_plan("Item,Quantity\nKorean Steak Bowl,1\n", PRODUCTS)
|
||||
page = _CartPage(
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from pathlib import Path
|
|||
|
||||
import pytest
|
||||
|
||||
from scraper.parse_menu import MenuParseError, parse_menu_html
|
||||
from scraper.parse_menu import MenuParseError, extract_catalog_products, parse_menu_html
|
||||
|
||||
FIXTURE = Path(__file__).resolve().parent / "fixtures" / "menu_page.html"
|
||||
|
||||
|
|
@ -43,6 +43,12 @@ def test_parse_menu_html_rejects_a_missing_catalog():
|
|||
parse_menu_html("<html></html>", menu_url="https://example.com/menu")
|
||||
|
||||
|
||||
def test_extract_catalog_products_rejects_an_empty_catalog():
|
||||
page = "<orders-page :products='[]' :newest-ids='[]'></orders-page>"
|
||||
with pytest.raises(MenuParseError, match="empty"):
|
||||
extract_catalog_products(page)
|
||||
|
||||
|
||||
def test_parse_menu_html_rejects_an_empty_catalog():
|
||||
page = "<orders-page :products='[]' :newest-ids='[]'></orders-page>"
|
||||
with pytest.raises(MenuParseError, match="empty"):
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue