Skip to content

Commit 383160d

Browse files
beaufourclaude
andcommitted
test: add integration tests that hit real Flickr API
- TestFindUserIntegration: test user lookup by username and URL - TestDownloadPhotoIntegration: test download, JSON metadata, skip existing - TestPrintSetsIntegration: test listing photosets Tests require ~/.flickr_download config with API credentials. Uses dynamic photo ID from test user's photostream. Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent 89db679 commit 383160d

File tree

1 file changed

+175
-0
lines changed

1 file changed

+175
-0
lines changed

tests/test_integration.py

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
"""Integration tests that hit the real Flickr API.
2+
3+
These tests require valid API credentials in ~/.flickr_download config file.
4+
They use a known public photoset for testing.
5+
"""
6+
7+
import json
8+
import os
9+
import tempfile
10+
from pathlib import Path
11+
12+
import pytest
13+
14+
from flickr_download.flick_download import (
15+
_init,
16+
_load_defaults,
17+
download_photo,
18+
find_user,
19+
print_sets,
20+
)
21+
from flickr_download.filename_handlers import get_filename_handler
22+
23+
24+
# Known public user for testing
25+
TEST_USER = "beaufour"
26+
27+
28+
@pytest.fixture(scope="module")
29+
def api_setup() -> bool:
30+
"""Set up API credentials from config file."""
31+
defaults = _load_defaults()
32+
if not defaults.get("api_key") or not defaults.get("api_secret"):
33+
pytest.skip("No API credentials found in ~/.flickr_download")
34+
35+
result = _init(defaults["api_key"], defaults["api_secret"], oauth=False)
36+
if not result:
37+
pytest.skip("Failed to initialize Flickr API")
38+
return True
39+
40+
41+
@pytest.fixture(scope="module")
42+
def test_photo_id(api_setup: bool) -> str:
43+
"""Get a real public photo ID from the test user's photostream."""
44+
user = find_user(TEST_USER)
45+
# Get the first photo from the user's public photos
46+
photos = user.getPhotos(per_page=1)
47+
if not photos:
48+
pytest.skip(f"No public photos found for user {TEST_USER}")
49+
return str(photos[0].id)
50+
51+
52+
class TestFindUserIntegration:
53+
"""Integration tests for user lookup."""
54+
55+
def test_find_user_by_username(self, api_setup: bool) -> None:
56+
"""Find a real user by username."""
57+
user = find_user(TEST_USER)
58+
assert user is not None
59+
assert user.username == TEST_USER
60+
61+
def test_find_user_by_url(self, api_setup: bool) -> None:
62+
"""Find a real user by Flickr URL."""
63+
user = find_user(f"https://www.flickr.com/photos/{TEST_USER}")
64+
assert user is not None
65+
assert user.username == TEST_USER
66+
67+
68+
class TestDownloadPhotoIntegration:
69+
"""Integration tests for single photo download."""
70+
71+
def test_download_single_photo(self, api_setup: bool, test_photo_id: str) -> None:
72+
"""Download a single photo and verify file is created."""
73+
with tempfile.TemporaryDirectory() as tmpdir:
74+
original_cwd = os.getcwd()
75+
os.chdir(tmpdir)
76+
try:
77+
get_filename = get_filename_handler("id")
78+
download_photo(
79+
test_photo_id,
80+
get_filename,
81+
size_label="Small", # Use small size for faster download
82+
skip_download=False,
83+
save_json=False,
84+
)
85+
86+
# Check that a file was created
87+
files = list(Path(".").glob("*"))
88+
assert len(files) == 1
89+
assert files[0].suffix in [".jpg", ".png", ".gif"]
90+
assert files[0].stat().st_size > 0
91+
finally:
92+
os.chdir(original_cwd)
93+
94+
def test_download_photo_with_json(self, api_setup: bool, test_photo_id: str) -> None:
95+
"""Download a photo with JSON metadata."""
96+
with tempfile.TemporaryDirectory() as tmpdir:
97+
original_cwd = os.getcwd()
98+
os.chdir(tmpdir)
99+
try:
100+
get_filename = get_filename_handler("id")
101+
download_photo(
102+
test_photo_id,
103+
get_filename,
104+
size_label="Small",
105+
skip_download=False,
106+
save_json=True,
107+
)
108+
109+
# Check that both photo and JSON were created
110+
photo_files = list(Path(".").glob("*.jpg")) + list(Path(".").glob("*.png"))
111+
json_files = list(Path(".").glob("*.json"))
112+
113+
assert len(photo_files) >= 1
114+
assert len(json_files) == 1
115+
116+
# Verify JSON contains expected fields
117+
with open(json_files[0]) as f:
118+
data = json.load(f)
119+
assert "id" in data
120+
assert "title" in data
121+
finally:
122+
os.chdir(original_cwd)
123+
124+
def test_download_photo_skip_existing(self, api_setup: bool, test_photo_id: str) -> None:
125+
"""Verify that existing photos are skipped."""
126+
with tempfile.TemporaryDirectory() as tmpdir:
127+
original_cwd = os.getcwd()
128+
os.chdir(tmpdir)
129+
try:
130+
get_filename = get_filename_handler("id")
131+
132+
# Download once
133+
download_photo(
134+
test_photo_id,
135+
get_filename,
136+
size_label="Small",
137+
skip_download=False,
138+
save_json=False,
139+
)
140+
141+
files = list(Path(".").glob("*"))
142+
assert len(files) == 1
143+
first_mtime = files[0].stat().st_mtime
144+
145+
# Download again - should skip
146+
download_photo(
147+
test_photo_id,
148+
get_filename,
149+
size_label="Small",
150+
skip_download=False,
151+
save_json=False,
152+
)
153+
154+
# File should not have been modified
155+
files = list(Path(".").glob("*"))
156+
assert len(files) == 1
157+
assert files[0].stat().st_mtime == first_mtime
158+
finally:
159+
os.chdir(original_cwd)
160+
161+
162+
class TestPrintSetsIntegration:
163+
"""Integration tests for listing photosets."""
164+
165+
def test_print_sets(self, api_setup: bool, capsys: pytest.CaptureFixture[str]) -> None:
166+
"""List photosets for a real user."""
167+
print_sets(TEST_USER)
168+
169+
captured = capsys.readouterr()
170+
# Should output at least one line with set ID and title
171+
assert captured.out.strip() != ""
172+
lines = captured.out.strip().split("\n")
173+
assert len(lines) >= 1
174+
# Each line should have format "id - title"
175+
assert " - " in lines[0]

0 commit comments

Comments
 (0)