From 2e1b0e230982a0697681a29e6a37762d790ff4fd Mon Sep 17 00:00:00 2001
From: fspreck <f.spreckelsen@indiscale.com>
Date: Fri, 13 Oct 2023 17:54:47 +0200
Subject: [PATCH] TST: Extend unit tests

---
 unittests/test_json_schema_exporter.py | 138 ++++++++++++++++++++++++-
 1 file changed, 136 insertions(+), 2 deletions(-)

diff --git a/unittests/test_json_schema_exporter.py b/unittests/test_json_schema_exporter.py
index ee81fed0..a17717b2 100644
--- a/unittests/test_json_schema_exporter.py
+++ b/unittests/test_json_schema_exporter.py
@@ -22,6 +22,7 @@
 
 import linkahead as db
 
+from jsonschema import FormatChecker, validate, ValidationError
 from pytest import raises
 
 from caosadvancedtools.json_schema_exporter import recordtype_to_json_schema as rtjs
@@ -57,12 +58,145 @@ def test_empty_rt():
 
 def test_rt_with_scalar_props():
 
-    pass
+    rt = db.RecordType(name="Test")
+    rt.add_property(name="SimpleText", datatype=db.TEXT, description="This is a simple text")
+    rt.add_property(name="ObligatoryDatetime", datatype=db.DATETIME, importance=db.OBLIGATORY)
+    rt.add_property(name="JustDateNoTime", datatype=db.DATETIME, description="Only dates, no times")
+    rt.add_property(name="ObligatoryInteger", datatype=db.INTEGER, importance=db.OBLIGATORY)
+    rt.add_property(name="Double", datatype=db.DOUBLE)
+    # Suggested shouldn't influence the result in any way.
+    rt.add_property(name="Boolean", datatype=db.BOOLEAN, importance=db.SUGGESTED)
+
+    schema = rtjs(rt, additional_options_for_text_props={"JustDateNoTime": {"format": "date"}})
+
+    assert "properties" in schema
+    props = schema["properties"]
+    assert len(props) == 6
+    assert "required" in schema
+    assert len(schema["required"]) == 2
+    assert "ObligatoryDatetime" in schema["required"]
+    assert "ObligatoryInteger" in schema["required"]
+
+    assert "SimpleText" in props
+    assert props["SimpleText"]["type"] == "string"
+    assert "format" not in props["SimpleText"]
+    assert "description" in props["SimpleText"]
+    assert props["SimpleText"]["description"] == "This is a simple text"
+
+    assert "ObligatoryDatetime" in props
+    assert props["ObligatoryDatetime"]["type"] == "string"
+    assert "anyOf" in props["ObligatoryDatetime"]
+    assert len(props["ObligatoryDatetime"]["anyOf"]) == 2
+    fmts = [fmt["format"] for fmt in props["ObligatoryDatetime"]["anyOf"]]
+    assert "date" in fmts
+    assert "date-time" in fmts
+
+    assert "JustDateNoTime" in props
+    assert props["JustDateNoTime"]["type"] == "string"
+    assert "anyOf" not in props["JustDateNoTime"]
+    assert "pattern" not in props["JustDateNoTime"]
+    assert props["JustDateNoTime"]["format"] == "date"
+    assert props["JustDateNoTime"]["description"] == "Only dates, no times"
+
+    assert "ObligatoryInteger" in props
+    assert props["ObligatoryInteger"]["type"] == "integer"
+
+    assert "Double" in props
+    assert props["Double"]["type"] == "number"
+
+    assert "Boolean" in props
+    assert props["Boolean"]["type"] == "boolean"
+
+    # test validation (we turst the jsonschema.validat function, so only test
+    # some more or less tricky cases with format or required).
+    example = {
+        "SimpleText": "something",
+        "ObligatoryInteger": 23,
+        "ObligatoryDatetime": "1900-01-01T12:34:56.0Z",
+        "JustDateNoTime": "2023-10-13"
+    }
+
+    # We need to explicitly enable the FormatChecker, otherwise format will be
+    # ignored
+    # (https://python-jsonschema.readthedocs.io/en/latest/validate/#validating-formats)
+    validate(example, schema, format_checker=FormatChecker())
+
+    example = {
+        "SimpleText": "something",
+        "ObligatoryInteger": 23,
+        "ObligatoryDatetime": "1900-01-01",
+        "JustDateNoTime": "2023-10-13"
+    }
+    validate(example, schema, format_checker=FormatChecker())
+
+    example = {
+        "SimpleText": "something",
+        "ObligatoryDatetime": "1900-01-01T12:34:56.0Z",
+        "JustDateNoTime": "2023-10-13"
+    }
+
+    with raises(ValidationError):
+        # required missing
+        validate(example, schema, format_checker=FormatChecker())
+
+    example = {
+        "SimpleText": "something",
+        "ObligatoryInteger": 23,
+        "ObligatoryDatetime": "1900-01-01T12:34:56.0Z",
+        "JustDateNoTime": "2023-10-13T23:59:59.123Z"
+    }
+
+    with raises(ValidationError):
+        # date expected in JustDateNoTime, but datetime given
+        validate(example, schema, format_checker=FormatChecker())
 
 
 def test_rt_with_list_props():
 
-    pass
+    rt = db.RecordType()
+    rt.add_property(name="ListOfIntegers", datatype=db.LIST(
+        db.INTEGER), description="List of integers")
+    rt.add_property(name="ListOfPatterns", datatype=db.LIST(db.TEXT))
+
+    schema = rtjs(rt, additional_options_for_text_props={"ListOfPatterns": {"pattern": "[A-Z]+"}})
+
+    props = schema["properties"]
+
+    assert "ListOfIntegers" in props
+    assert props["ListOfIntegers"]["type"] == "array"
+    assert "items" in props["ListOfIntegers"]
+    assert props["ListOfIntegers"]["items"]["type"] == "integer"
+    assert "description" not in props["ListOfIntegers"]["items"]
+    assert props["ListOfIntegers"]["description"] == "List of integers"
+
+    assert "ListOfPatterns" in props
+    assert props["ListOfPatterns"]["type"] == "array"
+    assert "items" in props["ListOfPatterns"]
+    assert props["ListOfPatterns"]["items"]["type"] == "string"
+    assert props["ListOfPatterns"]["items"]["pattern"] == "[A-Z]+"
+
+    # Validation
+    example = {
+        "ListOfIntegers": [1, 2, 3],
+        "ListOfPatterns": ["A", "BB", "CCC"]
+    }
+    validate(example, schema, format_checker=FormatChecker())
+
+    example = {
+        "ListOfIntegers": 1,
+        "ListOfPatterns": ["A", "BB", "CCC"]
+    }
+    with raises(ValidationError):
+        # No list
+        validate(example, schema, format_checker=FormatChecker())
+
+    example = {
+        "ListOfIntegers": [1, 2, 3],
+        "ListOfPatterns": ["A", "bb", "CCC"]
+    }
+    with raises(ValidationError):
+        # Pattern doesn't match
+        validate(example, schema, format_checker=FormatChecker())
 
 
 def test_rt_with_references():
-- 
GitLab