110 lines
4.0 KiB
Python
110 lines
4.0 KiB
Python
from __future__ import annotations
|
|
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
from sqlalchemy import select
|
|
|
|
from iaai_scraper.core.config import Settings
|
|
from iaai_scraper.storage.db import PersistenceService
|
|
from iaai_scraper.storage.models import Car, Image
|
|
from iaai_scraper.storage.schemas import CarRecord, ImageRecord
|
|
|
|
|
|
class TestPersistenceServiceIntegration(unittest.TestCase):
|
|
def setUp(self) -> None:
|
|
self.tmp_dir = tempfile.TemporaryDirectory()
|
|
db_path = Path(self.tmp_dir.name) / "test.sqlite"
|
|
|
|
self.settings = Settings()
|
|
self.settings.database.url = f"sqlite:///{db_path.as_posix()}"
|
|
self.settings.database.echo = False
|
|
|
|
self.persistence = PersistenceService(self.settings)
|
|
self.persistence.create_tables()
|
|
|
|
def tearDown(self) -> None:
|
|
self.persistence.engine.dispose()
|
|
self.tmp_dir.cleanup()
|
|
|
|
@staticmethod
|
|
def _record(origin_id: str, *, price: int = 1000, content_hash: str = "hash1") -> CarRecord:
|
|
return CarRecord(
|
|
parser_id=f"iaai:{origin_id}",
|
|
brand="Toyota",
|
|
model="Camry",
|
|
year=2014,
|
|
price=price,
|
|
origin_url=f"https://www.iaai.com/VehicleDetail/{origin_id}~US",
|
|
origin_id=origin_id,
|
|
slug=f"toyota-camry-{origin_id}",
|
|
content_hash=content_hash,
|
|
images=[
|
|
ImageRecord(
|
|
fullres_image="https://vis.iaai.com/resizer?imageKeys=1&width=845&height=633",
|
|
preview_image="https://vis.iaai.com/resizer?imageKeys=1&width=400&height=300",
|
|
order_index=0,
|
|
)
|
|
],
|
|
raw_attributes={"foo": "bar"},
|
|
)
|
|
|
|
def test_insert_update_and_skip_flow(self) -> None:
|
|
first = self._record("777", price=1000, content_hash="same")
|
|
inserted = self.persistence.upsert_car(first)
|
|
self.assertEqual(inserted["action"], "inserted")
|
|
self.assertEqual(inserted["images_upserted"], 1)
|
|
|
|
same = self._record("777", price=1000, content_hash="same")
|
|
updated_same = self.persistence.upsert_car(same)
|
|
self.assertEqual(updated_same["action"], "skipped")
|
|
self.assertEqual(updated_same["images_upserted"], 0)
|
|
|
|
changed = self._record("777", price=1500, content_hash="changed")
|
|
updated = self.persistence.upsert_car(changed)
|
|
self.assertEqual(updated["action"], "updated")
|
|
self.assertEqual(updated["images_upserted"], 1)
|
|
|
|
with self.persistence.session_scope() as session:
|
|
cars = session.execute(select(Car)).scalars().all()
|
|
images = session.execute(select(Image)).scalars().all()
|
|
|
|
self.assertEqual(len(cars), 1)
|
|
self.assertEqual(cars[0].price, 1500)
|
|
self.assertEqual(len(images), 1)
|
|
|
|
def test_update_replaces_old_images(self) -> None:
|
|
first = self._record("888", content_hash="v1")
|
|
self.persistence.upsert_car(first)
|
|
|
|
second = self._record("888", content_hash="v2")
|
|
second.images = [
|
|
ImageRecord(
|
|
fullres_image="https://vis.iaai.com/resizer?imageKeys=2&width=845&height=633",
|
|
preview_image="https://vis.iaai.com/resizer?imageKeys=2&width=400&height=300",
|
|
order_index=0,
|
|
)
|
|
]
|
|
self.persistence.upsert_car(second)
|
|
|
|
with self.persistence.session_scope() as session:
|
|
images = session.execute(select(Image)).scalars().all()
|
|
|
|
self.assertEqual(len(images), 1)
|
|
self.assertIn("imageKeys=2", images[0].fullres_image)
|
|
|
|
def test_same_content_hash_is_skipped(self) -> None:
|
|
first = self._record("999", content_hash="same-hash")
|
|
self.persistence.upsert_car(first)
|
|
|
|
second = self._record("999", content_hash="same-hash")
|
|
result = self.persistence.upsert_car(second)
|
|
|
|
self.assertEqual(result["action"], "skipped")
|
|
self.assertEqual(result["images_upserted"], 0)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|