73 lines
2.2 KiB
Python
73 lines
2.2 KiB
Python
"""models.py — compact result shapes (plan §6: ids, titles, quantities, statuses)."""
|
|
|
|
import pytest
|
|
from pydantic import ValidationError
|
|
|
|
from mcp_server.models import (
|
|
AllocationPolicy,
|
|
CompleteStepResult,
|
|
Consumable,
|
|
HandoffContext,
|
|
NextStep,
|
|
ProtocolAnnotation,
|
|
StepInfo,
|
|
)
|
|
|
|
|
|
def test_consumable_defaults_to_fifo_and_required():
|
|
consumable = Consumable(resource_key="ethanol_absolute", quantity=2.0, unit="mL")
|
|
assert consumable.allocation is AllocationPolicy.FIFO
|
|
assert consumable.optional is False
|
|
assert consumable.container_id is None
|
|
|
|
|
|
def test_consumable_quantity_may_be_null_for_prompted_steps():
|
|
consumable = Consumable(resource_key="x", quantity=None, unit="mL")
|
|
assert consumable.quantity is None
|
|
|
|
|
|
def test_consumable_rejects_missing_required_fields():
|
|
with pytest.raises(ValidationError):
|
|
Consumable(resource_key="x") # quantity and unit missing
|
|
|
|
|
|
def test_annotation_defaults():
|
|
annotation = ProtocolAnnotation()
|
|
assert annotation.consumables == []
|
|
assert annotation.prompt_quantity is False
|
|
|
|
|
|
def test_step_info_defaults_unfinished():
|
|
step = StepInfo(id=9, body="Add ethanol")
|
|
assert step.finished is False
|
|
assert step.position is None
|
|
|
|
|
|
def test_complete_step_result_status_is_restricted():
|
|
for status in ("completed", "protocol_complete", "reverted", "partial_failure"):
|
|
CompleteStepResult(
|
|
experiment_id=123,
|
|
status=status,
|
|
step=StepInfo(id=9, body="b"),
|
|
)
|
|
with pytest.raises(ValidationError):
|
|
CompleteStepResult(
|
|
experiment_id=123,
|
|
status="exploded",
|
|
step=StepInfo(id=9, body="b"),
|
|
)
|
|
|
|
|
|
def test_next_step_carries_consumables_and_stock():
|
|
next_step = NextStep(experiment_id=123, step=StepInfo(id=9, body="Add ethanol"))
|
|
assert next_step.consumables == []
|
|
assert next_step.stock == []
|
|
|
|
|
|
def test_handoff_context_is_id_only_and_rest_optional():
|
|
"""Plan §8: the app forwards only ids; device/location are optional extras."""
|
|
handoff = HandoffContext(experiment_id=123, user_id=2)
|
|
assert handoff.step_id is None
|
|
assert handoff.device_id is None
|
|
assert handoff.location_id is None
|