Skip to content

Commit

Permalink
adding get_collabs and get_collab_by_id API
Browse files Browse the repository at this point in the history
  • Loading branch information
aayushks committed Oct 15, 2017
1 parent 7d7def8 commit edb7ef8
Show file tree
Hide file tree
Showing 8 changed files with 167 additions and 27 deletions.
10 changes: 9 additions & 1 deletion pirant/app.py
Expand Up @@ -21,4 +21,12 @@ def get_weekly_rants(self, sort, skip):

def search_rants_by_keyword(self, keyword):
response = self.RequestHandler.search_rants_by_keyword(keyword)
return self.ResponseHandler.search_rants_by_keyword_build_response(response)
return self.ResponseHandler.search_rants_by_keyword_build_response(response)

def get_collabs(self, skip, limit):
response = self.RequestHandler.get_collabs(skip, limit)
return self.ResponseHandler.get_collabs_build_response(response)

def get_collab_by_id(self, collab_id):
response = self.RequestHandler.get_rant_by_id(collab_id)
return self.ResponseHandler.get_rant_by_id_build_response(response)
12 changes: 11 additions & 1 deletion pirant/handlers.py
Expand Up @@ -26,13 +26,18 @@ def search_rants_by_keyword_build_response(self, response):
deserialized = self.SearchResponse.deserialize(json_string)
return deserialized

def get_collabs_build_response(self, response):
json_string = json.loads(response.content)
deserialized = self.RantsResponse.deserialize(json_string)
return deserialized

class RequestHandler:

def __init__(self):
self.UrlBuilder = URLBuilder()

def get_rants(self, sort, limit, skip):
url = self.UrlBuilder.get_rant_url(sort, limit, skip)
url = self.UrlBuilder.get_rants_url(sort, limit, skip)
response = requests.get(url)
return response

Expand All @@ -49,4 +54,9 @@ def get_weekly_rants(self, sort, skip):
def search_rants_by_keyword(self, keyword):
url = self.UrlBuilder.search_rants_by_keywords(keyword)
response = requests.get(url)
return response

def get_collabs(self, skip, sort):
url = self.UrlBuilder.get_collabs_url(skip, sort)
response = requests.get(url)
return response
13 changes: 12 additions & 1 deletion pirant/models.py
Expand Up @@ -40,13 +40,24 @@ class Rant(colander.MappingSchema):
num_comments = colander.SchemaNode(colander.Int())
user_username = colander.SchemaNode(colander.String())
user_userscore = colander.SchemaNode(colander.Int(), missing=colander.drop)
edited = colander.SchemaNode(colander.Boolean(), missing=colander.drop)

# The below attributes only exist for collabs
link = colander.SchemaNode(colander.String(), missing=colander.drop)
c_type = colander.SchemaNode(colander.Int(), missing=colander.drop)
c_type_long = colander.SchemaNode(colander.String(), missing=colander.drop)
c_description = colander.SchemaNode(colander.String(), missing=colander.drop)
c_tect_stack = colander.SchemaNode(colander.String(), missing=colander.drop)
c_team_size = colander.SchemaNode(colander.Int(), missing=colander.drop)
c_url = colander.SchemaNode(colander.String(), missing=colander.drop)


class Rants(colander.SequenceSchema):
rant = Rant()

class RantsResponse(colander.MappingSchema):
rants = Rants()
news = News()
news = News(missing=colander.drop)
success = colander.SchemaNode(colander.Boolean(), missing=colander.drop)
error = colander.SchemaNode(colander.Boolean(), missing=colander.drop)
settings = colander.SchemaNode(colander.String(), missing=colander.drop)
Expand Down
22 changes: 14 additions & 8 deletions pirant/urlbuilder.py
@@ -1,32 +1,38 @@
class URLBuilder:
def __init__(self):
self.APP_VERSION = 3
self.BASE_URL = "https://www.devrant.io/api"
self.RANTS_URL = "%s/devrant/rants?sort=%s&limit=%d&skip=%d&app=%d"
self.WEEKLY_RANTS_URL = "%s/devrant/weekly-rants?sort=%s&skip=%d&app=%d"
self.RANT_PATH = "%s/devrant/rants/%d?app=%d"
self.SEARCH_PATH = "%s/devrant/search?term=%s&app=%d"
self.BASE_URL = "https://www.devrant.io/api/devrant"
self.RANTS_URL = "%s/rants?sort=%s&limit=%d&skip=%d&app=%d"
self.WEEKLY_RANTS_URL = "%s/weekly-rants?sort=%s&skip=%d&app=%d"
self.RANT_URL = "%s/rants/%d?app=%d"
self.SEARCH_URL = "%s/search?term=%s&app=%d"
self.COLLABS_URL = "%s/collabs?app=%d&skip=%d&limit=%d"
self.SORT_TOP = "top"
self.SORT_ALGO = "algo"
self.SORT_RECENT = "recent"
self.VALID_SORTS = [self.SORT_ALGO, self.SORT_RECENT, self.SORT_TOP]

