Reformat code using Ruff

This commit is contained in:
Peter Bittner 2025-04-04 13:25:00 +02:00
parent 82fbbeb6b2
commit a112ec445f
59 changed files with 1055 additions and 604 deletions

View file

@ -66,7 +66,7 @@ class AnalyticalNode(Node):
self.nodes = [node_cls() for node_cls in template_nodes[location]]
def render(self, context):
return "".join([node.render(context) for node in self.nodes])
return ''.join([node.render(context) for node in self.nodes])
def _load_template_nodes():
@ -82,14 +82,15 @@ 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)
return import_module("%s.templatetags.%s" % (app_name, lib_name))
return import_module('%s.templatetags.%s' % (app_name, lib_name))
template_nodes = _load_template_nodes()

View file

@ -12,7 +12,9 @@ from django.template import Library, Node, TemplateSyntaxError
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>"""
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;
@ -55,7 +57,7 @@ def chartbeat_top(parser, token):
class ChartbeatTopNode(Node):
def render(self, context):
if is_internal_ip(context):
return disable_html(INIT_CODE, "Chartbeat")
return disable_html(INIT_CODE, 'Chartbeat')
return INIT_CODE
@ -76,8 +78,9 @@ 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}
@ -106,6 +109,7 @@ def _get_domain(context):
return
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

@ -42,9 +42,11 @@ 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}

View file

@ -53,8 +53,8 @@ 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 = {}

View file

@ -9,10 +9,10 @@ from django.template import Library, Node, TemplateSyntaxError
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')
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,7 +38,8 @@ 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"
ACCOUNT_NUMBER_RE,
'must be (a string containing) a number',
)
def render(self, context):
@ -49,12 +50,15 @@ class CrazyEggNode(Node):
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)
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

View file

@ -60,11 +60,12 @@ 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+$'),
"must be (a string containing) a number",
'must be (a string containing) a number',
)
def render(self, context):

View file

@ -46,8 +46,8 @@ 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}

View file

@ -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,7 +55,10 @@ 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')
@ -80,8 +84,10 @@ 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)
@ -94,7 +100,7 @@ class GoogleAnalyticsNode(Node):
source = DEFAULT_SOURCE
html = SETUP_CODE % {
'property_id': self.property_id,
'commands': " ".join(commands),
'commands': ' '.join(commands),
'source_scheme': source[0],
'source_url': source[1],
}
@ -104,15 +110,17 @@ class GoogleAnalyticsNode(Node):
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')
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,12 +138,15 @@ 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):
@ -152,29 +161,42 @@ class GoogleAnalyticsNode(Node):
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

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,10 +51,12 @@ 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 = {}
@ -61,9 +65,12 @@ class GoogleAnalyticsGTagNode(Node):
if identity is not None:
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,

View file

@ -57,29 +57,34 @@ 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)
js_source = getattr(
settings,
'GOOGLE_ANALYTICS_JS_SOURCE',
'https://www.google-analytics.com/analytics.js'
'https://www.google-analytics.com/analytics.js',
)
html = SETUP_CODE.format(
property_id=self.property_id,
create_fields=json.dumps(create_fields),
commands="".join(commands),
commands=''.join(commands),
js_source=js_source,
)
if is_internal_ip(context, 'GOOGLE_ANALYTICS'):
@ -88,14 +93,17 @@ class GoogleAnalyticsJsNode(Node):
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')
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'
)
domain_fields['legacyCookieDomain'] = domain
if tracking_type == TRACK_MULTIPLE_DOMAINS:
domain_fields['allowLinker'] = True
@ -104,34 +112,39 @@ class GoogleAnalyticsJsNode(Node):
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")
"'GOOGLE_ANALYTICS_SITE_SPEED_SAMPLE_RATE' must be >= 0 and <= 100"
)
other_fields['siteSpeedSampleRate'] = value
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")
raise AnalyticalException(
"'GOOGLE_ANALYTICS_SAMPLE_RATE' must be >= 0 and <= 100"
)
other_fields['sampleRate'] = value
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")
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:
@ -141,10 +154,12 @@ 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):

View file

@ -52,8 +52,10 @@ 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]

View file

@ -15,7 +15,7 @@ TRACKING_CODE = """
heap.load("%(tracker_id)s");
</script>
""" # noqa
""" # noqa
register = Library()
@ -41,9 +41,9 @@ def heap(parser, token):
class HeapNode(Node):
def __init__(self):
self.tracker_id = get_required_setting('HEAP_TRACKER_ID',
HEAP_TRACKER_ID_RE,
"must be an numeric string")
self.tracker_id = get_required_setting(
'HEAP_TRACKER_ID', HEAP_TRACKER_ID_RE, 'must be an numeric string'
)
def render(self, context):
html = TRACKING_CODE % {'tracker_id': self.tracker_id}

View file

@ -41,12 +41,11 @@ def hotjar(parser, token):
class HotjarNode(Node):
def __init__(self):
self.site_id = get_required_setting(
'HOTJAR_SITE_ID',
re.compile(r'^\d+$'),
"must be (a string containing) a number",
'must be (a string containing) a number',
)
def render(self, context):

View file

@ -41,8 +41,9 @@ 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}

View file

@ -76,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()
@ -95,8 +95,7 @@ class IntercomNode(Node):
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)
params['name'] = get_identity(context, 'intercom', self._identify, user)
if 'email' not in params and user.email:
params['email'] = user.email
@ -120,10 +119,8 @@ class IntercomNode(Node):
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)
}
params['app_id'] = self.app_id
html = TRACKING_CODE % {'settings_json': json.dumps(params, sort_keys=True)}
if is_internal_ip(context, 'INTERCOM'):
html = disable_html(html, 'Intercom')

View file

@ -41,11 +41,15 @@ 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 = []
@ -59,7 +63,7 @@ class KissInsightsNode(Node):
html = SETUP_CODE % {
'account_number': self.account_number,
'site_code': self.site_code,
'commands': " ".join(commands),
'commands': ' '.join(commands),
}
return html

View file

@ -63,8 +63,10 @@ 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 = []
@ -79,22 +81,28 @@ 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),
'commands': ' '.join(commands),
}
if is_internal_ip(context, 'KISS_METRICS'):
html = disable_html(html, 'KISSmetrics')

View file

@ -39,12 +39,11 @@ def luckyorange(parser, token):
class LuckyOrangeNode(Node):
def __init__(self):
self.site_id = get_required_setting(
'LUCKYORANGE_SITE_ID',
re.compile(r'^\d+$'),
"must be (a string containing) a number",
'must be (a string containing) a number',
)
def render(self, context):

View file

@ -40,9 +40,11 @@ TRACKING_CODE = """
<noscript><p><img src="//%(url)s/matomo.php?idsite=%(siteid)s" style="border:0;" alt="" /></p></noscript>
""" # noqa
VARIABLE_CODE = '_paq.push(["setCustomVariable", %(index)s, "%(name)s", "%(value)s", "%(scope)s"]);' # noqa
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'
@ -75,23 +77,27 @@ 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', ())
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):
@ -99,15 +105,15 @@ class MatomoNode(Node):
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)
'commands': '\n '.join(commands),
}
if is_internal_ip(context, 'MATOMO'):
html = disable_html(html, 'Matomo')

