forked from HAL9000/cleveragents-core
149 lines
4.9 KiB
Python
149 lines
4.9 KiB
Python
"""Behave steps for UKO Layer 2 TTL validation and additional coverage.
|
|
|
|
Covers Turtle file loading, ParadigmVocabulary frozen-model checks,
|
|
and miscellaneous validation edge-cases.
|
|
|
|
All step definitions use the ``for uko_l2`` suffix to avoid
|
|
AmbiguousStep collisions with other feature files.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
from _uko_l2_test_helpers import capture_error
|
|
from behave import then, when
|
|
from behave.runner import Context
|
|
from pydantic import ValidationError
|
|
|
|
from cleveragents.acms.uko.vocabularies import (
|
|
ParadigmVocabulary,
|
|
VocabularyProperty,
|
|
get_oo_vocabulary,
|
|
)
|
|
from cleveragents.application.services.uko_loader import UKOLoader
|
|
|
|
_TTL_PATH = Path(__file__).resolve().parents[2] / "docs" / "ontology" / "uko.ttl"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Turtle validation
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@when("I load the UKO TTL file for uko_l2")
|
|
def step_load_ttl(ctx: Context) -> None:
|
|
loader = UKOLoader()
|
|
ctx.ontology = loader.load(_TTL_PATH)
|
|
|
|
|
|
@then("the ontology should load without errors for uko_l2")
|
|
def step_check_ontology_loaded(ctx: Context) -> None:
|
|
assert ctx.ontology is not None
|
|
assert len(ctx.ontology.nodes) > 0
|
|
|
|
|
|
@then("the ontology should contain uko-func prefix for uko_l2")
|
|
def step_check_func_prefix(ctx: Context) -> None:
|
|
prefixes = {p.prefix for p in ctx.ontology.prefixes}
|
|
assert "uko-func" in prefixes, f"uko-func not in {prefixes}"
|
|
|
|
|
|
@then("the ontology should contain uko-proc prefix for uko_l2")
|
|
def step_check_proc_prefix(ctx: Context) -> None:
|
|
prefixes = {p.prefix for p in ctx.ontology.prefixes}
|
|
assert "uko-proc" in prefixes, f"uko-proc not in {prefixes}"
|
|
|
|
|
|
@then('the ontology should contain node "{label}" for uko_l2')
|
|
def step_check_node_exists(ctx: Context, label: str) -> None:
|
|
labels = {n.label for n in ctx.ontology.nodes}
|
|
assert label in labels, f"Node '{label}' not in {labels}"
|
|
|
|
|
|
@then("the ontology should have at least {count:d} layer 2 nodes for uko_l2")
|
|
def step_check_layer2_count(ctx: Context, count: int) -> None:
|
|
layer2 = [n for n in ctx.ontology.nodes if n.layer == 2]
|
|
assert len(layer2) >= count, f"Expected >= {count} layer 2 nodes, got {len(layer2)}"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# ParadigmVocabulary frozen
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@when("I try to mutate the vocabulary prefix for uko_l2")
|
|
def step_mutate_vocab_prefix(ctx: Context) -> None:
|
|
with capture_error(ctx, ValidationError):
|
|
ctx.vocabulary.prefix = "changed:" # type: ignore[misc] # deliberate mutation to test frozen model
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Additional coverage steps
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@when("I create a paradigm vocabulary with empty prefix for uko_l2")
|
|
def step_create_vocab_empty_prefix(ctx: Context) -> None:
|
|
with capture_error(ctx, ValidationError):
|
|
ParadigmVocabulary(
|
|
prefix="",
|
|
iri="http://test",
|
|
layer=2,
|
|
parent_domain="uko-code:",
|
|
max_depth=0,
|
|
)
|
|
|
|
|
|
@when("I create a paradigm vocabulary with whitespace prefix for uko_l2")
|
|
def step_create_vocab_whitespace_prefix(ctx: Context) -> None:
|
|
with capture_error(ctx, ValidationError):
|
|
ParadigmVocabulary(
|
|
prefix=" ",
|
|
iri="http://test",
|
|
layer=2,
|
|
parent_domain="uko-code:",
|
|
max_depth=0,
|
|
)
|
|
|
|
|
|
@when("I create a vocabulary property with whitespace uri for uko_l2")
|
|
def step_create_vocab_prop_whitespace_uri(ctx: Context) -> None:
|
|
with capture_error(ctx, ValidationError):
|
|
VocabularyProperty(
|
|
uri=" ",
|
|
label="test",
|
|
domain_uri="https://example.com/d",
|
|
range_uri="https://example.com/r",
|
|
)
|
|
|
|
|
|
@then("the registry should return False for non-string contains for uko_l2")
|
|
def step_check_non_string_contains(ctx: Context) -> None:
|
|
assert 42 not in ctx.registry
|
|
assert None not in ctx.registry
|
|
|
|
|
|
@when("I try to register a vocabulary with duplicate IRI for uko_l2")
|
|
def step_register_duplicate_iri(ctx: Context) -> None:
|
|
oo = get_oo_vocabulary()
|
|
dup = ParadigmVocabulary(
|
|
prefix="uko-dup:",
|
|
iri=oo.iri,
|
|
layer=2,
|
|
parent_domain="uko-code:",
|
|
)
|
|
with capture_error(ctx, ValueError):
|
|
ctx.registry.register(dup)
|
|
|
|
|
|
@when("I create a paradigm vocabulary with prefix missing colon for uko_l2")
|
|
def step_create_paradigm_vocab_no_colon(ctx: Context) -> None:
|
|
with capture_error(ctx, ValidationError):
|
|
ParadigmVocabulary(
|
|
prefix="uko-test",
|
|
iri="https://example.org/test#",
|
|
layer=2,
|
|
parent_domain="uko-code:",
|
|
)
|