Test dashboard: full menu system, all-service tests, filtering

- Run tests for all 10 services via per-service pytest subprocesses
- Group results by service with section headers
- Clickable summary cards filter by outcome (passed/failed/errors/skipped)
- Service filter nav using ~nav-link buttons in menu bar
- Full menu integration: ~header-row + ~header-child + ~menu-row
- Show logo image via cart-mini rendering
- Mount full service directories in docker-compose for test access
- Add 24 unit test files across 9 services

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-28 22:54:25 +00:00
parent 81e51ae7bc
commit 3809affcab
41 changed files with 2484 additions and 110 deletions

View File

@@ -0,0 +1,96 @@
"""Unit tests for price parsing utilities."""
from __future__ import annotations
import pytest
from market.scrape.product.helpers.price import parse_price, parse_case_size
class TestParsePrice:
def test_gbp(self):
val, cur, raw = parse_price("£30.50")
assert val == 30.5
assert cur == "GBP"
def test_eur(self):
val, cur, raw = parse_price("€1,234.00")
assert val == 1234.0
assert cur == "EUR"
def test_usd(self):
val, cur, raw = parse_price("$9.99")
assert val == 9.99
assert cur == "USD"
def test_no_symbol(self):
val, cur, raw = parse_price("42.50")
assert val == 42.5
assert cur is None
def test_no_match(self):
val, cur, raw = parse_price("no price here")
assert val is None
assert cur is None
def test_empty_string(self):
val, cur, raw = parse_price("")
assert val is None
assert raw == ""
def test_none_input(self):
val, cur, raw = parse_price(None)
assert val is None
assert raw == ""
def test_thousands_comma_stripped(self):
val, cur, raw = parse_price("£1,000.50")
assert val == 1000.5
def test_whitespace_around_symbol(self):
val, cur, raw = parse_price("£ 5.00")
assert val == 5.0
assert cur == "GBP"
def test_raw_preserved(self):
_, _, raw = parse_price(" £10.00 ")
assert raw == "£10.00"
class TestParseCaseSize:
def test_standard(self):
count, qty, unit, _ = parse_case_size("6 x 500g")
assert count == 6
assert qty == 500.0
assert unit == "g"
def test_no_space(self):
count, qty, unit, _ = parse_case_size("12x1L")
assert count == 12
assert qty == 1.0
assert unit == "L"
def test_multiplication_sign(self):
count, qty, unit, _ = parse_case_size("24 × 330 ml")
assert count == 24
assert qty == 330.0
assert unit == "ml"
def test_uppercase_x(self):
count, qty, unit, _ = parse_case_size("6X500g")
assert count == 6
def test_no_match(self):
count, qty, unit, raw = parse_case_size("just text")
assert count is None
assert qty is None
assert unit is None
def test_empty(self):
count, qty, unit, raw = parse_case_size("")
assert count is None
assert raw == ""
def test_none_input(self):
count, _, _, raw = parse_case_size(None)
assert count is None
assert raw == ""