View file

@ -25,7 +25,7 @@ e,d])};b.__SV=1.2}})(document,window.mixpanel||[]);
</script>
""" # noqa
IDENTIFY_CODE = "mixpanel.identify('%s');"
IDENTIFY_PROPERTIES = "mixpanel.people.set(%s);"
IDENTIFY_PROPERTIES = 'mixpanel.people.set(%s);'
EVENT_CODE = "mixpanel.track('%(name)s', %(properties)s);"
EVENT_CONTEXT_KEY = 'mixpanel_event'
@ -49,29 +49,38 @@ 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')
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),
'commands': ' '.join(commands),
}
if is_internal_ip(context, 'MIXPANEL'):
html = disable_html(html, 'Mixpanel')

View file

@ -24,16 +24,29 @@ EMAIL_CODE = "olark('api.visitor.updateEmailAddress', {{emailAddress: '{0}'}});"
EMAIL_CONTEXT_KEY = 'olark_email'
STATUS_CODE = "olark('api.chat.updateVisitorStatus', {snippet: %s});"
STATUS_CONTEXT_KEY = 'olark_status'
MESSAGE_CODE = "olark.configure('locale.%(key)s', \"%(msg)s\");"
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()
@ -56,8 +69,10 @@ 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 = []
@ -76,21 +91,22 @@ 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),
'extra_code': ' '.join(extra_code),
}
return html
def _get_nickname(self, user):
name = user.get_full_name()
if name:
return "%s (%s)" % (name, user.username)
return '%s (%s)' % (name, user.username)
else:
return user.username

View file

@ -33,8 +33,10 @@ 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}

View file

@ -56,14 +56,14 @@ 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')
if identity is not None:
html = "%s%s" % (IDENTIFY_CODE % identity, html)
html = '%s%s' % (IDENTIFY_CODE % identity, html)
if is_internal_ip(context, 'PERFORMABLE'):
html = disable_html(html, 'Performable')
return html
@ -74,10 +74,13 @@ 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):

View file

@ -48,8 +48,10 @@ 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 % {

View file

@ -24,7 +24,9 @@ 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">
@ -34,7 +36,9 @@ SETUP_CODE = """
DOMAIN_CODE = 'SnapABug.setDomain("%s");'
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");'
@ -67,21 +71,24 @@ 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)
@ -89,61 +96,70 @@ class SnapEngageNode(Node):
if email is None:
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):
if self._get_setting(
context, 'snapengage_readonly_email', 'SNAPENGAGE_READONLY_EMAIL', False
):
readonly_tail = ',true'
else:
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):
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',
'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),
'settings_code': ' '.join(settings_code),
}
return html

View file

@ -53,8 +53,8 @@ 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 = {}
@ -63,8 +63,7 @@ class SpringMetricsNode(Node):
if var.startswith('spring_metrics_'):
custom[var[15:]] = val
if 'email' not in custom:
identity = get_identity(context, 'spring_metrics',
lambda u: u.email)
identity = get_identity(context, 'spring_metrics', lambda u: u.email)
if identity is not None:
custom['email'] = identity
@ -81,9 +80,11 @@ class SpringMetricsNode(Node):
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())
return " ".join(commands)
commands.extend(
"_springMetq.push(['setdata', {'%s': '%s'}]);" % (var, val)
for var, val in params.items()
)
return ' '.join(commands)
def contribute_to_analytical(add_node):

View file

@ -48,7 +48,8 @@ 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')
@ -65,13 +66,16 @@ class UserVoiceNode(Node):
if identity:
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):

View file

@ -49,8 +49,8 @@ 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)
@ -81,8 +81,7 @@ class WoopraNode(Node):
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
return params

View file

@ -57,15 +57,17 @@ 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
'accurateTrackBounce': True,
}
if getattr(settings, 'YANDEX_METRICA_WEBVISOR', False):
options['webvisor'] = True

View file

@ -5,8 +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):
@ -19,13 +18,14 @@ def get_required_setting(setting, value_re, invalid_msg):
try:
value = getattr(settings, setting)
except AttributeError:
raise AnalyticalException("%s setting: not found" % setting)
raise AnalyticalException('%s setting: not found' % setting)
if not value:
raise AnalyticalException("%s setting is not set" % setting)
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
@ -112,6 +112,7 @@ def get_domain(context, prefix):
if domain is None:
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):
@ -162,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

@ -1,21 +1,21 @@
def setup(app):
app.add_crossref_type(
directivename="setting",
rolename="setting",
indextemplate="pair: %s; setting",
directivename='setting',
rolename='setting',
indextemplate='pair: %s; setting',
)
app.add_crossref_type(
directivename="templatetag",
rolename="ttag",
indextemplate="pair: %s; template tag"
directivename='templatetag',
rolename='ttag',
indextemplate='pair: %s; template tag',
)
app.add_crossref_type(
directivename="templatefilter",
rolename="tfilter",
indextemplate="pair: %s; template filter"
directivename='templatefilter',
rolename='tfilter',
indextemplate='pair: %s; template filter',
)
app.add_crossref_type(
directivename="fieldlookup",
rolename="lookup",
indextemplate="pair: %s; field lookup type",
directivename='fieldlookup',
rolename='lookup',
indextemplate='pair: %s; field lookup type',
)

View file

@ -29,8 +29,10 @@ pygments_style = 'sphinx'
intersphinx_mapping = {
'python': ('http://docs.python.org/3.13', None),
'django': ('http://docs.djangoproject.com/en/stable',
'http://docs.djangoproject.com/en/stable/_objects/'),
'django': (
'http://docs.djangoproject.com/en/stable',
'http://docs.djangoproject.com/en/stable/_objects/',
),
}
@ -43,6 +45,11 @@ htmlhelp_basename = 'analyticaldoc'
# -- Options for LaTeX output -----------------------------------------------
latex_documents = [
('index', 'django-analytical.tex', 'Documentation for django-analytical',
'Joost Cassee', 'manual'),
(
'index',
'django-analytical.tex',
'Documentation for django-analytical',
'Joost Cassee',
'manual',
),
]

View file

@ -12,7 +12,8 @@ register = Library()
def _location_node(location):
class DummyNode(Node):
def render(self, context):
return "<!-- dummy_%s -->" % location
return '<!-- dummy_%s -->' % location
return DummyNode
@ -25,6 +26,7 @@ def _location_tag(location):
if len(bits) > 1:
raise TemplateSyntaxError("'%s' tag takes no arguments" % bits[0])
return _location_nodes[location]
return dummy_tag

View file

@ -27,7 +27,7 @@ class AnalyticsTagTestCase(TagTestCase):
def render_location_tag(self, location, vars=None):
if vars is None:
vars = {}
t = Template("{%% load analytical %%}{%% analytical_%s %%}" % location)
t = Template('{%% load analytical %%}{%% analytical_%s %%}' % location)
return t.render(Context(vars))
def test_location_tags(self):

