Applied isort and black to project

This commit is contained in:
David Smith 2020-12-06 16:49:43 +00:00
parent 8cd75d9e60
commit ad7f229a8c
66 changed files with 2069 additions and 1488 deletions

View file

@ -3,45 +3,44 @@ Analytical template tags and filters.
"""
import logging
from importlib import import_module
from django import template
from django.template import Node, TemplateSyntaxError
from importlib import import_module
from analytical.utils import AnalyticalException
TAG_LOCATIONS = ['head_top', 'head_bottom', 'body_top', 'body_bottom']
TAG_POSITIONS = ['first', None, 'last']
TAG_LOCATIONS = ["head_top", "head_bottom", "body_top", "body_bottom"]
TAG_POSITIONS = ["first", None, "last"]
TAG_MODULES = [
'analytical.chartbeat',
'analytical.clickmap',
'analytical.clicky',
'analytical.crazy_egg',
'analytical.facebook_pixel',
'analytical.gauges',
'analytical.google_analytics',
'analytical.google_analytics_js',
'analytical.google_analytics_gtag',
'analytical.gosquared',
'analytical.hotjar',
'analytical.hubspot',
'analytical.intercom',
'analytical.kiss_insights',
'analytical.kiss_metrics',
'analytical.luckyorange',
'analytical.matomo',
'analytical.mixpanel',
'analytical.olark',
'analytical.optimizely',
'analytical.performable',
'analytical.piwik',
'analytical.rating_mailru',
'analytical.snapengage',
'analytical.spring_metrics',
'analytical.uservoice',
'analytical.woopra',
'analytical.yandex_metrica',
"analytical.chartbeat",
"analytical.clickmap",
"analytical.clicky",
"analytical.crazy_egg",
"analytical.facebook_pixel",
"analytical.gauges",
"analytical.google_analytics",
"analytical.google_analytics_js",
"analytical.google_analytics_gtag",
"analytical.gosquared",
"analytical.hotjar",
"analytical.hubspot",
"analytical.intercom",
"analytical.kiss_insights",
"analytical.kiss_metrics",
"analytical.luckyorange",
"analytical.matomo",
"analytical.mixpanel",
"analytical.olark",
"analytical.optimizely",
"analytical.performable",
"analytical.piwik",
"analytical.rating_mailru",
"analytical.snapengage",
"analytical.spring_metrics",
"analytical.uservoice",
"analytical.woopra",
"analytical.yandex_metrica",
]
logger = logging.getLogger(__name__)
@ -59,7 +58,7 @@ def _location_tag(location):
for loc in TAG_LOCATIONS:
register.tag('analytical_%s' % loc, _location_tag(loc))
register.tag("analytical_%s" % loc, _location_tag(loc))
class AnalyticalNode(Node):
@ -83,13 +82,14 @@ def _load_template_nodes():
except AnalyticalException as e:
logger.debug("not loading tags from '%s': %s", path, e)
for location in TAG_LOCATIONS:
template_nodes[location] = sum((template_nodes[location][p]
for p in TAG_POSITIONS), [])
template_nodes[location] = sum(
(template_nodes[location][p] for p in TAG_POSITIONS), []
)
return template_nodes
def _import_tag_module(path):
app_name, lib_name = path.rsplit('.', 1)
app_name, lib_name = path.rsplit(".", 1)
return import_module("%s.templatetags.%s" % (app_name, lib_name))

View file

@ -9,11 +9,12 @@ from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import is_internal_ip, disable_html, get_required_setting
from analytical.utils import disable_html, get_required_setting, is_internal_ip
USER_ID_RE = re.compile(r'^\d+$')
INIT_CODE = """<script type="text/javascript">var _sf_startpt=(new Date()).getTime()</script>"""
USER_ID_RE = re.compile(r"^\d+$")
INIT_CODE = (
"""<script type="text/javascript">var _sf_startpt=(new Date()).getTime()</script>"""
)
SETUP_CODE = """
<script type="text/javascript">
var _sf_async_config=%(config)s;
@ -34,7 +35,7 @@ SETUP_CODE = """
})();
</script>
""" # noqa
DOMAIN_CONTEXT_KEY = 'chartbeat_domain'
DOMAIN_CONTEXT_KEY = "chartbeat_domain"
register = Library()
@ -77,24 +78,25 @@ def chartbeat_bottom(parser, token):
class ChartbeatBottomNode(Node):
def __init__(self):
self.user_id = get_required_setting('CHARTBEAT_USER_ID', USER_ID_RE,
"must be (a string containing) a number")
self.user_id = get_required_setting(
"CHARTBEAT_USER_ID", USER_ID_RE, "must be (a string containing) a number"
)
def render(self, context):
config = {'uid': self.user_id}
config = {"uid": self.user_id}
domain = _get_domain(context)
if domain is not None:
config['domain'] = domain
html = SETUP_CODE % {'config': json.dumps(config, sort_keys=True)}
if is_internal_ip(context, 'CHARTBEAT'):
html = disable_html(html, 'Chartbeat')
config["domain"] = domain
html = SETUP_CODE % {"config": json.dumps(config, sort_keys=True)}
if is_internal_ip(context, "CHARTBEAT"):
html = disable_html(html, "Chartbeat")
return html
def contribute_to_analytical(add_node):
ChartbeatBottomNode() # ensure properly configured
add_node('head_top', ChartbeatTopNode, 'first')
add_node('body_bottom', ChartbeatBottomNode, 'last')
add_node("head_top", ChartbeatTopNode, "first")
add_node("body_bottom", ChartbeatBottomNode, "last")
def _get_domain(context):
@ -103,10 +105,11 @@ def _get_domain(context):
if domain is not None:
return domain
else:
if 'django.contrib.sites' not in settings.INSTALLED_APPS:
if "django.contrib.sites" not in settings.INSTALLED_APPS:
return
elif getattr(settings, 'CHARTBEAT_AUTO_DOMAIN', True):
elif getattr(settings, "CHARTBEAT_AUTO_DOMAIN", True):
from django.contrib.sites.models import Site
try:
return Site.objects.get_current().domain
except (ImproperlyConfigured, Site.DoesNotExist): # pylint: disable=E1101

View file

@ -6,10 +6,9 @@ import re
from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import is_internal_ip, disable_html, get_required_setting
from analytical.utils import disable_html, get_required_setting, is_internal_ip
CLICKMAP_TRACKER_ID_RE = re.compile(r'^\w+$')
CLICKMAP_TRACKER_ID_RE = re.compile(r"^\w+$")
TRACKING_CODE = """
<script type="text/javascript">
var clickmapConfig = {tracker: '%(tracker_id)s', version:'2'};
@ -43,17 +42,19 @@ def clickmap(parser, token):
class ClickmapNode(Node):
def __init__(self):
self.tracker_id = get_required_setting('CLICKMAP_TRACKER_ID',
CLICKMAP_TRACKER_ID_RE,
"must be an alphanumeric string")
self.tracker_id = get_required_setting(
"CLICKMAP_TRACKER_ID",
CLICKMAP_TRACKER_ID_RE,
"must be an alphanumeric string",
)
def render(self, context):
html = TRACKING_CODE % {'tracker_id': self.tracker_id}
if is_internal_ip(context, 'CLICKMAP'):
html = disable_html(html, 'Clickmap')
html = TRACKING_CODE % {"tracker_id": self.tracker_id}
if is_internal_ip(context, "CLICKMAP"):
html = disable_html(html, "Clickmap")
return html
def contribute_to_analytical(add_node):
ClickmapNode() # ensure properly configured
add_node('body_bottom', ClickmapNode)
add_node("body_bottom", ClickmapNode)

View file

@ -7,11 +7,14 @@ import re
from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import get_identity, is_internal_ip, disable_html, \
get_required_setting
from analytical.utils import (
disable_html,
get_identity,
get_required_setting,
is_internal_ip,
)
SITE_ID_RE = re.compile(r'^\d+$')
SITE_ID_RE = re.compile(r"^\d+$")
TRACKING_CODE = """
<script type="text/javascript">
var clicky = { log: function(){ return; }, goal: function(){ return; }};
@ -50,29 +53,29 @@ def clicky(parser, token):
class ClickyNode(Node):
def __init__(self):
self.site_id = get_required_setting(
'CLICKY_SITE_ID', SITE_ID_RE,
"must be a (string containing) a number")
"CLICKY_SITE_ID", SITE_ID_RE, "must be a (string containing) a number"
)
def render(self, context):
custom = {}
for dict_ in context:
for var, val in dict_.items():
if var.startswith('clicky_'):
if var.startswith("clicky_"):
custom[var[7:]] = val
if 'username' not in custom.get('session', {}):
identity = get_identity(context, 'clicky')
if "username" not in custom.get("session", {}):
identity = get_identity(context, "clicky")
if identity is not None:
custom.setdefault('session', {})['username'] = identity
custom.setdefault("session", {})["username"] = identity
html = TRACKING_CODE % {
'site_id': self.site_id,
'custom': json.dumps(custom, sort_keys=True),
"site_id": self.site_id,
"custom": json.dumps(custom, sort_keys=True),
}
if is_internal_ip(context, 'CLICKY'):
html = disable_html(html, 'Clicky')
if is_internal_ip(context, "CLICKY"):
html = disable_html(html, "Clicky")
return html
def contribute_to_analytical(add_node):
ClickyNode() # ensure properly configured
add_node('body_bottom', ClickyNode)
add_node("body_bottom", ClickyNode)

View file

@ -6,14 +6,16 @@ import re
from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import is_internal_ip, disable_html, get_required_setting
from analytical.utils import disable_html, get_required_setting, is_internal_ip
ACCOUNT_NUMBER_RE = re.compile(r'^\d+$')
SETUP_CODE = '<script type="text/javascript" src="{placeholder_url}">' \
'</script>'.\
format(placeholder_url='//dnn506yrbagrg.cloudfront.net/pages/scripts/'
'%(account_nr_1)s/%(account_nr_2)s.js')
ACCOUNT_NUMBER_RE = re.compile(r"^\d+$")
SETUP_CODE = (
'<script type="text/javascript" src="{placeholder_url}">'
"</script>".format(
placeholder_url="//dnn506yrbagrg.cloudfront.net/pages/scripts/"
"%(account_nr_1)s/%(account_nr_2)s.js"
)
)
USERVAR_CODE = "CE2.set(%(varnr)d, '%(value)s');"
@ -38,29 +40,33 @@ def crazy_egg(parser, token):
class CrazyEggNode(Node):
def __init__(self):
self.account_nr = get_required_setting(
'CRAZY_EGG_ACCOUNT_NUMBER',
ACCOUNT_NUMBER_RE, "must be (a string containing) a number"
"CRAZY_EGG_ACCOUNT_NUMBER",
ACCOUNT_NUMBER_RE,
"must be (a string containing) a number",
)
def render(self, context):
html = SETUP_CODE % {
'account_nr_1': self.account_nr[:4],
'account_nr_2': self.account_nr[4:],
"account_nr_1": self.account_nr[:4],
"account_nr_2": self.account_nr[4:],
}
values = (context.get('crazy_egg_var%d' % i) for i in range(1, 6))
values = (context.get("crazy_egg_var%d" % i) for i in range(1, 6))
params = [(i, v) for i, v in enumerate(values, 1) if v is not None]
if params:
js = " ".join(USERVAR_CODE % {
'varnr': varnr,
'value': value,
} for (varnr, value) in params)
html = '%s\n' \
'<script type="text/javascript">%s</script>' % (html, js)
if is_internal_ip(context, 'CRAZY_EGG'):
html = disable_html(html, 'Crazy Egg')
js = " ".join(
USERVAR_CODE
% {
"varnr": varnr,
"value": value,
}
for (varnr, value) in params
)
html = "%s\n" '<script type="text/javascript">%s</script>' % (html, js)
if is_internal_ip(context, "CRAZY_EGG"):
html = disable_html(html, "Crazy Egg")
return html
def contribute_to_analytical(add_node):
CrazyEggNode() # ensure properly configured
add_node('body_bottom', CrazyEggNode)
add_node("body_bottom", CrazyEggNode)

View file

@ -6,8 +6,7 @@ import re
from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import get_required_setting, is_internal_ip, disable_html
from analytical.utils import disable_html, get_required_setting, is_internal_ip
FACEBOOK_PIXEL_HEAD_CODE = """\
<script>
@ -61,17 +60,18 @@ class _FacebookPixelNode(Node):
"""
Base class: override and provide code_template.
"""
def __init__(self):
self.pixel_id = get_required_setting(
'FACEBOOK_PIXEL_ID',
re.compile(r'^\d+$'),
"FACEBOOK_PIXEL_ID",
re.compile(r"^\d+$"),
"must be (a string containing) a number",
)
def render(self, context):
html = self.code_template % {'FACEBOOK_PIXEL_ID': self.pixel_id}
if is_internal_ip(context, 'FACEBOOK_PIXEL'):
return disable_html(html, 'Facebook Pixel')
html = self.code_template % {"FACEBOOK_PIXEL_ID": self.pixel_id}
if is_internal_ip(context, "FACEBOOK_PIXEL"):
return disable_html(html, "Facebook Pixel")
else:
return html
@ -92,5 +92,5 @@ def contribute_to_analytical(add_node):
# ensure properly configured
FacebookPixelHeadNode()
FacebookPixelBodyNode()
add_node('head_bottom', FacebookPixelHeadNode)
add_node('body_bottom', FacebookPixelBodyNode)
add_node("head_bottom", FacebookPixelHeadNode)
add_node("body_bottom", FacebookPixelBodyNode)

View file

@ -6,9 +6,9 @@ import re
from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import is_internal_ip, disable_html, get_required_setting
from analytical.utils import disable_html, get_required_setting, is_internal_ip
SITE_ID_RE = re.compile(r'[\da-f]+$')
SITE_ID_RE = re.compile(r"[\da-f]+$")
TRACKING_CODE = """
<script type="text/javascript">
var _gauges = _gauges || [];
@ -46,16 +46,16 @@ def gauges(parser, token):
class GaugesNode(Node):
def __init__(self):
self.site_id = get_required_setting(
'GAUGES_SITE_ID', SITE_ID_RE,
"must be a string looking like 'XXXXXXX'")
"GAUGES_SITE_ID", SITE_ID_RE, "must be a string looking like 'XXXXXXX'"
)
def render(self, context):
html = TRACKING_CODE % {'site_id': self.site_id}
if is_internal_ip(context, 'GAUGES'):
html = disable_html(html, 'Gauges')
html = TRACKING_CODE % {"site_id": self.site_id}
if is_internal_ip(context, "GAUGES"):
html = disable_html(html, "Gauges")
return html
def contribute_to_analytical(add_node):
GaugesNode()
add_node('head_bottom', GaugesNode)
add_node("head_bottom", GaugesNode)

View file

@ -26,7 +26,7 @@ SCOPE_VISITOR = 1
SCOPE_SESSION = 2
SCOPE_PAGE = 3
PROPERTY_ID_RE = re.compile(r'^UA-\d+-\d+$')
PROPERTY_ID_RE = re.compile(r"^UA-\d+-\d+$")
SETUP_CODE = """
<script type="text/javascript">
@ -45,8 +45,9 @@ DOMAIN_CODE = "_gaq.push(['_setDomainName', '%s']);"
NO_ALLOW_HASH_CODE = "_gaq.push(['_setAllowHash', false]);"
TRACK_PAGE_VIEW = "_gaq.push(['_trackPageview']);"
ALLOW_LINKER_CODE = "_gaq.push(['_setAllowLinker', true]);"
CUSTOM_VAR_CODE = "_gaq.push(['_setCustomVar', %(index)s, '%(name)s', " \
"'%(value)s', %(scope)s]);"
CUSTOM_VAR_CODE = (
"_gaq.push(['_setCustomVar', %(index)s, '%(name)s', " "'%(value)s', %(scope)s]);"
)
SITE_SPEED_CODE = "_gaq.push(['_trackPageLoadTime']);"
ANONYMIZE_IP_CODE = "_gaq.push(['_gat._anonymizeIp']);"
SAMPLE_RATE_CODE = "_gaq.push(['_setSampleRate', '%s']);"
@ -54,10 +55,13 @@ SITE_SPEED_SAMPLE_RATE_CODE = "_gaq.push(['_setSiteSpeedSampleRate', '%s']);"
SESSION_COOKIE_TIMEOUT_CODE = "_gaq.push(['_setSessionCookieTimeout', '%s']);"
VISITOR_COOKIE_TIMEOUT_CODE = "_gaq.push(['_setVisitorCookieTimeout', '%s']);"
DEFAULT_SOURCE = ("'https://ssl' : 'http://www'", "'.google-analytics.com/ga.js'")
DISPLAY_ADVERTISING_SOURCE = ("'https://' : 'http://'", "'stats.g.doubleclick.net/dc.js'")
DISPLAY_ADVERTISING_SOURCE = (
"'https://' : 'http://'",
"'stats.g.doubleclick.net/dc.js'",
)
ZEROPLACES = decimal.Decimal('0')
TWOPLACES = decimal.Decimal('0.01')
ZEROPLACES = decimal.Decimal("0")
TWOPLACES = decimal.Decimal("0.01")
register = Library()
@ -80,39 +84,43 @@ def google_analytics(parser, token):
class GoogleAnalyticsNode(Node):
def __init__(self):
self.property_id = get_required_setting(
'GOOGLE_ANALYTICS_PROPERTY_ID', PROPERTY_ID_RE,
"must be a string looking like 'UA-XXXXXX-Y'")
"GOOGLE_ANALYTICS_PROPERTY_ID",
PROPERTY_ID_RE,
"must be a string looking like 'UA-XXXXXX-Y'",
)
def render(self, context):
commands = self._get_domain_commands(context)
commands.extend(self._get_custom_var_commands(context))
commands.extend(self._get_other_commands(context))
commands.append(TRACK_PAGE_VIEW)
if getattr(settings, 'GOOGLE_ANALYTICS_DISPLAY_ADVERTISING', False):
if getattr(settings, "GOOGLE_ANALYTICS_DISPLAY_ADVERTISING", False):
source = DISPLAY_ADVERTISING_SOURCE
else:
source = DEFAULT_SOURCE
html = SETUP_CODE % {
'property_id': self.property_id,
'commands': " ".join(commands),
'source_scheme': source[0],
'source_url': source[1],
"property_id": self.property_id,
"commands": " ".join(commands),
"source_scheme": source[0],
"source_url": source[1],
}
if is_internal_ip(context, 'GOOGLE_ANALYTICS'):
html = disable_html(html, 'Google Analytics')
if is_internal_ip(context, "GOOGLE_ANALYTICS"):
html = disable_html(html, "Google Analytics")
return html
def _get_domain_commands(self, context):
commands = []
tracking_type = getattr(settings, 'GOOGLE_ANALYTICS_TRACKING_STYLE',
TRACK_SINGLE_DOMAIN)
tracking_type = getattr(
settings, "GOOGLE_ANALYTICS_TRACKING_STYLE", TRACK_SINGLE_DOMAIN
)
if tracking_type == TRACK_SINGLE_DOMAIN:
pass
else:
domain = get_domain(context, 'google_analytics')
domain = get_domain(context, "google_analytics")
if domain is None:
raise AnalyticalException(
"tracking multiple domains with Google Analytics requires a domain name")
"tracking multiple domains with Google Analytics requires a domain name"
)
commands.append(DOMAIN_CODE % domain)
commands.append(NO_ALLOW_HASH_CODE)
if tracking_type == TRACK_MULTIPLE_DOMAINS:
@ -120,9 +128,7 @@ class GoogleAnalyticsNode(Node):
return commands
def _get_custom_var_commands(self, context):
values = (
context.get('google_analytics_var%s' % i) for i in range(1, 6)
)
values = (context.get("google_analytics_var%s" % i) for i in range(1, 6))
params = [(i, v) for i, v in enumerate(values, 1) if v is not None]
commands = []
for index, var in params:
@ -132,53 +138,69 @@ class GoogleAnalyticsNode(Node):
scope = var[2]
except IndexError:
scope = SCOPE_PAGE
commands.append(CUSTOM_VAR_CODE % {
'index': index,
'name': name,
'value': value,
'scope': scope,
})
commands.append(
CUSTOM_VAR_CODE
% {
"index": index,
"name": name,
"value": value,
"scope": scope,
}
)
return commands
def _get_other_commands(self, context):
commands = []
if getattr(settings, 'GOOGLE_ANALYTICS_SITE_SPEED', False):
if getattr(settings, "GOOGLE_ANALYTICS_SITE_SPEED", False):
commands.append(SITE_SPEED_CODE)
if getattr(settings, 'GOOGLE_ANALYTICS_ANONYMIZE_IP', False):
if getattr(settings, "GOOGLE_ANALYTICS_ANONYMIZE_IP", False):
commands.append(ANONYMIZE_IP_CODE)
sampleRate = getattr(settings, 'GOOGLE_ANALYTICS_SAMPLE_RATE', False)
sampleRate = getattr(settings, "GOOGLE_ANALYTICS_SAMPLE_RATE", False)
if sampleRate is not False:
value = decimal.Decimal(sampleRate)
if not 0 <= value <= 100:
raise AnalyticalException("'GOOGLE_ANALYTICS_SAMPLE_RATE' must be >= 0 and <= 100")
raise AnalyticalException(
"'GOOGLE_ANALYTICS_SAMPLE_RATE' must be >= 0 and <= 100"
)
commands.append(SAMPLE_RATE_CODE % value.quantize(TWOPLACES))
siteSpeedSampleRate = getattr(settings, 'GOOGLE_ANALYTICS_SITE_SPEED_SAMPLE_RATE', False)
siteSpeedSampleRate = getattr(
settings, "GOOGLE_ANALYTICS_SITE_SPEED_SAMPLE_RATE", False
)
if siteSpeedSampleRate is not False:
value = decimal.Decimal(siteSpeedSampleRate)
if not 0 <= value <= 100:
raise AnalyticalException(
"'GOOGLE_ANALYTICS_SITE_SPEED_SAMPLE_RATE' must be >= 0 and <= 100")
"'GOOGLE_ANALYTICS_SITE_SPEED_SAMPLE_RATE' must be >= 0 and <= 100"
)
commands.append(SITE_SPEED_SAMPLE_RATE_CODE % value.quantize(TWOPLACES))
sessionCookieTimeout = getattr(settings, 'GOOGLE_ANALYTICS_SESSION_COOKIE_TIMEOUT', False)
sessionCookieTimeout = getattr(
settings, "GOOGLE_ANALYTICS_SESSION_COOKIE_TIMEOUT", False
)
if sessionCookieTimeout is not False:
value = decimal.Decimal(sessionCookieTimeout)
if value < 0:
raise AnalyticalException("'GOOGLE_ANALYTICS_SESSION_COOKIE_TIMEOUT' must be >= 0")
raise AnalyticalException(
"'GOOGLE_ANALYTICS_SESSION_COOKIE_TIMEOUT' must be >= 0"
)
commands.append(SESSION_COOKIE_TIMEOUT_CODE % value.quantize(ZEROPLACES))
visitorCookieTimeout = getattr(settings, 'GOOGLE_ANALYTICS_VISITOR_COOKIE_TIMEOUT', False)
visitorCookieTimeout = getattr(
settings, "GOOGLE_ANALYTICS_VISITOR_COOKIE_TIMEOUT", False
)
if visitorCookieTimeout is not False:
value = decimal.Decimal(visitorCookieTimeout)
if value < 0:
raise AnalyticalException("'GOOGLE_ANALYTICS_VISITOR_COOKIE_TIMEOUT' must be >= 0")
raise AnalyticalException(
"'GOOGLE_ANALYTICS_VISITOR_COOKIE_TIMEOUT' must be >= 0"
)
commands.append(VISITOR_COOKIE_TIMEOUT_CODE % value.quantize(ZEROPLACES))
return commands
def contribute_to_analytical(add_node):
GoogleAnalyticsNode() # ensure properly configured
add_node('head_bottom', GoogleAnalyticsNode)
add_node("head_bottom", GoogleAnalyticsNode)

View file

@ -13,7 +13,9 @@ from analytical.utils import (
is_internal_ip,
)
PROPERTY_ID_RE = re.compile(r'^UA-\d+-\d+$|^G-[a-zA-Z0-9]+$|^AW-[a-zA-Z0-9]+$|^DC-[a-zA-Z0-9]+$')
PROPERTY_ID_RE = re.compile(
r"^UA-\d+-\d+$|^G-[a-zA-Z0-9]+$|^AW-[a-zA-Z0-9]+$|^DC-[a-zA-Z0-9]+$"
)
SETUP_CODE = """
<script async src="https://www.googletagmanager.com/gtag/js?id={property_id}"></script>
<script>
@ -49,30 +51,35 @@ def google_analytics_gtag(parser, token):
class GoogleAnalyticsGTagNode(Node):
def __init__(self):
self.property_id = get_required_setting(
'GOOGLE_ANALYTICS_GTAG_PROPERTY_ID', PROPERTY_ID_RE,
'''must be a string looking like one of these patterns
"GOOGLE_ANALYTICS_GTAG_PROPERTY_ID",
PROPERTY_ID_RE,
"""must be a string looking like one of these patterns
('UA-XXXXXX-Y' , 'AW-XXXXXXXXXX',
'G-XXXXXXXX', 'DC-XXXXXXXX')''')
'G-XXXXXXXX', 'DC-XXXXXXXX')""",
)
def render(self, context):
other_fields = {}
identity = get_identity(context)
if identity is not None:
other_fields['user_id'] = identity
other_fields["user_id"] = identity
extra = '\n'.join([
GTAG_SET_CODE.format(key=key, value=value) for key, value in other_fields.items()
])
extra = "\n".join(
[
GTAG_SET_CODE.format(key=key, value=value)
for key, value in other_fields.items()
]
)
html = SETUP_CODE.format(
property_id=self.property_id,
extra=extra,
)
if is_internal_ip(context, 'GOOGLE_ANALYTICS'):
html = disable_html(html, 'Google Analytics')
if is_internal_ip(context, "GOOGLE_ANALYTICS"):
html = disable_html(html, "Google Analytics")
return html
def contribute_to_analytical(add_node):
GoogleAnalyticsGTagNode() # ensure properly configured
add_node('head_top', GoogleAnalyticsGTagNode)
add_node("head_top", GoogleAnalyticsGTagNode)

View file

@ -4,6 +4,7 @@ Google Analytics template tags and filters, using the new analytics.js library.
import decimal
import re
from django.conf import settings
from django.template import Library, Node, TemplateSyntaxError
@ -19,7 +20,7 @@ TRACK_SINGLE_DOMAIN = 1
TRACK_MULTIPLE_SUBDOMAINS = 2
TRACK_MULTIPLE_DOMAINS = 3
PROPERTY_ID_RE = re.compile(r'^UA-\d+-\d+$')
PROPERTY_ID_RE = re.compile(r"^UA-\d+-\d+$")
SETUP_CODE = """
<script>
(function(i,s,o,g,r,a,m){{i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){{
@ -56,16 +57,21 @@ def google_analytics_js(parser, token):
class GoogleAnalyticsJsNode(Node):
def __init__(self):
self.property_id = get_required_setting(
'GOOGLE_ANALYTICS_JS_PROPERTY_ID', PROPERTY_ID_RE,
"must be a string looking like 'UA-XXXXXX-Y'")
"GOOGLE_ANALYTICS_JS_PROPERTY_ID",
PROPERTY_ID_RE,
"must be a string looking like 'UA-XXXXXX-Y'",
)
def render(self, context):
import json
create_fields = self._get_domain_fields(context)
create_fields.update(self._get_other_create_fields(context))
commands = self._get_custom_var_commands(context)
commands.extend(self._get_other_commands(context))
display_features = getattr(settings, 'GOOGLE_ANALYTICS_DISPLAY_ADVERTISING', False)
display_features = getattr(
settings, "GOOGLE_ANALYTICS_DISPLAY_ADVERTISING", False
)
if display_features:
commands.insert(0, REQUIRE_DISPLAY_FEATURES)
@ -74,56 +80,64 @@ class GoogleAnalyticsJsNode(Node):
create_fields=json.dumps(create_fields),
commands="".join(commands),
)
if is_internal_ip(context, 'GOOGLE_ANALYTICS'):
html = disable_html(html, 'Google Analytics')
if is_internal_ip(context, "GOOGLE_ANALYTICS"):
html = disable_html(html, "Google Analytics")
return html
def _get_domain_fields(self, context):
domain_fields = {}
tracking_type = getattr(settings, 'GOOGLE_ANALYTICS_TRACKING_STYLE', TRACK_SINGLE_DOMAIN)
tracking_type = getattr(
settings, "GOOGLE_ANALYTICS_TRACKING_STYLE", TRACK_SINGLE_DOMAIN
)
if tracking_type == TRACK_SINGLE_DOMAIN:
pass
else:
domain = get_domain(context, 'google_analytics')
domain = get_domain(context, "google_analytics")
if domain is None:
raise AnalyticalException(
"tracking multiple domains with Google Analytics requires a domain name")
domain_fields['legacyCookieDomain'] = domain
"tracking multiple domains with Google Analytics requires a domain name"
)
domain_fields["legacyCookieDomain"] = domain
if tracking_type == TRACK_MULTIPLE_DOMAINS:
domain_fields['allowLinker'] = True
domain_fields["allowLinker"] = True
return domain_fields
def _get_other_create_fields(self, context):
other_fields = {}
site_speed_sample_rate = getattr(settings, 'GOOGLE_ANALYTICS_SITE_SPEED_SAMPLE_RATE', False)
site_speed_sample_rate = getattr(
settings, "GOOGLE_ANALYTICS_SITE_SPEED_SAMPLE_RATE", False
)
if site_speed_sample_rate is not False:
value = int(decimal.Decimal(site_speed_sample_rate))
if not 0 <= value <= 100:
raise AnalyticalException(
"'GOOGLE_ANALYTICS_SITE_SPEED_SAMPLE_RATE' must be >= 0 and <= 100")
other_fields['siteSpeedSampleRate'] = value
"'GOOGLE_ANALYTICS_SITE_SPEED_SAMPLE_RATE' must be >= 0 and <= 100"
)
other_fields["siteSpeedSampleRate"] = value
sample_rate = getattr(settings, 'GOOGLE_ANALYTICS_SAMPLE_RATE', False)
sample_rate = getattr(settings, "GOOGLE_ANALYTICS_SAMPLE_RATE", False)
if sample_rate is not False:
value = int(decimal.Decimal(sample_rate))
if not 0 <= value <= 100:
raise AnalyticalException("'GOOGLE_ANALYTICS_SAMPLE_RATE' must be >= 0 and <= 100")
other_fields['sampleRate'] = value
raise AnalyticalException(
"'GOOGLE_ANALYTICS_SAMPLE_RATE' must be >= 0 and <= 100"
)
other_fields["sampleRate"] = value
cookie_expires = getattr(settings, 'GOOGLE_ANALYTICS_COOKIE_EXPIRATION', False)
cookie_expires = getattr(settings, "GOOGLE_ANALYTICS_COOKIE_EXPIRATION", False)
if cookie_expires is not False:
value = int(decimal.Decimal(cookie_expires))
if value < 0:
raise AnalyticalException("'GOOGLE_ANALYTICS_COOKIE_EXPIRATION' must be >= 0")
other_fields['cookieExpires'] = value
raise AnalyticalException(
"'GOOGLE_ANALYTICS_COOKIE_EXPIRATION' must be >= 0"
)
other_fields["cookieExpires"] = value
return other_fields
def _get_custom_var_commands(self, context):
values = (
context.get('google_analytics_var%s' % i) for i in range(1, 6)
)
values = (context.get("google_analytics_var%s" % i) for i in range(1, 6))
params = [(i, v) for i, v in enumerate(values, 1) if v is not None]
commands = []
for _, var in params:
@ -133,16 +147,18 @@ class GoogleAnalyticsJsNode(Node):
float(value)
except ValueError:
value = f"'{value}'"
commands.append(CUSTOM_VAR_CODE.format(
name=name,
value=value,
))
commands.append(
CUSTOM_VAR_CODE.format(
name=name,
value=value,
)
)
return commands
def _get_other_commands(self, context):
commands = []
if getattr(settings, 'GOOGLE_ANALYTICS_ANONYMIZE_IP', False):
if getattr(settings, "GOOGLE_ANALYTICS_ANONYMIZE_IP", False):
commands.append(ANONYMIZE_IP_CODE)
return commands
@ -150,4 +166,4 @@ class GoogleAnalyticsJsNode(Node):
def contribute_to_analytical(add_node):
GoogleAnalyticsJsNode() # ensure properly configured
add_node('head_bottom', GoogleAnalyticsJsNode)
add_node("head_bottom", GoogleAnalyticsJsNode)

