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]] self.nodes = [node_cls() for node_cls in template_nodes[location]]
def render(self, context): 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(): def _load_template_nodes():
@ -82,14 +82,15 @@ def _load_template_nodes():
except AnalyticalException as e: except AnalyticalException as e:
logger.debug("not loading tags from '%s': %s", path, e) logger.debug("not loading tags from '%s': %s", path, e)
for location in TAG_LOCATIONS: for location in TAG_LOCATIONS:
template_nodes[location] = sum((template_nodes[location][p] template_nodes[location] = sum(
for p in TAG_POSITIONS), []) (template_nodes[location][p] for p in TAG_POSITIONS), []
)
return template_nodes return template_nodes
def _import_tag_module(path): def _import_tag_module(path):
app_name, lib_name = path.rsplit('.', 1) app_name, lib_name = path.rsplit('.', 1)
return import_module("%s.templatetags.%s" % (app_name, lib_name)) return import_module('%s.templatetags.%s' % (app_name, lib_name))
template_nodes = _load_template_nodes() 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 from analytical.utils import disable_html, get_required_setting, is_internal_ip
USER_ID_RE = re.compile(r'^\d+$') 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 = """ SETUP_CODE = """
<script type="text/javascript"> <script type="text/javascript">
var _sf_async_config=%(config)s; var _sf_async_config=%(config)s;
@ -55,7 +57,7 @@ def chartbeat_top(parser, token):
class ChartbeatTopNode(Node): class ChartbeatTopNode(Node):
def render(self, context): def render(self, context):
if is_internal_ip(context): if is_internal_ip(context):
return disable_html(INIT_CODE, "Chartbeat") return disable_html(INIT_CODE, 'Chartbeat')
return INIT_CODE return INIT_CODE
@ -76,8 +78,9 @@ def chartbeat_bottom(parser, token):
class ChartbeatBottomNode(Node): class ChartbeatBottomNode(Node):
def __init__(self): def __init__(self):
self.user_id = get_required_setting('CHARTBEAT_USER_ID', USER_ID_RE, self.user_id = get_required_setting(
"must be (a string containing) a number") 'CHARTBEAT_USER_ID', USER_ID_RE, 'must be (a string containing) a number'
)
def render(self, context): def render(self, context):
config = {'uid': self.user_id} config = {'uid': self.user_id}
@ -106,6 +109,7 @@ def _get_domain(context):
return return
elif getattr(settings, 'CHARTBEAT_AUTO_DOMAIN', True): elif getattr(settings, 'CHARTBEAT_AUTO_DOMAIN', True):
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
try: try:
return Site.objects.get_current().domain return Site.objects.get_current().domain
except (ImproperlyConfigured, Site.DoesNotExist): # pylint: disable=E1101 except (ImproperlyConfigured, Site.DoesNotExist): # pylint: disable=E1101

View file

@ -42,9 +42,11 @@ def clickmap(parser, token):
class ClickmapNode(Node): class ClickmapNode(Node):
def __init__(self): def __init__(self):
self.tracker_id = get_required_setting('CLICKMAP_TRACKER_ID', self.tracker_id = get_required_setting(
CLICKMAP_TRACKER_ID_RE, 'CLICKMAP_TRACKER_ID',
"must be an alphanumeric string") CLICKMAP_TRACKER_ID_RE,
'must be an alphanumeric string',
)
def render(self, context): def render(self, context):
html = TRACKING_CODE % {'tracker_id': self.tracker_id} html = TRACKING_CODE % {'tracker_id': self.tracker_id}

View file

@ -53,8 +53,8 @@ def clicky(parser, token):
class ClickyNode(Node): class ClickyNode(Node):
def __init__(self): def __init__(self):
self.site_id = get_required_setting( self.site_id = get_required_setting(
'CLICKY_SITE_ID', SITE_ID_RE, 'CLICKY_SITE_ID', SITE_ID_RE, 'must be a (string containing) a number'
"must be a (string containing) a number") )
def render(self, context): def render(self, context):
custom = {} 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 from analytical.utils import disable_html, get_required_setting, is_internal_ip
ACCOUNT_NUMBER_RE = re.compile(r'^\d+$') ACCOUNT_NUMBER_RE = re.compile(r'^\d+$')
SETUP_CODE = '<script type="text/javascript" src="{placeholder_url}">' \ SETUP_CODE = '<script type="text/javascript" src="{placeholder_url}"></script>'.format(
'</script>'.\ placeholder_url='//dnn506yrbagrg.cloudfront.net/pages/scripts/'
format(placeholder_url='//dnn506yrbagrg.cloudfront.net/pages/scripts/' '%(account_nr_1)s/%(account_nr_2)s.js'
'%(account_nr_1)s/%(account_nr_2)s.js') )
USERVAR_CODE = "CE2.set(%(varnr)d, '%(value)s');" USERVAR_CODE = "CE2.set(%(varnr)d, '%(value)s');"
@ -38,7 +38,8 @@ class CrazyEggNode(Node):
def __init__(self): def __init__(self):
self.account_nr = get_required_setting( self.account_nr = get_required_setting(
'CRAZY_EGG_ACCOUNT_NUMBER', '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): 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)) 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] params = [(i, v) for i, v in enumerate(values, 1) if v is not None]
if params: if params:
js = " ".join(USERVAR_CODE % { js = ' '.join(
'varnr': varnr, USERVAR_CODE
'value': value, % {
} for (varnr, value) in params) 'varnr': varnr,
html = '%s\n' \ 'value': value,
'<script type="text/javascript">%s</script>' % (html, js) }
for (varnr, value) in params
)
html = '%s\n<script type="text/javascript">%s</script>' % (html, js)
if is_internal_ip(context, 'CRAZY_EGG'): if is_internal_ip(context, 'CRAZY_EGG'):
html = disable_html(html, 'Crazy Egg') html = disable_html(html, 'Crazy Egg')
return html return html

View file

@ -60,11 +60,12 @@ class _FacebookPixelNode(Node):
""" """
Base class: override and provide code_template. Base class: override and provide code_template.
""" """
def __init__(self): def __init__(self):
self.pixel_id = get_required_setting( self.pixel_id = get_required_setting(
'FACEBOOK_PIXEL_ID', 'FACEBOOK_PIXEL_ID',
re.compile(r'^\d+$'), re.compile(r'^\d+$'),
"must be (a string containing) a number", 'must be (a string containing) a number',
) )
def render(self, context): def render(self, context):

View file

@ -46,8 +46,8 @@ def gauges(parser, token):
class GaugesNode(Node): class GaugesNode(Node):
def __init__(self): def __init__(self):
self.site_id = get_required_setting( self.site_id = get_required_setting(
'GAUGES_SITE_ID', SITE_ID_RE, 'GAUGES_SITE_ID', SITE_ID_RE, "must be a string looking like 'XXXXXXX'"
"must be a string looking like 'XXXXXXX'") )
def render(self, context): def render(self, context):
html = TRACKING_CODE % {'site_id': self.site_id} 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]);" NO_ALLOW_HASH_CODE = "_gaq.push(['_setAllowHash', false]);"
TRACK_PAGE_VIEW = "_gaq.push(['_trackPageview']);" TRACK_PAGE_VIEW = "_gaq.push(['_trackPageview']);"
ALLOW_LINKER_CODE = "_gaq.push(['_setAllowLinker', true]);" ALLOW_LINKER_CODE = "_gaq.push(['_setAllowLinker', true]);"
CUSTOM_VAR_CODE = "_gaq.push(['_setCustomVar', %(index)s, '%(name)s', " \ CUSTOM_VAR_CODE = (
"'%(value)s', %(scope)s]);" "_gaq.push(['_setCustomVar', %(index)s, '%(name)s', '%(value)s', %(scope)s]);"
)
SITE_SPEED_CODE = "_gaq.push(['_trackPageLoadTime']);" SITE_SPEED_CODE = "_gaq.push(['_trackPageLoadTime']);"
ANONYMIZE_IP_CODE = "_gaq.push(['_gat._anonymizeIp']);" ANONYMIZE_IP_CODE = "_gaq.push(['_gat._anonymizeIp']);"
SAMPLE_RATE_CODE = "_gaq.push(['_setSampleRate', '%s']);" 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']);" SESSION_COOKIE_TIMEOUT_CODE = "_gaq.push(['_setSessionCookieTimeout', '%s']);"
VISITOR_COOKIE_TIMEOUT_CODE = "_gaq.push(['_setVisitorCookieTimeout', '%s']);" VISITOR_COOKIE_TIMEOUT_CODE = "_gaq.push(['_setVisitorCookieTimeout', '%s']);"
DEFAULT_SOURCE = ("'https://ssl' : 'http://www'", "'.google-analytics.com/ga.js'") 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') ZEROPLACES = decimal.Decimal('0')
TWOPLACES = decimal.Decimal('0.01') TWOPLACES = decimal.Decimal('0.01')
@ -80,8 +84,10 @@ def google_analytics(parser, token):
class GoogleAnalyticsNode(Node): class GoogleAnalyticsNode(Node):
def __init__(self): def __init__(self):
self.property_id = get_required_setting( self.property_id = get_required_setting(
'GOOGLE_ANALYTICS_PROPERTY_ID', PROPERTY_ID_RE, 'GOOGLE_ANALYTICS_PROPERTY_ID',
"must be a string looking like 'UA-XXXXXX-Y'") PROPERTY_ID_RE,
"must be a string looking like 'UA-XXXXXX-Y'",
)
def render(self, context): def render(self, context):
commands = self._get_domain_commands(context) commands = self._get_domain_commands(context)
@ -94,7 +100,7 @@ class GoogleAnalyticsNode(Node):
source = DEFAULT_SOURCE source = DEFAULT_SOURCE
html = SETUP_CODE % { html = SETUP_CODE % {
'property_id': self.property_id, 'property_id': self.property_id,
'commands': " ".join(commands), 'commands': ' '.join(commands),
'source_scheme': source[0], 'source_scheme': source[0],
'source_url': source[1], 'source_url': source[1],
} }
@ -104,15 +110,17 @@ class GoogleAnalyticsNode(Node):
def _get_domain_commands(self, context): def _get_domain_commands(self, context):
commands = [] commands = []
tracking_type = getattr(settings, 'GOOGLE_ANALYTICS_TRACKING_STYLE', tracking_type = getattr(
TRACK_SINGLE_DOMAIN) settings, 'GOOGLE_ANALYTICS_TRACKING_STYLE', TRACK_SINGLE_DOMAIN
)
if tracking_type == TRACK_SINGLE_DOMAIN: if tracking_type == TRACK_SINGLE_DOMAIN:
pass pass
else: else:
domain = get_domain(context, 'google_analytics') domain = get_domain(context, 'google_analytics')
if domain is None: if domain is None:
raise AnalyticalException( 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(DOMAIN_CODE % domain)
commands.append(NO_ALLOW_HASH_CODE) commands.append(NO_ALLOW_HASH_CODE)
if tracking_type == TRACK_MULTIPLE_DOMAINS: if tracking_type == TRACK_MULTIPLE_DOMAINS:
@ -120,9 +128,7 @@ class GoogleAnalyticsNode(Node):
return commands return commands
def _get_custom_var_commands(self, context): def _get_custom_var_commands(self, context):
values = ( values = (context.get('google_analytics_var%s' % i) for i in range(1, 6))
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] params = [(i, v) for i, v in enumerate(values, 1) if v is not None]
commands = [] commands = []
for index, var in params: for index, var in params:
@ -132,12 +138,15 @@ class GoogleAnalyticsNode(Node):
scope = var[2] scope = var[2]
except IndexError: except IndexError:
scope = SCOPE_PAGE scope = SCOPE_PAGE
commands.append(CUSTOM_VAR_CODE % { commands.append(
'index': index, CUSTOM_VAR_CODE
'name': name, % {
'value': value, 'index': index,
'scope': scope, 'name': name,
}) 'value': value,
'scope': scope,
}
)
return commands return commands
def _get_other_commands(self, context): def _get_other_commands(self, context):
@ -152,29 +161,42 @@ class GoogleAnalyticsNode(Node):
if sampleRate is not False: if sampleRate is not False:
value = decimal.Decimal(sampleRate) value = decimal.Decimal(sampleRate)
if not 0 <= value <= 100: 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)) 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: if siteSpeedSampleRate is not False:
value = decimal.Decimal(siteSpeedSampleRate) value = decimal.Decimal(siteSpeedSampleRate)
if not 0 <= value <= 100: if not 0 <= value <= 100:
raise AnalyticalException( 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)) 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: if sessionCookieTimeout is not False:
value = decimal.Decimal(sessionCookieTimeout) value = decimal.Decimal(sessionCookieTimeout)
if value < 0: 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)) 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: if visitorCookieTimeout is not False:
value = decimal.Decimal(visitorCookieTimeout) value = decimal.Decimal(visitorCookieTimeout)
if value < 0: 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)) commands.append(VISITOR_COOKIE_TIMEOUT_CODE % value.quantize(ZEROPLACES))
return commands return commands