View file

@ -22,21 +22,25 @@ class ChartbeatTagTestCaseNoSites(TestCase):
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(
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)
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")
site = Site.objects.create(domain='test.com', name='test')
with override_settings(SITE_ID=site.id):
r = ChartbeatBottomNode().render(Context())
assert re.search('var _sf_async_config={.*"uid": "12345".*};', r)
@ -60,24 +64,36 @@ class ChartbeatTagTestCase(TagTestCase):
"""
def test_top_tag(self):
r = self.render_tag('chartbeat', 'chartbeat_top', {'chartbeat_domain': "test.com"})
r = self.render_tag(
'chartbeat', 'chartbeat_top', {'chartbeat_domain': 'test.com'}
)
assert 'var _sf_startpt=(new Date()).getTime()' in 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'}
)
assert re.search('var _sf_async_config={.*"uid": "12345".*};', r)
assert re.search('var _sf_async_config={.*"domain": "test.com".*};', r)
def test_top_node(self):
r = ChartbeatTopNode().render(Context({
'chartbeat_domain': "test.com",
}))
r = ChartbeatTopNode().render(
Context(
{
'chartbeat_domain': 'test.com',
}
)
)
assert 'var _sf_startpt=(new Date()).getTime()' in r
def test_bottom_node(self):
r = ChartbeatBottomNode().render(Context({
'chartbeat_domain': "test.com",
}))
r = ChartbeatBottomNode().render(
Context(
{
'chartbeat_domain': 'test.com',
}
)
)
assert re.search('var _sf_async_config={.*"uid": "12345".*};', r)
assert re.search('var _sf_async_config={.*"domain": "test.com".*};', r)

View file

@ -52,11 +52,17 @@ class ClickyTagTestCase(TagTestCase):
assert 'var clicky_custom = {"session": {"username":' not in r
def test_custom(self):
r = ClickyNode().render(Context({
'clicky_var1': 'val1',
'clicky_var2': 'val2',
}))
assert re.search(r'var clicky_custom = {.*"var1": "val1", "var2": "val2".*};', r)
r = ClickyNode().render(
Context(
{
'clicky_var1': 'val1',
'clicky_var2': 'val2',
}
)
)
assert re.search(
r'var clicky_custom = {.*"var1": "val1", "var2": "val2".*};', r
)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
def test_render_internal_ip(self):

View file

@ -1,6 +1,7 @@
"""
Tests for the Facebook Pixel template tags.
"""
import pytest
from django.http import HttpRequest
from django.template import Context, Template, TemplateSyntaxError
@ -39,7 +40,6 @@ expected_body_html = """\
@override_settings(FACEBOOK_PIXEL_ID='1234567890')
class FacebookPixelTagTestCase(TagTestCase):
maxDiff = None
def test_head_tag(self):
@ -60,11 +60,15 @@ class FacebookPixelTagTestCase(TagTestCase):
def test_tags_take_no_args(self):
template = '{%% load facebook_pixel %%}{%% facebook_pixel_%s "arg" %%}'
with pytest.raises(TemplateSyntaxError, match="'facebook_pixel_head' takes no arguments"):
Template(template % "head").render(Context({}))
with pytest.raises(
TemplateSyntaxError, match="'facebook_pixel_head' takes no arguments"
):
Template(template % 'head').render(Context({}))
with pytest.raises(TemplateSyntaxError, match="'facebook_pixel_body' takes no arguments"):
Template(template % "body").render(Context({}))
with pytest.raises(
TemplateSyntaxError, match="'facebook_pixel_body' takes no arguments"
):
Template(template % 'body').render(Context({}))
@override_settings(FACEBOOK_PIXEL_ID=None)
def test_no_id(self):
@ -76,9 +80,7 @@ class FacebookPixelTagTestCase(TagTestCase):
@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'$"
)
expected_pattern = r"FACEBOOK_PIXEL_ID setting: must be \(a string containing\) a number: 'invalid'$"
with pytest.raises(AnalyticalException, match=expected_pattern):
FacebookPixelHeadNode()
with pytest.raises(AnalyticalException, match=expected_pattern):
@ -91,11 +93,13 @@ class FacebookPixelTagTestCase(TagTestCase):
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)
assert _disabled(expected_head_html) == head_html

View file

@ -19,7 +19,9 @@ class GaugesTagTestCase(TagTestCase):
"""
def test_tag(self):
assert self.render_tag('gauges', 'gauges') == """
assert (
self.render_tag('gauges', 'gauges')
== """
<script type="text/javascript">
var _gauges = _gauges || [];
(function() {
@ -34,9 +36,12 @@ class GaugesTagTestCase(TagTestCase):
})();
</script>
"""
)
def test_node(self):
assert GaugesNode().render(Context()) == """
assert (
GaugesNode().render(Context())
== """
<script type="text/javascript">
var _gauges = _gauges || [];
(function() {
@ -51,6 +56,7 @@ class GaugesTagTestCase(TagTestCase):
})();
</script>
"""
)
@override_settings(GAUGES_SITE_ID=None)
def test_no_account_number(self):

View file

@ -20,8 +20,10 @@ from analytical.templatetags.google_analytics import (
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.
@ -47,15 +49,19 @@ class GoogleAnalyticsTagTestCase(TagTestCase):
with pytest.raises(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())
assert "_gaq.push(['_setDomainName', 'example.com']);" in r
assert "_gaq.push(['_setAllowHash', false]);" in 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())
assert "_gaq.push(['_setDomainName', 'example.com']);" in r
@ -63,12 +69,14 @@ class GoogleAnalyticsTagTestCase(TagTestCase):
assert "_gaq.push(['_setAllowLinker', true]);" in 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)
assert "_gaq.push(['_setCustomVar', 1, 'test1', 'foo', 3]);" in r
assert "_gaq.push(['_setCustomVar', 2, 'test2', 'bar', 1]);" in r
@ -83,10 +91,10 @@ class GoogleAnalyticsTagTestCase(TagTestCase):
def test_display_advertising(self):
with override_settings(GOOGLE_ANALYTICS_DISPLAY_ADVERTISING=False):
r = GoogleAnalyticsNode().render(Context())
assert "google-analytics.com/ga.js" in r
assert 'google-analytics.com/ga.js' in r
with override_settings(GOOGLE_ANALYTICS_DISPLAY_ADVERTISING=True):
r = GoogleAnalyticsNode().render(Context())
assert "stats.g.doubleclick.net/dc.js" in r
assert 'stats.g.doubleclick.net/dc.js' in r
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
def test_render_internal_ip(self):
@ -185,10 +193,12 @@ class GoogleAnalyticsTagTestCase(TagTestCase):
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

@ -64,21 +64,29 @@ class GoogleAnalyticsTagTestCase(TagTestCase):
The user_id variable must be set according to
google_analytics_gtag_identity variable in the context.
"""
r = GoogleAnalyticsGTagNode().render(Context({
'google_analytics_gtag_identity': 'foo_gtag_identity',
'analytical_identity': 'bar_analytical_identity',
'user': User(username='test'),
}))
r = GoogleAnalyticsGTagNode().render(
Context(
{
'google_analytics_gtag_identity': 'foo_gtag_identity',
'analytical_identity': 'bar_analytical_identity',
'user': User(username='test'),
}
)
)
assert "gtag('set', {'user_id': 'foo_gtag_identity'});" in r
def test_identity_context_general(self):
"""
The user_id variable must be set according to analytical_identity variable in the context.
"""
r = GoogleAnalyticsGTagNode().render(Context({
'analytical_identity': 'bar_analytical_identity',
'user': User(username='test'),
}))
r = GoogleAnalyticsGTagNode().render(
Context(
{
'analytical_identity': 'bar_analytical_identity',
'user': User(username='test'),
}
)
)
assert "gtag('set', {'user_id': 'bar_analytical_identity'});" in r
@override_settings(GOOGLE_ANALYTICS_GTAG_PROPERTY_ID='G-12345678')

