diff --git a/api/tests/opentrons/protocol_api_integration/test_trashes.py b/api/tests/opentrons/protocol_api_integration/test_trashes.py index b8436f6ce74..700e7b66b5b 100644 --- a/api/tests/opentrons/protocol_api_integration/test_trashes.py +++ b/api/tests/opentrons/protocol_api_integration/test_trashes.py @@ -3,7 +3,8 @@ from opentrons import protocol_api, simulate -from typing import Optional, Type +import contextlib +from typing import ContextManager, Optional, Type from typing_extensions import Literal import pytest @@ -93,3 +94,70 @@ def test_trash_search() -> None: # You should be able to override instrument.trash_container explicitly. instrument.trash_container = loaded_second assert instrument.trash_container is loaded_second + + +@pytest.mark.parametrize( + ("version", "robot_type", "expect_load_to_succeed"), + [ + pytest.param( + "2.13", + "OT-2", + False, + # This xfail (the system does let you load a labware onto slot 12, and does not raise) + # is surprising to me. It may be be a bug in old PAPI versions. + marks=pytest.mark.xfail(strict=True, raises=pytest.fail.Exception), + ), + ("2.14", "OT-2", False), + ("2.15", "OT-2", False), + pytest.param( + "2.15", + "Flex", + False, + marks=pytest.mark.ot3_only, # Simulating a Flex protocol requires a Flex hardware API. + ), + pytest.param( + "2.16", + "OT-2", + False, + # This should ideally raise, matching OT-2 behavior on prior Protocol API versions. + # It currently does not because Protocol API v2.15's trashes are implemented as + # addressable areas, not labware--and they're only brought into existence + # *on first use,* not at the beginning of a protocol. + # + # The good news is that even though the conflicting load will not raise like we want, + # something in the protocol will eventually raise, e.g. when a pipette goes to drop a + # tip in the fixed trash and finds that a fixed trash can't exist there because there's + # a labware. + marks=pytest.mark.xfail(strict=True, raises=pytest.fail.Exception), + ), + pytest.param( + "2.16", + "Flex", + True, + marks=pytest.mark.ot3_only, # Simulating a Flex protocol requires a Flex hardware API. + ), + ], +) +def test_fixed_trash_load_conflicts( + robot_type: Literal["Flex", "OT-2"], + version: str, + expect_load_to_succeed: bool, +) -> None: + """Test loading something onto the location historically used for the fixed trash. + + In configurations where there is a fixed trash, this should be disallowed. + In configurations without a fixed trash, this should be allowed. + """ + protocol = simulate.get_protocol_api(version=version, robot_type=robot_type) + + if expect_load_to_succeed: + expected_error: ContextManager[object] = contextlib.nullcontext() + else: + expected_error = pytest.raises( + Exception, + # Exact message doesn't matter, as long as it's definitely a labware load conflict. + match="LocationIsOccupiedError", + ) + + with expected_error: + protocol.load_labware("opentrons_96_wellplate_200ul_pcr_full_skirt", 12)