Files
school_compare/backend/tests/test_publication.py
T

68 lines
3.0 KiB
Python
Raw Normal View History

"""Publication must preserve the current dataset until every replacement is ready."""
import asyncio
import pandas as pd
import pytest
from fastapi.testclient import TestClient
from backend import app as api, data_loader
from backend.tests.test_sixth_form_flag import _schools_df
@pytest.fixture
def client(monkeypatch):
old = _schools_df()
monkeypatch.setattr(data_loader, '_df_cache', old)
monkeypatch.setattr(data_loader, '_df_latest_cache', old)
monkeypatch.setattr(api, '_place_registry', {'old': 'registry'})
monkeypatch.setattr(api, '_place_index', {'old': 'index'})
monkeypatch.setattr(api, '_place_index_source', api._place_registry)
monkeypatch.setattr(api, '_sitemaps', {'old.xml': 'old sitemap'})
monkeypatch.setattr(api, '_publication_lock', asyncio.Lock())
monkeypatch.setattr(api.limiter, 'enabled', False)
api.app.dependency_overrides[api.verify_admin_api_key] = lambda: True
yield TestClient(api.app, raise_server_exceptions=False)
api.app.dependency_overrides.clear()
def state():
return (data_loader._df_cache, data_loader._df_latest_cache, api._place_registry,
api._place_index, api._place_index_source, api._sitemaps)
@pytest.mark.parametrize('failure', ['empty', 'database', 'sitemap', 'duplicate'])
def test_failed_reload_preserves_every_published_object(client, monkeypatch, failure):
before = state()
df = _schools_df()
if failure == 'empty':
df = pd.DataFrame()
if failure == 'duplicate':
df = pd.concat([df, df.iloc[:1]], ignore_index=True)
def load():
if failure == 'database':
raise RuntimeError('database unavailable')
return df
monkeypatch.setattr(api, 'load_school_data_as_dataframe', load)
if failure == 'sitemap':
monkeypatch.setattr(api, 'build_sitemaps', lambda *args: (_ for _ in ()).throw(RuntimeError('bad XML')))
response = client.post('/api/admin/reload')
assert response.status_code == 503
assert all(a is b for a, b in zip(before, state()))
def test_success_publishes_school_data_places_and_sitemaps(client, monkeypatch):
df = _schools_df()
df.loc[0, 'school_name'] = 'Replacement School'
monkeypatch.setattr(api, 'load_school_data_as_dataframe', lambda: df)
response = client.post('/api/admin/reload')
assert response.status_code == 200
assert data_loader.load_school_data() is df
assert data_loader.load_latest_school_data().iloc[0].school_name == 'Replacement School'
assert api._place_index_source is api._place_registry
assert 'old.xml' not in api._sitemaps
assert 'replacement-school' in api._sitemaps['schools-1.xml']
def test_failed_sitemap_regeneration_keeps_existing_publication(client, monkeypatch):
before = state()
monkeypatch.setattr(api, 'build_sitemaps', lambda *args: (_ for _ in ()).throw(RuntimeError('bad XML')))
assert client.post('/api/admin/regenerate-sitemap').status_code == 503
assert all(a is b for a, b in zip(before, state()))