django-cms-qe 3.4.2__py3-none-any.whl → 3.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cms_qe/tests/__init__.py +0 -0
- cms_qe/tests/test_errors.py +61 -0
- cms_qe/tests/test_export.py +108 -0
- cms_qe/tests/test_monitoring.py +15 -0
- cms_qe/tests/test_utils.py +77 -0
- cms_qe/tests/test_views_security.py +18 -0
- cms_qe/views/maintenance.py +6 -0
- cms_qe_analytical/tests/__init__.py +0 -0
- cms_qe_analytical/tests/settings.py +24 -0
- cms_qe_analytical/tests/templatetags/__init__.py +0 -0
- cms_qe_analytical/tests/templatetags/dummy.py +37 -0
- cms_qe_analytical/tests/test_tag_google_analytics.py +178 -0
- cms_qe_analytical/tests/test_tag_piwik.py +152 -0
- cms_qe_analytical/tests/test_utils.py +112 -0
- cms_qe_analytical/tests/utils.py +56 -0
- cms_qe_auth/tests/__init__.py +0 -0
- cms_qe_auth/tests/test_models.py +70 -0
- cms_qe_auth/tests/test_utils.py +36 -0
- cms_qe_auth/tests/test_view.py +72 -0
- cms_qe_auth/tests/utils.py +22 -0
- cms_qe_newsletter/tests/__init__.py +0 -0
- cms_qe_newsletter/tests/test_mailchimp.py +38 -0
- cms_qe_newsletter/tests/test_managment.py +22 -0
- cms_qe_newsletter/tests/test_models.py +43 -0
- cms_qe_newsletter/tests/test_plugin.py +21 -0
- cms_qe_newsletter/tests/test_sync.py +71 -0
- cms_qe_newsletter/tests/test_views.py +13 -0
- cms_qe_plugins/cms_plugins.py +10 -0
- cms_qe_plugins/templates/cms_qe_plugins/published_or_draft_content.html +6 -0
- cms_qe_table/tests/__init__.py +0 -0
- cms_qe_table/tests/test_models.py +23 -0
- cms_qe_table/tests/test_plugin.py +18 -0
- cms_qe_table/tests/test_utils.py +90 -0
- cms_qe_video/tests/__init__.py +0 -0
- cms_qe_video/tests/test_models.py +96 -0
- cms_qe_video/tests/test_plugin.py +24 -0
- cms_qe_video/tests/test_templatetags.py +20 -0
- {django_cms_qe-3.4.2.dist-info → django_cms_qe-3.5.0.dist-info}/METADATA +12 -11
- {django_cms_qe-3.4.2.dist-info → django_cms_qe-3.5.0.dist-info}/RECORD +42 -7
- {django_cms_qe-3.4.2.dist-info → django_cms_qe-3.5.0.dist-info}/WHEEL +1 -1
- {django_cms_qe-3.4.2.dist-info → django_cms_qe-3.5.0.dist-info}/LICENSE +0 -0
- {django_cms_qe-3.4.2.dist-info → django_cms_qe-3.5.0.dist-info}/top_level.txt +0 -0
cms_qe/tests/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
from unittest.mock import patch
|
|
2
|
+
|
|
3
|
+
from django.contrib.auth.models import AnonymousUser
|
|
4
|
+
from django.test import RequestFactory, TestCase
|
|
5
|
+
|
|
6
|
+
from cms_qe.views import handler500
|
|
7
|
+
from cms_qe_test.cms import create_page
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_page_found(client):
|
|
11
|
+
create_page('Test page', page_params={'slug': 'test'})
|
|
12
|
+
html = client.get('/en/test/').content
|
|
13
|
+
assert b'<h1>Generic error</h1>' not in html
|
|
14
|
+
assert b'<title>Test page</title>' in html
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def test_page_not_found(client):
|
|
18
|
+
html = client.get('/en/non-existing-page/').content
|
|
19
|
+
assert b'<h1>Generic error</h1>' in html
|
|
20
|
+
assert b'error404' in html
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_page_not_found_custom_by_cms(client):
|
|
24
|
+
create_page('custom page not found', page_params={'slug': 'error404'})
|
|
25
|
+
response = client.get('/en/non-existing-page/')
|
|
26
|
+
assert response.status_code == 404
|
|
27
|
+
html = response.content
|
|
28
|
+
assert b'<h1>Generic error</h1>' not in html
|
|
29
|
+
assert b'<title>custom page not found</title>' in html
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_page_not_found_cached_custom_by_cms(client):
|
|
33
|
+
create_page('custom page not found', page_params={'slug': 'error404'})
|
|
34
|
+
# First request store page into the cache
|
|
35
|
+
response = client.get('/en/non-existing-page/')
|
|
36
|
+
assert response.status_code == 404
|
|
37
|
+
# Second request is taken from the cache.
|
|
38
|
+
response = client.get('/en/non-existing-page/')
|
|
39
|
+
assert response.get('QE-Status-Code') is None
|
|
40
|
+
assert response.status_code == 404
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class Handler500Test(TestCase):
|
|
44
|
+
def test_template_rendered(self):
|
|
45
|
+
request = RequestFactory().get("/500")
|
|
46
|
+
request.current_page = None
|
|
47
|
+
request.session = {}
|
|
48
|
+
request.user = AnonymousUser()
|
|
49
|
+
response = handler500(request)
|
|
50
|
+
self.assertContains(response, '<h1>Internal error</h1>', status_code=500)
|
|
51
|
+
self.assertContains(response, 'Something went very wrong. Please try again later.', status_code=500)
|
|
52
|
+
|
|
53
|
+
@patch('cms_qe.views.errors.render', side_effect=Exception("Fail!"))
|
|
54
|
+
def test_template_failure(self, render_mock):
|
|
55
|
+
request = RequestFactory().get("/500")
|
|
56
|
+
request.current_page = None
|
|
57
|
+
request.session = {}
|
|
58
|
+
request.user = AnonymousUser()
|
|
59
|
+
response = handler500(request)
|
|
60
|
+
self.assertContains(response, '<h1>Internal error</h1>', status_code=500)
|
|
61
|
+
self.assertContains(response, 'Something went very wrong. Please try again later.', status_code=500)
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import csv
|
|
2
|
+
import io
|
|
3
|
+
import json
|
|
4
|
+
from unittest.mock import patch
|
|
5
|
+
|
|
6
|
+
import pytest
|
|
7
|
+
from django.contrib.auth import get_user_model
|
|
8
|
+
from pytest_data import use_data
|
|
9
|
+
|
|
10
|
+
from ..export import export_data, export_file, get_supported_export_types
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ModelAdmin:
|
|
14
|
+
list_display = ('foo',)
|
|
15
|
+
|
|
16
|
+
def foo(self, obj):
|
|
17
|
+
return 'foo property'
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ExportDataAdmin(ModelAdmin):
|
|
21
|
+
|
|
22
|
+
def export_data(self, export_type, queryset):
|
|
23
|
+
return 'foo export_data'
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@pytest.mark.django_db
|
|
27
|
+
@use_data(user_data={'username': 'test_export_data_as_csv'})
|
|
28
|
+
def test_export_data_as_csv(user):
|
|
29
|
+
User = get_user_model()
|
|
30
|
+
queryset = User.objects.all()
|
|
31
|
+
data = export_data('csv', ModelAdmin(), queryset)
|
|
32
|
+
data = list(csv.reader(io.StringIO(data)))
|
|
33
|
+
assert len(data) == 2
|
|
34
|
+
assert 'test_export_data_as_csv' in data[1]
|
|
35
|
+
assert 'foo property' in data[1]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@pytest.mark.django_db
|
|
39
|
+
@use_data(user_data={'username': 'test_export_data_as_tsv'})
|
|
40
|
+
def test_export_data_as_tsv(user):
|
|
41
|
+
User = get_user_model()
|
|
42
|
+
queryset = User.objects.all()
|
|
43
|
+
data = export_data('tsv', ModelAdmin(), queryset)
|
|
44
|
+
data = list(csv.reader(io.StringIO(data), delimiter='\t'))
|
|
45
|
+
assert len(data) == 2
|
|
46
|
+
assert 'test_export_data_as_tsv' in data[1]
|
|
47
|
+
assert 'foo property' in data[1]
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@pytest.mark.django_db
|
|
51
|
+
@use_data(user_data={'username': 'test_export_data_as_json'})
|
|
52
|
+
def test_export_data_as_json(user):
|
|
53
|
+
User = get_user_model()
|
|
54
|
+
queryset = User.objects.all()
|
|
55
|
+
data = export_data('json', ModelAdmin(), queryset)
|
|
56
|
+
data = json.loads(data)
|
|
57
|
+
assert len(data) == 1
|
|
58
|
+
assert data[0]['username'] == 'test_export_data_as_json'
|
|
59
|
+
assert data[0]['foo'] == 'foo property'
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@pytest.mark.django_db
|
|
63
|
+
@use_data(user_data={'username': 'test_export_data_as_json'})
|
|
64
|
+
def test_export_data_admin_function(user):
|
|
65
|
+
User = get_user_model()
|
|
66
|
+
queryset = User.objects.all()
|
|
67
|
+
data = export_data('foo', ExportDataAdmin(), queryset)
|
|
68
|
+
assert data == 'foo export_data'
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@pytest.mark.django_db
|
|
72
|
+
@use_data(user_data={'username': 'test_export_data_as_json'})
|
|
73
|
+
def test_export_file():
|
|
74
|
+
User = get_user_model()
|
|
75
|
+
queryset = User.objects.all()
|
|
76
|
+
response = export_file('csv', ModelAdmin(), queryset)
|
|
77
|
+
assert response['content-disposition'] == 'attachment; ' \
|
|
78
|
+
'filename="export.csv"'
|
|
79
|
+
assert response.content == b'ID,password,last login,superuser ' \
|
|
80
|
+
b'status,username,first name,last name,email address,staff ' \
|
|
81
|
+
b'status,active,date joined,groups,user permissions,foo\r\n'
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def test_get_supported_export_types():
|
|
85
|
+
with patch('cms_qe.export.getattr') as mock_getattr:
|
|
86
|
+
mock_getattr.side_effect = [
|
|
87
|
+
'csv', 'html', 'json', 'latex', 'ods', 'rst', 'tsv', 'xls',
|
|
88
|
+
'xlsx', 'yaml']
|
|
89
|
+
data = get_supported_export_types()
|
|
90
|
+
assert sorted(data.keys()) == [
|
|
91
|
+
'csv', 'html', 'json', 'latex', 'ods', 'rst', 'tsv', 'xls', 'xlsx',
|
|
92
|
+
'yaml']
|
|
93
|
+
assert data['csv'].mimetype == 'text/csv'
|
|
94
|
+
assert data['csv'].label == 'Export selected as CSV'
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def test_get_supported_export_types_import_error():
|
|
98
|
+
with patch('cms_qe.export.getattr') as mock_getattr:
|
|
99
|
+
mock_getattr.side_effect = ImportError()
|
|
100
|
+
data = get_supported_export_types()
|
|
101
|
+
assert data == {}
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def test_get_supported_export_types_attribute_error():
|
|
105
|
+
with patch('cms_qe.export.getattr') as mock_getattr:
|
|
106
|
+
mock_getattr.side_effect = AttributeError()
|
|
107
|
+
data = get_supported_export_types()
|
|
108
|
+
assert data == {}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
from cms_qe.views import get_monitoring_data
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_get_monitoring_data():
|
|
7
|
+
data = get_monitoring_data()
|
|
8
|
+
assert data['status']
|
|
9
|
+
assert 'cms_qe' in data['app_details']
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_monitoring_view(client):
|
|
13
|
+
result = client.get('/api/monitoring').content
|
|
14
|
+
data = json.loads(str(result, 'utf8'))
|
|
15
|
+
assert data['status']
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
from unittest.mock import patch
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
from django.test import override_settings
|
|
5
|
+
from mailqueue.models import MailerMessage
|
|
6
|
+
from pytest_data import use_data
|
|
7
|
+
|
|
8
|
+
from cms_qe.utils import get_base_url, get_functions, get_module, get_modules
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@pytest.mark.parametrize('expect,module_name', [
|
|
12
|
+
(True, 'views'),
|
|
13
|
+
(True, 'views.monitoring'),
|
|
14
|
+
(False, 'no_module'),
|
|
15
|
+
(False, 'monitoring.get_status'),
|
|
16
|
+
])
|
|
17
|
+
def test_get_module(expect, module_name):
|
|
18
|
+
module = get_module('cms_qe', module_name)
|
|
19
|
+
assert module if expect else module is None
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def test_get_modules():
|
|
23
|
+
modules = get_modules('monitoring')
|
|
24
|
+
assert [module for app_name, module in modules if app_name == 'cms_qe']
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def test_get_functions():
|
|
28
|
+
functions = get_functions('monitoring', 'get_status')
|
|
29
|
+
assert [function for app_name, function in functions if app_name == 'cms_qe']
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_get_functions_existing_module_without_function():
|
|
33
|
+
functions = get_functions('monitoring', 'no_function')
|
|
34
|
+
assert not list(functions)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@override_settings(META_SITE_PROTOCOL='https', )
|
|
38
|
+
def test_get_absolute_url(post_request_empty):
|
|
39
|
+
request = post_request_empty
|
|
40
|
+
mock_url = 'test.com'
|
|
41
|
+
with patch('cms_qe.utils.get_current_site', return_value=mock_url):
|
|
42
|
+
base_url = get_base_url(request)
|
|
43
|
+
assert base_url == f'https://{mock_url}'
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def test_sending_email_synchronously(email, mailoutbox):
|
|
47
|
+
assert len(mailoutbox) == 0
|
|
48
|
+
email.save()
|
|
49
|
+
assert len(mailoutbox) == 1
|
|
50
|
+
sent_mail = mailoutbox[0]
|
|
51
|
+
assert 'Test content' in sent_mail.body
|
|
52
|
+
assert 'Test' in sent_mail.subject
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@override_settings(MAILQUEUE_QUEUE_UP=True)
|
|
56
|
+
def test_sending_email_asynchronously(email, mailoutbox):
|
|
57
|
+
assert MailerMessage.objects.all().count() == 0
|
|
58
|
+
email.save()
|
|
59
|
+
assert len(mailoutbox) == 0
|
|
60
|
+
assert MailerMessage.objects.all().count() == 1
|
|
61
|
+
assert 'Test content' in MailerMessage.objects.all().first().content
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@use_data(email_data={'to': ['test1@examile.com', 'test2@examile.com']})
|
|
65
|
+
def test_sending_email_synchronously_more_addressee(email, mailoutbox):
|
|
66
|
+
email.save()
|
|
67
|
+
assert len(mailoutbox) == 1
|
|
68
|
+
sent_mail = mailoutbox[0]
|
|
69
|
+
assert len(sent_mail.to) == 2
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@use_data(email_data={'to': ['test1@examile.com', 'test2@examile.com']})
|
|
73
|
+
@override_settings(MAILQUEUE_QUEUE_UP=True)
|
|
74
|
+
def test_sending_email_asynchronously_more_to_addressee(email, mailoutbox):
|
|
75
|
+
email.save()
|
|
76
|
+
assert MailerMessage.objects.all().count() == 1
|
|
77
|
+
assert MailerMessage.objects.all().first().to_address == 'test1@examile.com, test2@examile.com'
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from constance import config
|
|
2
|
+
from django.test import TestCase
|
|
3
|
+
from django.urls import reverse
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class SecurityTxtViewTest(TestCase):
|
|
7
|
+
|
|
8
|
+
def test_not_content(self):
|
|
9
|
+
config.SECURITY_TXT_CONTENT = None
|
|
10
|
+
response = self.client.get(reverse('security-txt'))
|
|
11
|
+
self.assertRedirects(response, "/en/.well-known/security.txt/",
|
|
12
|
+
status_code=302, target_status_code=404)
|
|
13
|
+
|
|
14
|
+
def test_content(self):
|
|
15
|
+
config.SECURITY_TXT_CONTENT = 'Contact: https://abuse.foo'
|
|
16
|
+
response = self.client.get(reverse('security-txt'))
|
|
17
|
+
self.assertContains(response, b'Contact: https://abuse.foo')
|
|
18
|
+
self.assertEqual(response['Content-Type'], 'text/plain')
|
cms_qe/views/maintenance.py
CHANGED
|
@@ -2,6 +2,7 @@ from django.conf import settings
|
|
|
2
2
|
from django.contrib.sites.models import Site
|
|
3
3
|
from django.core.cache import cache
|
|
4
4
|
from django.http import HttpRequest, HttpResponse
|
|
5
|
+
from django.utils.module_loading import import_string
|
|
5
6
|
from django.views import View
|
|
6
7
|
|
|
7
8
|
from cms_qe.signals import run_subprocess
|
|
@@ -21,6 +22,11 @@ class HealthCheckView(View):
|
|
|
21
22
|
cache.set(key, 'OK', 2)
|
|
22
23
|
if cache.get(key) != 'OK':
|
|
23
24
|
raise RuntimeError('cache')
|
|
25
|
+
# More checks if defined in HEALTHCHECK_FUNCTIONS = ["path1.to.fnc, "path2.to.fnc"].
|
|
26
|
+
if hasattr(settings, "HEALTHCHECK_FUNCTIONS"):
|
|
27
|
+
for path in settings.HEALTHCHECK_FUNCTIONS:
|
|
28
|
+
fnc = import_string(path)
|
|
29
|
+
fnc(request, *args, **kwargs)
|
|
24
30
|
return HttpResponse("OK", content_type="text/plain")
|
|
25
31
|
|
|
26
32
|
|
|
File without changes
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""
|
|
2
|
+
django-analytical testing settings.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
DATABASES = {
|
|
6
|
+
'default': {
|
|
7
|
+
'ENGINE': 'django.db.backends.sqlite3',
|
|
8
|
+
'NAME': ':memory:',
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
INSTALLED_APPS = [
|
|
13
|
+
'django.contrib.sites',
|
|
14
|
+
'django.contrib.contenttypes',
|
|
15
|
+
'django.contrib.auth',
|
|
16
|
+
'analytical',
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
SECRET_KEY = 'testing'
|
|
20
|
+
|
|
21
|
+
MIDDLEWARE_CLASSES = (
|
|
22
|
+
'django.middleware.common.CommonMiddleware',
|
|
23
|
+
'django.middleware.csrf.CsrfViewMiddleware',
|
|
24
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Dummy testing template tags and filters.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
from analytical.templatetags.analytical import TAG_LOCATIONS
|
|
7
|
+
from django.template import Library, Node, TemplateSyntaxError
|
|
8
|
+
|
|
9
|
+
register = Library()
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _location_node(location):
|
|
13
|
+
class DummyNode(Node):
|
|
14
|
+
def render(self, context):
|
|
15
|
+
return f"<!-- dummy_{location} -->"
|
|
16
|
+
return DummyNode
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
_location_nodes = {loc: _location_node(loc) for loc in TAG_LOCATIONS}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _location_tag(location):
|
|
23
|
+
def dummy_tag(parser, token):
|
|
24
|
+
bits = token.split_contents()
|
|
25
|
+
if len(bits) > 1:
|
|
26
|
+
raise TemplateSyntaxError(f"'{bits[0]}' tag takes no arguments")
|
|
27
|
+
return _location_nodes[location]
|
|
28
|
+
return dummy_tag
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
for loc in TAG_LOCATIONS:
|
|
32
|
+
register.tag(f'dummy_{loc}', _location_tag(loc))
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def contribute_to_analytical(add_node_cls):
|
|
36
|
+
for location in TAG_LOCATIONS:
|
|
37
|
+
add_node_cls(location, _location_nodes[location])
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tests for the Google Analytics template tags and filters.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from constance.test import override_config
|
|
6
|
+
from django.http import HttpRequest
|
|
7
|
+
from django.template import Context
|
|
8
|
+
from django.test import override_settings
|
|
9
|
+
|
|
10
|
+
from ..templatetags.google_analytics import (SCOPE_PAGE, SCOPE_SESSION, SCOPE_VISITOR, TRACK_MULTIPLE_DOMAINS,
|
|
11
|
+
TRACK_MULTIPLE_SUBDOMAINS, TRACK_SINGLE_DOMAIN, GoogleAnalyticsNode)
|
|
12
|
+
from ..tests.utils import TagTestCase
|
|
13
|
+
from ..utils import AnalyticalException
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@override_settings(GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_SINGLE_DOMAIN)
|
|
17
|
+
@override_config(GOOGLE_ANALYTICS_PROPERTY_ID='UA-123456-7')
|
|
18
|
+
class GoogleAnalyticsTagTestCase(TagTestCase):
|
|
19
|
+
"""
|
|
20
|
+
Tests for the ``google_analytics`` template tag.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def test_tag(self):
|
|
24
|
+
r = self.render_tag('google_analytics', 'google_analytics')
|
|
25
|
+
self.assertTrue("_gaq.push(['_setAccount', 'UA-123456-7']);" in r, r)
|
|
26
|
+
self.assertTrue("_gaq.push(['_trackPageview']);" in r, r)
|
|
27
|
+
|
|
28
|
+
def test_node(self):
|
|
29
|
+
r = GoogleAnalyticsNode().render(Context())
|
|
30
|
+
self.assertTrue("_gaq.push(['_setAccount', 'UA-123456-7']);" in r, r)
|
|
31
|
+
self.assertTrue("_gaq.push(['_trackPageview']);" in r, r)
|
|
32
|
+
|
|
33
|
+
@override_config(GOOGLE_ANALYTICS_PROPERTY_ID='wrong')
|
|
34
|
+
def test_wrong_property_id(self):
|
|
35
|
+
self.assertEqual(GoogleAnalyticsNode().render({}), '')
|
|
36
|
+
|
|
37
|
+
@override_settings(
|
|
38
|
+
GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_MULTIPLE_SUBDOMAINS,
|
|
39
|
+
GOOGLE_ANALYTICS_DOMAIN='example.com')
|
|
40
|
+
def test_track_multiple_subdomains(self):
|
|
41
|
+
r = GoogleAnalyticsNode().render(Context())
|
|
42
|
+
self.assertTrue("_gaq.push(['_setDomainName', 'example.com']);" in r, r)
|
|
43
|
+
self.assertTrue("_gaq.push(['_setAllowHash', false]);" in r, r)
|
|
44
|
+
|
|
45
|
+
@override_settings(GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_MULTIPLE_DOMAINS,
|
|
46
|
+
GOOGLE_ANALYTICS_DOMAIN='example.com')
|
|
47
|
+
def test_track_multiple_domains(self):
|
|
48
|
+
r = GoogleAnalyticsNode().render(Context())
|
|
49
|
+
self.assertTrue("_gaq.push(['_setDomainName', 'example.com']);" in r, r)
|
|
50
|
+
self.assertTrue("_gaq.push(['_setAllowHash', false]);" in r, r)
|
|
51
|
+
self.assertTrue("_gaq.push(['_setAllowLinker', true]);" in r, r)
|
|
52
|
+
|
|
53
|
+
def test_custom_vars(self):
|
|
54
|
+
context = Context({
|
|
55
|
+
'google_analytics_var1': ('test1', 'foo'),
|
|
56
|
+
'google_analytics_var2': ('test2', 'bar', SCOPE_VISITOR),
|
|
57
|
+
'google_analytics_var4': ('test4', 'baz', SCOPE_SESSION),
|
|
58
|
+
'google_analytics_var5': ('test5', 'qux', SCOPE_PAGE),
|
|
59
|
+
})
|
|
60
|
+
r = GoogleAnalyticsNode().render(context)
|
|
61
|
+
self.assertTrue("_gaq.push(['_setCustomVar', 1, 'test1', 'foo', 3]);"
|
|
62
|
+
in r, r)
|
|
63
|
+
self.assertTrue("_gaq.push(['_setCustomVar', 2, 'test2', 'bar', 1]);"
|
|
64
|
+
in r, r)
|
|
65
|
+
self.assertTrue("_gaq.push(['_setCustomVar', 4, 'test4', 'baz', 2]);"
|
|
66
|
+
in r, r)
|
|
67
|
+
self.assertTrue("_gaq.push(['_setCustomVar', 5, 'test5', 'qux', 3]);"
|
|
68
|
+
in r, r)
|
|
69
|
+
|
|
70
|
+
@override_config(GOOGLE_ANALYTICS_SITE_SPEED=True)
|
|
71
|
+
def test_track_page_load_time(self):
|
|
72
|
+
r = GoogleAnalyticsNode().render(Context())
|
|
73
|
+
self.assertTrue("_gaq.push(['_trackPageLoadTime']);" in r, r)
|
|
74
|
+
|
|
75
|
+
def test_display_advertising(self):
|
|
76
|
+
with override_config(GOOGLE_ANALYTICS_DISPLAY_ADVERTISING=False):
|
|
77
|
+
r = GoogleAnalyticsNode().render(Context())
|
|
78
|
+
self.assertTrue("google-analytics.com/ga.js" in r, r)
|
|
79
|
+
with override_config(GOOGLE_ANALYTICS_DISPLAY_ADVERTISING=True):
|
|
80
|
+
r = GoogleAnalyticsNode().render(Context())
|
|
81
|
+
self.assertTrue("stats.g.doubleclick.net/dc.js" in r, r)
|
|
82
|
+
|
|
83
|
+
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
|
|
84
|
+
def test_render_internal_ip(self):
|
|
85
|
+
req = HttpRequest()
|
|
86
|
+
req.META['REMOTE_ADDR'] = '1.1.1.1'
|
|
87
|
+
context = Context({'request': req})
|
|
88
|
+
r = GoogleAnalyticsNode().render(context)
|
|
89
|
+
self.assertTrue(r.startswith(
|
|
90
|
+
'<!-- Google Analytics disabled on internal IP address'), r)
|
|
91
|
+
self.assertTrue(r.endswith('-->'), r)
|
|
92
|
+
|
|
93
|
+
@override_config(GOOGLE_ANALYTICS_ANONYMIZE_IP=True)
|
|
94
|
+
def test_anonymize_ip(self):
|
|
95
|
+
r = GoogleAnalyticsNode().render(Context())
|
|
96
|
+
self.assertTrue("_gaq.push (['_gat._anonymizeIp']);" in r, r)
|
|
97
|
+
|
|
98
|
+
@override_config(GOOGLE_ANALYTICS_ANONYMIZE_IP=False)
|
|
99
|
+
def test_anonymize_ip_not_present(self):
|
|
100
|
+
r = GoogleAnalyticsNode().render(Context())
|
|
101
|
+
self.assertFalse("_gaq.push (['_gat._anonymizeIp']);" in r, r)
|
|
102
|
+
|
|
103
|
+
@override_config(GOOGLE_ANALYTICS_SAMPLE_RATE=0.0)
|
|
104
|
+
def test_set_sample_rate_min(self):
|
|
105
|
+
r = GoogleAnalyticsNode().render(Context())
|
|
106
|
+
self.assertTrue("_gaq.push (['_setSampleRate', '0.00']);" in r, r)
|
|
107
|
+
|
|
108
|
+
@override_config(GOOGLE_ANALYTICS_SAMPLE_RATE='100.00')
|
|
109
|
+
def test_set_sample_rate_max(self):
|
|
110
|
+
r = GoogleAnalyticsNode().render(Context())
|
|
111
|
+
self.assertTrue("_gaq.push (['_setSampleRate', '100.00']);" in r, r)
|
|
112
|
+
|
|
113
|
+
#
|
|
114
|
+
@override_config(GOOGLE_ANALYTICS_SAMPLE_RATE=-1)
|
|
115
|
+
def test_exception_whenset_sample_rate_too_small(self):
|
|
116
|
+
context = Context()
|
|
117
|
+
self.assertRaises(AnalyticalException, GoogleAnalyticsNode().render,
|
|
118
|
+
context)
|
|
119
|
+
|
|
120
|
+
@override_config(GOOGLE_ANALYTICS_SAMPLE_RATE=101)
|
|
121
|
+
def test_exception_when_set_sample_rate_too_large(self):
|
|
122
|
+
context = Context()
|
|
123
|
+
self.assertRaises(AnalyticalException, GoogleAnalyticsNode().render,
|
|
124
|
+
context)
|
|
125
|
+
|
|
126
|
+
@override_config(GOOGLE_ANALYTICS_SITE_SPEED_SAMPLE_RATE=0.0)
|
|
127
|
+
def test_set_site_speed_sample_rate_min(self):
|
|
128
|
+
r = GoogleAnalyticsNode().render(Context())
|
|
129
|
+
self.assertTrue("_gaq.push (['_setSiteSpeedSampleRate', '0.00']);" in r, r)
|
|
130
|
+
|
|
131
|
+
@override_config(GOOGLE_ANALYTICS_SITE_SPEED_SAMPLE_RATE='100.00')
|
|
132
|
+
def test_set_site_speed_sample_rate_max(self):
|
|
133
|
+
r = GoogleAnalyticsNode().render(Context())
|
|
134
|
+
self.assertTrue("_gaq.push (['_setSiteSpeedSampleRate', '100.00']);" in r, r)
|
|
135
|
+
|
|
136
|
+
@override_config(GOOGLE_ANALYTICS_SITE_SPEED_SAMPLE_RATE=-1)
|
|
137
|
+
def test_exception_whenset_site_speed_sample_rate_too_small(self):
|
|
138
|
+
context = Context()
|
|
139
|
+
self.assertRaises(AnalyticalException, GoogleAnalyticsNode().render,
|
|
140
|
+
context)
|
|
141
|
+
|
|
142
|
+
@override_config(GOOGLE_ANALYTICS_SITE_SPEED_SAMPLE_RATE=101)
|
|
143
|
+
def test_exception_when_set_site_speed_sample_rate_too_large(self):
|
|
144
|
+
context = Context()
|
|
145
|
+
self.assertRaises(AnalyticalException, GoogleAnalyticsNode().render,
|
|
146
|
+
context)
|
|
147
|
+
|
|
148
|
+
@override_config(GOOGLE_ANALYTICS_SESSION_COOKIE_TIMEOUT=0)
|
|
149
|
+
def test_set_session_cookie_timeout_min(self):
|
|
150
|
+
r = GoogleAnalyticsNode().render(Context())
|
|
151
|
+
self.assertTrue("_gaq.push (['_setSessionCookieTimeout', '0']);" in r, r)
|
|
152
|
+
|
|
153
|
+
@override_config(GOOGLE_ANALYTICS_SESSION_COOKIE_TIMEOUT='10000')
|
|
154
|
+
def test_set_session_cookie_timeout_as_string(self):
|
|
155
|
+
r = GoogleAnalyticsNode().render(Context())
|
|
156
|
+
self.assertTrue("_gaq.push (['_setSessionCookieTimeout', '10000']);" in r, r)
|
|
157
|
+
|
|
158
|
+
@override_config(GOOGLE_ANALYTICS_SESSION_COOKIE_TIMEOUT=-1)
|
|
159
|
+
def test_exception_when_set_session_cookie_timeout_too_small(self):
|
|
160
|
+
context = Context()
|
|
161
|
+
self.assertRaises(AnalyticalException, GoogleAnalyticsNode().render,
|
|
162
|
+
context)
|
|
163
|
+
|
|
164
|
+
@override_config(GOOGLE_ANALYTICS_VISITOR_COOKIE_TIMEOUT=0)
|
|
165
|
+
def test_set_visitor_cookie_timeout_min(self):
|
|
166
|
+
r = GoogleAnalyticsNode().render(Context())
|
|
167
|
+
self.assertTrue("_gaq.push (['_setVisitorCookieTimeout', '0']);" in r, r)
|
|
168
|
+
|
|
169
|
+
@override_config(GOOGLE_ANALYTICS_VISITOR_COOKIE_TIMEOUT='10000')
|
|
170
|
+
def test_set_visitor_cookie_timeout_as_string(self):
|
|
171
|
+
r = GoogleAnalyticsNode().render(Context())
|
|
172
|
+
self.assertTrue("_gaq.push (['_setVisitorCookieTimeout', '10000']);" in r, r)
|
|
173
|
+
|
|
174
|
+
@override_config(GOOGLE_ANALYTICS_VISITOR_COOKIE_TIMEOUT=-1)
|
|
175
|
+
def test_exception_when_set_visitor_cookie_timeout_too_small(self):
|
|
176
|
+
context = Context()
|
|
177
|
+
self.assertRaises(AnalyticalException, GoogleAnalyticsNode().render,
|
|
178
|
+
context)
|