# SPDX-License-Identifier: AGPL-3.0-or-later
#
# Cata-Log - the central hub for digital flyers
# Copyright (C) 2026 David Aderbauer & The Cata-Log Contributors
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from urllib.parse import urljoin
import pytest
from httpx import Client
from cata_log_hub.api import common
from cata_log_hub.api.v1 import models
[docs]
@pytest.mark.parametrize(
"order",
[item.value for item in models.PageOrderChoices],
)
def test_list_pages(full_database, fake_page, client, order):
response = client.get("/api/v1/pages", params={"order": order})
assert response.status_code == 200
data = response.json()
assert "results" in data
assert len(data["results"]) == 1
assert data["results"][0]
assert data["results"][0]["id"] == fake_page.id
assert data["results"][0]["catalog_id"] == fake_page.catalog_id
assert data["results"][0]["number"] == fake_page.number
[docs]
def test_list_pages__noauth(full_database, noauth_client):
response = noauth_client.get("/api/v1/pages")
assert response.status_code == 401
common.HTTPStatusError.model_validate(response.json())
assert "WWW-Authenticate" in response.headers
assert response.headers["WWW-Authenticate"] == "Basic"
[docs]
def test_list_pages__bad_auth(full_database, bad_auth_client):
response = bad_auth_client.get("/api/v1/pages")
assert response.status_code == 401
common.HTTPStatusError.model_validate(response.json())
assert "WWW-Authenticate" in response.headers
assert response.headers["WWW-Authenticate"] == "Basic"
[docs]
def test_list_pages__noauth__public_get(
full_database, fake_page, noauth_client, public_get
):
response = noauth_client.get("/api/v1/pages")
assert response.status_code == 200
data = response.json()
assert "results" in data
assert len(data["results"]) == 1
assert data["results"][0]
assert data["results"][0]["id"] == fake_page.id
assert data["results"][0]["catalog_id"] == fake_page.catalog_id
assert data["results"][0]["number"] == fake_page.number
[docs]
def test_get_page(fake_page, client):
response = client.get(f"/api/v1/pages/{fake_page.id}")
assert response.status_code == 200
data = response.json()
assert data["id"] == fake_page.id
[docs]
def test_get_page__noauth(fake_page, noauth_client):
response = noauth_client.get(f"/api/v1/pages/{fake_page.id}")
assert response.status_code == 401
common.HTTPStatusError.model_validate(response.json())
assert "WWW-Authenticate" in response.headers
assert response.headers["WWW-Authenticate"] == "Basic"
[docs]
def test_get_page__bad_auth(fake_page, bad_auth_client):
response = bad_auth_client.get(f"/api/v1/pages/{fake_page.id}")
assert response.status_code == 401
common.HTTPStatusError.model_validate(response.json())
assert "WWW-Authenticate" in response.headers
assert response.headers["WWW-Authenticate"] == "Basic"
[docs]
def test_get_page__noauth__public_get(fake_page, noauth_client, public_get):
response = noauth_client.get(f"/api/v1/pages/{fake_page.id}")
assert response.status_code == 200
data = response.json()
assert data["id"] == fake_page.id
[docs]
def test_get_page__not_found(client):
response = client.get("/api/v1/pages/456")
assert response.status_code == 404
common.HTTPStatusError.model_validate(response.json())
assert response.json() == {"detail": "Page not found"}
[docs]
@pytest.mark.parametrize(("filename"), [None, "page_image.png"])
def test_download_page(fake_page, fake_file, client, filename):
response = client.get(
urljoin(
f"/api/v1/pages/{fake_page.id}/download",
f"?filename={filename}" if filename else "",
)
)
assert response.status_code == 200
assert response.content == fake_file.read_bytes()
assert "content-disposition" in response.headers
assert (
response.headers["content-disposition"]
== f'attachment; filename="{filename or fake_file.name}"'
)
[docs]
def test_download_page__noauth(fake_page, noauth_client):
response = noauth_client.get(f"/api/v1/pages/{fake_page.id}/download")
assert response.status_code == 401
common.HTTPStatusError.model_validate(response.json())
assert "WWW-Authenticate" in response.headers
assert response.headers["WWW-Authenticate"] == "Basic"
[docs]
def test_download_page__bad_auth(fake_page, bad_auth_client):
response = bad_auth_client.get(f"/api/v1/pages/{fake_page.id}/download")
assert response.status_code == 401
common.HTTPStatusError.model_validate(response.json())
assert "WWW-Authenticate" in response.headers
assert response.headers["WWW-Authenticate"] == "Basic"
[docs]
def test_download_page__noauth__public_get(
fake_page, fake_file, noauth_client, public_get
):
response = noauth_client.get(
f"/api/v1/pages/{fake_page.id}/download",
)
assert response.status_code == 200
assert response.content == fake_file.read_bytes()
assert "content-disposition" in response.headers
assert (
response.headers["content-disposition"]
== f'attachment; filename="{fake_file.name}"'
)
[docs]
def test_download_page__not_found(client):
response = client.get("/api/v1/pages/456/download")
assert response.status_code == 404
common.HTTPStatusError.model_validate(response.json())
assert response.json() == {"detail": "Page not found"}
@pytest.mark.parametrize(("filename"), [None, "page_image.png"])
def test_embed_page(fake_page, fake_file, client, filename):
response = client.get(
urljoin(
f"/api/v1/pages/{fake_page.id}/embed",
f"?filename={filename}" if filename else "",
)
)
assert response.status_code == 200
assert response.content == fake_file.read_bytes()
assert "content-disposition" in response.headers
assert (
response.headers["content-disposition"]
== f'inline; filename="{filename or fake_file.name}"'
)
[docs]
def test_embed_page__noauth(fake_page, noauth_client):
response = noauth_client.get(f"/api/v1/pages/{fake_page.id}/embed")
assert response.status_code == 401
common.HTTPStatusError.model_validate(response.json())
assert "WWW-Authenticate" in response.headers
assert response.headers["WWW-Authenticate"] == "Basic"
[docs]
def test_embed_page__bad_auth(fake_page, bad_auth_client):
response = bad_auth_client.get(f"/api/v1/pages/{fake_page.id}/embed")
assert response.status_code == 401
common.HTTPStatusError.model_validate(response.json())
assert "WWW-Authenticate" in response.headers
assert response.headers["WWW-Authenticate"] == "Basic"
[docs]
def test_embed_page(fake_page, fake_file, noauth_client, public_get):
response = noauth_client.get(
f"/api/v1/pages/{fake_page.id}/embed",
)
assert response.status_code == 200
assert response.content == fake_file.read_bytes()
assert "content-disposition" in response.headers
assert (
response.headers["content-disposition"]
== f'inline; filename="{fake_file.name}"'
)
[docs]
def test_embed_page__not_found(client):
response = client.get("/api/v1/pages/456/embed")
assert response.status_code == 404
common.HTTPStatusError.model_validate(response.json())
assert response.json() == {"detail": "Page not found"}