View file

@ -17,8 +17,10 @@ from analytical.templatetags.google_analytics_js import (
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.
@ -26,19 +28,25 @@ class GoogleAnalyticsTagTestCase(TagTestCase):
def test_tag(self):
r = self.render_tag('google_analytics_js', 'google_analytics_js')
assert """(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
assert (
"""(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
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');"""
in r
)
assert "ga('create', 'UA-123456-7', 'auto', {});" in r
assert "ga('send', 'pageview');" in r
def test_node(self):
r = GoogleAnalyticsJsNode().render(Context())
assert """(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
assert (
"""(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
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');"""
in r
)
assert "ga('create', 'UA-123456-7', 'auto', {});" in r
assert "ga('send', 'pageview');" in r
@ -52,27 +60,36 @@ m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
with pytest.raises(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())
assert """ga('create', 'UA-123456-7', 'auto', {"legacyCookieDomain": "example.com"}""" in r
assert (
"""ga('create', 'UA-123456-7', 'auto', {"legacyCookieDomain": "example.com"}"""
in 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())
assert "ga('create', 'UA-123456-7', 'auto', {" in r
assert '"legacyCookieDomain": "example.com"' in r
assert '"allowLinker\": true' in r
assert '"allowLinker": true' in 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)
assert "ga('set', 'test1', 'foo');" in r
assert "ga('set', 'test2', 'bar');" in r
@ -82,9 +99,12 @@ 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())
assert """ga('create', 'UA-123456-7', 'auto', {});
assert (
"""ga('create', 'UA-123456-7', 'auto', {});
ga('require', 'displayfeatures');
ga('send', 'pageview');""" in r
ga('send', 'pageview');"""
in r
)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
def test_render_internal_ip(self):
@ -92,8 +112,7 @@ ga('send', 'pageview');""" in r
req.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': req})
r = GoogleAnalyticsJsNode().render(context)
assert r.startswith(
'<!-- Google Analytics disabled on internal IP address')
assert r.startswith('<!-- Google Analytics disabled on internal IP address')
assert r.endswith('-->')
@override_settings(GOOGLE_ANALYTICS_ANONYMIZE_IP=True)
@ -131,12 +150,17 @@ ga('send', 'pageview');""" in r
@override_settings(GOOGLE_ANALYTICS_SITE_SPEED_SAMPLE_RATE=0.0)
def test_set_site_speed_sample_rate_min(self):
r = GoogleAnalyticsJsNode().render(Context())
assert """ga('create', 'UA-123456-7', 'auto', {"siteSpeedSampleRate": 0});""" in r
assert (
"""ga('create', 'UA-123456-7', 'auto', {"siteSpeedSampleRate": 0});""" in r
)
@override_settings(GOOGLE_ANALYTICS_SITE_SPEED_SAMPLE_RATE='100.00')
def test_set_site_speed_sample_rate_max(self):
r = GoogleAnalyticsJsNode().render(Context())
assert """ga('create', 'UA-123456-7', 'auto', {"siteSpeedSampleRate": 100});""" in r
assert (
"""ga('create', 'UA-123456-7', 'auto', {"siteSpeedSampleRate": 100});"""
in r
)
@override_settings(GOOGLE_ANALYTICS_SITE_SPEED_SAMPLE_RATE=-1)
def test_exception_whenset_site_speed_sample_rate_too_small(self):
@ -167,10 +191,12 @@ ga('send', 'pageview');""" in r
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

@ -39,17 +39,25 @@ class GoSquaredTagTestCase(TagTestCase):
@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'),
}
)
)
assert 'GoSquared.UserName = "Test User";' in 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',
}
)
)
assert 'GoSquared.UserName = "test_identity";' in r
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)

View file

@ -20,11 +20,11 @@ class HeapTagTestCase(TagTestCase):
def test_tag(self):
r = self.render_tag('heap', 'heap')
assert "123456789" in r
assert '123456789' in r
def test_node(self):
r = HeapNode().render(Context({}))
assert "123456789" in r
assert '123456789' in r
def test_tags_take_no_args(self):
with pytest.raises(TemplateSyntaxError, match="'heap' takes no arguments"):

View file

@ -1,6 +1,7 @@
"""
Tests for the Hotjar template tags.
"""
import pytest
from django.http import HttpRequest
from django.template import Context, Template, TemplateSyntaxError
@ -27,7 +28,6 @@ expected_html = """\
@override_settings(HOTJAR_SITE_ID='123456789')
class HotjarTagTestCase(TagTestCase):
maxDiff = None
def test_tag(self):
@ -44,13 +44,14 @@ class HotjarTagTestCase(TagTestCase):
@override_settings(HOTJAR_SITE_ID=None)
def test_no_id(self):
with pytest.raises(AnalyticalException, match="HOTJAR_SITE_ID setting is not set"):
with pytest.raises(
AnalyticalException, match='HOTJAR_SITE_ID setting is not set'
):
HotjarNode()
@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'$")
expected_pattern = r"^HOTJAR_SITE_ID setting: must be \(a string containing\) a number: 'invalid'$"
with pytest.raises(AnalyticalException, match=expected_pattern):
HotjarNode()
@ -61,11 +62,13 @@ class HotjarTagTestCase(TagTestCase):
context = Context({'request': request})
actual_html = HotjarNode().render(context)
disabled_html = '\n'.join([
disabled_html = '\n'.join(
[
'<!-- Hotjar disabled on internal IP address',
expected_html,
'-->',
])
]
)
assert disabled_html == actual_html
def test_contribute_to_analytical(self):

View file

