Source code for goat.tests.test_authorities_util

from goat.authorities.util import *

import unittest, mock, json
import lxml.etree as ET


[docs]class TestGenerateRequest(unittest.TestCase): """ :meth:`goat.authorities.util.generate_request` should return a callable that will dispatch a request with provided parameters and/or headers. """ @mock.patch('requests.get')
[docs] def test_get(self, mock_get): """ By default, will generate a callable that performs a GET request using the configured parameters. """ config = { "path": "{endpoint}/Concept", "parameters": [ { "accept": "id", "send": "sendid", "required": True, }, ] } glob = {"endpoint": "http://chps.asu.edu/conceptpower/rest",} func = generate_request(config, glob=glob) result = func(id="testID") expected_endpoint = 'http://chps.asu.edu/conceptpower/rest/Concept' args, kwargs = mock_get.call_args self.assertEqual(mock_get.call_count, 1) self.assertEqual(args[0], expected_endpoint) self.assertIn('sendid', kwargs['params']) self.assertIn('headers', kwargs)
@mock.patch('requests.post')
[docs] def test_post(self, mock_post): """ If a POST request, will call ``requests.post`` with ``data``. """ config = { "method": "POST", "path": "{endpoint}/Concept", "parameters": [ { "accept": "id", "send": "sendid", "required": True, }, ] } glob = {"endpoint": "http://chps.asu.edu/conceptpower/rest",} func = generate_request(config, glob=glob) result = func(id="testID") expected_endpoint = 'http://chps.asu.edu/conceptpower/rest/Concept' args, kwargs = mock_post.call_args self.assertEqual(mock_post.call_count, 1) self.assertEqual(args[0], expected_endpoint) self.assertIn('data', kwargs) self.assertIn('sendid', kwargs['data']) self.assertIn('headers', kwargs)
@mock.patch('requests.get')
[docs] def test_get_required(self, mock_get): """ If a paramter is required, a TypeError will be raised if the callable does not receive it. """ config = { "path": "{endpoint}/Concept", "parameters": [ { "accept": "id", "send": "id", "required": True, }, ] } glob = {"endpoint": "http://chps.asu.edu/conceptpower/rest",} func = generate_request(config, glob=glob) with self.assertRaises(TypeError): result = func()
@mock.patch('requests.get')
[docs] def test_get_not_required(self, mock_get): """ If a paramter is not required (default), no error will be raised if the function does not receive it. """ config = { "path": "{endpoint}/Concept", "parameters": [ { "accept": "id", "send": "id", }, ] } glob = {"endpoint": "http://chps.asu.edu/conceptpower/rest",} func = generate_request(config, glob=glob) try: result = func() except TypeError: self.fail()
[docs]class TestParseXMLPath(unittest.TestCase):
[docs] def test_no_namespace_no_attrib(self): """ The default behavior of :meth:`goat.authorities.util.parse_xml_path` is to return a callable that, when passed an :class:`ET.Element`\, finds the element with specified name and returns its value (presumably CDATA). """ root = ET.Element('root') field = ET.Element('afieldname') field.text = 'avalue' root.append(field) path = "afieldname" self.assertEqual(parse_xml_path(path)(root), field.text)
[docs] def test_no_namespace_no_attrib_sep(self): """ If a separator is provided, should use that separator to individuate multiple values from a single element. """ root = ET.Element('root') field = ET.Element('afieldname') values = ['avalue', 'asecondvalue', 'athirdvalue'] field.text = ','.join(values) root.append(field) path = "afieldname|," result = parse_xml_path(path)(root) self.assertSetEqual(set(result), set(values))
[docs] def test_no_namespace_no_attrib_multiple(self): """ """ root = ET.Element('root') field = ET.Element('afieldname') field.text = 'avalue' field2 = ET.Element('afieldname') field2.text = 'asecondvalue' root.append(field) root.append(field2) path = "afieldname*" result = parse_xml_path(path)(root) self.assertEqual(result[0], field.text) self.assertEqual(result[1], field2.text)
[docs] def test_no_namespace_no_attrib_multiple_levels(self): """ The path can have several levels, separated by '/' characters. """ root = ET.Element('root') parent = ET.Element('parent') field = ET.Element('afieldname') field.text = 'avalue' parent.append(field) root.append(parent) path = "parent/afieldname" self.assertEqual(parse_xml_path(path)(root), field.text)
[docs] def test_no_namespace_no_attrib_multiple_levels_multivalue(self): """ Iteration can happen at any level of the path. """ root = ET.Element('root') parent = ET.Element('parent') parent2 = ET.Element('parent') field = ET.Element('afieldname') field.text = 'avalue' field2 = ET.Element('afieldname') field2.text = 'asecondvalue' parent.append(field) parent2.append(field2) root.append(parent) root.append(parent2) path = "parent*/afieldname" result = parse_xml_path(path)(root) self.assertEqual(result[0], field.text) self.assertEqual(result[1], field2.text)
[docs] def test_no_namespace_with_attribute(self): """ If an attribute name is included in square brackets, will return the value of that attribute rather than the CDATA child of the matched element. """ root = ET.Element('root') field = ET.Element('afieldname') field.text = 'avalue' field.attrib['test'] = 'foo' root.append(field) path = "afieldname[test]" self.assertEqual(parse_xml_path(path)(root), field.attrib['test'])
[docs] def test_namespace_no_attrib(self): """ Should be able to navigate namespaced paths. """ NS = 'http://test.com/' nsmap = {'test': NS} root = ET.Element(ET.QName(NS, 'root')) field = ET.Element(ET.QName(NS, 'afieldname')) field.text = 'avalue' root.append(field) path = "test:afieldname" self.assertEqual(parse_xml_path(path, nsmap)(root), field.text)
[docs]class TestJSONPath(unittest.TestCase):
[docs] def test_no_namespace_no_attrib(self): """ The default behavior of :meth:`goat.authorities.util.parse_json_path` is to return a callable that, when passed a ``dict`` parsed from JSON finds the element with specified name and returns its value (presumably CDATA). """ doc = JSONData(json.loads(""" { "key": "value" } """)) path = "key" self.assertEqual(parse_json_path(path)(doc), "value")
[docs] def test_no_namespace_no_attrib_sep(self): """ If a separator is provided, should use that separator to individuate multiple values from a single element. """ doc = JSONData(json.loads(""" { "key": "value1,value2" } """)) path = "key|," result = parse_json_path(path)(doc) self.assertSetEqual(set(result), set(["value1", "value2"]))
[docs] def test_no_namespace_no_attrib_multiple(self): """ The aterisk * operator is used to indicate that multiple elements should be expected. """ doc = JSONData(json.loads(""" { "data": [ { "key": "value1" }, { "key": "value2" } ] } """)) path = "data/key*" result = parse_json_path(path)(doc) self.assertSetEqual(set(result), set(["value1", "value2"]))
[docs] def test_no_namespace_no_attrib_multiple_levels(self): """ The path can have several levels, separated by '/' characters. """ doc = JSONData(json.loads(""" { "data": [ { "key": "value1" } ] } """)) path = "data/key" self.assertEqual(parse_json_path(path)(doc), "value1")
[docs] def test_no_namespace_no_attrib_multiple_levels_multivalue(self): """ Iteration can happen at any level of the path. An asterisk following a path element indicates that the element belongs to an object inside of an array. This is slightly counterintuitive, but keeps the syntax consistent with the XML syntax. """ doc = JSONData(json.loads(""" { "data": [ { "key": { "more": "data" } }, { "key": { "more": "awesome" } } ] } """)) path = "data/key*/more" result = parse_json_path(path)(doc) self.assertSetEqual(set(result), set(["data", "awesome"]))
# class TestNativeVIAFDocument(unittest.TestCase): # def test_get(self): # doc = ET.parse('tests/mock_responses/viaf_get.xml') # config =