def get_rant_url(self, sort, limit, skip):
def get_rants_url(self, sort, limit, skip):
sort = self.validate_sort_input(self, sort)
limit = self.validate_int_input(limit)
skip = self.validate_int_input(skip)
return str(self.RANTS_URL % (self.BASE_URL, sort, limit, skip, self.APP_VERSION))

def get_rant_by_id_url(self, rant_id):
return str(self.RANT_PATH % (self.BASE_URL, rant_id, self.APP_VERSION))
return str(self.RANT_URL % (self.BASE_URL, rant_id, self.APP_VERSION))

def get_weekly_rant_url(self, sort, skip):
sort = self.validate_sort_input(self, sort)
skip = self.validate_int_input(skip)
return str(self.WEEKLY_RANTS_URL % (self.BASE_URL, sort, skip, self.APP_VERSION))

def search_rants_by_keywords(self, keyword):
return str(self.SEARCH_PATH % (self.BASE_URL, keyword, self.APP_VERSION))
return str(self.SEARCH_URL % (self.BASE_URL, keyword, self.APP_VERSION))

def get_collabs_url(self, skip, limit):
limit = self.validate_int_input(limit)
skip = self.validate_int_input(skip)
return str(self.COLLABS_URL % (self.BASE_URL, self.APP_VERSION, skip, limit))

@staticmethod
def validate_sort_input(self, sort_type):
Expand Down
11 changes: 10 additions & 1 deletion samples/Demo.py
Expand Up @@ -26,4 +26,13 @@
searchResult = devrant.search_rants_by_keyword("devrant")
print searchResult['results'][1]['text']
print searchResult['results'][1]['attached_image']['url']
print searchResult['results'][1]['user_avatar']['i']
print searchResult['results'][1]['user_avatar']['i']

# Get Top 5 collabs
collabsResult = devrant.get_collabs(0, 5)
print collabsResult['rants'][0]['c_type_long']

# Get Collab and all its comments given Collab Id
collab= devrant.get_collab_by_id(913738)
print collab['rant']['c_description']
print collab['comments'][0]['body']
79 changes: 75 additions & 4 deletions tests/test_app.py
Expand Up @@ -9,7 +9,7 @@ def setUp(self):
self.devrant = DevRant()

