feat: pdf2cad
This commit is contained in:
347
tests/test_schema.py
Normal file
347
tests/test_schema.py
Normal file
@@ -0,0 +1,347 @@
|
||||
"""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)
|
||||
Reference in New Issue
Block a user