View file

@ -6,11 +6,14 @@ import re
from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import get_identity, \
is_internal_ip, disable_html, get_required_setting
from analytical.utils import (
disable_html,
get_identity,
get_required_setting,
is_internal_ip,
)
TOKEN_RE = re.compile(r'^\S+-\S+-\S+$')
TOKEN_RE = re.compile(r"^\S+-\S+-\S+$")
TRACKING_CODE = """
<script type="text/javascript">
var GoSquared={};
@ -49,20 +52,22 @@ def gosquared(parser, token):
class GoSquaredNode(Node):
def __init__(self):
self.site_token = get_required_setting(
'GOSQUARED_SITE_TOKEN', TOKEN_RE,
"must be a string looking like XXX-XXXXXX-X")
"GOSQUARED_SITE_TOKEN",
TOKEN_RE,
"must be a string looking like XXX-XXXXXX-X",
)
def render(self, context):
configs = [TOKEN_CODE % self.site_token]
identity = get_identity(context, 'gosquared', self._identify)
identity = get_identity(context, "gosquared", self._identify)
if identity:
configs.append(IDENTIFY_CODE % identity)
html = TRACKING_CODE % {
'token': self.site_token,
'config': ' '.join(configs),
"token": self.site_token,
"config": " ".join(configs),
}
if is_internal_ip(context, 'GOSQUARED'):
html = disable_html(html, 'GoSquared')
if is_internal_ip(context, "GOSQUARED"):
html = disable_html(html, "GoSquared")
return html
def _identify(self, user):
@ -74,4 +79,4 @@ class GoSquaredNode(Node):
def contribute_to_analytical(add_node):
GoSquaredNode() # ensure properly configured
add_node('body_bottom', GoSquaredNode)
add_node("body_bottom", GoSquaredNode)

View file

@ -6,8 +6,7 @@ import re
from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import get_required_setting, is_internal_ip, disable_html
from analytical.utils import disable_html, get_required_setting, is_internal_ip
HOTJAR_TRACKING_CODE = """\
<script>
@ -42,18 +41,17 @@ def hotjar(parser, token):
class HotjarNode(Node):
def __init__(self):
self.site_id = get_required_setting(
'HOTJAR_SITE_ID',
re.compile(r'^\d+$'),
"HOTJAR_SITE_ID",
re.compile(r"^\d+$"),
"must be (a string containing) a number",
)
def render(self, context):
html = HOTJAR_TRACKING_CODE % {'HOTJAR_SITE_ID': self.site_id}
if is_internal_ip(context, 'HOTJAR'):
return disable_html(html, 'Hotjar')
html = HOTJAR_TRACKING_CODE % {"HOTJAR_SITE_ID": self.site_id}
if is_internal_ip(context, "HOTJAR"):
return disable_html(html, "Hotjar")
else:
return html
@ -61,4 +59,4 @@ class HotjarNode(Node):
def contribute_to_analytical(add_node):
# ensure properly configured
HotjarNode()
add_node('head_bottom', HotjarNode)
add_node("head_bottom", HotjarNode)

View file

@ -6,10 +6,9 @@ import re
from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import is_internal_ip, disable_html, get_required_setting
from analytical.utils import disable_html, get_required_setting, is_internal_ip
PORTAL_ID_RE = re.compile(r'^\d+$')
PORTAL_ID_RE = re.compile(r"^\d+$")
TRACKING_CODE = """
<!-- Start of Async HubSpot Analytics Code -->
<script type="text/javascript">
@ -42,16 +41,17 @@ def hubspot(parser, token):
class HubSpotNode(Node):
def __init__(self):
self.portal_id = get_required_setting('HUBSPOT_PORTAL_ID', PORTAL_ID_RE,
"must be a (string containing a) number")
self.portal_id = get_required_setting(
"HUBSPOT_PORTAL_ID", PORTAL_ID_RE, "must be a (string containing a) number"
)
def render(self, context):
html = TRACKING_CODE % {'portal_id': self.portal_id}
if is_internal_ip(context, 'HUBSPOT'):
html = disable_html(html, 'HubSpot')
html = TRACKING_CODE % {"portal_id": self.portal_id}
if is_internal_ip(context, "HUBSPOT"):
html = disable_html(html, "HubSpot")
return html
def contribute_to_analytical(add_node):
HubSpotNode() # ensure properly configured
add_node('body_bottom', HubSpotNode)
add_node("body_bottom", HubSpotNode)

View file

@ -10,11 +10,16 @@ import re
from django.conf import settings
from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import disable_html, get_required_setting, \
is_internal_ip, get_user_from_context, get_identity, \
get_user_is_authenticated
from analytical.utils import (
disable_html,
get_identity,
get_required_setting,
get_user_from_context,
get_user_is_authenticated,
is_internal_ip,
)
APP_ID_RE = re.compile(r'[\da-z]+$')
APP_ID_RE = re.compile(r"[\da-z]+$")
TRACKING_CODE = """
<script id="IntercomSettingsScriptTag">
window.intercomSettings = %(settings_json)s;
@ -32,7 +37,7 @@ def _hashable_bytes(data):
if isinstance(data, bytes):
return data
elif isinstance(data, str):
return data.encode('ascii') # Fail on anything non-ASCII.
return data.encode("ascii") # Fail on anything non-ASCII.
else:
raise TypeError(data)
@ -43,7 +48,7 @@ def intercom_user_hash(data):
Return None if the `INTERCOM_HMAC_SECRET_KEY` setting is not configured.
"""
if getattr(settings, 'INTERCOM_HMAC_SECRET_KEY', None):
if getattr(settings, "INTERCOM_HMAC_SECRET_KEY", None):
return hmac.new(
key=_hashable_bytes(settings.INTERCOM_HMAC_SECRET_KEY),
msg=_hashable_bytes(data),
@ -71,8 +76,8 @@ def intercom(parser, token):
class IntercomNode(Node):
def __init__(self):
self.app_id = get_required_setting(
'INTERCOM_APP_ID', APP_ID_RE,
"must be a string looking like 'XXXXXXX'")
"INTERCOM_APP_ID", APP_ID_RE, "must be a string looking like 'XXXXXXX'"
)
def _identify(self, user):
name = user.get_full_name()
@ -84,47 +89,44 @@ class IntercomNode(Node):
params = {}
for dict_ in context:
for var, val in dict_.items():
if var.startswith('intercom_'):
if var.startswith("intercom_"):
params[var[9:]] = val
user = get_user_from_context(context)
if user is not None and get_user_is_authenticated(user):
if 'name' not in params:
params['name'] = get_identity(
context, 'intercom', self._identify, user)
if 'email' not in params and user.email:
params['email'] = user.email
if "name" not in params:
params["name"] = get_identity(context, "intercom", self._identify, user)
if "email" not in params and user.email:
params["email"] = user.email
params.setdefault('user_id', user.pk)
params.setdefault("user_id", user.pk)
params['created_at'] = int(user.date_joined.timestamp())
params["created_at"] = int(user.date_joined.timestamp())
else:
params['created_at'] = None
params["created_at"] = None
# Generate a user_hash HMAC to verify the user's identity, if configured.
# (If both user_id and email are present, the user_id field takes precedence.)
# See:
# https://www.intercom.com/help/configure-intercom-for-your-product-or-site/staying-secure/enable-identity-verification-on-your-web-product
user_hash_data = params.get('user_id', params.get('email'))
user_hash_data = params.get("user_id", params.get("email"))
if user_hash_data:
user_hash = intercom_user_hash(str(user_hash_data))
if user_hash is not None:
params.setdefault('user_hash', user_hash)
params.setdefault("user_hash", user_hash)
return params
def render(self, context):
params = self._get_custom_attrs(context)
params["app_id"] = self.app_id
html = TRACKING_CODE % {
"settings_json": json.dumps(params, sort_keys=True)
}
html = TRACKING_CODE % {"settings_json": json.dumps(params, sort_keys=True)}
if is_internal_ip(context, 'INTERCOM'):
html = disable_html(html, 'Intercom')
if is_internal_ip(context, "INTERCOM"):
html = disable_html(html, "Intercom")
return html
def contribute_to_analytical(add_node):
IntercomNode()
add_node('body_bottom', IntercomNode)
add_node("body_bottom", IntercomNode)

View file

@ -8,16 +8,15 @@ from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import get_identity, get_required_setting
ACCOUNT_NUMBER_RE = re.compile(r'^\d+$')
SITE_CODE_RE = re.compile(r'^[\w]+$')
ACCOUNT_NUMBER_RE = re.compile(r"^\d+$")
SITE_CODE_RE = re.compile(r"^[\w]+$")
SETUP_CODE = """
<script type="text/javascript">var _kiq = _kiq || []; %(commands)s</script>
<script type="text/javascript" src="//s3.amazonaws.com/ki.js/%(account_number)s/%(site_code)s.js" async="true"></script>
""" # noqa
IDENTIFY_CODE = "_kiq.push(['identify', '%s']);"
SHOW_SURVEY_CODE = "_kiq.push(['showSurvey', %s]);"
SHOW_SURVEY_CONTEXT_KEY = 'kiss_insights_show_survey'
SHOW_SURVEY_CONTEXT_KEY = "kiss_insights_show_survey"
register = Library()
@ -42,15 +41,19 @@ def kiss_insights(parser, token):
class KissInsightsNode(Node):
def __init__(self):
self.account_number = get_required_setting(
'KISS_INSIGHTS_ACCOUNT_NUMBER', ACCOUNT_NUMBER_RE,
"must be (a string containing) a number")
"KISS_INSIGHTS_ACCOUNT_NUMBER",
ACCOUNT_NUMBER_RE,
"must be (a string containing) a number",
)
self.site_code = get_required_setting(
'KISS_INSIGHTS_SITE_CODE', SITE_CODE_RE,
"must be a string containing three characters")
"KISS_INSIGHTS_SITE_CODE",
SITE_CODE_RE,
"must be a string containing three characters",
)
def render(self, context):
commands = []
identity = get_identity(context, 'kiss_insights')
identity = get_identity(context, "kiss_insights")
if identity is not None:
commands.append(IDENTIFY_CODE % identity)
try:
@ -58,13 +61,13 @@ class KissInsightsNode(Node):
except KeyError:
pass
html = SETUP_CODE % {
'account_number': self.account_number,
'site_code': self.site_code,
'commands': " ".join(commands),
"account_number": self.account_number,
"site_code": self.site_code,
"commands": " ".join(commands),
}
return html
def contribute_to_analytical(add_node):
KissInsightsNode() # ensure properly configured
add_node('body_top', KissInsightsNode)
add_node("body_top", KissInsightsNode)

View file

@ -7,11 +7,14 @@ import re
from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import is_internal_ip, disable_html, get_identity, \
get_required_setting
from analytical.utils import (
disable_html,
get_identity,
get_required_setting,
is_internal_ip,
)
API_KEY_RE = re.compile(r'^[0-9a-f]{40}$')
API_KEY_RE = re.compile(r"^[0-9a-f]{40}$")
TRACKING_CODE = """
<script type="text/javascript">
var _kmq = _kmq || [];
@ -35,9 +38,9 @@ EVENT_CODE = "_kmq.push(['record', '%(name)s', %(properties)s]);"
PROPERTY_CODE = "_kmq.push(['set', %(properties)s]);"
ALIAS_CODE = "_kmq.push(['alias', '%s', '%s']);"
EVENT_CONTEXT_KEY = 'kiss_metrics_event'
PROPERTY_CONTEXT_KEY = 'kiss_metrics_properties'
ALIAS_CONTEXT_KEY = 'kiss_metrics_alias'
EVENT_CONTEXT_KEY = "kiss_metrics_event"
PROPERTY_CONTEXT_KEY = "kiss_metrics_properties"
ALIAS_CONTEXT_KEY = "kiss_metrics_alias"
register = Library()
@ -60,12 +63,14 @@ def kiss_metrics(parser, token):
class KissMetricsNode(Node):
def __init__(self):
self.api_key = get_required_setting(
'KISS_METRICS_API_KEY', API_KEY_RE,
"must be a string containing a 40-digit hexadecimal number")
"KISS_METRICS_API_KEY",
API_KEY_RE,
"must be a string containing a 40-digit hexadecimal number",
)
def render(self, context):
commands = []
identity = get_identity(context, 'kiss_metrics')
identity = get_identity(context, "kiss_metrics")
if identity is not None:
commands.append(IDENTIFY_CODE % identity)
try:
@ -76,28 +81,34 @@ class KissMetricsNode(Node):
pass
try:
name, properties = context[EVENT_CONTEXT_KEY]
commands.append(EVENT_CODE % {
'name': name,
'properties': json.dumps(properties, sort_keys=True),
})
commands.append(
EVENT_CODE
% {
"name": name,
"properties": json.dumps(properties, sort_keys=True),
}
)
except KeyError:
pass
try:
properties = context[PROPERTY_CONTEXT_KEY]
commands.append(PROPERTY_CODE % {
'properties': json.dumps(properties, sort_keys=True),
})
commands.append(
PROPERTY_CODE
% {
"properties": json.dumps(properties, sort_keys=True),
}
)
except KeyError:
pass
html = TRACKING_CODE % {
'api_key': self.api_key,
'commands': " ".join(commands),
"api_key": self.api_key,
"commands": " ".join(commands),
}
if is_internal_ip(context, 'KISS_METRICS'):
html = disable_html(html, 'KISSmetrics')
if is_internal_ip(context, "KISS_METRICS"):
html = disable_html(html, "KISSmetrics")
return html
def contribute_to_analytical(add_node):
KissMetricsNode() # ensure properly configured
add_node('head_top', KissMetricsNode)
add_node("head_top", KissMetricsNode)

View file

@ -6,8 +6,7 @@ import re
from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import get_required_setting, is_internal_ip, disable_html
from analytical.utils import disable_html, get_required_setting, is_internal_ip
LUCKYORANGE_TRACKING_CODE = """\
<script type='text/javascript'>
@ -40,18 +39,17 @@ def luckyorange(parser, token):
class LuckyOrangeNode(Node):
def __init__(self):
self.site_id = get_required_setting(
'LUCKYORANGE_SITE_ID',
re.compile(r'^\d+$'),
"LUCKYORANGE_SITE_ID",
re.compile(r"^\d+$"),
"must be (a string containing) a number",
)
def render(self, context):
html = LUCKYORANGE_TRACKING_CODE % {'LUCKYORANGE_SITE_ID': self.site_id}
if is_internal_ip(context, 'LUCKYORANGE'):
return disable_html(html, 'Lucky Orange')
html = LUCKYORANGE_TRACKING_CODE % {"LUCKYORANGE_SITE_ID": self.site_id}
if is_internal_ip(context, "LUCKYORANGE"):
return disable_html(html, "Lucky Orange")
else:
return html
@ -59,4 +57,4 @@ class LuckyOrangeNode(Node):
def contribute_to_analytical(add_node):
# ensure properly configured
LuckyOrangeNode()
add_node('head_bottom', LuckyOrangeNode)
add_node("head_bottom", LuckyOrangeNode)

View file

@ -2,22 +2,25 @@
Matomo template tags and filters.
"""
import re
from collections import namedtuple
from itertools import chain
import re
from django.conf import settings
from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import (is_internal_ip, disable_html,
get_required_setting, get_identity)
from analytical.utils import (
disable_html,
get_identity,
get_required_setting,
is_internal_ip,
)
# domain name (characters separated by a dot), optional port, optional URI path, no slash
DOMAINPATH_RE = re.compile(r'^(([^./?#@:]+\.)*[^./?#@:]+)+(:[0-9]+)?(/[^/?#@:]+)*$')
DOMAINPATH_RE = re.compile(r"^(([^./?#@:]+\.)*[^./?#@:]+)+(:[0-9]+)?(/[^/?#@:]+)*$")
# numeric ID
SITEID_RE = re.compile(r'^\d+$')
SITEID_RE = re.compile(r"^\d+$")
TRACKING_CODE = """
<script type="text/javascript">
@ -39,11 +42,11 @@ TRACKING_CODE = """
VARIABLE_CODE = '_paq.push(["setCustomVariable", %(index)s, "%(name)s", "%(value)s", "%(scope)s"]);' # noqa
IDENTITY_CODE = '_paq.push(["setUserId", "%(userid)s"]);'
DISABLE_COOKIES_CODE = '_paq.push([\'disableCookies\']);'
DISABLE_COOKIES_CODE = "_paq.push(['disableCookies']);"
DEFAULT_SCOPE = 'page'
DEFAULT_SCOPE = "page"
MatomoVar = namedtuple('MatomoVar', ('index', 'name', 'value', 'scope'))
MatomoVar = namedtuple("MatomoVar", ("index", "name", "value", "scope"))
register = Library()
@ -72,45 +75,49 @@ def matomo(parser, token):
class MatomoNode(Node):
def __init__(self):
self.domain_path = \
get_required_setting('MATOMO_DOMAIN_PATH', DOMAINPATH_RE,
"must be a domain name, optionally followed "
"by an URI path, no trailing slash (e.g. "
"matomo.example.com or my.matomo.server/path)")
self.site_id = \
get_required_setting('MATOMO_SITE_ID', SITEID_RE,
"must be a (string containing a) number")
self.domain_path = get_required_setting(
"MATOMO_DOMAIN_PATH",
DOMAINPATH_RE,
"must be a domain name, optionally followed "
"by an URI path, no trailing slash (e.g. "
"matomo.example.com or my.matomo.server/path)",
)
self.site_id = get_required_setting(
"MATOMO_SITE_ID", SITEID_RE, "must be a (string containing a) number"
)
def render(self, context):
custom_variables = context.get('matomo_vars', ())
custom_variables = context.get("matomo_vars", ())
complete_variables = (var if len(var) >= 4 else var + (DEFAULT_SCOPE,)
for var in custom_variables)
complete_variables = (
var if len(var) >= 4 else var + (DEFAULT_SCOPE,) for var in custom_variables
)
variables_code = (VARIABLE_CODE % MatomoVar(*var)._asdict()
for var in complete_variables)
variables_code = (
VARIABLE_CODE % MatomoVar(*var)._asdict() for var in complete_variables
)
commands = []
if getattr(settings, 'MATOMO_DISABLE_COOKIES', False):
if getattr(settings, "MATOMO_DISABLE_COOKIES", False):
commands.append(DISABLE_COOKIES_CODE)
userid = get_identity(context, 'matomo')
userid = get_identity(context, "matomo")
if userid is not None:
variables_code = chain(variables_code, (
IDENTITY_CODE % {'userid': userid},
))
variables_code = chain(
variables_code, (IDENTITY_CODE % {"userid": userid},)
)
html = TRACKING_CODE % {
'url': self.domain_path,
'siteid': self.site_id,
'variables': '\n '.join(variables_code),
'commands': '\n '.join(commands)
"url": self.domain_path,
"siteid": self.site_id,
"variables": "\n ".join(variables_code),
"commands": "\n ".join(commands),
}
if is_internal_ip(context, 'MATOMO'):
html = disable_html(html, 'Matomo')
if is_internal_ip(context, "MATOMO"):
html = disable_html(html, "Matomo")
return html
def contribute_to_analytical(add_node):
MatomoNode() # ensure properly configured
add_node('body_bottom', MatomoNode)
add_node("body_bottom", MatomoNode)

View file

@ -8,11 +8,14 @@ import re
from django.template import Library, Node, TemplateSyntaxError
from django.utils.safestring import mark_safe
from analytical.utils import is_internal_ip, disable_html, get_identity, \
get_required_setting
from analytical.utils import (
disable_html,
get_identity,
get_required_setting,
is_internal_ip,
)
MIXPANEL_API_TOKEN_RE = re.compile(r'^[0-9a-f]{32}$')
MIXPANEL_API_TOKEN_RE = re.compile(r"^[0-9a-f]{32}$")
TRACKING_CODE = """
<script type="text/javascript">(function(e,b){if(!b.__SV){var a,f,i,g;window.mixpanel=b;a=e.createElement("script");a.type="text/javascript";a.async=!0;a.src=("https:"===e.location.protocol?"https:":"http:")+'//cdn.mxpnl.com/libs/mixpanel-2.2.min.js';f=e.getElementsByTagName("script")[0];f.parentNode.insertBefore(a,f);b._i=[];b.init=function(a,e,d){function f(b,h){var a=h.split(".");2==a.length&&(b=b[a[0]],h=a[1]);b[h]=function(){b.push([h].concat(Array.prototype.slice.call(arguments,0)))}}var c=b;"undefined"!==
typeof d?c=b[d]=[]:d="mixpanel";c.people=c.people||[];c.toString=function(b){var a="mixpanel";"mixpanel"!==d&&(a+="."+d);b||(a+=" (stub)");return a};c.people.toString=function(){return c.toString(1)+".people (stub)"};i="disable track track_pageview track_links track_forms register register_once alias unregister identify name_tag set_config people.set people.increment people.append people.track_charge people.clear_charges people.delete_user".split(" ");for(g=0;g<i.length;g++)f(c,i[g]);b._i.push([a,
@ -24,7 +27,7 @@ e,d])};b.__SV=1.2}})(document,window.mixpanel||[]);
IDENTIFY_CODE = "mixpanel.identify('%s');"
IDENTIFY_PROPERTIES = "mixpanel.people.set(%s);"
EVENT_CODE = "mixpanel.track('%(name)s', %(properties)s);"
EVENT_CONTEXT_KEY = 'mixpanel_event'
EVENT_CONTEXT_KEY = "mixpanel_event"
register = Library()
@ -46,35 +49,44 @@ def mixpanel(parser, token):
class MixpanelNode(Node):
def __init__(self):
self._token = get_required_setting(
'MIXPANEL_API_TOKEN', MIXPANEL_API_TOKEN_RE,
"must be a string containing a 32-digit hexadecimal number")
"MIXPANEL_API_TOKEN",
MIXPANEL_API_TOKEN_RE,
"must be a string containing a 32-digit hexadecimal number",
)
def render(self, context):
commands = []
identity = get_identity(context, 'mixpanel')
identity = get_identity(context, "mixpanel")
if identity is not None:
if isinstance(identity, dict):
commands.append(IDENTIFY_CODE % identity.get('id', identity.get('username')))
commands.append(IDENTIFY_PROPERTIES % json.dumps(identity, sort_keys=True))
commands.append(
IDENTIFY_CODE % identity.get("id", identity.get("username"))
)
commands.append(
IDENTIFY_PROPERTIES % json.dumps(identity, sort_keys=True)
)
else:
commands.append(IDENTIFY_CODE % identity)
try:
name, properties = context[EVENT_CONTEXT_KEY]
commands.append(EVENT_CODE % {
'name': name,
'properties': json.dumps(properties, sort_keys=True),
})
commands.append(
EVENT_CODE
% {
"name": name,
"properties": json.dumps(properties, sort_keys=True),
}
)
except KeyError:
pass
html = TRACKING_CODE % {
'token': self._token,
'commands': " ".join(commands),
"token": self._token,
"commands": " ".join(commands),
}
if is_internal_ip(context, 'MIXPANEL'):
html = disable_html(html, 'Mixpanel')
if is_internal_ip(context, "MIXPANEL"):
html = disable_html(html, "Mixpanel")
return mark_safe(html)
def contribute_to_analytical(add_node):
MixpanelNode() # ensure properly configured
add_node('head_bottom', MixpanelNode)
add_node("head_bottom", MixpanelNode)

View file

@ -9,8 +9,7 @@ from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import get_identity, get_required_setting
SITE_ID_RE = re.compile(r'^\d+-\d+-\d+-\d+$')
SITE_ID_RE = re.compile(r"^\d+-\d+-\d+-\d+$")
SETUP_CODE = """
<script type='text/javascript'>
/*{literal}<![CDATA[*/ window.olark||(function(k){var g=window,j=document,a=g.location.protocol=="https:"?"https:":"http:",i=k.name,b="load",h="addEventListener";(function(){g[i]=function(){(c.s=c.s||[]).push(arguments)};var c=g[i]._={},f=k.methods.length;while(f--){(function(l){g[i][l]=function(){g[i]("call",l,arguments)}})(k.methods[f])}c.l=k.loader;c.i=arguments.callee;c.p={0:+new Date};c.P=function(l){c.p[l]=new Date-c.p[0]};function e(){c.P(b);g[i](b)}g[h]?g[h](b,e,false):g.attachEvent("on"+b,e);c.P(1);var d=j.createElement("script"),m=document.getElementsByTagName("script")[0];d.type="text/javascript";d.async=true;d.src=a+"//"+c.l;m.parentNode.insertBefore(d,m);c.P(2)})()})({loader:(function(a){return "static.olark.com/jsclient/loader1.js?ts="+(a?a[1]:(+new Date))})(document.cookie.match(/olarkld=([0-9]+)/)),name:"olark",methods:["configure","extend","declare","identify"]}); olark.identify('%(site_id)s');/*]]>{/literal}*/
@ -18,23 +17,36 @@ SETUP_CODE = """
</script>
""" # noqa
NICKNAME_CODE = "olark('api.chat.updateVisitorNickname', {snippet: '%s'});"
NICKNAME_CONTEXT_KEY = 'olark_nickname'
NICKNAME_CONTEXT_KEY = "olark_nickname"
FULLNAME_CODE = "olark('api.visitor.updateFullName', {{fullName: '{0}'}});"
FULLNAME_CONTEXT_KEY = 'olark_fullname'
FULLNAME_CONTEXT_KEY = "olark_fullname"
EMAIL_CODE = "olark('api.visitor.updateEmailAddress', {{emailAddress: '{0}'}});"
EMAIL_CONTEXT_KEY = 'olark_email'
EMAIL_CONTEXT_KEY = "olark_email"
STATUS_CODE = "olark('api.chat.updateVisitorStatus', {snippet: %s});"
STATUS_CONTEXT_KEY = 'olark_status'
STATUS_CONTEXT_KEY = "olark_status"
MESSAGE_CODE = "olark.configure('locale.%(key)s', \"%(msg)s\");"
MESSAGE_KEYS = {
"welcome_title", "chatting_title", "unavailable_title",
"busy_title", "away_message", "loading_title", "welcome_message",
"busy_message", "chat_input_text", "name_input_text",
"email_input_text", "offline_note_message", "send_button_text",
"offline_note_thankyou_text", "offline_note_error_text",
"offline_note_sending_text", "operator_is_typing_text",
"operator_has_stopped_typing_text", "introduction_error_text",
"introduction_messages", "introduction_submit_button_text",
"welcome_title",
"chatting_title",
"unavailable_title",
"busy_title",
"away_message",
"loading_title",
"welcome_message",
"busy_message",
"chat_input_text",
"name_input_text",
"email_input_text",
"offline_note_message",
"send_button_text",
"offline_note_thankyou_text",
"offline_note_error_text",
"offline_note_sending_text",
"operator_is_typing_text",
"operator_has_stopped_typing_text",
"introduction_error_text",
"introduction_messages",
"introduction_submit_button_text",
}
register = Library()
@ -57,15 +69,17 @@ def olark(parser, token):
class OlarkNode(Node):
def __init__(self):
self.site_id = get_required_setting(
'OLARK_SITE_ID', SITE_ID_RE,
"must be a string looking like 'XXXX-XXX-XX-XXXX'")
"OLARK_SITE_ID",
SITE_ID_RE,
"must be a string looking like 'XXXX-XXX-XX-XXXX'",
)
def render(self, context):
extra_code = []
try:
extra_code.append(NICKNAME_CODE % context[NICKNAME_CONTEXT_KEY])
except KeyError:
identity = get_identity(context, 'olark', self._get_nickname)
identity = get_identity(context, "olark", self._get_nickname)
if identity is not None:
extra_code.append(NICKNAME_CODE % identity)
try:
@ -77,14 +91,15 @@ class OlarkNode(Node):
except KeyError:
pass
try:
extra_code.append(STATUS_CODE % json.dumps(context[STATUS_CONTEXT_KEY],
sort_keys=True))
extra_code.append(
STATUS_CODE % json.dumps(context[STATUS_CONTEXT_KEY], sort_keys=True)
)
except KeyError:
pass
extra_code.extend(self._get_configuration(context))
html = SETUP_CODE % {
'site_id': self.site_id,
'extra_code': " ".join(extra_code),
"site_id": self.site_id,
"extra_code": " ".join(extra_code),
}
return html
@ -99,13 +114,13 @@ class OlarkNode(Node):
code = []
for dict_ in context:
for var, val in dict_.items():
if var.startswith('olark_'):
if var.startswith("olark_"):
key = var[6:]
if key in MESSAGE_KEYS:
code.append(MESSAGE_CODE % {'key': key, 'msg': val})
code.append(MESSAGE_CODE % {"key": key, "msg": val})
return code
def contribute_to_analytical(add_node):
OlarkNode() # ensure properly configured
add_node('body_bottom', OlarkNode)
add_node("body_bottom", OlarkNode)

