from unittest import mock import pytest import tests.utils from passerelle.apps.vivaticket.models import VivaTicket from passerelle.utils.jsonresponse import APIError ERROR_RESPONSE = """{ "Message": "Une erreur s’est produite." }""" KEY_RESPONSE = """{ "Key": "86569D0CA1B1CBEF8D77DD5BDC9F5CBAE5C99074", "ReturnCode": 0, "Error": null }""" EVENTS_RESPONSE = """{ "ListOfSettings": [ { "Code": "01", "Label": "Visite Musée" }, { "Code": "02", "Label": "Visite Exposition" }, { "Code": "03", "Label": "Visite Musée + Atelier" }, { "Code": "04", "Label": "Visite Musée + Expo + Atelier" }, { "Code": "06", "Label": "Atelier" }, { "Code": "05", "Label": "Auditorium" }, { "Code": "10", "Label": "Prévente" } ], "ReturnCode": 0, "Error": null }""" ROOMS_RESPONSE = """{ "ListOfSettings": [ { "Code": "001", "Label": "Collections Permanentes" }, { "Code": "002", "Label": "Exposition" }, { "Code": "003", "Label": "Salle Pédagogique 1" }, { "Code": "004", "Label": "Salle Pédagogique 2" }, { "Code": "006", "Label": "Laboratoire" }, { "Code": "005", "Label": "Auditorium" } ], "ReturnCode": 0, "Error": null }""" THEMES_RESPONSE = """{ "ListOfSettings": [ { "Code": "A0001", "Label": "Atelier scolaire" }, { "Code": "A0002", "Label": "Atelier Enfant - Individuel" },, { "Code": "C0001", "Label": "Conférence - Sujet 1" }, { "Code": "C0002", "Label": "Conférence - Sujet 2" }, { "Code": "R0001", "Label": "Petit Déjeuner" }, { "Code": "R0002", "Label": "Déjeuner" }, { "Code": "S0001", "Label": "Spectacle - Titre 1" }, { "Code": "S0002", "Label": "Spectacle - Titre 2" }, { "Code": "S0003", "Label": "Spectacle - Titre 3" }, { "Code": "V001", "Label": "Visite Guidée Musée - Individuel" }, { "Code": "V002", "Label": "Visite Guidée Musée - Groupe" }, { "Code": "V003", "Label": "Visite Guidée Musée - Scolaire" }, { "Code": "V004", "Label": "Visite Libre Musée - Groupe" }, { "Code": "V0041", "Label": "Visite Libre Musée - Scolaire" }, { "Code": "V005", "Label": "Visite Guidée Expo - Individuel" }, { "Code": "V006", "Label": "Visite Guidée Expo - Groupe" }, { "Code": "V007", "Label": "Visite Guidée Expo - Scolaire" }, { "Code": "V008", "Label": "Visite Libre Expo - Groupe" }, { "Code": "V009", "Label": "Visite Libre Expo - Scolaire" } ], "ReturnCode": 0, "Error": null }""" CONTACT_RESPONSE = """{ "InternalCode": "0000000273", "LastName": "Bar", "FirstName": "Foo", "SocialReason": null, "Address1": null, "Address2": null, "Address3": null, "Address4": null, "ZipCode": null, "City": null, "Country": "FR", "Email": "foo@example.com", "Phone": null, "Mobile": null, "ExternalCode": "foo", "Civility": null }""" BOOKING_RESPONSE = """{ "bookingCode": "II0000013", "ReturnCode": 0, "Error": null }""" SCHOOL_LEVELS_RESPONSE = """{ "ListOfSettings": [ { "Code": "00", "Label": "Maternelle" }, { "Code": "01", "Label": "Cp" }, { "Code": "02", "Label": "Ce1-Ce2" }, { "Code": "03", "Label": "Cm1-Cm2" } ], "ReturnCode": 0, "Error": null }""" @pytest.fixture def connector(db): return tests.utils.setup_access_rights( VivaTicket.objects.create( slug='test', login='foo', password='bar', url='http://example.net/vivaticket' ) ) @mock.patch('passerelle.utils.Request.post') def test_get_api_key(mocked_post, app, connector): with pytest.raises(APIError): mocked_post.return_value = tests.utils.FakedResponse(content=ERROR_RESPONSE, ok=False) connector.get_apikey() mocked_post.return_value = tests.utils.FakedResponse(content=KEY_RESPONSE, ok=True) connector.get_apikey() assert mocked_post.call_count == 2 assert 'Connect/PostConnect' in mocked_post.call_args[0][0] assert mocked_post.call_args[1]['json']['Login'] == 'foo' assert mocked_post.call_args[1]['json']['Password'] == 'bar' # make sure the key from cache is used connector.get_apikey() assert mocked_post.call_count == 2 connector.get_apikey(True) assert mocked_post.call_count == 3 @mock.patch('passerelle.utils.Request.post') @mock.patch('passerelle.utils.Request.get') def test_get_events(mocked_get, mocked_post, app, connector): mocked_get.return_value = tests.utils.FakedResponse(content=EVENTS_RESPONSE, status_code=200) mocked_post.return_value = tests.utils.FakedResponse(content=KEY_RESPONSE, status_code=200) result = tests.utils.endpoint_get('/vivaticket/test/events', app, connector, 'events') assert mocked_post.call_count == 1 assert mocked_get.call_args[1]['params']['key'] == '86569D0CA1B1CBEF8D77DD5BDC9F5CBAE5C99074' assert 'data' in result.json for item in result.json['data']: assert 'id' in item assert 'text' in item @mock.patch('passerelle.utils.Request.post') @mock.patch('passerelle.utils.Request.get') def test_get_events_with_expired_key(mocked_get, mocked_post, app, connector): mocked_get.return_value = tests.utils.FakedResponse(content=EVENTS_RESPONSE, status_code=401) mocked_post.return_value = tests.utils.FakedResponse(content=KEY_RESPONSE, status_code=200) tests.utils.endpoint_get('/vivaticket/test/events', app, connector, 'events') assert mocked_post.call_count == 2 @mock.patch('passerelle.utils.Request.post') @mock.patch('passerelle.utils.Request.get') def test_get_rooms(mocked_get, mocked_post, app, connector): mocked_get.return_value = tests.utils.FakedResponse(content=ROOMS_RESPONSE, status_code=200) mocked_post.return_value = tests.utils.FakedResponse(content=KEY_RESPONSE, status_code=200) result = tests.utils.endpoint_get('/vivaticket/test/rooms', app, connector, 'rooms') assert mocked_get.call_args[1]['params']['key'] == '86569D0CA1B1CBEF8D77DD5BDC9F5CBAE5C99074' assert 'data' in result.json for item in result.json['data']: assert 'id' in item assert 'text' in item result = tests.utils.endpoint_get( '/vivaticket/test/rooms', app, connector, 'rooms', params={'event': '02'} ) assert mocked_get.call_args[1]['params']['eventCategory'] == '02' @mock.patch('passerelle.utils.Request.post') @mock.patch('passerelle.utils.Request.get') def test_get_themes(mocked_get, mocked_post, app, connector): mocked_get.return_value = tests.utils.FakedResponse(content=ROOMS_RESPONSE, status_code=200) mocked_post.return_value = tests.utils.FakedResponse(content=KEY_RESPONSE, status_code=200) result = tests.utils.endpoint_get('/vivaticket/test/themes', app, connector, 'themes') assert mocked_get.call_args[1]['params']['key'] == '86569D0CA1B1CBEF8D77DD5BDC9F5CBAE5C99074' assert 'data' in result.json for item in result.json['data']: assert 'id' in item assert 'text' in item result = tests.utils.endpoint_get( '/vivaticket/test/themes', app, connector, 'themes', params={'room': '001'} ) assert mocked_get.call_args[1]['params']['room'] == '001' @mock.patch('passerelle.utils.Request.post') @mock.patch('passerelle.utils.Request.get') def test_get_school_levels(mocked_get, mocked_post, app, connector): mocked_get.return_value = tests.utils.FakedResponse(content=SCHOOL_LEVELS_RESPONSE, status_code=200) mocked_post.return_value = tests.utils.FakedResponse(content=KEY_RESPONSE, status_code=200) result = tests.utils.endpoint_get('/vivaticket/test/school-levels', app, connector, 'school-levels') assert mocked_get.call_args[1]['params']['key'] == '86569D0CA1B1CBEF8D77DD5BDC9F5CBAE5C99074' assert 'data' in result.json for item in result.json['data']: assert 'id' in item assert 'text' in item @mock.patch('passerelle.utils.Request.post') @mock.patch('passerelle.utils.Request.put') @mock.patch('passerelle.utils.Request.get') def test_get_or_create_contact(mocked_get, mocked_put, mocked_post, app, connector): mocked_get.return_value = tests.utils.FakedResponse(content='', ok=False) mocked_post.side_effect = [ tests.utils.FakedResponse(content=KEY_RESPONSE, status_code=200), tests.utils.FakedResponse( content='{"InternalCode": "0000000273", "ReturnCode": 0, "Error": null}', status_code=200 ), ] assert connector.get_or_create_contact({'email': 'foo@example.com'}) == {'InternalCode': '0000000273'} assert mocked_get.call_args[1]['params']['externalCode'] == 'b48def645758b95537d4' assert mocked_get.call_args[1]['params']['email'] == 'foo@example.com' mocked_put.assert_not_called() assert mocked_post.call_args[1]['json']['Key'] == '86569D0CA1B1CBEF8D77DD5BDC9F5CBAE5C99074' assert mocked_post.call_args[1]['json']['Contact']['Email'] == 'foo@example.com' assert mocked_post.call_args[1]['json']['Contact']['ExternalCode'] == 'b48def645758b95537d4' mocked_post.return_value = tests.utils.FakedResponse( content='{"InternalCode": "0000000273", "ReturnCode": 0, "Error": null}', status_code=200 ) mocked_get.return_value = tests.utils.FakedResponse(content=CONTACT_RESPONSE, ok=True) mocked_put.return_value = tests.utils.FakedResponse(content='', status_code=204) connector.get_or_create_contact({'email': 'foo@example.com'}) mocked_put.assert_called() assert mocked_put.call_args[1]['params']['id'] == '0000000273' assert mocked_put.call_args[1]['json']['Key'] == '86569D0CA1B1CBEF8D77DD5BDC9F5CBAE5C99074' assert mocked_put.call_args[1]['json']['Contact']['Email'] == 'foo@example.com' @mock.patch('passerelle.utils.Request.post') @mock.patch('passerelle.utils.Request.put') @mock.patch('passerelle.utils.Request.get') def test_book(mocked_get, mocked_put, mocked_post, app, connector): mocked_get.return_value = tests.utils.FakedResponse(content=CONTACT_RESPONSE, status_code=200) url = tests.utils.generic_endpoint_url('vivaticket', 'book') payload = {'id': 'formid', 'email': 'foo@example.com'} response = app.post_json(url, params=payload, status=400) payload['start_datetime'] = '2019-01-15' payload['end_datetime'] = '2019-01-15' payload['event'] = '01' payload['theme'] = '001' payload['room'] = 'v001' payload['school_level'] = '01' payload['quantity'] = '01' payload['booking_comment'] = 'Booking comment' payload['room_comment'] = 'Room comment' payload['form_url'] = 'http://mysite.com/form/id/' response = app.post_json(url, params=payload, status=400) assert "does not match '^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}$" in response.json['err_desc'] payload['start_datetime'] = '2019-01-15T10:00' payload['end_datetime'] = '2019-01-15T11:00' # first return the API key, then the result of the booking creation mocked_post.side_effect = [ tests.utils.FakedResponse(content=KEY_RESPONSE, status_code=200), tests.utils.FakedResponse(content=BOOKING_RESPONSE), Exception(), ] response = app.post_json(url, params=payload) assert mocked_post.call_args[1]['json']['Key'] == '86569D0CA1B1CBEF8D77DD5BDC9F5CBAE5C99074' assert mocked_post.call_args[1]['json']['Booking']['externalCode'] == 'formid' assert mocked_post.call_args[1]['json']['Booking']['startDateTime'] == '2019-01-15T10:00' assert mocked_post.call_args[1]['json']['Booking']['endDateTime'] == '2019-01-15T11:00' assert mocked_post.call_args[1]['json']['Booking']['comment'] == 'Booking comment' assert mocked_post.call_args[1]['json']['Booking']['roomList'][0]['comment'] == 'Room comment' assert mocked_post.call_args[1]['json']['Booking']['roomList'][0]['quantity'] == 1 assert mocked_post.call_args[1]['json']['Booking']['roomList'][0]['schoolLevelCode'] == '01' assert mocked_post.call_args[1]['json']['Booking']['contact'] == {'InternalCode': '0000000273'} assert mocked_post.call_args[1]['headers'] == {'X-Vivaticket-Form-URL': 'http://mysite.com/form/id/'} assert response.json['data']['bookingCode'] == 'II0000013' # no more need to fake key response because the key is in cache mocked_post.side_effect = [ tests.utils.FakedResponse(text='This external booking code already exists.', ok=False) ] response = app.post_json(url, params=payload) assert response.json['err'] == 1 assert response.json['err_desc'] == 'This external booking code already exists.' assert response.json['err_class'] == 'passerelle.utils.jsonresponse.APIError'