from unittest import mock from urllib import parse as urlparse import pytest from django.contrib.contenttypes.models import ContentType from requests.exceptions import HTTPError from passerelle.apps.clicrdv.models import ClicRdv from passerelle.base.models import AccessRight, ApiUser from tests.test_manager import login @pytest.fixture def connector(db): return ClicRdv.objects.create( slug='test', group_id='5242', apikey='test', username='test', password='test' ) def test_connector_is_legacy(connector, app, admin_user): app = login(app) # check the existing instance is displayed on homepage resp = app.get('/manage/', status=200) assert 'Clicrdv Agenda' in resp # and check it's not available on "add connector" page resp = resp.click('Add Connector') assert 'Clicrdv Agenda' not in resp @mock.patch('passerelle.utils.Request.request') def test_request_call(mocked_request, app, connector): mocked_request.json.return_value = 'foo' connector.request('bar') assert mocked_request.call_count == 1 req = mocked_request.call_args[0][1] assert req.startswith('https://sandbox.clicrdv.com/api/v1/groups/5242/bar') @mock.patch('passerelle.utils.Request.request') def test_interventionsets(mocked_request, app, connector): response = mock.Mock() response.json.return_value = { 'totalRecords': 2, 'records': [ { 'sort': 1, 'publicname': 'Une Demande de Passeport', 'name': 'Demande', 'id': 7032, 'group_id': 5242, }, { 'sort': 2, 'publicname': 'Un Retrait de Passeport', 'name': 'Retrait', 'id': 7033, 'group_id': 5242, }, ], } mocked_request.return_value = response resp = app.get('/clicrdv/test/interventionsets/') assert len(resp.json.get('data')) == 2 assert resp.json.get('data')[0]['text'] == 'Une Demande de Passeport' @mock.patch('passerelle.utils.Request.request') def test_interventionsets_details(mocked_request, app, connector): response = mock.Mock() response.json.return_value = { 'totalRecords': 2, 'records': [ { 'sort': 1, 'publicname': 'pour une personne', 'description': None, 'name': '1 personne', 'interventionset_id': 7032, 'group_id': 5242, 'id': 63258, 'abbr': '1 demande', }, { 'sort': 2, 'publicname': 'pour deuxs personnes', 'description': None, 'name': '2 personnes', 'interventionset_id': 7032, 'group_id': 5242, 'id': 63259, 'abbr': '2 demandes', }, ], } mocked_request.return_value = response resp = app.get('/clicrdv/test/interventionsets/7032/') assert len(resp.json.get('data')) == 2 assert resp.json.get('data')[0]['text'] == 'pour une personne' @mock.patch('passerelle.utils.Request.request') def test_interventions_get_datetimes(mocked_request, app, connector): response = mock.Mock() response.json.return_value = {'availabletimeslots': []} mocked_request.return_value = response resp = app.get('/clicrdv/test/interventions/63258/dates/') assert resp.json.get('data') == [] assert resp.json.get('err') == 0 assert mocked_request.call_count == 1 url = mocked_request.call_args[0][1] # https://sandbox.clicrdv.com/api/v1/groups/5242/availabletimeslots? # intervention_ids[]=63258&start=2016-09-21&end=2017-09-22&apikey=test&format=json scheme, netloc, path, params, query, fragment = urlparse.urlparse(url) query = urlparse.parse_qs(query, keep_blank_values=True) assert scheme == 'https' assert netloc == 'sandbox.clicrdv.com' assert path == '/api/v1/groups/5242/availabletimeslots' assert params == '' assert fragment == '' assert query['intervention_ids[]'] == ['63258'] assert 'start' in query assert 'end' in query assert query['apikey'] == ['test'] assert query['format'] == ['json'] response.json.return_value = { 'availabletimeslots': [{'start': '2016-09-21 12:34:56'}, {'start': '2016-09-22 11:22:33'}] } mocked_request.return_value = response resp = app.get('/clicrdv/test/interventions/63258/dates/').json assert mocked_request.call_count == 2 assert resp.get('err') == 0 assert len(resp.get('data')) == 2 assert resp['data'][0] == {'id': '2016-09-21', 'text': '21 September 2016'} assert resp['data'][1] == {'id': '2016-09-22', 'text': '22 September 2016'} response.json.return_value = { 'availabletimeslots': [{'start': '2016-09-22 11:22:33'}, {'start': '2016-09-21 12:34:56'}] } # will be sorted mocked_request.return_value = response resp = app.get('/clicrdv/test/interventions/63258/datetimes/').json assert mocked_request.call_count == 3 assert resp.get('err') == 0 assert len(resp.get('data')) == 2 assert resp['data'][0] == {'id': '2016-09-21-12:34:56', 'text': '21 September 2016 12:34'} assert resp['data'][1] == {'id': '2016-09-22-11:22:33', 'text': '22 September 2016 11:22'} response.json.return_value = { 'availabletimeslots': [{'start': '2016-09-21 12:34:56'}, {'start': '2016-09-21 11:22:33'}] } # will be sorted mocked_request.return_value = response resp = app.get('/clicrdv/test/interventions/63258/2016-09-21/times').json assert mocked_request.call_count == 4 url = mocked_request.call_args[0][1] scheme, netloc, path, params, query, fragment = urlparse.urlparse(url) query = urlparse.parse_qs(query, keep_blank_values=True) assert query['start'] == ['2016-09-21 00:00:00'] assert query['end'] == ['2016-09-21 23:59:59'] assert resp.get('err') == 0 assert len(resp.get('data')) == 2 assert resp['data'][0] == {'id': '11:22:33', 'text': '11:22'} assert resp['data'][1] == {'id': '12:34:56', 'text': '12:34'} @mock.patch('passerelle.utils.Request.request') def test_interventions_get_datetimes_error(mocked_request, app, connector): def raise_for_status(): raise HTTPError('400 Client Error: Bad Request for url: xxx') response = mock.Mock() response.json.return_value = [ {'error': 'The intervention_ids parameter contains at least one invalid id'} ] response.raise_for_status = raise_for_status mocked_request.return_value = response resp = app.get('/clicrdv/test/interventions/63258/datetimes/').json assert len(resp.get('data')) == 0 @mock.patch('passerelle.utils.Request.request') def test_cancel_appointment(mocked_request, app, connector): obj_type = ContentType.objects.get_for_model(ClicRdv) apiuser = ApiUser.objects.create(username='apiuser', keytype='API', key='apiuser') AccessRight.objects.create( codename='can_manage_appointment', resource_type=obj_type, resource_pk=connector.pk, apiuser=apiuser ) resp = app.get('/clicrdv/test/63258/cancel?apikey=apiuser').json assert mocked_request.call_count == 1 assert resp['data']['success'] @mock.patch('passerelle.utils.Request.request') def test_failed_cancel_appointment(mocked_request, app, connector): def raise_for_status(): raise HTTPError('400 Client Error: Bad Request for url: xxx') response = mock.Mock() response.json.return_value = [{'msg': 'cancel failed'}] response.raise_for_status = raise_for_status mocked_request.return_value = response obj_type = ContentType.objects.get_for_model(ClicRdv) apiuser = ApiUser.objects.create(username='apiuser', keytype='API', key='apiuser') AccessRight.objects.create( codename='can_manage_appointment', resource_type=obj_type, resource_pk=connector.pk, apiuser=apiuser ) resp = app.get('/clicrdv/test/63258/cancel?apikey=apiuser').json assert mocked_request.call_count == 1 assert resp.get('err') == 0 assert resp['data'] assert 'cancel failed' in resp['data']['error'] @mock.patch('passerelle.utils.Request.request') def test_failed_appointment_creation(mocked_request, app, connector): def raise_for_status(): raise HTTPError('400 Client Error: Bad Request for url: xxx') response = mock.Mock() response.json.return_value = [{'msg': 'creation failed'}] response.raise_for_status = raise_for_status mocked_request.return_value = response obj_type = ContentType.objects.get_for_model(ClicRdv) apiuser = ApiUser.objects.create(username='apiuser', keytype='API', key='apiuser') AccessRight.objects.create( codename='can_manage_appointment', resource_type=obj_type, resource_pk=connector.pk, apiuser=apiuser ) data = { 'fields': { 'clicrdv_date_raw': '2017-01-01', 'clicrdv_time_raw': '12:00:00', 'clicrdv_fiche_str10': 'Test', 'firstname': 'Foo', 'lastname': 'Bar', 'email': 'foobar@example.com', } } resp = app.post_json('/clicrdv/test/interventions/63258/create?apikey=apiuser', params=data).json assert resp['data'] assert not resp['data']['success'] assert 'creation failed' in resp['data']['error']