import json from io import BytesIO from zipfile import ZipFile import pytest from django.test import Client from django.urls import reverse pytestmark = pytest.mark.django_db(transaction=True) def test_export_index_explains_the_portable_package(client): response = client.get(reverse("export-index")) assert response.status_code == 200 body = response.content.decode() assert "Export financial data" in body assert "accounts" in body assert "transactions" in body assert "source records" in body assert "ZIP" in body assert f'action="{reverse("export-download")}"' in body def test_export_download_posts_an_in_memory_versioned_zip(client, settings, tmp_path): settings.EXPORT_ROOT = tmp_path response = client.post( reverse("export-download"), {"output": "../../outside.zip", "path": str(tmp_path / "chosen.zip")}, ) assert response.status_code == 200 assert response["Content-Type"] == "application/zip" assert response["Content-Disposition"].startswith( 'attachment; filename="gizmoduck-export-' ) assert response["Content-Disposition"].endswith('.zip"') with ZipFile(BytesIO(response.content)) as package: manifest = json.loads(package.read("manifest.json")) assert manifest["format"] == "gizmoduck-export" assert manifest["version"] == 1 assert list(tmp_path.iterdir()) == [] def test_export_download_requires_post(client): assert client.get(reverse("export-download")).status_code == 405 def test_export_download_requires_csrf(): guarded = Client(enforce_csrf_checks=True) response = guarded.post(reverse("export-download")) assert response.status_code == 403 def test_exports_are_linked_from_other_pages(client): response = client.get(reverse("transaction-list")) assert response.status_code == 200 assert f'href="{reverse("export-index")}">Exports' in response.content.decode()