Files
scrap/tests/stores/test_cdiscount_fixtures.py
2026-01-13 19:49:04 +01:00

202 lines
8.7 KiB
Python
Executable File

"""
Tests pour pricewatch.app.stores.cdiscount.store avec fixtures HTML réels.
Teste le parsing de vraies pages HTML capturées depuis Cdiscount.com.
"""
import pytest
from pathlib import Path
from pricewatch.app.stores.cdiscount.store import CdiscountStore
from pricewatch.app.core.schema import DebugStatus, StockStatus
class TestCdiscountRealFixtures:
"""Tests avec fixtures HTML réels capturés depuis Cdiscount."""
@pytest.fixture
def store(self) -> CdiscountStore:
"""Fixture: CdiscountStore instance."""
return CdiscountStore()
@pytest.fixture
def fixture_tuf608umrv004(self) -> str:
"""Fixture: HTML Cdiscount tuf608umrv004 (PC Portable Gamer ASUS)."""
fixture_path = Path(__file__).parent.parent.parent / \
"pricewatch/app/stores/cdiscount/fixtures/cdiscount_tuf608umrv004_pw.html"
with open(fixture_path, "r", encoding="utf-8") as f:
return f.read()
@pytest.fixture
def fixture_a128902(self) -> str:
"""Fixture: HTML Cdiscount a128902 (Canapé d'angle NIRVANA)."""
fixture_path = Path(__file__).parent.parent.parent / \
"pricewatch/app/stores/cdiscount/fixtures/cdiscount_a128902_pw.html"
with open(fixture_path, "r", encoding="utf-8") as f:
return f.read()
def test_parse_tuf608umrv004_complete(self, store, fixture_tuf608umrv004):
"""Parse fixture tuf608umrv004 - doit extraire toutes les données essentielles."""
url = "https://www.cdiscount.com/informatique/ordinateurs-pc-portables/pc-portable-gamer-asus-tuf-gaming-a16-sans-windo/f-10709-tuf608umrv004.html"
snapshot = store.parse(fixture_tuf608umrv004, url)
# Métadonnées
assert snapshot.source == "cdiscount"
assert snapshot.url == url
assert snapshot.reference == "10709-tuf608umrv004"
assert snapshot.fetched_at is not None
# Titre (doit contenir "ASUS" ou "TUF")
assert snapshot.title is not None
assert len(snapshot.title) > 0
assert "ASUS" in snapshot.title or "TUF" in snapshot.title
# Prix
assert snapshot.price is not None
assert snapshot.price > 0
assert snapshot.currency == "EUR"
# Status
assert snapshot.debug.status in [DebugStatus.SUCCESS, DebugStatus.PARTIAL]
def test_parse_a128902_complete(self, store, fixture_a128902):
"""Parse fixture a128902 - doit extraire toutes les données essentielles."""
url = "https://www.cdiscount.com/maison/canape-canapes/canape-d-angle-convertible-reversible-nirvana-4-5/f-11701-a128902.html"
snapshot = store.parse(fixture_a128902, url)
# Métadonnées
assert snapshot.source == "cdiscount"
assert snapshot.url == url
assert snapshot.reference == "11701-a128902"
# Titre
assert snapshot.title is not None
assert "Canapé" in snapshot.title or "NIRVANA" in snapshot.title.upper()
# Prix
assert snapshot.price is not None
assert snapshot.price > 0
assert snapshot.currency == "EUR"
# Status
assert snapshot.debug.status in [DebugStatus.SUCCESS, DebugStatus.PARTIAL]
def test_parse_tuf608umrv004_images(self, store, fixture_tuf608umrv004):
"""Parse fixture tuf608umrv004 - doit extraire au moins une image."""
url = "https://www.cdiscount.com/informatique/.../f-10709-tuf608umrv004.html"
snapshot = store.parse(fixture_tuf608umrv004, url)
# Doit avoir au moins une image
assert len(snapshot.images) > 0
# Les images doivent être des URLs valides
for img_url in snapshot.images:
assert img_url.startswith("http")
assert "cdiscount.com" in img_url.lower() or "cdscdn.com" in img_url.lower()
def test_parse_a128902_images(self, store, fixture_a128902):
"""Parse fixture a128902 - doit extraire au moins une image."""
url = "https://www.cdiscount.com/maison/.../f-11701-a128902.html"
snapshot = store.parse(fixture_a128902, url)
# Doit avoir au moins une image
assert len(snapshot.images) > 0
# Les images doivent être des URLs valides
for img_url in snapshot.images:
assert img_url.startswith("http")
def test_parse_tuf608umrv004_completeness(self, store, fixture_tuf608umrv004):
"""Parse fixture tuf608umrv004 - vérifier is_complete()."""
url = "https://www.cdiscount.com/informatique/.../f-10709-tuf608umrv004.html"
snapshot = store.parse(fixture_tuf608umrv004, url)
# Si titre ET prix sont présents, is_complete() doit être True
if snapshot.title and snapshot.price:
assert snapshot.is_complete() is True
else:
assert snapshot.is_complete() is False
def test_parse_a128902_completeness(self, store, fixture_a128902):
"""Parse fixture a128902 - vérifier is_complete()."""
url = "https://www.cdiscount.com/maison/.../f-11701-a128902.html"
snapshot = store.parse(fixture_a128902, url)
# Si titre ET prix sont présents, is_complete() doit être True
if snapshot.title and snapshot.price:
assert snapshot.is_complete() is True
else:
assert snapshot.is_complete() is False
def test_parse_tuf608umrv004_json_serialization(self, store, fixture_tuf608umrv004):
"""Parse fixture tuf608umrv004 - vérifier sérialisation JSON."""
url = "https://www.cdiscount.com/informatique/.../f-10709-tuf608umrv004.html"
snapshot = store.parse(fixture_tuf608umrv004, url)
# Doit pouvoir sérialiser en JSON sans erreur
json_str = snapshot.to_json()
assert json_str is not None
assert len(json_str) > 0
assert 'cdiscount' in json_str
assert 'tuf608umrv004' in json_str.lower()
def test_parse_a128902_json_serialization(self, store, fixture_a128902):
"""Parse fixture a128902 - vérifier sérialisation JSON."""
url = "https://www.cdiscount.com/maison/.../f-11701-a128902.html"
snapshot = store.parse(fixture_a128902, url)
# Doit pouvoir sérialiser en JSON sans erreur
json_str = snapshot.to_json()
assert json_str is not None
assert len(json_str) > 0
assert 'cdiscount' in json_str
assert 'a128902' in json_str
def test_parse_fixtures_preserve_sku(self, store, fixture_tuf608umrv004, fixture_a128902):
"""Parse fixtures - le SKU dans l'URL doit être préservé dans reference."""
# Test tuf608umrv004
url1 = "https://www.cdiscount.com/informatique/.../f-10709-tuf608umrv004.html"
snapshot1 = store.parse(fixture_tuf608umrv004, url1)
assert snapshot1.reference == "10709-tuf608umrv004"
# Test a128902
url2 = "https://www.cdiscount.com/maison/.../f-11701-a128902.html"
snapshot2 = store.parse(fixture_a128902, url2)
assert snapshot2.reference == "11701-a128902"
def test_parse_tuf608umrv004_price_format(self, store, fixture_tuf608umrv004):
"""Parse fixture tuf608umrv004 - le prix doit être un float valide."""
url = "https://www.cdiscount.com/informatique/.../f-10709-tuf608umrv004.html"
snapshot = store.parse(fixture_tuf608umrv004, url)
if snapshot.price:
assert isinstance(snapshot.price, float)
assert snapshot.price > 0
# Le prix doit avoir maximum 2 décimales
assert snapshot.price == round(snapshot.price, 2)
def test_parse_a128902_price_format(self, store, fixture_a128902):
"""Parse fixture a128902 - le prix doit être un float valide."""
url = "https://www.cdiscount.com/maison/.../f-11701-a128902.html"
snapshot = store.parse(fixture_a128902, url)
if snapshot.price:
assert isinstance(snapshot.price, float)
assert snapshot.price > 0
# Le prix doit avoir maximum 2 décimales
assert snapshot.price == round(snapshot.price, 2)
def test_parse_different_categories(self, store, fixture_tuf608umrv004, fixture_a128902):
"""Parse fixtures de catégories différentes - les deux doivent fonctionner."""
# PC Portable (informatique)
url1 = "https://www.cdiscount.com/informatique/.../f-10709-tuf608umrv004.html"
snapshot1 = store.parse(fixture_tuf608umrv004, url1)
assert snapshot1.is_complete()
# Canapé (maison)
url2 = "https://www.cdiscount.com/maison/.../f-11701-a128902.html"
snapshot2 = store.parse(fixture_a128902, url2)
assert snapshot2.is_complete()
# Les deux doivent être valides
assert snapshot1.price != snapshot2.price # Produits différents
assert snapshot1.title != snapshot2.title # Produits différents