feat(crawler): read back pixelrag visual evidence
This commit is contained in:
@@ -2,6 +2,7 @@ import json
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from datetime import datetime, timezone
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -234,6 +235,107 @@ def test_pixelrag_ai_automation_route_returns_assessment_and_manifest():
|
||||
assert manifest["capture_target"]["platform"] == "pchome"
|
||||
|
||||
|
||||
def _write_capture_receipt(root, *, platform="pchome", manifest_id="manifest-1"):
|
||||
target_dir = root / platform / manifest_id
|
||||
tiles_dir = target_dir / "tiles"
|
||||
tiles_dir.mkdir(parents=True)
|
||||
screenshot = target_dir / "fullpage.png"
|
||||
tile_0 = tiles_dir / "tile_000.png"
|
||||
tile_1 = tiles_dir / "tile_001.png"
|
||||
screenshot.write_bytes(b"png")
|
||||
tile_0.write_bytes(b"png")
|
||||
tile_1.write_bytes(b"png")
|
||||
receipt = {
|
||||
"success": True,
|
||||
"policy": "read_only_pixelrag_visual_capture_artifact_v1",
|
||||
"status": "captured",
|
||||
"generated_at": datetime.now(timezone.utc).isoformat(),
|
||||
"manifest_id": manifest_id,
|
||||
"capture_target": {
|
||||
"platform": platform,
|
||||
"crawler": "PChomeCrawler.visual_fallback",
|
||||
"trigger_reason": "parser_empty",
|
||||
"url": "https://24h.pchome.com.tw/",
|
||||
},
|
||||
"http_status": 200,
|
||||
"page_metrics": {
|
||||
"final_url": "https://24h.pchome.com.tw/",
|
||||
"title": "PChome 24h購物",
|
||||
},
|
||||
"tile_plan": {
|
||||
"planned_tile_count": 6,
|
||||
"emitted_tile_count": 2,
|
||||
},
|
||||
"files": [
|
||||
{"kind": "fullpage_screenshot", "path": str(screenshot)},
|
||||
{"kind": "tile", "path": str(tile_0)},
|
||||
{"kind": "tile", "path": str(tile_1)},
|
||||
],
|
||||
}
|
||||
(target_dir / "capture_receipt.json").write_text(
|
||||
json.dumps(receipt, ensure_ascii=False),
|
||||
encoding="utf-8",
|
||||
)
|
||||
return target_dir / "capture_receipt.json"
|
||||
|
||||
|
||||
def test_pixelrag_visual_evidence_readback_reports_latest_receipt(tmp_path):
|
||||
from services.pixelrag_crawler_integration_service import (
|
||||
READBACK_POLICY,
|
||||
build_pixelrag_visual_evidence_readback,
|
||||
)
|
||||
|
||||
receipt_path = _write_capture_receipt(tmp_path)
|
||||
payload = build_pixelrag_visual_evidence_readback(
|
||||
artifact_root=tmp_path,
|
||||
platform="pchome",
|
||||
manifest_id="manifest-1",
|
||||
)
|
||||
|
||||
assert payload["policy"] == READBACK_POLICY
|
||||
assert payload["status"] == "ok"
|
||||
assert payload["summary"]["receipt_count"] == 1
|
||||
assert payload["summary"]["tile_file_count"] == 2
|
||||
assert payload["summary"]["missing_file_count"] == 0
|
||||
assert payload["summary"]["http_status"] == 200
|
||||
assert payload["latest_receipt"]["path"] == str(receipt_path)
|
||||
assert payload["next_machine_action"] == "keep_pixelrag_visual_evidence_receipt"
|
||||
assert payload["controlled_apply"]["db_write"] is False
|
||||
|
||||
|
||||
def test_pixelrag_visual_evidence_readback_warns_when_missing(tmp_path):
|
||||
from services.pixelrag_crawler_integration_service import build_pixelrag_visual_evidence_readback
|
||||
|
||||
payload = build_pixelrag_visual_evidence_readback(artifact_root=tmp_path, platform="momo")
|
||||
|
||||
assert payload["success"] is False
|
||||
assert payload["status"] == "warning"
|
||||
assert payload["summary"]["receipt_count"] == 0
|
||||
assert payload["next_machine_action"] == "run_pixelrag_visual_capture_worker"
|
||||
|
||||
|
||||
def test_pixelrag_visual_evidence_readback_route_returns_payload(tmp_path, monkeypatch):
|
||||
from flask import Flask
|
||||
from routes import system_public_routes as routes
|
||||
from services import pixelrag_crawler_integration_service as service
|
||||
|
||||
_write_capture_receipt(tmp_path, platform="pchome", manifest_id="route-manifest")
|
||||
monkeypatch.setattr(service, "DEFAULT_ARTIFACT_ROOT", str(tmp_path))
|
||||
app = Flask(__name__)
|
||||
|
||||
with app.test_request_context(
|
||||
"/api/ai-automation/pixelrag-visual-evidence-readback"
|
||||
"?platform=pchome&manifest_id=route-manifest&max_age_hours=999"
|
||||
):
|
||||
response = routes.ai_automation_pixelrag_visual_evidence_readback_api.__wrapped__()
|
||||
payload = response.get_json()
|
||||
|
||||
assert payload["policy"] == "read_only_pixelrag_visual_evidence_readback_v1"
|
||||
assert payload["status"] == "ok"
|
||||
assert payload["manifest_id"] == "route-manifest"
|
||||
assert payload["summary"]["tile_file_count"] == 2
|
||||
|
||||
|
||||
def test_pixelrag_capture_worker_dry_run_plans_artifact_outputs(tmp_path):
|
||||
if not shutil.which("node"):
|
||||
pytest.skip("node is required for the dry-run capture worker test")
|
||||
|
||||
Reference in New Issue
Block a user