Spaces:
Running
Running
File size: 6,524 Bytes
690eb5c ee7e58b 690eb5c 27e940d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
"""
Tests for the image search module.
"""
from io import BytesIO
from typing import Any, Dict
import pytest
from slidedeckai.helpers import image_search
class _MockResponse:
"""A tiny response-like object to simulate `requests` responses."""
def __init__(
self,
*,
content: bytes = b'',
json_data: Any = None,
status_ok: bool = True
) -> None:
self.content = content
self._json = json_data
self._status_ok = status_ok
def raise_for_status(self) -> None:
"""Raise an exception when status is not OK."""
if not self._status_ok:
raise RuntimeError('status not ok')
def json(self) -> Any:
"""Return preconfigured JSON data."""
return self._json
def _dummy_requests_get_success_search(
url: str,
headers: Dict[str, str],
params: Dict[str, Any],
timeout: int
):
"""Return a successful mock response for search_pexels."""
# Validate that the function under test passes expected args
assert 'Authorization' in headers
assert 'User-Agent' in headers
assert 'query' in params
photos = [
{
'url': 'https://pexels.com/photo/1',
'src': {'large': 'https://images/1_large.jpg'}
},
{
'url': 'https://pexels.com/photo/2',
'src': {'original': 'https://images/2_original.jpg'}
},
{
'url': 'https://pexels.com/photo/3',
'src': {'large': 'https://images/3_large.jpg'}
}
]
return _MockResponse(json_data={'photos': photos})
def _dummy_requests_get_image(
url: str,
headers: Dict[str, str],
stream: bool, timeout: int
):
"""Return a mock image response for get_image_from_url."""
assert stream is True
assert 'Authorization' in headers
data = b'\x89PNG\r\n\x1a\n...'
return _MockResponse(content=data)
def test_extract_dimensions_with_params() -> None:
"""Extract_dimensions extracts width and height from URL query params."""
url = 'https://images.example.com/photo.jpg?w=800&h=600'
width, height = image_search.extract_dimensions(url)
assert isinstance(width, int)
assert isinstance(height, int)
assert (width, height) == (800, 600)
def test_extract_dimensions_missing_params() -> None:
"""When dimensions are missing the function returns (0, 0)."""
url = 'https://images.example.com/photo.jpg'
assert image_search.extract_dimensions(url) == (0, 0)
def test_get_photo_url_from_api_response_none() -> None:
"""Returns (None, None) when there are no photos in the response."""
result = image_search.get_photo_url_from_api_response({'not_photos': []})
assert result == (None, None)
def test_get_photo_url_from_api_response_selects_large_and_original(monkeypatch) -> None:
"""Ensure the function picks the expected photo and returns correct URLs.
This test patches random.choice to deterministically pick indices that exercise
the 'large' and 'original' branches.
"""
photos = [
{'url': 'https://pexels.com/photo/1', 'src': {'large': 'https://images/1_large.jpg'}},
{'url': 'https://pexels.com/photo/2', 'src': {'original': 'https://images/2_original.jpg'}},
{'url': 'https://pexels.com/photo/3', 'src': {'large': 'https://images/3_large.jpg'}},
]
# Ensure the Pexels API key is present so the helper will attempt to select
# and return photo URLs rather than early-returning (None, None).
monkeypatch.setenv('PEXEL_API_KEY', 'akey')
# Force selection of index 1 (second photo) which only has 'original'
monkeypatch.setattr(image_search.random, 'choice', lambda seq: 1)
photo_url, page_url = image_search.get_photo_url_from_api_response({'photos': photos})
assert page_url == 'https://pexels.com/photo/2'
assert photo_url == 'https://images/2_original.jpg'
# Force selection of index 0 which has 'large'
monkeypatch.setattr(image_search.random, 'choice', lambda seq: 0)
photo_url, page_url = image_search.get_photo_url_from_api_response({'photos': photos})
assert page_url == 'https://pexels.com/photo/1'
assert photo_url == 'https://images/1_large.jpg'
def test_get_image_from_url_success(monkeypatch) -> None:
"""get_image_from_url returns a BytesIO object with image content."""
monkeypatch.setattr(
'slidedeckai.helpers.image_search.requests.get',
lambda *a, **k: _dummy_requests_get_image(*a, **k)
)
monkeypatch.setenv('PEXEL_API_KEY', 'dummykey')
img = image_search.get_image_from_url('https://images/1_large.jpg')
assert isinstance(img, BytesIO)
data = img.getvalue()
assert data.startswith(b'\x89PNG')
def test_search_pexels_success(monkeypatch) -> None:
"""search_pexels forwards the request and returns parsed JSON."""
monkeypatch.setattr(
'slidedeckai.helpers.image_search.requests.get',
lambda *a, **k: _dummy_requests_get_success_search(*a, **k)
)
monkeypatch.setenv('PEXEL_API_KEY', 'akey')
result = image_search.search_pexels(query='people', size='medium', per_page=3)
assert isinstance(result, dict)
assert 'photos' in result
assert len(result['photos']) == 3
def test_search_pexels_raises_on_request_error(monkeypatch) -> None:
"""When requests.get raises an exception, it should propagate from search_pexels."""
def _raise(*a, **k):
raise RuntimeError('network')
monkeypatch.setattr('slidedeckai.helpers.image_search.requests.get', _raise)
monkeypatch.setenv('PEXEL_API_KEY', 'akey')
with pytest.raises(RuntimeError):
image_search.search_pexels(query='x')
def test_search_pexels_returns_empty_when_no_api_key(monkeypatch) -> None:
"""When PEXEL_API_KEY is not set, search_pexels should return an empty dict."""
monkeypatch.delenv('PEXEL_API_KEY', raising=False)
result = image_search.search_pexels(query='people')
assert result == {}
def test_get_photo_url_from_api_response_returns_none_when_no_api_key(monkeypatch) -> None:
"""When PEXEL_API_KEY is not set, get_photo_url_from_api_response should return (None, None)."""
photos = [
{'url': 'https://pexels.com/photo/1', 'src': {'large': 'https://images/1_large.jpg'}}
]
monkeypatch.delenv('PEXEL_API_KEY', raising=False)
result = image_search.get_photo_url_from_api_response({'photos': photos})
assert result == (None, None)
|