@ -15,7 +15,7 @@ from analytical.templatetags.intercom import IntercomNode, intercom_user_hash
from analytical.utils import AnalyticalException
@override_settings(INTERCOM_APP_ID="abc123xyz")
@override_settings(INTERCOM_APP_ID='abc123xyz')
class IntercomTagTestCase(TagTestCase):
"""
Tests for the ``intercom`` template tag.
@ -23,7 +23,9 @@ class IntercomTagTestCase(TagTestCase):
def test_tag(self):
rendered_tag = self.render_tag('intercom', 'intercom')
assert rendered_tag.strip().startswith('<script id="IntercomSettingsScriptTag">')
assert rendered_tag.strip().startswith(
'<script id="IntercomSettingsScriptTag">'
)
def test_node(self):
now = datetime.datetime(2014, 4, 9, 15, 15, 0)
@ -31,17 +33,21 @@ class IntercomTagTestCase(TagTestCase):
username='test',
first_name='Firstname',
last_name='Lastname',
email="test@example.com",
email='test@example.com',
date_joined=now,
)
rendered_tag = IntercomNode().render(Context({'user': user}))
# Because the json isn't predictably ordered, we can't just test the whole thing verbatim.
assert rendered_tag == """
assert (
rendered_tag
== """
<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} # noqa
"""
% {'user_id': user.pk}
) # noqa
@override_settings(INTERCOM_APP_ID=None)
def test_no_account_number(self):
@ -59,32 +65,40 @@ class IntercomTagTestCase(TagTestCase):
username='test',
first_name='Firstname',
last_name='Lastname',
email="test@example.com",
email='test@example.com',
date_joined=now,
)
r = IntercomNode().render(Context({
'user': user,
}))
r = IntercomNode().render(
Context(
{
'user': user,
}
)
)
assert (
'window.intercomSettings = {"app_id": "abc123xyz", "created_at": 1397074500, '
f'"email": "test@example.com", "name": "Firstname Lastname", "user_id": {user.pk}}};'
) in 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'})
)
assert '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"),
}))
r = IntercomNode().render(
Context(
{
'user': User(
username='test',
first_name='Firstname',
last_name='Lastname',
email='test@example.com',
),
}
)
)
assert '"email": "test@example.com", "name": "Firstname Lastname"' in r
def test_identify_username_no_email(self):
@ -92,17 +106,25 @@ class IntercomTagTestCase(TagTestCase):
assert '"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'),
}
)
)
assert '"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'),
}
)
)
assert '"email": "explicit"' in r, r
@override_settings(INTERCOM_HMAC_SECRET_KEY='secret')
@ -135,10 +157,14 @@ class IntercomTagTestCase(TagTestCase):
"""
'user_hash' of context-provided `user_id`.
"""
attrs = IntercomNode()._get_custom_attrs(Context({
'intercom_email': 'test@example.com',
'intercom_user_id': '5',
}))
attrs = IntercomNode()._get_custom_attrs(
Context(
{
'intercom_email': 'test@example.com',
'intercom_user_id': '5',
}
)
)
assert attrs == {
'created_at': None,
'email': 'test@example.com',
@ -152,9 +178,13 @@ class IntercomTagTestCase(TagTestCase):
"""
'user_hash' of context-provided `email`.
"""
attrs = IntercomNode()._get_custom_attrs(Context({
'intercom_email': 'test@example.com',
}))
attrs = IntercomNode()._get_custom_attrs(
Context(
{
'intercom_email': 'test@example.com',
}
)
)
assert attrs == {
'created_at': None,
'email': 'test@example.com',

View file

@ -20,11 +20,11 @@ class KissInsightsTagTestCase(TagTestCase):
def test_tag(self):
r = self.render_tag('kiss_insights', 'kiss_insights')
assert "//s3.amazonaws.com/ki.js/12345/abc.js" in r
assert '//s3.amazonaws.com/ki.js/12345/abc.js' in r
def test_node(self):
r = KissInsightsNode().render(Context())
assert "//s3.amazonaws.com/ki.js/12345/abc.js" in r
assert '//s3.amazonaws.com/ki.js/12345/abc.js' in r
@override_settings(KISS_INSIGHTS_ACCOUNT_NUMBER=None)
def test_no_account_number(self):

View file

@ -21,11 +21,17 @@ class KissMetricsTagTestCase(TagTestCase):
def test_tag(self):
r = self.render_tag('kiss_metrics', 'kiss_metrics')
assert "//doug1izaerwt3.cloudfront.net/0123456789abcdef0123456789abcdef01234567.1.js" in r
assert (
'//doug1izaerwt3.cloudfront.net/0123456789abcdef0123456789abcdef01234567.1.js'
in r
)
def test_node(self):
r = KissMetricsNode().render(Context())
assert "//doug1izaerwt3.cloudfront.net/0123456789abcdef0123456789abcdef01234567.1.js" in r
assert (
'//doug1izaerwt3.cloudfront.net/0123456789abcdef0123456789abcdef01234567.1.js'
in r
)
@override_settings(KISS_METRICS_API_KEY=None)
def test_no_api_key(self):
@ -53,22 +59,37 @@ class KissMetricsTagTestCase(TagTestCase):
assert "_kmq.push(['identify', " not in r
def test_event(self):
r = KissMetricsNode().render(Context({
'kiss_metrics_event': ('test_event', {'prop1': 'val1', 'prop2': 'val2'}),
}))
r = KissMetricsNode().render(
Context(
{
'kiss_metrics_event': (
'test_event',
{'prop1': 'val1', 'prop2': 'val2'},
),
}
)
)
assert "_kmq.push(['record', 'test_event', "
'{"prop1": "val1", "prop2": "val2"}]);' in r
def test_property(self):
r = KissMetricsNode().render(Context({
'kiss_metrics_properties': {'prop1': 'val1', 'prop2': 'val2'},
}))
r = KissMetricsNode().render(
Context(
{
'kiss_metrics_properties': {'prop1': 'val1', 'prop2': 'val2'},
}
)
)
assert '_kmq.push([\'set\', {"prop1": "val1", "prop2": "val2"}]);' in 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'},
}
)
)
assert "_kmq.push(['alias', 'test', 'test_alias']);" in r
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])

View file

@ -1,6 +1,7 @@
"""
Tests for the Lucky Orange template tags.
"""
import pytest
from django.http import HttpRequest
from django.template import Context, Template, TemplateSyntaxError
@ -25,7 +26,6 @@ window.__lo_site_id = 123456;
@override_settings(LUCKYORANGE_SITE_ID='123456')
class LuckyOrangeTagTestCase(TagTestCase):
maxDiff = None
def test_tag(self):
@ -37,18 +37,23 @@ class LuckyOrangeTagTestCase(TagTestCase):
assert expected_html == html
def test_tags_take_no_args(self):
with pytest.raises(TemplateSyntaxError, match="'luckyorange' takes no arguments"):
Template('{% load luckyorange %}{% luckyorange "arg" %}').render(Context({}))
with pytest.raises(
TemplateSyntaxError, match="'luckyorange' takes no arguments"
):
Template('{% load luckyorange %}{% luckyorange "arg" %}').render(
Context({})
)
@override_settings(LUCKYORANGE_SITE_ID=None)
def test_no_id(self):
with pytest.raises(AnalyticalException, match="LUCKYORANGE_SITE_ID setting is not set"):
with pytest.raises(
AnalyticalException, match='LUCKYORANGE_SITE_ID setting is not set'
):
LuckyOrangeNode()
@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'$")
expected_pattern = r"^LUCKYORANGE_SITE_ID setting: must be \(a string containing\) a number: 'invalid'$"
with pytest.raises(AnalyticalException, match=expected_pattern):
LuckyOrangeNode()
@ -59,11 +64,13 @@ class LuckyOrangeTagTestCase(TagTestCase):
context = Context({'request': request})
actual_html = LuckyOrangeNode().render(context)
disabled_html = '\n'.join([
disabled_html = '\n'.join(
[
'<!-- Lucky Orange disabled on internal IP address',
expected_html,
'-->',
])
]
)
assert disabled_html == actual_html
def test_contribute_to_analytical(self):

