Skip to main content
Glama
test_restriction_workflows.py10.8 kB
"""Integration tests for restriction workflows.""" import pytest from ids_mcp_server.tools.document import create_ids, export_ids from ids_mcp_server.tools.specification import add_specification from ids_mcp_server.tools.facets import add_entity_facet, add_property_facet, add_attribute_facet from ids_mcp_server.tools.restrictions import ( add_enumeration_restriction, add_pattern_restriction, add_bounds_restriction, add_length_restriction ) from ids_mcp_server.session.storage import get_session_storage from ifctester import ids @pytest.mark.asyncio async def test_fire_safety_specification_workflow(mock_context): """ Integration test: Fire safety wall specification with multiple restrictions. Scenario: Define requirements for fire-rated walls - Walls must be IFCWALL entities - FireRating must be REI30, REI60, or REI90 (enumeration) - Tag must match pattern EW-[0-9]{3} - Height must be between 2.4m and 3.5m (bounds) - Description must be 10-200 characters (length) """ # Create IDS document await create_ids( title="Fire Safety Wall Requirements", ctx=mock_context, description="Requirements for fire-rated walls in commercial buildings" ) # Add specification await add_specification( name="Fire-rated External Walls", ifc_versions=["IFC4"], ctx=mock_context, identifier="FS-EW-001", description="External walls with fire rating requirements" ) # Applicability: All walls await add_entity_facet( spec_id="FS-EW-001", location="applicability", entity_name="IFCWALL", ctx=mock_context ) # Requirement 1: FireRating property with enumeration restriction await add_property_facet( spec_id="FS-EW-001", location="requirements", property_name="FireRating", property_set="Pset_WallCommon", ctx=mock_context ) await add_enumeration_restriction( spec_id="FS-EW-001", facet_index=0, # First requirement parameter_name="value", base_type="xs:string", values=["REI30", "REI60", "REI90"], ctx=mock_context, location="requirements" ) # Requirement 2: Tag attribute with pattern restriction await add_attribute_facet( spec_id="FS-EW-001", location="requirements", attribute_name="Tag", ctx=mock_context ) await add_pattern_restriction( spec_id="FS-EW-001", facet_index=1, # Second requirement parameter_name="value", base_type="xs:string", pattern="EW-[0-9]{3}", ctx=mock_context, location="requirements" ) # Requirement 3: Height property with bounds restriction await add_property_facet( spec_id="FS-EW-001", location="requirements", property_name="Height", property_set="Pset_WallCommon", data_type="IFCREAL", ctx=mock_context ) await add_bounds_restriction( spec_id="FS-EW-001", facet_index=2, # Third requirement parameter_name="value", base_type="xs:double", min_inclusive=2.4, max_inclusive=3.5, ctx=mock_context, location="requirements" ) # Requirement 4: Description attribute with length restriction await add_attribute_facet( spec_id="FS-EW-001", location="requirements", attribute_name="Description", ctx=mock_context ) await add_length_restriction( spec_id="FS-EW-001", facet_index=3, # Fourth requirement parameter_name="value", base_type="xs:string", min_length=10, max_length=200, ctx=mock_context, location="requirements" ) # Verify IfcTester object structure storage = get_session_storage() session_data = storage.get(mock_context.session_id) ids_obj = session_data.ids_obj assert len(ids_obj.specifications) == 1 spec = ids_obj.specifications[0] # Verify specification assert spec.name == "Fire-rated External Walls" assert len(spec.applicability) == 1 assert len(spec.requirements) == 4 # Verify enumeration restriction (FireRating) fire_rating = spec.requirements[0] assert isinstance(fire_rating, ids.Property) # IfcTester may store baseName as string or object base_name = fire_rating.baseName if isinstance(fire_rating.baseName, str) else fire_rating.baseName.simpleValue assert base_name == "FireRating" assert isinstance(fire_rating.value, ids.Restriction) assert fire_rating.value.base == "string" # IfcTester normalizes # Verify pattern restriction (Tag) tag = spec.requirements[1] assert isinstance(tag, ids.Attribute) tag_name = tag.name if isinstance(tag.name, str) else tag.name.simpleValue assert tag_name == "Tag" assert isinstance(tag.value, ids.Restriction) # Verify bounds restriction (Height) height = spec.requirements[2] assert isinstance(height, ids.Property) height_name = height.baseName if isinstance(height.baseName, str) else height.baseName.simpleValue assert height_name == "Height" assert isinstance(height.value, ids.Restriction) assert height.value.base == "double" # Verify length restriction (Description) description = spec.requirements[3] assert isinstance(description, ids.Attribute) desc_name = description.name if isinstance(description.name, str) else description.name.simpleValue assert desc_name == "Description" assert isinstance(description.value, ids.Restriction) # Export to XML result = await export_ids(ctx=mock_context, validate=False) # Verify XML contains all restrictions xml = result["xml"] assert "<xs:enumeration" in xml assert 'value="REI30"' in xml assert 'value="REI60"' in xml assert 'value="REI90"' in xml assert "<xs:pattern" in xml assert 'value="EW-[0-9]{3}"' in xml assert "<xs:minInclusive" in xml or 'value="2.4"' in xml assert "<xs:maxInclusive" in xml or 'value="3.5"' in xml assert "<xs:minLength" in xml or 'value="10"' in xml assert "<xs:maxLength" in xml or 'value="200"' in xml # Verify IDS structure assert '<title>Fire Safety Wall Requirements</title>' in xml assert 'name="Fire-rated External Walls"' in xml @pytest.mark.asyncio async def test_multiple_specifications_with_restrictions(mock_context): """ Integration test: Multiple specifications, each with different restrictions. Demonstrates managing complex IDS documents with multiple specs. """ # Create IDS await create_ids(title="Building Standards", ctx=mock_context) # Specification 1: Wall heights await add_specification( name="Wall Heights", ifc_versions=["IFC4"], ctx=mock_context, identifier="S1" ) await add_entity_facet( spec_id="S1", location="applicability", entity_name="IFCWALL", ctx=mock_context ) await add_property_facet( spec_id="S1", location="requirements", property_name="Height", property_set="Pset_WallCommon", # Required for valid IDS ctx=mock_context ) await add_bounds_restriction( spec_id="S1", facet_index=0, parameter_name="value", base_type="xs:double", min_inclusive=2.0, max_inclusive=4.0, ctx=mock_context, location="requirements" ) # Specification 2: Door sizes await add_specification( name="Door Sizes", ifc_versions=["IFC4"], ctx=mock_context, identifier="S2" ) await add_entity_facet( spec_id="S2", location="applicability", entity_name="IFCDOOR", ctx=mock_context ) await add_property_facet( spec_id="S2", location="requirements", property_name="Width", property_set="Pset_DoorCommon", # Required for valid IDS ctx=mock_context ) await add_enumeration_restriction( spec_id="S2", facet_index=0, parameter_name="value", base_type="xs:double", values=["0.8", "0.9", "1.0"], ctx=mock_context, location="requirements" ) # Verify storage = get_session_storage() ids_obj = storage.get(mock_context.session_id).ids_obj assert len(ids_obj.specifications) == 2 # Verify S1 s1 = ids_obj.specifications[0] assert s1.name == "Wall Heights" assert len(s1.requirements) == 1 assert isinstance(s1.requirements[0].value, ids.Restriction) # Verify S2 s2 = ids_obj.specifications[1] assert s2.name == "Door Sizes" assert len(s2.requirements) == 1 assert isinstance(s2.requirements[0].value, ids.Restriction) # Export result = await export_ids(ctx=mock_context, validate=False) assert result["status"] == "exported" assert "Wall Heights" in result["xml"] assert "Door Sizes" in result["xml"] @pytest.mark.asyncio async def test_restriction_on_different_parameters(mock_context): """ Integration test: Apply restrictions to different facet parameters. Demonstrates that restrictions can be applied to various parameters, not just 'value'. """ await create_ids(title="Advanced Restrictions", ctx=mock_context) await add_specification( name="Property Set Patterns", ifc_versions=["IFC4"], ctx=mock_context, identifier="ADV1" ) await add_entity_facet( spec_id="ADV1", location="applicability", entity_name="IFCWALL", ctx=mock_context ) # Add property with pattern restriction on propertySet parameter await add_property_facet( spec_id="ADV1", location="requirements", property_name=".*", # Any property name ctx=mock_context, property_set="Pset_Common" ) await add_pattern_restriction( spec_id="ADV1", facet_index=0, parameter_name="propertySet", # Restrict the property set name, not value base_type="xs:string", pattern="Pset_.*", # Only allow standard property sets ctx=mock_context, location="requirements" ) # Verify restriction applied to propertySet parameter storage = get_session_storage() spec = storage.get(mock_context.session_id).ids_obj.specifications[0] prop = spec.requirements[0] assert isinstance(prop.propertySet, ids.Restriction) assert prop.propertySet.base == "string" # Verify baseName is still a simple value (not restricted) assert hasattr(prop.baseName, "simpleValue") or isinstance(prop.baseName, str)

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/vinnividivicci/ifc-ids-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server