Files
Tirsvad 5ac60a43fc MIL-002 scrape price (Step 1)
Delivers MIL-002 (lecture Step 1): BeautifulSoup reads the title and the price (as a float, 99.99) from the practice page. Layers: domain (Product, errors), application (ports, read_product), infrastructure (scraper, HTTP client), main as composition root. Tests use a trimmed fixture of the practice page and never the network.

Review: code against QC-PY-001 as RC-011 (Go, autonomous, not independent). 15 pytest tests, ruff and mypy --strict pass; a real run printed 99.99. Screenshots: docs/images/step-1-*.png.

Task: MIL-002#1
Task: MIL-002#2
Task: MIL-002#3
Task: MIL-002#4
Task: MIL-002#5
2026-10-28 14:40:33 +08:00

35 lines
999 B
Python

from amazon_price_tracker.application.read_product import read_product
from amazon_price_tracker.domain.product import Product
class FakeFetcher:
def __init__(self, html: str) -> None:
self.html = html
self.urls: list[str] = []
def fetch(self, url: str) -> str:
self.urls.append(url)
return self.html
class FakeParser:
def __init__(self, product: Product) -> None:
self.product = product
self.received: list[str] = []
def parse(self, html: str) -> Product:
self.received.append(html)
return self.product
def test_read_product_fetches_url_and_returns_parsed_product() -> None:
expected = Product(title="Pot", price=9.5)
fetcher = FakeFetcher("<html>page</html>")
parser = FakeParser(expected)
result = read_product(fetcher, parser, "https://example.test/p")
assert result == expected
assert fetcher.urls == ["https://example.test/p"]
assert parser.received == ["<html>page</html>"]