View file

@ -31,20 +31,19 @@ class MatomoTagTestCase(TagTestCase):
assert "_paq.push(['setSiteId', 345]);" in r
assert 'img src="//example.com/matomo.php?idsite=345"' in 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')
assert '"//example.com/matomo/"' in 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')
assert '"//example.com:1234/";' in 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')
assert '"//example.com:1234/matomo/"' in r
@ -104,46 +103,54 @@ class MatomoTagTestCase(TagTestCase):
assert r.endswith('-->')
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)
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"]);']:
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"]);',
]:
assert var_code in 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)
var_code = '_paq.push(["setUserId", "BDFL"]);'
assert var_code in r
def test_matomo_usertrack(self):
context = Context({
'matomo_identity': 'BDFL'
})
context = Context({'matomo_identity': 'BDFL'})
r = MatomoNode().render(context)
var_code = '_paq.push(["setUserId", "BDFL"]);'
assert var_code in r
def test_analytical_usertrack(self):
context = Context({
'analytical_identity': 'BDFL'
})
context = Context({'analytical_identity': 'BDFL'})
r = MatomoNode().render(context)
var_code = '_paq.push(["setUserId", "BDFL"]);'
assert var_code in 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)
var_code = '_paq.push(["setUserId", "BDFL"]);'
assert var_code not in r

View file

@ -50,12 +50,19 @@ class MixpanelTagTestCase(TagTestCase):
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify_anonymous_user(self):
r = MixpanelNode().render(Context({'user': AnonymousUser()}))
assert "mixpanel.register_once({distinct_id:" not in r
assert 'mixpanel.register_once({distinct_id:' not in r
def test_event(self):
r = MixpanelNode().render(Context({
'mixpanel_event': ('test_event', {'prop1': 'val1', 'prop2': 'val2'}),
}))
r = MixpanelNode().render(
Context(
{
'mixpanel_event': (
'test_event',
{'prop1': 'val1', 'prop2': 'val2'},
),
}
)
)
assert "mixpanel.track('test_event', "
'{"prop1": "val1", "prop2": "val2"});' in r

View file

@ -38,10 +38,17 @@ class OlarkTestCase(TagTestCase):
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify(self):
r = OlarkNode().render(Context({
'user': User(username='test', first_name='Test', last_name='User'),
}))
assert "olark('api.chat.updateVisitorNickname', {snippet: 'Test User (test)'});" in r
r = OlarkNode().render(
Context(
{
'user': User(username='test', first_name='Test', last_name='User'),
}
)
)
assert (
"olark('api.chat.updateVisitorNickname', {snippet: 'Test User (test)'});"
in r
)
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify_anonymous_user(self):
@ -58,37 +65,41 @@ class OlarkTestCase(TagTestCase):
'{snippet: "teststatus"});' in r
def test_status_string_list(self):
r = OlarkNode().render(Context({
'olark_status': ['teststatus1', 'teststatus2'],
}))
r = OlarkNode().render(
Context(
{
'olark_status': ['teststatus1', 'teststatus2'],
}
)
)
assert "olark('api.chat.updateVisitorStatus', "
'{snippet: ["teststatus1", "teststatus2"]});' in r
def test_messages(self):
messages = [
"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',
]
vars = {f'olark_{m}': m for m in messages}
r = OlarkNode().render(Context(vars))
for m in messages:
assert f"olark.configure('locale.{m}', \"{m}\");" in r
assert f'olark.configure(\'locale.{m}\', "{m}");' in r

View file

@ -20,11 +20,11 @@ class RatingMailruTagTestCase(TagTestCase):
def test_tag(self):
r = self.render_tag('rating_mailru', 'rating_mailru')
assert "counter?id=1234567;js=na" in r
assert 'counter?id=1234567;js=na' in r
def test_node(self):
r = RatingMailruNode().render(Context({}))
assert "counter?id=1234567;js=na" in r
assert 'counter?id=1234567;js=na' in r
@override_settings(RATING_MAILRU_COUNTER_ID=None)
def test_no_site_id(self):

View file

