Skip to content

Commit d266f73

Browse files
committed
adds jcr_helpers module. includes get_jcr_content() and get_page_hierarchy() helper methods
1 parent 1694918 commit d266f73

File tree

3 files changed

+494
-2
lines changed

3 files changed

+494
-2
lines changed

setup.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import os
21
from setuptools import setup
32

43

@@ -11,7 +10,7 @@ def readme():
1110

1211
setup(
1312
name="theark",
14-
version="0.0.9",
13+
version="0.1.0",
1514
author="meltmedia QA Team",
1615
author_email="[email protected]",
1716
description="meltQA Tools Common Library.",

tests/test_jcr_helpers.py

+356
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,356 @@
1+
import unittest
2+
from mock import patch, Mock, call
3+
from the_ark import jcr_helpers
4+
import requests.exceptions
5+
6+
TEST_URL = "http://www.test.com"
7+
TEST_PATH = "/content/path"
8+
9+
JCR_NON_PAGE = {
10+
"jcr:primaryType": "nt:unstructured",
11+
"jcr:lastModifiedBy": "admin",
12+
"jcr:lastModified": "Thu Dec 08 2016 00:19:17 GMT+0000"
13+
}
14+
15+
JCR_GREATGRANDCHILD = {
16+
"jcr:primaryType": "cq:Page",
17+
"jcr:createdBy": "admin",
18+
"jcr:created": "Thu Jan 18 2018 00:17:21 GMT+0000",
19+
"jcr:content": {
20+
"jcr:primaryType": "cq:PageContent",
21+
"jcr:createdBy": "admin",
22+
"jcr:title": "Great Grandchild 1",
23+
"jcr:versionHistory": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
24+
"cq:template": "/greatgrandchild",
25+
"jcr:lastModifiedBy": "admin",
26+
"jcr:predecessors": [
27+
"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
28+
],
29+
"jcr:created": "Thu Jan 18 2018 00:17:21 GMT+0000",
30+
"cq:lastModified": "Wed Jan 11 2017 16:15:23 GMT+0000",
31+
"jcr:baseVersion": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
32+
"jcr:lastModified": "Wed Jan 11 2017 16:15:23 GMT+0000",
33+
"jcr:uuid": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
34+
"sling:resourceType": "/greatgrandchild",
35+
"cq:lastModifiedBy": "admin"
36+
}
37+
}
38+
39+
JCR_GRANDCHILD_1 = {
40+
"jcr:primaryType": "cq:Page",
41+
"jcr:createdBy": "admin",
42+
"jcr:created": "Thu Jan 18 2018 00:17:21 GMT+0000",
43+
"jcr:content": {
44+
"jcr:primaryType": "cq:PageContent",
45+
"jcr:createdBy": "admin",
46+
"jcr:title": "Grandchild 1",
47+
"jcr:versionHistory": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
48+
"cq:template": "/grandchild1",
49+
"jcr:lastModifiedBy": "admin",
50+
"jcr:predecessors": [
51+
"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
52+
],
53+
"jcr:created": "Thu Jan 18 2018 00:17:21 GMT+0000",
54+
"cq:lastModified": "Wed Jan 11 2017 16:15:23 GMT+0000",
55+
"jcr:baseVersion": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
56+
"jcr:lastModified": "Wed Jan 11 2017 16:15:23 GMT+0000",
57+
"jcr:uuid": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
58+
"sling:resourceType": "/grandchild1",
59+
"cq:lastModifiedBy": "admin"
60+
},
61+
"great_grandchild1": JCR_GREATGRANDCHILD
62+
}
63+
64+
JCR_GRANDCHILD_2 = {
65+
"jcr:primaryType": "cq:Page",
66+
"jcr:createdBy": "admin",
67+
"jcr:created": "Thu Jan 18 2018 00:17:21 GMT+0000",
68+
"jcr:content": {
69+
"jcr:primaryType": "cq:PageContent",
70+
"jcr:createdBy": "admin",
71+
"jcr:title": "Grandchild 2",
72+
"jcr:versionHistory": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
73+
"cq:template": "/grandchild2",
74+
"jcr:lastModifiedBy": "admin",
75+
"jcr:predecessors": [
76+
"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
77+
],
78+
"jcr:created": "Thu Jan 18 2018 00:17:21 GMT+0000",
79+
"cq:lastModified": "Wed Jan 11 2017 16:15:23 GMT+0000",
80+
"jcr:baseVersion": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
81+
"jcr:lastModified": "Wed Jan 11 2017 16:15:23 GMT+0000",
82+
"jcr:uuid": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
83+
"sling:resourceType": "/grandchild2",
84+
"cq:lastModifiedBy": "admin"
85+
},
86+
"nonpage3": JCR_NON_PAGE,
87+
}
88+
89+
JCR_CHILD_1 = {
90+
"jcr:primaryType": "cq:Page",
91+
"jcr:createdBy": "admin",
92+
"jcr:created": "Mon Feb 19 2018 00:17:26 GMT+0000",
93+
"jcr:content": {
94+
"jcr:primaryType": "cq:PageContent",
95+
"jcr:createdBy": "admin",
96+
"jcr:title": "Child 1",
97+
"jcr:versionHistory": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
98+
"cq:template": "/child",
99+
"jcr:lastModifiedBy": "admin",
100+
"jcr:predecessors": [
101+
"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
102+
],
103+
"jcr:created": "Fri Dec 09 2016 18:34:21 GMT+0000",
104+
"cq:lastModified": "Mon Feb 06 2017 17:33:11 GMT+0000",
105+
"jcr:baseVersion": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
106+
"jcr:uuid": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
107+
"sling:resourceType": "/child",
108+
"cq:lastModifiedBy": "admin"
109+
}
110+
}
111+
112+
JCR_CHILD_2 = {
113+
"jcr:primaryType": "cq:Page",
114+
"jcr:createdBy": "admin",
115+
"jcr:created": "Thu Jan 18 2018 00:17:21 GMT+0000",
116+
"jcr:content": {
117+
"jcr:primaryType": "cq:PageContent",
118+
"jcr:createdBy": "admin",
119+
"jcr:title": "Child 2",
120+
"jcr:versionHistory": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
121+
"cq:template": "/child2",
122+
"jcr:lastModifiedBy": "admin",
123+
"jcr:predecessors": [
124+
"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
125+
],
126+
"jcr:created": "Thu Jan 18 2018 00:17:21 GMT+0000",
127+
"cq:lastModified": "Wed Nov 08 2017 18:22:25 GMT+0000",
128+
"jcr:description": "testing",
129+
"jcr:baseVersion": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
130+
"jcr:lastModified": "Thu Jan 12 2017 18:40:21 GMT+0000",
131+
"jcr:uuid": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
132+
"sling:resourceType": "/child",
133+
"cq:lastModifiedBy": "admin"
134+
},
135+
"nonpage1": JCR_NON_PAGE,
136+
"nonpage2": JCR_NON_PAGE,
137+
"grandchild1": JCR_GRANDCHILD_1,
138+
"grandchild2": JCR_GRANDCHILD_2
139+
}
140+
141+
142+
class UtilsTestCase(unittest.TestCase):
143+
144+
def setUp(self):
145+
146+
self.jcr_content_infinity_dict = {
147+
"jcr:primaryType": "cq:Page",
148+
"jcr:createdBy": "admin",
149+
"jcr:created": "Thu Jan 18 2018 00:17:21 GMT+0000",
150+
"jcr:content": {
151+
"jcr:primaryType": "cq:PageContent",
152+
"jcr:createdBy": "admin",
153+
"jcr:title": "Root",
154+
"jcr:versionHistory": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
155+
"cq:template": "/root",
156+
"jcr:lastModifiedBy": "admin",
157+
"jcr:predecessors": [
158+
"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
159+
],
160+
"jcr:created": "Thu Jan 18 2018 00:17:21 GMT+0000",
161+
"cq:lastModified": "Mon Apr 24 2017 20:44:33 GMT+0000",
162+
"jcr:baseVersion": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
163+
"jcr:lastModified": "Mon Apr 24 2017 20:44:33 GMT+0000",
164+
"jcr:uuid": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
165+
"sling:resourceType": "/root",
166+
"cq:designPath": "/etc/designs/test",
167+
"cq:lastModifiedBy": "admin"
168+
},
169+
"nonpage": JCR_NON_PAGE,
170+
"child1": JCR_CHILD_1,
171+
"child2": JCR_CHILD_2
172+
}
173+
174+
self.jcr_content_infinity_list = [
175+
"{}.2.json".format(TEST_PATH),
176+
"{}.1.json".format(TEST_PATH),
177+
"{}.0.json"
178+
]
179+
180+
self.page_hierarchy_with_jcr_content = {
181+
'{}.html'.format(TEST_PATH): {
182+
'children': ['{}/child1.html'.format(TEST_PATH), '{}/child2.html'.format(TEST_PATH)],
183+
'template': self.jcr_content_infinity_dict["jcr:content"]["cq:template"],
184+
'depth': 0,
185+
'parent': False,
186+
'jcr_content': self.jcr_content_infinity_dict["jcr:content"],
187+
'url': '{}{}.html'.format(TEST_URL, TEST_PATH)
188+
},
189+
'{}/child1.html'.format(TEST_PATH): {
190+
'children': [],
191+
'template': JCR_CHILD_1["jcr:content"]["cq:template"],
192+
'depth': 1,
193+
'parent': '{}.html'.format(TEST_PATH),
194+
'jcr_content': JCR_CHILD_1["jcr:content"],
195+
'url': '{}{}/child1.html'.format(TEST_URL, TEST_PATH)
196+
},
197+
'{}/child2.html'.format(TEST_PATH): {
198+
'children': ['{}/child2/grandchild1.html'.format(TEST_PATH),
199+
'{}/child2/grandchild2.html'.format(TEST_PATH)],
200+
'template': JCR_CHILD_2["jcr:content"]["cq:template"],
201+
'depth': 1,
202+
'parent': '{}.html'.format(TEST_PATH),
203+
'jcr_content': JCR_CHILD_2["jcr:content"],
204+
'url': '{}{}/child2.html'.format(TEST_URL, TEST_PATH)
205+
},
206+
'{}/child2/grandchild1.html'.format(TEST_PATH): {
207+
'children': ['{}/child2/grandchild1/great_grandchild1.html'.format(TEST_PATH)],
208+
'template': JCR_GRANDCHILD_1["jcr:content"]["cq:template"],
209+
'depth': 2,
210+
'parent': '{}/child2.html'.format(TEST_PATH),
211+
'jcr_content': JCR_GRANDCHILD_1["jcr:content"],
212+
'url': '{}{}/child2/grandchild1.html'.format(TEST_URL, TEST_PATH)
213+
},
214+
'{}/child2/grandchild1/great_grandchild1.html'.format(TEST_PATH): {
215+
'children': [],
216+
'template': JCR_GREATGRANDCHILD["jcr:content"]["cq:template"],
217+
'depth': 3,
218+
'parent': '{}/child2/grandchild1.html'.format(TEST_PATH),
219+
'jcr_content': JCR_GREATGRANDCHILD["jcr:content"],
220+
'url': '{}{}/child2/grandchild1/great_grandchild1.html'.format(TEST_URL, TEST_PATH)
221+
},
222+
'{}/child2/grandchild2.html'.format(TEST_PATH): {
223+
'children': [],
224+
'template': JCR_GRANDCHILD_2["jcr:content"]["cq:template"],
225+
'depth': 2,
226+
'parent': '{}/child2.html'.format(TEST_PATH),
227+
'jcr_content': JCR_GRANDCHILD_2["jcr:content"],
228+
'url': '{}{}/child2/grandchild2.html'.format(TEST_URL, TEST_PATH)
229+
}
230+
}
231+
232+
self.page_hierarchy = {
233+
k: {x: v[x] for x in v if x != "jcr_content"} for k, v in self.page_hierarchy_with_jcr_content.iteritems()
234+
}
235+
236+
@patch('requests.get')
237+
def test_get_jcr_content_default_depth(self, requests_get):
238+
mock_response = Mock()
239+
mock_response.json.return_value = JCR_CHILD_1
240+
requests_get.return_value = mock_response
241+
242+
resp = jcr_helpers.get_jcr_content(root_url=TEST_URL, root_path=TEST_PATH)
243+
requests_get.assert_called_once_with("{}{}.0.json".format(TEST_URL, TEST_PATH))
244+
self.assertEqual(resp, JCR_CHILD_1)
245+
246+
@patch('requests.get')
247+
def test_get_jcr_content_provided_depth(self, requests_get):
248+
mock_response = Mock()
249+
mock_response.json.return_value = self.jcr_content_infinity_dict
250+
requests_get.return_value = mock_response
251+
252+
test_url = "{}/".format(TEST_URL)
253+
test_path = TEST_PATH[1:]
254+
resp = jcr_helpers.get_jcr_content(root_url=test_url, root_path=test_path, depth=100)
255+
requests_get.assert_called_once_with("{}{}.100.json".format(test_url[:-1], "/{}".format(test_path)))
256+
self.assertEqual(resp, self.jcr_content_infinity_dict)
257+
258+
@patch('requests.get')
259+
def test_get_jcr_content_infinity(self, requests_get):
260+
mock_response = Mock()
261+
mock_response.json.return_value = self.jcr_content_infinity_dict
262+
requests_get.return_value = mock_response
263+
264+
resp = jcr_helpers.get_jcr_content(root_url=TEST_URL, root_path=TEST_PATH, infinity=True)
265+
requests_get.assert_called_once_with("{}{}.infinity.json".format(TEST_URL, TEST_PATH))
266+
self.assertEqual(resp, self.jcr_content_infinity_dict)
267+
268+
@patch('requests.get')
269+
def test_get_jcr_content_missing_scheme(self, requests_get):
270+
mock_response = Mock()
271+
mock_response.json.return_value = JCR_CHILD_1
272+
requests_get.return_value = mock_response
273+
274+
test_url = TEST_URL[7:]
275+
test_path = "{}.html".format(TEST_PATH)
276+
resp = jcr_helpers.get_jcr_content(root_url=test_url, root_path=test_path)
277+
requests_get.assert_called_once_with("http://{}{}.0.json".format(test_url, test_path[:-5]))
278+
self.assertEqual(resp, JCR_CHILD_1)
279+
280+
@patch('requests.get')
281+
def test_get_jcr_content_request_exception(self, requests_get):
282+
requests_get.side_effect = requests.exceptions.ConnectionError()
283+
self.assertRaises(
284+
jcr_helpers.JCRHelperException, jcr_helpers.get_jcr_content,
285+
root_url=TEST_URL, root_path=TEST_PATH, infinity=True)
286+
287+
@patch('requests.get')
288+
def test_get_jcr_content_unexpected_jcr_content_response(self, requests_get):
289+
mock_response = Mock()
290+
mock_response.json.side_effect = ValueError()
291+
requests_get.return_value = mock_response
292+
self.assertRaises(
293+
jcr_helpers.JCRHelperException, jcr_helpers.get_jcr_content,
294+
root_url=TEST_URL, root_path=TEST_PATH, infinity=True)
295+
296+
@patch('requests.get')
297+
def test_get_jcr_content_unexpected_error(self, requests_get):
298+
requests_get.return_value = {}
299+
self.assertRaises(
300+
jcr_helpers.JCRHelperException, jcr_helpers.get_jcr_content,
301+
root_url="", root_path=TEST_PATH, infinity=True)
302+
303+
@patch('the_ark.jcr_helpers.get_jcr_content')
304+
def test_get_page_hierarchy_non_paginated(self, get_jcr_content):
305+
get_jcr_content.return_value = self.jcr_content_infinity_dict
306+
resp = jcr_helpers.get_page_hierarchy(TEST_URL, TEST_PATH)
307+
get_jcr_content.assert_called_once_with(root_url=TEST_URL, root_path=TEST_PATH, infinity=True)
308+
self.assertEqual(resp, self.page_hierarchy)
309+
310+
@patch('the_ark.jcr_helpers.get_jcr_content')
311+
def test_get_page_hierarchy_paginated(self, get_jcr_content):
312+
get_jcr_content.side_effect = [self.jcr_content_infinity_list, self.jcr_content_infinity_dict]
313+
resp = jcr_helpers.get_page_hierarchy(TEST_URL, TEST_PATH)
314+
get_jcr_content.assert_has_calls([
315+
call(root_url=TEST_URL, root_path=TEST_PATH, infinity=True),
316+
call(root_url=TEST_URL, root_path=TEST_PATH, depth=self.jcr_content_infinity_list[0].split('.')[1])
317+
])
318+
self.assertEqual(resp, self.page_hierarchy)
319+
320+
@patch('the_ark.jcr_helpers.get_jcr_content')
321+
def test_get_page_hierarchy_missing_scheme(self, get_jcr_content):
322+
get_jcr_content.return_value = self.jcr_content_infinity_dict
323+
324+
test_url = TEST_URL[7:]
325+
test_path = "{}.html".format(TEST_PATH)
326+
resp = jcr_helpers.get_page_hierarchy(root_url=test_url, root_path=test_path)
327+
get_jcr_content.assert_called_once_with(root_url=TEST_URL, root_path=TEST_PATH, infinity=True)
328+
self.assertEqual(resp, self.page_hierarchy)
329+
330+
@patch('the_ark.jcr_helpers.get_jcr_content')
331+
def test_get_page_hierarchy_with_jcr_content(self, get_jcr_content):
332+
get_jcr_content.return_value = self.jcr_content_infinity_dict
333+
resp = jcr_helpers.get_page_hierarchy(TEST_URL, TEST_PATH, include_jcr_content=True)
334+
get_jcr_content.assert_called_once_with(root_url=TEST_URL, root_path=TEST_PATH, infinity=True)
335+
self.assertEqual(resp, self.page_hierarchy_with_jcr_content)
336+
337+
@patch('the_ark.jcr_helpers.get_jcr_content')
338+
def test_get_page_hierarchy_unexpected_jcr_content(self, get_jcr_content):
339+
get_jcr_content.return_value = {}
340+
self.assertRaises(
341+
jcr_helpers.JCRHelperException, jcr_helpers.get_page_hierarchy,
342+
root_url=TEST_URL, root_path=TEST_PATH)
343+
344+
def test_jcrhelperexception_to_string(self):
345+
jcr_exc = jcr_helpers.JCRHelperException(msg="error message")
346+
self.assertIn("error message", str(jcr_exc))
347+
348+
def test_jcrhelperexception_with_stacktrace(self):
349+
jcr_exc = jcr_helpers.JCRHelperException(msg="error message", stacktrace="test")
350+
self.assertIn("test", str(jcr_exc))
351+
352+
def test_exception_with_details(self):
353+
details = {"test": "testing"}
354+
jcr_exc = jcr_helpers.JCRHelperException(msg="error message", details=details)
355+
self.assertIn("test: testing", str(jcr_exc))
356+
self.assertIn("Exception Details", str(jcr_exc))

0 commit comments

Comments
 (0)