Commit 69de58ca authored by Dom Sekotill's avatar Dom Sekotill
Browse files

Add unit tests for behave_utils.json

parent 47421ab3
Loading
Loading
Loading
Loading
+174 −0
Original line number Diff line number Diff line
#  Copyright 2022  Dominik Sekotill <dom.sekotill@kodo.org.uk>
#
#  This Source Code Form is subject to the terms of the Mozilla Public
#  License, v. 2.0. If a copy of the MPL was not distributed with this
#  file, You can obtain one at http://mozilla.org/MPL/2.0/.

"""
Unit tests for behave_utils.json
"""

from json import dumps as json_dumps
from typing import Any

from behave_utils.json import JSONArray
from behave_utils.json import JSONObject

from . import TestCase

SAMPLE_OBJECT = {
	"integer_object": {
		"first": 1,
		"second": 2,
	},
}

SAMPLE_ARRAY = [
	SAMPLE_OBJECT,
	SAMPLE_OBJECT,
]

SAMPLE_OBJECT_JSON = json_dumps(SAMPLE_OBJECT).encode()
SAMPLE_ARRAY_JSON = json_dumps(SAMPLE_ARRAY).encode()


class JSONObjectTests(TestCase):
	"""
	Tests for behave_utils.json.JSONObject
	"""

	def test_from_dict(self) -> None:
		"""
		Check that a JSONObject can be created from a dictionary of values
		"""
		instance = JSONObject(SAMPLE_OBJECT)

		self.assertIsInstance(instance, JSONObject)
		self.assertDictEqual(instance, SAMPLE_OBJECT)

	def test_from_JSONObject(self) -> None:
		"""
		Check that a JSONObject can be created from another JSONObject
		"""
		source = JSONObject(SAMPLE_OBJECT)

		instance = JSONObject(source)

		self.assertIsInstance(instance, JSONObject)
		self.assertDictEqual(instance, SAMPLE_OBJECT)

	def test_from_from_string(self) -> None:
		"""
		Check that a JSONObject can be created from a string passed to the from_string method
		"""
		instance = JSONObject.from_string(SAMPLE_OBJECT_JSON)

		self.assertIsInstance(instance, JSONObject)
		self.assertDictEqual(instance, SAMPLE_OBJECT)

	def test_from_from_string_bad_type(self) -> None:
		"""
		Check that a JSON string of the wrong type raises TypeError
		"""
		with self.assertRaises(TypeError):
			JSONObject.from_string(b"""[1,2,3]""")

	def test_path(self) -> None:
		"""
		Check that retrieving values with the path method works with various types
		"""
		sample = JSONObject(SAMPLE_OBJECT)

		with self.subTest("single return"):
			output: Any = sample.path("$.integer_object.first", int)

			self.assertIsInstance(output, int)

		with self.subTest("multiple returns"):
			output = sample.path("$.integer_object[*]", list[int])

			self.assertIsInstance(output, list)
			self.assertSetEqual(set(output), {1, 2})

		with self.subTest("object return"):
			output = sample.path("$.integer_object", dict[str, int])

			self.assertIsInstance(output, dict)
			self.assertDictEqual(output, SAMPLE_OBJECT["integer_object"])

	def test_path_convert(self) -> None:
		"""
		Check that passing "convert" to the path method works
		"""
		sample = JSONObject(SAMPLE_OBJECT)

		with self.subTest("int -> str"):
			output: Any = sample.path("$.integer_object.first", int, str)

			self.assertIsInstance(output, str)

		with self.subTest("list -> set"):
			output = sample.path("$.integer_object[*]", list[int], set[int])

			self.assertIsInstance(output, set)
			self.assertSetEqual(output, {1, 2})

	def test_path_bad_type(self) -> None:
		"""
		Check that TypeError is raised when the type passed to path() does not match
		"""
		sample = JSONObject(SAMPLE_OBJECT)

		with self.assertRaises(TypeError):
			sample.path("$.integer_object.first", str)

	def test_path_missing(self) -> None:
		"""
		Check that KeyError is raised when no result is found
		"""
		sample = JSONObject(SAMPLE_OBJECT)

		with self.assertRaises(KeyError):
			sample.path("$.integer_object.last", int)


class JSONArrayTests(TestCase):
	"""
	Tests for behave_utils.json.JSONArray
	"""

	def test_from_dict(self) -> None:
		"""
		Check that a JSONArray can be created from a dictionary of values
		"""
		instance = JSONArray(SAMPLE_ARRAY)

		self.assertIsInstance(instance, JSONArray)
		self.assertListEqual(instance, SAMPLE_ARRAY)

	def test_from_JSONObject(self) -> None:
		"""
		Check that a JSONArray can be created from another JSONArray
		"""
		source = JSONArray(SAMPLE_ARRAY)

		instance = JSONArray(source)

		self.assertIsInstance(instance, JSONArray)
		self.assertListEqual(instance, SAMPLE_ARRAY)

	def test_from_from_string(self) -> None:
		"""
		Check that a JSONArray can be created from a string passed to the from_string method
		"""
		instance = JSONArray.from_string(SAMPLE_ARRAY_JSON)

		self.assertIsInstance(instance, JSONArray)
		self.assertListEqual(instance, SAMPLE_ARRAY)

	def test_from_from_string_bad_type(self) -> None:
		"""
		Check that a JSON string of the wrong type raises TypeError
		"""
		with self.assertRaises(TypeError):
			JSONArray.from_string(b"""{"first": 1}""")