@ -29,7 +29,7 @@ WIDGET_ID = 'ec329c69-0bf0-4db8-9b77-3f8150fb977e'
SNAPENGAGE_WIDGET_ID=WIDGET_ID,
SNAPENGAGE_BUTTON=BUTTON_STYLE_DEFAULT,
SNAPENGAGE_BUTTON_LOCATION=BUTTON_LOCATION_LEFT,
SNAPENGAGE_BUTTON_OFFSET="55%",
SNAPENGAGE_BUTTON_OFFSET='55%',
)
class SnapEngageTestCase(TagTestCase):
"""
@ -38,11 +38,15 @@ class SnapEngageTestCase(TagTestCase):
def test_tag(self):
r = self.render_tag('snapengage', 'snapengage')
assert 'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","0","55%");' in r
assert (
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","0","55%");' in r
)
def test_node(self):
r = SnapEngageNode().render(Context())
assert 'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","0","55%");' in r
assert (
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","0","55%");' in r
)
@override_settings(SNAPENGAGE_WIDGET_ID=None)
def test_no_site_id(self):
@ -55,142 +59,220 @@ class SnapEngageTestCase(TagTestCase):
SnapEngageNode()
def test_no_button(self):
r = SnapEngageNode().render(Context({
'snapengage_button': BUTTON_STYLE_NONE,
}))
r = SnapEngageNode().render(
Context(
{
'snapengage_button': BUTTON_STYLE_NONE,
}
)
)
assert 'SnapABug.init("ec329c69-0bf0-4db8-9b77-3f8150fb977e")' in r
with override_settings(SNAPENGAGE_BUTTON=BUTTON_STYLE_NONE):
r = SnapEngageNode().render(Context())
assert 'SnapABug.init("ec329c69-0bf0-4db8-9b77-3f8150fb977e")' in r
def test_live_button(self):
r = SnapEngageNode().render(Context({
'snapengage_button': BUTTON_STYLE_LIVE,
}))
assert 'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","0","55%",true);' in r
r = SnapEngageNode().render(
Context(
{
'snapengage_button': BUTTON_STYLE_LIVE,
}
)
)
assert (
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","0","55%",true);'
in r
)
with override_settings(SNAPENGAGE_BUTTON=BUTTON_STYLE_LIVE):
r = SnapEngageNode().render(Context())
assert 'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","0","55%",true);' in r
assert (
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","0","55%",true);'
in r
)
def test_custom_button(self):
r = SnapEngageNode().render(Context({
'snapengage_button': "http://www.example.com/button.png",
}))
assert 'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","0","55%");' in r
r = SnapEngageNode().render(
Context(
{
'snapengage_button': 'http://www.example.com/button.png',
}
)
)
assert (
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","0","55%");' in r
)
assert 'SnapABug.setButton("http://www.example.com/button.png");' in r
with override_settings(
SNAPENGAGE_BUTTON="http://www.example.com/button.png"):
with override_settings(SNAPENGAGE_BUTTON='http://www.example.com/button.png'):
r = SnapEngageNode().render(Context())
assert 'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","0","55%");' in r
assert (
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","0","55%");'
in r
)
assert 'SnapABug.setButton("http://www.example.com/button.png");' in r
def test_button_location_right(self):
r = SnapEngageNode().render(Context({
'snapengage_button_location': BUTTON_LOCATION_RIGHT,
}))
assert 'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","1","55%");' in r
r = SnapEngageNode().render(
Context(
{
'snapengage_button_location': BUTTON_LOCATION_RIGHT,
}
)
)
assert (
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","1","55%");' in r
)
with override_settings(SNAPENGAGE_BUTTON_LOCATION=BUTTON_LOCATION_RIGHT):
r = SnapEngageNode().render(Context())
assert 'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","1","55%");' in r
assert (
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","1","55%");'
in r
)
def test_button_location_top(self):
r = SnapEngageNode().render(Context({
'snapengage_button_location': BUTTON_LOCATION_TOP,
}))
assert 'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","2","55%");' in r
r = SnapEngageNode().render(
Context(
{
'snapengage_button_location': BUTTON_LOCATION_TOP,
}
)
)
assert (
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","2","55%");' in r
)
with override_settings(SNAPENGAGE_BUTTON_LOCATION=BUTTON_LOCATION_TOP):
r = SnapEngageNode().render(Context())
assert 'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","2","55%");' in r
assert (
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","2","55%");'
in r
)
def test_button_location_bottom(self):
r = SnapEngageNode().render(Context({
'snapengage_button_location': BUTTON_LOCATION_BOTTOM,
}))
assert 'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","3","55%");' in r
with override_settings(
SNAPENGAGE_BUTTON_LOCATION=BUTTON_LOCATION_BOTTOM):
r = SnapEngageNode().render(
Context(
{
'snapengage_button_location': BUTTON_LOCATION_BOTTOM,
}
)
)
assert (
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","3","55%");' in r
)
with override_settings(SNAPENGAGE_BUTTON_LOCATION=BUTTON_LOCATION_BOTTOM):
r = SnapEngageNode().render(Context())
assert 'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","3","55%");' in r
assert (
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","3","55%");'
in r
)
def test_button_offset(self):
r = SnapEngageNode().render(Context({
'snapengage_button_location_offset': "30%",
}))
assert 'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","0","30%");' in r
with override_settings(SNAPENGAGE_BUTTON_LOCATION_OFFSET="30%"):
r = SnapEngageNode().render(
Context(
{
'snapengage_button_location_offset': '30%',
}
)
)
assert (
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","0","30%");' in r
)
with override_settings(SNAPENGAGE_BUTTON_LOCATION_OFFSET='30%'):
r = SnapEngageNode().render(Context())
assert 'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","0","30%");' in r
assert (
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","0","30%");'
in r
)
def test_button_effect(self):
r = SnapEngageNode().render(Context({
'snapengage_button_effect': "-4px",
}))
r = SnapEngageNode().render(
Context(
{
'snapengage_button_effect': '-4px',
}
)
)
assert 'SnapABug.setButtonEffect("-4px");' in r
with override_settings(SNAPENGAGE_BUTTON_EFFECT="-4px"):
with override_settings(SNAPENGAGE_BUTTON_EFFECT='-4px'):
r = SnapEngageNode().render(Context())
assert 'SnapABug.setButtonEffect("-4px");' in 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,
}
)
)
assert 'SnapABug.setChatFormPosition("tl");' in r
with override_settings(SNAPENGAGE_FORM_POSITION=FORM_POSITION_TOP_LEFT):
r = SnapEngageNode().render(Context())
assert 'SnapABug.setChatFormPosition("tl");' in r
def test_form_top_position(self):
r = SnapEngageNode().render(Context({
'snapengage_form_top_position': 40,
}))
r = SnapEngageNode().render(
Context(
{
'snapengage_form_top_position': 40,
}
)
)
assert 'SnapABug.setFormTopPosition(40);' in r
with override_settings(SNAPENGAGE_FORM_TOP_POSITION=40):
r = SnapEngageNode().render(Context())
assert 'SnapABug.setFormTopPosition(40);' in r
def test_domain(self):
r = SnapEngageNode().render(Context({
'snapengage_domain': "example.com"}))
r = SnapEngageNode().render(Context({'snapengage_domain': 'example.com'}))
assert 'SnapABug.setDomain("example.com");' in r
with override_settings(SNAPENGAGE_DOMAIN="example.com"):
with override_settings(SNAPENGAGE_DOMAIN='example.com'):
r = SnapEngageNode().render(Context())
assert 'SnapABug.setDomain("example.com");' in r
def test_secure_connection(self):
r = SnapEngageNode().render(Context({
'snapengage_secure_connection': True}))
r = SnapEngageNode().render(Context({'snapengage_secure_connection': True}))
assert 'SnapABug.setSecureConnexion();' in r
with override_settings(SNAPENGAGE_SECURE_CONNECTION=True):
r = SnapEngageNode().render(Context())
assert 'SnapABug.setSecureConnexion();' in r
def test_show_offline(self):
r = SnapEngageNode().render(Context({
'snapengage_show_offline': False,
}))
r = SnapEngageNode().render(
Context(
{
'snapengage_show_offline': False,
}
)
)
assert 'SnapABug.allowOffline(false);' in r
with override_settings(SNAPENGAGE_SHOW_OFFLINE=False):
r = SnapEngageNode().render(Context())
assert 'SnapABug.allowOffline(false);' in r
def test_proactive_chat(self):
r = SnapEngageNode().render(Context({
'snapengage_proactive_chat': False}))
r = SnapEngageNode().render(Context({'snapengage_proactive_chat': False}))
assert 'SnapABug.allowProactiveChat(false);' in r
def test_screenshot(self):
r = SnapEngageNode().render(Context({
'snapengage_screenshots': False,
}))
r = SnapEngageNode().render(
Context(
{
'snapengage_screenshots': False,
}
)
)
assert 'SnapABug.allowScreenshot(false);' in r
with override_settings(SNAPENGAGE_SCREENSHOTS=False):
r = SnapEngageNode().render(Context())
assert 'SnapABug.allowScreenshot(false);' in r
def test_offline_screenshots(self):
r = SnapEngageNode().render(Context({
'snapengage_offline_screenshots': False,
}))
r = SnapEngageNode().render(
Context(
{
'snapengage_offline_screenshots': False,
}
)
)
assert 'SnapABug.showScreenshotOption(false);' in r
with override_settings(SNAPENGAGE_OFFLINE_SCREENSHOTS=False):
r = SnapEngageNode().render(Context())
@ -205,35 +287,55 @@ class SnapEngageTestCase(TagTestCase):
@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',
}
)
)
assert 'SnapABug.setUserEmail("test@example.com");' in 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,
}
)
)
assert 'SnapABug.setUserEmail("test@example.com",true);' in 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',
}
)
)
assert 'SnapABug.setUserEmail("test@example.com",true);' in 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'),
}
)
)
assert 'SnapABug.setUserEmail("test@example.com");' in r
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify_anonymous_user(self):
r = SnapEngageNode().render(Context({
'user': AnonymousUser(),
}))
r = SnapEngageNode().render(
Context(
{
'user': AnonymousUser(),
}
)
)
assert 'SnapABug.setUserEmail(' not in r
def test_language(self):

View file

@ -39,9 +39,13 @@ class SpringMetricsTagTestCase(TagTestCase):
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify(self):
r = SpringMetricsNode().render(Context({
'user': User(email='test@test.com'),
}))
r = SpringMetricsNode().render(
Context(
{
'user': User(email='test@test.com'),
}
)
)
assert "_springMetq.push(['setdata', {'email': 'test@test.com'}]);" in r
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
@ -50,10 +54,14 @@ class SpringMetricsTagTestCase(TagTestCase):
assert "_springMetq.push(['setdata', {'email':" not in 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',
}
)
)
assert "_springMetq.push(['setdata', {'var1': 'val1'}]);" in r
assert "_springMetq.push(['setdata', {'var2': 'val2'}]);" in r

View file

@ -19,11 +19,11 @@ class UserVoiceTagTestCase(TagTestCase):
def test_node(self):
r = UserVoiceNode().render(Context())
assert "widget.uservoice.com/abcdefghijklmnopqrst.js" in r
assert 'widget.uservoice.com/abcdefghijklmnopqrst.js' in r
def test_tag(self):
r = self.render_tag('uservoice', 'uservoice')
assert "widget.uservoice.com/abcdefghijklmnopqrst.js" in r
assert 'widget.uservoice.com/abcdefghijklmnopqrst.js' in r
@override_settings(USERVOICE_WIDGET_KEY=None)
def test_no_key(self):
@ -43,7 +43,7 @@ class UserVoiceTagTestCase(TagTestCase):
def test_overridden_key(self):
vars = {'uservoice_widget_key': 'defghijklmnopqrstuvw'}
r = UserVoiceNode().render(Context(vars))
assert "widget.uservoice.com/defghijklmnopqrstuvw.js" in r
assert 'widget.uservoice.com/defghijklmnopqrstuvw.js' in r
@override_settings(USERVOICE_WIDGET_OPTIONS={'key1': 'val1'})
def test_options(self):

View file

@ -40,23 +40,35 @@ class WoopraTagTestCase(TagTestCase):
@override_settings(WOOPRA_IDLE_TIMEOUT=1234)
def test_idle_timeout(self):
r = WoopraNode().render(Context({}))
assert 'var woo_settings = {"domain": "example.com", "idle_timeout": "1234"};' in r
assert (
'var woo_settings = {"domain": "example.com", "idle_timeout": "1234"};' in 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',
}
)
)
assert 'var woo_visitor = {"var1": "val1", "var2": "val2"};' in 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"),
}))
r = WoopraNode().render(
Context(
{
'user': User(
username='test',
first_name='Firstname',
last_name='Lastname',
email='test@example.com',
),
}
)
)
assert 'var woo_visitor = '
'{"email": "test@example.com", "name": "Firstname Lastname"};' in r
@ -67,18 +79,26 @@ class WoopraTagTestCase(TagTestCase):
@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'),
}
)
)
assert 'var woo_visitor = {"name": "explicit"};' in 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'),
}
)
)
assert 'var woo_visitor = {"email": "explicit"};' in r
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)

View file

@ -2,7 +2,6 @@
Tests for the Yandex.Metrica template tags and filters.
"""
import pytest
from django.http import HttpRequest
from django.template import Context
@ -21,11 +20,11 @@ class YandexMetricaTagTestCase(TagTestCase):
def test_tag(self):
r = self.render_tag('yandex_metrica', 'yandex_metrica')
assert "w.yaCounter12345678 = new Ya.Metrika" in r
assert 'w.yaCounter12345678 = new Ya.Metrika' in r
def test_node(self):
r = YandexMetricaNode().render(Context({}))
assert "w.yaCounter12345678 = new Ya.Metrika" in r
assert 'w.yaCounter12345678 = new Ya.Metrika' in r
@override_settings(YANDEX_METRICA_COUNTER_ID=None)
def test_no_site_id(self):

