Spaces:
Running
Running
| """Tests for the DMart market source adapter.""" | |
| from __future__ import annotations | |
| from datetime import date | |
| from pathlib import Path | |
| import pytest | |
| from shopstack.market.schema import MarketSnapshot | |
| from shopstack.market.sources._dmart_adapter import ( | |
| DmartAdapter, | |
| DEFAULT_CAPTURED_AT, | |
| DEFAULT_SNAPSHOT_ID, | |
| load_raw, | |
| load_snapshot, | |
| normalize_record, | |
| snapshot_freshness, | |
| ) | |
| _FIXTURE_DIR = Path(__file__).resolve().parent / "fixtures" | |
| # ---------- Raw loader ---------- | |
| class TestDmartLoader: | |
| def test_load_raw(self): | |
| raw = load_raw(_FIXTURE_DIR) | |
| assert len(raw) == 6 | |
| def test_load_snapshot(self): | |
| snapshot = load_snapshot(data_dir=_FIXTURE_DIR) | |
| assert isinstance(snapshot, MarketSnapshot) | |
| assert len(snapshot.normalized_records) == 6 | |
| def test_snapshot_id(self): | |
| snapshot = load_snapshot(data_dir=_FIXTURE_DIR) | |
| assert snapshot.snapshot_id.startswith("dmart_") | |
| assert snapshot.source == "dmart" | |
| def test_file_not_found(self): | |
| with pytest.raises(FileNotFoundError, match="No dmart_fresh_vegetables_"): | |
| load_raw(Path("/nonexistent")) | |
| # ---------- Normalization ---------- | |
| class TestDmartNormalization: | |
| def test_tomato_normalization(self): | |
| raw = load_raw(_FIXTURE_DIR) | |
| record = normalize_record(raw[0]) | |
| assert record.source == "dmart" | |
| assert record.raw_name == "Hybrid Tomato" | |
| assert record.canonical_name == "tomato" | |
| assert record.raw_size == "500 g" | |
| assert record.normalized_quantity == 500 | |
| assert record.normalized_unit == "g" | |
| assert record.is_weight_based is True | |
| assert record.is_available is True | |
| assert record.price_inr == 26.0 # current_price | |
| assert record.mrp_inr == 32.0 # listed_price | |
| assert record.price_per_kg == 52.0 | |
| assert record.price_per_100g == 5.2 | |
| def test_onion_normalization(self): | |
| raw = load_raw(_FIXTURE_DIR) | |
| record = normalize_record(raw[1]) | |
| assert record.canonical_name == "onion" | |
| assert record.raw_size == "1 kg" | |
| assert record.normalized_quantity == 1000 | |
| assert record.price_inr == 25.0 | |
| assert record.mrp_inr == 30.0 | |
| assert record.price_per_kg == 25.0 | |
| assert record.brand == "DMart Fresh" | |
| def test_sold_out_carrot(self): | |
| raw = load_raw(_FIXTURE_DIR) | |
| record = normalize_record(raw[3]) | |
| assert record.canonical_name == "carrot" | |
| assert record.is_available is False | |
| def test_ad_tagged_item(self): | |
| raw = load_raw(_FIXTURE_DIR) | |
| record = normalize_record(raw[4]) | |
| assert record.is_ad is True | |
| assert record.is_upgrade is False | |
| assert record.tag == "ad" | |
| def test_combo_item(self): | |
| raw = load_raw(_FIXTURE_DIR) | |
| record = normalize_record(raw[5]) | |
| assert record.is_combo is True | |
| assert record.price_per_kg is None | |
| def test_missing_fields_avoid_crash(self): | |
| record = normalize_record({}) | |
| assert record.raw_name == "" | |
| assert record.price_inr == 0.0 | |
| assert record.is_available is False | |
| def test_promotional_discount(self): | |
| raw = load_raw(_FIXTURE_DIR) | |
| record = normalize_record(raw[0]) | |
| assert abs(record.computed_discount_percent - 18.8) < 0.1 | |
| # ---------- Freshness ---------- | |
| class TestDmartFreshness: | |
| def test_freshness_current(self): | |
| snapshot = load_snapshot(data_dir=_FIXTURE_DIR, captured_at="2026-06-06") | |
| freshness = snapshot_freshness(snapshot, today=date(2026, 6, 6)) | |
| assert freshness["age_days"] == 0 | |
| assert freshness["is_stale"] is False | |
| def test_freshness_yesterday(self): | |
| snapshot = load_snapshot(data_dir=_FIXTURE_DIR, captured_at="2026-06-05") | |
| freshness = snapshot_freshness(snapshot, today=date(2026, 6, 6)) | |
| assert freshness["age_days"] == 1 | |
| assert freshness["is_stale"] is False | |
| def test_freshness_stale(self): | |
| snapshot = load_snapshot(data_dir=_FIXTURE_DIR, captured_at="2026-06-01") | |
| freshness = snapshot_freshness(snapshot, today=date(2026, 6, 6)) | |
| assert freshness["age_days"] == 5 | |
| assert freshness["is_stale"] is True | |
| def test_freshness_no_date(self): | |
| snapshot = load_snapshot(data_dir=_FIXTURE_DIR, captured_at="bad-date") | |
| freshness = snapshot_freshness(snapshot) | |
| assert freshness["age_days"] is None | |
| assert freshness["is_stale"] is True | |
| # ---------- Adapter class ---------- | |
| class TestDmartAdapter: | |
| def test_adapter_instantiate(self): | |
| adapter = DmartAdapter(data_dir=_FIXTURE_DIR) | |
| assert adapter.source_id == "dmart" | |
| assert adapter.source_category == "fresh_vegetables" | |
| def test_adapter_load_snapshot(self): | |
| adapter = DmartAdapter(data_dir=_FIXTURE_DIR) | |
| snapshot = adapter.load_snapshot() | |
| assert isinstance(snapshot, MarketSnapshot) | |
| assert snapshot.source == "dmart" | |
| def test_adapter_freshness(self): | |
| adapter = DmartAdapter(data_dir=_FIXTURE_DIR) | |
| snapshot = adapter.load_snapshot() | |
| freshness = adapter.freshness(snapshot) | |
| assert "age_days" in freshness | |
| assert "is_stale" in freshness | |
| assert "label" in freshness | |
| def test_adapter_available_names(self): | |
| adapter = DmartAdapter(data_dir=_FIXTURE_DIR) | |
| snapshot = adapter.load_snapshot() | |
| names = adapter.available_canonical_names(snapshot) | |
| assert "tomato" in names | |
| assert "onion" in names | |
| assert "cucumber" in names | |
| assert "carrot" not in names # sold out | |
| def test_adapter_loads_from_any_directory(self): | |
| adapter = DmartAdapter(data_dir=_FIXTURE_DIR) | |
| snapshot = adapter.load_snapshot() | |
| assert len(snapshot.normalized_records) == 6 | |