feat: improve SPA scraping and increase test coverage
- Add SPA support for Playwright with wait_for_network_idle and extra_wait_ms - Add BaseStore.get_spa_config() and requires_playwright() methods - Implement AliExpress SPA config with JSON price extraction patterns - Fix Amazon price parsing to prioritize whole+fraction combination - Fix AliExpress regex patterns (remove double backslashes) - Add CLI tests: detect, doctor, fetch, parse, run commands - Add API tests: auth, logs, products, scraping_logs, webhooks Tests: 417 passed, 85% coverage Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
99
tests/cli/test_parse.py
Normal file
99
tests/cli/test_parse.py
Normal file
@@ -0,0 +1,99 @@
|
||||
"""Tests pour la commande CLI parse."""
|
||||
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from typer.testing import CliRunner
|
||||
|
||||
from pricewatch.app.cli.main import app
|
||||
|
||||
runner = CliRunner()
|
||||
|
||||
|
||||
class TestParseCommand:
|
||||
"""Tests pour la commande parse."""
|
||||
|
||||
@pytest.fixture
|
||||
def amazon_html_file(self, tmp_path: Path) -> Path:
|
||||
"""Cree un fichier HTML Amazon temporaire."""
|
||||
html = """
|
||||
<html>
|
||||
<body>
|
||||
<span id="productTitle">Test Product</span>
|
||||
<span class="a-price-whole">299,99 €</span>
|
||||
<div id="availability">
|
||||
<span>En stock</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
file_path = tmp_path / "amazon_test.html"
|
||||
file_path.write_text(html, encoding="utf-8")
|
||||
return file_path
|
||||
|
||||
@pytest.fixture
|
||||
def cdiscount_html_file(self, tmp_path: Path) -> Path:
|
||||
"""Cree un fichier HTML Cdiscount temporaire."""
|
||||
html = """
|
||||
<html>
|
||||
<head>
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@type": "Product",
|
||||
"name": "Produit Cdiscount",
|
||||
"offers": {"price": "199.99", "priceCurrency": "EUR"}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1 data-e2e="title">Produit Cdiscount</h1>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
file_path = tmp_path / "cdiscount_test.html"
|
||||
file_path.write_text(html, encoding="utf-8")
|
||||
return file_path
|
||||
|
||||
def test_parse_amazon_success(self, amazon_html_file: Path):
|
||||
"""Parse doit extraire les donnees d'un HTML Amazon."""
|
||||
result = runner.invoke(
|
||||
app, ["parse", "amazon", "--in", str(amazon_html_file)]
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
assert "Test Product" in result.stdout
|
||||
assert "299" in result.stdout
|
||||
|
||||
def test_parse_cdiscount_success(self, cdiscount_html_file: Path):
|
||||
"""Parse doit extraire les donnees d'un HTML Cdiscount."""
|
||||
result = runner.invoke(
|
||||
app, ["parse", "cdiscount", "--in", str(cdiscount_html_file)]
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
assert "Produit Cdiscount" in result.stdout
|
||||
assert "199" in result.stdout
|
||||
|
||||
def test_parse_unknown_store(self, amazon_html_file: Path):
|
||||
"""Parse doit echouer pour un store inconnu."""
|
||||
result = runner.invoke(
|
||||
app, ["parse", "unknown_store", "--in", str(amazon_html_file)]
|
||||
)
|
||||
assert result.exit_code == 1
|
||||
assert "inconnu" in result.stdout.lower()
|
||||
|
||||
def test_parse_with_debug(self, amazon_html_file: Path):
|
||||
"""Parse doit fonctionner avec --debug."""
|
||||
result = runner.invoke(
|
||||
app, ["parse", "amazon", "--in", str(amazon_html_file), "--debug"]
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
|
||||
def test_parse_shows_fields(self, amazon_html_file: Path):
|
||||
"""Parse doit afficher les champs extraits."""
|
||||
result = runner.invoke(
|
||||
app, ["parse", "amazon", "--in", str(amazon_html_file)]
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
assert "Titre" in result.stdout
|
||||
assert "Prix" in result.stdout
|
||||
assert "Stock" in result.stdout
|
||||
Reference in New Issue
Block a user