67 lines
2.4 KiB
Python
67 lines
2.4 KiB
Python
|
|
"""Tests for api.classification validation module (STATE-WP-0065 P2)."""
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import pytest
|
||
|
|
|
||
|
|
from api.classification import (
|
||
|
|
ClassificationData,
|
||
|
|
validate_classification,
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def _valid_block(**overrides) -> dict:
|
||
|
|
base = {
|
||
|
|
"category": "tooling",
|
||
|
|
"domain": "infotech",
|
||
|
|
"secondary_domains": [],
|
||
|
|
"capability_tags": ["platform"],
|
||
|
|
"business_stake": ["technology", "operations"],
|
||
|
|
"business_mechanics": ["coordination"],
|
||
|
|
}
|
||
|
|
base.update(overrides)
|
||
|
|
return base
|
||
|
|
|
||
|
|
|
||
|
|
class TestValidateClassification:
|
||
|
|
def test_valid_block_passes(self):
|
||
|
|
errors, warnings = validate_classification(_valid_block())
|
||
|
|
assert errors == []
|
||
|
|
|
||
|
|
def test_missing_category_fails(self):
|
||
|
|
block = _valid_block()
|
||
|
|
del block["category"]
|
||
|
|
errors, _ = validate_classification(block)
|
||
|
|
assert any("category" in err for err in errors)
|
||
|
|
|
||
|
|
def test_invalid_category_fails(self):
|
||
|
|
errors, _ = validate_classification(_valid_block(category="not-a-category"))
|
||
|
|
assert any("category" in err for err in errors)
|
||
|
|
|
||
|
|
def test_invalid_domain_fails(self):
|
||
|
|
errors, _ = validate_classification(_valid_block(domain="not-a-domain"))
|
||
|
|
assert any("domain" in err for err in errors)
|
||
|
|
|
||
|
|
def test_unknown_capability_tag_warns(self):
|
||
|
|
_, warnings = validate_classification(_valid_block(capability_tags=["totally-made-up-tag"]))
|
||
|
|
assert any("capability_tag" in warn for warn in warnings)
|
||
|
|
|
||
|
|
def test_invalid_business_stake_fails(self):
|
||
|
|
errors, _ = validate_classification(_valid_block(business_stake=["not-a-stake"]))
|
||
|
|
assert any("business_stake" in err for err in errors)
|
||
|
|
|
||
|
|
def test_secondary_domain_repeats_primary_fails(self):
|
||
|
|
errors, _ = validate_classification(
|
||
|
|
_valid_block(domain="infotech", secondary_domains=["infotech"])
|
||
|
|
)
|
||
|
|
assert any("repeats the primary domain" in err for err in errors)
|
||
|
|
|
||
|
|
|
||
|
|
class TestClassificationData:
|
||
|
|
def test_round_trip_dict(self):
|
||
|
|
block = _valid_block(classified_at="2026-06-22", classified_by="human", version="1.0")
|
||
|
|
data = ClassificationData.from_block(block)
|
||
|
|
payload = data.to_dict()
|
||
|
|
assert payload["category"] == "tooling"
|
||
|
|
assert payload["domain"] == "infotech"
|
||
|
|
assert payload["classified_by"] == "human"
|
||
|
|
assert payload["standard_version"] == "1.0"
|