View file

@ -13,7 +13,9 @@ from analytical.utils import (
is_internal_ip, 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 = """ SETUP_CODE = """
<script async src="https://www.googletagmanager.com/gtag/js?id={property_id}"></script> <script async src="https://www.googletagmanager.com/gtag/js?id={property_id}"></script>
<script> <script>
@ -49,10 +51,12 @@ def google_analytics_gtag(parser, token):
class GoogleAnalyticsGTagNode(Node): class GoogleAnalyticsGTagNode(Node):
def __init__(self): def __init__(self):
self.property_id = get_required_setting( self.property_id = get_required_setting(
'GOOGLE_ANALYTICS_GTAG_PROPERTY_ID', PROPERTY_ID_RE, 'GOOGLE_ANALYTICS_GTAG_PROPERTY_ID',
'''must be a string looking like one of these patterns PROPERTY_ID_RE,
"""must be a string looking like one of these patterns
('UA-XXXXXX-Y' , 'AW-XXXXXXXXXX', ('UA-XXXXXX-Y' , 'AW-XXXXXXXXXX',
'G-XXXXXXXX', 'DC-XXXXXXXX')''') 'G-XXXXXXXX', 'DC-XXXXXXXX')""",
)
def render(self, context): def render(self, context):
other_fields = {} other_fields = {}
@ -61,9 +65,12 @@ class GoogleAnalyticsGTagNode(Node):
if identity is not None: if identity is not None:
other_fields['user_id'] = identity other_fields['user_id'] = identity
extra = '\n'.join([ extra = '\n'.join(
GTAG_SET_CODE.format(key=key, value=value) for key, value in other_fields.items() [
]) GTAG_SET_CODE.format(key=key, value=value)
for key, value in other_fields.items()
]
)
html = SETUP_CODE.format( html = SETUP_CODE.format(
property_id=self.property_id, property_id=self.property_id,
extra=extra, extra=extra,

View file

@ -57,29 +57,34 @@ def google_analytics_js(parser, token):
class GoogleAnalyticsJsNode(Node): class GoogleAnalyticsJsNode(Node):
def __init__(self): def __init__(self):
self.property_id = get_required_setting( self.property_id = get_required_setting(
'GOOGLE_ANALYTICS_JS_PROPERTY_ID', PROPERTY_ID_RE, 'GOOGLE_ANALYTICS_JS_PROPERTY_ID',
"must be a string looking like 'UA-XXXXXX-Y'") PROPERTY_ID_RE,
"must be a string looking like 'UA-XXXXXX-Y'",
)
def render(self, context): def render(self, context):
import json import json
create_fields = self._get_domain_fields(context) create_fields = self._get_domain_fields(context)
create_fields.update(self._get_other_create_fields(context)) create_fields.update(self._get_other_create_fields(context))
commands = self._get_custom_var_commands(context) commands = self._get_custom_var_commands(context)
commands.extend(self._get_other_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: if display_features:
commands.insert(0, REQUIRE_DISPLAY_FEATURES) commands.insert(0, REQUIRE_DISPLAY_FEATURES)
js_source = getattr( js_source = getattr(
settings, settings,
'GOOGLE_ANALYTICS_JS_SOURCE', 'GOOGLE_ANALYTICS_JS_SOURCE',
'https://www.google-analytics.com/analytics.js' 'https://www.google-analytics.com/analytics.js',
) )
html = SETUP_CODE.format( html = SETUP_CODE.format(
property_id=self.property_id, property_id=self.property_id,
create_fields=json.dumps(create_fields), create_fields=json.dumps(create_fields),
commands="".join(commands), commands=''.join(commands),
js_source=js_source, js_source=js_source,
) )
if is_internal_ip(context, 'GOOGLE_ANALYTICS'): if is_internal_ip(context, 'GOOGLE_ANALYTICS'):
@ -88,14 +93,17 @@ class GoogleAnalyticsJsNode(Node):
def _get_domain_fields(self, context): def _get_domain_fields(self, context):
domain_fields = {} 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: if tracking_type == TRACK_SINGLE_DOMAIN:
pass pass
else: else:
domain = get_domain(context, 'google_analytics') domain = get_domain(context, 'google_analytics')
if domain is None: if domain is None:
raise AnalyticalException( 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 domain_fields['legacyCookieDomain'] = domain
if tracking_type == TRACK_MULTIPLE_DOMAINS: if tracking_type == TRACK_MULTIPLE_DOMAINS:
domain_fields['allowLinker'] = True domain_fields['allowLinker'] = True
@ -104,34 +112,39 @@ class GoogleAnalyticsJsNode(Node):
def _get_other_create_fields(self, context): def _get_other_create_fields(self, context):
other_fields = {} 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: if site_speed_sample_rate is not False:
value = int(decimal.Decimal(site_speed_sample_rate)) value = int(decimal.Decimal(site_speed_sample_rate))
if not 0 <= value <= 100: if not 0 <= value <= 100:
raise AnalyticalException( 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 other_fields['siteSpeedSampleRate'] = value
sample_rate = getattr(settings, 'GOOGLE_ANALYTICS_SAMPLE_RATE', False) sample_rate = getattr(settings, 'GOOGLE_ANALYTICS_SAMPLE_RATE', False)
if sample_rate is not False: if sample_rate is not False:
value = int(decimal.Decimal(sample_rate)) value = int(decimal.Decimal(sample_rate))
if not 0 <= value <= 100: 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 other_fields['sampleRate'] = value
cookie_expires = getattr(settings, 'GOOGLE_ANALYTICS_COOKIE_EXPIRATION', False) cookie_expires = getattr(settings, 'GOOGLE_ANALYTICS_COOKIE_EXPIRATION', False)
if cookie_expires is not False: if cookie_expires is not False:
value = int(decimal.Decimal(cookie_expires)) value = int(decimal.Decimal(cookie_expires))
if value < 0: 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 other_fields['cookieExpires'] = value
return other_fields return other_fields
def _get_custom_var_commands(self, context): def _get_custom_var_commands(self, context):
values = ( values = (context.get('google_analytics_var%s' % i) for i in range(1, 6))
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] params = [(i, v) for i, v in enumerate(values, 1) if v is not None]
commands = [] commands = []
for _, var in params: for _, var in params:
@ -141,10 +154,12 @@ class GoogleAnalyticsJsNode(Node):
float(value) float(value)
except ValueError: except ValueError:
value = f"'{value}'" value = f"'{value}'"
commands.append(CUSTOM_VAR_CODE.format( commands.append(
name=name, CUSTOM_VAR_CODE.format(
value=value, name=name,
)) value=value,
)
)
return commands return commands
def _get_other_commands(self, context): def _get_other_commands(self, context):

View file

@ -52,8 +52,10 @@ def gosquared(parser, token):
class GoSquaredNode(Node): class GoSquaredNode(Node):
def __init__(self): def __init__(self):
self.site_token = get_required_setting( self.site_token = get_required_setting(
'GOSQUARED_SITE_TOKEN', TOKEN_RE, 'GOSQUARED_SITE_TOKEN',
"must be a string looking like XXX-XXXXXX-X") TOKEN_RE,
'must be a string looking like XXX-XXXXXX-X',
)
def render(self, context): def render(self, context):
configs = [TOKEN_CODE % self.site_token] configs = [TOKEN_CODE % self.site_token]

View file

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

View file

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

View file

@ -41,8 +41,9 @@ def hubspot(parser, token):
class HubSpotNode(Node): class HubSpotNode(Node):
def __init__(self): def __init__(self):
self.portal_id = get_required_setting('HUBSPOT_PORTAL_ID', PORTAL_ID_RE, self.portal_id = get_required_setting(
"must be a (string containing a) number") 'HUBSPOT_PORTAL_ID', PORTAL_ID_RE, 'must be a (string containing a) number'
)
def render(self, context): def render(self, context):
html = TRACKING_CODE % {'portal_id': self.portal_id} html = TRACKING_CODE % {'portal_id': self.portal_id}

View file

@ -76,8 +76,8 @@ def intercom(parser, token):
class IntercomNode(Node): class IntercomNode(Node):
def __init__(self): def __init__(self):
self.app_id = get_required_setting( self.app_id = get_required_setting(
'INTERCOM_APP_ID', APP_ID_RE, 'INTERCOM_APP_ID', APP_ID_RE, "must be a string looking like 'XXXXXXX'"
"must be a string looking like 'XXXXXXX'") )
def _identify(self, user): def _identify(self, user):
name = user.get_full_name() name = user.get_full_name()
@ -95,8 +95,7 @@ class IntercomNode(Node):
user = get_user_from_context(context) user = get_user_from_context(context)
if user is not None and get_user_is_authenticated(user): if user is not None and get_user_is_authenticated(user):
if 'name' not in params: if 'name' not in params:
params['name'] = get_identity( params['name'] = get_identity(context, 'intercom', self._identify, user)
context, 'intercom', self._identify, user)
if 'email' not in params and user.email: if 'email' not in params and user.email:
params['email'] = user.email params['email'] = user.email
@ -120,10 +119,8 @@ class IntercomNode(Node):
def render(self, context): def render(self, context):
params = self._get_custom_attrs(context) params = self._get_custom_attrs(context)
params["app_id"] = self.app_id params['app_id'] = self.app_id
html = TRACKING_CODE % { html = TRACKING_CODE % {'settings_json': json.dumps(params, sort_keys=True)}
"settings_json": json.dumps(params, sort_keys=True)
}
if is_internal_ip(context, 'INTERCOM'): if is_internal_ip(context, 'INTERCOM'):
html = disable_html(html, 'Intercom') html = disable_html(html, 'Intercom')

View file

@ -41,11 +41,15 @@ def kiss_insights(parser, token):
class KissInsightsNode(Node): class KissInsightsNode(Node):
def __init__(self): def __init__(self):
self.account_number = get_required_setting( self.account_number = get_required_setting(
'KISS_INSIGHTS_ACCOUNT_NUMBER', ACCOUNT_NUMBER_RE, 'KISS_INSIGHTS_ACCOUNT_NUMBER',
"must be (a string containing) a number") ACCOUNT_NUMBER_RE,
'must be (a string containing) a number',
)
self.site_code = get_required_setting( self.site_code = get_required_setting(
'KISS_INSIGHTS_SITE_CODE', SITE_CODE_RE, 'KISS_INSIGHTS_SITE_CODE',
"must be a string containing three characters") SITE_CODE_RE,
'must be a string containing three characters',
)
def render(self, context): def render(self, context):
commands = [] commands = []
@ -59,7 +63,7 @@ class KissInsightsNode(Node):
html = SETUP_CODE % { html = SETUP_CODE % {
'account_number': self.account_number, 'account_number': self.account_number,
'site_code': self.site_code, 'site_code': self.site_code,
'commands': " ".join(commands), 'commands': ' '.join(commands),
} }
return html return html

View file

@ -63,8 +63,10 @@ def kiss_metrics(parser, token):
class KissMetricsNode(Node): class KissMetricsNode(Node):
def __init__(self): def __init__(self):
self.api_key = get_required_setting( self.api_key = get_required_setting(
'KISS_METRICS_API_KEY', API_KEY_RE, 'KISS_METRICS_API_KEY',
"must be a string containing a 40-digit hexadecimal number") API_KEY_RE,
'must be a string containing a 40-digit hexadecimal number',
)
def render(self, context): def render(self, context):
commands = [] commands = []
@ -79,22 +81,28 @@ class KissMetricsNode(Node):
pass pass
try: try:
name, properties = context[EVENT_CONTEXT_KEY] name, properties = context[EVENT_CONTEXT_KEY]
commands.append(EVENT_CODE % { commands.append(
'name': name, EVENT_CODE
'properties': json.dumps(properties, sort_keys=True), % {
}) 'name': name,
'properties': json.dumps(properties, sort_keys=True),
}
)
except KeyError: except KeyError:
pass pass
try: try:
properties = context[PROPERTY_CONTEXT_KEY] properties = context[PROPERTY_CONTEXT_KEY]
commands.append(PROPERTY_CODE % { commands.append(
'properties': json.dumps(properties, sort_keys=True), PROPERTY_CODE
}) % {
'properties': json.dumps(properties, sort_keys=True),
}
)
except KeyError: except KeyError:
pass pass
html = TRACKING_CODE % { html = TRACKING_CODE % {
'api_key': self.api_key, 'api_key': self.api_key,
'commands': " ".join(commands), 'commands': ' '.join(commands),
} }
if is_internal_ip(context, 'KISS_METRICS'): if is_internal_ip(context, 'KISS_METRICS'):
html = disable_html(html, 'KISSmetrics') html = disable_html(html, 'KISSmetrics')

View file

@ -39,12 +39,11 @@ def luckyorange(parser, token):
class LuckyOrangeNode(Node): class LuckyOrangeNode(Node):
def __init__(self): def __init__(self):
self.site_id = get_required_setting( self.site_id = get_required_setting(
'LUCKYORANGE_SITE_ID', 'LUCKYORANGE_SITE_ID',
re.compile(r'^\d+$'), re.compile(r'^\d+$'),
"must be (a string containing) a number", 'must be (a string containing) a number',
) )
def render(self, context): 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> <noscript><p><img src="//%(url)s/matomo.php?idsite=%(siteid)s" style="border:0;" alt="" /></p></noscript>
""" # noqa """ # 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"]);' IDENTITY_CODE = '_paq.push(["setUserId", "%(userid)s"]);'
DISABLE_COOKIES_CODE = '_paq.push([\'disableCookies\']);' DISABLE_COOKIES_CODE = "_paq.push(['disableCookies']);"
DEFAULT_SCOPE = 'page' DEFAULT_SCOPE = 'page'
@ -75,23 +77,27 @@ def matomo(parser, token):
class MatomoNode(Node): class MatomoNode(Node):
def __init__(self): def __init__(self):
self.domain_path = \ self.domain_path = get_required_setting(
get_required_setting('MATOMO_DOMAIN_PATH', DOMAINPATH_RE, 'MATOMO_DOMAIN_PATH',
"must be a domain name, optionally followed " DOMAINPATH_RE,
"by an URI path, no trailing slash (e.g. " 'must be a domain name, optionally followed '
"matomo.example.com or my.matomo.server/path)") 'by an URI path, no trailing slash (e.g. '
self.site_id = \ 'matomo.example.com or my.matomo.server/path)',
get_required_setting('MATOMO_SITE_ID', SITEID_RE, )
"must be a (string containing a) number") self.site_id = get_required_setting(
'MATOMO_SITE_ID', SITEID_RE, 'must be a (string containing a) number'
)
def render(self, context): def render(self, context):
custom_variables = context.get('matomo_vars', ()) custom_variables = context.get('matomo_vars', ())
complete_variables = (var if len(var) >= 4 else var + (DEFAULT_SCOPE,) complete_variables = (
for var in custom_variables) var if len(var) >= 4 else var + (DEFAULT_SCOPE,) for var in custom_variables
)
variables_code = (VARIABLE_CODE % MatomoVar(*var)._asdict() variables_code = (
for var in complete_variables) VARIABLE_CODE % MatomoVar(*var)._asdict() for var in complete_variables
)
commands = [] commands = []
if getattr(settings, 'MATOMO_DISABLE_COOKIES', False): if getattr(settings, 'MATOMO_DISABLE_COOKIES', False):
@ -99,15 +105,15 @@ class MatomoNode(Node):
userid = get_identity(context, 'matomo') userid = get_identity(context, 'matomo')
if userid is not None: if userid is not None:
variables_code = chain(variables_code, ( variables_code = chain(
IDENTITY_CODE % {'userid': userid}, variables_code, (IDENTITY_CODE % {'userid': userid},)
)) )
html = TRACKING_CODE % { html = TRACKING_CODE % {
'url': self.domain_path, 'url': self.domain_path,
'siteid': self.site_id, 'siteid': self.site_id,
'variables': '\n '.join(variables_code), 'variables': '\n '.join(variables_code),
'commands': '\n '.join(commands) 'commands': '\n '.join(commands),
} }
if is_internal_ip(context, 'MATOMO'): if is_internal_ip(context, 'MATOMO'):
html = disable_html(html, 'Matomo') html = disable_html(html, 'Matomo')

View file

@ -25,7 +25,7 @@ e,d])};b.__SV=1.2}})(document,window.mixpanel||[]);
</script> </script>
""" # noqa """ # noqa
IDENTIFY_CODE = "mixpanel.identify('%s');" 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_CODE = "mixpanel.track('%(name)s', %(properties)s);"
EVENT_CONTEXT_KEY = 'mixpanel_event' EVENT_CONTEXT_KEY = 'mixpanel_event'
@ -49,29 +49,38 @@ def mixpanel(parser, token):
class MixpanelNode(Node): class MixpanelNode(Node):
def __init__(self): def __init__(self):
self._token = get_required_setting( self._token = get_required_setting(
'MIXPANEL_API_TOKEN', MIXPANEL_API_TOKEN_RE, 'MIXPANEL_API_TOKEN',
"must be a string containing a 32-digit hexadecimal number") MIXPANEL_API_TOKEN_RE,
'must be a string containing a 32-digit hexadecimal number',
)
def render(self, context): def render(self, context):
commands = [] commands = []
identity = get_identity(context, 'mixpanel') identity = get_identity(context, 'mixpanel')
if identity is not None: if identity is not None:
if isinstance(identity, dict): if isinstance(identity, dict):
commands.append(IDENTIFY_CODE % identity.get('id', identity.get('username'))) commands.append(
commands.append(IDENTIFY_PROPERTIES % json.dumps(identity, sort_keys=True)) IDENTIFY_CODE % identity.get('id', identity.get('username'))
)
commands.append(
IDENTIFY_PROPERTIES % json.dumps(identity, sort_keys=True)
)
else: else:
commands.append(IDENTIFY_CODE % identity) commands.append(IDENTIFY_CODE % identity)
try: try:
name, properties = context[EVENT_CONTEXT_KEY] name, properties = context[EVENT_CONTEXT_KEY]
commands.append(EVENT_CODE % { commands.append(
'name': name, EVENT_CODE
'properties': json.dumps(properties, sort_keys=True), % {
}) 'name': name,
'properties': json.dumps(properties, sort_keys=True),
}
)
except KeyError: except KeyError:
pass pass
html = TRACKING_CODE % { html = TRACKING_CODE % {
'token': self._token, 'token': self._token,
'commands': " ".join(commands), 'commands': ' '.join(commands),
} }
if is_internal_ip(context, 'MIXPANEL'): if is_internal_ip(context, 'MIXPANEL'):
html = disable_html(html, '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' EMAIL_CONTEXT_KEY = 'olark_email'
STATUS_CODE = "olark('api.chat.updateVisitorStatus', {snippet: %s});" STATUS_CODE = "olark('api.chat.updateVisitorStatus', {snippet: %s});"
STATUS_CONTEXT_KEY = 'olark_status' STATUS_CONTEXT_KEY = 'olark_status'
MESSAGE_CODE = "olark.configure('locale.%(key)s', \"%(msg)s\");" MESSAGE_CODE = 'olark.configure(\'locale.%(key)s\', "%(msg)s");'
MESSAGE_KEYS = { MESSAGE_KEYS = {
"welcome_title", "chatting_title", "unavailable_title", 'welcome_title',
"busy_title", "away_message", "loading_title", "welcome_message", 'chatting_title',
"busy_message", "chat_input_text", "name_input_text", 'unavailable_title',
"email_input_text", "offline_note_message", "send_button_text", 'busy_title',
"offline_note_thankyou_text", "offline_note_error_text", 'away_message',
"offline_note_sending_text", "operator_is_typing_text", 'loading_title',
"operator_has_stopped_typing_text", "introduction_error_text", 'welcome_message',
"introduction_messages", "introduction_submit_button_text", '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() register = Library()
@ -56,8 +69,10 @@ def olark(parser, token):
class OlarkNode(Node): class OlarkNode(Node):
def __init__(self): def __init__(self):
self.site_id = get_required_setting( self.site_id = get_required_setting(
'OLARK_SITE_ID', SITE_ID_RE, 'OLARK_SITE_ID',
"must be a string looking like 'XXXX-XXX-XX-XXXX'") SITE_ID_RE,
"must be a string looking like 'XXXX-XXX-XX-XXXX'",
)
def render(self, context): def render(self, context):
extra_code = [] extra_code = []
@ -76,21 +91,22 @@ class OlarkNode(Node):
except KeyError: except KeyError:
pass pass
try: try:
extra_code.append(STATUS_CODE % json.dumps(context[STATUS_CONTEXT_KEY], extra_code.append(
sort_keys=True)) STATUS_CODE % json.dumps(context[STATUS_CONTEXT_KEY], sort_keys=True)
)
except KeyError: except KeyError:
pass pass
extra_code.extend(self._get_configuration(context)) extra_code.extend(self._get_configuration(context))
html = SETUP_CODE % { html = SETUP_CODE % {
'site_id': self.site_id, 'site_id': self.site_id,
'extra_code': " ".join(extra_code), 'extra_code': ' '.join(extra_code),
} }
return html return html
def _get_nickname(self, user): def _get_nickname(self, user):
name = user.get_full_name() name = user.get_full_name()
if name: if name:
return "%s (%s)" % (name, user.username) return '%s (%s)' % (name, user.username)
else: else:
return user.username return user.username

View file

@ -33,8 +33,10 @@ def optimizely(parser, token):
class OptimizelyNode(Node): class OptimizelyNode(Node):
def __init__(self): def __init__(self):
self.account_number = get_required_setting( self.account_number = get_required_setting(
'OPTIMIZELY_ACCOUNT_NUMBER', ACCOUNT_NUMBER_RE, 'OPTIMIZELY_ACCOUNT_NUMBER',
"must be a string looking like 'XXXXXXX'") ACCOUNT_NUMBER_RE,
"must be a string looking like 'XXXXXXX'",
)
def render(self, context): def render(self, context):
html = SETUP_CODE % {'account_number': self.account_number} html = SETUP_CODE % {'account_number': self.account_number}

View file

@ -56,14 +56,14 @@ def performable(parser, token):
class PerformableNode(Node): class PerformableNode(Node):
def __init__(self): def __init__(self):
self.api_key = get_required_setting( self.api_key = get_required_setting(
'PERFORMABLE_API_KEY', API_KEY_RE, 'PERFORMABLE_API_KEY', API_KEY_RE, "must be a string looking like 'XXXXX'"
"must be a string looking like 'XXXXX'") )
def render(self, context): def render(self, context):
html = SETUP_CODE % {'api_key': self.api_key} html = SETUP_CODE % {'api_key': self.api_key}
identity = get_identity(context, 'performable') identity = get_identity(context, 'performable')
if identity is not None: 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'): if is_internal_ip(context, 'PERFORMABLE'):
html = disable_html(html, 'Performable') html = disable_html(html, 'Performable')
return html return html
@ -74,10 +74,13 @@ def performable_embed(hostname, page_id):
""" """
Include a Performable landing page. Include a Performable landing page.
""" """
return mark_safe(EMBED_CODE % { return mark_safe(
'hostname': hostname, EMBED_CODE
'page_id': page_id, % {
}) 'hostname': hostname,
'page_id': page_id,
}
)
def contribute_to_analytical(add_node): def contribute_to_analytical(add_node):

View file

@ -48,8 +48,10 @@ def rating_mailru(parser, token):
class RatingMailruNode(Node): class RatingMailruNode(Node):
def __init__(self): def __init__(self):
self.counter_id = get_required_setting( self.counter_id = get_required_setting(
'RATING_MAILRU_COUNTER_ID', COUNTER_ID_RE, 'RATING_MAILRU_COUNTER_ID',
"must be (a string containing) a number'") COUNTER_ID_RE,
"must be (a string containing) a number'",
)
def render(self, context): def render(self, context):
html = COUNTER_CODE % { html = COUNTER_CODE % {

View file

@ -24,7 +24,9 @@ FORM_POSITION_TOP_RIGHT = 'tr'
FORM_POSITION_BOTTOM_LEFT = 'bl' FORM_POSITION_BOTTOM_LEFT = 'bl'
FORM_POSITION_BOTTOM_RIGHT = 'br' 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 = """ SETUP_CODE = """
<script type="text/javascript"> <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"> 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");' DOMAIN_CODE = 'SnapABug.setDomain("%s");'
SECURE_CONNECTION_CODE = 'SnapABug.setSecureConnexion();' SECURE_CONNECTION_CODE = 'SnapABug.setSecureConnexion();'
INIT_CODE = 'SnapABug.init("%s");' 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");' SETBUTTON_CODE = 'SnapABug.setButton("%s");'
SETEMAIL_CODE = 'SnapABug.setUserEmail("%s"%s);' SETEMAIL_CODE = 'SnapABug.setUserEmail("%s"%s);'
SETLOCALE_CODE = 'SnapABug.setLocale("%s");' SETLOCALE_CODE = 'SnapABug.setLocale("%s");'
@ -67,21 +71,24 @@ def snapengage(parser, token):
class SnapEngageNode(Node): class SnapEngageNode(Node):
def __init__(self): def __init__(self):
self.widget_id = get_required_setting( self.widget_id = get_required_setting(
'SNAPENGAGE_WIDGET_ID', WIDGET_ID_RE, 'SNAPENGAGE_WIDGET_ID',
"must be a string looking like this: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'") WIDGET_ID_RE,
"must be a string looking like this: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'",
)
def render(self, context): def render(self, context):
settings_code = [] settings_code = []
domain = self._get_setting(context, 'snapengage_domain', domain = self._get_setting(context, 'snapengage_domain', 'SNAPENGAGE_DOMAIN')
'SNAPENGAGE_DOMAIN')
if domain is not None: if domain is not None:
settings_code.append(DOMAIN_CODE % domain) settings_code.append(DOMAIN_CODE % domain)
secure_connection = self._get_setting(context, secure_connection = self._get_setting(
'snapengage_secure_connection', context,
'SNAPENGAGE_SECURE_CONNECTION', 'snapengage_secure_connection',
False) 'SNAPENGAGE_SECURE_CONNECTION',
False,
)
if secure_connection: if secure_connection:
settings_code.append(SECURE_CONNECTION_CODE) settings_code.append(SECURE_CONNECTION_CODE)
@ -89,61 +96,70 @@ class SnapEngageNode(Node):
if email is None: if email is None:
email = get_identity(context, 'snapengage', lambda u: u.email) email = get_identity(context, 'snapengage', lambda u: u.email)
if email is not None: if email is not None:
if self._get_setting(context, 'snapengage_readonly_email', if self._get_setting(
'SNAPENGAGE_READONLY_EMAIL', False): context, 'snapengage_readonly_email', 'SNAPENGAGE_READONLY_EMAIL', False
):
readonly_tail = ',true' readonly_tail = ',true'
else: else:
readonly_tail = '' readonly_tail = ''
settings_code.append(SETEMAIL_CODE % (email, readonly_tail)) settings_code.append(SETEMAIL_CODE % (email, readonly_tail))
locale = self._get_setting(context, 'snapengage_locale', locale = self._get_setting(context, 'snapengage_locale', 'SNAPENGAGE_LOCALE')
'SNAPENGAGE_LOCALE')
if locale is None: if locale is None:
locale = translation.to_locale(translation.get_language()) locale = translation.to_locale(translation.get_language())
settings_code.append(SETLOCALE_CODE % locale) settings_code.append(SETLOCALE_CODE % locale)
form_position = self._get_setting(context, form_position = self._get_setting(
'snapengage_form_position', 'SNAPENGAGE_FORM_POSITION') context, 'snapengage_form_position', 'SNAPENGAGE_FORM_POSITION'
)
if form_position is not None: if form_position is not None:
settings_code.append(FORM_POSITION_CODE % form_position) settings_code.append(FORM_POSITION_CODE % form_position)
form_top_position = self._get_setting(context, form_top_position = self._get_setting(
'snapengage_form_top_position', context, 'snapengage_form_top_position', 'SNAPENGAGE_FORM_TOP_POSITION'
'SNAPENGAGE_FORM_TOP_POSITION') )
if form_top_position is not None: if form_top_position is not None:
settings_code.append(FORM_TOP_POSITION_CODE % form_top_position) settings_code.append(FORM_TOP_POSITION_CODE % form_top_position)
show_offline = self._get_setting(context, 'snapengage_show_offline', show_offline = self._get_setting(
'SNAPENGAGE_SHOW_OFFLINE', True) context, 'snapengage_show_offline', 'SNAPENGAGE_SHOW_OFFLINE', True
)
if not show_offline: if not show_offline:
settings_code.append(DISABLE_OFFLINE_CODE) settings_code.append(DISABLE_OFFLINE_CODE)
screenshots = self._get_setting(context, 'snapengage_screenshots', screenshots = self._get_setting(
'SNAPENGAGE_SCREENSHOTS', True) context, 'snapengage_screenshots', 'SNAPENGAGE_SCREENSHOTS', True
)
if not screenshots: if not screenshots:
settings_code.append(DISABLE_SCREENSHOT_CODE) settings_code.append(DISABLE_SCREENSHOT_CODE)
offline_screenshots = self._get_setting(context, offline_screenshots = self._get_setting(
'snapengage_offline_screenshots', context,
'SNAPENGAGE_OFFLINE_SCREENSHOTS', True) 'snapengage_offline_screenshots',
'SNAPENGAGE_OFFLINE_SCREENSHOTS',
True,
)
if not offline_screenshots: if not offline_screenshots:
settings_code.append(DISABLE_OFFLINE_SCREENSHOT_CODE) settings_code.append(DISABLE_OFFLINE_SCREENSHOT_CODE)
if not context.get('snapengage_proactive_chat', True): if not context.get('snapengage_proactive_chat', True):
settings_code.append(DISABLE_PROACTIVE_CHAT_CODE) settings_code.append(DISABLE_PROACTIVE_CHAT_CODE)
sounds = self._get_setting(context, 'snapengage_sounds', sounds = self._get_setting(
'SNAPENGAGE_SOUNDS', True) context, 'snapengage_sounds', 'SNAPENGAGE_SOUNDS', True
)
if not sounds: if not sounds:
settings_code.append(DISABLE_SOUNDS_CODE) settings_code.append(DISABLE_SOUNDS_CODE)
button_effect = self._get_setting(context, 'snapengage_button_effect', button_effect = self._get_setting(
'SNAPENGAGE_BUTTON_EFFECT') context, 'snapengage_button_effect', 'SNAPENGAGE_BUTTON_EFFECT'
)
if button_effect is not None: if button_effect is not None:
settings_code.append(BUTTONEFFECT_CODE % button_effect) settings_code.append(BUTTONEFFECT_CODE % button_effect)
button = self._get_setting(context, 'snapengage_button', button = self._get_setting(
'SNAPENGAGE_BUTTON', BUTTON_STYLE_DEFAULT) context, 'snapengage_button', 'SNAPENGAGE_BUTTON', BUTTON_STYLE_DEFAULT
)
if button == BUTTON_STYLE_NONE: if button == BUTTON_STYLE_NONE:
settings_code.append(INIT_CODE % self.widget_id) settings_code.append(INIT_CODE % self.widget_id)
else: else:
@ -152,21 +168,28 @@ class SnapEngageNode(Node):
settings_code.append(SETBUTTON_CODE % button) settings_code.append(SETBUTTON_CODE % button)
button_location = self._get_setting( button_location = self._get_setting(
context, context,
'snapengage_button_location', 'SNAPENGAGE_BUTTON_LOCATION', 'snapengage_button_location',
BUTTON_LOCATION_LEFT) 'SNAPENGAGE_BUTTON_LOCATION',
BUTTON_LOCATION_LEFT,
)
button_offset = self._get_setting( button_offset = self._get_setting(
context, context,
'snapengage_button_location_offset', 'snapengage_button_location_offset',
'SNAPENGAGE_BUTTON_LOCATION_OFFSET', '55%') 'SNAPENGAGE_BUTTON_LOCATION_OFFSET',
settings_code.append(ADDBUTTON_CODE % { '55%',
'id': self.widget_id, )
'location': button_location, settings_code.append(
'offset': button_offset, ADDBUTTON_CODE
'dynamic_tail': ',true' if (button == BUTTON_STYLE_LIVE) else '', % {
}) 'id': self.widget_id,
'location': button_location,
'offset': button_offset,
'dynamic_tail': ',true' if (button == BUTTON_STYLE_LIVE) else '',
}
)
html = SETUP_CODE % { html = SETUP_CODE % {
'widget_id': self.widget_id, 'widget_id': self.widget_id,
'settings_code': " ".join(settings_code), 'settings_code': ' '.join(settings_code),
} }
return html return html

View file

@ -53,8 +53,8 @@ def spring_metrics(parser, token):
class SpringMetricsNode(Node): class SpringMetricsNode(Node):
def __init__(self): def __init__(self):
self.tracking_id = get_required_setting( self.tracking_id = get_required_setting(
'SPRING_METRICS_TRACKING_ID', 'SPRING_METRICS_TRACKING_ID', TRACKING_ID_RE, 'must be a hexadecimal string'
TRACKING_ID_RE, "must be a hexadecimal string") )
def render(self, context): def render(self, context):
custom = {} custom = {}
@ -63,8 +63,7 @@ class SpringMetricsNode(Node):
if var.startswith('spring_metrics_'): if var.startswith('spring_metrics_'):
custom[var[15:]] = val custom[var[15:]] = val
if 'email' not in custom: if 'email' not in custom:
identity = get_identity(context, 'spring_metrics', identity = get_identity(context, 'spring_metrics', lambda u: u.email)
lambda u: u.email)
if identity is not None: if identity is not None:
custom['email'] = identity custom['email'] = identity
@ -81,9 +80,11 @@ class SpringMetricsNode(Node):
convert = params.pop('convert', None) convert = params.pop('convert', None)
if convert is not None: if convert is not None:
commands.append("_springMetq.push(['convert', '%s'])" % convert) commands.append("_springMetq.push(['convert', '%s'])" % convert)
commands.extend("_springMetq.push(['setdata', {'%s': '%s'}]);" commands.extend(
% (var, val) for var, val in params.items()) "_springMetq.push(['setdata', {'%s': '%s'}]);" % (var, val)
return " ".join(commands) for var, val in params.items()
)
return ' '.join(commands)
def contribute_to_analytical(add_node): def contribute_to_analytical(add_node):

View file

@ -48,7 +48,8 @@ def uservoice(parser, token):
class UserVoiceNode(Node): class UserVoiceNode(Node):
def __init__(self): def __init__(self):
self.default_widget_key = get_required_setting( 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): def render(self, context):
widget_key = context.get('uservoice_widget_key') widget_key = context.get('uservoice_widget_key')
@ -65,13 +66,16 @@ class UserVoiceNode(Node):
if identity: if identity:
identity = IDENTITY % {'options': json.dumps(identity, sort_keys=True)} identity = IDENTITY % {'options': json.dumps(identity, sort_keys=True)}
trigger = context.get('uservoice_add_trigger', trigger = context.get(
getattr(settings, 'USERVOICE_ADD_TRIGGER', True)) 'uservoice_add_trigger', getattr(settings, 'USERVOICE_ADD_TRIGGER', True)
)
html = TRACKING_CODE % {'widget_key': widget_key, html = TRACKING_CODE % {
'options': json.dumps(options, sort_keys=True), 'widget_key': widget_key,
'trigger': TRIGGER if trigger else '', 'options': json.dumps(options, sort_keys=True),
'identity': identity if identity else ''} 'trigger': TRIGGER if trigger else '',
'identity': identity if identity else '',
}
return html return html
def _identify(self, user): def _identify(self, user):

View file

@ -49,8 +49,8 @@ def woopra(parser, token):
class WoopraNode(Node): class WoopraNode(Node):
def __init__(self): def __init__(self):
self.domain = get_required_setting( self.domain = get_required_setting(
'WOOPRA_DOMAIN', DOMAIN_RE, 'WOOPRA_DOMAIN', DOMAIN_RE, 'must be a domain name'
"must be a domain name") )
def render(self, context): def render(self, context):
settings = self._get_settings(context) settings = self._get_settings(context)
@ -81,8 +81,7 @@ class WoopraNode(Node):
if 'name' not in params and 'email' not in params: if 'name' not in params and 'email' not in params:
user = get_user_from_context(context) user = get_user_from_context(context)
if user is not None and get_user_is_authenticated(user): if user is not None and get_user_is_authenticated(user):
params['name'] = get_identity( params['name'] = get_identity(context, 'woopra', self._identify, user)
context, 'woopra', self._identify, user)
if user.email: if user.email:
params['email'] = user.email params['email'] = user.email
return params return params

View file

@ -57,15 +57,17 @@ def yandex_metrica(parser, token):
class YandexMetricaNode(Node): class YandexMetricaNode(Node):
def __init__(self): def __init__(self):
self.counter_id = get_required_setting( self.counter_id = get_required_setting(
'YANDEX_METRICA_COUNTER_ID', COUNTER_ID_RE, 'YANDEX_METRICA_COUNTER_ID',
"must be (a string containing) a number'") COUNTER_ID_RE,
"must be (a string containing) a number'",
)
def render(self, context): def render(self, context):
options = { options = {
'id': int(self.counter_id), 'id': int(self.counter_id),
'clickmap': True, 'clickmap': True,
'trackLinks': True, 'trackLinks': True,
'accurateTrackBounce': True 'accurateTrackBounce': True,
} }
if getattr(settings, 'YANDEX_METRICA_WEBVISOR', False): if getattr(settings, 'YANDEX_METRICA_WEBVISOR', False):
options['webvisor'] = True options['webvisor'] = True

View file

@ -5,8 +5,7 @@ Utility function for django-analytical.
from django.conf import settings from django.conf import settings
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
HTML_COMMENT = "<!-- %(service)s disabled on internal IP " \ HTML_COMMENT = '<!-- %(service)s disabled on internal IP address\n%(html)s\n-->'
"address\n%(html)s\n-->"
def get_required_setting(setting, value_re, invalid_msg): def get_required_setting(setting, value_re, invalid_msg):
@ -19,13 +18,14 @@ def get_required_setting(setting, value_re, invalid_msg):
try: try:
value = getattr(settings, setting) value = getattr(settings, setting)
except AttributeError: except AttributeError:
raise AnalyticalException("%s setting: not found" % setting) raise AnalyticalException('%s setting: not found' % setting)
if not value: if not value:
raise AnalyticalException("%s setting is not set" % setting) raise AnalyticalException('%s setting is not set' % setting)
value = str(value) value = str(value)
if not value_re.search(value): if not value_re.search(value):
raise AnalyticalException("%s setting: %s: '%s'" raise AnalyticalException(
% (setting, invalid_msg, value)) "%s setting: %s: '%s'" % (setting, invalid_msg, value)
)
return value return value
@ -112,6 +112,7 @@ def get_domain(context, prefix):
if domain is None: if domain is None:
if 'django.contrib.sites' in settings.INSTALLED_APPS: if 'django.contrib.sites' in settings.INSTALLED_APPS:
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
try: try:
domain = Site.objects.get_current().domain domain = Site.objects.get_current().domain
except (ImproperlyConfigured, Site.DoesNotExist): except (ImproperlyConfigured, Site.DoesNotExist):
@ -162,4 +163,5 @@ class AnalyticalException(Exception):
Raised when an exception occurs in any django-analytical code that should Raised when an exception occurs in any django-analytical code that should
be silenced in templates. be silenced in templates.
""" """
silent_variable_failure = True silent_variable_failure = True

View file

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

View file

@ -29,8 +29,10 @@ pygments_style = 'sphinx'
intersphinx_mapping = { intersphinx_mapping = {
'python': ('http://docs.python.org/3.13', None), 'python': ('http://docs.python.org/3.13', None),
'django': ('http://docs.djangoproject.com/en/stable', 'django': (
'http://docs.djangoproject.com/en/stable/_objects/'), 'http://docs.djangoproject.com/en/stable',
'http://docs.djangoproject.com/en/stable/_objects/',
),
} }
@ -43,6 +45,11 @@ htmlhelp_basename = 'analyticaldoc'
# -- Options for LaTeX output ----------------------------------------------- # -- Options for LaTeX output -----------------------------------------------
latex_documents = [ 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): def _location_node(location):
class DummyNode(Node): class DummyNode(Node):
def render(self, context): def render(self, context):
return "<!-- dummy_%s -->" % location return '<!-- dummy_%s -->' % location
return DummyNode return DummyNode
@ -25,6 +26,7 @@ def _location_tag(location):
if len(bits) > 1: if len(bits) > 1:
raise TemplateSyntaxError("'%s' tag takes no arguments" % bits[0]) raise TemplateSyntaxError("'%s' tag takes no arguments" % bits[0])
return _location_nodes[location] return _location_nodes[location]
return dummy_tag return dummy_tag

View file

@ -27,7 +27,7 @@ class AnalyticsTagTestCase(TagTestCase):
def render_location_tag(self, location, vars=None): def render_location_tag(self, location, vars=None):
if vars is None: if vars is None:
vars = {} vars = {}
t = Template("{%% load analytical %%}{%% analytical_%s %%}" % location) t = Template('{%% load analytical %%}{%% analytical_%s %%}' % location)
return t.render(Context(vars)) return t.render(Context(vars))
def test_location_tags(self): 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) self.assertTrue('var _sf_async_config={"uid": "12345"};' in r, r)
@override_settings(INSTALLED_APPS=( @override_settings(
'analytical', INSTALLED_APPS=(
'django.contrib.sites', 'analytical',
'django.contrib.auth', 'django.contrib.sites',
'django.contrib.contenttypes', 'django.contrib.auth',
)) 'django.contrib.contenttypes',
)
)
@override_settings(CHARTBEAT_USER_ID='12345') @override_settings(CHARTBEAT_USER_ID='12345')
class ChartbeatTagTestCaseWithSites(TestCase): class ChartbeatTagTestCaseWithSites(TestCase):
def setUp(self): def setUp(self):
from django.core.management import call_command from django.core.management import call_command
call_command("migrate", verbosity=0)
call_command('migrate', verbosity=0)
def test_rendering_setup_site(self): def test_rendering_setup_site(self):
from django.contrib.sites.models import Site 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): with override_settings(SITE_ID=site.id):
r = ChartbeatBottomNode().render(Context()) r = ChartbeatBottomNode().render(Context())
assert re.search('var _sf_async_config={.*"uid": "12345".*};', r) assert re.search('var _sf_async_config={.*"uid": "12345".*};', r)
@ -60,24 +64,36 @@ class ChartbeatTagTestCase(TagTestCase):
""" """
def test_top_tag(self): 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 assert 'var _sf_startpt=(new Date()).getTime()' in r
def test_bottom_tag(self): 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={.*"uid": "12345".*};', r)
assert re.search('var _sf_async_config={.*"domain": "test.com".*};', r) assert re.search('var _sf_async_config={.*"domain": "test.com".*};', r)
def test_top_node(self): def test_top_node(self):
r = ChartbeatTopNode().render(Context({ r = ChartbeatTopNode().render(
'chartbeat_domain': "test.com", Context(
})) {
'chartbeat_domain': 'test.com',
}
)
)
assert 'var _sf_startpt=(new Date()).getTime()' in r assert 'var _sf_startpt=(new Date()).getTime()' in r
def test_bottom_node(self): def test_bottom_node(self):
r = ChartbeatBottomNode().render(Context({ r = ChartbeatBottomNode().render(
'chartbeat_domain': "test.com", Context(
})) {
'chartbeat_domain': 'test.com',
}
)
)
assert re.search('var _sf_async_config={.*"uid": "12345".*};', r) assert re.search('var _sf_async_config={.*"uid": "12345".*};', r)
assert re.search('var _sf_async_config={.*"domain": "test.com".*};', 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 assert 'var clicky_custom = {"session": {"username":' not in r
def test_custom(self): def test_custom(self):
r = ClickyNode().render(Context({ r = ClickyNode().render(
'clicky_var1': 'val1', Context(
'clicky_var2': 'val2', {
})) 'clicky_var1': 'val1',
assert re.search(r'var clicky_custom = {.*"var1": "val1", "var2": "val2".*};', r) 'clicky_var2': 'val2',
}
)
)
assert re.search(
r'var clicky_custom = {.*"var1": "val1", "var2": "val2".*};', r
)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1']) @override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
def test_render_internal_ip(self): def test_render_internal_ip(self):

View file

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

View file

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

View file

@ -20,8 +20,10 @@ from analytical.templatetags.google_analytics import (
from analytical.utils import AnalyticalException from analytical.utils import AnalyticalException
@override_settings(GOOGLE_ANALYTICS_PROPERTY_ID='UA-123456-7', @override_settings(
GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_SINGLE_DOMAIN) GOOGLE_ANALYTICS_PROPERTY_ID='UA-123456-7',
GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_SINGLE_DOMAIN,
)
class GoogleAnalyticsTagTestCase(TagTestCase): class GoogleAnalyticsTagTestCase(TagTestCase):
""" """
Tests for the ``google_analytics`` template tag. Tests for the ``google_analytics`` template tag.
@ -47,15 +49,19 @@ class GoogleAnalyticsTagTestCase(TagTestCase):
with pytest.raises(AnalyticalException): with pytest.raises(AnalyticalException):
GoogleAnalyticsNode() GoogleAnalyticsNode()
@override_settings(GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_MULTIPLE_SUBDOMAINS, @override_settings(
GOOGLE_ANALYTICS_DOMAIN='example.com') GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_MULTIPLE_SUBDOMAINS,
GOOGLE_ANALYTICS_DOMAIN='example.com',
)
def test_track_multiple_subdomains(self): def test_track_multiple_subdomains(self):
r = GoogleAnalyticsNode().render(Context()) r = GoogleAnalyticsNode().render(Context())
assert "_gaq.push(['_setDomainName', 'example.com']);" in r assert "_gaq.push(['_setDomainName', 'example.com']);" in r
assert "_gaq.push(['_setAllowHash', false]);" in r assert "_gaq.push(['_setAllowHash', false]);" in r
@override_settings(GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_MULTIPLE_DOMAINS, @override_settings(
GOOGLE_ANALYTICS_DOMAIN='example.com') GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_MULTIPLE_DOMAINS,
GOOGLE_ANALYTICS_DOMAIN='example.com',
)
def test_track_multiple_domains(self): def test_track_multiple_domains(self):
r = GoogleAnalyticsNode().render(Context()) r = GoogleAnalyticsNode().render(Context())
assert "_gaq.push(['_setDomainName', 'example.com']);" in r assert "_gaq.push(['_setDomainName', 'example.com']);" in r
@ -63,12 +69,14 @@ class GoogleAnalyticsTagTestCase(TagTestCase):
assert "_gaq.push(['_setAllowLinker', true]);" in r assert "_gaq.push(['_setAllowLinker', true]);" in r
def test_custom_vars(self): def test_custom_vars(self):
context = Context({ context = Context(
'google_analytics_var1': ('test1', 'foo'), {
'google_analytics_var2': ('test2', 'bar', SCOPE_VISITOR), 'google_analytics_var1': ('test1', 'foo'),
'google_analytics_var4': ('test4', 'baz', SCOPE_SESSION), 'google_analytics_var2': ('test2', 'bar', SCOPE_VISITOR),
'google_analytics_var5': ('test5', 'qux', SCOPE_PAGE), 'google_analytics_var4': ('test4', 'baz', SCOPE_SESSION),
}) 'google_analytics_var5': ('test5', 'qux', SCOPE_PAGE),
}
)
r = GoogleAnalyticsNode().render(context) r = GoogleAnalyticsNode().render(context)
assert "_gaq.push(['_setCustomVar', 1, 'test1', 'foo', 3]);" in r assert "_gaq.push(['_setCustomVar', 1, 'test1', 'foo', 3]);" in r
assert "_gaq.push(['_setCustomVar', 2, 'test2', 'bar', 1]);" in r assert "_gaq.push(['_setCustomVar', 2, 'test2', 'bar', 1]);" in r
@ -83,10 +91,10 @@ class GoogleAnalyticsTagTestCase(TagTestCase):
def test_display_advertising(self): def test_display_advertising(self):
with override_settings(GOOGLE_ANALYTICS_DISPLAY_ADVERTISING=False): with override_settings(GOOGLE_ANALYTICS_DISPLAY_ADVERTISING=False):
r = GoogleAnalyticsNode().render(Context()) 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): with override_settings(GOOGLE_ANALYTICS_DISPLAY_ADVERTISING=True):
r = GoogleAnalyticsNode().render(Context()) 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']) @override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
def test_render_internal_ip(self): def test_render_internal_ip(self):
@ -185,10 +193,12 @@ class GoogleAnalyticsTagTestCase(TagTestCase):
GoogleAnalyticsNode().render(context) GoogleAnalyticsNode().render(context)
@override_settings(GOOGLE_ANALYTICS_PROPERTY_ID='UA-123456-7', @override_settings(
GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_MULTIPLE_DOMAINS, GOOGLE_ANALYTICS_PROPERTY_ID='UA-123456-7',
GOOGLE_ANALYTICS_DOMAIN=None, GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_MULTIPLE_DOMAINS,
ANALYTICAL_DOMAIN=None) GOOGLE_ANALYTICS_DOMAIN=None,
ANALYTICAL_DOMAIN=None,
)
class NoDomainTestCase(TestCase): class NoDomainTestCase(TestCase):
def test_exception_without_domain(self): def test_exception_without_domain(self):
context = Context() context = Context()

View file

@ -64,21 +64,29 @@ class GoogleAnalyticsTagTestCase(TagTestCase):
The user_id variable must be set according to The user_id variable must be set according to
google_analytics_gtag_identity variable in the context. google_analytics_gtag_identity variable in the context.
""" """
r = GoogleAnalyticsGTagNode().render(Context({ r = GoogleAnalyticsGTagNode().render(
'google_analytics_gtag_identity': 'foo_gtag_identity', Context(
'analytical_identity': 'bar_analytical_identity', {
'user': User(username='test'), '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 assert "gtag('set', {'user_id': 'foo_gtag_identity'});" in r
def test_identity_context_general(self): def test_identity_context_general(self):
""" """
The user_id variable must be set according to analytical_identity variable in the context. The user_id variable must be set according to analytical_identity variable in the context.
""" """
r = GoogleAnalyticsGTagNode().render(Context({ r = GoogleAnalyticsGTagNode().render(
'analytical_identity': 'bar_analytical_identity', Context(
'user': User(username='test'), {
})) 'analytical_identity': 'bar_analytical_identity',
'user': User(username='test'),
}
)
)
assert "gtag('set', {'user_id': 'bar_analytical_identity'});" in r assert "gtag('set', {'user_id': 'bar_analytical_identity'});" in r
@override_settings(GOOGLE_ANALYTICS_GTAG_PROPERTY_ID='G-12345678') @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 from analytical.utils import AnalyticalException
@override_settings(GOOGLE_ANALYTICS_JS_PROPERTY_ID='UA-123456-7', @override_settings(
GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_SINGLE_DOMAIN) GOOGLE_ANALYTICS_JS_PROPERTY_ID='UA-123456-7',
GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_SINGLE_DOMAIN,
)
class GoogleAnalyticsTagTestCase(TagTestCase): class GoogleAnalyticsTagTestCase(TagTestCase):
""" """
Tests for the ``google_analytics_js`` template tag. Tests for the ``google_analytics_js`` template tag.
@ -26,19 +28,25 @@ class GoogleAnalyticsTagTestCase(TagTestCase):
def test_tag(self): def test_tag(self):
r = self.render_tag('google_analytics_js', 'google_analytics_js') 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), (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) 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('create', 'UA-123456-7', 'auto', {});" in r
assert "ga('send', 'pageview');" in r assert "ga('send', 'pageview');" in r
def test_node(self): def test_node(self):
r = GoogleAnalyticsJsNode().render(Context()) 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), (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) 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('create', 'UA-123456-7', 'auto', {});" in r
assert "ga('send', 'pageview');" 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): with pytest.raises(AnalyticalException):
GoogleAnalyticsJsNode() GoogleAnalyticsJsNode()
@override_settings(GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_MULTIPLE_SUBDOMAINS, @override_settings(
GOOGLE_ANALYTICS_DOMAIN='example.com') GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_MULTIPLE_SUBDOMAINS,
GOOGLE_ANALYTICS_DOMAIN='example.com',
)
def test_track_multiple_subdomains(self): def test_track_multiple_subdomains(self):
r = GoogleAnalyticsJsNode().render(Context()) 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, @override_settings(
GOOGLE_ANALYTICS_DOMAIN='example.com') GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_MULTIPLE_DOMAINS,
GOOGLE_ANALYTICS_DOMAIN='example.com',
)
def test_track_multiple_domains(self): def test_track_multiple_domains(self):
r = GoogleAnalyticsJsNode().render(Context()) r = GoogleAnalyticsJsNode().render(Context())
assert "ga('create', 'UA-123456-7', 'auto', {" in r assert "ga('create', 'UA-123456-7', 'auto', {" in r
assert '"legacyCookieDomain": "example.com"' in r assert '"legacyCookieDomain": "example.com"' in r
assert '"allowLinker\": true' in r assert '"allowLinker": true' in r
def test_custom_vars(self): def test_custom_vars(self):
context = Context({ context = Context(
'google_analytics_var1': ('test1', 'foo'), {
'google_analytics_var2': ('test2', 'bar'), 'google_analytics_var1': ('test1', 'foo'),
'google_analytics_var4': ('test4', 1), 'google_analytics_var2': ('test2', 'bar'),
'google_analytics_var5': ('test5', 2.2), 'google_analytics_var4': ('test4', 1),
}) 'google_analytics_var5': ('test5', 2.2),
}
)
r = GoogleAnalyticsJsNode().render(context) r = GoogleAnalyticsJsNode().render(context)
assert "ga('set', 'test1', 'foo');" in r assert "ga('set', 'test1', 'foo');" in r
assert "ga('set', 'test2', 'bar');" 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): def test_display_advertising(self):
with override_settings(GOOGLE_ANALYTICS_DISPLAY_ADVERTISING=True): with override_settings(GOOGLE_ANALYTICS_DISPLAY_ADVERTISING=True):
r = GoogleAnalyticsJsNode().render(Context()) r = GoogleAnalyticsJsNode().render(Context())
assert """ga('create', 'UA-123456-7', 'auto', {}); assert (
"""ga('create', 'UA-123456-7', 'auto', {});
ga('require', 'displayfeatures'); ga('require', 'displayfeatures');
ga('send', 'pageview');""" in r ga('send', 'pageview');"""
in r
)
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1']) @override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
def test_render_internal_ip(self): def test_render_internal_ip(self):
@ -92,8 +112,7 @@ ga('send', 'pageview');""" in r
req.META['REMOTE_ADDR'] = '1.1.1.1' req.META['REMOTE_ADDR'] = '1.1.1.1'
context = Context({'request': req}) context = Context({'request': req})
r = GoogleAnalyticsJsNode().render(context) r = GoogleAnalyticsJsNode().render(context)
assert r.startswith( assert r.startswith('<!-- Google Analytics disabled on internal IP address')
'<!-- Google Analytics disabled on internal IP address')
assert r.endswith('-->') assert r.endswith('-->')
@override_settings(GOOGLE_ANALYTICS_ANONYMIZE_IP=True) @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) @override_settings(GOOGLE_ANALYTICS_SITE_SPEED_SAMPLE_RATE=0.0)
def test_set_site_speed_sample_rate_min(self): def test_set_site_speed_sample_rate_min(self):
r = GoogleAnalyticsJsNode().render(Context()) 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') @override_settings(GOOGLE_ANALYTICS_SITE_SPEED_SAMPLE_RATE='100.00')
def test_set_site_speed_sample_rate_max(self): def test_set_site_speed_sample_rate_max(self):
r = GoogleAnalyticsJsNode().render(Context()) 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) @override_settings(GOOGLE_ANALYTICS_SITE_SPEED_SAMPLE_RATE=-1)
def test_exception_whenset_site_speed_sample_rate_too_small(self): def test_exception_whenset_site_speed_sample_rate_too_small(self):
@ -167,10 +191,12 @@ ga('send', 'pageview');""" in r
GoogleAnalyticsJsNode().render(context) GoogleAnalyticsJsNode().render(context)
@override_settings(GOOGLE_ANALYTICS_JS_PROPERTY_ID='UA-123456-7', @override_settings(
GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_MULTIPLE_DOMAINS, GOOGLE_ANALYTICS_JS_PROPERTY_ID='UA-123456-7',
GOOGLE_ANALYTICS_DOMAIN=None, GOOGLE_ANALYTICS_TRACKING_STYLE=TRACK_MULTIPLE_DOMAINS,
ANALYTICAL_DOMAIN=None) GOOGLE_ANALYTICS_DOMAIN=None,
ANALYTICAL_DOMAIN=None,
)
class NoDomainTestCase(TestCase): class NoDomainTestCase(TestCase):
def test_exception_without_domain(self): def test_exception_without_domain(self):
context = Context() context = Context()

View file

@ -39,17 +39,25 @@ class GoSquaredTagTestCase(TagTestCase):
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True) @override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_auto_identify(self): def test_auto_identify(self):
r = GoSquaredNode().render(Context({ r = GoSquaredNode().render(
'user': User(username='test', first_name='Test', last_name='User'), Context(
})) {
'user': User(username='test', first_name='Test', last_name='User'),
}
)
)
assert 'GoSquared.UserName = "Test User";' in r assert 'GoSquared.UserName = "Test User";' in r
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True) @override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_manual_identify(self): def test_manual_identify(self):
r = GoSquaredNode().render(Context({ r = GoSquaredNode().render(
'user': User(username='test', first_name='Test', last_name='User'), Context(
'gosquared_identity': 'test_identity', {
})) 'user': User(username='test', first_name='Test', last_name='User'),
'gosquared_identity': 'test_identity',
}
)
)
assert 'GoSquared.UserName = "test_identity";' in r assert 'GoSquared.UserName = "test_identity";' in r
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True) @override_settings(ANALYTICAL_AUTO_IDENTIFY=True)

