133 lines
4.6 KiB
Python
133 lines
4.6 KiB
Python
"""Unit tests for Apify → CompetitiveSnapshot mapping (no network)."""
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
from pathlib import Path
|
|
|
|
from pricing_agent.schemas import BuyBoxStatus
|
|
from pricing_agent.tools.amazon.apify import item_to_competitive
|
|
|
|
FIX = Path(__file__).parent / "fixtures" / "apify_amazon_item.json"
|
|
ITEMS = json.loads(FIX.read_text(encoding="utf-8"))
|
|
OUR_SELLER = "A3AQP8TDYVYCGL"
|
|
|
|
|
|
def test_won_when_seller_matches():
|
|
snap = item_to_competitive(
|
|
ITEMS["won"],
|
|
asin="B01ND3Y00M",
|
|
our_price=6.98,
|
|
our_seller_id=OUR_SELLER,
|
|
)
|
|
assert snap.buy_box_status == BuyBoxStatus.WON
|
|
assert snap.buy_box_price == 6.98
|
|
assert snap.is_suppressed is False
|
|
assert "Featured Offer" in snap.reason or "hold" in snap.reason.lower()
|
|
# Sole seller, no rival offers -> there is no competitive band to report.
|
|
assert snap.competitive_low is None
|
|
assert snap.competitive_median is None
|
|
assert snap.competitive_high is None
|
|
|
|
|
|
def test_our_own_offers_never_become_the_competitive_band():
|
|
"""Regression: B01ND3Y00M returns three offers, all ours, one of them used.
|
|
|
|
The old mapper reported low/median/high = 6.99/9.99/12.99 and told the user
|
|
"Competitors: Utopia Brands" — it was quoting us back at ourselves.
|
|
"""
|
|
snap = item_to_competitive(
|
|
ITEMS["won_self_offers_only"],
|
|
asin="B01ND3Y00M",
|
|
our_price=6.99,
|
|
our_seller_id=OUR_SELLER,
|
|
)
|
|
assert snap.buy_box_status == BuyBoxStatus.WON
|
|
assert snap.buy_box_price == 6.99
|
|
# No rivals on this listing -> no band at all.
|
|
assert snap.competitive_low is None
|
|
assert snap.competitive_median is None
|
|
assert snap.competitive_high is None
|
|
assert all(o.is_ours for o in snap.offers)
|
|
assert "Competitors: none" in snap.reason
|
|
assert "Utopia Brands @ $9.99" not in snap.reason.split("Our own offers:")[0]
|
|
|
|
|
|
def test_used_offers_excluded_from_band():
|
|
"""A used rival offer must not set competitive_low; only new stock competes."""
|
|
snap = item_to_competitive(
|
|
ITEMS["won_with_used_rival"],
|
|
asin="B0MIXED001",
|
|
our_price=19.99,
|
|
our_seller_id=OUR_SELLER,
|
|
)
|
|
assert snap.buy_box_status == BuyBoxStatus.WON
|
|
# Only the New rival at 22.50 counts. The used $8.00 offer is ignored, and our
|
|
# own $19.99 featured offer is not a competitor either.
|
|
assert snap.competitive_low == 22.50
|
|
assert snap.competitive_median == 22.50
|
|
assert snap.competitive_high == 22.50
|
|
|
|
|
|
def test_rival_holds_buy_box_at_higher_price_is_not_a_price_loss():
|
|
"""We are cheaper but still lost the Buy Box -> eligibility, not price."""
|
|
snap = item_to_competitive(
|
|
ITEMS["lost_eligibility"],
|
|
asin="B0ELIG0001",
|
|
our_price=24.99,
|
|
our_seller_id=OUR_SELLER,
|
|
)
|
|
assert snap.buy_box_status == BuyBoxStatus.LOST_ELIGIBILITY
|
|
assert snap.buy_box_price == 26.00
|
|
# Band is the rival only; our own 24.99 offer is excluded.
|
|
assert snap.competitive_low == 26.00
|
|
assert snap.competitive_high == 26.00
|
|
|
|
|
|
def test_lost_price_and_offer_band():
|
|
snap = item_to_competitive(
|
|
ITEMS["lost_with_offers"],
|
|
asin="B0COMPETE01",
|
|
our_price=24.99,
|
|
our_seller_id=OUR_SELLER,
|
|
)
|
|
assert snap.buy_box_status == BuyBoxStatus.LOST_PRICE
|
|
assert snap.buy_box_price == 21.49
|
|
assert snap.buy_box_seller_name == "Rival Seller"
|
|
assert snap.competitive_low == 21.49
|
|
assert snap.competitive_high == 24.99
|
|
assert snap.competitive_median == 22.00
|
|
assert snap.is_suppressed is False
|
|
assert len(snap.offers) >= 3
|
|
names = {o.seller_name for o in snap.offers}
|
|
assert "Rival Seller" in names
|
|
assert "Other Mart" in names
|
|
assert "Budget Goods" in names
|
|
buy_box = next(o for o in snap.offers if o.is_buy_box)
|
|
assert buy_box.price == 21.49
|
|
assert "Competitors:" in snap.reason
|
|
|
|
|
|
def test_suppressed_when_no_featured_price():
|
|
snap = item_to_competitive(
|
|
ITEMS["suppressed"],
|
|
asin="B0NOSHOW",
|
|
our_price=24.99,
|
|
our_seller_id=OUR_SELLER,
|
|
)
|
|
assert snap.buy_box_status == BuyBoxStatus.SUPPRESSED
|
|
assert snap.is_suppressed is True
|
|
assert snap.buy_box_price is None
|
|
assert snap.competitive_low == 19.99
|
|
assert any(o.seller_name == "Third Party Co" and o.price == 19.99 for o in snap.offers)
|
|
|
|
|
|
def test_undercut_without_seller_id_flags_lost_price():
|
|
snap = item_to_competitive(
|
|
ITEMS["lost_with_offers"],
|
|
asin="B0COMPETE01",
|
|
our_price=24.99,
|
|
our_seller_id=None,
|
|
)
|
|
assert snap.buy_box_status == BuyBoxStatus.LOST_PRICE
|
|
assert "APIFY_SELLER_ID" in snap.reason
|