"""Shared test helpers — FakeAbacusClient, make_gql_input.""" from schemas import ( AbacusContract, AbacusContractInput, AbacusContractLifecycleInput, AbacusContractLifecycleScheduleInput, AbacusContractWithLifecyclesInput, ContractType, GraphQLResult, PeriodType, ProcessingStatus, RenewalType, RunControllerContract, ) class FakeAbacusClient: """Test double for AbacusClient with per-method error injection. Set ``fail_create`` to return a generic error from create. Set ``create_error`` to an Exception to raise from create. Set ``fail_get_entities`` to return an empty entity list. Set ``attach_error`` to an Exception to raise from attach. """ def __init__( self, contract_id: int = 42, fail_create: bool = False, create_error: Exception | None = None, fail_get_entities: bool = False, attach_error: Exception | None = None, signing_entities: list | None = None, run_controllers: list | None = None, ): self._contract_id = contract_id self._fail_create = fail_create self._create_error = create_error self._fail_get_entities = fail_get_entities self._attach_error = attach_error self._signing_entities = signing_entities or [] self._run_controllers = run_controllers or [] self.created: list[AbacusContractWithLifecyclesInput] = [] self.attached: list[tuple[int, int]] = [] def get_reference_signing_entities(self) -> list: if self._fail_get_entities: return [] return self._signing_entities def get_run_controllers(self) -> list: return self._run_controllers def create_contract_with_lifecycles( self, gql_input: AbacusContractWithLifecyclesInput, ) -> GraphQLResult[AbacusContract]: self.created.append(gql_input) if self._create_error is not None: raise self._create_error if self._fail_create: return GraphQLResult( status=ProcessingStatus.ERROR, error='mock error', ) return GraphQLResult( status=ProcessingStatus.SUCCESS, data=AbacusContract( contract_id=self._contract_id, contract_name=gql_input.contract.contract_name, contract_type=gql_input.contract.contract_type, ), ) def attach_run_controller( self, contract_id: int, run_controller_id: int ) -> RunControllerContract: if self._attach_error is not None: raise self._attach_error self.attached.append((contract_id, run_controller_id)) return RunControllerContract( contract_id=contract_id, run_controller_contract_id=1, run_controller_id=run_controller_id, ) def make_gql_input( name: str = 'Test Contract', ) -> AbacusContractWithLifecyclesInput: """Build a minimal valid AbacusContractWithLifecyclesInput for testing.""" lifecycle = AbacusContractLifecycleInput( lifecycle_term_start='2026-01-01', ) return AbacusContractWithLifecyclesInput( contract=AbacusContractInput( account_id=1, contract_name=name, contract_type=ContractType.DISTRIBUTION, ), lifecycle=lifecycle, lifecycle_schedules=[ AbacusContractLifecycleScheduleInput( renewal_type=RenewalType.CONTINUOUSLY_ACTIVE, termination_notice_detail_interval=30, termination_notice_detail_type=PeriodType.DAY, contract_lifecycle=lifecycle, ) ], )