View file

@ -6,10 +6,9 @@ import re
from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import is_internal_ip, disable_html, get_required_setting
from analytical.utils import disable_html, get_required_setting, is_internal_ip
ACCOUNT_NUMBER_RE = re.compile(r'^\d+$')
ACCOUNT_NUMBER_RE = re.compile(r"^\d+$")
SETUP_CODE = """<script src="//cdn.optimizely.com/js/%(account_number)s.js"></script>"""
@ -34,16 +33,18 @@ def optimizely(parser, token):
class OptimizelyNode(Node):
def __init__(self):
self.account_number = get_required_setting(
'OPTIMIZELY_ACCOUNT_NUMBER', ACCOUNT_NUMBER_RE,
"must be a string looking like 'XXXXXXX'")
"OPTIMIZELY_ACCOUNT_NUMBER",
ACCOUNT_NUMBER_RE,
"must be a string looking like 'XXXXXXX'",
)
def render(self, context):
html = SETUP_CODE % {'account_number': self.account_number}
if is_internal_ip(context, 'OPTIMIZELY'):
html = disable_html(html, 'Optimizely')
html = SETUP_CODE % {"account_number": self.account_number}
if is_internal_ip(context, "OPTIMIZELY"):
html = disable_html(html, "Optimizely")
return html
def contribute_to_analytical(add_node):
OptimizelyNode() # ensure properly configured
add_node('head_top', OptimizelyNode)
add_node("head_top", OptimizelyNode)

View file

@ -7,11 +7,14 @@ import re
from django.template import Library, Node, TemplateSyntaxError
from django.utils.safestring import mark_safe
from analytical.utils import is_internal_ip, disable_html, get_identity, \
get_required_setting
from analytical.utils import (
disable_html,
get_identity,
get_required_setting,
is_internal_ip,
)
API_KEY_RE = re.compile(r'^\w+$')
API_KEY_RE = re.compile(r"^\w+$")
SETUP_CODE = """
<script src="//d1nu2rn22elx8m.cloudfront.net/performable/pax/%(api_key)s.js" type="text/javascript"></script>
""" # noqa
@ -53,16 +56,16 @@ def performable(parser, token):
class PerformableNode(Node):
def __init__(self):
self.api_key = get_required_setting(
'PERFORMABLE_API_KEY', API_KEY_RE,
"must be a string looking like 'XXXXX'")
"PERFORMABLE_API_KEY", API_KEY_RE, "must be a string looking like 'XXXXX'"
)
def render(self, context):
html = SETUP_CODE % {'api_key': self.api_key}
identity = get_identity(context, 'performable')
html = SETUP_CODE % {"api_key": self.api_key}
identity = get_identity(context, "performable")
if identity is not None:
html = "%s%s" % (IDENTIFY_CODE % identity, html)
if is_internal_ip(context, 'PERFORMABLE'):
html = disable_html(html, 'Performable')
if is_internal_ip(context, "PERFORMABLE"):
html = disable_html(html, "Performable")
return html
@ -71,12 +74,15 @@ def performable_embed(hostname, page_id):
"""
Include a Performable landing page.
"""
return mark_safe(EMBED_CODE % {
'hostname': hostname,
'page_id': page_id,
})
return mark_safe(
EMBED_CODE
% {
"hostname": hostname,
"page_id": page_id,
}
)
def contribute_to_analytical(add_node):
PerformableNode() # ensure properly configured
add_node('body_bottom', PerformableNode)
add_node("body_bottom", PerformableNode)

View file

@ -2,23 +2,26 @@
Piwik template tags and filters.
"""
import re
import warnings
from collections import namedtuple
from itertools import chain
import re
from django.conf import settings
from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import (is_internal_ip, disable_html,
get_required_setting, get_identity)
import warnings
from analytical.utils import (
disable_html,
get_identity,
get_required_setting,
is_internal_ip,
)
# domain name (characters separated by a dot), optional port, optional URI path, no slash
DOMAINPATH_RE = re.compile(r'^(([^./?#@:]+\.)*[^./?#@:]+)+(:[0-9]+)?(/[^/?#@:]+)*$')
DOMAINPATH_RE = re.compile(r"^(([^./?#@:]+\.)*[^./?#@:]+)+(:[0-9]+)?(/[^/?#@:]+)*$")
# numeric ID
SITEID_RE = re.compile(r'^\d+$')
SITEID_RE = re.compile(r"^\d+$")
TRACKING_CODE = """
<script type="text/javascript">
@ -40,11 +43,11 @@ TRACKING_CODE = """
VARIABLE_CODE = '_paq.push(["setCustomVariable", %(index)s, "%(name)s", "%(value)s", "%(scope)s"]);' # noqa
IDENTITY_CODE = '_paq.push(["setUserId", "%(userid)s"]);'
DISABLE_COOKIES_CODE = '_paq.push([\'disableCookies\']);'
DISABLE_COOKIES_CODE = "_paq.push(['disableCookies']);"
DEFAULT_SCOPE = 'page'
DEFAULT_SCOPE = "page"
PiwikVar = namedtuple('PiwikVar', ('index', 'name', 'value', 'scope'))
PiwikVar = namedtuple("PiwikVar", ("index", "name", "value", "scope"))
register = Library()
@ -65,7 +68,9 @@ def piwik(parser, token):
(default) or ``'visit'``. Index should be an integer and the
other parameters should be strings.
"""
warnings.warn('The Piwik module is deprecated; use the Matomo module.', DeprecationWarning)
warnings.warn(
"The Piwik module is deprecated; use the Matomo module.", DeprecationWarning
)
bits = token.split_contents()
if len(bits) > 1:
raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
@ -74,45 +79,49 @@ def piwik(parser, token):
class PiwikNode(Node):
def __init__(self):
self.domain_path = \
get_required_setting('PIWIK_DOMAIN_PATH', DOMAINPATH_RE,
"must be a domain name, optionally followed "
"by an URI path, no trailing slash (e.g. "
"piwik.example.com or my.piwik.server/path)")
self.site_id = \
get_required_setting('PIWIK_SITE_ID', SITEID_RE,
"must be a (string containing a) number")
self.domain_path = get_required_setting(
"PIWIK_DOMAIN_PATH",
DOMAINPATH_RE,
"must be a domain name, optionally followed "
"by an URI path, no trailing slash (e.g. "
"piwik.example.com or my.piwik.server/path)",
)
self.site_id = get_required_setting(
"PIWIK_SITE_ID", SITEID_RE, "must be a (string containing a) number"
)
def render(self, context):
custom_variables = context.get('piwik_vars', ())
custom_variables = context.get("piwik_vars", ())
complete_variables = (var if len(var) >= 4 else var + (DEFAULT_SCOPE,)
for var in custom_variables)
complete_variables = (
var if len(var) >= 4 else var + (DEFAULT_SCOPE,) for var in custom_variables
)
variables_code = (VARIABLE_CODE % PiwikVar(*var)._asdict()
for var in complete_variables)
variables_code = (
VARIABLE_CODE % PiwikVar(*var)._asdict() for var in complete_variables
)
commands = []
if getattr(settings, 'PIWIK_DISABLE_COOKIES', False):
if getattr(settings, "PIWIK_DISABLE_COOKIES", False):
commands.append(DISABLE_COOKIES_CODE)
userid = get_identity(context, 'piwik')
userid = get_identity(context, "piwik")
if userid is not None:
variables_code = chain(variables_code, (
IDENTITY_CODE % {'userid': userid},
))
variables_code = chain(
variables_code, (IDENTITY_CODE % {"userid": userid},)
)
html = TRACKING_CODE % {
'url': self.domain_path,
'siteid': self.site_id,
'variables': '\n '.join(variables_code),
'commands': '\n '.join(commands)
"url": self.domain_path,
"siteid": self.site_id,
"variables": "\n ".join(variables_code),
"commands": "\n ".join(commands),
}
if is_internal_ip(context, 'PIWIK'):
html = disable_html(html, 'Piwik')
if is_internal_ip(context, "PIWIK"):
html = disable_html(html, "Piwik")
return html
def contribute_to_analytical(add_node):
PiwikNode() # ensure properly configured
add_node('body_bottom', PiwikNode)
add_node("body_bottom", PiwikNode)

View file

@ -6,11 +6,9 @@ import re
from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import is_internal_ip, disable_html, \
get_required_setting
from analytical.utils import disable_html, get_required_setting, is_internal_ip
COUNTER_ID_RE = re.compile(r'^\d{7}$')
COUNTER_ID_RE = re.compile(r"^\d{7}$")
COUNTER_CODE = """
<script type="text/javascript">
var _tmr = window._tmr || (window._tmr = []);
@ -50,18 +48,20 @@ def rating_mailru(parser, token):
class RatingMailruNode(Node):
def __init__(self):
self.counter_id = get_required_setting(
'RATING_MAILRU_COUNTER_ID', COUNTER_ID_RE,
"must be (a string containing) a number'")
"RATING_MAILRU_COUNTER_ID",
COUNTER_ID_RE,
"must be (a string containing) a number'",
)
def render(self, context):
html = COUNTER_CODE % {
'counter_id': self.counter_id,
"counter_id": self.counter_id,
}
if is_internal_ip(context, 'RATING_MAILRU_METRICA'):
html = disable_html(html, 'Rating@Mail.ru')
if is_internal_ip(context, "RATING_MAILRU_METRICA"):
html = disable_html(html, "Rating@Mail.ru")
return html
def contribute_to_analytical(add_node):
RatingMailruNode() # ensure properly configured
add_node('head_bottom', RatingMailruNode)
add_node("head_bottom", RatingMailruNode)

View file

@ -19,12 +19,14 @@ BUTTON_STYLE_NONE = 0
BUTTON_STYLE_DEFAULT = 1
BUTTON_STYLE_LIVE = 2
FORM_POSITION_TOP_LEFT = 'tl'
FORM_POSITION_TOP_RIGHT = 'tr'
FORM_POSITION_BOTTOM_LEFT = 'bl'
FORM_POSITION_BOTTOM_RIGHT = 'br'
FORM_POSITION_TOP_LEFT = "tl"
FORM_POSITION_TOP_RIGHT = "tr"
FORM_POSITION_BOTTOM_LEFT = "bl"
FORM_POSITION_BOTTOM_RIGHT = "br"
WIDGET_ID_RE = re.compile(r'^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$')
WIDGET_ID_RE = re.compile(
r"^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$"
)
SETUP_CODE = """
<script type="text/javascript">
document.write(unescape("%%3Cscript src='" + ((document.location.protocol=="https:")?"https://snapabug.appspot.com":"http://www.snapengage.com") + "/snapabug.js' type='text/javascript'%%3E%%3C/script%%3E"));</script><script type="text/javascript">
@ -32,20 +34,22 @@ SETUP_CODE = """
</script>
""" # noqa
DOMAIN_CODE = 'SnapABug.setDomain("%s");'
SECURE_CONNECTION_CODE = 'SnapABug.setSecureConnexion();'
SECURE_CONNECTION_CODE = "SnapABug.setSecureConnexion();"
INIT_CODE = 'SnapABug.init("%s");'
ADDBUTTON_CODE = 'SnapABug.addButton("%(id)s","%(location)s","%(offset)s"%(dynamic_tail)s);'
ADDBUTTON_CODE = (
'SnapABug.addButton("%(id)s","%(location)s","%(offset)s"%(dynamic_tail)s);'
)
SETBUTTON_CODE = 'SnapABug.setButton("%s");'
SETEMAIL_CODE = 'SnapABug.setUserEmail("%s"%s);'
SETLOCALE_CODE = 'SnapABug.setLocale("%s");'
FORM_POSITION_CODE = 'SnapABug.setChatFormPosition("%s");'
FORM_TOP_POSITION_CODE = 'SnapABug.setFormTopPosition(%d);'
FORM_TOP_POSITION_CODE = "SnapABug.setFormTopPosition(%d);"
BUTTONEFFECT_CODE = 'SnapABug.setButtonEffect("%s");'
DISABLE_OFFLINE_CODE = 'SnapABug.allowOffline(false);'
DISABLE_SCREENSHOT_CODE = 'SnapABug.allowScreenshot(false);'
DISABLE_OFFLINE_SCREENSHOT_CODE = 'SnapABug.showScreenshotOption(false);'
DISABLE_PROACTIVE_CHAT_CODE = 'SnapABug.allowProactiveChat(false);'
DISABLE_SOUNDS_CODE = 'SnapABug.allowChatSound(false);'
DISABLE_OFFLINE_CODE = "SnapABug.allowOffline(false);"
DISABLE_SCREENSHOT_CODE = "SnapABug.allowScreenshot(false);"
DISABLE_OFFLINE_SCREENSHOT_CODE = "SnapABug.showScreenshotOption(false);"
DISABLE_PROACTIVE_CHAT_CODE = "SnapABug.allowProactiveChat(false);"
DISABLE_SOUNDS_CODE = "SnapABug.allowChatSound(false);"
register = Library()
@ -67,83 +71,95 @@ def snapengage(parser, token):
class SnapEngageNode(Node):
def __init__(self):
self.widget_id = get_required_setting(
'SNAPENGAGE_WIDGET_ID', WIDGET_ID_RE,
"must be a string looking like this: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'")
"SNAPENGAGE_WIDGET_ID",
WIDGET_ID_RE,
"must be a string looking like this: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'",
)
def render(self, context):
settings_code = []
domain = self._get_setting(context, 'snapengage_domain',
'SNAPENGAGE_DOMAIN')
domain = self._get_setting(context, "snapengage_domain", "SNAPENGAGE_DOMAIN")
if domain is not None:
settings_code.append(DOMAIN_CODE % domain)
secure_connection = self._get_setting(context,
'snapengage_secure_connection',
'SNAPENGAGE_SECURE_CONNECTION',
False)
secure_connection = self._get_setting(
context,
"snapengage_secure_connection",
"SNAPENGAGE_SECURE_CONNECTION",
False,
)
if secure_connection:
settings_code.append(SECURE_CONNECTION_CODE)
email = context.get('snapengage_email')
email = context.get("snapengage_email")
if email is None:
email = get_identity(context, 'snapengage', lambda u: u.email)
email = get_identity(context, "snapengage", lambda u: u.email)
if email is not None:
if self._get_setting(context, 'snapengage_readonly_email',
'SNAPENGAGE_READONLY_EMAIL', False):
readonly_tail = ',true'
if self._get_setting(
context, "snapengage_readonly_email", "SNAPENGAGE_READONLY_EMAIL", False
):
readonly_tail = ",true"
else:
readonly_tail = ''
readonly_tail = ""
settings_code.append(SETEMAIL_CODE % (email, readonly_tail))
locale = self._get_setting(context, 'snapengage_locale',
'SNAPENGAGE_LOCALE')
locale = self._get_setting(context, "snapengage_locale", "SNAPENGAGE_LOCALE")
if locale is None:
locale = translation.to_locale(translation.get_language())
settings_code.append(SETLOCALE_CODE % locale)
form_position = self._get_setting(context,
'snapengage_form_position', 'SNAPENGAGE_FORM_POSITION')
form_position = self._get_setting(
context, "snapengage_form_position", "SNAPENGAGE_FORM_POSITION"
)
if form_position is not None:
settings_code.append(FORM_POSITION_CODE % form_position)
form_top_position = self._get_setting(context,
'snapengage_form_top_position',
'SNAPENGAGE_FORM_TOP_POSITION')
form_top_position = self._get_setting(
context, "snapengage_form_top_position", "SNAPENGAGE_FORM_TOP_POSITION"
)
if form_top_position is not None:
settings_code.append(FORM_TOP_POSITION_CODE % form_top_position)
show_offline = self._get_setting(context, 'snapengage_show_offline',
'SNAPENGAGE_SHOW_OFFLINE', True)
show_offline = self._get_setting(
context, "snapengage_show_offline", "SNAPENGAGE_SHOW_OFFLINE", True
)
if not show_offline:
settings_code.append(DISABLE_OFFLINE_CODE)
screenshots = self._get_setting(context, 'snapengage_screenshots',
'SNAPENGAGE_SCREENSHOTS', True)
screenshots = self._get_setting(
context, "snapengage_screenshots", "SNAPENGAGE_SCREENSHOTS", True
)
if not screenshots:
settings_code.append(DISABLE_SCREENSHOT_CODE)
offline_screenshots = self._get_setting(context,
'snapengage_offline_screenshots',
'SNAPENGAGE_OFFLINE_SCREENSHOTS', True)
offline_screenshots = self._get_setting(
context,
"snapengage_offline_screenshots",
"SNAPENGAGE_OFFLINE_SCREENSHOTS",
True,
)
if not offline_screenshots:
settings_code.append(DISABLE_OFFLINE_SCREENSHOT_CODE)
if not context.get('snapengage_proactive_chat', True):
if not context.get("snapengage_proactive_chat", True):
settings_code.append(DISABLE_PROACTIVE_CHAT_CODE)
sounds = self._get_setting(context, 'snapengage_sounds',
'SNAPENGAGE_SOUNDS', True)
sounds = self._get_setting(
context, "snapengage_sounds", "SNAPENGAGE_SOUNDS", True
)
if not sounds:
settings_code.append(DISABLE_SOUNDS_CODE)
button_effect = self._get_setting(context, 'snapengage_button_effect',
'SNAPENGAGE_BUTTON_EFFECT')
button_effect = self._get_setting(
context, "snapengage_button_effect", "SNAPENGAGE_BUTTON_EFFECT"
)
if button_effect is not None:
settings_code.append(BUTTONEFFECT_CODE % button_effect)
button = self._get_setting(context, 'snapengage_button',
'SNAPENGAGE_BUTTON', BUTTON_STYLE_DEFAULT)
button = self._get_setting(
context, "snapengage_button", "SNAPENGAGE_BUTTON", BUTTON_STYLE_DEFAULT
)
if button == BUTTON_STYLE_NONE:
settings_code.append(INIT_CODE % self.widget_id)
else:
@ -152,21 +168,28 @@ class SnapEngageNode(Node):
settings_code.append(SETBUTTON_CODE % button)
button_location = self._get_setting(
context,
'snapengage_button_location', 'SNAPENGAGE_BUTTON_LOCATION',
BUTTON_LOCATION_LEFT)
"snapengage_button_location",
"SNAPENGAGE_BUTTON_LOCATION",
BUTTON_LOCATION_LEFT,
)
button_offset = self._get_setting(
context,
'snapengage_button_location_offset',
'SNAPENGAGE_BUTTON_LOCATION_OFFSET', '55%')
settings_code.append(ADDBUTTON_CODE % {
'id': self.widget_id,
'location': button_location,
'offset': button_offset,
'dynamic_tail': ',true' if (button == BUTTON_STYLE_LIVE) else '',
})
"snapengage_button_location_offset",
"SNAPENGAGE_BUTTON_LOCATION_OFFSET",
"55%",
)
settings_code.append(
ADDBUTTON_CODE
% {
"id": self.widget_id,
"location": button_location,
"offset": button_offset,
"dynamic_tail": ",true" if (button == BUTTON_STYLE_LIVE) else "",
}
)
html = SETUP_CODE % {
'widget_id': self.widget_id,
'settings_code': " ".join(settings_code),
"widget_id": self.widget_id,
"settings_code": " ".join(settings_code),
}
return html
@ -182,4 +205,4 @@ class SnapEngageNode(Node):
def contribute_to_analytical(add_node):
SnapEngageNode() # ensure properly configured
add_node('body_bottom', SnapEngageNode)
add_node("body_bottom", SnapEngageNode)

View file

@ -6,11 +6,14 @@ import re
from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import get_identity, is_internal_ip, disable_html, \
get_required_setting
from analytical.utils import (
disable_html,
get_identity,
get_required_setting,
is_internal_ip,
)
TRACKING_ID_RE = re.compile(r'^[0-9a-f]+$')
TRACKING_ID_RE = re.compile(r"^[0-9a-f]+$")
TRACKING_CODE = """
<script type='text/javascript'>
var _springMetq = _springMetq || [];
@ -50,39 +53,40 @@ def spring_metrics(parser, token):
class SpringMetricsNode(Node):
def __init__(self):
self.tracking_id = get_required_setting(
'SPRING_METRICS_TRACKING_ID',
TRACKING_ID_RE, "must be a hexadecimal string")
"SPRING_METRICS_TRACKING_ID", TRACKING_ID_RE, "must be a hexadecimal string"
)
def render(self, context):
custom = {}
for dict_ in context:
for var, val in dict_.items():
if var.startswith('spring_metrics_'):
if var.startswith("spring_metrics_"):
custom[var[15:]] = val
if 'email' not in custom:
identity = get_identity(context, 'spring_metrics',
lambda u: u.email)
if "email" not in custom:
identity = get_identity(context, "spring_metrics", lambda u: u.email)
if identity is not None:
custom['email'] = identity
custom["email"] = identity
html = TRACKING_CODE % {
'tracking_id': self.tracking_id,
'custom_commands': self._generate_custom_javascript(custom),
"tracking_id": self.tracking_id,
"custom_commands": self._generate_custom_javascript(custom),
}
if is_internal_ip(context, 'SPRING_METRICS'):
html = disable_html(html, 'Spring Metrics')
if is_internal_ip(context, "SPRING_METRICS"):
html = disable_html(html, "Spring Metrics")
return html
def _generate_custom_javascript(self, params):
commands = []
convert = params.pop('convert', None)
convert = params.pop("convert", None)
if convert is not None:
commands.append("_springMetq.push(['convert', '%s'])" % convert)
commands.extend("_springMetq.push(['setdata', {'%s': '%s'}]);"
% (var, val) for var, val in params.items())
commands.extend(
"_springMetq.push(['setdata', {'%s': '%s'}]);" % (var, val)
for var, val in params.items()
)
return " ".join(commands)
def contribute_to_analytical(add_node):
SpringMetricsNode() # ensure properly configured
add_node('head_bottom', SpringMetricsNode)
add_node("head_bottom", SpringMetricsNode)

View file

@ -7,10 +7,10 @@ import re
from django.conf import settings
from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import get_required_setting, get_identity
from analytical.utils import get_identity, get_required_setting
WIDGET_KEY_RE = re.compile(r'^[a-zA-Z0-9]*$')
WIDGET_KEY_RE = re.compile(r"^[a-zA-Z0-9]*$")
TRACKING_CODE = """
<script type="text/javascript">
@ -48,39 +48,43 @@ def uservoice(parser, token):
class UserVoiceNode(Node):
def __init__(self):
self.default_widget_key = get_required_setting(
'USERVOICE_WIDGET_KEY', WIDGET_KEY_RE, "must be an alphanumeric string")
"USERVOICE_WIDGET_KEY", WIDGET_KEY_RE, "must be an alphanumeric string"
)
def render(self, context):
widget_key = context.get('uservoice_widget_key')
widget_key = context.get("uservoice_widget_key")
if not widget_key:
widget_key = self.default_widget_key
if not widget_key:
return ''
return ""
# default
options = {}
options.update(getattr(settings, 'USERVOICE_WIDGET_OPTIONS', {}))
options.update(context.get('uservoice_widget_options', {}))
options.update(getattr(settings, "USERVOICE_WIDGET_OPTIONS", {}))
options.update(context.get("uservoice_widget_options", {}))
identity = get_identity(context, 'uservoice', self._identify)
identity = get_identity(context, "uservoice", self._identify)
if identity:
identity = IDENTITY % {'options': json.dumps(identity, sort_keys=True)}
identity = IDENTITY % {"options": json.dumps(identity, sort_keys=True)}
trigger = context.get('uservoice_add_trigger',
getattr(settings, 'USERVOICE_ADD_TRIGGER', True))
trigger = context.get(
"uservoice_add_trigger", getattr(settings, "USERVOICE_ADD_TRIGGER", True)
)
html = TRACKING_CODE % {'widget_key': widget_key,
'options': json.dumps(options, sort_keys=True),
'trigger': TRIGGER if trigger else '',
'identity': identity if identity else ''}
html = TRACKING_CODE % {
"widget_key": widget_key,
"options": json.dumps(options, sort_keys=True),
"trigger": TRIGGER if trigger else "",
"identity": identity if identity else "",
}
return html
def _identify(self, user):
name = user.get_full_name()
if not name:
name = user.username
return {'name': name, 'email': user.email}
return {"name": name, "email": user.email}
def contribute_to_analytical(add_node):
UserVoiceNode() # ensure properly configured
add_node('body_bottom', UserVoiceNode)
add_node("body_bottom", UserVoiceNode)

View file

