test: cover manifest validation errors

This commit is contained in:
lda
2026-08-03 07:05:12 +07:00 Unverified
parent 9b09ea7a4c
commit ad030f8074
+147 -1
View File
@@ -1,10 +1,25 @@
from __future__ import annotations
from wf_contract_manifest import manifest_from_openrpc
from typing import Any
import pytest
from wf_contract_manifest import ManifestError, manifest_from_openrpc
from .fixtures import synthetic_openrpc_document
def assert_manifest_error(
document: dict[str, Any], path: str, message: str
) -> None:
with pytest.raises(ManifestError) as error_info:
manifest_from_openrpc(document)
assert error_info.value.path == path
assert error_info.value.message == message
assert str(error_info.value) == f"{path}: {message}"
def test_normalizes_operations_and_components_deterministically() -> None:
manifest = manifest_from_openrpc(synthetic_openrpc_document())
@@ -76,3 +91,134 @@ def test_preserves_conditional_schema_keywords() -> None:
assert alpha["if"] == {"properties": {"mode": {"const": "alpha"}}}
assert alpha["then"] == {"required": ["payload"]}
assert alpha["not"] == {"required": ["forbidden"]}
@pytest.mark.parametrize(
("field", "value", "missing", "path", "message"),
[
("openrpc", None, True, "$.openrpc", "expected a non-empty string"),
("openrpc", 1.2, False, "$.openrpc", "expected a non-empty string"),
("methods", None, True, "$.methods", "expected an array"),
("methods", {}, False, "$.methods", "expected an array"),
("components", None, True, "$.components", "expected an object"),
("components", [], False, "$.components", "expected an object"),
(
"schemas",
None,
True,
"$.components.schemas",
"expected an object",
),
(
"schemas",
[],
False,
"$.components.schemas",
"expected an object",
),
(
"errors",
None,
True,
"$.components.errors",
"expected an object",
),
("errors", [], False, "$.components.errors", "expected an object"),
],
)
def test_rejects_invalid_or_missing_top_level_envelope_values(
field: str,
value: object,
missing: bool,
path: str,
message: str,
) -> None:
document = synthetic_openrpc_document()
if field in {"schemas", "errors"}:
components = document["components"]
if missing:
components.pop(field)
else:
components[field] = value
elif missing:
document.pop(field)
else:
document[field] = value
assert_manifest_error(document, path, message)
@pytest.mark.parametrize(
("name", "message"),
[
("", "expected a non-empty string"),
("workflow", "expected a method name with non-empty dot-separated segments"),
(
"workflow..run",
"expected a method name with non-empty dot-separated segments",
),
(
".workflow.run",
"expected a method name with non-empty dot-separated segments",
),
(
"workflow.run.",
"expected a method name with non-empty dot-separated segments",
),
],
)
def test_rejects_empty_or_malformed_dotted_method_names(
name: str, message: str
) -> None:
document = synthetic_openrpc_document()
document["methods"][0]["name"] = name
assert_manifest_error(document, "$.methods[0].name", message)
@pytest.mark.parametrize(
("field", "value", "missing", "message"),
[
("required", "yes", False, "expected a boolean"),
("required", None, True, "expected a boolean"),
("schema", [], False, "expected a schema object"),
("schema", None, True, "expected a schema object"),
],
)
def test_rejects_invalid_or_missing_parameter_fields(
field: str, value: object, missing: bool, message: str
) -> None:
document = synthetic_openrpc_document()
parameter = document["methods"][1]["params"][0]
if missing:
parameter.pop(field)
else:
parameter[field] = value
assert_manifest_error(
document,
f"$.methods[1].params[0].{field}",
message,
)
def test_rejects_invalid_result_schema_shape() -> None:
document = synthetic_openrpc_document()
document["methods"][1]["result"]["schema"] = []
assert_manifest_error(
document,
"$.methods[1].result.schema",
"expected a schema object",
)
def test_rejects_invalid_method_error_schema_shape() -> None:
document = synthetic_openrpc_document()
document["methods"][1]["errors"][0] = []
assert_manifest_error(
document,
"$.methods[1].errors[0]",
"expected a schema object",
)