Files
pdf2cad/tests/test_schema.py
2026-03-03 21:24:02 +00:00

348 lines
12 KiB
Python

"""Tests for JSON Schema validation."""
import jsonschema
import pytest
from pdf2imos.schema.validator import load_schema, validate_metadata
class TestSchemaLoading:
"""Tests for schema loading."""
def test_schema_loads_as_valid_json(self):
"""Test that the schema file is valid JSON."""
schema = load_schema()
assert isinstance(schema, dict)
assert "$schema" in schema
assert schema["$schema"] == "https://json-schema.org/draft/2020-12/schema"
def test_schema_has_required_properties(self):
"""Test that schema defines required properties."""
schema = load_schema()
assert "required" in schema
required = schema["required"]
assert "source_pdf" in required
assert "extraction_timestamp" in required
assert "part_name" in required
assert "overall_dimensions" in required
assert "parts" in required
assert "raw_annotations" in required
class TestValidMetadata:
"""Tests for valid metadata."""
@pytest.fixture
def valid_metadata(self):
"""Fixture for valid metadata."""
return {
"source_pdf": "test.pdf",
"extraction_timestamp": "2026-01-01T00:00:00Z",
"part_name": "cabinet",
"overall_dimensions": {
"width_mm": 600,
"height_mm": 720,
"depth_mm": 400,
},
"parts": [],
"raw_annotations": [],
}
def test_validate_valid_metadata(self, valid_metadata):
"""Test that valid metadata passes validation."""
# Should not raise
validate_metadata(valid_metadata)
def test_validate_metadata_with_parts(self):
"""Test validation with parts data."""
metadata = {
"source_pdf": "test.pdf",
"extraction_timestamp": "2026-01-01T00:00:00Z",
"part_name": "cabinet",
"overall_dimensions": {
"width_mm": 600,
"height_mm": 720,
"depth_mm": 400,
},
"parts": [
{
"name": "side_panel",
"dimensions": {
"width_mm": 18,
"height_mm": 720,
"depth_mm": 400,
},
"material": {
"type": "plywood",
"thickness_mm": 18,
"finish": "veneer",
},
}
],
"raw_annotations": ["annotation1"],
}
# Should not raise
validate_metadata(metadata)
def test_validate_metadata_with_edgebanding(self):
"""Test validation with edgebanding data."""
metadata = {
"source_pdf": "test.pdf",
"extraction_timestamp": "2026-01-01T00:00:00Z",
"part_name": "cabinet",
"overall_dimensions": {
"width_mm": 600,
"height_mm": 720,
"depth_mm": 400,
},
"parts": [
{
"name": "shelf",
"dimensions": {
"width_mm": 550,
"height_mm": 20,
"depth_mm": 350,
},
"edgebanding": {
"top": {"material": "pvc", "thickness_mm": 2},
"bottom": None,
"left": {"material": "pvc", "thickness_mm": 2},
"right": {"material": "pvc", "thickness_mm": 2},
},
}
],
"raw_annotations": [],
}
# Should not raise
validate_metadata(metadata)
def test_validate_metadata_with_hardware(self):
"""Test validation with hardware data."""
metadata = {
"source_pdf": "test.pdf",
"extraction_timestamp": "2026-01-01T00:00:00Z",
"part_name": "cabinet",
"overall_dimensions": {
"width_mm": 600,
"height_mm": 720,
"depth_mm": 400,
},
"parts": [
{
"name": "door",
"dimensions": {
"width_mm": 300,
"height_mm": 700,
"depth_mm": 20,
},
"hardware": [
{
"type": "hinge",
"model": "BLUM-CLIP",
"position": "top_left",
},
{
"type": "hinge",
"model": "BLUM-CLIP",
"position": "bottom_left",
},
],
}
],
"raw_annotations": [],
}
# Should not raise
validate_metadata(metadata)
def test_validate_metadata_with_drilling(self):
"""Test validation with drilling data."""
metadata = {
"source_pdf": "test.pdf",
"extraction_timestamp": "2026-01-01T00:00:00Z",
"part_name": "cabinet",
"overall_dimensions": {
"width_mm": 600,
"height_mm": 720,
"depth_mm": 400,
},
"parts": [
{
"name": "panel",
"dimensions": {
"width_mm": 550,
"height_mm": 700,
"depth_mm": 18,
},
"drilling": [
{
"x_mm": 100,
"y_mm": 200,
"diameter_mm": 5,
"depth_mm": 10,
},
{
"x_mm": 200,
"y_mm": 300,
"diameter_mm": 8,
"depth_mm": 15,
},
],
}
],
"raw_annotations": [],
}
# Should not raise
validate_metadata(metadata)
class TestInvalidMetadata:
"""Tests for invalid metadata."""
def test_validate_empty_dict_raises(self):
"""Test that empty dict raises ValidationError."""
with pytest.raises(jsonschema.ValidationError):
validate_metadata({})
def test_validate_missing_required_field_raises(self):
"""Test that missing required field raises ValidationError."""
metadata = {
"source_pdf": "test.pdf",
"extraction_timestamp": "2026-01-01T00:00:00Z",
"part_name": "cabinet",
"overall_dimensions": {
"width_mm": 600,
"height_mm": 720,
"depth_mm": 400,
},
# Missing "parts" and "raw_annotations"
}
with pytest.raises(jsonschema.ValidationError):
validate_metadata(metadata)
def test_validate_negative_dimension_raises(self):
"""Test that negative dimension raises ValidationError."""
metadata = {
"source_pdf": "test.pdf",
"extraction_timestamp": "2026-01-01T00:00:00Z",
"part_name": "cabinet",
"overall_dimensions": {
"width_mm": -1,
"height_mm": 100,
"depth_mm": 50,
},
"parts": [],
"raw_annotations": [],
}
with pytest.raises(jsonschema.ValidationError):
validate_metadata(metadata)
def test_validate_zero_dimension_raises(self):
"""Test that zero dimension raises ValidationError (exclusiveMinimum)."""
metadata = {
"source_pdf": "test.pdf",
"extraction_timestamp": "2026-01-01T00:00:00Z",
"part_name": "cabinet",
"overall_dimensions": {
"width_mm": 0,
"height_mm": 100,
"depth_mm": 50,
},
"parts": [],
"raw_annotations": [],
}
with pytest.raises(jsonschema.ValidationError):
validate_metadata(metadata)
def test_validate_wrong_type_raises(self):
"""Test that wrong type raises ValidationError."""
metadata = {
"source_pdf": 123, # Should be string
"extraction_timestamp": "2026-01-01T00:00:00Z",
"part_name": "cabinet",
"overall_dimensions": {
"width_mm": 600,
"height_mm": 720,
"depth_mm": 400,
},
"parts": [],
"raw_annotations": [],
}
with pytest.raises(jsonschema.ValidationError):
validate_metadata(metadata)
def test_validate_additional_properties_raises(self):
"""Test that additional properties raise ValidationError."""
metadata = {
"source_pdf": "test.pdf",
"extraction_timestamp": "2026-01-01T00:00:00Z",
"part_name": "cabinet",
"overall_dimensions": {
"width_mm": 600,
"height_mm": 720,
"depth_mm": 400,
},
"parts": [],
"raw_annotations": [],
"extra_field": "not allowed",
}
with pytest.raises(jsonschema.ValidationError):
validate_metadata(metadata)
def test_validate_parts_missing_required_field_raises(self):
"""Test that parts missing required field raises ValidationError."""
metadata = {
"source_pdf": "test.pdf",
"extraction_timestamp": "2026-01-01T00:00:00Z",
"part_name": "cabinet",
"overall_dimensions": {
"width_mm": 600,
"height_mm": 720,
"depth_mm": 400,
},
"parts": [
{
"name": "panel",
# Missing "dimensions"
}
],
"raw_annotations": [],
}
with pytest.raises(jsonschema.ValidationError):
validate_metadata(metadata)
def test_validate_edgebanding_additional_properties_raises(self):
"""Test that edgebanding with additional properties raises ValidationError."""
metadata = {
"source_pdf": "test.pdf",
"extraction_timestamp": "2026-01-01T00:00:00Z",
"part_name": "cabinet",
"overall_dimensions": {
"width_mm": 600,
"height_mm": 720,
"depth_mm": 400,
},
"parts": [
{
"name": "shelf",
"dimensions": {
"width_mm": 550,
"height_mm": 20,
"depth_mm": 350,
},
"edgebanding": {
"top": {
"material": "pvc",
"thickness_mm": 2,
"extra_field": "not allowed",
},
"bottom": None,
"left": None,
"right": None,
},
}
],
"raw_annotations": [],
}
with pytest.raises(jsonschema.ValidationError):
validate_metadata(metadata)