Finance-Accounts/ar-aging-app/backend/tests/conftest.py

83 lines
3.3 KiB
Python

"""Shared test fixtures. Locates the Jan-2026 sample files (large; integration tests)."""
from __future__ import annotations
import os
import tempfile
from pathlib import Path
import pytest
# ---------------------------------------------------------------------------------------
# Redirect ALL test data away from production — BEFORE anything imports app.config, which
# reads these variables once at module load and caches them.
#
# The suite creates AND DELETES closings, so pointing it at the live database would destroy
# Finance's data. That already happened once under SQLite (75 test sessions accumulated in
# the production file), and the blast radius is larger now that the store is a shared MySQL
# server rather than a local file.
#
# `load_dotenv()` in app/config.py does not override variables already present in the
# environment, so setting MYSQL_DATABASE here wins over .env. The database is created
# automatically by database._ensure_database().
# ---------------------------------------------------------------------------------------
_TEST_DATA_DIR = Path(tempfile.mkdtemp(prefix="ar-aging-tests-"))
os.environ["AR_DATA_DIR"] = str(_TEST_DATA_DIR)
_PROD_DB = os.environ.get("MYSQL_DATABASE", "")
TEST_DB_NAME = os.environ.get("AR_TEST_MYSQL_DATABASE", "ar_aging_pytest")
os.environ["MYSQL_DATABASE"] = TEST_DB_NAME
# Default: the project root two levels above ar-aging-app/backend.
_DEFAULT_SAMPLE_DIR = Path(__file__).resolve().parents[3]
SAMPLE_DIR = Path(os.environ.get("AR_SAMPLE_DIR", str(_DEFAULT_SAMPLE_DIR)))
JAN_FILES = [
"USA Amazon Transactions 01 to 10 January,2026.xlsx",
"USA Amazon Transactions 11 to 20 January,2026.xlsx",
"USA Amazon Transactions 21 to 31 January,2026.xlsx",
]
SAMPLE_WORKBOOK = "Accounts Receivable Aging (Jan-26) 1.xlsx"
@pytest.fixture(scope="session")
def jan_files() -> list[str]:
paths = [str(SAMPLE_DIR / f) for f in JAN_FILES]
missing = [p for p in paths if not os.path.exists(p)]
if missing:
pytest.skip(f"Sample Jan-2026 files not found: {missing}")
return paths
@pytest.fixture(scope="session")
def sample_workbook() -> str:
p = str(SAMPLE_DIR / SAMPLE_WORKBOOK)
if not os.path.exists(p):
pytest.skip(f"Sample workbook not found: {p}")
return p
@pytest.fixture(autouse=True, scope="session")
def _never_touch_production_data():
"""
Hard stop if the redirect above ever fails.
The suite creates and deletes closings, so running against the live database would
destroy Finance's data. Assert the isolation actually took effect rather than trusting
it — this fixture is the reason a renamed config variable can't silently re-point the
tests at production.
"""
from app.config import DATA_DIR, MYSQL_DATABASE
assert MYSQL_DATABASE == TEST_DB_NAME, (
f"tests are pointed at MySQL database {MYSQL_DATABASE!r} — expected "
f"{TEST_DB_NAME!r}. app/config.py reads MYSQL_DATABASE; check that name."
)
assert not _PROD_DB or MYSQL_DATABASE != _PROD_DB, (
f"the test database is the same as the configured production database "
f"({_PROD_DB!r}). Set AR_TEST_MYSQL_DATABASE to a separate name."
)
assert str(DATA_DIR).startswith(str(_TEST_DATA_DIR)), (
f"tests would write uploads/exports to {DATA_DIR}, not a temp directory."
)
yield