Files
Vorrania/backend/tests/test_product_images.py
Scarriffle 2fa274eae8 Backup-Import: Bildadresse ging weiterhin verloren
Der vorige Anlauf war wirkungslos. _import_json baut aus jedem JSON-Eintrag eine
eigene Zeile fuer _get_or_create_product - und image_url stand in dieser Zeile
nicht drin. Die Abfrage lief also immer ins Leere.

Zwei Tests gehen jetzt durch _import_json statt nur durch
_get_or_create_product, weil die Adresse genau zwischen den beiden herausfiel.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 13:52:04 +02:00

109 lines
3.4 KiB
Python

import json
import pytest
from app.models import BaseUnit, Product, ProductImage, Role, User
from app.routers import transfer
from app.services import images
EIN_PIXEL = b"\x89PNG\r\n\x1a\n-nicht-echt-aber-egal"
def _artikel(db, url=None):
p = Product(name="Pesto", base_unit=BaseUnit.gram, package_size=195, image_url=url)
db.add(p)
db.commit()
db.refresh(p)
return p
def test_ohne_bildadresse_gibt_es_nichts_zu_holen(db, monkeypatch):
monkeypatch.setattr(images, "fetch", lambda url: (_ for _ in ()).throw(AssertionError))
assert images.ensure(db, _artikel(db)) is None
def test_bild_wird_einmal_geholt_und_danach_lokal_geliefert(db, monkeypatch):
aufrufe = []
def gefaelscht(url):
aufrufe.append(url)
return EIN_PIXEL, "image/png"
monkeypatch.setattr(images, "fetch", gefaelscht)
artikel = _artikel(db, "https://example.org/pesto.png")
erstes = images.ensure(db, artikel)
assert erstes is not None
assert erstes.data == EIN_PIXEL
assert erstes.content_type == "image/png"
# Zweiter Aufruf darf nicht erneut ins Netz gehen - genau das ist der Zweck.
images.ensure(db, artikel)
assert aufrufe == ["https://example.org/pesto.png"]
def test_ein_nicht_erreichbares_bild_bleibt_folgenlos(db, monkeypatch):
monkeypatch.setattr(images, "fetch", lambda url: None)
artikel = _artikel(db, "https://example.org/weg.png")
assert images.ensure(db, artikel) is None
assert db.get(ProductImage, artikel.id) is None
@pytest.fixture()
def user(db):
person = User(username="tester", password_hash="x", role=Role.admin)
db.add(person)
db.commit()
db.refresh(person)
return person
def test_backup_import_uebernimmt_die_bildadresse(db, user):
"""Sie stand im Backup, ging beim Einlesen aber verloren.
Der Test geht bewusst durch _import_json und nicht nur durch
_get_or_create_product: Genau zwischen beiden fiel die Adresse heraus.
"""
backup = {
"products": [
{
"name": "Pesto",
"brand": "Barilla",
"image_url": "https://example.org/pesto.jpg",
"unit": "Gramm",
"package_size": 195,
"lots": [],
}
]
}
transfer._import_json(db, json.dumps(backup).encode("utf-8"), user, "add")
db.commit()
artikel = db.query(Product).filter(Product.name == "Pesto").one()
assert artikel.image_url == "https://example.org/pesto.jpg"
def test_import_ueberschreibt_kein_vorhandenes_bild(db, user):
vorhanden = Product(
name="Pesto", base_unit=BaseUnit.gram, image_url="https://eigenes.example/bild.jpg"
)
db.add(vorhanden)
db.commit()
backup = {"products": [{"name": "Pesto", "image_url": "https://off.example/anderes.jpg",
"unit": "Gramm", "lots": []}]}
transfer._import_json(db, json.dumps(backup).encode("utf-8"), user, "add")
db.commit()
db.refresh(vorhanden)
assert vorhanden.image_url == "https://eigenes.example/bild.jpg"
def test_fetch_geht_nur_an_http_adressen(monkeypatch):
"""Ohne diese Schranke waere eine 'file://'-Adresse ein Weg ins Dateisystem."""
monkeypatch.setattr(
images.httpx, "get", lambda *a, **k: (_ for _ in ()).throw(AssertionError)
)
assert images.fetch("file:///etc/passwd") is None
assert images.fetch("") is None