# 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 from django.contrib.contenttypes.models import ContentType from django.core.files.base import ContentFile from welco.qualif.models import Association from welco.sources.mail.models import Mail def login(app, username='toto', password='toto'): login_page = app.get('/login/') login_form = login_page.forms[0] login_form['username'] = username login_form['password'] = password resp = login_form.submit() assert resp.status_int == 302 return app @pytest.fixture def logged_app(app, user): return login(app) def test_unlogged_access(app): # connect while not being logged in assert app.get('/', status=302).location.endswith('/login/?next=/') def test_no_channel_access(logged_app): logged_app.get('/', status=403) def test_access(logged_app, mail_group): resp = logged_app.get('/', status=302) assert resp.location == 'mail/' def test_logout(logged_app): app = logged_app app.get('/logout/') assert app.get('/', status=302).location.endswith('/login/?next=/') @mock.patch('welco.views.get_idps', return_value=[{'METADATA': '...'}]) @mock.patch('welco.views.resolve_url', return_value='foo-url') def test_mellon_idp_redirections(mocked_resolv_url, mocked_get_idps, app): resp = app.get('/login/', status=302) assert resp.location == 'foo-url' resp = app.get('/login/?next=http://foo/?bar', status=302) assert resp.location == 'foo-url?next=http%3A//foo/%3Fbar' resp = app.get('/logout/', status=302) assert resp.location == 'foo-url' def test_mail_view(app, user, mail_group): resp = app.get('/mail/', status=302) assert resp.location == '/login/?next=/mail/' app.set_user(user.username) resp = app.get('/mail/', status=200) assert resp.html.find('h2').text == 'Mails' def test_no_channel_access_on_mail_view(app, user): app.set_user(user.username) app.get('/mail/', status=403) def test_phone_view(app, user, phone_group): resp = app.get('/phone/', status=302) assert resp.location == '/login/?next=/phone/' app.set_user(user.username) resp = app.get('/phone/', status=200) assert resp.html.find('h2').text == 'Phone Call' def test_counter_view(app, user, counter_group): resp = app.get('/counter/', status=302) assert resp.location == '/login/?next=/counter/' app.set_user(user.username) resp = app.get('/counter/', status=200) assert resp.html.find('h2').text == 'Counter' def test_kb_view(app, user, kb_group): resp = app.get('/kb/', status=302) assert resp.location == '/login/?next=/kb/' app.set_user(user.username) resp = app.get('/kb/', status=200) assert resp.html.find('h2').text == 'Knowledge Base' def test_wcs_summary_view(app, mail_group, user): mail = Mail.objects.create(content=ContentFile('foo', name='bar.txt')) source_type = ContentType.objects.get_for_model(Mail).pk resp = app.get('/ajax/summary/%s/%s/?callback=spam' % (source_type, mail.pk), status=302) assert resp.location.startswith('/login/?next=') app.set_user(user.username) resp = app.get('/ajax/summary/%s/%s/?callback=spam' % (source_type, mail.pk), status=200) assert resp.content_type == 'application/javascript' assert 'bar' in resp.text assert resp.text.startswith('spam({') def test_remove_association_view(app, mail_group, user): mail = Mail.objects.create(content=ContentFile('foo', name='bar.txt')) source_type = ContentType.objects.get_for_model(Mail).pk association = Association.objects.create( source_type=ContentType.objects.get(id=source_type), source_pk=mail.pk ) assert Association.objects.filter(id=association.pk).count() == 1 resp = app.get('/ajax/remove-association/%s' % association.pk, status=302) assert resp.location.startswith('/login/?next=') app.set_user(user.username) resp = app.get('/ajax/remove-association/%s' % association.pk, status=302) assert resp.location == '/' assert Association.objects.filter(id=association.pk).count() == 0 def test_create_formdata_view(settings, app, mail_group, user): settings.KNOWN_SERVICES = { 'wcs': { 'demarches': { 'url': 'http://wcs.example.net/', } } } mail = Mail.objects.create(content=ContentFile('foo', name='bar.txt')) source_type = ContentType.objects.get_for_model(Mail).pk association = Association.objects.create( source_type=ContentType.objects.get(id=source_type), source_pk=mail.pk ) resp = app.get('/ajax/create-formdata/%s' % association.pk, status=302) assert resp.location.startswith('/login/?next=') app.set_user(user.username) resp = app.get('/ajax/create-formdata/%s' % association.pk, status=200) assert resp.content_type == 'application/json' assert resp.json == {'err': 1} resp = app.post('/ajax/create-formdata/%s' % association.pk, status=200) assert resp.json == {'err': 1, 'msg': "'NoneType' object has no attribute 'split'"} association.formdef_reference = 'demarches:bar' association.save() @httmock.urlmatch(netloc='wcs.example.net', path='/api/formdefs/bar/schema', method='GET') def response_get(url, request): headers = {'content-type': 'application/json'} content = {} return httmock.response(200, content, headers) @httmock.urlmatch(netloc='wcs.example.net', path='/api/formdefs/bar/submit', method='POST') def response_post(url, request): headers = {'content-type': 'application/json'} content = { 'err': 0, 'data': { 'id': 42, 'backoffice_url': 'http://example.net', }, } return httmock.response(200, content, headers) with httmock.HTTMock(response_get, response_post): resp = app.post('/ajax/create-formdata/%s' % association.pk, status=200) assert resp.content_type == 'application/json' assert resp.json == { 'result': 'ok', 'url': 'http://wcs.example.net/backoffice/management/bar/42/', } def test_menu_json_view(app, user, mail_group, phone_group, counter_group, kb_group): resp = app.get('/menu.json', status=302) assert resp.location.startswith('/login/?next=') app.set_user(user.username) resp = app.get('/menu.json', status=200) assert resp.content_type == 'application/json' assert sorted([x['label'] for x in resp.json]) == ['Call Center', 'Counter', 'Knowledge Base', 'Mails'] resp = app.get('/menu.json?callback=foo', status=200) assert resp.content_type == 'application/javascript' assert resp.text.startswith('foo([{')