fix(dry-run) : garantir une simulation sans persistance #24

Merged
AntoineVe merged 4 commits from fix/dry-run-source-state into main 2026-09-11 12:00:40 +02:00
2 changed files with 43 additions and 0 deletions
Showing only changes of commit fde8fbe264 - Show all commits

View File

@@ -126,6 +126,8 @@ class PipelineRunner:
:rtype: PipelineRunner :rtype: PipelineRunner
""" """
effective_dry_run = settings.app.dry_run if dry_run is None else dry_run effective_dry_run = settings.app.dry_run if dry_run is None else dry_run
if effective_dry_run and settings.pronote.auth_mode == "qr_token":
raise ValueError("Le mode qr_token n'est pas compatible avec le dry-run.")
persistence_enabled = not effective_dry_run persistence_enabled = not effective_dry_run
theoretical_provider = get_theoretical_provider( theoretical_provider = get_theoretical_provider(
settings.app.theoretical_agenda_path, settings.app.theoretical_agenda_path,

View File

@@ -428,6 +428,47 @@ def test_from_settings_password_mode_passes_auth_state_none(
assert constructed[0][1] is None assert constructed[0][1] is None
def test_from_settings_rejects_qr_token_dry_run_before_constructing_pronote_client(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""QR-token dry-run fails before authentication or data dependencies are created."""
import pronote_sync.pipeline.run as run_module
qr_pin_sentinel = "qr-pin-must-not-appear"
constructed: list[object] = []
class FailingClient:
"""Pronote client sentinel that makes unexpected construction explicit."""
def __init__(self, settings: PronoteSettings, *, auth_state: object) -> None:
"""Record and reject any unexpected client construction.
:param settings: Pronote settings supplied by the composition root.
:param auth_state: Authentication state supplied by the composition root.
"""
del settings, auth_state
constructed.append(object())
raise AssertionError("PronoteClient must not be constructed for QR-token dry-run")
monkeypatch.setattr(run_module, "PronoteClient", FailingClient)
with pytest.raises(ValueError) as exc_info:
PipelineRunner.from_settings(
Settings(
app=AppSettings(dry_run=True),
pronote=PronoteSettings(
auth_mode="qr_token",
qr_pin=SecretStr(qr_pin_sentinel),
),
)
)
assert "qr_token" in str(exc_info.value)
assert "dry-run" in str(exc_info.value)
assert qr_pin_sentinel not in str(exc_info.value)
assert constructed == []
def test_from_settings_qr_token_mode_passes_auth_state_instance( def test_from_settings_qr_token_mode_passes_auth_state_instance(
monkeypatch: pytest.MonkeyPatch, monkeypatch: pytest.MonkeyPatch,
) -> None: ) -> None: