Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

project delete & get endpoints #107

Merged
merged 8 commits into from
Jan 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions CmixAPIClient/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,38 @@ def fetch_raw_results(self, survey_id, payload):
response = requests.post(url, headers=self._authentication_headers, json=payload)
return response.json()

def api_get(self, endpoint, error=''):
self.check_auth_headers()
url = '{}/{}'.format(CMIX_SERVICES['survey'][self.url_type], endpoint)
response = requests.get(url, headers=self._authentication_headers)
if response.status_code != 200:
if '' == error:
error = 'CMIX returned a non-200 response code'
raise CmixError(
'{}: {} and error {}'.format(
error,
response.status_code,
response.text
)
)
return response.json()

def api_delete(self, endpoint, error=''):
self.check_auth_headers()
url = '{}/{}'.format(CMIX_SERVICES['survey'][self.url_type], endpoint)
response = requests.delete(url, headers=self._authentication_headers)
if response.status_code != 200:
if '' == error:
error = 'CMIX returned a non-200 response code'
raise CmixError(
'{}: {} and error {}'.format(
error,
response.status_code,
response.text
)
)
return response.json()

def get_surveys(self, status, *args, **kwargs):
'''kwargs:

Expand Down Expand Up @@ -402,3 +434,9 @@ def get_survey_simulations(self, survey_id):
)
)
return simulations_response.json()

def get_projects(self):
project_endpoint = 'projects'
project_error = 'CMIX returned a non-200 response code while getting projects'
project_response = self.api_get(project_endpoint, project_error)
return project_response
78 changes: 78 additions & 0 deletions CmixAPIClient/project.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from .error import CmixError


class CmixProject(object):
def __init__(self, client, project_id):
if None in [client, project_id]:
raise CmixError("Client and project id are required.")
self.client = client
self.project_id = project_id

def delete_project(self):
project_endpoint = 'projects/{}'.format(self.project_id)
project_error = 'CMIX returned a non-200 response code while deleting project'
project_response = self.client.api_delete(project_endpoint, project_error)
return project_response

def delete_group(self, group_id):
project_endpoint = 'projects/{}/groups/{}'.format(self.project_id, group_id)
project_error = 'CMIX returned a non-200 response code while deleting group'
project_response = self.client.api_delete(project_endpoint, project_error)
return project_response

def get_project(self):
project_endpoint = 'projects/{}'.format(self.project_id)
project_error = 'CMIX returned a non-200 response code while getting project'
project_response = self.client.api_get(project_endpoint, project_error)
return project_response

def get_sources(self):
project_endpoint = 'projects/{}/sources'.format(self.project_id)
project_error = 'CMIX returned a non-200 response code while getting project sources'
project_response = self.client.api_get(project_endpoint, project_error)
return project_response

def get_groups(self):
project_endpoint = 'projects/{}/groups'.format(self.project_id)
project_error = 'CMIX returned a non-200 response code while getting project groups'
project_response = self.client.api_get(project_endpoint, project_error)
return project_response

def get_links(self):
project_endpoint = 'projects/{}/links'.format(self.project_id)
project_error = 'CMIX returned a non-200 response code while getting project links'
project_response = self.client.api_get(project_endpoint, project_error)
return project_response

def get_full_links(self):
project_endpoint = 'projects/{}/full-links'.format(self.project_id)
project_error = 'CMIX returned a non-200 response code while getting project full links'
project_response = self.client.api_get(project_endpoint, project_error)
return project_response

def get_locales(self):
project_endpoint = 'projects/{}/locales'.format(self.project_id)
project_error = 'CMIX returned a non-200 response code while getting project locales'
project_response = self.client.api_get(project_endpoint, project_error)
return project_response

def get_markup_files(self):
project_endpoint = 'projects/{}/markup-files'.format(self.project_id)
project_error = 'CMIX returned a non-200 response code while getting project markup files'
project_response = self.client.api_get(project_endpoint, project_error)
return project_response

def get_respondent_links(self):
project_endpoint = 'projects/{}/respondent-links'.format(self.project_id)
project_error = 'CMIX returned a non-200 response code while getting project respondent links'
project_response = self.client.api_get(project_endpoint, project_error)
return project_response

def get_surveys(self):
project_endpoint = 'projects/{}/surveys'.format(self.project_id)
project_error = 'CMIX returned a non-200 response code while getting project surveys'
project_response = self.client.api_get(project_endpoint, project_error)
return project_response
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ A Python client library for the [Dynata Cmix API](https://wiki2.criticalmix.net/

## Supported API Functions

### CmixAPI
authenticate(*args, **kwargs)
fetch_banner_filter(survey_id, question_a, question_b, response_id)
fetch_raw_results(survey_id, payload)
get_projects()
get_surveys(status, *args, **kwargs)
get_survey_data_layouts(survey_id)
get_survey_definition(survey_id)
Expand All @@ -46,6 +48,20 @@ A Python client library for the [Dynata Cmix API](https://wiki2.criticalmix.net/
update_project(project_id, status=None)
create_survey(xml_string)

### CmixProject

delete_group(group_id)
delete_project()
get_full_links()
get_groups()
get_links()
get_locales()
get_markup_files()
get_project()
get_respondent_links()
get_sources()
get_surveys()

## Contributing

Information on [contributing](https://github.com/dynata/python-cmixapi-client/blob/dev/CONTRIBUTING.md) to this python library.
Expand Down
30 changes: 30 additions & 0 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,33 @@ def setUp(self):
self.cmix_api = default_cmix_api()
self.cmix_api._authentication_headers = {'Authorization': 'Bearer test'}
self.survey_id = 1337
self.project_id = 1492

def helper_get(self, function_name, endpoint):
func = getattr(self.cmix_api, function_name)

# success case
with mock.patch('CmixAPIClient.api.requests') as mock_request:
mock_get = mock.Mock()
mock_get.status_code = 200
mock_get.json.return_value = {}
mock_request.get.return_value = mock_get

func()

base_url = CMIX_SERVICES['survey']['BASE_URL']
project_url = '{}/{}'.format(base_url, endpoint)
mock_request.get.assert_any_call(project_url, headers=self.cmix_api._authentication_headers)

# error case (survey not found)
with mock.patch('CmixAPIClient.api.requests') as mock_request:
mock_get = mock.Mock()
mock_get.status_code = 404
mock_get.json.return_value = {}
mock_request.get.return_value = mock_get

with self.assertRaises(CmixError):
func()

def test_cmix_authentication_check(self):
with self.assertRaises(CmixError):
Expand Down Expand Up @@ -424,3 +451,6 @@ def test_get_survey_simulations(self):

with self.assertRaises(CmixError):
self.cmix_api.get_survey_simulations(self.survey_id)

def test_get_projects(self):
self.helper_get('get_projects', 'projects')
110 changes: 110 additions & 0 deletions tests/test_project.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# -*- coding: utf-8 -*-
from __future__ import print_function
from __future__ import unicode_literals
import mock

from unittest import TestCase
from CmixAPIClient.api import CMIX_SERVICES
from CmixAPIClient.project import CmixProject
from CmixAPIClient.error import CmixError
from .test_api import default_cmix_api


class TestCmixProject(TestCase):
def setUp(self):
self.cmix_api = default_cmix_api()
self.cmix_api._authentication_headers = {'Authorization': 'Bearer test'}
self.project_id = 1492

def helper_get(self, function_name, endpoint):
project = CmixProject(self.cmix_api, self.project_id)
func = getattr(project, function_name)

# success case
with mock.patch('CmixAPIClient.api.requests') as mock_request:
mock_get = mock.Mock()
mock_get.status_code = 200
mock_get.json.return_value = {}
mock_request.get.return_value = mock_get

func()

base_url = CMIX_SERVICES['survey']['BASE_URL']
project_url = '{}/projects{}'.format(base_url, endpoint)
mock_request.get.assert_any_call(project_url, headers=self.cmix_api._authentication_headers)

# error case (survey not found)
with mock.patch('CmixAPIClient.api.requests') as mock_request:
mock_get = mock.Mock()
mock_get.status_code = 404
mock_get.json.return_value = {}
mock_request.get.return_value = mock_get

with self.assertRaises(CmixError):
func()

def helper_delete(self, function_name, endpoint, group_id=None):
project = CmixProject(self.cmix_api, self.project_id)
func = getattr(project, function_name)

# success case
with mock.patch('CmixAPIClient.api.requests') as mock_request:
mock_delete = mock.Mock()
mock_delete.status_code = 200
mock_delete.json.return_value = {}
mock_request.delete.return_value = mock_delete

if group_id is not None:
func(group_id)
else:
func()

base_url = CMIX_SERVICES['survey']['BASE_URL']
project_url = '{}/projects{}'.format(base_url, endpoint)
mock_request.delete.assert_any_call(project_url, headers=self.cmix_api._authentication_headers)

# error case (survey not found)
with mock.patch('CmixAPIClient.api.requests') as mock_request:
mock_delete = mock.Mock()
mock_delete.status_code = 404
mock_delete.json.return_value = {}
mock_request.delete.return_value = mock_delete

with self.assertRaises(CmixError):
if group_id is not None:
func(group_id)
else:
func()

def test_delete_group(self):
self.helper_delete('delete_group', '/{}/groups/{}'.format(self.project_id, 13), 13)

def test_delete_project(self):
self.helper_delete('delete_project', '/{}'.format(self.project_id))

def test_get_project(self):
self.helper_get('get_project', '/{}'.format(self.project_id))

def test_get_sources(self):
self.helper_get('get_sources', '/{}/sources'.format(self.project_id))

def test_get_groups(self):
self.helper_get('get_groups', '/{}/groups'.format(self.project_id))

def test_get_links(self):
self.helper_get('get_links', '/{}/links'.format(self.project_id))

def test_get_full_links(self):
self.helper_get('get_full_links', '/{}/full-links'.format(self.project_id))

def test_get_locales(self):
self.helper_get('get_locales', '/{}/locales'.format(self.project_id))

def test_get_markup_files(self):
self.helper_get('get_markup_files', '/{}/markup-files'.format(self.project_id))

def test_get_respondent_links(self):
self.helper_get('get_respondent_links', '/{}/respondent-links'.format(self.project_id))

def test_get_surveys(self):
self.helper_get('get_surveys', '/{}/surveys'.format(self.project_id))