@ -17,7 +17,7 @@ from analytical.utils import (
is_internal_ip,
)
DOMAIN_RE = re.compile(r'^\S+$')
DOMAIN_RE = re.compile(r"^\S+$")
TRACKING_CODE = """
<script type="text/javascript">
var woo_settings = %(settings)s;
@ -49,25 +49,25 @@ def woopra(parser, token):
class WoopraNode(Node):
def __init__(self):
self.domain = get_required_setting(
'WOOPRA_DOMAIN', DOMAIN_RE,
"must be a domain name")
"WOOPRA_DOMAIN", DOMAIN_RE, "must be a domain name"
)
def render(self, context):
settings = self._get_settings(context)
visitor = self._get_visitor(context)
html = TRACKING_CODE % {
'settings': json.dumps(settings, sort_keys=True),
'visitor': json.dumps(visitor, sort_keys=True),
"settings": json.dumps(settings, sort_keys=True),
"visitor": json.dumps(visitor, sort_keys=True),
}
if is_internal_ip(context, 'WOOPRA'):
html = disable_html(html, 'Woopra')
if is_internal_ip(context, "WOOPRA"):
html = disable_html(html, "Woopra")
return html
def _get_settings(self, context):
variables = {'domain': self.domain}
variables = {"domain": self.domain}
try:
variables['idle_timeout'] = str(settings.WOOPRA_IDLE_TIMEOUT)
variables["idle_timeout"] = str(settings.WOOPRA_IDLE_TIMEOUT)
except AttributeError:
pass
return variables
@ -76,15 +76,14 @@ class WoopraNode(Node):
params = {}
for dict_ in context:
for var, val in dict_.items():
if var.startswith('woopra_'):
if var.startswith("woopra_"):
params[var[7:]] = val
if 'name' not in params and 'email' not in params:
if "name" not in params and "email" not in params:
user = get_user_from_context(context)
if user is not None and get_user_is_authenticated(user):
params['name'] = get_identity(
context, 'woopra', self._identify, user)
params["name"] = get_identity(context, "woopra", self._identify, user)
if user.email:
params['email'] = user.email
params["email"] = user.email
return params
def _identify(self, user):
@ -96,4 +95,4 @@ class WoopraNode(Node):
def contribute_to_analytical(add_node):
WoopraNode() # ensure properly configured
add_node('head_bottom', WoopraNode)
add_node("head_bottom", WoopraNode)

View file

@ -8,11 +8,9 @@ import re
from django.conf import settings
from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import is_internal_ip, disable_html, \
get_required_setting
from analytical.utils import disable_html, get_required_setting, is_internal_ip
COUNTER_ID_RE = re.compile(r'^\d{8}$')
COUNTER_ID_RE = re.compile(r"^\d{8}$")
COUNTER_CODE = """
<script type="text/javascript">
(function (d, w, c) {
@ -59,33 +57,35 @@ def yandex_metrica(parser, token):
class YandexMetricaNode(Node):
def __init__(self):
self.counter_id = get_required_setting(
'YANDEX_METRICA_COUNTER_ID', COUNTER_ID_RE,
"must be (a string containing) a number'")
"YANDEX_METRICA_COUNTER_ID",
COUNTER_ID_RE,
"must be (a string containing) a number'",
)
def render(self, context):
options = {
'id': int(self.counter_id),
'clickmap': True,
'trackLinks': True,
'accurateTrackBounce': True
"id": int(self.counter_id),
"clickmap": True,
"trackLinks": True,
"accurateTrackBounce": True,
}
if getattr(settings, 'YANDEX_METRICA_WEBVISOR', False):
options['webvisor'] = True
if getattr(settings, 'YANDEX_METRICA_TRACKHASH', False):
options['trackHash'] = True
if getattr(settings, 'YANDEX_METRICA_NOINDEX', False):
options['ut'] = 'noindex'
if getattr(settings, 'YANDEX_METRICA_ECOMMERCE', False):
options['ecommerce'] = 'dataLayer'
if getattr(settings, "YANDEX_METRICA_WEBVISOR", False):
options["webvisor"] = True
if getattr(settings, "YANDEX_METRICA_TRACKHASH", False):
options["trackHash"] = True
if getattr(settings, "YANDEX_METRICA_NOINDEX", False):
options["ut"] = "noindex"
if getattr(settings, "YANDEX_METRICA_ECOMMERCE", False):
options["ecommerce"] = "dataLayer"
html = COUNTER_CODE % {
'counter_id': self.counter_id,
'options': json.dumps(options),
"counter_id": self.counter_id,
"options": json.dumps(options),
}
if is_internal_ip(context, 'YANDEX_METRICA'):
html = disable_html(html, 'Yandex.Metrica')
if is_internal_ip(context, "YANDEX_METRICA"):
html = disable_html(html, "Yandex.Metrica")
return html
def contribute_to_analytical(add_node):
YandexMetricaNode() # ensure properly configured
add_node('head_bottom', YandexMetricaNode)
add_node("head_bottom", YandexMetricaNode)

View file

@ -5,9 +5,7 @@ Utility function for django-analytical.
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
HTML_COMMENT = "<!-- %(service)s disabled on internal IP " \
"address\n%(html)s\n-->"
HTML_COMMENT = "<!-- %(service)s disabled on internal IP " "address\n%(html)s\n-->"
def get_required_setting(setting, value_re, invalid_msg):
@ -25,8 +23,9 @@ def get_required_setting(setting, value_re, invalid_msg):
raise AnalyticalException("%s setting is not set" % setting)
value = str(value)
if not value_re.search(value):
raise AnalyticalException("%s setting: %s: '%s'"
% (setting, invalid_msg, value))
raise AnalyticalException(
"%s setting: %s: '%s'" % (setting, invalid_msg, value)
)
return value
@ -38,11 +37,11 @@ def get_user_from_context(context):
`None` is returned.
"""
try:
return context['user']
return context["user"]
except KeyError:
pass
try:
request = context['request']
request = context["request"]
return request.user
except (KeyError, AttributeError):
pass
@ -73,14 +72,14 @@ def get_identity(context, prefix=None, identity_func=None, user=None):
"""
if prefix is not None:
try:
return context['%s_identity' % prefix]
return context["%s_identity" % prefix]
except KeyError:
pass
try:
return context['analytical_identity']
return context["analytical_identity"]
except KeyError:
pass
if getattr(settings, 'ANALYTICAL_AUTO_IDENTIFY', True):
if getattr(settings, "ANALYTICAL_AUTO_IDENTIFY", True):
try:
if user is None:
user = get_user_from_context(context)
@ -103,16 +102,17 @@ def get_domain(context, prefix):
If no explicit domain is found in either the context or the
settings, try to get the domain from the contrib sites framework.
"""
domain = context.get('%s_domain' % prefix)
domain = context.get("%s_domain" % prefix)
if domain is None:
domain = context.get('analytical_domain')
domain = context.get("analytical_domain")
if domain is None:
domain = getattr(settings, '%s_DOMAIN' % prefix.upper(), None)
domain = getattr(settings, "%s_DOMAIN" % prefix.upper(), None)
if domain is None:
domain = getattr(settings, 'ANALYTICAL_DOMAIN', None)
domain = getattr(settings, "ANALYTICAL_DOMAIN", None)
if domain is None:
if 'django.contrib.sites' in settings.INSTALLED_APPS:
if "django.contrib.sites" in settings.INSTALLED_APPS:
from django.contrib.sites.models import Site
try:
domain = Site.objects.get_current().domain
except (ImproperlyConfigured, Site.DoesNotExist):
@ -129,20 +129,20 @@ def is_internal_ip(context, prefix=None):
different notions of internal addresses.
"""
try:
request = context['request']
remote_ip = request.META.get('HTTP_X_FORWARDED_FOR', '')
request = context["request"]
remote_ip = request.META.get("HTTP_X_FORWARDED_FOR", "")
if not remote_ip:
remote_ip = request.META.get('REMOTE_ADDR', '')
remote_ip = request.META.get("REMOTE_ADDR", "")
if not remote_ip:
return False
internal_ips = None
if prefix is not None:
internal_ips = getattr(settings, '%s_INTERNAL_IPS' % prefix, None)
internal_ips = getattr(settings, "%s_INTERNAL_IPS" % prefix, None)
if internal_ips is None:
internal_ips = getattr(settings, 'ANALYTICAL_INTERNAL_IPS', None)
internal_ips = getattr(settings, "ANALYTICAL_INTERNAL_IPS", None)
if internal_ips is None:
internal_ips = getattr(settings, 'INTERNAL_IPS', None)
internal_ips = getattr(settings, "INTERNAL_IPS", None)
return remote_ip in (internal_ips or [])
except (KeyError, AttributeError):
@ -155,7 +155,7 @@ def disable_html(html, service):
The `service` argument is used to display a friendly message.
"""
return HTML_COMMENT % {'html': html, 'service': service}
return HTML_COMMENT % {"html": html, "service": service}
class AnalyticalException(Exception):
@ -163,4 +163,5 @@ class AnalyticalException(Exception):
Raised when an exception occurs in any django-analytical code that should
be silenced in templates.
"""
silent_variable_failure = True

View file

@ -8,3 +8,6 @@ upload-dir = build/docs/html
[tool:pytest]
DJANGO_SETTINGS_MODULE = tests.testproject.settings
[isort]
profile = black

View file

@ -10,46 +10,46 @@ def read_file(fname):
setup(
name='django-analytical',
name="django-analytical",
version=package.__version__,
license=package.__license__,
description=package.__doc__.strip(),
long_description=read_file('README.rst'),
long_description_content_type='text/x-rst',
long_description=read_file("README.rst"),
long_description_content_type="text/x-rst",
author=package.__author__,
author_email=package.__email__,
packages=[
'analytical',
'analytical.templatetags',
"analytical",
"analytical.templatetags",
],
keywords=[
'django',
'analytics',
"django",
"analytics",
],
classifiers=[
'Development Status :: 5 - Production/Stable',
'Environment :: Web Environment',
'Framework :: Django',
'Framework :: Django :: 2.2',
'Framework :: Django :: 3.0',
'Framework :: Django :: 3.1',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Topic :: Internet :: WWW/HTTP',
'Topic :: Software Development :: Libraries :: Python Modules',
"Development Status :: 5 - Production/Stable",
"Environment :: Web Environment",
"Framework :: Django",
"Framework :: Django :: 2.2",
"Framework :: Django :: 3.0",
"Framework :: Django :: 3.1",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Topic :: Internet :: WWW/HTTP",
"Topic :: Software Development :: Libraries :: Python Modules",
],
python_requires='>=3.6',
platforms=['any'],
url='https://github.com/jazzband/django-analytical',
download_url='https://github.com/jazzband/django-analytical/archive/master.zip',
python_requires=">=3.6",
platforms=["any"],
url="https://github.com/jazzband/django-analytical",
download_url="https://github.com/jazzband/django-analytical/archive/master.zip",
project_urls={
'Documentation': 'https://django-analytical.readthedocs.io/',
"Documentation": "https://django-analytical.readthedocs.io/",
},
)

View file

@ -3,29 +3,29 @@ django-analytical testing settings.
"""
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': ':memory:',
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": ":memory:",
}
}
INSTALLED_APPS = [
'django.contrib.sites',
'django.contrib.contenttypes',
'django.contrib.auth',
'analytical',
"django.contrib.sites",
"django.contrib.contenttypes",
"django.contrib.auth",
"analytical",
]
SECRET_KEY = 'testing'
SECRET_KEY = "testing"
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
)
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'APP_DIRS': True,
"BACKEND": "django.template.backends.django.DjangoTemplates",
"APP_DIRS": True,
},
]

View file

@ -6,7 +6,6 @@ from django.template import Library, Node, TemplateSyntaxError
from analytical.templatetags.analytical import TAG_LOCATIONS
register = Library()
@ -14,6 +13,7 @@ def _location_node(location):
class DummyNode(Node):
def render(self, context):
return "<!-- dummy_%s -->" % location
return DummyNode
@ -26,11 +26,12 @@ def _location_tag(location):
if len(bits) > 1:
raise TemplateSyntaxError("'%s' tag takes no arguments" % bits[0])
return _location_nodes[location]
return dummy_tag
for loc in TAG_LOCATIONS:
register.tag('dummy_%s' % loc, _location_tag(loc))
register.tag("dummy_%s" % loc, _location_tag(loc))
def contribute_to_analytical(add_node_cls):

View file

@ -3,9 +3,9 @@ Tests for the generic template tags and filters.
"""
from django.template import Context, Template
from utils import TagTestCase
from analytical.templatetags import analytical
from utils import TagTestCase
class AnalyticsTagTestCase(TagTestCase):
@ -16,7 +16,7 @@ class AnalyticsTagTestCase(TagTestCase):
def setUp(self):
super().setUp()
self._tag_modules = analytical.TAG_MODULES
analytical.TAG_MODULES = ['tests.testproject.dummy']
analytical.TAG_MODULES = ["tests.testproject.dummy"]
analytical.template_nodes = analytical._load_template_nodes()
def tearDown(self):
@ -31,6 +31,6 @@ class AnalyticsTagTestCase(TagTestCase):
return t.render(Context(vars))
def test_location_tags(self):
for loc in ['head_top', 'head_bottom', 'body_top', 'body_bottom']:
for loc in ["head_top", "head_bottom", "body_top", "body_bottom"]:
r = self.render_location_tag(loc)
self.assertTrue('dummy_%s' % loc in r, r)
self.assertTrue("dummy_%s" % loc in r, r)

View file

@ -8,39 +8,46 @@ from django.http import HttpRequest
from django.template import Context
from django.test import TestCase
from django.test.utils import override_settings
from analytical.templatetags.chartbeat import ChartbeatTopNode, \
ChartbeatBottomNode
from utils import TagTestCase
from analytical.templatetags.chartbeat import ChartbeatBottomNode, ChartbeatTopNode
from analytical.utils import AnalyticalException
@override_settings(CHARTBEAT_USER_ID='12345')
@override_settings(CHARTBEAT_USER_ID="12345")
class ChartbeatTagTestCaseNoSites(TestCase):
def test_rendering_setup_no_site(self):
r = ChartbeatBottomNode().render(Context())
self.assertTrue('var _sf_async_config={"uid": "12345"};' in r, r)
@override_settings(INSTALLED_APPS=(
'analytical',
'django.contrib.sites',
'django.contrib.auth',
'django.contrib.contenttypes',
))
@override_settings(CHARTBEAT_USER_ID='12345')
@override_settings(
INSTALLED_APPS=(
"analytical",
"django.contrib.sites",
"django.contrib.auth",
"django.contrib.contenttypes",
)
)
@override_settings(CHARTBEAT_USER_ID="12345")
class ChartbeatTagTestCaseWithSites(TestCase):
def setUp(self):
from django.core.management import call_command
call_command("migrate", verbosity=0)
def test_rendering_setup_site(self):
from django.contrib.sites.models import Site
site = Site.objects.create(domain="test.com", name="test")
with override_settings(SITE_ID=site.id):
r = ChartbeatBottomNode().render(Context())
self.assertTrue(re.search('var _sf_async_config={.*"uid": "12345".*};', r), r)
self.assertTrue(re.search('var _sf_async_config={.*"domain": "test.com".*};', r), r)
self.assertTrue(
re.search('var _sf_async_config={.*"uid": "12345".*};', r), r
)
self.assertTrue(
re.search('var _sf_async_config={.*"domain": "test.com".*};', r), r
)
@override_settings(CHARTBEAT_AUTO_DOMAIN=False)
def test_auto_domain_false(self):
@ -53,48 +60,65 @@ class ChartbeatTagTestCaseWithSites(TestCase):
self.assertTrue('var _sf_async_config={"uid": "12345"};' in r, r)
@override_settings(CHARTBEAT_USER_ID='12345')
@override_settings(CHARTBEAT_USER_ID="12345")
class ChartbeatTagTestCase(TagTestCase):
"""
Tests for the ``chartbeat`` template tag.
"""
def test_top_tag(self):
r = self.render_tag('chartbeat', 'chartbeat_top', {'chartbeat_domain': "test.com"})
self.assertTrue('var _sf_startpt=(new Date()).getTime()' in r, r)
r = self.render_tag(
"chartbeat", "chartbeat_top", {"chartbeat_domain": "test.com"}
)
self.assertTrue("var _sf_startpt=(new Date()).getTime()" in r, r)
def test_bottom_tag(self):
r = self.render_tag('chartbeat', 'chartbeat_bottom', {'chartbeat_domain': "test.com"})
r = self.render_tag(
"chartbeat", "chartbeat_bottom", {"chartbeat_domain": "test.com"}
)
self.assertTrue(re.search('var _sf_async_config={.*"uid": "12345".*};', r), r)
self.assertTrue(re.search('var _sf_async_config={.*"domain": "test.com".*};', r), r)
self.assertTrue(
re.search('var _sf_async_config={.*"domain": "test.com".*};', r), r
)
def test_top_node(self):
r = ChartbeatTopNode().render(Context({
'chartbeat_domain': "test.com",
}))
self.assertTrue('var _sf_startpt=(new Date()).getTime()' in r, r)
r = ChartbeatTopNode().render(
Context(
{
"chartbeat_domain": "test.com",
}
)
)
self.assertTrue("var _sf_startpt=(new Date()).getTime()" in r, r)
def test_bottom_node(self):
r = ChartbeatBottomNode().render(Context({
'chartbeat_domain': "test.com",
}))
r = ChartbeatBottomNode().render(
Context(
{
"chartbeat_domain": "test.com",
}
)
)
self.assertTrue(re.search('var _sf_async_config={.*"uid": "12345".*};', r), r)
self.assertTrue(re.search('var _sf_async_config={.*"domain": "test.com".*};', r), r)
self.assertTrue(
re.search('var _sf_async_config={.*"domain": "test.com".*};', r), r
)
@override_settings(CHARTBEAT_USER_ID=None)
def test_no_user_id(self):
self.assertRaises(AnalyticalException, ChartbeatBottomNode)
@override_settings(CHARTBEAT_USER_ID='123abc')
@override_settings(CHARTBEAT_USER_ID="123abc")
def test_wrong_user_id(self):
self.assertRaises(AnalyticalException, ChartbeatBottomNode)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
@override_settings(ANALYTICAL_INTERNAL_IPS=["1.1.1.1"])
def test_render_internal_ip(self):
req = HttpRequest()
req.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': req})
req.META["REMOTE_ADDR"] = "1.1.1.1"
context = Context({"request": req})
r = ChartbeatBottomNode().render(context)
self.assertTrue(r.startswith(
'<!-- Chartbeat disabled on internal IP address'), r)
self.assertTrue(r.endswith('-->'), r)
self.assertTrue(
r.startswith("<!-- Chartbeat disabled on internal IP address"), r
)
self.assertTrue(r.endswith("-->"), r)

View file

@ -5,20 +5,20 @@ Tests for the Clickmap template tags and filters.
from django.http import HttpRequest
from django.template import Context
from django.test.utils import override_settings
from utils import TagTestCase
from analytical.templatetags.clickmap import ClickmapNode
from utils import TagTestCase
from analytical.utils import AnalyticalException
@override_settings(CLICKMAP_TRACKER_ID='12345ABC')
@override_settings(CLICKMAP_TRACKER_ID="12345ABC")
class ClickmapTagTestCase(TagTestCase):
"""
Tests for the ``clickmap`` template tag.
"""
def test_tag(self):
r = self.render_tag('clickmap', 'clickmap')
r = self.render_tag("clickmap", "clickmap")
self.assertTrue("tracker: '12345ABC', version:'2'};" in r, r)
def test_node(self):
@ -29,16 +29,17 @@ class ClickmapTagTestCase(TagTestCase):
def test_no_site_id(self):
self.assertRaises(AnalyticalException, ClickmapNode)
@override_settings(CLICKMAP_TRACKER_ID='ab#c')
@override_settings(CLICKMAP_TRACKER_ID="ab#c")
def test_wrong_site_id(self):
self.assertRaises(AnalyticalException, ClickmapNode)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
@override_settings(ANALYTICAL_INTERNAL_IPS=["1.1.1.1"])
def test_render_internal_ip(self):
req = HttpRequest()
req.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': req})
req.META["REMOTE_ADDR"] = "1.1.1.1"
context = Context({"request": req})
r = ClickmapNode().render(context)
self.assertTrue(r.startswith(
'<!-- Clickmap disabled on internal IP address'), r)
self.assertTrue(r.endswith('-->'), r)
self.assertTrue(
r.startswith("<!-- Clickmap disabled on internal IP address"), r
)
self.assertTrue(r.endswith("-->"), r)

View file

@ -4,65 +4,71 @@ Tests for the Clicky template tags and filters.
import re
from django.contrib.auth.models import User, AnonymousUser
from django.contrib.auth.models import AnonymousUser, User
from django.http import HttpRequest
from django.template import Context
from django.test.utils import override_settings
from utils import TagTestCase
from analytical.templatetags.clicky import ClickyNode
from utils import TagTestCase
from analytical.utils import AnalyticalException
@override_settings(CLICKY_SITE_ID='12345678')
@override_settings(CLICKY_SITE_ID="12345678")
class ClickyTagTestCase(TagTestCase):
"""
Tests for the ``clicky`` template tag.
"""
def test_tag(self):
r = self.render_tag('clicky', 'clicky')
self.assertTrue('clicky_site_ids.push(12345678);' in r, r)
r = self.render_tag("clicky", "clicky")
self.assertTrue("clicky_site_ids.push(12345678);" in r, r)
self.assertTrue('src="//in.getclicky.com/12345678ns.gif"' in r, r)
def test_node(self):
r = ClickyNode().render(Context({}))
self.assertTrue('clicky_site_ids.push(12345678);' in r, r)
self.assertTrue("clicky_site_ids.push(12345678);" in r, r)
self.assertTrue('src="//in.getclicky.com/12345678ns.gif"' in r, r)
@override_settings(CLICKY_SITE_ID=None)
def test_no_site_id(self):
self.assertRaises(AnalyticalException, ClickyNode)
@override_settings(CLICKY_SITE_ID='123abc')
@override_settings(CLICKY_SITE_ID="123abc")
def test_wrong_site_id(self):
self.assertRaises(AnalyticalException, ClickyNode)
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify(self):
r = ClickyNode().render(Context({'user': User(username='test')}))
self.assertTrue('var clicky_custom = {"session": {"username": "test"}};' in r, r)
r = ClickyNode().render(Context({"user": User(username="test")}))
self.assertTrue(
'var clicky_custom = {"session": {"username": "test"}};' in r, r
)
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify_anonymous_user(self):
r = ClickyNode().render(Context({'user': AnonymousUser()}))
r = ClickyNode().render(Context({"user": AnonymousUser()}))
self.assertFalse('var clicky_custom = {"session": {"username":' in r, r)
def test_custom(self):
r = ClickyNode().render(Context({
'clicky_var1': 'val1',
'clicky_var2': 'val2',
}))
r = ClickyNode().render(
Context(
{
"clicky_var1": "val1",
"clicky_var2": "val2",
}
)
)
self.assertTrue(
re.search(r'var clicky_custom = {.*"var1": "val1", "var2": "val2".*};', r),
r)
r,
)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
@override_settings(ANALYTICAL_INTERNAL_IPS=["1.1.1.1"])
def test_render_internal_ip(self):
req = HttpRequest()
req.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': req})
req.META["REMOTE_ADDR"] = "1.1.1.1"
context = Context({"request": req})
r = ClickyNode().render(context)
self.assertTrue(r.startswith(
'<!-- Clicky disabled on internal IP address'), r)
self.assertTrue(r.endswith('-->'), r)
self.assertTrue(r.startswith("<!-- Clicky disabled on internal IP address"), r)
self.assertTrue(r.endswith("-->"), r)

View file

@ -5,46 +5,47 @@ Tests for the Crazy Egg template tags and filters.
from django.http import HttpRequest
from django.template import Context
from django.test.utils import override_settings
from utils import TagTestCase
from analytical.templatetags.crazy_egg import CrazyEggNode
from utils import TagTestCase
from analytical.utils import AnalyticalException
@override_settings(CRAZY_EGG_ACCOUNT_NUMBER='12345678')
@override_settings(CRAZY_EGG_ACCOUNT_NUMBER="12345678")
class CrazyEggTagTestCase(TagTestCase):
"""
Tests for the ``crazy_egg`` template tag.
"""
def test_tag(self):
r = self.render_tag('crazy_egg', 'crazy_egg')
self.assertTrue('/1234/5678.js' in r, r)
r = self.render_tag("crazy_egg", "crazy_egg")
self.assertTrue("/1234/5678.js" in r, r)
def test_node(self):
r = CrazyEggNode().render(Context())
self.assertTrue('/1234/5678.js' in r, r)
self.assertTrue("/1234/5678.js" in r, r)
@override_settings(CRAZY_EGG_ACCOUNT_NUMBER=None)
def test_no_account_number(self):
self.assertRaises(AnalyticalException, CrazyEggNode)
@override_settings(CRAZY_EGG_ACCOUNT_NUMBER='123abc')
@override_settings(CRAZY_EGG_ACCOUNT_NUMBER="123abc")
def test_wrong_account_number(self):
self.assertRaises(AnalyticalException, CrazyEggNode)
def test_uservars(self):
context = Context({'crazy_egg_var1': 'foo', 'crazy_egg_var2': 'bar'})
context = Context({"crazy_egg_var1": "foo", "crazy_egg_var2": "bar"})
r = CrazyEggNode().render(context)
self.assertTrue("CE2.set(1, 'foo');" in r, r)
self.assertTrue("CE2.set(2, 'bar');" in r, r)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
@override_settings(ANALYTICAL_INTERNAL_IPS=["1.1.1.1"])
def test_render_internal_ip(self):
req = HttpRequest()
req.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': req})
req.META["REMOTE_ADDR"] = "1.1.1.1"
context = Context({"request": req})
r = CrazyEggNode().render(context)
self.assertTrue(r.startswith(
'<!-- Crazy Egg disabled on internal IP address'), r)
self.assertTrue(r.endswith('-->'), r)
self.assertTrue(
r.startswith("<!-- Crazy Egg disabled on internal IP address"), r
)
self.assertTrue(r.endswith("-->"), r)

View file

@ -4,13 +4,15 @@ Tests for the Facebook Pixel template tags.
from django.http import HttpRequest
from django.template import Context, Template, TemplateSyntaxError
from django.test import override_settings
from utils import TagTestCase
from analytical.templatetags.analytical import _load_template_nodes
from analytical.templatetags.facebook_pixel import FacebookPixelHeadNode, FacebookPixelBodyNode
from utils import TagTestCase
from analytical.templatetags.facebook_pixel import (
FacebookPixelBodyNode,
FacebookPixelHeadNode,
)
from analytical.utils import AnalyticalException
expected_head_html = """\
<script>
!function(f,b,e,v,n,t,s)
@ -34,13 +36,13 @@ expected_body_html = """\
"""
@override_settings(FACEBOOK_PIXEL_ID='1234567890')
@override_settings(FACEBOOK_PIXEL_ID="1234567890")
class FacebookPixelTagTestCase(TagTestCase):
maxDiff = None
def test_head_tag(self):
html = self.render_tag('facebook_pixel', 'facebook_pixel_head')
html = self.render_tag("facebook_pixel", "facebook_pixel_head")
self.assertEqual(expected_head_html, html)
def test_head_node(self):
@ -48,7 +50,7 @@ class FacebookPixelTagTestCase(TagTestCase):
self.assertEqual(expected_head_html, html)
def test_body_tag(self):
html = self.render_tag('facebook_pixel', 'facebook_pixel_body')
html = self.render_tag("facebook_pixel", "facebook_pixel_body")
self.assertEqual(expected_body_html, html)
def test_body_node(self):
@ -59,41 +61,59 @@ class FacebookPixelTagTestCase(TagTestCase):
self.assertRaisesRegex(
TemplateSyntaxError,
r"^'facebook_pixel_head' takes no arguments$",
lambda: (Template('{% load facebook_pixel %}{% facebook_pixel_head "arg" %}')
.render(Context({}))),
lambda: (
Template(
'{% load facebook_pixel %}{% facebook_pixel_head "arg" %}'
).render(Context({}))
),
)
self.assertRaisesRegex(
TemplateSyntaxError,
r"^'facebook_pixel_body' takes no arguments$",
lambda: (Template('{% load facebook_pixel %}{% facebook_pixel_body "arg" %}')
.render(Context({}))),
lambda: (
Template(
'{% load facebook_pixel %}{% facebook_pixel_body "arg" %}'
).render(Context({}))
),
)
@override_settings(FACEBOOK_PIXEL_ID=None)
def test_no_id(self):
expected_pattern = r'^FACEBOOK_PIXEL_ID setting is not set$'
self.assertRaisesRegex(AnalyticalException, expected_pattern, FacebookPixelHeadNode)
self.assertRaisesRegex(AnalyticalException, expected_pattern, FacebookPixelBodyNode)
expected_pattern = r"^FACEBOOK_PIXEL_ID setting is not set$"
self.assertRaisesRegex(
AnalyticalException, expected_pattern, FacebookPixelHeadNode
)
self.assertRaisesRegex(
AnalyticalException, expected_pattern, FacebookPixelBodyNode
)
@override_settings(FACEBOOK_PIXEL_ID='invalid')
@override_settings(FACEBOOK_PIXEL_ID="invalid")
def test_invalid_id(self):
expected_pattern = (
r"^FACEBOOK_PIXEL_ID setting: must be \(a string containing\) a number: 'invalid'$")
self.assertRaisesRegex(AnalyticalException, expected_pattern, FacebookPixelHeadNode)
self.assertRaisesRegex(AnalyticalException, expected_pattern, FacebookPixelBodyNode)
r"^FACEBOOK_PIXEL_ID setting: must be"
r" \(a string containing\) a number: 'invalid'$"
)
self.assertRaisesRegex(
AnalyticalException, expected_pattern, FacebookPixelHeadNode
)
self.assertRaisesRegex(
AnalyticalException, expected_pattern, FacebookPixelBodyNode
)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
@override_settings(ANALYTICAL_INTERNAL_IPS=["1.1.1.1"])
def test_render_internal_ip(self):
request = HttpRequest()
request.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': request})
request.META["REMOTE_ADDR"] = "1.1.1.1"
context = Context({"request": request})
def _disabled(html):
return '\n'.join([
'<!-- Facebook Pixel disabled on internal IP address',
html,
'-->',
])
return "\n".join(
[
"<!-- Facebook Pixel disabled on internal IP address",
html,
"-->",
]
)
head_html = FacebookPixelHeadNode().render(context)
self.assertEqual(_disabled(expected_head_html), head_html)
@ -106,9 +126,12 @@ class FacebookPixelTagTestCase(TagTestCase):
`facebook_pixel.contribute_to_analytical` registers the head and body nodes.
"""
template_nodes = _load_template_nodes()
self.assertEqual({
'head_top': [],
'head_bottom': [FacebookPixelHeadNode],
'body_top': [],
'body_bottom': [FacebookPixelBodyNode],
}, template_nodes)
self.assertEqual(
{
"head_top": [],
"head_bottom": [FacebookPixelHeadNode],
"body_top": [],
"body_bottom": [FacebookPixelBodyNode],
},
template_nodes,
)

View file

@ -5,20 +5,21 @@ Tests for the Gauges template tags and filters.
from django.http import HttpRequest
from django.template import Context
from django.test.utils import override_settings
from utils import TagTestCase
from analytical.templatetags.gauges import GaugesNode
from utils import TagTestCase
from analytical.utils import AnalyticalException
@override_settings(GAUGES_SITE_ID='1234567890abcdef0123456789')
@override_settings(GAUGES_SITE_ID="1234567890abcdef0123456789")
class GaugesTagTestCase(TagTestCase):
"""
Tests for the ``gauges`` template tag.
"""
def test_tag(self):
self.assertEqual("""
self.assertEqual(
"""
<script type="text/javascript">
var _gauges = _gauges || [];
(function() {
@ -32,11 +33,13 @@ class GaugesTagTestCase(TagTestCase):
s.parentNode.insertBefore(t, s);
})();
</script>
""", self.render_tag('gauges', 'gauges'))
""",
self.render_tag("gauges", "gauges"),
)
def test_node(self):
self.assertEqual(
"""
"""
<script type="text/javascript">
var _gauges = _gauges || [];
(function() {
@ -50,22 +53,23 @@ class GaugesTagTestCase(TagTestCase):
s.parentNode.insertBefore(t, s);
})();
</script>
""", GaugesNode().render(Context()))
""",
GaugesNode().render(Context()),
)
@override_settings(GAUGES_SITE_ID=None)
def test_no_account_number(self):
self.assertRaises(AnalyticalException, GaugesNode)
@override_settings(GAUGES_SITE_ID='123abQ')
@override_settings(GAUGES_SITE_ID="123abQ")
def test_wrong_account_number(self):
self.assertRaises(AnalyticalException, GaugesNode)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
@override_settings(ANALYTICAL_INTERNAL_IPS=["1.1.1.1"])
def test_render_internal_ip(self):
req = HttpRequest()
req.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': req})
req.META["REMOTE_ADDR"] = "1.1.1.1"
context = Context({"request": req})
r = GaugesNode().render(context)
self.assertTrue(r.startswith(
'<!-- Gauges disabled on internal IP address'), r)
self.assertTrue(r.endswith('-->'), r)
self.assertTrue(r.startswith("<!-- Gauges disabled on internal IP address"), r)
self.assertTrue(r.endswith("-->"), r)

View file

@ -5,23 +5,31 @@ Tests for the Google Analytics template tags and filters.
from django.http import HttpRequest
from django.template import Context
from django.test.utils import override_settings
from utils import TagTestCase, TestCase
from analytical.templatetags.google_analytics import GoogleAnalyticsNode, \
TRACK_SINGLE_DOMAIN, TRACK_MULTIPLE_DOMAINS, TRACK_MULTIPLE_SUBDOMAINS,\
SCOPE_VISITOR, SCOPE_SESSION, SCOPE_PAGE
from utils import TestCase, TagTestCase
from analytical.templatetags.google_analytics import (
SCOPE_PAGE,
SCOPE_SESSION,
SCOPE_VISITOR,
TRACK_MULTIPLE_DOMAINS,
TRACK_MULTIPLE_SUBDOMAINS,
TRACK_SINGLE_DOMAIN,
GoogleAnalyticsNode,
)
from analytical.utils import AnalyticalException
@override_settings(GOOGLE_ANALYTICS_PROPERTY_ID='UA-123456-7',
GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_SINGLE_DOMAIN)
@override_settings(
GOOGLE_ANALYTICS_PROPERTY_ID="UA-123456-7",
GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_SINGLE_DOMAIN,
)
class GoogleAnalyticsTagTestCase(TagTestCase):
"""
Tests for the ``google_analytics`` template tag.
"""
def test_tag(self):
r = self.render_tag('google_analytics', 'google_analytics')
r = self.render_tag("google_analytics", "google_analytics")
self.assertTrue("_gaq.push(['_setAccount', 'UA-123456-7']);" in r, r)
self.assertTrue("_gaq.push(['_trackPageview']);" in r, r)
@ -34,19 +42,23 @@ class GoogleAnalyticsTagTestCase(TagTestCase):
def test_no_property_id(self):
self.assertRaises(AnalyticalException, GoogleAnalyticsNode)
@override_settings(GOOGLE_ANALYTICS_PROPERTY_ID='wrong')
@override_settings(GOOGLE_ANALYTICS_PROPERTY_ID="wrong")
def test_wrong_property_id(self):
self.assertRaises(AnalyticalException, GoogleAnalyticsNode)
@override_settings(GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_MULTIPLE_SUBDOMAINS,
GOOGLE_ANALYTICS_DOMAIN='example.com')
@override_settings(
GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_MULTIPLE_SUBDOMAINS,
GOOGLE_ANALYTICS_DOMAIN="example.com",
)
def test_track_multiple_subdomains(self):
r = GoogleAnalyticsNode().render(Context())
self.assertTrue("_gaq.push(['_setDomainName', 'example.com']);" in r, r)
self.assertTrue("_gaq.push(['_setAllowHash', false]);" in r, r)
@override_settings(GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_MULTIPLE_DOMAINS,
GOOGLE_ANALYTICS_DOMAIN='example.com')
@override_settings(
GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_MULTIPLE_DOMAINS,
GOOGLE_ANALYTICS_DOMAIN="example.com",
)
def test_track_multiple_domains(self):
r = GoogleAnalyticsNode().render(Context())
self.assertTrue("_gaq.push(['_setDomainName', 'example.com']);" in r, r)
@ -54,12 +66,14 @@ class GoogleAnalyticsTagTestCase(TagTestCase):
self.assertTrue("_gaq.push(['_setAllowLinker', true]);" in r, r)
def test_custom_vars(self):
context = Context({
'google_analytics_var1': ('test1', 'foo'),
'google_analytics_var2': ('test2', 'bar', SCOPE_VISITOR),
'google_analytics_var4': ('test4', 'baz', SCOPE_SESSION),
'google_analytics_var5': ('test5', 'qux', SCOPE_PAGE),
})
context = Context(
{
"google_analytics_var1": ("test1", "foo"),
"google_analytics_var2": ("test2", "bar", SCOPE_VISITOR),
"google_analytics_var4": ("test4", "baz", SCOPE_SESSION),
"google_analytics_var5": ("test5", "qux", SCOPE_PAGE),
}
)
r = GoogleAnalyticsNode().render(context)
self.assertTrue("_gaq.push(['_setCustomVar', 1, 'test1', 'foo', 3]);" in r, r)
self.assertTrue("_gaq.push(['_setCustomVar', 2, 'test2', 'bar', 1]);" in r, r)
@ -79,21 +93,22 @@ class GoogleAnalyticsTagTestCase(TagTestCase):
r = GoogleAnalyticsNode().render(Context())
self.assertTrue("stats.g.doubleclick.net/dc.js" in r, r)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
@override_settings(ANALYTICAL_INTERNAL_IPS=["1.1.1.1"])
def test_render_internal_ip(self):
req = HttpRequest()
req.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': req})
req.META["REMOTE_ADDR"] = "1.1.1.1"
context = Context({"request": req})
r = GoogleAnalyticsNode().render(context)
self.assertTrue(r.startswith(
'<!-- Google Analytics disabled on internal IP address'), r)
self.assertTrue(r.endswith('-->'), r)
self.assertTrue(
r.startswith("<!-- Google Analytics disabled on internal IP address"), r
)
self.assertTrue(r.endswith("-->"), r)
@override_settings(GOOGLE_ANALYTICS_ANONYMIZE_IP=True)
def test_anonymize_ip(self):
r = GoogleAnalyticsNode().render(Context())
self.assertTrue("_gaq.push(['_gat._anonymizeIp']);" in r, r)
self.assertTrue(r.index('_gat._anonymizeIp') < r.index('_trackPageview'), r)
self.assertTrue(r.index("_gat._anonymizeIp") < r.index("_trackPageview"), r)
@override_settings(GOOGLE_ANALYTICS_ANONYMIZE_IP=False)
def test_anonymize_ip_not_present(self):
@ -105,7 +120,7 @@ class GoogleAnalyticsTagTestCase(TagTestCase):
r = GoogleAnalyticsNode().render(Context())
self.assertTrue("_gaq.push(['_setSampleRate', '0.00']);" in r, r)
@override_settings(GOOGLE_ANALYTICS_SAMPLE_RATE='100.00')
@override_settings(GOOGLE_ANALYTICS_SAMPLE_RATE="100.00")
def test_set_sample_rate_max(self):
r = GoogleAnalyticsNode().render(Context())
self.assertTrue("_gaq.push(['_setSampleRate', '100.00']);" in r, r)
@ -125,7 +140,7 @@ class GoogleAnalyticsTagTestCase(TagTestCase):
r = GoogleAnalyticsNode().render(Context())
self.assertTrue("_gaq.push(['_setSiteSpeedSampleRate', '0.00']);" in r, r)
@override_settings(GOOGLE_ANALYTICS_SITE_SPEED_SAMPLE_RATE='100.00')
@override_settings(GOOGLE_ANALYTICS_SITE_SPEED_SAMPLE_RATE="100.00")
def test_set_site_speed_sample_rate_max(self):
r = GoogleAnalyticsNode().render(Context())
self.assertTrue("_gaq.push(['_setSiteSpeedSampleRate', '100.00']);" in r, r)
@ -145,7 +160,7 @@ class GoogleAnalyticsTagTestCase(TagTestCase):
r = GoogleAnalyticsNode().render(Context())
self.assertTrue("_gaq.push(['_setSessionCookieTimeout', '0']);" in r, r)
@override_settings(GOOGLE_ANALYTICS_SESSION_COOKIE_TIMEOUT='10000')
@override_settings(GOOGLE_ANALYTICS_SESSION_COOKIE_TIMEOUT="10000")
def test_set_session_cookie_timeout_as_string(self):
r = GoogleAnalyticsNode().render(Context())
self.assertTrue("_gaq.push(['_setSessionCookieTimeout', '10000']);" in r, r)
@ -160,7 +175,7 @@ class GoogleAnalyticsTagTestCase(TagTestCase):
r = GoogleAnalyticsNode().render(Context())
self.assertTrue("_gaq.push(['_setVisitorCookieTimeout', '0']);" in r, r)
@override_settings(GOOGLE_ANALYTICS_VISITOR_COOKIE_TIMEOUT='10000')
@override_settings(GOOGLE_ANALYTICS_VISITOR_COOKIE_TIMEOUT="10000")
def test_set_visitor_cookie_timeout_as_string(self):
r = GoogleAnalyticsNode().render(Context())
self.assertTrue("_gaq.push(['_setVisitorCookieTimeout', '10000']);" in r, r)
@ -171,10 +186,12 @@ class GoogleAnalyticsTagTestCase(TagTestCase):
self.assertRaises(AnalyticalException, GoogleAnalyticsNode().render, context)
@override_settings(GOOGLE_ANALYTICS_PROPERTY_ID='UA-123456-7',
GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_MULTIPLE_DOMAINS,
GOOGLE_ANALYTICS_DOMAIN=None,
ANALYTICAL_DOMAIN=None)
@override_settings(
GOOGLE_ANALYTICS_PROPERTY_ID="UA-123456-7",
GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_MULTIPLE_DOMAINS,
GOOGLE_ANALYTICS_DOMAIN=None,
ANALYTICAL_DOMAIN=None,
)
class NoDomainTestCase(TestCase):
def test_exception_without_domain(self):
context = Context()

View file

@ -6,23 +6,25 @@ from django.contrib.auth.models import User
from django.http import HttpRequest
from django.template import Context
from django.test.utils import override_settings
from utils import TagTestCase
from analytical.templatetags.google_analytics_gtag import GoogleAnalyticsGTagNode
from utils import TagTestCase
from analytical.utils import AnalyticalException
@override_settings(GOOGLE_ANALYTICS_GTAG_PROPERTY_ID='UA-123456-7')
@override_settings(GOOGLE_ANALYTICS_GTAG_PROPERTY_ID="UA-123456-7")
class GoogleAnalyticsTagTestCase(TagTestCase):
"""
Tests for the ``google_analytics_js`` template tag.
"""
def test_tag(self):
r = self.render_tag('google_analytics_gtag', 'google_analytics_gtag')
r = self.render_tag("google_analytics_gtag", "google_analytics_gtag")
self.assertTrue(
'<script async src="https://www.googletagmanager.com/gtag/js?id=UA-123456-7"></script>'
in r, r)
in r,
r,
)
self.assertTrue("gtag('js', new Date());" in r, r)
self.assertTrue("gtag('config', 'UA-123456-7');" in r, r)
@ -30,7 +32,9 @@ class GoogleAnalyticsTagTestCase(TagTestCase):
r = GoogleAnalyticsGTagNode().render(Context())
self.assertTrue(
'<script async src="https://www.googletagmanager.com/gtag/js?id=UA-123456-7"></script>'
in r, r)
in r,
r,
)
self.assertTrue("gtag('js', new Date());" in r, r)
self.assertTrue("gtag('config', 'UA-123456-7');" in r, r)
@ -38,51 +42,64 @@ class GoogleAnalyticsTagTestCase(TagTestCase):
def test_no_property_id(self):
self.assertRaises(AnalyticalException, GoogleAnalyticsGTagNode)
@override_settings(GOOGLE_ANALYTICS_GTAG_PROPERTY_ID='wrong')
@override_settings(GOOGLE_ANALYTICS_GTAG_PROPERTY_ID="wrong")
def test_wrong_property_id(self):
self.assertRaises(AnalyticalException, GoogleAnalyticsGTagNode)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
@override_settings(ANALYTICAL_INTERNAL_IPS=["1.1.1.1"])
def test_render_internal_ip(self):
req = HttpRequest()
req.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': req})
req.META["REMOTE_ADDR"] = "1.1.1.1"
context = Context({"request": req})
r = GoogleAnalyticsGTagNode().render(context)
self.assertTrue(r.startswith(
'<!-- Google Analytics disabled on internal IP address'), r)
self.assertTrue(r.endswith('-->'), r)
self.assertTrue(
r.startswith("<!-- Google Analytics disabled on internal IP address"), r
)
self.assertTrue(r.endswith("-->"), r)
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify(self):
r = GoogleAnalyticsGTagNode().render(Context({'user': User(username='test')}))
r = GoogleAnalyticsGTagNode().render(Context({"user": User(username="test")}))
self.assertTrue("gtag('set', {'user_id': 'test'});" in r, r)
@override_settings(GOOGLE_ANALYTICS_GTAG_PROPERTY_ID='G-12345678')
@override_settings(GOOGLE_ANALYTICS_GTAG_PROPERTY_ID="G-12345678")
def test_tag_with_measurement_id(self):
r = self.render_tag('google_analytics_gtag', 'google_analytics_gtag')
r = self.render_tag("google_analytics_gtag", "google_analytics_gtag")
self.assertTrue(
('<script async src="https://www.googletagmanager.com/gtag/' +
'js?id=G-12345678"></script>')
in r, r)
(
'<script async src="https://www.googletagmanager.com/gtag/'
+ 'js?id=G-12345678"></script>'
)
in r,
r,
)
self.assertTrue("gtag('js', new Date());" in r, r)
self.assertTrue("gtag('config', 'G-12345678');" in r, r)
@override_settings(GOOGLE_ANALYTICS_GTAG_PROPERTY_ID='AW-1234567890')
@override_settings(GOOGLE_ANALYTICS_GTAG_PROPERTY_ID="AW-1234567890")
def test_tag_with_conversion_id(self):
r = self.render_tag('google_analytics_gtag', 'google_analytics_gtag')
r = self.render_tag("google_analytics_gtag", "google_analytics_gtag")
self.assertTrue(
('<script async src="https://www.googletagmanager.com/gtag/' +
'js?id=AW-1234567890"></script>')
in r, r)
(
'<script async src="https://www.googletagmanager.com/gtag/'
+ 'js?id=AW-1234567890"></script>'
)
in r,
r,
)
self.assertTrue("gtag('js', new Date());" in r, r)
self.assertTrue("gtag('config', 'AW-1234567890');" in r, r)
@override_settings(GOOGLE_ANALYTICS_GTAG_PROPERTY_ID='DC-12345678')
@override_settings(GOOGLE_ANALYTICS_GTAG_PROPERTY_ID="DC-12345678")
def test_tag_with_advertiser_id(self):
r = self.render_tag('google_analytics_gtag', 'google_analytics_gtag')
r = self.render_tag("google_analytics_gtag", "google_analytics_gtag")
self.assertTrue(
('<script async src="https://www.googletagmanager.com/gtag/' +
'js?id=DC-12345678"></script>')
in r, r)
(
'<script async src="https://www.googletagmanager.com/gtag/'
+ 'js?id=DC-12345678"></script>'
)
in r,
r,
)
self.assertTrue("gtag('js', new Date());" in r, r)
self.assertTrue("gtag('config', 'DC-12345678');" in r, r)

View file

@ -5,35 +5,49 @@ Tests for the Google Analytics template tags and filters, using the new analytic
from django.http import HttpRequest
from django.template import Context
from django.test.utils import override_settings
from utils import TagTestCase, TestCase
from analytical.templatetags.google_analytics_js import GoogleAnalyticsJsNode, \
TRACK_SINGLE_DOMAIN, TRACK_MULTIPLE_DOMAINS, TRACK_MULTIPLE_SUBDOMAINS
from utils import TestCase, TagTestCase
from analytical.templatetags.google_analytics_js import (
TRACK_MULTIPLE_DOMAINS,
TRACK_MULTIPLE_SUBDOMAINS,
TRACK_SINGLE_DOMAIN,
GoogleAnalyticsJsNode,
)
from analytical.utils import AnalyticalException
@override_settings(GOOGLE_ANALYTICS_JS_PROPERTY_ID='UA-123456-7',
GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_SINGLE_DOMAIN)
@override_settings(
GOOGLE_ANALYTICS_JS_PROPERTY_ID="UA-123456-7",
GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_SINGLE_DOMAIN,
)
class GoogleAnalyticsTagTestCase(TagTestCase):
"""
Tests for the ``google_analytics_js`` template tag.
"""
def test_tag(self):
r = self.render_tag('google_analytics_js', 'google_analytics_js')
self.assertTrue("""(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
r = self.render_tag("google_analytics_js", "google_analytics_js")
self.assertTrue(
"""(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');""" in r, r)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');"""
in r,
r,
)
self.assertTrue("ga('create', 'UA-123456-7', 'auto', {});" in r, r)
self.assertTrue("ga('send', 'pageview');" in r, r)
def test_node(self):
r = GoogleAnalyticsJsNode().render(Context())
self.assertTrue("""(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
self.assertTrue(
"""(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');""" in r, r)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');"""
in r,
r,
)
self.assertTrue("ga('create', 'UA-123456-7', 'auto', {});" in r, r)
self.assertTrue("ga('send', 'pageview');" in r, r)
@ -41,32 +55,41 @@ m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
def test_no_property_id(self):
self.assertRaises(AnalyticalException, GoogleAnalyticsJsNode)
@override_settings(GOOGLE_ANALYTICS_JS_PROPERTY_ID='wrong')
@override_settings(GOOGLE_ANALYTICS_JS_PROPERTY_ID="wrong")
def test_wrong_property_id(self):
self.assertRaises(AnalyticalException, GoogleAnalyticsJsNode)
@override_settings(GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_MULTIPLE_SUBDOMAINS,
GOOGLE_ANALYTICS_DOMAIN='example.com')
@override_settings(
GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_MULTIPLE_SUBDOMAINS,
GOOGLE_ANALYTICS_DOMAIN="example.com",
)
def test_track_multiple_subdomains(self):
r = GoogleAnalyticsJsNode().render(Context())
self.assertTrue(
"""ga('create', 'UA-123456-7', 'auto', {"legacyCookieDomain": "example.com"}""" in r, r)
"""ga('create', 'UA-123456-7', 'auto', {"legacyCookieDomain": "example.com"}"""
in r,
r,
)
@override_settings(GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_MULTIPLE_DOMAINS,
GOOGLE_ANALYTICS_DOMAIN='example.com')
@override_settings(
GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_MULTIPLE_DOMAINS,
GOOGLE_ANALYTICS_DOMAIN="example.com",
)
def test_track_multiple_domains(self):
r = GoogleAnalyticsJsNode().render(Context())
self.assertTrue("ga('create', 'UA-123456-7', 'auto', {" in r, r)
self.assertTrue('"legacyCookieDomain": "example.com"' in r, r)
self.assertTrue('"allowLinker\": true' in r, r)
self.assertTrue('"allowLinker": true' in r, r)
def test_custom_vars(self):
context = Context({
'google_analytics_var1': ('test1', 'foo'),
'google_analytics_var2': ('test2', 'bar'),
'google_analytics_var4': ('test4', 1),
'google_analytics_var5': ('test5', 2.2),
})
context = Context(
{
"google_analytics_var1": ("test1", "foo"),
"google_analytics_var2": ("test2", "bar"),
"google_analytics_var4": ("test4", 1),
"google_analytics_var5": ("test5", 2.2),
}
)
r = GoogleAnalyticsJsNode().render(context)
self.assertTrue("ga('set', 'test1', 'foo');" in r, r)
self.assertTrue("ga('set', 'test2', 'bar');" in r, r)
@ -76,19 +99,24 @@ m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
def test_display_advertising(self):
with override_settings(GOOGLE_ANALYTICS_DISPLAY_ADVERTISING=True):
r = GoogleAnalyticsJsNode().render(Context())
self.assertTrue("""ga('create', 'UA-123456-7', 'auto', {});
self.assertTrue(
"""ga('create', 'UA-123456-7', 'auto', {});
ga('require', 'displayfeatures');
ga('send', 'pageview');""" in r, r)
ga('send', 'pageview');"""
in r,
r,
)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
@override_settings(ANALYTICAL_INTERNAL_IPS=["1.1.1.1"])
def test_render_internal_ip(self):
req = HttpRequest()
req.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': req})
req.META["REMOTE_ADDR"] = "1.1.1.1"
context = Context({"request": req})
r = GoogleAnalyticsJsNode().render(context)
self.assertTrue(r.startswith(
'<!-- Google Analytics disabled on internal IP address'), r)
self.assertTrue(r.endswith('-->'), r)
self.assertTrue(
r.startswith("<!-- Google Analytics disabled on internal IP address"), r
)
self.assertTrue(r.endswith("-->"), r)
@override_settings(GOOGLE_ANALYTICS_ANONYMIZE_IP=True)
def test_anonymize_ip(self):
@ -103,12 +131,16 @@ ga('send', 'pageview');""" in r, r)
@override_settings(GOOGLE_ANALYTICS_SAMPLE_RATE=0.0)
def test_set_sample_rate_min(self):
r = GoogleAnalyticsJsNode().render(Context())
self.assertTrue("""ga('create', 'UA-123456-7', 'auto', {"sampleRate": 0});""" in r, r)
self.assertTrue(
"""ga('create', 'UA-123456-7', 'auto', {"sampleRate": 0});""" in r, r
)
@override_settings(GOOGLE_ANALYTICS_SAMPLE_RATE='100.00')
@override_settings(GOOGLE_ANALYTICS_SAMPLE_RATE="100.00")
def test_set_sample_rate_max(self):
r = GoogleAnalyticsJsNode().render(Context())
self.assertTrue("""ga('create', 'UA-123456-7', 'auto', {"sampleRate": 100});""" in r, r)
self.assertTrue(
"""ga('create', 'UA-123456-7', 'auto', {"sampleRate": 100});""" in r, r
)
@override_settings(GOOGLE_ANALYTICS_SAMPLE_RATE=-1)
def test_exception_whenset_sample_rate_too_small(self):
@ -124,13 +156,18 @@ ga('send', 'pageview');""" in r, r)
def test_set_site_speed_sample_rate_min(self):
r = GoogleAnalyticsJsNode().render(Context())
self.assertTrue(
"""ga('create', 'UA-123456-7', 'auto', {"siteSpeedSampleRate": 0});""" in r, r)
"""ga('create', 'UA-123456-7', 'auto', {"siteSpeedSampleRate": 0});""" in r,
r,
)
@override_settings(GOOGLE_ANALYTICS_SITE_SPEED_SAMPLE_RATE='100.00')
@override_settings(GOOGLE_ANALYTICS_SITE_SPEED_SAMPLE_RATE="100.00")
def test_set_site_speed_sample_rate_max(self):
r = GoogleAnalyticsJsNode().render(Context())
self.assertTrue(
"""ga('create', 'UA-123456-7', 'auto', {"siteSpeedSampleRate": 100});""" in r, r)
"""ga('create', 'UA-123456-7', 'auto', {"siteSpeedSampleRate": 100});"""
in r,
r,
)
@override_settings(GOOGLE_ANALYTICS_SITE_SPEED_SAMPLE_RATE=-1)
def test_exception_whenset_site_speed_sample_rate_too_small(self):
@ -145,13 +182,16 @@ ga('send', 'pageview');""" in r, r)
@override_settings(GOOGLE_ANALYTICS_COOKIE_EXPIRATION=0)
def test_set_cookie_expiration_min(self):
r = GoogleAnalyticsJsNode().render(Context())
self.assertTrue("""ga('create', 'UA-123456-7', 'auto', {"cookieExpires": 0});""" in r, r)
self.assertTrue(
"""ga('create', 'UA-123456-7', 'auto', {"cookieExpires": 0});""" in r, r
)
@override_settings(GOOGLE_ANALYTICS_COOKIE_EXPIRATION='10000')
@override_settings(GOOGLE_ANALYTICS_COOKIE_EXPIRATION="10000")
def test_set_cookie_expiration_as_string(self):
r = GoogleAnalyticsJsNode().render(Context())
self.assertTrue(
"""ga('create', 'UA-123456-7', 'auto', {"cookieExpires": 10000});""" in r, r)
"""ga('create', 'UA-123456-7', 'auto', {"cookieExpires": 10000});""" in r, r
)
@override_settings(GOOGLE_ANALYTICS_COOKIE_EXPIRATION=-1)
def test_exception_when_set_cookie_expiration_too_small(self):
@ -159,10 +199,12 @@ ga('send', 'pageview');""" in r, r)
self.assertRaises(AnalyticalException, GoogleAnalyticsJsNode().render, context)
@override_settings(GOOGLE_ANALYTICS_JS_PROPERTY_ID='UA-123456-7',
GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_MULTIPLE_DOMAINS,
GOOGLE_ANALYTICS_DOMAIN=None,
ANALYTICAL_DOMAIN=None)
@override_settings(
GOOGLE_ANALYTICS_JS_PROPERTY_ID="UA-123456-7",
GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_MULTIPLE_DOMAINS,
GOOGLE_ANALYTICS_DOMAIN=None,
ANALYTICAL_DOMAIN=None,
)
class NoDomainTestCase(TestCase):
def test_exception_without_domain(self):
context = Context()

View file