View file

@ -21,15 +21,14 @@ from analytical.utils import (
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 pytest.raises(AnalyticalException, match="USER_ID setting is not set"):
get_required_setting("USER_ID", r"\d+", "invalid USER_ID")
with pytest.raises(AnalyticalException, match='USER_ID setting is not set'):
get_required_setting('USER_ID', r'\d+', 'invalid USER_ID')
class MyUser(AbstractBaseUser):
@ -47,20 +46,30 @@ class GetIdentityTestCase(TestCase):
assert get_id == 'fake_id'
def test_custom_identity_specific_provider(self):
get_id = get_identity(Context({
'foo_provider_identity': 'bar',
'analytical_identity': 'baz',
}), prefix='foo_provider')
get_id = get_identity(
Context(
{
'foo_provider_identity': 'bar',
'analytical_identity': 'baz',
}
),
prefix='foo_provider',
)
assert get_id == 'bar'
def test_custom_identity_general(self):
get_id = get_identity(Context({
'analytical_identity': 'baz',
}), prefix='foo_provider')
get_id = get_identity(
Context(
{
'analytical_identity': 'baz',
}
),
prefix='foo_provider',
)
assert get_id == 'baz'
@override_settings(ANALYTICAL_DOMAIN="example.org")
@override_settings(ANALYTICAL_DOMAIN='example.org')
class GetDomainTestCase(TestCase):
def test_get_service_domain_from_context(self):
context = Context({'test_domain': 'example.com'})
@ -70,7 +79,7 @@ class GetDomainTestCase(TestCase):
context = Context({'analytical_domain': 'example.com'})
assert get_domain(context, 'test') == 'example.com'
@override_settings(TEST_DOMAIN="example.net")
@override_settings(TEST_DOMAIN='example.net')
def test_get_service_domain_from_settings(self):
context = Context()
assert get_domain(context, 'test') == 'example.net'
@ -92,7 +101,6 @@ class GetDomainTestCase(TestCase):
class InternalIpTestCase(TestCase):
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
def test_render_no_internal_ip(self):
context = Context()

View file

@ -16,7 +16,7 @@ class TagTestCase(TestCase):
def render_tag(self, library, tag, vars=None, request=None):
if vars is None:
vars = {}
t = Template("{%% load %s %%}{%% %s %%}" % (library, tag))
t = Template('{%% load %s %%}{%% %s %%}' % (library, tag))
if request is not None:
context = RequestContext(request, vars)
else: