ocado-grocy/tests/test_images.py
2026-09-19 11:32:53 +01:00

87 lines
3 KiB
Python

import json
from types import SimpleNamespace
import pytest
from ocado_grocy.images import add_picture, file_path, image_type
DATA = b'\xff\xd8\xfftest-image'
def product():
return {'id':72, 'name':'Ocado title', 'description':'<p>Ocado product ID: 123</p>' + json.dumps({'Ocado product ID':'123','image_url':'https://www.ocado.com/images-v3/test.jpg'}), 'picture_file_name':None}
def response(data=DATA):
return SimpleNamespace(status_code=200, content=data, raise_for_status=lambda:None)
class API:
url = 'https://grocy.test/api'
timeout = 30
def __init__(self):
self.product = product()
self.writes = []
self.stored = DATA
self.session = self
def get(self, path, **kwargs):
if path.startswith(self.url):
assert '/files/productpictures/' in path
return response(self.stored)
assert path == '/objects/products/72'
return self.product.copy()
def put(self, path, **kwargs):
assert path.startswith(self.url + '/files/productpictures/')
assert kwargs['data'] == DATA
assert kwargs['headers'] == {'Content-Type':'application/octet-stream'}
self.writes.append(path)
return response()
def request(self, method, path, payload):
assert method == 'PUT' and path == '/objects/products/72'
assert set(payload) == {'picture_file_name'}
self.writes.append(payload)
self.product.update(payload)
class Downloader:
def get(self, url, **kwargs):
assert url == 'https://www.ocado.com/images-v3/test.jpg'
assert set(kwargs) == {'timeout','allow_redirects'}
return response()
def test_upload_verifies_file_and_only_sets_picture_field():
api = API()
assert add_picture(api, Downloader(), product()) == 'updated'
assert len(api.writes) == 2
assert api.product['name'] == 'Ocado title'
assert api.product['description'] == product()['description']
assert add_picture(api, Downloader(), api.product) == 'existing_picture'
assert len(api.writes) == 2
def test_failed_file_verification_does_not_assign_picture():
api = API()
api.stored = b'wrong file'
with pytest.raises(ValueError, match='verification'):
add_picture(api, Downloader(), product())
assert api.product['picture_file_name'] is None
def test_concurrent_picture_or_deleted_product_is_preserved():
api = API()
api.product['picture_file_name'] = 'user-picture.jpg'
assert add_picture(api, Downloader(), product()) == 'existing_picture'
api.product = {}
assert add_picture(api, Downloader(), product()) == 'deleted_product'
assert not api.writes
def test_rejects_non_images_and_external_urls():
with pytest.raises(ValueError):
image_type(b'<html>not an image</html>')
p = product()
p['description'] = p['description'].replace('www.ocado.com', 'example.com')
with pytest.raises(ValueError, match='Ocado image URL'):
add_picture(API(), Downloader(), p)
assert file_path('test.jpg') == '/files/productpictures/dGVzdC5qcGc%3D'