@patch('pirant.handlers.RequestHandler.get_rants')
def test_happyCaseGetRants(self, mock_get_rants_response):
def test_happy_case_get_rants(self, mock_get_rants_response):
test_content = {
'rants': [{
'id': 1234,
Expand Down Expand Up @@ -41,7 +41,7 @@ def test_happyCaseGetRants(self, mock_get_rants_response):
self.assertEqual(rants['rants'][0]['text'], 'Txt')

@patch('pirant.handlers.RequestHandler.get_rant_by_id')
def test_happyCaseGetRantById(self, mock_get_rant_by_id_response):
def test_happy_case_get_rant_by_id(self, mock_get_rant_by_id_response):
test_content = {
'rant': {
'id': 1234,
Expand Down Expand Up @@ -175,11 +175,82 @@ def test_happy_case_search_rants_by_keyword(self, mock_search_rants_by_keyword_r
test_content = json.dumps(test_content)
test_status_code = 200
test_keyword = "test"
mock_reponse = MockHttpResponse(test_content, test_status_code)
mock_search_rants_by_keyword_response.return_value = mock_reponse
mock_response = MockHttpResponse(test_content, test_status_code)
mock_search_rants_by_keyword_response.return_value = mock_response
searchResults = self.devrant.search_rants_by_keyword(test_keyword)
self.assertTrue(mock_search_rants_by_keyword_response.called)
assert searchResults['success'] == True

@patch('pirant.handlers.RequestHandler.get_collabs')
def test_happy_case_get_collabs(self, mock_get_collabs_response):
test_content = {
"success": True,
"rants": [{
"id": 1,
"text": "Test text",
"score": 5,
"created_time": 1507872,
"attached_image": "",
"num_comments": 3,
"tags": [],
"vote_state": 0,
"edited": False,
"link": "collabs\/1\/test",
"rt": 2,
"rc": 2,
"c_type": 3,
"c_type_long": "Project idea",
"user_id": 3321,
"user_username": "test",
"user_score": 14,
"user_avatar": {
"b": "2awsd",
"i": "v-17_c-3_b-4_g-m_9-1_1-9-9_6-3_10-1_2-10_15-11_4-1.jpg"
}
}]
}
test_content = json.dumps(test_content)
test_status_code = 200
mock_response = MockHttpResponse(test_content, test_status_code)
mock_get_collabs_response.return_value = mock_response
collabs = self.devrant.get_collabs(0,1)
self.assertTrue(mock_get_collabs_response.called)
assert collabs['rants'][0]['id'] == 1

@patch('pirant.handlers.RequestHandler.get_rant_by_id')
def test_happy_case_get_collab_by_id(self, mock_get_rant_by_id_response):
test_content = {
'rant': {
'id': 1234,
'text': 'Txt',
'score': 111,
'created_time': 234432,
'user_id': 43289,
'num_comments': 121,
'user_username': 'user'
},
'comments': [{
'id': 1234,
'rant_id': 2345,
'body': 'test body',
'upvotes': 2,
'downvotes': 1,
'score': 10,
'created_time': 20102313123,
'user_id': 111,
'user_username': 'testUser',
'user_userscore': 56
}],
'success': True
}
test_content = json.dumps(test_content)
test_status_code = 200
mock_response = MockHttpResponse(test_content, test_status_code)
mock_get_rant_by_id_response.return_value = mock_response
rant = self.devrant.get_collab_by_id(2)
self.assertTrue(mock_get_rant_by_id_response.called)
assert rant['rant']['id'] == 1234
assert rant['comments'][0]['upvotes'] == 2

if __name__ == '__main__':
unittest.main()
15 changes: 13 additions & 2 deletions tests/test_handlers.py
Expand Up @@ -13,7 +13,7 @@ def setUp(self):
self.requestHandler = RequestHandler()

@patch('pirant.handlers.requests.get')
def test_successfulGetRantsResponse(self, mock_success_get_rants_request):
def test_successful_get_rants_response(self, mock_success_get_rants_request):
sortType = "top"
limit = 1
skip = 0
Expand All @@ -25,7 +25,7 @@ def test_successfulGetRantsResponse(self, mock_success_get_rants_request):
self.assertEqual(testJSONResponse, response.json())

@patch('pirant.handlers.requests.get')
def test_successfulGetRantByIdResponse(self, mock_success_get_rant_by_id_request):
def test_successful_get_rant_by_id_response(self, mock_success_get_rant_by_id_request):
rantId = 1
testJSONResponse = "{\"rant\": {\"id\": 1234,\"text\": \"Txt\",\"score\": 111,\"created_time\": 234432,\"user_id\": 43289,\"num_comments\": 121,\"user_username\": \"user\"},\"comments\": [{\"id\": 1234,\"rant_id\": 2345,\"body\": \"test body\",\"upvotes\": 2,\"downvotes\": 1,\"score\": 10,\"created_time\": 20102313123,\"user_id\": 111,\"user_username\": \"testUser\",\"user_userscore\": 56}],\"success\": True}"
mock_success_get_rant_by_id_request.return_value = Mock(ok=True)
Expand Down Expand Up @@ -55,6 +55,17 @@ def test_successful_search_rants_by_keyword(self, mock_success_search_rants_by_k
self.assertTrue(mock_success_search_rants_by_keyword.called)
self.assertEqual(test_json_response, response.json())

@patch('pirant.handlers.requests.get')
def test_successful_get_collabs(self, mock_success_get_collabs):
test_skip = 0
test_limit = 1
test_json_response = "{\"success\":true,\"rants\":[{\"id\":435,\"text\":\"Test Text\",\"score\":5,\"created_time\":15072,\"attached_image\":\"\",\"num_comments\":3,\"tags\":[],\"vote_state\":0,\"edited\":false,\"link\":\"collabs\/913738\/sample-link\",\"rt\":2,\"rc\":2,\"c_type\":3,\"c_type_long\":\"Project idea\",\"user_id\":9856,\"user_username\":\"testuser\",\"user_score\":14,\"user_avatar\":{\"b\":\"b9d\",\"i\":\"v-10-1_2-10_15-11_4-1.jpg\"}}]}"
mock_success_get_collabs.return_value = Mock(ok=True)
mock_success_get_collabs.return_value.json.return_value = test_json_response
response = self.requestHandler.get_collabs(test_skip, test_limit)
self.assertTrue(mock_success_get_collabs.called)
self.assertEqual(test_json_response, response.json())

class TestResponseHandler(unittest.TestCase):
"""
Unit tests for ResponseHandler class
Expand Down
32 changes: 23 additions & 9 deletions tests/test_urlbuilder.py
Expand Up @@ -11,25 +11,25 @@ def setUp(self):
self.test_limit = 10
self.test_skip = 1

def test_happy_case_get_rant_url(self):
def test_happy_case_get_rants_url(self):
expected_url = "https://www.devrant.io/api/devrant/rants?sort=top&limit=10&skip=1&app=3"
obtained_url = self.url_builder.get_rant_url(self.test_sort, self.test_limit, self.test_skip)
obtained_url = self.url_builder.get_rants_url(self.test_sort, self.test_limit, self.test_skip)
self.assertEqual(expected_url, obtained_url)

def test_empty_sort_type_get_rant_url(self):
def test_empty_sort_type_get_rants_url(self):
test_devrant_url = "https://www.devrant.io/api/devrant/rants?sort=top&limit=10&skip=1&app=3"
devrant_url = self.url_builder.get_rant_url("", self.test_limit, self.test_skip)
devrant_url = self.url_builder.get_rants_url("", self.test_limit, self.test_skip)
self.assertEqual(test_devrant_url, devrant_url)

def test_invalid_sort_type_get_rant_url(self):
def test_invalid_sort_type_get_rants_url(self):
test_sort = "dummy_sort"
with self.assertRaises(ValueError):
self.url_builder.get_rant_url(test_sort, self.test_limit, self.test_skip)
self.url_builder.get_rants_url(test_sort, self.test_limit, self.test_skip)

def test_invalid_limit_value_get_rant_url(self):
def test_invalid_limit_value_get_rants_url(self):
test_limit = -1
with self.assertRaises(ValueError):
self.url_builder.get_rant_url(self.test_sort, test_limit, self.test_skip)
self.url_builder.get_rants_url(self.test_sort, test_limit, self.test_skip)

def test_happy_case_get_rant_by_id_url(self):
test_devrant_url = "https://www.devrant.io/api/devrant/rants/2?app=3"
Expand All @@ -42,11 +42,25 @@ def test_id_must_be_int_get_rant_by_id_url(self):
with self.assertRaises(TypeError):
self.url_builder.get_rant_by_id_url(test_rant_id)

def test_idMustBeIntGetRantByIdUrl(self):
def test_id_must_b_int_get_rant_by_id_url(self):
test_rant_id = '2'
with self.assertRaises(TypeError):
self.url_builder.get_rant_by_id_url(test_rant_id)

def test_happy_case_get_collabs_url(self):
expected_url = "https://www.devrant.io/api/devrant/collabs?app=3&skip=1&limit=10"
actual_url = self.url_builder.get_collabs_url(self.test_skip, self.test_limit)
self.assertEqual(expected_url, actual_url)

def test_invalid_limit_value_get_collabs_url(self):
test_limit = -1
with self.assertRaises(ValueError):
self.url_builder.get_collabs_url(self.test_skip, test_limit)

def test_invalid_skip_value_get_collabs_url(self):
test_skip = -1
with self.assertRaises(ValueError):
self.url_builder.get_collabs_url(test_skip, self.test_limit)

if __name__ == '__main__':
unittest.main()

0 comments on commit edb7ef8

Please sign in to comment.