hobo/tests/test_matomo_views.py

234 lines
8.5 KiB
Python

# -*- coding: utf-8 -*-
import json
import mock
import pytest
import re
from requests import Response
from webtest import TestApp
from django.conf import settings
from django.contrib.auth.models import User
from django.test import override_settings
from hobo.environment.models import Variable, Wcs, Combo, Fargo
from hobo.wsgi import application
pytestmark = pytest.mark.django_db
CONFIG = {'URL': 'https://matomo.test',
'TOKEN_AUTH': '1234',
'EMAIL_TEMPLATE': 'noreply+%s@entrouvert.test'}
GET_NO_SITE_FROM_URL = """<?xml version="1.0" encoding="utf-8" ?>
<result />
"""
ADD_SITE_SUCCESS = """<?xml version="1.0" encoding="utf-8" ?>
<result>42</result>
"""
ADD_SITE_ALIAS_URLS_SUCCESS = """<?xml version="1.0" encoding="utf-8" ?>
<result>1</result>
"""
DEL_UNKNOWN_USER = """<?xml version="1.0" encoding="utf-8" ?>
<result>
<error message="User 'hobo.dev.publik.love' doesn't exist." />
</result>
"""
MATOMO_SUCCESS = """<?xml version="1.0" encoding="utf-8" ?>
<result>
<success message="ok" />
</result>
"""
JAVASCRIPT_TAG_BAD_RESPONSE = """<?xml version="1.0" encoding="utf-8" ?>
<no_result_tag/>
"""
JAVASCRIPT_TAG = """<?xml version="1.0" encoding="utf-8" ?>
<result>&lt;!-- Matomo --&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
var _paq = window._paq || [];
/* tracker methods like &quot;setCustomDimension&quot; should be called before &quot;trackPageView&quot; */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u=&quot;//matomo-test.entrouvert.org/&quot;;
_paq.push(['setTrackerUrl', u+'piwik.php']);
_paq.push(['setSiteId', '7']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
})();
&lt;/script&gt;
&lt;!-- End Matomo Code --&gt;
</result>
"""
PING_SUCCESS = '{"status":"success","tracked":1,"invalid":0}'
PING_ERROR = '{"status":"not success"}'
def requests_post_mocked_replies(contents):
"""buid an iterator for mock's side_effect parameter"""
responses = []
for content in contents:
response = Response()
# response may be XML or JSON
if content[0] == '{':
response.json = mock.MagicMock(return_value=json.loads(content))
response._content = content
response.status_code = 200
responses.append(response)
return responses
@pytest.fixture
def admin_user():
try:
user = User.objects.get(username='admin')
except User.DoesNotExist:
user = User.objects.create_superuser('admin', email=None, password='admin')
return user
def login(app, username='admin', password='admin'):
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
def test_unlogged_access():
# connect while not being logged in
app = TestApp(application)
resp = app.get('/visits-tracking/', status=302)
assert resp.location.endswith('/login/?next=/visits-tracking/')
def test_access(admin_user):
app = login(TestApp(application))
assert app.get('/visits-tracking/', status=200)
def test_disable(admin_user):
app = login(TestApp(application))
resp1 = app.get('/visits-tracking/disable', status=200)
resp2 = resp1.form.submit()
assert resp2.location.endswith('/visits-tracking/')
def test_enable_manual(admin_user):
"""scenario where user manually paste a javascript code"""
app = login(TestApp(application))
# get matomo's validation page
resp1 = app.get('/visits-tracking/enable-manual', status=200)
assert re.search('<textarea.* name="tracking_js"', resp1.body)
# validate and get matomo's home page
resp1.form['tracking_js'] = '...js_code_1...'
resp2 = resp1.form.submit().follow()
assert resp2.body.find('Manual configuration.')
assert re.search('<textarea.* name="tracking_js"', resp2.body)
assert resp2.body.find('...js_code_1...</textarea>') != -1
assert resp2.body.find('<button class="submit-button">Save</button>') != -1
# update JS code on matomo's home page
resp2.form['tracking_js'] = '...js_code_2...'
resp3 = resp2.form.submit().follow()
assert resp3.body.find('Manual configuration.') != -1
assert re.search('<textarea.* name="tracking_js"', resp3.body)
assert resp3.body.find('...js_code_2...</textarea>') != -1
assert resp3.body.find('<button class="submit-button">Save</button>') != -1
assert resp3.body.find('Good respect of user rights') != -1
def test_available_options(admin_user):
"""check available buttons (manual/automatic configurations)"""
with override_settings(MATOMO_SERVER=CONFIG):
app = login(TestApp(application))
resp = app.get('/visits-tracking/', status=200)
assert str(resp).find('href="/visits-tracking/enable-manual"') != -1
assert str(resp).find('href="/visits-tracking/enable-auto"') != -1
# without configuration: no automatic configuration available
app = login(TestApp(application))
resp = app.get('/visits-tracking/', status=200)
assert str(resp).find('href="/visits-tracking/enable-manual"') != -1
assert str(resp).find('href="/visits-tracking/enable-auto"') == -1
@mock.patch('requests.post')
def test_enable_auto(mocked_post, admin_user):
"""succesfull automatic scenario"""
Combo.objects.create(base_url='https://combo.dev.publik.love',
template_name='portal-user')
Wcs.objects.create(base_url='https://wcs.dev.publik.love')
Fargo.objects.create(base_url='https://fargo.dev.publik.love')
contents = [GET_NO_SITE_FROM_URL, ADD_SITE_SUCCESS, ADD_SITE_ALIAS_URLS_SUCCESS,
DEL_UNKNOWN_USER, MATOMO_SUCCESS,
JAVASCRIPT_TAG, PING_SUCCESS]
mocked_post.side_effect = requests_post_mocked_replies(contents)
with override_settings(MATOMO_SERVER=CONFIG):
app = login(TestApp(application))
resp1 = app.get('/visits-tracking/enable-auto', status=200)
resp2 = resp1.form.submit()
# call utils.py::auto_configure_matomo()
resp3 = resp2.follow()
# expect the CNIL compliance message is displayed
assert resp3.body.find('Excellent respect of user rights') != -1
@mock.patch('requests.post')
def test_enable_auto_warning(mocked_post, admin_user):
"""succesfull automatic scenario having final ping failure"""
Combo.objects.create(base_url='https://combo.dev.publik.love',
template_name='portal-user')
Wcs.objects.create(base_url='https://wcs.dev.publik.love')
Fargo.objects.create(base_url='https://fargo.dev.publik.love')
contents = [GET_NO_SITE_FROM_URL, ADD_SITE_SUCCESS, ADD_SITE_ALIAS_URLS_SUCCESS,
DEL_UNKNOWN_USER, MATOMO_SUCCESS,
JAVASCRIPT_TAG, PING_ERROR]
mocked_post.side_effect = requests_post_mocked_replies(contents)
with override_settings(MATOMO_SERVER=CONFIG):
app = login(TestApp(application))
resp1 = app.get('/visits-tracking/enable-auto', status=200)
resp2 = resp1.form.submit()
# call utils.py::auto_configure_matomo()
resp3 = resp2.follow()
# expect 'ping fails' warning
assert resp3.body.find('class="warning">ping: ping fails') != -1
# expect the CNIL compliance message is displayed
assert resp3.body.find('Excellent respect of user rights') != -1
@mock.patch('requests.post')
def test_enable_auto_error(mocked_post, admin_user):
"""error on automatic scenario"""
Combo.objects.create(base_url='https://combo.dev.publik.love',
template_name='portal-user')
Wcs.objects.create(base_url='https://wcs.dev.publik.love')
Fargo.objects.create(base_url='https://fargo.dev.publik.love')
contents = [GET_NO_SITE_FROM_URL, ADD_SITE_SUCCESS, ADD_SITE_ALIAS_URLS_SUCCESS,
DEL_UNKNOWN_USER, MATOMO_SUCCESS,
JAVASCRIPT_TAG_BAD_RESPONSE]
mocked_post.side_effect = requests_post_mocked_replies(contents)
with override_settings(MATOMO_SERVER=CONFIG):
app = login(TestApp(application))
resp1 = app.get('/visits-tracking/enable-auto', status=200)
resp2 = resp1.form.submit()
# call utils.py::auto_configure_matomo()
resp3 = resp2.follow()
# expect a Django error message is displayed
assert resp3.body.find('class="error">matomo: get_javascript_tag fails') != -1