Skip to content

Commit cd6aecb

Browse files
committed
feat: add tests for ConstraintType
1 parent 114072a commit cd6aecb

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed

tests/unit/experimental/components/test_schema.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,48 @@ def test_schema_additional_parameter_validation() -> None:
225225
GraphSchema.model_validate(schema_dict)
226226

227227

228+
def test_schema_constraint_validation_property_not_in_node_type() -> None:
229+
schema_dict: dict[str, Any] = {
230+
"node_types": [
231+
{
232+
"label": "Person",
233+
"properties": [{"name": "name", "type": "STRING"}],
234+
}
235+
],
236+
"constraints": [
237+
{"type": "UNIQUENESS", "node_type": "Person", "property_name": "email"}
238+
]
239+
}
240+
241+
with pytest.raises(SchemaValidationError) as exc_info:
242+
GraphSchema.model_validate(schema_dict)
243+
244+
assert "Constraint references undefined property" in str(exc_info.value)
245+
assert "on node type 'Person'" in str(exc_info.value)
246+
247+
248+
def test_schema_constraint_with_additional_properties_allows_unknown_property() -> None:
249+
# if additional_properties is True, we can define constraints that are not in the node_type
250+
schema_dict: dict[str, Any] = {
251+
"node_types": [
252+
{
253+
"label": "Person",
254+
"properties": [{"name": "name", "type": "STRING"}],
255+
"additional_properties": True,
256+
}
257+
],
258+
"constraints": [
259+
{"type": "UNIQUENESS", "node_type": "Person", "property_name": "email"}
260+
],
261+
}
262+
263+
# Should NOT raise - email is allowed because additional_properties=True
264+
schema = GraphSchema.model_validate(schema_dict)
265+
266+
assert len(schema.constraints) == 1
267+
assert schema.constraints[0].property_name == "email"
268+
269+
228270
def test_schema_with_valid_constraints() -> None:
229271
schema_dict: dict[str, Any] = {
230272
"node_types": [
@@ -1100,6 +1142,28 @@ def schema_json_with_relationships_without_labels() -> str:
11001142
"""
11011143

11021144

1145+
@pytest.fixture
1146+
def schema_json_with_nonexistent_property_constraint() -> str:
1147+
return """
1148+
{
1149+
"node_types": [
1150+
{
1151+
"label": "Person",
1152+
"properties": [
1153+
{"name": "name", "type": "STRING"}
1154+
]
1155+
}
1156+
],
1157+
"relationship_types": [],
1158+
"patterns": [],
1159+
"constraints": [
1160+
{"type": "UNIQUENESS", "node_type": "Person", "property_name": "name"},
1161+
{"type": "UNIQUENESS", "node_type": "Person", "property_name": "nonexistent_property"}
1162+
]
1163+
}
1164+
"""
1165+
1166+
11031167
@pytest.mark.asyncio
11041168
async def test_schema_from_text_filters_invalid_node_patterns(
11051169
schema_from_text: SchemaFromTextExtractor,
@@ -1237,6 +1301,26 @@ async def test_schema_from_text_filters_invalid_constraints(
12371301
assert schema.constraints[0].property_name == "name"
12381302

12391303

1304+
@pytest.mark.asyncio
1305+
async def test_schema_from_text_filters_constraint_with_nonexistent_property(
1306+
schema_from_text: SchemaFromTextExtractor,
1307+
mock_llm: AsyncMock,
1308+
schema_json_with_nonexistent_property_constraint: str,
1309+
) -> None:
1310+
# configure the mock LLM to return schema with constraint on nonexistent property
1311+
mock_llm.ainvoke.return_value = LLMResponse(
1312+
content=schema_json_with_nonexistent_property_constraint
1313+
)
1314+
1315+
# run the schema extraction
1316+
schema = await schema_from_text.run(text="Sample text for extraction")
1317+
1318+
# verify that only the valid constraint (with "name" property) remains
1319+
# the constraint with "nonexistent_property" should be filtered out
1320+
assert len(schema.constraints) == 1
1321+
assert schema.constraints[0].property_name == "name"
1322+
1323+
12401324
@pytest.mark.asyncio
12411325
async def test_schema_from_text_handles_null_constraints(
12421326
schema_from_text: SchemaFromTextExtractor,

0 commit comments

Comments
 (0)