@ -2,24 +2,24 @@
Tests for the GoSquared template tags and filters.
"""
from django.contrib.auth.models import User, AnonymousUser
from django.contrib.auth.models import AnonymousUser, User
from django.http import HttpRequest
from django.template import Context
from django.test.utils import override_settings
from utils import TagTestCase
from analytical.templatetags.gosquared import GoSquaredNode
from utils import TagTestCase
from analytical.utils import AnalyticalException
@override_settings(GOSQUARED_SITE_TOKEN='ABC-123456-D')
@override_settings(GOSQUARED_SITE_TOKEN="ABC-123456-D")
class GoSquaredTagTestCase(TagTestCase):
"""
Tests for the ``gosquared`` template tag.
"""
def test_tag(self):
r = self.render_tag('gosquared', 'gosquared')
r = self.render_tag("gosquared", "gosquared")
self.assertTrue('GoSquared.acct = "ABC-123456-D";' in r, r)
def test_node(self):
@ -30,36 +30,45 @@ class GoSquaredTagTestCase(TagTestCase):
def test_no_token(self):
self.assertRaises(AnalyticalException, GoSquaredNode)
@override_settings(GOSQUARED_SITE_TOKEN='this is not a token')
@override_settings(GOSQUARED_SITE_TOKEN="this is not a token")
def test_wrong_token(self):
self.assertRaises(AnalyticalException, GoSquaredNode)
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_auto_identify(self):
r = GoSquaredNode().render(Context({
'user': User(username='test', first_name='Test', last_name='User'),
}))
r = GoSquaredNode().render(
Context(
{
"user": User(username="test", first_name="Test", last_name="User"),
}
)
)
self.assertTrue('GoSquared.UserName = "Test User";' in r, r)
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_manual_identify(self):
r = GoSquaredNode().render(Context({
'user': User(username='test', first_name='Test', last_name='User'),
'gosquared_identity': 'test_identity',
}))
r = GoSquaredNode().render(
Context(
{
"user": User(username="test", first_name="Test", last_name="User"),
"gosquared_identity": "test_identity",
}
)
)
self.assertTrue('GoSquared.UserName = "test_identity";' in r, r)
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify_anonymous_user(self):
r = GoSquaredNode().render(Context({'user': AnonymousUser()}))
self.assertFalse('GoSquared.UserName = ' in r, r)
r = GoSquaredNode().render(Context({"user": AnonymousUser()}))
self.assertFalse("GoSquared.UserName = " in r, r)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
@override_settings(ANALYTICAL_INTERNAL_IPS=["1.1.1.1"])
def test_render_internal_ip(self):
req = HttpRequest()
req.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': req})
req.META["REMOTE_ADDR"] = "1.1.1.1"
context = Context({"request": req})
r = GoSquaredNode().render(context)
self.assertTrue(r.startswith(
'<!-- GoSquared disabled on internal IP address'), r)
self.assertTrue(r.endswith('-->'), r)
self.assertTrue(
r.startswith("<!-- GoSquared disabled on internal IP address"), r
)
self.assertTrue(r.endswith("-->"), r)

View file

@ -4,13 +4,12 @@ Tests for the Hotjar template tags.
from django.http import HttpRequest
from django.template import Context, Template, TemplateSyntaxError
from django.test import override_settings
from utils import TagTestCase
from analytical.templatetags.analytical import _load_template_nodes
from analytical.templatetags.hotjar import HotjarNode
from utils import TagTestCase
from analytical.utils import AnalyticalException
expected_html = """\
<script>
(function(h,o,t,j,a,r){
@ -25,13 +24,13 @@ expected_html = """\
"""
@override_settings(HOTJAR_SITE_ID='123456789')
@override_settings(HOTJAR_SITE_ID="123456789")
class HotjarTagTestCase(TagTestCase):
maxDiff = None
def test_tag(self):
html = self.render_tag('hotjar', 'hotjar')
html = self.render_tag("hotjar", "hotjar")
self.assertEqual(expected_html, html)
def test_node(self):
@ -42,33 +41,38 @@ class HotjarTagTestCase(TagTestCase):
self.assertRaisesRegex(
TemplateSyntaxError,
r"^'hotjar' takes no arguments$",
lambda: (Template('{% load hotjar %}{% hotjar "arg" %}')
.render(Context({}))),
lambda: (
Template('{% load hotjar %}{% hotjar "arg" %}').render(Context({}))
),
)
@override_settings(HOTJAR_SITE_ID=None)
def test_no_id(self):
expected_pattern = r'^HOTJAR_SITE_ID setting is not set$'
expected_pattern = r"^HOTJAR_SITE_ID setting is not set$"
self.assertRaisesRegex(AnalyticalException, expected_pattern, HotjarNode)
@override_settings(HOTJAR_SITE_ID='invalid')
@override_settings(HOTJAR_SITE_ID="invalid")
def test_invalid_id(self):
expected_pattern = (
r"^HOTJAR_SITE_ID setting: must be \(a string containing\) a number: 'invalid'$")
r"^HOTJAR_SITE_ID setting: must be "
r"\(a string containing\) a number: 'invalid'$"
)
self.assertRaisesRegex(AnalyticalException, expected_pattern, HotjarNode)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
@override_settings(ANALYTICAL_INTERNAL_IPS=["1.1.1.1"])
def test_render_internal_ip(self):
request = HttpRequest()
request.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': request})
request.META["REMOTE_ADDR"] = "1.1.1.1"
context = Context({"request": request})
actual_html = HotjarNode().render(context)
disabled_html = '\n'.join([
'<!-- Hotjar disabled on internal IP address',
disabled_html = "\n".join(
[
"<!-- Hotjar disabled on internal IP address",
expected_html,
'-->',
])
"-->",
]
)
self.assertEqual(disabled_html, actual_html)
def test_contribute_to_analytical(self):
@ -76,9 +80,12 @@ class HotjarTagTestCase(TagTestCase):
`hotjar.contribute_to_analytical` registers the head and body nodes.
"""
template_nodes = _load_template_nodes()
self.assertEqual({
'head_top': [],
'head_bottom': [HotjarNode],
'body_top': [],
'body_bottom': [],
}, template_nodes)
self.assertEqual(
{
"head_top": [],
"head_bottom": [HotjarNode],
"body_top": [],
"body_bottom": [],
},
template_nodes,
)

View file

@ -5,41 +5,47 @@ Tests for the HubSpot template tags and filters.
from django.http import HttpRequest
from django.template import Context
from django.test.utils import override_settings
from utils import TagTestCase
from analytical.templatetags.hubspot import HubSpotNode
from utils import TagTestCase
from analytical.utils import AnalyticalException
@override_settings(HUBSPOT_PORTAL_ID='1234')
@override_settings(HUBSPOT_PORTAL_ID="1234")
class HubSpotTagTestCase(TagTestCase):
"""
Tests for the ``hubspot`` template tag.
"""
def test_tag(self):
r = self.render_tag('hubspot', 'hubspot')
self.assertTrue("n.id=i;n.src='//js.hs-analytics.net/analytics/'"
"+(Math.ceil(new Date()/r)*r)+'/1234.js';" in r, r)
r = self.render_tag("hubspot", "hubspot")
self.assertTrue(
"n.id=i;n.src='//js.hs-analytics.net/analytics/'"
"+(Math.ceil(new Date()/r)*r)+'/1234.js';" in r,
r,
)
def test_node(self):
r = HubSpotNode().render(Context())
self.assertTrue("n.id=i;n.src='//js.hs-analytics.net/analytics/'"
"+(Math.ceil(new Date()/r)*r)+'/1234.js';" in r, r)
self.assertTrue(
"n.id=i;n.src='//js.hs-analytics.net/analytics/'"
"+(Math.ceil(new Date()/r)*r)+'/1234.js';" in r,
r,
)
@override_settings(HUBSPOT_PORTAL_ID=None)
def test_no_portal_id(self):
self.assertRaises(AnalyticalException, HubSpotNode)
@override_settings(HUBSPOT_PORTAL_ID='wrong')
@override_settings(HUBSPOT_PORTAL_ID="wrong")
def test_wrong_portal_id(self):
self.assertRaises(AnalyticalException, HubSpotNode)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
@override_settings(ANALYTICAL_INTERNAL_IPS=["1.1.1.1"])
def test_render_internal_ip(self):
req = HttpRequest()
req.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': req})
req.META["REMOTE_ADDR"] = "1.1.1.1"
context = Context({"request": req})
r = HubSpotNode().render(context)
self.assertTrue(r.startswith('<!-- HubSpot disabled on internal IP address'), r)
self.assertTrue(r.endswith('-->'), r)
self.assertTrue(r.startswith("<!-- HubSpot disabled on internal IP address"), r)
self.assertTrue(r.endswith("-->"), r)

View file

@ -8,9 +8,9 @@ from django.contrib.auth.models import User
from django.http import HttpRequest
from django.template import Context
from django.test.utils import override_settings
from utils import TagTestCase
from analytical.templatetags.intercom import IntercomNode, intercom_user_hash
from utils import TagTestCase
from analytical.utils import AnalyticalException
@ -21,152 +21,201 @@ class IntercomTagTestCase(TagTestCase):
"""
def test_tag(self):
rendered_tag = self.render_tag('intercom', 'intercom')
self.assertTrue(rendered_tag.strip().startswith('<script id="IntercomSettingsScriptTag">'))
rendered_tag = self.render_tag("intercom", "intercom")
self.assertTrue(
rendered_tag.strip().startswith('<script id="IntercomSettingsScriptTag">')
)
def test_node(self):
now = datetime.datetime(2014, 4, 9, 15, 15, 0)
user = User.objects.create(
username='test',
first_name='Firstname',
last_name='Lastname',
username="test",
first_name="Firstname",
last_name="Lastname",
email="test@example.com",
date_joined=now,
)
rendered_tag = IntercomNode().render(Context({'user': user}))
rendered_tag = IntercomNode().render(Context({"user": user}))
# Because the json isn't predictably ordered, we can't just test the whole thing verbatim.
self.assertEqual("""
self.assertEqual(
"""
<script id="IntercomSettingsScriptTag">
window.intercomSettings = {"app_id": "abc123xyz", "created_at": 1397074500, "email": "test@example.com", "name": "Firstname Lastname", "user_id": %(user_id)s};
</script>
<script>(function(){var w=window;var ic=w.Intercom;if(typeof ic==="function"){ic('reattach_activator');ic('update',intercomSettings);}else{var d=document;var i=function(){i.c(arguments)};i.q=[];i.c=function(args){i.q.push(args)};w.Intercom=i;function l(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='https://static.intercomcdn.com/intercom.v1.js';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);}if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})()</script>
""" % {'user_id': user.pk}, rendered_tag) # noqa
""" # noqa
% {"user_id": user.pk},
rendered_tag,
)
@override_settings(INTERCOM_APP_ID=None)
def test_no_account_number(self):
self.assertRaises(AnalyticalException, IntercomNode)
@override_settings(INTERCOM_APP_ID='123abQ')
@override_settings(INTERCOM_APP_ID="123abQ")
def test_wrong_account_number(self):
self.assertRaises(AnalyticalException, IntercomNode)
def test_identify_name_email_and_created_at(self):
now = datetime.datetime(2014, 4, 9, 15, 15, 0)
user = User.objects.create(
username='test',
first_name='Firstname',
last_name='Lastname',
username="test",
first_name="Firstname",
last_name="Lastname",
email="test@example.com",
date_joined=now,
)
r = IntercomNode().render(Context({
'user': user,
}))
self.assertTrue('window.intercomSettings = {'
'"app_id": "abc123xyz", "created_at": 1397074500, '
'"email": "test@example.com", "name": "Firstname Lastname", '
'"user_id": %(user_id)s'
'};' % {'user_id': user.pk} in r, msg=r)
r = IntercomNode().render(
Context(
{
"user": user,
}
)
)
self.assertTrue(
"window.intercomSettings = {"
'"app_id": "abc123xyz", "created_at": 1397074500, '
'"email": "test@example.com", "name": "Firstname Lastname", '
'"user_id": %(user_id)s'
"};" % {"user_id": user.pk} in r,
msg=r,
)
def test_custom(self):
r = IntercomNode().render(Context({
'intercom_var1': 'val1',
'intercom_var2': 'val2'
}))
r = IntercomNode().render(
Context({"intercom_var1": "val1", "intercom_var2": "val2"})
)
self.assertTrue('var1": "val1", "var2": "val2"' in r)
def test_identify_name_and_email(self):
r = IntercomNode().render(Context({
'user': User(
username='test',
first_name='Firstname',
last_name='Lastname',
email="test@example.com"),
}))
self.assertTrue('"email": "test@example.com", "name": "Firstname Lastname"' in r)
r = IntercomNode().render(
Context(
{
"user": User(
username="test",
first_name="Firstname",
last_name="Lastname",
email="test@example.com",
),
}
)
)
self.assertTrue(
'"email": "test@example.com", "name": "Firstname Lastname"' in r
)
def test_identify_username_no_email(self):
r = IntercomNode().render(Context({'user': User(username='test')}))
r = IntercomNode().render(Context({"user": User(username="test")}))
self.assertTrue('"name": "test"' in r, r)
def test_no_identify_when_explicit_name(self):
r = IntercomNode().render(Context({
'intercom_name': 'explicit',
'user': User(username='implicit'),
}))
r = IntercomNode().render(
Context(
{
"intercom_name": "explicit",
"user": User(username="implicit"),
}
)
)
self.assertTrue('"name": "explicit"' in r, r)
def test_no_identify_when_explicit_email(self):
r = IntercomNode().render(Context({
'intercom_email': 'explicit',
'user': User(username='implicit'),
}))
r = IntercomNode().render(
Context(
{
"intercom_email": "explicit",
"user": User(username="implicit"),
}
)
)
self.assertTrue('"email": "explicit"' in r, r)
@override_settings(INTERCOM_HMAC_SECRET_KEY='secret')
@override_settings(INTERCOM_HMAC_SECRET_KEY="secret")
def test_user_hash__without_user_details(self):
"""
No `user_hash` without `user_id` or `email`.
"""
attrs = IntercomNode()._get_custom_attrs(Context())
self.assertEqual({
'created_at': None,
}, attrs)
self.assertEqual(
{
"created_at": None,
},
attrs,
)
@override_settings(INTERCOM_HMAC_SECRET_KEY='secret')
@override_settings(INTERCOM_HMAC_SECRET_KEY="secret")
def test_user_hash__with_user(self):
"""
'user_hash' of default `user_id`.
"""
user = User.objects.create(
email='test@example.com',
email="test@example.com",
) # type: User
attrs = IntercomNode()._get_custom_attrs(Context({'user': user}))
self.assertEqual({
'created_at': int(user.date_joined.timestamp()),
'email': 'test@example.com',
'name': '',
'user_hash': intercom_user_hash(str(user.pk)),
'user_id': user.pk,
}, attrs)
attrs = IntercomNode()._get_custom_attrs(Context({"user": user}))
self.assertEqual(
{
"created_at": int(user.date_joined.timestamp()),
"email": "test@example.com",
"name": "",
"user_hash": intercom_user_hash(str(user.pk)),
"user_id": user.pk,
},
attrs,
)
@override_settings(INTERCOM_HMAC_SECRET_KEY='secret')
@override_settings(INTERCOM_HMAC_SECRET_KEY="secret")
def test_user_hash__with_explicit_user_id(self):
"""
'user_hash' of context-provided `user_id`.
"""
attrs = IntercomNode()._get_custom_attrs(Context({
'intercom_email': 'test@example.com',
'intercom_user_id': '5',
}))
self.assertEqual({
'created_at': None,
'email': 'test@example.com',
# HMAC for user_id:
'user_hash': 'd3123a7052b42272d9b520235008c248a5aff3221cc0c530b754702ad91ab102',
'user_id': '5',
}, attrs)
attrs = IntercomNode()._get_custom_attrs(
Context(
{
"intercom_email": "test@example.com",
"intercom_user_id": "5",
}
)
)
self.assertEqual(
{
"created_at": None,
"email": "test@example.com",
# HMAC for user_id:
"user_hash": "d3123a7052b42272d9b520235008c248a5aff3221cc0c530b754702ad91ab102",
"user_id": "5",
},
attrs,
)
@override_settings(INTERCOM_HMAC_SECRET_KEY='secret')
@override_settings(INTERCOM_HMAC_SECRET_KEY="secret")
def test_user_hash__with_explicit_email(self):
"""
'user_hash' of context-provided `email`.
"""
attrs = IntercomNode()._get_custom_attrs(Context({
'intercom_email': 'test@example.com',
}))
self.assertEqual({
'created_at': None,
'email': 'test@example.com',
# HMAC for email:
'user_hash': '49e43229ee99dca2565241719b8341b04e71dd4de0628f991b5bea30a526e153',
}, attrs)
attrs = IntercomNode()._get_custom_attrs(
Context(
{
"intercom_email": "test@example.com",
}
)
)
self.assertEqual(
{
"created_at": None,
"email": "test@example.com",
# HMAC for email:
"user_hash": "49e43229ee99dca2565241719b8341b04e71dd4de0628f991b5bea30a526e153",
},
attrs,
)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
@override_settings(ANALYTICAL_INTERNAL_IPS=["1.1.1.1"])
def test_render_internal_ip(self):
req = HttpRequest()
req.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': req})
req.META["REMOTE_ADDR"] = "1.1.1.1"
context = Context({"request": req})
r = IntercomNode().render(context)
self.assertTrue(r.startswith('<!-- Intercom disabled on internal IP address'), r)
self.assertTrue(r.endswith('-->'), r)
self.assertTrue(
r.startswith("<!-- Intercom disabled on internal IP address"), r
)
self.assertTrue(r.endswith("-->"), r)

View file

@ -2,23 +2,23 @@
Tests for the KISSinsights template tags and filters.
"""
from django.contrib.auth.models import User, AnonymousUser
from django.contrib.auth.models import AnonymousUser, User
from django.template import Context
from django.test.utils import override_settings
from utils import TagTestCase
from analytical.templatetags.kiss_insights import KissInsightsNode
from utils import TagTestCase
from analytical.utils import AnalyticalException
@override_settings(KISS_INSIGHTS_ACCOUNT_NUMBER='12345', KISS_INSIGHTS_SITE_CODE='abc')
@override_settings(KISS_INSIGHTS_ACCOUNT_NUMBER="12345", KISS_INSIGHTS_SITE_CODE="abc")
class KissInsightsTagTestCase(TagTestCase):
"""
Tests for the ``kiss_insights`` template tag.
"""
def test_tag(self):
r = self.render_tag('kiss_insights', 'kiss_insights')
r = self.render_tag("kiss_insights", "kiss_insights")
self.assertTrue("//s3.amazonaws.com/ki.js/12345/abc.js" in r, r)
def test_node(self):
@ -33,24 +33,24 @@ class KissInsightsTagTestCase(TagTestCase):
def test_no_site_code(self):
self.assertRaises(AnalyticalException, KissInsightsNode)
@override_settings(KISS_INSIGHTS_ACCOUNT_NUMBER='abcde')
@override_settings(KISS_INSIGHTS_ACCOUNT_NUMBER="abcde")
def test_wrong_account_number(self):
self.assertRaises(AnalyticalException, KissInsightsNode)
@override_settings(KISS_INSIGHTS_SITE_CODE='abc def')
@override_settings(KISS_INSIGHTS_SITE_CODE="abc def")
def test_wrong_site_id(self):
self.assertRaises(AnalyticalException, KissInsightsNode)
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify(self):
r = KissInsightsNode().render(Context({'user': User(username='test')}))
r = KissInsightsNode().render(Context({"user": User(username="test")}))
self.assertTrue("_kiq.push(['identify', 'test']);" in r, r)
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify_anonymous_user(self):
r = KissInsightsNode().render(Context({'user': AnonymousUser()}))
r = KissInsightsNode().render(Context({"user": AnonymousUser()}))
self.assertFalse("_kiq.push(['identify', " in r, r)
def test_show_survey(self):
r = KissInsightsNode().render(Context({'kiss_insights_show_survey': 1234}))
r = KissInsightsNode().render(Context({"kiss_insights_show_survey": 1234}))
self.assertTrue("_kiq.push(['showSurvey', 1234]);" in r, r)

View file

@ -2,80 +2,106 @@
Tests for the KISSmetrics tags and filters.
"""
from django.contrib.auth.models import User, AnonymousUser
from django.contrib.auth.models import AnonymousUser, User
from django.http import HttpRequest
from django.template import Context
from django.test.utils import override_settings
from utils import TagTestCase
from analytical.templatetags.kiss_metrics import KissMetricsNode
from utils import TagTestCase
from analytical.utils import AnalyticalException
@override_settings(KISS_METRICS_API_KEY='0123456789abcdef0123456789abcdef01234567')
@override_settings(KISS_METRICS_API_KEY="0123456789abcdef0123456789abcdef01234567")
class KissMetricsTagTestCase(TagTestCase):
"""
Tests for the ``kiss_metrics`` template tag.
"""
def test_tag(self):
r = self.render_tag('kiss_metrics', 'kiss_metrics')
self.assertTrue("//doug1izaerwt3.cloudfront.net/"
"0123456789abcdef0123456789abcdef01234567.1.js" in r, r)
r = self.render_tag("kiss_metrics", "kiss_metrics")
self.assertTrue(
"//doug1izaerwt3.cloudfront.net/"
"0123456789abcdef0123456789abcdef01234567.1.js" in r,
r,
)
def test_node(self):
r = KissMetricsNode().render(Context())
self.assertTrue("//doug1izaerwt3.cloudfront.net/"
"0123456789abcdef0123456789abcdef01234567.1.js" in r, r)
self.assertTrue(
"//doug1izaerwt3.cloudfront.net/"
"0123456789abcdef0123456789abcdef01234567.1.js" in r,
r,
)
@override_settings(KISS_METRICS_API_KEY=None)
def test_no_api_key(self):
self.assertRaises(AnalyticalException, KissMetricsNode)
@override_settings(KISS_METRICS_API_KEY='0123456789abcdef0123456789abcdef0123456')
@override_settings(KISS_METRICS_API_KEY="0123456789abcdef0123456789abcdef0123456")
def test_api_key_too_short(self):
self.assertRaises(AnalyticalException, KissMetricsNode)
@override_settings(KISS_METRICS_API_KEY='0123456789abcdef0123456789abcdef012345678')
@override_settings(KISS_METRICS_API_KEY="0123456789abcdef0123456789abcdef012345678")
def test_api_key_too_long(self):
self.assertRaises(AnalyticalException, KissMetricsNode)
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify(self):
r = KissMetricsNode().render(Context({'user': User(username='test')}))
r = KissMetricsNode().render(Context({"user": User(username="test")}))
self.assertTrue("_kmq.push(['identify', 'test']);" in r, r)
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify_anonymous_user(self):
r = KissMetricsNode().render(Context({'user': AnonymousUser()}))
r = KissMetricsNode().render(Context({"user": AnonymousUser()}))
self.assertFalse("_kmq.push(['identify', " in r, r)
def test_event(self):
r = KissMetricsNode().render(Context({
'kiss_metrics_event': ('test_event', {'prop1': 'val1', 'prop2': 'val2'}),
}))
self.assertTrue("_kmq.push(['record', 'test_event', "
'{"prop1": "val1", "prop2": "val2"}]);' in r, r)
r = KissMetricsNode().render(
Context(
{
"kiss_metrics_event": (
"test_event",
{"prop1": "val1", "prop2": "val2"},
),
}
)
)
self.assertTrue(
"_kmq.push(['record', 'test_event', "
'{"prop1": "val1", "prop2": "val2"}]);' in r,
r,
)
def test_property(self):
r = KissMetricsNode().render(Context({
'kiss_metrics_properties': {'prop1': 'val1', 'prop2': 'val2'},
}))
self.assertTrue("_kmq.push([\'set\', "
'{"prop1": "val1", "prop2": "val2"}]);' in r, r)
r = KissMetricsNode().render(
Context(
{
"kiss_metrics_properties": {"prop1": "val1", "prop2": "val2"},
}
)
)
self.assertTrue(
"_kmq.push(['set', " '{"prop1": "val1", "prop2": "val2"}]);' in r, r
)
def test_alias(self):
r = KissMetricsNode().render(Context({
'kiss_metrics_alias': {'test': 'test_alias'},
}))
r = KissMetricsNode().render(
Context(
{
"kiss_metrics_alias": {"test": "test_alias"},
}
)
)
self.assertTrue("_kmq.push(['alias', 'test', 'test_alias']);" in r, r)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
@override_settings(ANALYTICAL_INTERNAL_IPS=["1.1.1.1"])
def test_render_internal_ip(self):
req = HttpRequest()
req.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': req})
req.META["REMOTE_ADDR"] = "1.1.1.1"
context = Context({"request": req})
r = KissMetricsNode().render(context)
self.assertTrue(r.startswith(
'<!-- KISSmetrics disabled on internal IP address'), r)
self.assertTrue(r.endswith('-->'), r)
self.assertTrue(
r.startswith("<!-- KISSmetrics disabled on internal IP address"), r
)
self.assertTrue(r.endswith("-->"), r)

View file

@ -4,13 +4,12 @@ Tests for the Lucky Orange template tags.
from django.http import HttpRequest
from django.template import Context, Template, TemplateSyntaxError
from django.test import override_settings
from utils import TagTestCase
from analytical.templatetags.analytical import _load_template_nodes
from analytical.templatetags.luckyorange import LuckyOrangeNode
from utils import TagTestCase
from analytical.utils import AnalyticalException
expected_html = """\
<script type='text/javascript'>
window.__lo_site_id = 123456;
@ -23,13 +22,13 @@ window.__lo_site_id = 123456;
"""
@override_settings(LUCKYORANGE_SITE_ID='123456')
@override_settings(LUCKYORANGE_SITE_ID="123456")
class LuckyOrangeTagTestCase(TagTestCase):
maxDiff = None
def test_tag(self):
html = self.render_tag('luckyorange', 'luckyorange')
html = self.render_tag("luckyorange", "luckyorange")
self.assertEqual(expected_html, html)
def test_node(self):
@ -40,33 +39,40 @@ class LuckyOrangeTagTestCase(TagTestCase):
self.assertRaisesRegex(
TemplateSyntaxError,
r"^'luckyorange' takes no arguments$",
lambda: (Template('{% load luckyorange %}{% luckyorange "arg" %}')
.render(Context({}))),
lambda: (
Template('{% load luckyorange %}{% luckyorange "arg" %}').render(
Context({})
)
),
)
@override_settings(LUCKYORANGE_SITE_ID=None)
def test_no_id(self):
expected_pattern = r'^LUCKYORANGE_SITE_ID setting is not set$'
expected_pattern = r"^LUCKYORANGE_SITE_ID setting is not set$"
self.assertRaisesRegex(AnalyticalException, expected_pattern, LuckyOrangeNode)
@override_settings(LUCKYORANGE_SITE_ID='invalid')
@override_settings(LUCKYORANGE_SITE_ID="invalid")
def test_invalid_id(self):
expected_pattern = (
r"^LUCKYORANGE_SITE_ID setting: must be \(a string containing\) a number: 'invalid'$")
r"^LUCKYORANGE_SITE_ID setting: must be "
r"\(a string containing\) a number: 'invalid'$"
)
self.assertRaisesRegex(AnalyticalException, expected_pattern, LuckyOrangeNode)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
@override_settings(ANALYTICAL_INTERNAL_IPS=["1.1.1.1"])
def test_render_internal_ip(self):
request = HttpRequest()
request.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': request})
request.META["REMOTE_ADDR"] = "1.1.1.1"
context = Context({"request": request})
actual_html = LuckyOrangeNode().render(context)
disabled_html = '\n'.join([
'<!-- Lucky Orange disabled on internal IP address',
disabled_html = "\n".join(
[
"<!-- Lucky Orange disabled on internal IP address",
expected_html,
'-->',
])
"-->",
]
)
self.assertEqual(disabled_html, actual_html)
def test_contribute_to_analytical(self):
@ -74,9 +80,12 @@ class LuckyOrangeTagTestCase(TagTestCase):
`luckyorange.contribute_to_analytical` registers the head and body nodes.
"""
template_nodes = _load_template_nodes()
self.assertEqual({
'head_top': [],
'head_bottom': [LuckyOrangeNode],
'body_top': [],
'body_bottom': [],
}, template_nodes)
self.assertEqual(
{
"head_top": [],
"head_bottom": [LuckyOrangeNode],
"body_top": [],
"body_bottom": [],
},
template_nodes,
)

View file

@ -6,48 +6,45 @@ from django.contrib.auth.models import User
from django.http import HttpRequest
from django.template import Context
from django.test.utils import override_settings
from utils import TagTestCase
from analytical.templatetags.matomo import MatomoNode
from utils import TagTestCase
from analytical.utils import AnalyticalException
@override_settings(MATOMO_DOMAIN_PATH='example.com', MATOMO_SITE_ID='345')
@override_settings(MATOMO_DOMAIN_PATH="example.com", MATOMO_SITE_ID="345")
class MatomoTagTestCase(TagTestCase):
"""
Tests for the ``matomo`` template tag.
"""
def test_tag(self):
r = self.render_tag('matomo', 'matomo')
r = self.render_tag("matomo", "matomo")
self.assertTrue('"//example.com/"' in r, r)
self.assertTrue("_paq.push(['setSiteId', 345]);" in r, r)
self.assertTrue('img src="//example.com/piwik.php?idsite=345"'
in r, r)
self.assertTrue('img src="//example.com/piwik.php?idsite=345"' in r, r)
def test_node(self):
r = MatomoNode().render(Context({}))
self.assertTrue('"//example.com/";' in r, r)
self.assertTrue("_paq.push(['setSiteId', 345]);" in r, r)
self.assertTrue('img src="//example.com/piwik.php?idsite=345"'
in r, r)
self.assertTrue('img src="//example.com/piwik.php?idsite=345"' in r, r)
@override_settings(MATOMO_DOMAIN_PATH='example.com/matomo',
MATOMO_SITE_ID='345')
@override_settings(MATOMO_DOMAIN_PATH="example.com/matomo", MATOMO_SITE_ID="345")
def test_domain_path_valid(self):
r = self.render_tag('matomo', 'matomo')
r = self.render_tag("matomo", "matomo")
self.assertTrue('"//example.com/matomo/"' in r, r)
@override_settings(MATOMO_DOMAIN_PATH='example.com:1234',
MATOMO_SITE_ID='345')
@override_settings(MATOMO_DOMAIN_PATH="example.com:1234", MATOMO_SITE_ID="345")
def test_domain_port_valid(self):
r = self.render_tag('matomo', 'matomo')
r = self.render_tag("matomo", "matomo")
self.assertTrue('"//example.com:1234/";' in r, r)
@override_settings(MATOMO_DOMAIN_PATH='example.com:1234/matomo',
MATOMO_SITE_ID='345')
@override_settings(
MATOMO_DOMAIN_PATH="example.com:1234/matomo", MATOMO_SITE_ID="345"
)
def test_domain_port_path_valid(self):
r = self.render_tag('matomo', 'matomo')
r = self.render_tag("matomo", "matomo")
self.assertTrue('"//example.com:1234/matomo/"' in r, r)
@override_settings(MATOMO_DOMAIN_PATH=None)
@ -58,91 +55,98 @@ class MatomoTagTestCase(TagTestCase):
def test_no_siteid(self):
self.assertRaises(AnalyticalException, MatomoNode)
@override_settings(MATOMO_SITE_ID='x')
@override_settings(MATOMO_SITE_ID="x")
def test_siteid_not_a_number(self):
self.assertRaises(AnalyticalException, MatomoNode)
@override_settings(MATOMO_DOMAIN_PATH='http://www.example.com')
@override_settings(MATOMO_DOMAIN_PATH="http://www.example.com")
def test_domain_protocol_invalid(self):
self.assertRaises(AnalyticalException, MatomoNode)
@override_settings(MATOMO_DOMAIN_PATH='example.com/')
@override_settings(MATOMO_DOMAIN_PATH="example.com/")
def test_domain_slash_invalid(self):
self.assertRaises(AnalyticalException, MatomoNode)
@override_settings(MATOMO_DOMAIN_PATH='example.com:123:456')
@override_settings(MATOMO_DOMAIN_PATH="example.com:123:456")
def test_domain_multi_port(self):
self.assertRaises(AnalyticalException, MatomoNode)
@override_settings(MATOMO_DOMAIN_PATH='example.com:')
@override_settings(MATOMO_DOMAIN_PATH="example.com:")
def test_domain_incomplete_port(self):
self.assertRaises(AnalyticalException, MatomoNode)
@override_settings(MATOMO_DOMAIN_PATH='example.com:/matomo')
@override_settings(MATOMO_DOMAIN_PATH="example.com:/matomo")
def test_domain_uri_incomplete_port(self):
self.assertRaises(AnalyticalException, MatomoNode)
@override_settings(MATOMO_DOMAIN_PATH='example.com:12df')
@override_settings(MATOMO_DOMAIN_PATH="example.com:12df")
def test_domain_port_invalid(self):
self.assertRaises(AnalyticalException, MatomoNode)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
@override_settings(ANALYTICAL_INTERNAL_IPS=["1.1.1.1"])
def test_render_internal_ip(self):
req = HttpRequest()
req.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': req})
req.META["REMOTE_ADDR"] = "1.1.1.1"
context = Context({"request": req})
r = MatomoNode().render(context)
self.assertTrue(r.startswith(
'<!-- Matomo disabled on internal IP address'), r)
self.assertTrue(r.endswith('-->'), r)
self.assertTrue(r.startswith("<!-- Matomo disabled on internal IP address"), r)
self.assertTrue(r.endswith("-->"), r)
def test_uservars(self):
context = Context({'matomo_vars': [(1, 'foo', 'foo_val'),
(2, 'bar', 'bar_val', 'page'),
(3, 'spam', 'spam_val', 'visit')]})
context = Context(
{
"matomo_vars": [
(1, "foo", "foo_val"),
(2, "bar", "bar_val", "page"),
(3, "spam", "spam_val", "visit"),
]
}
)
r = MatomoNode().render(context)
msg = 'Incorrect Matomo custom variable rendering. Expected:\n%s\nIn:\n%s'
for var_code in ['_paq.push(["setCustomVariable", 1, "foo", "foo_val", "page"]);',
'_paq.push(["setCustomVariable", 2, "bar", "bar_val", "page"]);',
'_paq.push(["setCustomVariable", 3, "spam", "spam_val", "visit"]);']:
msg = "Incorrect Matomo custom variable rendering. Expected:\n%s\nIn:\n%s"
for var_code in [
'_paq.push(["setCustomVariable", 1, "foo", "foo_val", "page"]);',
'_paq.push(["setCustomVariable", 2, "bar", "bar_val", "page"]);',
'_paq.push(["setCustomVariable", 3, "spam", "spam_val", "visit"]);',
]:
self.assertIn(var_code, r, msg % (var_code, r))
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_default_usertrack(self):
context = Context({
'user': User(username='BDFL', first_name='Guido', last_name='van Rossum')
})
context = Context(
{"user": User(username="BDFL", first_name="Guido", last_name="van Rossum")}
)
r = MatomoNode().render(context)
msg = 'Incorrect Matomo user tracking rendering.\nNot found:\n%s\nIn:\n%s'
msg = "Incorrect Matomo user tracking rendering.\nNot found:\n%s\nIn:\n%s"
var_code = '_paq.push(["setUserId", "BDFL"]);'
self.assertIn(var_code, r, msg % (var_code, r))
def test_matomo_usertrack(self):
context = Context({
'matomo_identity': 'BDFL'
})
context = Context({"matomo_identity": "BDFL"})
r = MatomoNode().render(context)
msg = 'Incorrect Matomo user tracking rendering.\nNot found:\n%s\nIn:\n%s'
msg = "Incorrect Matomo user tracking rendering.\nNot found:\n%s\nIn:\n%s"
var_code = '_paq.push(["setUserId", "BDFL"]);'
self.assertIn(var_code, r, msg % (var_code, r))
def test_analytical_usertrack(self):
context = Context({
'analytical_identity': 'BDFL'
})
context = Context({"analytical_identity": "BDFL"})
r = MatomoNode().render(context)
msg = 'Incorrect Matomo user tracking rendering.\nNot found:\n%s\nIn:\n%s'
msg = "Incorrect Matomo user tracking rendering.\nNot found:\n%s\nIn:\n%s"
var_code = '_paq.push(["setUserId", "BDFL"]);'
self.assertIn(var_code, r, msg % (var_code, r))
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_disable_usertrack(self):
context = Context({
'user': User(username='BDFL', first_name='Guido', last_name='van Rossum'),
'matomo_identity': None
})
context = Context(
{
"user": User(
username="BDFL", first_name="Guido", last_name="van Rossum"
),
"matomo_identity": None,
}
)
r = MatomoNode().render(context)
msg = 'Incorrect Matomo user tracking rendering.\nFound:\n%s\nIn:\n%s'
msg = "Incorrect Matomo user tracking rendering.\nFound:\n%s\nIn:\n%s"
var_code = '_paq.push(["setUserId", "BDFL"]);'
self.assertNotIn(var_code, r, msg % (var_code, r))

View file

@ -2,24 +2,24 @@
Tests for the Mixpanel tags and filters.
"""
from django.contrib.auth.models import User, AnonymousUser
from django.contrib.auth.models import AnonymousUser, User
from django.http import HttpRequest
from django.template import Context
from django.test.utils import override_settings
from utils import TagTestCase
from analytical.templatetags.mixpanel import MixpanelNode
from utils import TagTestCase
from analytical.utils import AnalyticalException
@override_settings(MIXPANEL_API_TOKEN='0123456789abcdef0123456789abcdef')
@override_settings(MIXPANEL_API_TOKEN="0123456789abcdef0123456789abcdef")
class MixpanelTagTestCase(TagTestCase):
"""
Tests for the ``mixpanel`` template tag.
"""
def test_tag(self):
r = self.render_tag('mixpanel', 'mixpanel')
r = self.render_tag("mixpanel", "mixpanel")
self.assertIn("mixpanel.init('0123456789abcdef0123456789abcdef');", r)
def test_node(self):
@ -30,37 +30,47 @@ class MixpanelTagTestCase(TagTestCase):
def test_no_token(self):
self.assertRaises(AnalyticalException, MixpanelNode)
@override_settings(MIXPANEL_API_TOKEN='0123456789abcdef0123456789abcdef0')
@override_settings(MIXPANEL_API_TOKEN="0123456789abcdef0123456789abcdef0")
def test_token_too_long(self):
self.assertRaises(AnalyticalException, MixpanelNode)
@override_settings(MIXPANEL_API_TOKEN='0123456789abcdef0123456789abcde')
@override_settings(MIXPANEL_API_TOKEN="0123456789abcdef0123456789abcde")
def test_token_too_short(self):
self.assertRaises(AnalyticalException, MixpanelNode)
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify(self):
r = MixpanelNode().render(Context({'user': User(username='test')}))
r = MixpanelNode().render(Context({"user": User(username="test")}))
self.assertIn("mixpanel.identify('test');", r)
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify_anonymous_user(self):
r = MixpanelNode().render(Context({'user': AnonymousUser()}))
r = MixpanelNode().render(Context({"user": AnonymousUser()}))
self.assertFalse("mixpanel.register_once({distinct_id:" in r, r)
def test_event(self):
r = MixpanelNode().render(Context({
'mixpanel_event': ('test_event', {'prop1': 'val1', 'prop2': 'val2'}),
}))
self.assertTrue("mixpanel.track('test_event', "
'{"prop1": "val1", "prop2": "val2"});' in r, r)
r = MixpanelNode().render(
Context(
{
"mixpanel_event": (
"test_event",
{"prop1": "val1", "prop2": "val2"},
),
}
)
)
self.assertTrue(
"mixpanel.track('test_event', " '{"prop1": "val1", "prop2": "val2"});' in r,
r,
)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
@override_settings(ANALYTICAL_INTERNAL_IPS=["1.1.1.1"])
def test_render_internal_ip(self):
req = HttpRequest()
req.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': req})
req.META["REMOTE_ADDR"] = "1.1.1.1"
context = Context({"request": req})
r = MixpanelNode().render(context)
self.assertTrue(r.startswith(
'<!-- Mixpanel disabled on internal IP address'), r)
self.assertTrue(r.endswith('-->'), r)
self.assertTrue(
r.startswith("<!-- Mixpanel disabled on internal IP address"), r
)
self.assertTrue(r.endswith("-->"), r)

View file

@ -2,23 +2,23 @@
Tests for the Olark template tags and filters.
"""
from django.contrib.auth.models import User, AnonymousUser
from django.contrib.auth.models import AnonymousUser, User
from django.template import Context
from django.test.utils import override_settings
from utils import TagTestCase
from analytical.templatetags.olark import OlarkNode
from utils import TagTestCase
from analytical.utils import AnalyticalException
@override_settings(OLARK_SITE_ID='1234-567-89-0123')
@override_settings(OLARK_SITE_ID="1234-567-89-0123")
class OlarkTestCase(TagTestCase):
"""
Tests for the ``olark`` template tag.
"""
def test_tag(self):
r = self.render_tag('olark', 'olark')
r = self.render_tag("olark", "olark")
self.assertTrue("olark.identify('1234-567-89-0123');" in r, r)
def test_node(self):
@ -29,39 +29,55 @@ class OlarkTestCase(TagTestCase):
def test_no_site_id(self):
self.assertRaises(AnalyticalException, OlarkNode)
@override_settings(OLARK_SITE_ID='1234-567-8901234')
@override_settings(OLARK_SITE_ID="1234-567-8901234")
def test_wrong_site_id(self):
self.assertRaises(AnalyticalException, OlarkNode)
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify(self):
r = OlarkNode().render(Context({
'user': User(username='test', first_name='Test', last_name='User'),
}))
self.assertTrue("olark('api.chat.updateVisitorNickname', "
"{snippet: 'Test User (test)'});" in r, r)
r = OlarkNode().render(
Context(
{
"user": User(username="test", first_name="Test", last_name="User"),
}
)
)
self.assertTrue(
"olark('api.chat.updateVisitorNickname', "
"{snippet: 'Test User (test)'});" in r,
r,
)
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify_anonymous_user(self):
r = OlarkNode().render(Context({'user': AnonymousUser()}))
r = OlarkNode().render(Context({"user": AnonymousUser()}))
self.assertFalse("olark('api.chat.updateVisitorNickname', " in r, r)
def test_nickname(self):
r = OlarkNode().render(Context({'olark_nickname': 'testnick'}))
self.assertTrue("olark('api.chat.updateVisitorNickname', "
"{snippet: 'testnick'});" in r, r)
r = OlarkNode().render(Context({"olark_nickname": "testnick"}))
self.assertTrue(
"olark('api.chat.updateVisitorNickname', " "{snippet: 'testnick'});" in r, r
)
def test_status_string(self):
r = OlarkNode().render(Context({'olark_status': 'teststatus'}))
self.assertTrue("olark('api.chat.updateVisitorStatus', "
'{snippet: "teststatus"});' in r, r)
r = OlarkNode().render(Context({"olark_status": "teststatus"}))
self.assertTrue(
"olark('api.chat.updateVisitorStatus', " '{snippet: "teststatus"});' in r, r
)
def test_status_string_list(self):
r = OlarkNode().render(Context({
'olark_status': ['teststatus1', 'teststatus2'],
}))
self.assertTrue("olark('api.chat.updateVisitorStatus', "
'{snippet: ["teststatus1", "teststatus2"]});' in r, r)
r = OlarkNode().render(
Context(
{
"olark_status": ["teststatus1", "teststatus2"],
}
)
)
self.assertTrue(
"olark('api.chat.updateVisitorStatus', "
'{snippet: ["teststatus1", "teststatus2"]});' in r,
r,
)
def test_messages(self):
messages = [
@ -87,7 +103,7 @@ class OlarkTestCase(TagTestCase):
"introduction_messages",
"introduction_submit_button_text",
]
vars = {'olark_%s' % m: m for m in messages}
vars = {"olark_%s" % m: m for m in messages}
r = OlarkNode().render(Context(vars))
for m in messages:
self.assertTrue("olark.configure('locale.%s', \"%s\");" % (m, m) in r, r)

View file

@ -5,13 +5,13 @@ Tests for the Optimizely template tags and filters.
from django.http import HttpRequest
from django.template import Context
from django.test.utils import override_settings
from utils import TagTestCase
from analytical.templatetags.optimizely import OptimizelyNode
from utils import TagTestCase
from analytical.utils import AnalyticalException
@override_settings(OPTIMIZELY_ACCOUNT_NUMBER='1234567')
@override_settings(OPTIMIZELY_ACCOUNT_NUMBER="1234567")
class OptimizelyTagTestCase(TagTestCase):
"""
Tests for the ``optimizely`` template tag.
@ -19,28 +19,31 @@ class OptimizelyTagTestCase(TagTestCase):
def test_tag(self):
self.assertEqual(
'<script src="//cdn.optimizely.com/js/1234567.js"></script>',
self.render_tag('optimizely', 'optimizely'))
'<script src="//cdn.optimizely.com/js/1234567.js"></script>',
self.render_tag("optimizely", "optimizely"),
)
def test_node(self):
self.assertEqual(
'<script src="//cdn.optimizely.com/js/1234567.js"></script>',
OptimizelyNode().render(Context()))
'<script src="//cdn.optimizely.com/js/1234567.js"></script>',
OptimizelyNode().render(Context()),
)
@override_settings(OPTIMIZELY_ACCOUNT_NUMBER=None)
def test_no_account_number(self):
self.assertRaises(AnalyticalException, OptimizelyNode)
@override_settings(OPTIMIZELY_ACCOUNT_NUMBER='123abc')
@override_settings(OPTIMIZELY_ACCOUNT_NUMBER="123abc")
def test_wrong_account_number(self):
self.assertRaises(AnalyticalException, OptimizelyNode)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
@override_settings(ANALYTICAL_INTERNAL_IPS=["1.1.1.1"])
def test_render_internal_ip(self):
req = HttpRequest()
req.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': req})
req.META["REMOTE_ADDR"] = "1.1.1.1"
context = Context({"request": req})
r = OptimizelyNode().render(context)
self.assertTrue(r.startswith(
'<!-- Optimizely disabled on internal IP address'), r)
self.assertTrue(r.endswith('-->'), r)
self.assertTrue(
r.startswith("<!-- Optimizely disabled on internal IP address"), r
)
self.assertTrue(r.endswith("-->"), r)

View file

@ -2,56 +2,57 @@
Tests for the Performable template tags and filters.
"""
from django.contrib.auth.models import User, AnonymousUser
from django.contrib.auth.models import AnonymousUser, User
from django.http import HttpRequest
from django.template import Context
from django.test.utils import override_settings
from utils import TagTestCase
from analytical.templatetags.performable import PerformableNode
from utils import TagTestCase
from analytical.utils import AnalyticalException
@override_settings(PERFORMABLE_API_KEY='123ABC')
@override_settings(PERFORMABLE_API_KEY="123ABC")
class PerformableTagTestCase(TagTestCase):
"""
Tests for the ``performable`` template tag.
"""
def test_tag(self):
r = self.render_tag('performable', 'performable')
self.assertTrue('/performable/pax/123ABC.js' in r, r)
r = self.render_tag("performable", "performable")
self.assertTrue("/performable/pax/123ABC.js" in r, r)
def test_node(self):
r = PerformableNode().render(Context())
self.assertTrue('/performable/pax/123ABC.js' in r, r)
self.assertTrue("/performable/pax/123ABC.js" in r, r)
@override_settings(PERFORMABLE_API_KEY=None)
def test_no_api_key(self):
self.assertRaises(AnalyticalException, PerformableNode)
@override_settings(PERFORMABLE_API_KEY='123 ABC')
@override_settings(PERFORMABLE_API_KEY="123 ABC")
def test_wrong_account_number(self):
self.assertRaises(AnalyticalException, PerformableNode)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
@override_settings(ANALYTICAL_INTERNAL_IPS=["1.1.1.1"])
def test_render_internal_ip(self):
req = HttpRequest()
req.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': req})
req.META["REMOTE_ADDR"] = "1.1.1.1"
context = Context({"request": req})
r = PerformableNode().render(context)
self.assertTrue(r.startswith(
'<!-- Performable disabled on internal IP address'), r)
self.assertTrue(r.endswith('-->'), r)
self.assertTrue(
r.startswith("<!-- Performable disabled on internal IP address"), r
)
self.assertTrue(r.endswith("-->"), r)
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify(self):
r = PerformableNode().render(Context({'user': User(username='test')}))
r = PerformableNode().render(Context({"user": User(username="test")}))
self.assertTrue('_paq.push(["identify", {identity: "test"}]);' in r, r)
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify_anonymous_user(self):
r = PerformableNode().render(Context({'user': AnonymousUser()}))
r = PerformableNode().render(Context({"user": AnonymousUser()}))
self.assertFalse('_paq.push(["identify", ' in r, r)
@ -61,11 +62,9 @@ class PerformableEmbedTagTestCase(TagTestCase):
"""
def test_tag(self):
domain = 'example.com'
page = 'test'
domain = "example.com"
page = "test"
tag = self.render_tag(
'performable', 'performable_embed "%s" "%s"' % (domain, page)
)
self.assertIn(
"$f.initialize({'host': 'example.com', 'page': 'test'});", tag
"performable", 'performable_embed "%s" "%s"' % (domain, page)
)
self.assertIn("$f.initialize({'host': 'example.com', 'page': 'test'});", tag)

View file

@ -6,48 +6,43 @@ from django.contrib.auth.models import User
from django.http import HttpRequest
from django.template import Context
from django.test.utils import override_settings
from utils import TagTestCase
from analytical.templatetags.piwik import PiwikNode
from utils import TagTestCase
from analytical.utils import AnalyticalException
@override_settings(PIWIK_DOMAIN_PATH='example.com', PIWIK_SITE_ID='345')
@override_settings(PIWIK_DOMAIN_PATH="example.com", PIWIK_SITE_ID="345")
class PiwikTagTestCase(TagTestCase):
"""
Tests for the ``piwik`` template tag.
"""
def test_tag(self):
r = self.render_tag('piwik', 'piwik')
r = self.render_tag("piwik", "piwik")
self.assertTrue('"//example.com/"' in r, r)
self.assertTrue("_paq.push(['setSiteId', 345]);" in r, r)
self.assertTrue('img src="//example.com/piwik.php?idsite=345"'
in r, r)
self.assertTrue('img src="//example.com/piwik.php?idsite=345"' in r, r)
def test_node(self):
r = PiwikNode().render(Context({}))
self.assertTrue('"//example.com/";' in r, r)
self.assertTrue("_paq.push(['setSiteId', 345]);" in r, r)
self.assertTrue('img src="//example.com/piwik.php?idsite=345"'
in r, r)
self.assertTrue('img src="//example.com/piwik.php?idsite=345"' in r, r)
@override_settings(PIWIK_DOMAIN_PATH='example.com/piwik',
PIWIK_SITE_ID='345')
@override_settings(PIWIK_DOMAIN_PATH="example.com/piwik", PIWIK_SITE_ID="345")
def test_domain_path_valid(self):
r = self.render_tag('piwik', 'piwik')
r = self.render_tag("piwik", "piwik")
self.assertTrue('"//example.com/piwik/"' in r, r)
@override_settings(PIWIK_DOMAIN_PATH='example.com:1234',
PIWIK_SITE_ID='345')
@override_settings(PIWIK_DOMAIN_PATH="example.com:1234", PIWIK_SITE_ID="345")
def test_domain_port_valid(self):
r = self.render_tag('piwik', 'piwik')
r = self.render_tag("piwik", "piwik")
self.assertTrue('"//example.com:1234/";' in r, r)
@override_settings(PIWIK_DOMAIN_PATH='example.com:1234/piwik',
PIWIK_SITE_ID='345')
@override_settings(PIWIK_DOMAIN_PATH="example.com:1234/piwik", PIWIK_SITE_ID="345")
def test_domain_port_path_valid(self):
r = self.render_tag('piwik', 'piwik')
r = self.render_tag("piwik", "piwik")
self.assertTrue('"//example.com:1234/piwik/"' in r, r)
@override_settings(PIWIK_DOMAIN_PATH=None)
@ -58,91 +53,98 @@ class PiwikTagTestCase(TagTestCase):
def test_no_siteid(self):
self.assertRaises(AnalyticalException, PiwikNode)
@override_settings(PIWIK_SITE_ID='x')
@override_settings(PIWIK_SITE_ID="x")
def test_siteid_not_a_number(self):
self.assertRaises(AnalyticalException, PiwikNode)
@override_settings(PIWIK_DOMAIN_PATH='http://www.example.com')
@override_settings(PIWIK_DOMAIN_PATH="http://www.example.com")
def test_domain_protocol_invalid(self):
self.assertRaises(AnalyticalException, PiwikNode)
@override_settings(PIWIK_DOMAIN_PATH='example.com/')
@override_settings(PIWIK_DOMAIN_PATH="example.com/")
def test_domain_slash_invalid(self):
self.assertRaises(AnalyticalException, PiwikNode)
@override_settings(PIWIK_DOMAIN_PATH='example.com:123:456')
@override_settings(PIWIK_DOMAIN_PATH="example.com:123:456")
def test_domain_multi_port(self):
self.assertRaises(AnalyticalException, PiwikNode)
@override_settings(PIWIK_DOMAIN_PATH='example.com:')
@override_settings(PIWIK_DOMAIN_PATH="example.com:")
def test_domain_incomplete_port(self):
self.assertRaises(AnalyticalException, PiwikNode)
@override_settings(PIWIK_DOMAIN_PATH='example.com:/piwik')
@override_settings(PIWIK_DOMAIN_PATH="example.com:/piwik")
def test_domain_uri_incomplete_port(self):
self.assertRaises(AnalyticalException, PiwikNode)
@override_settings(PIWIK_DOMAIN_PATH='example.com:12df')
@override_settings(PIWIK_DOMAIN_PATH="example.com:12df")
def test_domain_port_invalid(self):
self.assertRaises(AnalyticalException, PiwikNode)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
@override_settings(ANALYTICAL_INTERNAL_IPS=["1.1.1.1"])
def test_render_internal_ip(self):
req = HttpRequest()
req.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': req})
req.META["REMOTE_ADDR"] = "1.1.1.1"
context = Context({"request": req})
r = PiwikNode().render(context)
self.assertTrue(r.startswith(
'<!-- Piwik disabled on internal IP address'), r)
self.assertTrue(r.endswith('-->'), r)
self.assertTrue(r.startswith("<!-- Piwik disabled on internal IP address"), r)
self.assertTrue(r.endswith("-->"), r)
def test_uservars(self):
context = Context({'piwik_vars': [(1, 'foo', 'foo_val'),
(2, 'bar', 'bar_val', 'page'),
(3, 'spam', 'spam_val', 'visit')]})
context = Context(
{
"piwik_vars": [
(1, "foo", "foo_val"),
(2, "bar", "bar_val", "page"),
(3, "spam", "spam_val", "visit"),
]
}
)
r = PiwikNode().render(context)
msg = 'Incorrect Piwik custom variable rendering. Expected:\n%s\nIn:\n%s'
for var_code in ['_paq.push(["setCustomVariable", 1, "foo", "foo_val", "page"]);',
'_paq.push(["setCustomVariable", 2, "bar", "bar_val", "page"]);',
'_paq.push(["setCustomVariable", 3, "spam", "spam_val", "visit"]);']:
msg = "Incorrect Piwik custom variable rendering. Expected:\n%s\nIn:\n%s"
for var_code in [
'_paq.push(["setCustomVariable", 1, "foo", "foo_val", "page"]);',
'_paq.push(["setCustomVariable", 2, "bar", "bar_val", "page"]);',
'_paq.push(["setCustomVariable", 3, "spam", "spam_val", "visit"]);',
]:
self.assertIn(var_code, r, msg % (var_code, r))
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_default_usertrack(self):
context = Context({
'user': User(username='BDFL', first_name='Guido', last_name='van Rossum')
})
context = Context(
{"user": User(username="BDFL", first_name="Guido", last_name="van Rossum")}
)
r = PiwikNode().render(context)
msg = 'Incorrect Piwik user tracking rendering.\nNot found:\n%s\nIn:\n%s'
msg = "Incorrect Piwik user tracking rendering.\nNot found:\n%s\nIn:\n%s"
var_code = '_paq.push(["setUserId", "BDFL"]);'
self.assertIn(var_code, r, msg % (var_code, r))
def test_piwik_usertrack(self):
context = Context({
'piwik_identity': 'BDFL'
})
context = Context({"piwik_identity": "BDFL"})
r = PiwikNode().render(context)
msg = 'Incorrect Piwik user tracking rendering.\nNot found:\n%s\nIn:\n%s'
msg = "Incorrect Piwik user tracking rendering.\nNot found:\n%s\nIn:\n%s"
var_code = '_paq.push(["setUserId", "BDFL"]);'
self.assertIn(var_code, r, msg % (var_code, r))
def test_analytical_usertrack(self):
context = Context({
'analytical_identity': 'BDFL'
})
context = Context({"analytical_identity": "BDFL"})
r = PiwikNode().render(context)
msg = 'Incorrect Piwik user tracking rendering.\nNot found:\n%s\nIn:\n%s'
msg = "Incorrect Piwik user tracking rendering.\nNot found:\n%s\nIn:\n%s"
var_code = '_paq.push(["setUserId", "BDFL"]);'
self.assertIn(var_code, r, msg % (var_code, r))
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_disable_usertrack(self):
context = Context({
'user': User(username='BDFL', first_name='Guido', last_name='van Rossum'),
'piwik_identity': None
})
context = Context(
{
"user": User(
username="BDFL", first_name="Guido", last_name="van Rossum"
),
"piwik_identity": None,
}
)
r = PiwikNode().render(context)
msg = 'Incorrect Piwik user tracking rendering.\nFound:\n%s\nIn:\n%s'
msg = "Incorrect Piwik user tracking rendering.\nFound:\n%s\nIn:\n%s"
var_code = '_paq.push(["setUserId", "BDFL"]);'
self.assertNotIn(var_code, r, msg % (var_code, r))

View file

@ -5,20 +5,20 @@ Tests for the Rating@Mail.ru template tags and filters.
from django.http import HttpRequest
from django.template import Context
from django.test.utils import override_settings
from utils import TagTestCase
from analytical.templatetags.rating_mailru import RatingMailruNode
from utils import TagTestCase
from analytical.utils import AnalyticalException
@override_settings(RATING_MAILRU_COUNTER_ID='1234567')
@override_settings(RATING_MAILRU_COUNTER_ID="1234567")
class RatingMailruTagTestCase(TagTestCase):
"""
Tests for the ``rating_mailru`` template tag.
"""
def test_tag(self):
r = self.render_tag('rating_mailru', 'rating_mailru')
r = self.render_tag("rating_mailru", "rating_mailru")
self.assertTrue("counter?id=1234567;js=na" in r, r)
def test_node(self):
@ -29,16 +29,17 @@ class RatingMailruTagTestCase(TagTestCase):
def test_no_site_id(self):
self.assertRaises(AnalyticalException, RatingMailruNode)
@override_settings(RATING_MAILRU_COUNTER_ID='1234abc')
@override_settings(RATING_MAILRU_COUNTER_ID="1234abc")
def test_wrong_site_id(self):
self.assertRaises(AnalyticalException, RatingMailruNode)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
@override_settings(ANALYTICAL_INTERNAL_IPS=["1.1.1.1"])
def test_render_internal_ip(self):
req = HttpRequest()
req.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': req})
req.META["REMOTE_ADDR"] = "1.1.1.1"
context = Context({"request": req})
r = RatingMailruNode().render(context)
self.assertTrue(r.startswith(
'<!-- Rating@Mail.ru disabled on internal IP address'), r)
self.assertTrue(r.endswith('-->'), r)
self.assertTrue(
r.startswith("<!-- Rating@Mail.ru disabled on internal IP address"), r
)
self.assertTrue(r.endswith("-->"), r)

View file

@ -2,20 +2,26 @@
Tests for the SnapEngage template tags and filters.
"""
from django.contrib.auth.models import User, AnonymousUser
from django.contrib.auth.models import AnonymousUser, User
from django.template import Context
from django.test.utils import override_settings
from django.utils import translation
from analytical.templatetags.snapengage import SnapEngageNode, \
BUTTON_STYLE_LIVE, BUTTON_STYLE_DEFAULT, BUTTON_STYLE_NONE, \
BUTTON_LOCATION_LEFT, BUTTON_LOCATION_RIGHT, BUTTON_LOCATION_TOP, \
BUTTON_LOCATION_BOTTOM, FORM_POSITION_TOP_LEFT
from utils import TagTestCase
from analytical.templatetags.snapengage import (
BUTTON_LOCATION_BOTTOM,
BUTTON_LOCATION_LEFT,
BUTTON_LOCATION_RIGHT,
BUTTON_LOCATION_TOP,
BUTTON_STYLE_DEFAULT,
BUTTON_STYLE_LIVE,
BUTTON_STYLE_NONE,
FORM_POSITION_TOP_LEFT,
SnapEngageNode,
)
from analytical.utils import AnalyticalException
WIDGET_ID = 'ec329c69-0bf0-4db8-9b77-3f8150fb977e'
WIDGET_ID = "ec329c69-0bf0-4db8-9b77-3f8150fb977e"
@override_settings(
@ -30,246 +36,343 @@ class SnapEngageTestCase(TagTestCase):
"""
def test_tag(self):
r = self.render_tag('snapengage', 'snapengage')
r = self.render_tag("snapengage", "snapengage")
self.assertTrue(
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","0",'
'"55%");' in r, r)
'"55%");' in r,
r,
)
def test_node(self):
r = SnapEngageNode().render(Context())
self.assertTrue(
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","0",'
'"55%");' in r, r)
'"55%");' in r,
r,
)
@override_settings(SNAPENGAGE_WIDGET_ID=None)
def test_no_site_id(self):
self.assertRaises(AnalyticalException, SnapEngageNode)
@override_settings(SNAPENGAGE_WIDGET_ID='abc')
@override_settings(SNAPENGAGE_WIDGET_ID="abc")
def test_wrong_site_id(self):
self.assertRaises(AnalyticalException, SnapEngageNode)
def test_no_button(self):
r = SnapEngageNode().render(Context({
'snapengage_button': BUTTON_STYLE_NONE,
}))
r = SnapEngageNode().render(
Context(
{
"snapengage_button": BUTTON_STYLE_NONE,
}
)
)
self.assertTrue('SnapABug.init("ec329c69-0bf0-4db8-9b77-3f8150fb977e")' in r, r)
with override_settings(SNAPENGAGE_BUTTON=BUTTON_STYLE_NONE):
r = SnapEngageNode().render(Context())
self.assertTrue(
'SnapABug.init("ec329c69-0bf0-4db8-9b77-3f8150fb977e")' in r, r)
'SnapABug.init("ec329c69-0bf0-4db8-9b77-3f8150fb977e")' in r, r
)
def test_live_button(self):
r = SnapEngageNode().render(Context({
'snapengage_button': BUTTON_STYLE_LIVE,
}))
r = SnapEngageNode().render(
Context(
{
"snapengage_button": BUTTON_STYLE_LIVE,
}
)
)
self.assertTrue(
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","0",'
'"55%",true);' in r, r)
'"55%",true);' in r,
r,
)
with override_settings(SNAPENGAGE_BUTTON=BUTTON_STYLE_LIVE):
r = SnapEngageNode().render(Context())
self.assertTrue(
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","0",'
'"55%",true);' in r, r)
'"55%",true);' in r,
r,
)
def test_custom_button(self):
r = SnapEngageNode().render(Context({
'snapengage_button': "http://www.example.com/button.png",
}))
r = SnapEngageNode().render(
Context(
{
"snapengage_button": "http://www.example.com/button.png",
}
)
)
self.assertTrue(
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","0",'
'"55%");' in r, r)
'"55%");' in r,
r,
)
self.assertTrue(
'SnapABug.setButton("http://www.example.com/button.png");' in r, r)
with override_settings(
SNAPENGAGE_BUTTON="http://www.example.com/button.png"):
'SnapABug.setButton("http://www.example.com/button.png");' in r, r
)
with override_settings(SNAPENGAGE_BUTTON="http://www.example.com/button.png"):
r = SnapEngageNode().render(Context())
self.assertTrue(
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","0",'
'"55%");' in r, r)
'"55%");' in r,
r,
)
self.assertTrue(
'SnapABug.setButton("http://www.example.com/button.png");' in r,
r)
'SnapABug.setButton("http://www.example.com/button.png");' in r, r
)
def test_button_location_right(self):
r = SnapEngageNode().render(Context({
'snapengage_button_location': BUTTON_LOCATION_RIGHT,
}))
r = SnapEngageNode().render(
Context(
{
"snapengage_button_location": BUTTON_LOCATION_RIGHT,
}
)
)
self.assertTrue(
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","1",'
'"55%");' in r, r)
'"55%");' in r,
r,
)
with override_settings(SNAPENGAGE_BUTTON_LOCATION=BUTTON_LOCATION_RIGHT):
r = SnapEngageNode().render(Context())
self.assertTrue(
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","1",'
'"55%");' in r, r)
'"55%");' in r,
r,
)
def test_button_location_top(self):
r = SnapEngageNode().render(Context({
'snapengage_button_location': BUTTON_LOCATION_TOP,
}))
r = SnapEngageNode().render(
Context(
{
"snapengage_button_location": BUTTON_LOCATION_TOP,
}
)
)
self.assertTrue(
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","2",'
'"55%");' in r, r)
'"55%");' in r,
r,
)
with override_settings(SNAPENGAGE_BUTTON_LOCATION=BUTTON_LOCATION_TOP):
r = SnapEngageNode().render(Context())
self.assertTrue(
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","2",'
'"55%");' in r, r)
'"55%");' in r,
r,
)
def test_button_location_bottom(self):
r = SnapEngageNode().render(Context({
'snapengage_button_location': BUTTON_LOCATION_BOTTOM,
}))
r = SnapEngageNode().render(
Context(
{
"snapengage_button_location": BUTTON_LOCATION_BOTTOM,
}
)
)
self.assertTrue(
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","3",'
'"55%");' in r, r)
with override_settings(
SNAPENGAGE_BUTTON_LOCATION=BUTTON_LOCATION_BOTTOM):
'"55%");' in r,
r,
)
with override_settings(SNAPENGAGE_BUTTON_LOCATION=BUTTON_LOCATION_BOTTOM):
r = SnapEngageNode().render(Context())
self.assertTrue(
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","3",'
'"55%");' in r, r)
'"55%");' in r,
r,
)
def test_button_offset(self):
r = SnapEngageNode().render(Context({
'snapengage_button_location_offset': "30%",
}))
r = SnapEngageNode().render(
Context(
{
"snapengage_button_location_offset": "30%",
}
)
)
self.assertTrue(
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","0",'
'"30%");' in r, r)
'"30%");' in r,
r,
)
with override_settings(SNAPENGAGE_BUTTON_LOCATION_OFFSET="30%"):
r = SnapEngageNode().render(Context())
self.assertTrue(
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","0",'
'"30%");' in r, r)
'"30%");' in r,
r,
)
def test_button_effect(self):
r = SnapEngageNode().render(Context({
'snapengage_button_effect': "-4px",
}))
r = SnapEngageNode().render(
Context(
{
"snapengage_button_effect": "-4px",
}
)
)
self.assertTrue('SnapABug.setButtonEffect("-4px");' in r, r)
with override_settings(SNAPENGAGE_BUTTON_EFFECT="-4px"):
r = SnapEngageNode().render(Context())
self.assertTrue('SnapABug.setButtonEffect("-4px");' in r, r)
def test_form_position(self):
r = SnapEngageNode().render(Context({
'snapengage_form_position': FORM_POSITION_TOP_LEFT,
}))
r = SnapEngageNode().render(
Context(
{
"snapengage_form_position": FORM_POSITION_TOP_LEFT,
}
)
)
self.assertTrue('SnapABug.setChatFormPosition("tl");' in r, r)
with override_settings(SNAPENGAGE_FORM_POSITION=FORM_POSITION_TOP_LEFT):
r = SnapEngageNode().render(Context())
self.assertTrue('SnapABug.setChatFormPosition("tl");' in r, r)
def test_form_top_position(self):
r = SnapEngageNode().render(Context({
'snapengage_form_top_position': 40,
}))
self.assertTrue('SnapABug.setFormTopPosition(40);' in r, r)
r = SnapEngageNode().render(
Context(
{
"snapengage_form_top_position": 40,
}
)
)
self.assertTrue("SnapABug.setFormTopPosition(40);" in r, r)
with override_settings(SNAPENGAGE_FORM_TOP_POSITION=40):
r = SnapEngageNode().render(Context())
self.assertTrue('SnapABug.setFormTopPosition(40);' in r, r)
self.assertTrue("SnapABug.setFormTopPosition(40);" in r, r)
def test_domain(self):
r = SnapEngageNode().render(Context({
'snapengage_domain': "example.com"}))
r = SnapEngageNode().render(Context({"snapengage_domain": "example.com"}))
self.assertTrue('SnapABug.setDomain("example.com");' in r, r)
with override_settings(SNAPENGAGE_DOMAIN="example.com"):
r = SnapEngageNode().render(Context())
self.assertTrue('SnapABug.setDomain("example.com");' in r, r)
def test_secure_connection(self):
r = SnapEngageNode().render(Context({
'snapengage_secure_connection': True}))
self.assertTrue('SnapABug.setSecureConnexion();' in r, r)
r = SnapEngageNode().render(Context({"snapengage_secure_connection": True}))
self.assertTrue("SnapABug.setSecureConnexion();" in r, r)
with override_settings(SNAPENGAGE_SECURE_CONNECTION=True):
r = SnapEngageNode().render(Context())
self.assertTrue('SnapABug.setSecureConnexion();' in r, r)
self.assertTrue("SnapABug.setSecureConnexion();" in r, r)
def test_show_offline(self):
r = SnapEngageNode().render(Context({
'snapengage_show_offline': False,
}))
self.assertTrue('SnapABug.allowOffline(false);' in r, r)
r = SnapEngageNode().render(
Context(
{
"snapengage_show_offline": False,
}
)
)
self.assertTrue("SnapABug.allowOffline(false);" in r, r)
with override_settings(SNAPENGAGE_SHOW_OFFLINE=False):
r = SnapEngageNode().render(Context())
self.assertTrue('SnapABug.allowOffline(false);' in r, r)
self.assertTrue("SnapABug.allowOffline(false);" in r, r)
def test_proactive_chat(self):
r = SnapEngageNode().render(Context({
'snapengage_proactive_chat': False}))
self.assertTrue('SnapABug.allowProactiveChat(false);' in r, r)
r = SnapEngageNode().render(Context({"snapengage_proactive_chat": False}))
self.assertTrue("SnapABug.allowProactiveChat(false);" in r, r)
def test_screenshot(self):
r = SnapEngageNode().render(Context({
'snapengage_screenshots': False,
}))
self.assertTrue('SnapABug.allowScreenshot(false);' in r, r)
r = SnapEngageNode().render(
Context(
{
"snapengage_screenshots": False,
}
)
)
self.assertTrue("SnapABug.allowScreenshot(false);" in r, r)
with override_settings(SNAPENGAGE_SCREENSHOTS=False):
r = SnapEngageNode().render(Context())
self.assertTrue('SnapABug.allowScreenshot(false);' in r, r)
self.assertTrue("SnapABug.allowScreenshot(false);" in r, r)
def test_offline_screenshots(self):
r = SnapEngageNode().render(Context({
'snapengage_offline_screenshots': False,
}))
self.assertTrue('SnapABug.showScreenshotOption(false);' in r, r)
r = SnapEngageNode().render(
Context(
{
"snapengage_offline_screenshots": False,
}
)
)
self.assertTrue("SnapABug.showScreenshotOption(false);" in r, r)
with override_settings(SNAPENGAGE_OFFLINE_SCREENSHOTS=False):
r = SnapEngageNode().render(Context())
self.assertTrue('SnapABug.showScreenshotOption(false);' in r, r)
self.assertTrue("SnapABug.showScreenshotOption(false);" in r, r)
def test_sounds(self):
r = SnapEngageNode().render(Context({'snapengage_sounds': False}))
self.assertTrue('SnapABug.allowChatSound(false);' in r, r)
r = SnapEngageNode().render(Context({"snapengage_sounds": False}))
self.assertTrue("SnapABug.allowChatSound(false);" in r, r)
with override_settings(SNAPENGAGE_SOUNDS=False):
r = SnapEngageNode().render(Context())
self.assertTrue('SnapABug.allowChatSound(false);' in r, r)
self.assertTrue("SnapABug.allowChatSound(false);" in r, r)
@override_settings(SNAPENGAGE_READONLY_EMAIL=False)
def test_email(self):
r = SnapEngageNode().render(Context({
'snapengage_email': 'test@example.com',
}))
r = SnapEngageNode().render(
Context(
{
"snapengage_email": "test@example.com",
}
)
)
self.assertTrue('SnapABug.setUserEmail("test@example.com");' in r, r)
def test_email_readonly(self):
r = SnapEngageNode().render(Context({
'snapengage_email': 'test@example.com',
'snapengage_readonly_email': True,
}))
r = SnapEngageNode().render(
Context(
{
"snapengage_email": "test@example.com",
"snapengage_readonly_email": True,
}
)
)
self.assertTrue('SnapABug.setUserEmail("test@example.com",true);' in r, r)
with override_settings(SNAPENGAGE_READONLY_EMAIL=True):
r = SnapEngageNode().render(Context({
'snapengage_email': 'test@example.com',
}))
r = SnapEngageNode().render(
Context(
{
"snapengage_email": "test@example.com",
}
)
)
self.assertTrue('SnapABug.setUserEmail("test@example.com",true);' in r, r)
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify(self):
r = SnapEngageNode().render(Context({
'user': User(username='test', email='test@example.com'),
}))
r = SnapEngageNode().render(
Context(
{
"user": User(username="test", email="test@example.com"),
}
)
)
self.assertTrue('SnapABug.setUserEmail("test@example.com");' in r, r)
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify_anonymous_user(self):
r = SnapEngageNode().render(Context({
'user': AnonymousUser(),
}))
self.assertFalse('SnapABug.setUserEmail(' in r, r)
r = SnapEngageNode().render(
Context(
{
"user": AnonymousUser(),
}
)
)
self.assertFalse("SnapABug.setUserEmail(" in r, r)
def test_language(self):
r = SnapEngageNode().render(Context({'snapengage_locale': 'fr'}))
r = SnapEngageNode().render(Context({"snapengage_locale": "fr"}))
self.assertTrue('SnapABug.setLocale("fr");' in r, r)
with override_settings(SNAPENGAGE_LOCALE='fr'):
with override_settings(SNAPENGAGE_LOCALE="fr"):
r = SnapEngageNode().render(Context())
self.assertTrue('SnapABug.setLocale("fr");' in r, r)
def test_automatic_language(self):
real_get_language = translation.get_language
try:
translation.get_language = lambda: 'fr-ca'
translation.get_language = lambda: "fr-ca"
r = SnapEngageNode().render(Context())
self.assertTrue('SnapABug.setLocale("fr_CA");' in r, r)
finally:

View file

@ -2,24 +2,24 @@
Tests for the Spring Metrics template tags and filters.
"""
from django.contrib.auth.models import User, AnonymousUser
from django.contrib.auth.models import AnonymousUser, User
from django.http import HttpRequest
from django.template import Context
from django.test.utils import override_settings
from utils import TagTestCase
from analytical.templatetags.spring_metrics import SpringMetricsNode
from utils import TagTestCase
from analytical.utils import AnalyticalException
@override_settings(SPRING_METRICS_TRACKING_ID='12345678')
@override_settings(SPRING_METRICS_TRACKING_ID="12345678")
class SpringMetricsTagTestCase(TagTestCase):
"""
Tests for the ``spring_metrics`` template tag.
"""
def test_tag(self):
r = self.render_tag('spring_metrics', 'spring_metrics')
r = self.render_tag("spring_metrics", "spring_metrics")
self.assertTrue("_springMetq.push(['id', '12345678']);" in r, r)
def test_node(self):
@ -30,36 +30,47 @@ class SpringMetricsTagTestCase(TagTestCase):
def test_no_site_id(self):
self.assertRaises(AnalyticalException, SpringMetricsNode)
@override_settings(SPRING_METRICS_TRACKING_ID='123xyz')
@override_settings(SPRING_METRICS_TRACKING_ID="123xyz")
def test_wrong_site_id(self):
self.assertRaises(AnalyticalException, SpringMetricsNode)
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify(self):
r = SpringMetricsNode().render(Context({
'user': User(email='test@test.com'),
}))
self.assertTrue("_springMetq.push(['setdata', {'email': 'test@test.com'}]);" in r, r)
r = SpringMetricsNode().render(
Context(
{
"user": User(email="test@test.com"),
}
)
)
self.assertTrue(
"_springMetq.push(['setdata', {'email': 'test@test.com'}]);" in r, r
)
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify_anonymous_user(self):
r = SpringMetricsNode().render(Context({'user': AnonymousUser()}))
r = SpringMetricsNode().render(Context({"user": AnonymousUser()}))
self.assertFalse("_springMetq.push(['setdata', {'email':" in r, r)
def test_custom(self):
r = SpringMetricsNode().render(Context({
'spring_metrics_var1': 'val1',
'spring_metrics_var2': 'val2',
}))
r = SpringMetricsNode().render(
Context(
{
"spring_metrics_var1": "val1",
"spring_metrics_var2": "val2",
}
)
)
self.assertTrue("_springMetq.push(['setdata', {'var1': 'val1'}]);" in r, r)
self.assertTrue("_springMetq.push(['setdata', {'var2': 'val2'}]);" in r, r)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
@override_settings(ANALYTICAL_INTERNAL_IPS=["1.1.1.1"])
def test_render_internal_ip(self):
req = HttpRequest()
req.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': req})
req.META["REMOTE_ADDR"] = "1.1.1.1"
context = Context({"request": req})
r = SpringMetricsNode().render(context)
self.assertTrue(r.startswith(
'<!-- Spring Metrics disabled on internal IP address'), r)
self.assertTrue(r.endswith('-->'), r)
self.assertTrue(
r.startswith("<!-- Spring Metrics disabled on internal IP address"), r
)
self.assertTrue(r.endswith("-->"), r)

View file

@ -4,13 +4,13 @@ Tests for the UserVoice tags and filters.
from django.template import Context
from django.test.utils import override_settings
from utils import TagTestCase
from analytical.templatetags.uservoice import UserVoiceNode
from utils import TagTestCase
from analytical.utils import AnalyticalException
@override_settings(USERVOICE_WIDGET_KEY='abcdefghijklmnopqrst')
@override_settings(USERVOICE_WIDGET_KEY="abcdefghijklmnopqrst")
class UserVoiceTagTestCase(TagTestCase):
"""
Tests for the ``uservoice`` template tag.
@ -27,34 +27,34 @@ class UserVoiceTagTestCase(TagTestCase):
self.assertIn("widget.uservoice.com/abcdefghijklmnopqrst.js", r)
def test_tag(self):
r = self.render_tag('uservoice', 'uservoice')
r = self.render_tag("uservoice", "uservoice")
self.assertIn("widget.uservoice.com/abcdefghijklmnopqrst.js", r)
@override_settings(USERVOICE_WIDGET_KEY=None)
def test_no_key(self):
self.assertRaises(AnalyticalException, UserVoiceNode)
@override_settings(USERVOICE_WIDGET_KEY='abcdefgh ijklmnopqrst')
@override_settings(USERVOICE_WIDGET_KEY="abcdefgh ijklmnopqrst")
def test_invalid_key(self):
self.assertRaises(AnalyticalException, UserVoiceNode)
@override_settings(USERVOICE_WIDGET_KEY='')
@override_settings(USERVOICE_WIDGET_KEY="")
def test_empty_key(self):
self.assertRaises(AnalyticalException, UserVoiceNode)
def test_overridden_key(self):
vars = {'uservoice_widget_key': 'defghijklmnopqrstuvw'}
vars = {"uservoice_widget_key": "defghijklmnopqrstuvw"}
r = UserVoiceNode().render(Context(vars))
self.assertIn("widget.uservoice.com/defghijklmnopqrstuvw.js", r)
@override_settings(USERVOICE_WIDGET_OPTIONS={'key1': 'val1'})
@override_settings(USERVOICE_WIDGET_OPTIONS={"key1": "val1"})
def test_options(self):
r = UserVoiceNode().render(Context())
self.assertIn("""UserVoice.push(['set', {"key1": "val1"}]);""", r)
@override_settings(USERVOICE_WIDGET_OPTIONS={'key1': 'val1'})
@override_settings(USERVOICE_WIDGET_OPTIONS={"key1": "val1"})
def test_override_options(self):
data = {'uservoice_widget_options': {'key1': 'val2'}}
data = {"uservoice_widget_options": {"key1": "val2"}}
r = UserVoiceNode().render(Context(data))
self.assertIn("""UserVoice.push(['set', {"key1": "val2"}]);""", r)
@ -69,5 +69,5 @@ class UserVoiceTagTestCase(TagTestCase):
@override_settings(USERVOICE_ADD_TRIGGER=False)
def test_auto_trigger_custom_win(self):
r = UserVoiceNode().render(Context({'uservoice_add_trigger': True}))
r = UserVoiceNode().render(Context({"uservoice_add_trigger": True}))
self.assertTrue("UserVoice.push(['addTrigger', {}]);" in r, r)

View file

@ -2,24 +2,24 @@
Tests for the Woopra template tags and filters.
"""
from django.contrib.auth.models import User, AnonymousUser
from django.contrib.auth.models import AnonymousUser, User
from django.http import HttpRequest
from django.template import Context
from django.test.utils import override_settings
from utils import TagTestCase
from analytical.templatetags.woopra import WoopraNode
from utils import TagTestCase
from analytical.utils import AnalyticalException
@override_settings(WOOPRA_DOMAIN='example.com')
@override_settings(WOOPRA_DOMAIN="example.com")
class WoopraTagTestCase(TagTestCase):
"""
Tests for the ``woopra`` template tag.
"""
def test_tag(self):
r = self.render_tag('woopra', 'woopra')
r = self.render_tag("woopra", "woopra")
self.assertTrue('var woo_settings = {"domain": "example.com"};' in r, r)
def test_node(self):
@ -30,66 +30,89 @@ class WoopraTagTestCase(TagTestCase):
def test_no_domain(self):
self.assertRaises(AnalyticalException, WoopraNode)
@override_settings(WOOPRA_DOMAIN='this is not a domain')
@override_settings(WOOPRA_DOMAIN="this is not a domain")
def test_wrong_domain(self):
self.assertRaises(AnalyticalException, WoopraNode)
@override_settings(WOOPRA_IDLE_TIMEOUT=1234)
def test_idle_timeout(self):
r = WoopraNode().render(Context({}))
self.assertTrue('var woo_settings = '
'{"domain": "example.com", "idle_timeout": "1234"};' in r, r)
self.assertTrue(
"var woo_settings = "
'{"domain": "example.com", "idle_timeout": "1234"};' in r,
r,
)
def test_custom(self):
r = WoopraNode().render(Context({
'woopra_var1': 'val1',
'woopra_var2': 'val2',
}))
r = WoopraNode().render(
Context(
{
"woopra_var1": "val1",
"woopra_var2": "val2",
}
)
)
self.assertTrue('var woo_visitor = {"var1": "val1", "var2": "val2"};' in r, r)
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify_name_and_email(self):
r = WoopraNode().render(Context({
'user': User(username='test',
first_name='Firstname',
last_name='Lastname',
email="test@example.com"),
}))
self.assertTrue('var woo_visitor = '
'{"email": "test@example.com", "name": "Firstname Lastname"};' in r, r)
r = WoopraNode().render(
Context(
{
"user": User(
username="test",
first_name="Firstname",
last_name="Lastname",
email="test@example.com",
),
}
)
)
self.assertTrue(
"var woo_visitor = "
'{"email": "test@example.com", "name": "Firstname Lastname"};' in r,
r,
)
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify_username_no_email(self):
r = WoopraNode().render(Context({'user': User(username='test')}))
r = WoopraNode().render(Context({"user": User(username="test")}))
self.assertTrue('var woo_visitor = {"name": "test"};' in r, r)
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_no_identify_when_explicit_name(self):
r = WoopraNode().render(Context({
'woopra_name': 'explicit',
'user': User(username='implicit'),
}))
r = WoopraNode().render(
Context(
{
"woopra_name": "explicit",
"user": User(username="implicit"),
}
)
)
self.assertTrue('var woo_visitor = {"name": "explicit"};' in r, r)
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_no_identify_when_explicit_email(self):
r = WoopraNode().render(Context({
'woopra_email': 'explicit',
'user': User(username='implicit'),
}))
r = WoopraNode().render(
Context(
{
"woopra_email": "explicit",
"user": User(username="implicit"),
}
)
)
self.assertTrue('var woo_visitor = {"email": "explicit"};' in r, r)
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify_anonymous_user(self):
r = WoopraNode().render(Context({'user': AnonymousUser()}))
self.assertTrue('var woo_visitor = {};' in r, r)
r = WoopraNode().render(Context({"user": AnonymousUser()}))
self.assertTrue("var woo_visitor = {};" in r, r)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
@override_settings(ANALYTICAL_INTERNAL_IPS=["1.1.1.1"])
def test_render_internal_ip(self):
req = HttpRequest()
req.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': req})
req.META["REMOTE_ADDR"] = "1.1.1.1"
context = Context({"request": req})
r = WoopraNode().render(context)
self.assertTrue(r.startswith(
'<!-- Woopra disabled on internal IP address'), r)
self.assertTrue(r.endswith('-->'), r)
self.assertTrue(r.startswith("<!-- Woopra disabled on internal IP address"), r)
self.assertTrue(r.endswith("-->"), r)

View file

@ -6,20 +6,20 @@ Tests for the Yandex.Metrica template tags and filters.
from django.http import HttpRequest
from django.template import Context
from django.test.utils import override_settings
from utils import TagTestCase
from analytical.templatetags.yandex_metrica import YandexMetricaNode
from utils import TagTestCase
from analytical.utils import AnalyticalException
@override_settings(YANDEX_METRICA_COUNTER_ID='12345678')
@override_settings(YANDEX_METRICA_COUNTER_ID="12345678")
class YandexMetricaTagTestCase(TagTestCase):
"""
Tests for the ``yandex_metrica`` template tag.
"""
def test_tag(self):
r = self.render_tag('yandex_metrica', 'yandex_metrica')
r = self.render_tag("yandex_metrica", "yandex_metrica")
self.assertTrue("w.yaCounter12345678 = new Ya.Metrika" in r, r)
def test_node(self):
@ -30,16 +30,17 @@ class YandexMetricaTagTestCase(TagTestCase):
def test_no_site_id(self):
self.assertRaises(AnalyticalException, YandexMetricaNode)
@override_settings(YANDEX_METRICA_COUNTER_ID='1234abcd')
@override_settings(YANDEX_METRICA_COUNTER_ID="1234abcd")
def test_wrong_site_id(self):
self.assertRaises(AnalyticalException, YandexMetricaNode)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
@override_settings(ANALYTICAL_INTERNAL_IPS=["1.1.1.1"])
def test_render_internal_ip(self):
req = HttpRequest()
req.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': req})
req.META["REMOTE_ADDR"] = "1.1.1.1"
context = Context({"request": req})
r = YandexMetricaNode().render(context)
self.assertTrue(r.startswith(
'<!-- Yandex.Metrica disabled on internal IP address'), r)
self.assertTrue(r.endswith('-->'), r)
self.assertTrue(
r.startswith("<!-- Yandex.Metrica disabled on internal IP address"), r
)
self.assertTrue(r.endswith("-->"), r)

View file

@ -8,6 +8,7 @@ from django.db import models
from django.http import HttpRequest
from django.template import Context
from django.test.utils import override_settings
from utils import TestCase
from analytical.utils import (
AnalyticalException,
@ -16,54 +17,54 @@ from analytical.utils import (
get_required_setting,
is_internal_ip,
)
from utils import TestCase
class SettingDeletedTestCase(TestCase):
@override_settings(USER_ID=None)
def test_get_required_setting(self):
"""
Make sure using get_required_setting fails in the right place.
"""
with self.assertRaisesRegex(AnalyticalException, "^USER_ID setting is not set$"):
with self.assertRaisesRegex(
AnalyticalException, "^USER_ID setting is not set$"
):
get_required_setting("USER_ID", r"\d+", "invalid USER_ID")
class MyUser(AbstractBaseUser):
identity = models.CharField(max_length=50)
USERNAME_FIELD = 'identity'
USERNAME_FIELD = "identity"
class Meta:
abstract = True
app_label = 'testapp'
app_label = "testapp"
class GetIdentityTestCase(TestCase):
def test_custom_username_field(self):
get_id = get_identity(Context({}), user=MyUser(identity='fake_id'))
self.assertEqual(get_id, 'fake_id')
get_id = get_identity(Context({}), user=MyUser(identity="fake_id"))
self.assertEqual(get_id, "fake_id")
@override_settings(ANALYTICAL_DOMAIN="example.org")
class GetDomainTestCase(TestCase):
def test_get_service_domain_from_context(self):
context = Context({'test_domain': 'example.com'})
self.assertEqual(get_domain(context, 'test'), 'example.com')
context = Context({"test_domain": "example.com"})
self.assertEqual(get_domain(context, "test"), "example.com")
def test_get_analytical_domain_from_context(self):
context = Context({'analytical_domain': 'example.com'})
self.assertEqual(get_domain(context, 'test'), 'example.com')
context = Context({"analytical_domain": "example.com"})
self.assertEqual(get_domain(context, "test"), "example.com")
@override_settings(TEST_DOMAIN="example.net")
def test_get_service_domain_from_settings(self):
context = Context()
self.assertEqual(get_domain(context, 'test'), 'example.net')
self.assertEqual(get_domain(context, "test"), "example.net")
def test_get_analytical_domain_from_settings(self):
context = Context()
self.assertEqual(get_domain(context, 'test'), 'example.org')
self.assertEqual(get_domain(context, "test"), "example.org")
# FIXME: enable Django apps dynamically and enable test again
@ -78,51 +79,50 @@ class GetDomainTestCase(TestCase):
class InternalIpTestCase(TestCase):
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
@override_settings(ANALYTICAL_INTERNAL_IPS=["1.1.1.1"])
def test_render_no_internal_ip(self):
context = Context()
self.assertFalse(is_internal_ip(context))
@override_settings(INTERNAL_IPS=['1.1.1.1'])
@override_settings(INTERNAL_IPS=["1.1.1.1"])
@override_settings(ANALYTICAL_INTERNAL_IPS=[])
def test_render_analytical_internal_ips_override_when_empty(self):
req = HttpRequest()
req.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': req})
req.META["REMOTE_ADDR"] = "1.1.1.1"
context = Context({"request": req})
self.assertFalse(is_internal_ip(context))
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
@override_settings(ANALYTICAL_INTERNAL_IPS=["1.1.1.1"])
def test_render_internal_ip(self):
req = HttpRequest()
req.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': req})
req.META["REMOTE_ADDR"] = "1.1.1.1"
context = Context({"request": req})
self.assertTrue(is_internal_ip(context))
@override_settings(TEST_INTERNAL_IPS=['1.1.1.1'])
@override_settings(TEST_INTERNAL_IPS=["1.1.1.1"])
def test_render_prefix_internal_ip(self):
req = HttpRequest()
req.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': req})
self.assertTrue(is_internal_ip(context, 'TEST'))
req.META["REMOTE_ADDR"] = "1.1.1.1"
context = Context({"request": req})
self.assertTrue(is_internal_ip(context, "TEST"))
@override_settings(INTERNAL_IPS=['1.1.1.1'])
@override_settings(INTERNAL_IPS=["1.1.1.1"])
def test_render_internal_ip_fallback(self):
req = HttpRequest()
req.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': req})
req.META["REMOTE_ADDR"] = "1.1.1.1"
context = Context({"request": req})
self.assertTrue(is_internal_ip(context))
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
@override_settings(ANALYTICAL_INTERNAL_IPS=["1.1.1.1"])
def test_render_internal_ip_forwarded_for(self):
req = HttpRequest()
req.META['HTTP_X_FORWARDED_FOR'] = '1.1.1.1'
context = Context({'request': req})
req.META["HTTP_X_FORWARDED_FOR"] = "1.1.1.1"
context = Context({"request": req})
self.assertTrue(is_internal_ip(context))
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
@override_settings(ANALYTICAL_INTERNAL_IPS=["1.1.1.1"])
def test_render_different_internal_ip(self):
req = HttpRequest()
req.META['REMOTE_ADDR'] = '2.2.2.2'
context = Context({'request': req})
req.META["REMOTE_ADDR"] = "2.2.2.2"
context = Context({"request": req})
self.assertFalse(is_internal_ip(context))

View file

@ -2,7 +2,7 @@
Testing utilities.
"""
from django.template import Template, Context, RequestContext
from django.template import Context, RequestContext, Template
from django.test.testcases import TestCase

15
tox.ini
View file

@ -2,7 +2,7 @@
envlist =
# Python/Django combinations that are officially supported
py{36,37,38,39}-django{22,30,31}
py37-{flake8,bandit,readme,docs}
py37-{lint,bandit,readme,docs}
[testenv]
description = Unit tests
@ -36,10 +36,17 @@ deps = sphinx
commands = sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html
whitelist_externals = make
[testenv:py37-flake8]
[testenv:py37-lint]
description = Static code analysis and code style
deps = flake8
commands = flake8
skip_install = True
deps =
flake8
isort
black
commands =
flake8
isort tests setup.py analytical --check --diff
black tests setup.py analytical --check
[testenv:py37-readme]
description = Ensure README renders on PyPI