# Fixtures Cdiscount

Ce dossier contient des fichiers HTML réels capturés depuis Cdiscount.com pour les tests.

## ⚠️ Note importante sur Cdiscount

Cdiscount utilise une **protection anti-bot forte** (Cloudflare/Baleen):
- HTTP simple retourne une page de protection JavaScript (~14 KB)
- **Playwright est OBLIGATOIRE** pour récupérer le vrai contenu
- Temps de chargement: ~2-3 secondes

## Fichiers

### cdiscount_tuf608umrv004_pw.html
- **Produit**: PC Portable Gamer ASUS TUF Gaming A16
- **SKU**: tuf608umrv004
- **URL**: https://www.cdiscount.com/informatique/ordinateurs-pc-portables/pc-portable-gamer-asus-tuf-gaming-a16-sans-windo/f-10709-tuf608umrv004.html
- **Taille**: ~310 KB
- **Lignes**: 399
- **Méthode**: Playwright (headless)
- **Date capture**: 2026-01-13
- **Usage**: Test complet parsing produit tech

## Différences avec Amazon

| Aspect | Amazon | Cdiscount |
|--------|--------|-----------|
| **Anti-bot** | Faible (HTTP OK) | ✗ Fort (Playwright requis) |
| **Sélecteurs** | Stables (IDs) | Instables (classes générées) |
| **Structure** | `#productTitle`, `.a-price` | `data-e2e="title"`, classes dynamiques |
| **Prix** | 3 parties (whole+fraction+symbol) | Texte direct "1499,99 €" |
| **Référence** | ASIN dans URL `/dp/{ASIN}` | SKU dans URL `/f-{cat}-{SKU}.html` |
| **Catégorie** | Breadcrumb HTML | Dans l'URL path |
| **Specs** | Tables HTML | Peut être dans onglets cachés |

## Sélecteurs identifiés

### Titre
```css
h1[data-e2e="title"]
```
Exemple: "PC Portable Gamer ASUS TUF Gaming A16 | Sans Windows - 16" WUXGA..."

### Prix
Classes CSS instables. Utiliser **regex sur le texte**:
```regex
(\d+[,\.]\d+)\s*€
```
Exemple: "1199,99 €" → 1199.99

### Images
```css
img[alt]
```
Filtrer celles dont `alt` contient le titre du produit.
Format URL: `https://www.cdiscount.com/pdt2/0/0/4/{num}/700x700/{sku}/rw/...`

### SKU
Extraction depuis l'URL:
```regex
/f-\d+-([a-z0-9]+)\.html
```
Groupe 1 = SKU (ex: `tuf608umrv004`)

### Catégorie
Extraction depuis l'URL path:
```
/informatique/ordinateurs-pc-portables/...
  ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^
  catégorie1 catégorie2
```

## Utilisation dans les tests

```python
@pytest.fixture
def cdiscount_fixture_tuf608umrv004():
    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()

def test_parse_real_fixture(store, cdiscount_fixture_tuf608umrv004):
    url = "https://www.cdiscount.com/informatique/.../f-10709-tuf608umrv004.html"
    snapshot = store.parse(cdiscount_fixture_tuf608umrv004, url)

    assert snapshot.title is not None
    assert "ASUS" in snapshot.title
    assert snapshot.price == 1199.99
    assert snapshot.reference == "tuf608umrv004"
```

## Points d'attention pour les tests

1. **Ne pas tester les valeurs exactes** (prix, nombre d'avis) car elles changent
2. **Tester le format** et la présence des données
3. **Prévoir des fallbacks** pour chaque champ (sélecteurs instables)
4. Les classes CSS peuvent changer à tout moment
5. Utiliser `data-e2e` attributes quand disponibles (plus stables)
6. Parser le prix par regex plutôt que par sélecteurs CSS

## Comment capturer une nouvelle fixture

```python
from pricewatch.app.scraping.pw_fetch import fetch_playwright

url = "https://www.cdiscount.com/..."
result = fetch_playwright(url, headless=True, timeout_ms=60000)

if result.success:
    with open("fixture.html", "w", encoding="utf-8") as f:
        f.write(result.html)
```

⚠️ **N'utilisez JAMAIS** `fetch_http()` pour Cdiscount - cela ne fonctionnera pas!