View file

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

View file

@ -1,6 +1,7 @@
""" """
Tests for the Hotjar template tags. Tests for the Hotjar template tags.
""" """
import pytest import pytest
from django.http import HttpRequest from django.http import HttpRequest
from django.template import Context, Template, TemplateSyntaxError from django.template import Context, Template, TemplateSyntaxError
@ -27,7 +28,6 @@ expected_html = """\
@override_settings(HOTJAR_SITE_ID='123456789') @override_settings(HOTJAR_SITE_ID='123456789')
class HotjarTagTestCase(TagTestCase): class HotjarTagTestCase(TagTestCase):
maxDiff = None maxDiff = None
def test_tag(self): def test_tag(self):
@ -44,13 +44,14 @@ class HotjarTagTestCase(TagTestCase):
@override_settings(HOTJAR_SITE_ID=None) @override_settings(HOTJAR_SITE_ID=None)
def test_no_id(self): 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() HotjarNode()
@override_settings(HOTJAR_SITE_ID='invalid') @override_settings(HOTJAR_SITE_ID='invalid')
def test_invalid_id(self): def test_invalid_id(self):
expected_pattern = ( expected_pattern = r"^HOTJAR_SITE_ID setting: must be \(a string containing\) a number: 'invalid'$"
r"^HOTJAR_SITE_ID setting: must be \(a string containing\) a number: 'invalid'$")
with pytest.raises(AnalyticalException, match=expected_pattern): with pytest.raises(AnalyticalException, match=expected_pattern):
HotjarNode() HotjarNode()
@ -61,11 +62,13 @@ class HotjarTagTestCase(TagTestCase):
context = Context({'request': request}) context = Context({'request': request})
actual_html = HotjarNode().render(context) actual_html = HotjarNode().render(context)
disabled_html = '\n'.join([ disabled_html = '\n'.join(
[
'<!-- Hotjar disabled on internal IP address', '<!-- Hotjar disabled on internal IP address',
expected_html, expected_html,
'-->', '-->',
]) ]
)
assert disabled_html == actual_html assert disabled_html == actual_html
def test_contribute_to_analytical(self): 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 from analytical.utils import AnalyticalException
@override_settings(INTERCOM_APP_ID="abc123xyz") @override_settings(INTERCOM_APP_ID='abc123xyz')
class IntercomTagTestCase(TagTestCase): class IntercomTagTestCase(TagTestCase):
""" """
Tests for the ``intercom`` template tag. Tests for the ``intercom`` template tag.
@ -23,7 +23,9 @@ class IntercomTagTestCase(TagTestCase):
def test_tag(self): def test_tag(self):
rendered_tag = self.render_tag('intercom', 'intercom') 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): def test_node(self):
now = datetime.datetime(2014, 4, 9, 15, 15, 0) now = datetime.datetime(2014, 4, 9, 15, 15, 0)
@ -31,17 +33,21 @@ class IntercomTagTestCase(TagTestCase):
username='test', username='test',
first_name='Firstname', first_name='Firstname',
last_name='Lastname', last_name='Lastname',
email="test@example.com", email='test@example.com',
date_joined=now, date_joined=now,
) )
rendered_tag = IntercomNode().render(Context({'user': user})) rendered_tag = IntercomNode().render(Context({'user': user}))
# Because the json isn't predictably ordered, we can't just test the whole thing verbatim. # 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"> <script id="IntercomSettingsScriptTag">
window.intercomSettings = {"app_id": "abc123xyz", "created_at": 1397074500, "email": "test@example.com", "name": "Firstname Lastname", "user_id": %(user_id)s}; window.intercomSettings = {"app_id": "abc123xyz", "created_at": 1397074500, "email": "test@example.com", "name": "Firstname Lastname", "user_id": %(user_id)s};
</script> </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> <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) @override_settings(INTERCOM_APP_ID=None)
def test_no_account_number(self): def test_no_account_number(self):
@ -59,32 +65,40 @@ class IntercomTagTestCase(TagTestCase):
username='test', username='test',
first_name='Firstname', first_name='Firstname',
last_name='Lastname', last_name='Lastname',
email="test@example.com", email='test@example.com',
date_joined=now, date_joined=now,
) )
r = IntercomNode().render(Context({ r = IntercomNode().render(
'user': user, Context(
})) {
'user': user,
}
)
)
assert ( assert (
'window.intercomSettings = {"app_id": "abc123xyz", "created_at": 1397074500, ' 'window.intercomSettings = {"app_id": "abc123xyz", "created_at": 1397074500, '
f'"email": "test@example.com", "name": "Firstname Lastname", "user_id": {user.pk}}};' f'"email": "test@example.com", "name": "Firstname Lastname", "user_id": {user.pk}}};'
) in r ) in r
def test_custom(self): def test_custom(self):
r = IntercomNode().render(Context({ r = IntercomNode().render(
'intercom_var1': 'val1', Context({'intercom_var1': 'val1', 'intercom_var2': 'val2'})
'intercom_var2': 'val2' )
}))
assert 'var1": "val1", "var2": "val2"' in r assert 'var1": "val1", "var2": "val2"' in r
def test_identify_name_and_email(self): def test_identify_name_and_email(self):
r = IntercomNode().render(Context({ r = IntercomNode().render(
'user': User( Context(
username='test', {
first_name='Firstname', 'user': User(
last_name='Lastname', username='test',
email="test@example.com"), first_name='Firstname',
})) last_name='Lastname',
email='test@example.com',
),
}
)
)
assert '"email": "test@example.com", "name": "Firstname Lastname"' in r assert '"email": "test@example.com", "name": "Firstname Lastname"' in r
def test_identify_username_no_email(self): def test_identify_username_no_email(self):
@ -92,17 +106,25 @@ class IntercomTagTestCase(TagTestCase):
assert '"name": "test"' in r, r assert '"name": "test"' in r, r
def test_no_identify_when_explicit_name(self): def test_no_identify_when_explicit_name(self):
r = IntercomNode().render(Context({ r = IntercomNode().render(
'intercom_name': 'explicit', Context(
'user': User(username='implicit'), {
})) 'intercom_name': 'explicit',
'user': User(username='implicit'),
}
)
)
assert '"name": "explicit"' in r, r assert '"name": "explicit"' in r, r
def test_no_identify_when_explicit_email(self): def test_no_identify_when_explicit_email(self):
r = IntercomNode().render(Context({ r = IntercomNode().render(
'intercom_email': 'explicit', Context(
'user': User(username='implicit'), {
})) 'intercom_email': 'explicit',
'user': User(username='implicit'),
}
)
)
assert '"email": "explicit"' in r, r assert '"email": "explicit"' in r, r
@override_settings(INTERCOM_HMAC_SECRET_KEY='secret') @override_settings(INTERCOM_HMAC_SECRET_KEY='secret')
@ -135,10 +157,14 @@ class IntercomTagTestCase(TagTestCase):
""" """
'user_hash' of context-provided `user_id`. 'user_hash' of context-provided `user_id`.
""" """
attrs = IntercomNode()._get_custom_attrs(Context({ attrs = IntercomNode()._get_custom_attrs(
'intercom_email': 'test@example.com', Context(
'intercom_user_id': '5', {
})) 'intercom_email': 'test@example.com',
'intercom_user_id': '5',
}
)
)
assert attrs == { assert attrs == {
'created_at': None, 'created_at': None,
'email': 'test@example.com', 'email': 'test@example.com',
@ -152,9 +178,13 @@ class IntercomTagTestCase(TagTestCase):
""" """
'user_hash' of context-provided `email`. 'user_hash' of context-provided `email`.
""" """
attrs = IntercomNode()._get_custom_attrs(Context({ attrs = IntercomNode()._get_custom_attrs(
'intercom_email': 'test@example.com', Context(
})) {
'intercom_email': 'test@example.com',
}
)
)
assert attrs == { assert attrs == {
'created_at': None, 'created_at': None,
'email': 'test@example.com', 'email': 'test@example.com',

View file

@ -20,11 +20,11 @@ class KissInsightsTagTestCase(TagTestCase):
def test_tag(self): def test_tag(self):
r = self.render_tag('kiss_insights', 'kiss_insights') 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): def test_node(self):
r = KissInsightsNode().render(Context()) 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) @override_settings(KISS_INSIGHTS_ACCOUNT_NUMBER=None)
def test_no_account_number(self): def test_no_account_number(self):

View file

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

View file

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

View file

@ -31,20 +31,19 @@ class MatomoTagTestCase(TagTestCase):
assert "_paq.push(['setSiteId', 345]);" in r assert "_paq.push(['setSiteId', 345]);" in r
assert 'img src="//example.com/matomo.php?idsite=345"' in r assert 'img src="//example.com/matomo.php?idsite=345"' in r
@override_settings(MATOMO_DOMAIN_PATH='example.com/matomo', @override_settings(MATOMO_DOMAIN_PATH='example.com/matomo', MATOMO_SITE_ID='345')
MATOMO_SITE_ID='345')
def test_domain_path_valid(self): def test_domain_path_valid(self):
r = self.render_tag('matomo', 'matomo') r = self.render_tag('matomo', 'matomo')
assert '"//example.com/matomo/"' in r assert '"//example.com/matomo/"' in r
@override_settings(MATOMO_DOMAIN_PATH='example.com:1234', @override_settings(MATOMO_DOMAIN_PATH='example.com:1234', MATOMO_SITE_ID='345')
MATOMO_SITE_ID='345')
def test_domain_port_valid(self): def test_domain_port_valid(self):
r = self.render_tag('matomo', 'matomo') r = self.render_tag('matomo', 'matomo')
assert '"//example.com:1234/";' in r assert '"//example.com:1234/";' in r
@override_settings(MATOMO_DOMAIN_PATH='example.com:1234/matomo', @override_settings(
MATOMO_SITE_ID='345') MATOMO_DOMAIN_PATH='example.com:1234/matomo', MATOMO_SITE_ID='345'
)
def test_domain_port_path_valid(self): def test_domain_port_path_valid(self):
r = self.render_tag('matomo', 'matomo') r = self.render_tag('matomo', 'matomo')
assert '"//example.com:1234/matomo/"' in r assert '"//example.com:1234/matomo/"' in r
@ -104,46 +103,54 @@ class MatomoTagTestCase(TagTestCase):
assert r.endswith('-->') assert r.endswith('-->')
def test_uservars(self): def test_uservars(self):
context = Context({'matomo_vars': [(1, 'foo', 'foo_val'), context = Context(
(2, 'bar', 'bar_val', 'page'), {
(3, 'spam', 'spam_val', 'visit')]}) 'matomo_vars': [
(1, 'foo', 'foo_val'),
(2, 'bar', 'bar_val', 'page'),
(3, 'spam', 'spam_val', 'visit'),
]
}
)
r = MatomoNode().render(context) r = MatomoNode().render(context)
for var_code in ['_paq.push(["setCustomVariable", 1, "foo", "foo_val", "page"]);', for var_code in [
'_paq.push(["setCustomVariable", 2, "bar", "bar_val", "page"]);', '_paq.push(["setCustomVariable", 1, "foo", "foo_val", "page"]);',
'_paq.push(["setCustomVariable", 3, "spam", "spam_val", "visit"]);']: '_paq.push(["setCustomVariable", 2, "bar", "bar_val", "page"]);',
'_paq.push(["setCustomVariable", 3, "spam", "spam_val", "visit"]);',
]:
assert var_code in r assert var_code in r
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True) @override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_default_usertrack(self): def test_default_usertrack(self):
context = Context({ context = Context(
'user': User(username='BDFL', first_name='Guido', last_name='van Rossum') {'user': User(username='BDFL', first_name='Guido', last_name='van Rossum')}
}) )
r = MatomoNode().render(context) r = MatomoNode().render(context)
var_code = '_paq.push(["setUserId", "BDFL"]);' var_code = '_paq.push(["setUserId", "BDFL"]);'
assert var_code in r assert var_code in r
def test_matomo_usertrack(self): def test_matomo_usertrack(self):
context = Context({ context = Context({'matomo_identity': 'BDFL'})
'matomo_identity': 'BDFL'
})
r = MatomoNode().render(context) r = MatomoNode().render(context)
var_code = '_paq.push(["setUserId", "BDFL"]);' var_code = '_paq.push(["setUserId", "BDFL"]);'
assert var_code in r assert var_code in r
def test_analytical_usertrack(self): def test_analytical_usertrack(self):
context = Context({ context = Context({'analytical_identity': 'BDFL'})
'analytical_identity': 'BDFL'
})
r = MatomoNode().render(context) r = MatomoNode().render(context)
var_code = '_paq.push(["setUserId", "BDFL"]);' var_code = '_paq.push(["setUserId", "BDFL"]);'
assert var_code in r assert var_code in r
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True) @override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_disable_usertrack(self): def test_disable_usertrack(self):
context = Context({ context = Context(
'user': User(username='BDFL', first_name='Guido', last_name='van Rossum'), {
'matomo_identity': None 'user': User(
}) username='BDFL', first_name='Guido', last_name='van Rossum'
),
'matomo_identity': None,
}
)
r = MatomoNode().render(context) r = MatomoNode().render(context)
var_code = '_paq.push(["setUserId", "BDFL"]);' var_code = '_paq.push(["setUserId", "BDFL"]);'
assert var_code not in r assert var_code not in r

View file

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

View file

@ -38,10 +38,17 @@ class OlarkTestCase(TagTestCase):
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True) @override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify(self): def test_identify(self):
r = OlarkNode().render(Context({ r = OlarkNode().render(
'user': User(username='test', first_name='Test', last_name='User'), Context(
})) {
assert "olark('api.chat.updateVisitorNickname', {snippet: 'Test User (test)'});" in r '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) @override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify_anonymous_user(self): def test_identify_anonymous_user(self):
@ -58,37 +65,41 @@ class OlarkTestCase(TagTestCase):
'{snippet: "teststatus"});' in r '{snippet: "teststatus"});' in r
def test_status_string_list(self): def test_status_string_list(self):
r = OlarkNode().render(Context({ r = OlarkNode().render(
'olark_status': ['teststatus1', 'teststatus2'], Context(
})) {
'olark_status': ['teststatus1', 'teststatus2'],
}
)
)
assert "olark('api.chat.updateVisitorStatus', " assert "olark('api.chat.updateVisitorStatus', "
'{snippet: ["teststatus1", "teststatus2"]});' in r '{snippet: ["teststatus1", "teststatus2"]});' in r
def test_messages(self): def test_messages(self):
messages = [ messages = [
"welcome_title", 'welcome_title',
"chatting_title", 'chatting_title',
"unavailable_title", 'unavailable_title',
"busy_title", 'busy_title',
"away_message", 'away_message',
"loading_title", 'loading_title',
"welcome_message", 'welcome_message',
"busy_message", 'busy_message',
"chat_input_text", 'chat_input_text',
"name_input_text", 'name_input_text',
"email_input_text", 'email_input_text',
"offline_note_message", 'offline_note_message',
"send_button_text", 'send_button_text',
"offline_note_thankyou_text", 'offline_note_thankyou_text',
"offline_note_error_text", 'offline_note_error_text',
"offline_note_sending_text", 'offline_note_sending_text',
"operator_is_typing_text", 'operator_is_typing_text',
"operator_has_stopped_typing_text", 'operator_has_stopped_typing_text',
"introduction_error_text", 'introduction_error_text',
"introduction_messages", 'introduction_messages',
"introduction_submit_button_text", 'introduction_submit_button_text',
] ]
vars = {f'olark_{m}': m for m in messages} vars = {f'olark_{m}': m for m in messages}
r = OlarkNode().render(Context(vars)) r = OlarkNode().render(Context(vars))
for m in messages: 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): def test_tag(self):
r = self.render_tag('rating_mailru', 'rating_mailru') 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): def test_node(self):
r = RatingMailruNode().render(Context({})) 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) @override_settings(RATING_MAILRU_COUNTER_ID=None)
def test_no_site_id(self): 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_WIDGET_ID=WIDGET_ID,
SNAPENGAGE_BUTTON=BUTTON_STYLE_DEFAULT, SNAPENGAGE_BUTTON=BUTTON_STYLE_DEFAULT,
SNAPENGAGE_BUTTON_LOCATION=BUTTON_LOCATION_LEFT, SNAPENGAGE_BUTTON_LOCATION=BUTTON_LOCATION_LEFT,
SNAPENGAGE_BUTTON_OFFSET="55%", SNAPENGAGE_BUTTON_OFFSET='55%',
) )
class SnapEngageTestCase(TagTestCase): class SnapEngageTestCase(TagTestCase):
""" """
@ -38,11 +38,15 @@ class SnapEngageTestCase(TagTestCase):
def test_tag(self): def test_tag(self):
r = self.render_tag('snapengage', 'snapengage') 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): def test_node(self):
r = SnapEngageNode().render(Context()) 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) @override_settings(SNAPENGAGE_WIDGET_ID=None)
def test_no_site_id(self): def test_no_site_id(self):
@ -55,142 +59,220 @@ class SnapEngageTestCase(TagTestCase):
SnapEngageNode() SnapEngageNode()
def test_no_button(self): def test_no_button(self):
r = SnapEngageNode().render(Context({ r = SnapEngageNode().render(
'snapengage_button': BUTTON_STYLE_NONE, Context(
})) {
'snapengage_button': BUTTON_STYLE_NONE,
}
)
)
assert 'SnapABug.init("ec329c69-0bf0-4db8-9b77-3f8150fb977e")' in r assert 'SnapABug.init("ec329c69-0bf0-4db8-9b77-3f8150fb977e")' in r
with override_settings(SNAPENGAGE_BUTTON=BUTTON_STYLE_NONE): with override_settings(SNAPENGAGE_BUTTON=BUTTON_STYLE_NONE):
r = SnapEngageNode().render(Context()) r = SnapEngageNode().render(Context())
assert 'SnapABug.init("ec329c69-0bf0-4db8-9b77-3f8150fb977e")' in r assert 'SnapABug.init("ec329c69-0bf0-4db8-9b77-3f8150fb977e")' in r
def test_live_button(self): def test_live_button(self):
r = SnapEngageNode().render(Context({ r = SnapEngageNode().render(
'snapengage_button': BUTTON_STYLE_LIVE, Context(
})) {
assert 'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","0","55%",true);' in r '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): with override_settings(SNAPENGAGE_BUTTON=BUTTON_STYLE_LIVE):
r = SnapEngageNode().render(Context()) 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): def test_custom_button(self):
r = SnapEngageNode().render(Context({ r = SnapEngageNode().render(
'snapengage_button': "http://www.example.com/button.png", Context(
})) {
assert 'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","0","55%");' in r '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 assert 'SnapABug.setButton("http://www.example.com/button.png");' in r
with override_settings( with override_settings(SNAPENGAGE_BUTTON='http://www.example.com/button.png'):
SNAPENGAGE_BUTTON="http://www.example.com/button.png"):
r = SnapEngageNode().render(Context()) 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 assert 'SnapABug.setButton("http://www.example.com/button.png");' in r
def test_button_location_right(self): def test_button_location_right(self):
r = SnapEngageNode().render(Context({ r = SnapEngageNode().render(
'snapengage_button_location': BUTTON_LOCATION_RIGHT, Context(
})) {
assert 'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","1","55%");' in r '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): with override_settings(SNAPENGAGE_BUTTON_LOCATION=BUTTON_LOCATION_RIGHT):
r = SnapEngageNode().render(Context()) 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): def test_button_location_top(self):
r = SnapEngageNode().render(Context({ r = SnapEngageNode().render(
'snapengage_button_location': BUTTON_LOCATION_TOP, Context(
})) {
assert 'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","2","55%");' in r '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): with override_settings(SNAPENGAGE_BUTTON_LOCATION=BUTTON_LOCATION_TOP):
r = SnapEngageNode().render(Context()) 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): def test_button_location_bottom(self):
r = SnapEngageNode().render(Context({ r = SnapEngageNode().render(
'snapengage_button_location': BUTTON_LOCATION_BOTTOM, Context(
})) {
assert 'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","3","55%");' in r 'snapengage_button_location': BUTTON_LOCATION_BOTTOM,
with override_settings( }
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()) 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): def test_button_offset(self):
r = SnapEngageNode().render(Context({ r = SnapEngageNode().render(
'snapengage_button_location_offset': "30%", Context(
})) {
assert 'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","0","30%");' in r 'snapengage_button_location_offset': '30%',
with override_settings(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()) 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): def test_button_effect(self):
r = SnapEngageNode().render(Context({ r = SnapEngageNode().render(
'snapengage_button_effect': "-4px", Context(
})) {
'snapengage_button_effect': '-4px',
}
)
)
assert 'SnapABug.setButtonEffect("-4px");' in r assert 'SnapABug.setButtonEffect("-4px");' in r
with override_settings(SNAPENGAGE_BUTTON_EFFECT="-4px"): with override_settings(SNAPENGAGE_BUTTON_EFFECT='-4px'):
r = SnapEngageNode().render(Context()) r = SnapEngageNode().render(Context())
assert 'SnapABug.setButtonEffect("-4px");' in r assert 'SnapABug.setButtonEffect("-4px");' in r
def test_form_position(self): def test_form_position(self):
r = SnapEngageNode().render(Context({ r = SnapEngageNode().render(
'snapengage_form_position': FORM_POSITION_TOP_LEFT, Context(
})) {
'snapengage_form_position': FORM_POSITION_TOP_LEFT,
}
)
)
assert 'SnapABug.setChatFormPosition("tl");' in r assert 'SnapABug.setChatFormPosition("tl");' in r
with override_settings(SNAPENGAGE_FORM_POSITION=FORM_POSITION_TOP_LEFT): with override_settings(SNAPENGAGE_FORM_POSITION=FORM_POSITION_TOP_LEFT):
r = SnapEngageNode().render(Context()) r = SnapEngageNode().render(Context())
assert 'SnapABug.setChatFormPosition("tl");' in r assert 'SnapABug.setChatFormPosition("tl");' in r
def test_form_top_position(self): def test_form_top_position(self):
r = SnapEngageNode().render(Context({ r = SnapEngageNode().render(
'snapengage_form_top_position': 40, Context(
})) {
'snapengage_form_top_position': 40,
}
)
)
assert 'SnapABug.setFormTopPosition(40);' in r assert 'SnapABug.setFormTopPosition(40);' in r
with override_settings(SNAPENGAGE_FORM_TOP_POSITION=40): with override_settings(SNAPENGAGE_FORM_TOP_POSITION=40):
r = SnapEngageNode().render(Context()) r = SnapEngageNode().render(Context())
assert 'SnapABug.setFormTopPosition(40);' in r assert 'SnapABug.setFormTopPosition(40);' in r
def test_domain(self): def test_domain(self):
r = SnapEngageNode().render(Context({ r = SnapEngageNode().render(Context({'snapengage_domain': 'example.com'}))
'snapengage_domain': "example.com"}))
assert 'SnapABug.setDomain("example.com");' in r 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()) r = SnapEngageNode().render(Context())
assert 'SnapABug.setDomain("example.com");' in r assert 'SnapABug.setDomain("example.com");' in r
def test_secure_connection(self): def test_secure_connection(self):
r = SnapEngageNode().render(Context({ r = SnapEngageNode().render(Context({'snapengage_secure_connection': True}))
'snapengage_secure_connection': True}))
assert 'SnapABug.setSecureConnexion();' in r assert 'SnapABug.setSecureConnexion();' in r
with override_settings(SNAPENGAGE_SECURE_CONNECTION=True): with override_settings(SNAPENGAGE_SECURE_CONNECTION=True):
r = SnapEngageNode().render(Context()) r = SnapEngageNode().render(Context())
assert 'SnapABug.setSecureConnexion();' in r assert 'SnapABug.setSecureConnexion();' in r
def test_show_offline(self): def test_show_offline(self):
r = SnapEngageNode().render(Context({ r = SnapEngageNode().render(
'snapengage_show_offline': False, Context(
})) {
'snapengage_show_offline': False,
}
)
)
assert 'SnapABug.allowOffline(false);' in r assert 'SnapABug.allowOffline(false);' in r
with override_settings(SNAPENGAGE_SHOW_OFFLINE=False): with override_settings(SNAPENGAGE_SHOW_OFFLINE=False):
r = SnapEngageNode().render(Context()) r = SnapEngageNode().render(Context())
assert 'SnapABug.allowOffline(false);' in r assert 'SnapABug.allowOffline(false);' in r
def test_proactive_chat(self): def test_proactive_chat(self):
r = SnapEngageNode().render(Context({ r = SnapEngageNode().render(Context({'snapengage_proactive_chat': False}))
'snapengage_proactive_chat': False}))
assert 'SnapABug.allowProactiveChat(false);' in r assert 'SnapABug.allowProactiveChat(false);' in r
def test_screenshot(self): def test_screenshot(self):
r = SnapEngageNode().render(Context({ r = SnapEngageNode().render(
'snapengage_screenshots': False, Context(
})) {
'snapengage_screenshots': False,
}
)
)
assert 'SnapABug.allowScreenshot(false);' in r assert 'SnapABug.allowScreenshot(false);' in r
with override_settings(SNAPENGAGE_SCREENSHOTS=False): with override_settings(SNAPENGAGE_SCREENSHOTS=False):
r = SnapEngageNode().render(Context()) r = SnapEngageNode().render(Context())
assert 'SnapABug.allowScreenshot(false);' in r assert 'SnapABug.allowScreenshot(false);' in r
def test_offline_screenshots(self): def test_offline_screenshots(self):
r = SnapEngageNode().render(Context({ r = SnapEngageNode().render(
'snapengage_offline_screenshots': False, Context(
})) {
'snapengage_offline_screenshots': False,
}
)
)
assert 'SnapABug.showScreenshotOption(false);' in r assert 'SnapABug.showScreenshotOption(false);' in r
with override_settings(SNAPENGAGE_OFFLINE_SCREENSHOTS=False): with override_settings(SNAPENGAGE_OFFLINE_SCREENSHOTS=False):
r = SnapEngageNode().render(Context()) r = SnapEngageNode().render(Context())
@ -205,35 +287,55 @@ class SnapEngageTestCase(TagTestCase):
@override_settings(SNAPENGAGE_READONLY_EMAIL=False) @override_settings(SNAPENGAGE_READONLY_EMAIL=False)
def test_email(self): def test_email(self):
r = SnapEngageNode().render(Context({ r = SnapEngageNode().render(
'snapengage_email': 'test@example.com', Context(
})) {
'snapengage_email': 'test@example.com',
}
)
)
assert 'SnapABug.setUserEmail("test@example.com");' in r assert 'SnapABug.setUserEmail("test@example.com");' in r
def test_email_readonly(self): def test_email_readonly(self):
r = SnapEngageNode().render(Context({ r = SnapEngageNode().render(
'snapengage_email': 'test@example.com', Context(
'snapengage_readonly_email': True, {
})) 'snapengage_email': 'test@example.com',
'snapengage_readonly_email': True,
}
)
)
assert 'SnapABug.setUserEmail("test@example.com",true);' in r assert 'SnapABug.setUserEmail("test@example.com",true);' in r
with override_settings(SNAPENGAGE_READONLY_EMAIL=True): with override_settings(SNAPENGAGE_READONLY_EMAIL=True):
r = SnapEngageNode().render(Context({ r = SnapEngageNode().render(
'snapengage_email': 'test@example.com', Context(
})) {
'snapengage_email': 'test@example.com',
}
)
)
assert 'SnapABug.setUserEmail("test@example.com",true);' in r assert 'SnapABug.setUserEmail("test@example.com",true);' in r
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True) @override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify(self): def test_identify(self):
r = SnapEngageNode().render(Context({ r = SnapEngageNode().render(
'user': User(username='test', email='test@example.com'), Context(
})) {
'user': User(username='test', email='test@example.com'),
}
)
)
assert 'SnapABug.setUserEmail("test@example.com");' in r assert 'SnapABug.setUserEmail("test@example.com");' in r
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True) @override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
def test_identify_anonymous_user(self): def test_identify_anonymous_user(self):
r = SnapEngageNode().render(Context({ r = SnapEngageNode().render(
'user': AnonymousUser(), Context(
})) {
'user': AnonymousUser(),
}
)
)
assert 'SnapABug.setUserEmail(' not in r assert 'SnapABug.setUserEmail(' not in r
def test_language(self): def test_language(self):

View file

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

View file

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

View file

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

View file

@ -2,7 +2,6 @@
Tests for the Yandex.Metrica template tags and filters. Tests for the Yandex.Metrica template tags and filters.
""" """
import pytest import pytest
from django.http import HttpRequest from django.http import HttpRequest
from django.template import Context from django.template import Context
@ -21,11 +20,11 @@ class YandexMetricaTagTestCase(TagTestCase):
def test_tag(self): def test_tag(self):
r = self.render_tag('yandex_metrica', 'yandex_metrica') 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): def test_node(self):
r = YandexMetricaNode().render(Context({})) 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) @override_settings(YANDEX_METRICA_COUNTER_ID=None)
def test_no_site_id(self): def test_no_site_id(self):

View file

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

View file

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