"""Shared fixtures for the whole suite (plan Step 6). Determinism here is a property of the interface, not of the harness. Tests get `frozen_today` and pass it to scripts as `--today`; nothing monkeypatches `datetime`. The difference matters: a script that only behaves deterministically because a test patched the clock is a script whose callers cannot make it behave deterministically at all, and `dagens` (build-brief 5.8) has to be reproducible from the command line. The autouse `fixtures_are_pristine` guard exists because the failure it catches does not announce itself. A test that writes into `tests/fixtures/` leaves every later run reading a corpus that no longer matches what it says it is, and the eventual failure surfaces in some unrelated test hours later. Catching it at the end of the offending test names the culprit. """ import os import shutil import pytest from helpers import golden as golden_helper from helpers import workspace as workspace_helper from jobbsok_lib import paths FIXTURES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "fixtures") #: Every date in the corpus is relative to this. 2026-09-15 is a Tuesday, so #: weekday-sensitive output does not accidentally land on a weekend. FROZEN_TODAY = workspace_helper.FROZEN_TODAY def pytest_addoption(parser): parser.addoption( "--update-golden", action="store_true", default=False, help="rewrite golden files instead of comparing against them", ) @pytest.fixture def fixtures_dir(): """Absolute path to the read-only fixture corpus.""" return FIXTURES_DIR @pytest.fixture def frozen_today(): """The date the suite reasons from, passed to scripts as ``--today``.""" return FROZEN_TODAY @pytest.fixture def empty_workspace(tmp_path): """A scaffolded but empty build-brief section 5 workspace.""" root = str(tmp_path / "workspace") paths.scaffold(root) return root @pytest.fixture def workspace(empty_workspace): """A workspace with the fixture corpus copied in, when there is one. The populated corpus arrives in plan Step 19; until then this is the scaffolded tree, so tests written against it now keep working when the corpus lands rather than being rewritten then. """ source = os.path.join(FIXTURES_DIR, "workspace") if os.path.isdir(source): shutil.copytree(source, empty_workspace, dirs_exist_ok=True) return empty_workspace @pytest.fixture def golden(request): """`assert_golden` with the ``--update-golden`` flag already bound.""" update = request.config.getoption("--update-golden") def compare(path, actual): return golden_helper.assert_golden(path, actual, update=update) return compare @pytest.fixture(autouse=True) def fixtures_are_pristine(request): """Fail the test that mutated the read-only corpus, at that test.""" if not os.path.isdir(FIXTURES_DIR): yield return if request.config.getoption("--update-golden"): # Golden regeneration is the one sanctioned write into the corpus. yield return before = workspace_helper.snapshot_tree(FIXTURES_DIR) yield workspace_helper.assert_tree_unchanged(FIXTURES_DIR, before)