This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
from pathlib import Path
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
@@ -24,6 +25,9 @@ def test_competitor_feeder_persists_all_match_attempt_outcomes():
|
||||
assert "_should_upsert_competitor_price" in source
|
||||
assert "replace_legacy_unverified" in source
|
||||
assert "identity_v2" in source
|
||||
assert "_fetch_expired_identity_skus" in source
|
||||
assert "run_expired_identity_refresh" in source
|
||||
assert "refresh_known_identity" in source
|
||||
|
||||
assert "CREATE TABLE IF NOT EXISTS competitor_match_attempts" in migration
|
||||
assert "attempt_status" in migration
|
||||
@@ -47,3 +51,75 @@ def test_competitor_feeder_logs_keyword_parser_fallback(monkeypatch, caplog):
|
||||
|
||||
assert terms
|
||||
assert "fallback to cleaned product name" in caplog.text
|
||||
|
||||
|
||||
def test_competitor_feeder_refreshes_expired_identity_by_known_product_id(monkeypatch):
|
||||
from services.competitor_price_feeder import CompetitorPriceFeeder
|
||||
from services.pchome_crawler import PChomeProduct
|
||||
|
||||
requested = []
|
||||
product = PChomeProduct(
|
||||
product_id="DDAB01-1900ABCD",
|
||||
name="舒特膚 AD 乳液 200ml",
|
||||
price=899,
|
||||
original_price=999,
|
||||
discount=10,
|
||||
image_url="",
|
||||
product_url="https://24h.pchome.com.tw/prod/DDAB01-1900ABCD",
|
||||
stock=50,
|
||||
store="24h",
|
||||
rating=4.8,
|
||||
review_count=12,
|
||||
is_on_sale=True,
|
||||
crawled_at=datetime.now(),
|
||||
)
|
||||
|
||||
class FakeCrawler:
|
||||
def __init__(self, *_args, **_kwargs):
|
||||
pass
|
||||
|
||||
def fetch_product_details(self, product_ids, batch_size=20):
|
||||
requested.extend(product_ids)
|
||||
return True, "ok", [product]
|
||||
|
||||
monkeypatch.setattr("services.pchome_crawler.PChomeCrawler", FakeCrawler)
|
||||
feeder = CompetitorPriceFeeder(engine=object())
|
||||
writes = []
|
||||
attempts = []
|
||||
monkeypatch.setattr(
|
||||
feeder,
|
||||
"_should_upsert_competitor_price",
|
||||
lambda *_args, **_kwargs: (True, "same_or_empty_existing"),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
feeder,
|
||||
"_upsert_competitor_price",
|
||||
lambda sku, product, score, tags, **kwargs: writes.append({
|
||||
"sku": sku,
|
||||
"product_id": product.product_id,
|
||||
"score": score,
|
||||
"tags": tags,
|
||||
**kwargs,
|
||||
}),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
feeder,
|
||||
"_record_match_attempt",
|
||||
lambda *args, **kwargs: attempts.append(kwargs),
|
||||
)
|
||||
|
||||
result = feeder._run_known_identity_refresh_items([{
|
||||
"sku": "A001",
|
||||
"name": "舒特膚 AD 乳液 200ml",
|
||||
"product_id": 1,
|
||||
"momo_price": 980,
|
||||
"competitor_product_id": "DDAB01-1900ABCD",
|
||||
}])
|
||||
|
||||
assert requested == ["DDAB01-1900ABCD"]
|
||||
assert result.matched == 1
|
||||
assert writes[0]["product_id"] == "DDAB01-1900ABCD"
|
||||
assert "identity_v2" in writes[0]["tags"]
|
||||
assert "refresh_known_identity" in writes[0]["tags"]
|
||||
assert attempts[0]["attempt_status"] == "matched"
|
||||
assert attempts[0]["search_terms"] == ["known_product_id:DDAB01-1900ABCD"]
|
||||
|
||||
@@ -359,6 +359,7 @@ def test_ai_product_pick_agent_uses_real_competitor_data_and_dashboard_action():
|
||||
feeder_source = (ROOT / "services/competitor_price_feeder.py").read_text(encoding="utf-8")
|
||||
agent_source = (ROOT / "services/ai_product_pick_agent.py").read_text(encoding="utf-8")
|
||||
route_source = (ROOT / "routes/ai_routes.py").read_text(encoding="utf-8")
|
||||
scheduler_source = (ROOT / "scheduler.py").read_text(encoding="utf-8")
|
||||
template = (ROOT / "templates/ai_intelligence.html").read_text(encoding="utf-8")
|
||||
|
||||
assert "MIN_MATCH_SCORE = 0.76" in feeder_source
|
||||
@@ -369,7 +370,11 @@ def test_ai_product_pick_agent_uses_real_competitor_data_and_dashboard_action():
|
||||
assert "_search_pchome_candidates" in feeder_source
|
||||
assert "crawler.search_products(keyword, limit=SEARCH_LIMIT)" in feeder_source
|
||||
assert "_fetch_unmatched_priority_skus" in feeder_source
|
||||
assert "_fetch_expired_identity_skus" in feeder_source
|
||||
assert "run_expired_identity_refresh" in feeder_source
|
||||
assert "fetch_product_details(requested_ids" in feeder_source
|
||||
assert "run_unmatched_priority" in feeder_source
|
||||
assert "run_expired_identity_refresh(limit=240)" in scheduler_source
|
||||
|
||||
assert "generate_product_pick_list" in agent_source
|
||||
assert "clear_dashboard_cache()" in route_source
|
||||
|
||||
Reference in New Issue
Block a user