import io
import json
from pathlib import Path
import subprocess
import sys
import os
import pytest
from PIL import Image
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from app import create_app
TOKEN = "t" * 48
AUTH = {"Authorization": "Bearer " + TOKEN}
@pytest.fixture
def service(tmp_path):
app = create_app(tmp_path / "data", TOKEN)
app.config["TESTING"] = True
return app, app.test_client(), tmp_path / "data"
def photo(color="red", format="JPEG", size=(40, 20), exif=None):
output = io.BytesIO()
Image.new("RGB", size, color).save(output, format, **({"exif": exif} if exif else {}))
return output.getvalue()
def upload(client, images=None, caption="", headers=AUTH):
return client.post("/api/photos", headers=headers, data={
"caption": caption,
"photos": [(io.BytesIO(raw), "../../escape.jpg") for raw in (images or [photo()])],
})
def test_authentication_and_request_limits(service):
app, client, data = service
assert upload(client, headers={}).status_code == 401
assert upload(client, headers={"Authorization": "Bearer wrong"}).status_code == 401
assert client.get("/api/photos/" + "a" * 64).status_code == 401
assert client.get("/healthz").status_code == 200
assert upload(client, caption="a" * 4001).status_code == 400
assert client.post("/api/photos", headers=AUTH).status_code == 400
assert upload(client, [photo()] * 21).status_code == 400
app.config["MAX_CONTENT_LENGTH"] = 100
assert upload(client).status_code == 413
assert not list((data / "submissions").iterdir())
def test_validation_is_all_or_nothing(service):
_, client, data = service
assert upload(client, [photo(), b"not an image"]).status_code == 400
assert upload(client, [photo(format="GIF")]).status_code == 400
assert not list((data / "submissions").iterdir())
assert not list((data / "temporary").iterdir())
def test_album_caption_order_and_retry_deduplication(service):
_, client, data = service
caption = ' {% include secret %} {{ site.email }}\nsecond line'
images = [photo("red"), photo("blue")]
response = upload(client, images, caption)
assert response.status_code == 202
job = response.json["id"]
folder = data / "submissions" / job
entry = (folder / "entry.md").read_text()
assert "