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':'
Ocado product ID: 123
' + 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'not an image') 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'