- 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>
97 lines
2.5 KiB
Python
97 lines
2.5 KiB
Python
"""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 == ""
|