diff --git a/tests/test_contacts_manager.py b/tests/test_contacts_manager.py new file mode 100644 index 0000000..203395d --- /dev/null +++ b/tests/test_contacts_manager.py @@ -0,0 +1,229 @@ +# welco - multichannel request processing +# Copyright (C) 2020 Entr'ouvert +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU Affero General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +import httmock +import mock +import pytest +import requests + +from django.contrib.contenttypes.models import ContentType +from django.core.files.base import ContentFile + +from welco.sources.mail.models import Mail + + +def test_get_contacts_zone_view(app, db): + resp = app.get('/ajax/contacts', status=200) + assert resp.html.find('button')['data-url'] == '/contacts/add/' + + mail = Mail.objects.create( + content=ContentFile('foo', name='bar.txt'), + contact_id='42') + source_type = ContentType.objects.get_for_model(Mail).pk + resp = app.get( + '/ajax/contacts', + params={'source_type': source_type, 'source_pk': mail.pk}, + status=200) + assert resp.html.find('a').text == '...' + assert resp.html.find('a')['data-page-slug'] == '42' + + +def test_post_contacts_zone_view(app, db): + mail = Mail.objects.create(content=ContentFile('foo', name='bar.txt')) + assert not mail.contact_id + source_type = ContentType.objects.get_for_model(Mail).pk + resp = app.post( + '/ajax/contacts', + params={'source_type': source_type, 'source_pk': mail.pk, 'user_id': 42}, + status=200) + assert resp.text == 'ok' + assert Mail.objects.get(id=mail.pk).contact_id == '42' + + +def test_search_json_view_without_channel(app): + app.get('/contacts/search/json/', status=403) + + +def test_search_json_view_without_query(app, user, mail_group): + app.set_user(user.username) + resp = app.get('/contacts/search/json/', status=200) + assert resp.content_type == 'application/json' + assert resp.json == {'data': []} + + +def test_search_json_view(settings, app, user, mail_group): + settings.KNOWN_SERVICES = { + 'wcs': { + 'demarches': { + 'url': 'http://wcs.example.net/', + } + } + } + app.set_user(user.username) + + @httmock.urlmatch(netloc='wcs.example.net', path='/api/users/', method='GET') + def response(url, request): + headers = {'content-type': 'application/json'} + content = {'err': 1, 'msg': 'oups'} + return httmock.response(200, content, headers) + + with httmock.HTTMock(response): + with pytest.raises(Exception, match='oups'): + resp = app.get('/contacts/search/json/', params={'q': 'Doe'}) + + @httmock.urlmatch(netloc='wcs.example.net', path='/api/users/', method='GET') + def response(url, request): + headers = {'content-type': 'application/json'} + content = { + 'data': [{ + 'user_display_name': 'John Doe', + 'user_email': 'john@example.net', + 'user_var_phone': '0123456789', + 'user_var_mobile': '0612345789', + 'user_id': '42', + 'user_roles': [{ + 'name': 'Agent', + 'text': 'Agent', + 'slug': 'agent', + 'id': '8d73434814484aa0b8555ac9c68a9300' + }], + }], + 'err': 0 + } + return httmock.response(200, content, headers) + + with httmock.HTTMock(response): + resp = app.get('/contacts/search/json/', params={'q': 'Doe'}, status=200) + assert resp.content_type == 'application/json' + assert resp.json['data'][0]['user_display_name'] == 'John Doe' + + +def test_contact_detail_fragment_view(settings, app, db): + settings.KNOWN_SERVICES = { + 'wcs': { + 'demarches': { + 'url': 'http://wcs.example.net/', + } + } + } + @httmock.urlmatch(netloc='wcs.example.net', path='/api/users/42/', method='GET') + def response(url, request): + headers = {'content-type': 'application/json'} + content = { + 'user_display_name': 'John Doe', + 'user_email': 'john@example.net', + 'user_var_phone': '0123456789', + 'user_var_mobile': '0612345789', + 'user_id': '42', + 'user_roles': [{ + 'name': 'Agent', + 'text': 'Agent', + 'slug': 'agent', + 'id': '8d73434814484aa0b8555ac9c68a9300' + }], + } + return httmock.response(200, content, headers) + + with httmock.HTTMock(response): + resp = app.get('/ajax/contacts/42/', status=200) + assert resp.html.find('h3').text == 'John Doe' + assert resp.html.find('p').text == 'Agent' + assert resp.html.find('li').text == 'Phone: 0123456789' + + # unused 'is_pinned_user' context + mail = Mail.objects.create( + content=ContentFile('foo', name='bar.txt'), + contact_id='42') + source_type = ContentType.objects.get_for_model(Mail).pk + with httmock.HTTMock(response): + resp = app.get( + '/ajax/contacts/42/', + params={'source_type': source_type, 'source_pk': mail.pk}, + status=200) + assert resp.html.find('h3').text == 'John Doe' + + +def test_get_contact_add_view(app): + resp = app.get('/contacts/add/', status=200) + assert resp.html.find('select')['name'] == 'title' + assert resp.html.find('input', {'id': 'id_first_name'})['name'] == 'first_name' + + +@mock.patch('welco.contacts.views.time.sleep') +def test_post_contact_add_view(mocked_sleep, settings, app, db): + settings.CONTACT_SEND_REGISTRATION_EMAIL = True + settings.KNOWN_SERVICES = { + 'authentic': { + 'connexion': { + 'url': 'http://authentic.example.net/', + 'orig': 'http://welco.example.net/', + 'secret': 'xxx', + } + }, + 'wcs': { + 'demarches': { + 'url': 'http://wcs.example.net/', + } + } + } + + # normal case + @httmock.urlmatch(netloc='authentic.example.net', path='/api/users/', method='POST') + def authentic_response(url, request): + headers = {'content-type': 'application/json'} + content = {'uuid': '42'} + return httmock.response(200, content, headers) + + @httmock.urlmatch(netloc='wcs.example.net', path='/api/users/42/', method='GET') + def wcs_response(url, request): + headers = {'content-type': 'application/json'} + content = { + 'user_display_name': 'John Doe', + 'id': '43', + } + return httmock.response(200, content, headers) + + with httmock.HTTMock(authentic_response, wcs_response): + resp = app.post( + '/contacts/add/', + params={ + 'title': 'Mr', + 'first_name': 'John', + 'last_name': 'Doe', + }, + status=200) + assert resp.content_type == 'application/json' + assert resp.json['data']['user_id'] == '43' + + # timeout + @httmock.urlmatch(netloc='wcs.example.net', path='/api/users/42/', method='GET') + def wcs_no_response(url, request): + return httmock.response(404) + + with httmock.HTTMock(authentic_response, wcs_no_response): + resp = app.post('/contacts/add/', status=200) + assert resp.content_type == 'application/json' + assert resp.json['err'] == 1 + assert resp.json['data'] == 'timeout when calling wcs' + + # error + @httmock.urlmatch(netloc='wcs.example.net', path='/api/users/42/', method='GET') + def wcs_no_response(url, request): + return httmock.response(500) + + with httmock.HTTMock(authentic_response, wcs_no_response): + with pytest.raises(requests.HTTPError): + resp = app.post('/contacts/add/', status=200)