import unittest from copy import deepcopy from typing import Dict from wrpylib.json_tools import order_json_keys, _resolve_ref schema_object: Dict = { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "required": [ "name" ], "properties": { "name": { "type": "string", }, "aliases": { "type": "array", "items": { "type": "string", "title": "Alternativer Name" } }, "entry_under_construction": { "type": "boolean", "default": True, }, "length": { "type": "number", "minimum": 1, "optional": True }, "difficulty": { "type": "string", "enum": [ "leicht", "mittel", "schwer" ], }, "walkup_time": { "type": "number", }, } } schema_array = { "$schema": "http://json-schema.org/draft-07/schema#", "type": "array", "items": { "type": "string", } } class TestResolveRef(unittest.TestCase): def test_no_ref(self): sub_schema = schema_object['properties']['aliases'] actual = _resolve_ref(sub_schema, schema_object) self.assertEqual(actual, sub_schema) def test_ref(self): root_schema = schema_object.copy() root_schema["definitions"] = { "weblink": { "type": "string", } } sub_schema = { "$ref": "#/definitions/weblink" } expected = { "type": "string", } actual = _resolve_ref(sub_schema, root_schema) self.assertEqual(expected, actual) class TestOrderJsonKeys(unittest.TestCase): def test_string_empty(self): actual = order_json_keys('', {"type": "string"}) self.assertEqual('', actual) def test_string_valid(self): actual = order_json_keys('äüß', {"type": "string"}) self.assertEqual('äüß', actual) def test_string_wrong_types(self): for value in [True, False, None, 0, 1, 0.5, [], ['abc'], {}, {'a': 'b'}]: with self.subTest(f'Try invalid value {value}.', value=value): with self.assertRaises(ValueError): order_json_keys(value, {"type": "string"}) def test_number_valid(self): for value in [0, 1, -10, 8.8, 0.0, -1024.9]: with self.subTest(f'Valid number {value}.', value=value): actual = order_json_keys(value, {"type": "number"}) self.assertEqual(value, actual) def test_number_wrong_types(self): for value in [True, False, None, '', 'abc', [], [0], [1], {}, {'a': 1}]: with self.subTest(f'Try invalid value {value}.', value=value): with self.assertRaises(ValueError): order_json_keys(value, {"type": "number"}) def test_object_empty(self): schema = schema_object.copy() del schema['required'] actual = order_json_keys({}, schema) self.assertEqual({}, actual) def test_object_missing_keys(self): with self.assertRaises(ValueError): order_json_keys({}, schema_object) def test_object_some_keys(self): actual = order_json_keys({'name': 'X', 'walkup_time': 30, 'difficulty': 'mittel'}, schema_object) self.assertEqual({'name': 'X', 'difficulty': 'mittel', 'walkup_time': 30}, actual) def test_object_all_keys(self): value = { 'walkup_time': 120, 'aliases': ['c', 'a', 'b'], 'entry_under_construction': False, 'name': 'ÖÄÜ', 'difficulty': 'leicht', 'length': 60, } expected = { 'name': 'ÖÄÜ', 'aliases': ['c', 'a', 'b'], 'entry_under_construction': False, 'length': 60, 'difficulty': 'leicht', 'walkup_time': 120, } actual = order_json_keys(value, schema_object) self.assertEqual(expected, actual) def test_object_additional_keys(self): value = { 'walkup_time': 120, 'aliases': ['c', 'a', 'b'], 'entry_under_construction': False, 'name': 'ÖÄÜ', 'surprise': True, 'difficulty': 'leicht', 'length': 60, } expected = { 'name': 'ÖÄÜ', 'aliases': ['c', 'a', 'b'], 'entry_under_construction': False, 'length': 60, 'difficulty': 'leicht', 'walkup_time': 120, 'surprise': True, } actual = order_json_keys(value, schema_object) self.assertEqual(expected, actual) def test_object_forbidden_additional_keys(self): value = { 'name': 'abc', 'surprise': True, 'difficulty': 'leicht', } schema = schema_object.copy() schema['additionalProperties'] = False with self.assertRaises(ValueError): order_json_keys(value, schema) def test_object_nested(self): schema = deepcopy(schema_object) schema['properties']['nested'] = schema_object value = { 'nested': { 'length': 3, 'name': 'Mustermann', }, 'name': 'parent', } expected = { 'name': 'parent', 'nested': { 'name': 'Mustermann', 'length': 3, } } actual = order_json_keys(value, schema) self.assertEqual(expected, actual) def test_object_nested_wrong_type(self): schema = deepcopy(schema_object) schema['properties']['nested'] = schema_object with self.assertRaises(ValueError) as cm: order_json_keys({'name': 'name', 'nested': {'name': True}}, schema) self.assertIn("['nested']['name']", str(cm.exception)) def test_array_empty(self): schema = schema_array actual = order_json_keys([], schema) self.assertEqual([], actual) def test_array_string(self): schema = schema_array actual = order_json_keys(['', 'a', 'ßöÄ'], schema) self.assertEqual(['', 'a', 'ßöÄ'], actual) def test_array_number(self): schema = deepcopy(schema_array) schema['items']['type'] = "number" value = [0, 6.3, -3] actual = order_json_keys(value, schema) self.assertEqual(value, actual) def test_array_object(self): schema = deepcopy(schema_array) schema['items']['type'] = "object" value = [{}, {'a': 'b'}] actual = order_json_keys(value, schema) self.assertEqual(value, actual) def test_array_array(self): schema = deepcopy(schema_array) schema['items']['type'] = "array" value = [[], [3], [6, 8, 3.3]] actual = order_json_keys(value, schema) self.assertEqual(value, actual) def test_array_boolean(self): schema = deepcopy(schema_array) schema['items']['type'] = "boolean" value = [False, True, False] actual = order_json_keys(value, schema) self.assertEqual(value, actual) def test_array_null(self): schema = deepcopy(schema_array) schema['items']['type'] = "null" value = [None, None] actual = order_json_keys(value, schema) self.assertEqual(value, actual) def test_array_wrong_string_types(self): schema = { "type": "array", "items": { "type": "string", } } for v in [7, 0.4, {}, {'a': 'b'}, [], [1, 2, 3], True, False, None]: value = [v] with self.subTest(f'Try invalid value {value}.', value=value): with self.assertRaises(ValueError): order_json_keys(value, schema) def test_array_mixed_types(self): schema = { "type": "array", "items": { "type": "string", } } for v in [7, 0.4, {}, {'a': 'b'}, [], [1, 2, 3], True, False, None]: value = ['a', v] with self.subTest(f'Try invalid value {value}.', value=value): with self.assertRaises(ValueError): order_json_keys(value, schema) def test_boolean_valid(self): for value in [False, True]: with self.subTest(f'Valid boolean {value}.', value=value): actual = order_json_keys(value, {"type": "boolean"}) self.assertEqual(value, actual) def test_boolean_wrong_types(self): for value in [0, 1, -3, 10, 5.5, None, '', 'True', [], [True], [False], {}, {'a': True}]: with self.subTest(f'Try invalid value {value}.', value=value): with self.assertRaises(ValueError): order_json_keys(value, {"type": "boolean"}) def test_null_valid(self): actual = order_json_keys(None, {"type": "null"}) self.assertEqual(None, actual) def test_null_wrong_types(self): for value in [True, False, 0, 1, -3, 10, 5.5, '', 'abc', [], [0], [1], {}, {'a': 1}]: with self.subTest(f'Try invalid value {value}.', value=value): with self.assertRaises(ValueError): order_json_keys(value, {"type": "null"})