chore: sync project files
This commit is contained in:
201
tests/stores/test_cdiscount_fixtures.py
Executable file
201
tests/stores/test_cdiscount_fixtures.py
Executable file
@@ -0,0 +1,201 @@
|
||||
"""
|
||||
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
|
||||
Reference in New Issue
Block a user