diff --git a/analytical/__init__.py b/analytical/__init__.py
index 29462f7..aebc2c2 100644
--- a/analytical/__init__.py
+++ b/analytical/__init__.py
@@ -13,10 +13,3 @@ __email__ = "joost@cassee.net"
__version__ = "0.2.0alpha"
__copyright__ = "Copyright (C) 2011 Joost Cassee"
__license__ = "MIT License"
-
-try:
- from collections import namedtuple
-except ImportError:
- namedtuple = lambda name, fields: lambda *values: values
-
-Property = namedtuple('Property', ['num', 'name', 'value'])
diff --git a/analytical/context_processors.py b/analytical/context_processors.py
deleted file mode 100644
index ccd09d8..0000000
--- a/analytical/context_processors.py
+++ /dev/null
@@ -1,33 +0,0 @@
-"""
-Context processors for django-analytical.
-"""
-
-from django.conf import settings
-
-
-IMPORT_SETTINGS = [
- 'ANALYTICAL_INTERNAL_IPS',
- 'ANALYTICAL_SERVICES',
- 'CHARTBEAT_USER_ID',
- 'CLICKY_SITE_ID',
- 'CRAZY_EGG_ACCOUNT_NUMBER',
- 'GOOGLE_ANALYTICS_PROPERTY_ID',
- 'KISS_INSIGHTS_ACCOUNT_NUMBER',
- 'KISS_INSIGHTS_SITE_CODE',
- 'KISS_METRICS_API_KEY',
- 'MIXPANEL_TOKEN',
- 'OPTIMIZELY_ACCOUNT_NUMBER',
-]
-
-
-def settings(request):
- """
- Import all django-analytical settings into the template context.
- """
- vars = {}
- for setting in IMPORT_SETTINGS:
- try:
- vars[setting] = getattr(settings, setting)
- except AttributeError:
- pass
- return vars
diff --git a/analytical/templatetags/analytical.py b/analytical/templatetags/analytical.py
index c5a917f..4f20cf9 100644
--- a/analytical/templatetags/analytical.py
+++ b/analytical/templatetags/analytical.py
@@ -5,36 +5,24 @@ Analytical template tags and filters.
import logging
from django import template
-from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.template import Node, TemplateSyntaxError
from django.utils.importlib import import_module
-from analytical.templatetags import chartbeat, clicky, crazy_egg, \
- google_analytics, hubspot, kiss_insights, kiss_metrics, mixpanel, \
- optimizely
-
-TAG_NODES = {
- 'head_top': [
- chartbeat.ChartbeatTopNode, # Chartbeat should come first
- kiss_metrics.KissMetricsNode,
- optimizely.OptimizelyNode,
- ],
- 'head_bottom': [
- google_analytics.GoogleAnalyticsNode,
- mixpanel.MixpanelNode,
- ],
- 'body_top': [
- kiss_insights.KissInsightsNode,
- ],
- 'body_bottom': [
- clicky.ClickyNode,
- crazy_egg.CrazyEggNode,
- hubspot.HubSpotNode,
- chartbeat.ChartbeatBottomNode, # Chartbeat should come last
- ],
-}
+TAG_LOCATIONS = ['head_top', 'head_bottom', 'body_top', 'body_bottom']
+TAG_POSITIONS = ['first', None, 'last']
+TAG_MODULES = [
+ 'analytical.chartbeat',
+ 'analytical.clicky',
+ 'analytical.crazy_egg',
+ 'analytical.google_analytics',
+ 'analytical.hubspot',
+ 'analytical.kiss_insights',
+ 'analytical.kiss_metrics',
+ 'analytical.mixpanel',
+ 'analytical.optimizely'
+]
logger = logging.getLogger(__name__)
@@ -49,29 +37,36 @@ def _location_tag(location):
return AnalyticalNode(location)
return analytical_tag
-for loc in TAG_NODES.keys():
+for loc in TAG_LOCATIONS:
register.tag('analytical_%s' % loc, _location_tag(loc))
class AnalyticalNode(Node):
def __init__(self, location):
- self.nodes = template_nodes[location]
+ self.nodes = [node_cls() for node_cls in template_nodes[location]]
def render(self, context):
return "".join([node.render(context) for node in self.nodes])
def _load_template_nodes():
- location_nodes = {}
- for location, node_classes in TAG_NODES.items():
- location_nodes[location] = []
- for node_class in node_classes:
- try:
- node = node_class()
- except ImproperlyConfigured, e:
- logger.debug("not loading analytical service '%s': %s",
- node_class.name, e)
- location_nodes.append(node)
- return location_nodes
+ template_nodes = dict((l, dict((p, []) for p in TAG_POSITIONS))
+ for l in TAG_LOCATIONS)
+ def add_node_cls(location, node, position=None):
+ template_nodes[location][position].append(node)
+ for path in TAG_MODULES:
+ module = _import_tag_module(path)
+ try:
+ module.contribute_to_analytical(add_node_cls)
+ except ImproperlyConfigured, e:
+ logger.debug("not loading tags from '%s': %s", path, e)
+ for location in TAG_LOCATIONS:
+ template_nodes[location] = sum((template_nodes[location][p]
+ for p in TAG_POSITIONS), [])
+ return template_nodes
+
+def _import_tag_module(path):
+ app_name, lib_name = path.rsplit('.', 1)
+ return import_module("%s.templatetags.%s" % (app_name, lib_name))
template_nodes = _load_template_nodes()
diff --git a/analytical/templatetags/chartbeat.py b/analytical/templatetags/chartbeat.py
index c1b00bd..a49e7c2 100644
--- a/analytical/templatetags/chartbeat.py
+++ b/analytical/templatetags/chartbeat.py
@@ -12,7 +12,8 @@ from django.core.exceptions import ImproperlyConfigured
from django.template import Library, Node, TemplateSyntaxError
from django.utils import simplejson
-from analytical.utils import is_internal_ip, disable_html
+from analytical.utils import is_internal_ip, disable_html, validate_setting, \
+ get_required_setting
USER_ID_RE = re.compile(r'^\d{5}$')
@@ -56,8 +57,6 @@ def chartbeat_top(parser, token):
return ChartbeatTopNode()
class ChartbeatTopNode(Node):
- name = 'Chartbeat top code'
-
def render(self, context):
if is_internal_ip(context):
return disable_html(INIT_CODE, self.name)
@@ -79,10 +78,8 @@ def chartbeat_bottom(parser, token):
return ChartbeatBottomNode()
class ChartbeatBottomNode(Node):
- name = 'Chartbeat bottom code'
-
def __init__(self):
- self.user_id = self.get_required_setting(
+ self.user_id = get_required_setting(
'CHARTBEAT_USER_ID', USER_ID_RE,
"must be a string containing an five-digit number")
@@ -97,6 +94,13 @@ class ChartbeatBottomNode(Node):
if domain is not None:
config['domain'] = domain
html = SETUP_CODE % {'config': simplejson.dumps(config)}
- if is_internal_ip(context):
- html = disable_html(html, self.name)
+ if is_internal_ip(context, 'CHARTBEAT'):
+ html = disable_html(html, 'Chartbeat')
return html
+
+
+def contribute_to_analytical(add_node):
+ validate_setting('CHARTBEAT_USER_ID', USER_ID_RE,
+ "must be a string containing an five-digit number")
+ add_node('head_top', ChartbeatTopNode, 'first')
+ add_node('body_bottom', ChartbeatBottomNode, 'last')
diff --git a/analytical/templatetags/clicky.py b/analytical/templatetags/clicky.py
index a4e86b2..9cdc939 100644
--- a/analytical/templatetags/clicky.py
+++ b/analytical/templatetags/clicky.py
@@ -9,8 +9,8 @@ import re
from django.template import Library, Node, TemplateSyntaxError
from django.utils import simplejson
-from analytical.utils import get_required_setting, get_identity, \
- is_internal_ip, disable_html
+from analytical.utils import get_identity, is_internal_ip, disable_html, \
+ validate_setting, get_required_setting
SITE_ID_RE = re.compile(r'^\d{8}$')
@@ -49,24 +49,29 @@ def clicky(parser, token):
return ClickyNode()
class ClickyNode(Node):
- name = 'Clicky'
-
def __init__(self):
self.site_id = get_required_setting('CLICKY_SITE_ID', SITE_ID_RE,
"must be a string containing an eight-digit number")
def render(self, context):
custom = {}
- for var, value in context.items():
- if var.startswith('clicky_'):
- custom[var[7:]] = value
+ for dict_ in context:
+ for var, val in dict_.items():
+ if var.startswith('clicky_'):
+ custom[var[7:]] = val
if 'username' not in custom.get('session', {}):
- identity = get_identity(context)
+ identity = get_identity(context, 'clicky')
if identity is not None:
custom.setdefault('session', {})['username'] = identity
html = TRACKING_CODE % {'site_id': self.site_id,
'custom': simplejson.dumps(custom)}
- if is_internal_ip(context):
- html = disable_html(html, self.name)
+ if is_internal_ip(context, 'CLICKY'):
+ html = disable_html(html, 'Clicky')
return html
+
+
+def contribute_to_analytical(add_node):
+ validate_setting('CLICKY_SITE_ID', SITE_ID_RE,
+ "must be a string containing an eight-digit number")
+ add_node('body_bottom', ClickyNode)
diff --git a/analytical/templatetags/crazy_egg.py b/analytical/templatetags/crazy_egg.py
index 5e19a61..00abd39 100644
--- a/analytical/templatetags/crazy_egg.py
+++ b/analytical/templatetags/crazy_egg.py
@@ -8,7 +8,8 @@ import re
from django.template import Library, Node, TemplateSyntaxError
-from analytical.utils import is_internal_ip, disable_html
+from analytical.utils import is_internal_ip, disable_html, validate_setting, \
+ get_required_setting
ACCOUNT_NUMBER_RE = re.compile(r'^\d{8}$')
@@ -34,10 +35,8 @@ def crazy_egg(parser, token):
return CrazyEggNode()
class CrazyEggNode(Node):
- name = 'Crazy Egg'
-
def __init__(self):
- self.account_nr = self.get_required_setting('CRAZY_EGG_ACCOUNT_NUMBER',
+ self.account_nr = get_required_setting('CRAZY_EGG_ACCOUNT_NUMBER',
ACCOUNT_NUMBER_RE,
"must be a string containing an eight-digit number")
@@ -51,6 +50,12 @@ class CrazyEggNode(Node):
for (varnr, value) in vars)
html = '%s\n' \
% (html, js)
- if is_internal_ip(context):
- html = disable_html(html, self.name)
+ if is_internal_ip(context, 'CRAZY_EGG'):
+ html = disable_html(html, 'Crazy Egg')
return html
+
+
+def contribute_to_analytical(add_node):
+ validate_setting('CRAZY_EGG_ACCOUNT_NUMBER', ACCOUNT_NUMBER_RE,
+ "must be a string containing an eight-digit number")
+ add_node('body_bottom', CrazyEggNode)
diff --git a/analytical/templatetags/google_analytics.py b/analytical/templatetags/google_analytics.py
index f2490d8..8c67846 100644
--- a/analytical/templatetags/google_analytics.py
+++ b/analytical/templatetags/google_analytics.py
@@ -8,7 +8,8 @@ import re
from django.template import Library, Node, TemplateSyntaxError
-from analytical.utils import is_internal_ip, disable_html
+from analytical.utils import is_internal_ip, disable_html, validate_setting, \
+ get_required_setting
SCOPE_VISITOR = 1
SCOPE_SESSION = 2
@@ -30,8 +31,8 @@ SETUP_CODE = """
"""
-CUSTOM_VAR_CODE = "_gaq.push(['_setCustomVar', %(index)d, '%(name)s', " \
- "'%(value)s', %(scope)d]);"
+CUSTOM_VAR_CODE = "_gaq.push(['_setCustomVar', %(index)s, '%(name)s', " \
+ "'%(value)s', %(scope)s]);"
register = Library()
@@ -52,10 +53,8 @@ def google_analytics(parser, token):
return GoogleAnalyticsNode()
class GoogleAnalyticsNode(Node):
- name = 'Google Analytics'
-
def __init__(self):
- self.property_id = self.get_required_setting(
+ self.property_id = get_required_setting(
'GOOGLE_ANALYTICS_PROPERTY_ID', PROPERTY_ID_RE,
"must be a string looking like 'UA-XXXXXX-Y'")
@@ -63,21 +62,27 @@ class GoogleAnalyticsNode(Node):
commands = self._get_custom_var_commands(context)
html = SETUP_CODE % {'property_id': self.property_id,
'commands': " ".join(commands)}
- if is_internal_ip(context):
- html = disable_html(html, self.name)
+ if is_internal_ip(context, 'GOOGLE_ANALYTICS'):
+ html = disable_html(html, 'Google Analytics')
return html
def _get_custom_var_commands(self, context):
- values = (context.get('google_analytics_var%d' % i)
+ values = (context.get('google_analytics_var%s' % i)
for i in range(1, 6))
vars = [(i, v) for i, v in enumerate(values, 1) if v is not None]
commands = []
- for index, value in vars:
- name = value[0]
- value = value[1]
+ for index, var in vars:
+ name = var[0]
+ value = var[1]
try:
- scope = value[2]
+ scope = var[2]
except IndexError:
scope = SCOPE_PAGE
commands.append(CUSTOM_VAR_CODE % locals())
return commands
+
+
+def contribute_to_analytical(add_node):
+ validate_setting('GOOGLE_ANALYTICS_PROPERTY_ID', PROPERTY_ID_RE,
+ "must be a string looking like 'UA-XXXXXX-Y'")
+ add_node('head_bottom', GoogleAnalyticsNode)
diff --git a/analytical/templatetags/hubspot.py b/analytical/templatetags/hubspot.py
index 5284943..d958c2b 100644
--- a/analytical/templatetags/hubspot.py
+++ b/analytical/templatetags/hubspot.py
@@ -8,7 +8,8 @@ import re
from django.template import Library, Node, TemplateSyntaxError
-from analytical.utils import get_required_setting, is_internal_ip, disable_html
+from analytical.utils import is_internal_ip, disable_html, validate_setting, \
+ get_required_setting
PORTAL_ID_RE = re.compile(r'^\d+$')
@@ -18,7 +19,7 @@ TRACKING_CODE = """
var hs_portalid = %(portal_id)s;
var hs_salog_version = "2.00";
var hs_ppa = "%(domain)s";
- document.write(unescape("%3Cscript src='" + document.location.protocol + "//" + hs_ppa + "/salog.js.aspx' type='text/javascript'%3E%3C/script%3E"));
+ document.write(unescape("%%3Cscript src='" + document.location.protocol + "//" + hs_ppa + "/salog.js.aspx' type='text/javascript'%%3E%%3C/script%%3E"));
"""
@@ -41,17 +42,23 @@ def hubspot(parser, token):
return HubSpotNode()
class HubSpotNode(Node):
- name = 'HubSpot'
-
def __init__(self):
- self.site_id = get_required_setting('HUPSPOT_PORTAL_ID',
+ self.portal_id = get_required_setting('HUBSPOT_PORTAL_ID',
PORTAL_ID_RE, "must be a (string containing a) number")
- self.domain = get_required_setting('HUPSPOT_DOMAIN',
+ self.domain = get_required_setting('HUBSPOT_DOMAIN',
DOMAIN_RE, "must be an internet domain name")
def render(self, context):
html = TRACKING_CODE % {'portal_id': self.portal_id,
'domain': self.domain}
- if is_internal_ip(context):
+ if is_internal_ip(context, 'HUBSPOT'):
html = disable_html(html, self.name)
return html
+
+
+def contribute_to_analytical(add_node):
+ validate_setting('HUBSPOT_PORTAL_ID', PORTAL_ID_RE,
+ "must be a (string containing a) number")
+ validate_setting('HUBSPOT_DOMAIN', DOMAIN_RE,
+ "must be an internet domain name")
+ add_node('body_bottom', HubSpotNode)
diff --git a/analytical/templatetags/kiss_insights.py b/analytical/templatetags/kiss_insights.py
index 7f68d9f..1c93d7a 100644
--- a/analytical/templatetags/kiss_insights.py
+++ b/analytical/templatetags/kiss_insights.py
@@ -8,6 +8,9 @@ import re
from django.template import Library, Node, TemplateSyntaxError
+from analytical.utils import validate_setting, get_identity, \
+ get_required_setting
+
ACCOUNT_NUMBER_RE = re.compile(r'^\d+$')
SITE_CODE_RE = re.compile(r'^[\w]{3}$')
@@ -39,18 +42,16 @@ def kiss_insights(parser, token):
return KissInsightsNode()
class KissInsightsNode(Node):
- name = 'KISSinsights'
-
def __init__(self):
- self.account_number = self.get_required_setting(
+ self.account_number = get_required_setting(
'KISS_INSIGHTS_ACCOUNT_NUMBER', ACCOUNT_NUMBER_RE,
"must be (a string containing) a number")
- self.site_code = self.get_required_setting('KISS_INSIGHTS_SITE_CODE',
+ self.site_code = get_required_setting('KISS_INSIGHTS_SITE_CODE',
SITE_CODE_RE, "must be a string containing three characters")
def render(self, context):
commands = []
- identity = self.get_identity(context)
+ identity = get_identity(context, 'kiss_insights')
if identity is not None:
commands.append(IDENTIFY_CODE % identity)
try:
@@ -61,3 +62,9 @@ class KissInsightsNode(Node):
html = SETUP_CODE % {'account_number': self.account_number,
'site_code': self.site_code, 'commands': " ".join(commands)}
return html
+
+
+def contribute_to_analytical(add_node):
+ validate_setting('KISS_INSIGHTS_ACCOUNT_NUMBER', ACCOUNT_NUMBER_RE,
+ "must be (a string containing) a number")
+ add_node('body_top', KissInsightsNode)
diff --git a/analytical/templatetags/kiss_metrics.py b/analytical/templatetags/kiss_metrics.py
index 61ce903..69ce2e0 100644
--- a/analytical/templatetags/kiss_metrics.py
+++ b/analytical/templatetags/kiss_metrics.py
@@ -9,7 +9,8 @@ import re
from django.template import Library, Node, TemplateSyntaxError
from django.utils import simplejson
-from analytical.utils import is_internal_ip, disable_html
+from analytical.utils import is_internal_ip, disable_html, get_identity, \
+ validate_setting, get_required_setting
API_KEY_RE = re.compile(r'^[0-9a-f]{40}$')
@@ -53,16 +54,14 @@ def kiss_metrics(parser, token):
return KissMetricsNode()
class KissMetricsNode(Node):
- name = 'KISSmetrics'
-
def __init__(self):
- self.api_key = self.get_required_setting('KISS_METRICS_API_KEY',
+ self.api_key = get_required_setting('KISS_METRICS_API_KEY',
API_KEY_RE,
"must be a string containing a 40-digit hexadecimal number")
def render(self, context):
commands = []
- identity = self.get_identity(context)
+ identity = get_identity(context, 'kiss_metrics')
if identity is not None:
commands.append(IDENTIFY_CODE % identity)
try:
@@ -73,6 +72,12 @@ class KissMetricsNode(Node):
pass
html = TRACKING_CODE % {'api_key': self.api_key,
'commands': " ".join(commands)}
- if is_internal_ip(context):
- html = disable_html(html, self.name)
+ if is_internal_ip(context, 'KISS_METRICS'):
+ html = disable_html(html, 'KISSmetrics')
return html
+
+
+def contribute_to_analytical(add_node):
+ validate_setting('KISS_METRICS_API_KEY', API_KEY_RE,
+ "must be a string containing a 40-digit hexadecimal number")
+ add_node('head_top', KissMetricsNode)
diff --git a/analytical/templatetags/mixpanel.py b/analytical/templatetags/mixpanel.py
index 36daa5c..d3846b8 100644
--- a/analytical/templatetags/mixpanel.py
+++ b/analytical/templatetags/mixpanel.py
@@ -9,7 +9,8 @@ import re
from django.template import Library, Node, TemplateSyntaxError
from django.utils import simplejson
-from analytical.utils import is_internal_ip, disable_html
+from analytical.utils import is_internal_ip, disable_html, get_identity, \
+ validate_setting, get_required_setting
MIXPANEL_TOKEN_RE = re.compile(r'^[0-9a-f]{32}$')
@@ -27,7 +28,7 @@ TRACKING_CODE = """
"""
IDENTIFY_CODE = "mpq.push(['identify', '%s']);"
EVENT_CODE = "mpq.push(['track', '%(name)s', %(properties)s]);"
-EVENT_CONTEXT_KEY = 'mixpanel_metrics_event'
+EVENT_CONTEXT_KEY = 'mixpanel_event'
register = Library()
@@ -46,16 +47,14 @@ def mixpanel(parser, token):
return MixpanelNode()
class MixpanelNode(Node):
- name = 'Mixpanel'
-
def __init__(self):
- self.token = self.get_required_setting('MIXPANEL_TOKEN',
+ self.token = get_required_setting('MIXPANEL_TOKEN',
MIXPANEL_TOKEN_RE,
"must be a string containing a 32-digit hexadecimal number")
def render(self, context):
commands = []
- identity = self.get_identity(context)
+ identity = get_identity(context, 'mixpanel')
if identity is not None:
commands.append(IDENTIFY_CODE % identity)
try:
@@ -66,6 +65,12 @@ class MixpanelNode(Node):
pass
html = TRACKING_CODE % {'token': self.token,
'commands': " ".join(commands)}
- if is_internal_ip(context):
- html = disable_html(html, self.name)
+ if is_internal_ip(context, 'MIXPANEL'):
+ html = disable_html(html, 'Mixpanel')
return html
+
+
+def contribute_to_analytical(add_node):
+ validate_setting('MIXPANEL_TOKEN', MIXPANEL_TOKEN_RE,
+ "must be a string containing a 32-digit hexadecimal number")
+ add_node('head_bottom', MixpanelNode)
diff --git a/analytical/templatetags/optimizely.py b/analytical/templatetags/optimizely.py
index ea91f81..99e7323 100644
--- a/analytical/templatetags/optimizely.py
+++ b/analytical/templatetags/optimizely.py
@@ -8,7 +8,8 @@ import re
from django.template import Library, Node, TemplateSyntaxError
-from analytical.utils import is_internal_ip, disable_html
+from analytical.utils import is_internal_ip, disable_html, validate_setting, \
+ get_required_setting
ACCOUNT_NUMBER_RE = re.compile(r'^\d{7}$')
@@ -33,15 +34,19 @@ def optimizely(parser, token):
return OptimizelyNode()
class OptimizelyNode(Node):
- name = 'Optimizely'
-
def __init__(self):
- self.account_number = self.get_required_setting(
+ self.account_number = get_required_setting(
'OPTIMIZELY_ACCOUNT_NUMBER', ACCOUNT_NUMBER_RE,
"must be a string containing an seven-digit number")
def render(self, context):
html = SETUP_CODE % {'account_number': self.account_number}
- if is_internal_ip(context):
+ if is_internal_ip(context, 'OPTIMIZELY'):
html = disable_html(html, self.name)
return html
+
+
+def contribute_to_analytical(add_node):
+ validate_setting('OPTIMIZELY_ACCOUNT_NUMBER', ACCOUNT_NUMBER_RE,
+ "must be a string containing an seven-digit number")
+ add_node('head_top', OptimizelyNode)
diff --git a/analytical/tests/__init__.py b/analytical/tests/__init__.py
index 2648c6a..dd969f2 100644
--- a/analytical/tests/__init__.py
+++ b/analytical/tests/__init__.py
@@ -2,7 +2,14 @@
Tests for django-analytical.
"""
-from analytical.tests.test_services import *
-from analytical.tests.test_template_tags import *
-
-from analytical.tests.services import *
+from analytical.tests.test_tag_analytical import *
+from analytical.tests.test_tag_chartbeat import *
+from analytical.tests.test_tag_clicky import *
+from analytical.tests.test_tag_crazy_egg import *
+from analytical.tests.test_tag_google_analytics import *
+from analytical.tests.test_tag_hubspot import *
+from analytical.tests.test_tag_kiss_insights import *
+from analytical.tests.test_tag_kiss_metrics import *
+from analytical.tests.test_tag_mixpanel import *
+from analytical.tests.test_tag_optimizely import *
+from analytical.tests.test_utils import *
diff --git a/analytical/tests/services/__init__.py b/analytical/tests/services/__init__.py
deleted file mode 100644
index 6907280..0000000
--- a/analytical/tests/services/__init__.py
+++ /dev/null
@@ -1,14 +0,0 @@
-"""
-Tests for the Analytical analytics services.
-"""
-
-from analytical.tests.services.test_base import *
-from analytical.tests.services.test_chartbeat import *
-from analytical.tests.services.test_clicky import *
-from analytical.tests.services.test_console import *
-from analytical.tests.services.test_crazy_egg import *
-from analytical.tests.services.test_google_analytics import *
-from analytical.tests.services.test_kiss_insights import *
-from analytical.tests.services.test_kiss_metrics import *
-from analytical.tests.services.test_mixpanel import *
-from analytical.tests.services.test_optimizely import *
diff --git a/analytical/tests/services/test_base.py b/analytical/tests/services/test_base.py
deleted file mode 100644
index 23dd147..0000000
--- a/analytical/tests/services/test_base.py
+++ /dev/null
@@ -1,74 +0,0 @@
-"""
-Tests for the base service.
-"""
-
-import re
-
-from django.contrib.auth.models import User, AnonymousUser
-from django.core.exceptions import ImproperlyConfigured
-from django.http import HttpRequest
-from django.test import TestCase
-
-from analytical.services.base import AnalyticalService
-from analytical.tests.utils import TestSettingsManager
-
-
-class DummyService(AnalyticalService):
- def render_test(self, context):
- return context
-
-
-class BaseServiceTestCase(TestCase):
- """
- Tests for the base service.
- """
-
- def setUp(self):
- self.settings_manager = TestSettingsManager()
- self.service = DummyService()
-
- def tearDown(self):
- self.settings_manager.revert()
-
- def test_render(self):
- r = self.service.render('test', 'foo')
- self.assertEqual('foo', r)
-
- def test_get_required_setting(self):
- self.settings_manager.set(TEST='test')
- r = self.service.get_required_setting('TEST', re.compile('es'), 'fail')
- self.assertEqual('test', r)
-
- def test_get_required_setting_missing(self):
- self.settings_manager.delete('TEST')
- self.assertRaises(ImproperlyConfigured,
- self.service.get_required_setting, 'TEST', re.compile('es'),
- 'fail')
-
- def test_get_required_setting_wrong(self):
- self.settings_manager.set(TEST='test')
- self.assertRaises(ImproperlyConfigured,
- self.service.get_required_setting, 'TEST', re.compile('foo'),
- 'fail')
-
- def test_get_identity_none(self):
- context = {}
- self.assertEqual(None, self.service.get_identity(context))
-
- def test_get_identity_authenticated(self):
- context = {'user': User(username='test')}
- self.assertEqual('test', self.service.get_identity(context))
-
- def test_get_identity_authenticated_request(self):
- req = HttpRequest()
- req.user = User(username='test')
- context = {'request': req}
- self.assertEqual('test', self.service.get_identity(context))
-
- def test_get_identity_anonymous(self):
- context = {'user': AnonymousUser()}
- self.assertEqual(None, self.service.get_identity(context))
-
- def test_get_identity_non_user(self):
- context = {'user': object()}
- self.assertEqual(None, self.service.get_identity(context))
diff --git a/analytical/tests/services/test_clicky.py b/analytical/tests/services/test_clicky.py
deleted file mode 100644
index 68e6bf7..0000000
--- a/analytical/tests/services/test_clicky.py
+++ /dev/null
@@ -1,60 +0,0 @@
-"""
-Tests for the Clicky service.
-"""
-
-import re
-
-from django.contrib.auth.models import User
-from django.core.exceptions import ImproperlyConfigured
-from django.test import TestCase
-
-from analytical.services.clicky import ClickyService
-from analytical.tests.utils import TestSettingsManager
-
-
-class ClickyTestCase(TestCase):
- """
- Tests for the Clicky service.
- """
-
- def setUp(self):
- self.settings_manager = TestSettingsManager()
- self.settings_manager.set(CLICKY_SITE_ID='12345678')
- self.service = ClickyService()
-
- def tearDown(self):
- self.settings_manager.revert()
-
- def test_empty_locations(self):
- self.assertEqual(self.service.render_head_top({}), "")
- self.assertEqual(self.service.render_head_bottom({}), "")
- self.assertEqual(self.service.render_body_top({}), "")
-
- def test_no_site_id(self):
- self.settings_manager.delete('CLICKY_SITE_ID')
- self.assertRaises(ImproperlyConfigured, ClickyService)
-
- def test_wrong_site_id(self):
- self.settings_manager.set(CLICKY_SITE_ID='1234567')
- self.assertRaises(ImproperlyConfigured, ClickyService)
- self.settings_manager.set(CLICKY_SITE_ID='123456789')
- self.assertRaises(ImproperlyConfigured, ClickyService)
-
- def test_rendering(self):
- r = self.service.render_body_bottom({})
- self.assertTrue('var clicky_site_id = 12345678;' in r, r)
- self.assertTrue('src="http://in.getclicky.com/12345678ns.gif"' in r,
- r)
-
- def test_identify(self):
- self.settings_manager.set(ANALYTICAL_AUTO_IDENTIFY=True)
- r = self.service.render_body_bottom({'user': User(username='test')})
- self.assertTrue(
- 'var clicky_custom = {"session": {"username": "test"}};' in r,
- r)
-
- def test_custom(self):
- custom = {'var1': 'val1', 'var2': 'val2'}
- r = self.service.render_body_bottom({'clicky_custom': custom})
- self.assertTrue(re.search('var clicky_custom = {.*'
- '"var1": "val1", "var2": "val2".*};', r), r)
diff --git a/analytical/tests/services/test_console.py b/analytical/tests/services/test_console.py
deleted file mode 100644
index d9e5eb5..0000000
--- a/analytical/tests/services/test_console.py
+++ /dev/null
@@ -1,45 +0,0 @@
-"""
-Tests for the console debugging service.
-"""
-
-from django.contrib.auth.models import User
-from django.test import TestCase
-
-from analytical.services.console import ConsoleService
-
-
-class ConsoleTestCase(TestCase):
- """
- Tests for the console debugging service.
- """
-
- def setUp(self):
- self.service = ConsoleService()
-
- def test_render_head_top(self):
- r = self.service.render_head_top({})
- self.assertTrue('rendering analytical_head_top tag' in r, r)
- r = self.service.render_head_top({'user': User(username='test')})
- self.assertTrue('rendering analytical_head_top tag for user test'
- in r, r)
-
- def test_render_head_bottom(self):
- r = self.service.render_head_bottom({})
- self.assertTrue('rendering analytical_head_bottom tag' in r, r)
- r = self.service.render_head_bottom({'user': User(username='test')})
- self.assertTrue('rendering analytical_head_bottom tag for user test'
- in r, r)
-
- def test_render_body_top(self):
- r = self.service.render_body_top({})
- self.assertTrue('rendering analytical_body_top tag' in r, r)
- r = self.service.render_body_top({'user': User(username='test')})
- self.assertTrue('rendering analytical_body_top tag for user test'
- in r, r)
-
- def test_render_body_bottom(self):
- r = self.service.render_body_bottom({})
- self.assertTrue('rendering analytical_body_bottom tag' in r, r)
- r = self.service.render_body_bottom({'user': User(username='test')})
- self.assertTrue('rendering analytical_body_bottom tag for user test'
- in r, r)
diff --git a/analytical/tests/services/test_crazy_egg.py b/analytical/tests/services/test_crazy_egg.py
deleted file mode 100644
index 9663440..0000000
--- a/analytical/tests/services/test_crazy_egg.py
+++ /dev/null
@@ -1,48 +0,0 @@
-"""
-Tests for the Crazy Egg service.
-"""
-
-from django.core.exceptions import ImproperlyConfigured
-from django.test import TestCase
-
-from analytical.services.crazy_egg import CrazyEggService
-from analytical.tests.utils import TestSettingsManager
-
-
-class CrazyEggTestCase(TestCase):
- """
- Tests for the Crazy Egg service.
- """
-
- def setUp(self):
- self.settings_manager = TestSettingsManager()
- self.settings_manager.set(CRAZY_EGG_ACCOUNT_NUMBER='12345678')
- self.service = CrazyEggService()
-
- def tearDown(self):
- self.settings_manager.revert()
-
- def test_empty_locations(self):
- self.assertEqual(self.service.render_head_top({}), "")
- self.assertEqual(self.service.render_head_bottom({}), "")
- self.assertEqual(self.service.render_body_top({}), "")
-
- def test_no_account_number(self):
- self.settings_manager.delete('CRAZY_EGG_ACCOUNT_NUMBER')
- self.assertRaises(ImproperlyConfigured, CrazyEggService)
-
- def test_wrong_account_number(self):
- self.settings_manager.set(CRAZY_EGG_ACCOUNT_NUMBER='1234567')
- self.assertRaises(ImproperlyConfigured, CrazyEggService)
- self.settings_manager.set(CRAZY_EGG_ACCOUNT_NUMBER='123456789')
- self.assertRaises(ImproperlyConfigured, CrazyEggService)
-
- def test_rendering(self):
- r = self.service.render_body_bottom({})
- self.assertTrue('/1234/5678.js' in r, r)
-
- def test_uservars(self):
- context = {'crazy_egg_uservars': {1: 'foo', 2: 'bar'}}
- r = self.service.render_body_bottom(context)
- self.assertTrue("CE2.set(1, 'foo');" in r, r)
- self.assertTrue("CE2.set(2, 'bar');" in r, r)
diff --git a/analytical/tests/services/test_google_analytics.py b/analytical/tests/services/test_google_analytics.py
deleted file mode 100644
index 03c01b1..0000000
--- a/analytical/tests/services/test_google_analytics.py
+++ /dev/null
@@ -1,56 +0,0 @@
-"""
-Tests for the Google Analytics service.
-"""
-
-from django.core.exceptions import ImproperlyConfigured
-from django.test import TestCase
-
-from analytical.services.google_analytics import GoogleAnalyticsService
-from analytical.tests.utils import TestSettingsManager
-
-
-class GoogleAnalyticsTestCase(TestCase):
- """
- Tests for the Google Analytics service.
- """
-
- def setUp(self):
- self.settings_manager = TestSettingsManager()
- self.settings_manager.set(GOOGLE_ANALYTICS_PROPERTY_ID='UA-123456-7')
- self.service = GoogleAnalyticsService()
-
- def tearDown(self):
- self.settings_manager.revert()
-
- def test_empty_locations(self):
- self.assertEqual(self.service.render_head_top({}), "")
- self.assertEqual(self.service.render_body_top({}), "")
- self.assertEqual(self.service.render_body_bottom({}), "")
-
- def test_no_property_id(self):
- self.settings_manager.delete('GOOGLE_ANALYTICS_PROPERTY_ID')
- self.assertRaises(ImproperlyConfigured, GoogleAnalyticsService)
-
- def test_wrong_property_id(self):
- self.settings_manager.set(GOOGLE_ANALYTICS_PROPERTY_ID='wrong')
- self.assertRaises(ImproperlyConfigured, GoogleAnalyticsService)
-
- def test_rendering(self):
- r = self.service.render_head_bottom({})
- self.assertTrue("_gaq.push(['_setAccount', 'UA-123456-7']);" in r, r)
- self.assertTrue("_gaq.push(['_trackPageview']);" in r, r)
-
- def test_custom_vars(self):
- context = {'google_analytics_custom_vars': [
- (1, 'test1', 'foo'),
- (5, 'test2', 'bar', 1),
- ]}
- r = self.service.render_head_bottom(context)
- self.assertTrue("_gaq.push(['_setCustomVar', 1, 'test1', 'foo', 2]);"
- in r, r)
- self.assertTrue("_gaq.push(['_setCustomVar', 5, 'test2', 'bar', 1]);"
- in r, r)
- self.assertRaises(ValueError, self.service.render_head_bottom,
- {'google_analytics_custom_vars': [(0, 'test', 'test')]})
- self.assertRaises(ValueError, self.service.render_head_bottom,
- {'google_analytics_custom_vars': [(6, 'test', 'test')]})
diff --git a/analytical/tests/services/test_kiss_insights.py b/analytical/tests/services/test_kiss_insights.py
deleted file mode 100644
index 8ac4da4..0000000
--- a/analytical/tests/services/test_kiss_insights.py
+++ /dev/null
@@ -1,63 +0,0 @@
-"""
-Tests for the KISSinsights service.
-"""
-
-from django.contrib.auth.models import User
-from django.core.exceptions import ImproperlyConfigured
-from django.test import TestCase
-
-from analytical.services.kiss_insights import KissInsightsService
-from analytical.tests.utils import TestSettingsManager
-
-
-class KissInsightsTestCase(TestCase):
- """
- Tests for the KISSinsights service.
- """
-
- def setUp(self):
- self.settings_manager = TestSettingsManager()
- self.settings_manager.set(KISS_INSIGHTS_ACCOUNT_NUMBER='12345')
- self.settings_manager.set(KISS_INSIGHTS_SITE_CODE='abc')
- self.service = KissInsightsService()
-
- def tearDown(self):
- self.settings_manager.revert()
-
- def test_empty_locations(self):
- self.assertEqual(self.service.render_head_top({}), "")
- self.assertEqual(self.service.render_head_bottom({}), "")
- self.assertEqual(self.service.render_body_bottom({}), "")
-
- def test_no_account_number(self):
- self.settings_manager.delete('KISS_INSIGHTS_ACCOUNT_NUMBER')
- self.assertRaises(ImproperlyConfigured, KissInsightsService)
-
- def test_no_site_code(self):
- self.settings_manager.delete('KISS_INSIGHTS_SITE_CODE')
- self.assertRaises(ImproperlyConfigured, KissInsightsService)
-
- def test_wrong_account_number(self):
- self.settings_manager.set(KISS_INSIGHTS_ACCOUNT_NUMBER='1234')
- self.assertRaises(ImproperlyConfigured, KissInsightsService)
- self.settings_manager.set(KISS_INSIGHTS_ACCOUNT_NUMBER='123456')
- self.assertRaises(ImproperlyConfigured, KissInsightsService)
-
- def test_wrong_site_id(self):
- self.settings_manager.set(KISS_INSIGHTS_SITE_CODE='ab')
- self.assertRaises(ImproperlyConfigured, KissInsightsService)
- self.settings_manager.set(KISS_INSIGHTS_SITE_CODE='abcd')
- self.assertRaises(ImproperlyConfigured, KissInsightsService)
-
- def test_rendering(self):
- r = self.service.render_body_top({})
- self.assertTrue("//s3.amazonaws.com/ki.js/12345/abc.js" in r, r)
-
- def test_identify(self):
- self.settings_manager.set(ANALYTICAL_AUTO_IDENTIFY=True)
- r = self.service.render_body_top({'user': User(username='test')})
- self.assertTrue("_kiq.push(['identify', 'test']);" in r, r)
-
- def test_show_survey(self):
- r = self.service.render_body_top({'kiss_insights_show_survey': 1234})
- self.assertTrue("_kiq.push(['showSurvey', 1234]);" in r, r)
diff --git a/analytical/tests/services/test_kiss_metrics.py b/analytical/tests/services/test_kiss_metrics.py
deleted file mode 100644
index 5829e23..0000000
--- a/analytical/tests/services/test_kiss_metrics.py
+++ /dev/null
@@ -1,58 +0,0 @@
-"""
-Tests for the KISSmetrics service.
-"""
-
-from django.contrib.auth.models import User
-from django.core.exceptions import ImproperlyConfigured
-from django.test import TestCase
-
-from analytical.services.kiss_metrics import KissMetricsService
-from analytical.tests.utils import TestSettingsManager
-
-
-class KissMetricsTestCase(TestCase):
- """
- Tests for the KISSmetrics service.
- """
-
- def setUp(self):
- self.settings_manager = TestSettingsManager()
- self.settings_manager.set(KISS_METRICS_API_KEY='0123456789abcdef012345'
- '6789abcdef01234567')
- self.service = KissMetricsService()
-
- def tearDown(self):
- self.settings_manager.revert()
-
- def test_empty_locations(self):
- self.assertEqual(self.service.render_head_bottom({}), "")
- self.assertEqual(self.service.render_body_top({}), "")
- self.assertEqual(self.service.render_body_bottom({}), "")
-
- def test_no_api_key(self):
- self.settings_manager.delete('KISS_METRICS_API_KEY')
- self.assertRaises(ImproperlyConfigured, KissMetricsService)
-
- def test_wrong_api_key(self):
- self.settings_manager.set(KISS_METRICS_API_KEY='0123456789abcdef012345'
- '6789abcdef0123456')
- self.assertRaises(ImproperlyConfigured, KissMetricsService)
- self.settings_manager.set(KISS_METRICS_API_KEY='0123456789abcdef012345'
- '6789abcdef012345678')
- self.assertRaises(ImproperlyConfigured, KissMetricsService)
-
- def test_rendering(self):
- r = self.service.render_head_top({})
- self.assertTrue("//doug1izaerwt3.cloudfront.net/0123456789abcdef012345"
- "6789abcdef01234567.1.js" in r, r)
-
- def test_identify(self):
- self.settings_manager.set(ANALYTICAL_AUTO_IDENTIFY=True)
- r = self.service.render_head_top({'user': User(username='test')})
- self.assertTrue("_kmq.push(['identify', 'test']);" in r, r)
-
- def test_event(self):
- r = self.service.render_event('test_event', {'prop1': 'val1',
- 'prop2': 'val2'})
- self.assertEqual(r, "_kmq.push(['record', 'test_event', "
- '{"prop1": "val1", "prop2": "val2"}]);')
diff --git a/analytical/tests/services/test_mixpanel.py b/analytical/tests/services/test_mixpanel.py
deleted file mode 100644
index 92226c7..0000000
--- a/analytical/tests/services/test_mixpanel.py
+++ /dev/null
@@ -1,59 +0,0 @@
-"""
-Tests for the Mixpanel service.
-"""
-
-from django.contrib.auth.models import User
-from django.core.exceptions import ImproperlyConfigured
-from django.test import TestCase
-
-from analytical.services.mixpanel import MixpanelService
-from analytical.tests.utils import TestSettingsManager
-
-
-class MixpanelTestCase(TestCase):
- """
- Tests for the Mixpanel service.
- """
-
- def setUp(self):
- self.settings_manager = TestSettingsManager()
- self.settings_manager.set(
- MIXPANEL_TOKEN='0123456789abcdef0123456789abcdef')
- self.service = MixpanelService()
-
- def tearDown(self):
- self.settings_manager.revert()
-
- def test_empty_locations(self):
- self.assertEqual(self.service.render_head_top({}), "")
- self.assertEqual(self.service.render_body_top({}), "")
- self.assertEqual(self.service.render_body_bottom({}), "")
-
- def test_no_token(self):
- self.settings_manager.delete('MIXPANEL_TOKEN')
- self.assertRaises(ImproperlyConfigured, MixpanelService)
-
- def test_wrong_token(self):
- self.settings_manager.set(
- MIXPANEL_TOKEN='0123456789abcdef0123456789abcde')
- self.assertRaises(ImproperlyConfigured, MixpanelService)
- self.settings_manager.set(
- MIXPANEL_TOKEN='0123456789abcdef0123456789abcdef0')
- self.assertRaises(ImproperlyConfigured, MixpanelService)
-
- def test_rendering(self):
- r = self.service.render_head_bottom({})
- self.assertTrue(
- "mpq.push(['init', '0123456789abcdef0123456789abcdef']);" in r,
- r)
-
- def test_identify(self):
- self.settings_manager.set(ANALYTICAL_AUTO_IDENTIFY=True)
- r = self.service.render_head_bottom({'user': User(username='test')})
- self.assertTrue("mpq.push(['identify', 'test']);" in r, r)
-
- def test_event(self):
- r = self.service.render_event('test_event', {'prop1': 'val1',
- 'prop2': 'val2'})
- self.assertEqual(r, "mpq.push(['track', 'test_event', "
- '{"prop1": "val1", "prop2": "val2"}]);')
diff --git a/analytical/tests/services/test_optimizely.py b/analytical/tests/services/test_optimizely.py
deleted file mode 100644
index feebd6f..0000000
--- a/analytical/tests/services/test_optimizely.py
+++ /dev/null
@@ -1,42 +0,0 @@
-"""
-Tests for the Optimizely service.
-"""
-
-from django.core.exceptions import ImproperlyConfigured
-from django.test import TestCase
-
-from analytical.services.optimizely import OptimizelyService
-from analytical.tests.utils import TestSettingsManager
-
-
-class OptimizelyTestCase(TestCase):
- """
- Tests for the Optimizely service.
- """
-
- def setUp(self):
- self.settings_manager = TestSettingsManager()
- self.settings_manager.set(OPTIMIZELY_ACCOUNT_NUMBER='1234567')
- self.service = OptimizelyService()
-
- def tearDown(self):
- self.settings_manager.revert()
-
- def test_empty_locations(self):
- self.assertEqual(self.service.render_head_bottom({}), "")
- self.assertEqual(self.service.render_body_top({}), "")
- self.assertEqual(self.service.render_body_bottom({}), "")
-
- def test_no_account_number(self):
- self.settings_manager.delete('OPTIMIZELY_ACCOUNT_NUMBER')
- self.assertRaises(ImproperlyConfigured, OptimizelyService)
-
- def test_wrong_account_number(self):
- self.settings_manager.set(OPTIMIZELY_ACCOUNT_NUMBER='123456')
- self.assertRaises(ImproperlyConfigured, OptimizelyService)
- self.settings_manager.set(OPTIMIZELY_ACCOUNT_NUMBER='12345678')
- self.assertRaises(ImproperlyConfigured, OptimizelyService)
-
- def test_rendering(self):
- self.assertEqual(self.service.render_head_top({}),
- '')
diff --git a/analytical/tests/templatetags/__init__.py b/analytical/tests/templatetags/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/analytical/tests/templatetags/dummy.py b/analytical/tests/templatetags/dummy.py
new file mode 100644
index 0000000..40d9781
--- /dev/null
+++ b/analytical/tests/templatetags/dummy.py
@@ -0,0 +1,38 @@
+"""
+Dummy testing template tags and filters.
+"""
+
+from __future__ import absolute_import
+
+from django.template import Library, Node, TemplateSyntaxError
+
+from analytical.templatetags.analytical import TAG_LOCATIONS
+
+
+register = Library()
+
+
+def _location_node(location):
+ class DummyNode(Node):
+ def render(self, context):
+ return "" % location
+ return DummyNode
+
+_location_nodes = dict((l, _location_node(l)) for l in TAG_LOCATIONS)
+
+
+def _location_tag(location):
+ def dummy_tag(parser, token):
+ bits = token.split_contents()
+ if len(bits) > 1:
+ raise TemplateSyntaxError("'%s' tag takes no arguments" % bits[0])
+ return _location_nodes[location]
+ return dummy_tag
+
+for loc in TAG_LOCATIONS:
+ register.tag('dummy_%s' % loc, _location_tag(loc))
+
+
+def contribute_to_analytical(add_node_cls):
+ for location in TAG_LOCATIONS:
+ add_node_cls(location, _location_nodes[location])
diff --git a/analytical/tests/test_services.py b/analytical/tests/test_services.py
deleted file mode 100644
index beb7187..0000000
--- a/analytical/tests/test_services.py
+++ /dev/null
@@ -1,80 +0,0 @@
-"""
-Tests for the services package.
-"""
-
-from django.core.exceptions import ImproperlyConfigured
-from django.test import TestCase
-
-from analytical import services
-from analytical.services import load_services
-from analytical.tests.utils import TestSettingsManager
-from analytical.services.google_analytics import GoogleAnalyticsService
-
-
-class GetEnabledServicesTestCase(TestCase):
- """
- Tests for get_enabled_services.
- """
-
- def setUp(self):
- services.enabled_services = None
- services.load_services = lambda: 'test'
-
- def tearDown(self):
- services.enabled_services = None
- services.load_services = load_services
-
- def test_get_enabled_services(self):
- result = services.get_enabled_services()
- self.assertEqual(result, 'test')
- services.load_services = lambda: 'test2'
- result = services.get_enabled_services()
- self.assertEqual(result, 'test')
-
-
-class LoadServicesTestCase(TestCase):
- """
- Tests for load_services.
- """
-
- def setUp(self):
- self.settings_manager = TestSettingsManager()
- self.settings_manager.delete('ANALYTICAL_SERVICES')
- self.settings_manager.delete('CLICKY_SITE_ID')
- self.settings_manager.delete('CHARTBEAT_USER_ID')
- self.settings_manager.delete('CRAZY_EGG_ACCOUNT_NUMBER')
- self.settings_manager.delete('GOOGLE_ANALYTICS_PROPERTY_ID')
- self.settings_manager.delete('KISSINSIGHTS_ACCOUNT_NUMBER')
- self.settings_manager.delete('KISSINSIGHTS_SITE_CODE')
- self.settings_manager.delete('KISSMETRICS_API_KEY')
- self.settings_manager.delete('MIXPANEL_TOKEN')
- self.settings_manager.delete('OPTIMIZELY_ACCOUNT_NUMBER')
- services.enabled_services = None
-
- def tearDown(self):
- self.settings_manager.revert()
- services.enabled_services = None
-
- def test_no_services(self):
- self.assertEqual(load_services(), [])
-
- def test_enabled_service(self):
- self.settings_manager.set(GOOGLE_ANALYTICS_PROPERTY_ID='UA-1234567-8')
- results = load_services()
- self.assertEqual(len(results), 1, results)
- self.assertTrue(isinstance(results[0], GoogleAnalyticsService),
- results)
-
- def test_explicit_service(self):
- self.settings_manager.set(ANALYTICAL_SERVICES=[
- 'analytical.services.google_analytics.GoogleAnalyticsService'])
- self.settings_manager.set(GOOGLE_ANALYTICS_PROPERTY_ID='UA-1234567-8')
- results = load_services()
- self.assertEqual(len(results), 1, results)
- self.assertTrue(isinstance(results[0], GoogleAnalyticsService),
- results)
-
- def test_explicit_service_misconfigured(self):
- self.settings_manager.set(ANALYTICAL_SERVICES=[
- 'analytical.services.google_analytics.GoogleAnalyticsService'])
- self.assertRaises(ImproperlyConfigured, load_services)
diff --git a/analytical/tests/test_tag_analytical.py b/analytical/tests/test_tag_analytical.py
new file mode 100644
index 0000000..8439197
--- /dev/null
+++ b/analytical/tests/test_tag_analytical.py
@@ -0,0 +1,37 @@
+"""
+Tests for the generic template tags and filters.
+"""
+
+from django.template import Context, Template
+
+from analytical.templatetags import analytical
+from analytical.tests.utils import TagTestCase
+
+
+class AnalyticsTagTestCase(TagTestCase):
+ """
+ Tests for the ``analytical`` template tags.
+ """
+
+ def setUp(self):
+ super(AnalyticsTagTestCase, self).setUp()
+ self._tag_modules = analytical.TAG_MODULES
+ analytical.TAG_MODULES = ['analytical.tests.dummy']
+ analytical.template_nodes = analytical._load_template_nodes()
+
+ def tearDown(self):
+ analytical.TAG_MODULES = self._tag_modules
+ analytical.template_nodes = analytical._load_template_nodes()
+ super(AnalyticsTagTestCase, self).tearDown()
+
+ def render_location_tag(self, location, vars=None):
+ if vars is None:
+ vars = {}
+ t = Template("{%% load analytical %%}{%% analytical_%s %%}"
+ % location)
+ return t.render(Context(vars))
+
+ def test_location_tags(self):
+ for l in ['head_top', 'head_bottom', 'body_top', 'body_bottom']:
+ r = self.render_location_tag(l)
+ self.assertTrue('dummy_%s' % l in r, r)
diff --git a/analytical/tests/services/test_chartbeat.py b/analytical/tests/test_tag_chartbeat.py
similarity index 50%
rename from analytical/tests/services/test_chartbeat.py
rename to analytical/tests/test_tag_chartbeat.py
index 4afe7fd..fa3bbbd 100644
--- a/analytical/tests/services/test_chartbeat.py
+++ b/analytical/tests/test_tag_chartbeat.py
@@ -1,62 +1,69 @@
"""
-Tests for the Chartbeat service.
+Tests for the Chartbeat template tags and filters.
"""
import re
from django.conf import settings
from django.contrib.sites.models import Site
-from django.core.exceptions import ImproperlyConfigured
-from django.http import HttpRequest
-from django.test import TestCase
+from django.template import Context
-from analytical.services.chartbeat import ChartbeatService
-from analytical.tests.utils import TestSettingsManager
+from analytical.templatetags.chartbeat import ChartbeatTopNode, \
+ ChartbeatBottomNode
+from analytical.tests.utils import TagTestCase
+from analytical.utils import AnalyticalException
-class ChartbeatTestCase(TestCase):
+class ChartbeatTagTestCase(TagTestCase):
"""
- Tests for the Chartbeat service.
+ Tests for the ``chartbeat`` template tag.
"""
def setUp(self):
- self.settings_manager = TestSettingsManager()
+ super(ChartbeatTagTestCase, self).setUp()
self.settings_manager.set(CHARTBEAT_USER_ID='12345')
- self.service = ChartbeatService()
- def tearDown(self):
- self.settings_manager.revert()
-
- def test_empty_locations(self):
- self.assertEqual(self.service.render_head_bottom({}), "")
- self.assertEqual(self.service.render_body_top({}), "")
-
- def test_no_user_id(self):
- self.settings_manager.delete('CHARTBEAT_USER_ID')
- self.assertRaises(ImproperlyConfigured, ChartbeatService)
-
- def test_wrong_user_id(self):
- self.settings_manager.set(CHARTBEAT_USER_ID='1234')
- self.assertRaises(ImproperlyConfigured, ChartbeatService)
- self.settings_manager.set(CHARTBEAT_USER_ID='123456')
- self.assertRaises(ImproperlyConfigured, ChartbeatService)
-
- def test_rendering_init(self):
- r = self.service.render_head_top({})
+ def test_top_tag(self):
+ r = self.render_tag('chartbeat', 'chartbeat_top',
+ {'chartbeat_domain': "test.com"})
self.assertTrue('var _sf_startpt=(new Date()).getTime()' in r, r)
- def test_rendering_setup(self):
- r = self.service.render_body_bottom({'chartbeat_domain': "test.com"})
+ def test_bottom_tag(self):
+ r = self.render_tag('chartbeat', 'chartbeat_bottom',
+ {'chartbeat_domain': "test.com"})
self.assertTrue(re.search(
'var _sf_async_config={.*"uid": "12345".*};', r), r)
self.assertTrue(re.search(
'var _sf_async_config={.*"domain": "test.com".*};', r), r)
+ def test_top_node(self):
+ r = ChartbeatTopNode().render(
+ Context({'chartbeat_domain': "test.com"}))
+ self.assertTrue('var _sf_startpt=(new Date()).getTime()' in r, r)
+
+ def test_bottom_node(self):
+ r = ChartbeatBottomNode().render(
+ Context({'chartbeat_domain': "test.com"}))
+ self.assertTrue(re.search(
+ 'var _sf_async_config={.*"uid": "12345".*};', r), r)
+ self.assertTrue(re.search(
+ 'var _sf_async_config={.*"domain": "test.com".*};', r), r)
+
+ def test_no_user_id(self):
+ self.settings_manager.delete('CHARTBEAT_USER_ID')
+ self.assertRaises(AnalyticalException, ChartbeatBottomNode)
+
+ def test_wrong_user_id(self):
+ self.settings_manager.set(CHARTBEAT_USER_ID='1234')
+ self.assertRaises(AnalyticalException, ChartbeatBottomNode)
+ self.settings_manager.set(CHARTBEAT_USER_ID='123456')
+ self.assertRaises(AnalyticalException, ChartbeatBottomNode)
+
def test_rendering_setup_no_site(self):
installed_apps = [a for a in settings.INSTALLED_APPS
if a != 'django.contrib.sites']
self.settings_manager.set(INSTALLED_APPS=installed_apps)
- r = self.service.render_body_bottom({})
+ r = ChartbeatBottomNode().render(Context())
self.assertTrue('var _sf_async_config={"uid": "12345"};' in r, r)
def test_rendering_setup_site(self):
@@ -65,7 +72,7 @@ class ChartbeatTestCase(TestCase):
self.settings_manager.set(INSTALLED_APPS=installed_apps)
site = Site.objects.create(domain="test.com", name="test")
self.settings_manager.set(SITE_ID=site.id)
- r = self.service.render_body_bottom({})
+ r = ChartbeatBottomNode().render(Context())
self.assertTrue(re.search(
'var _sf_async_config={.*"uid": "12345".*};', r), r)
self.assertTrue(re.search(
diff --git a/analytical/tests/test_tag_clicky.py b/analytical/tests/test_tag_clicky.py
new file mode 100644
index 0000000..2130dbb
--- /dev/null
+++ b/analytical/tests/test_tag_clicky.py
@@ -0,0 +1,57 @@
+"""
+Tests for the Clicky template tags and filters.
+"""
+
+import re
+
+from django.contrib.auth.models import User
+from django.template import Context
+
+from analytical.templatetags.clicky import ClickyNode
+from analytical.tests.utils import TagTestCase
+from analytical.utils import AnalyticalException
+
+
+class ClickyTagTestCase(TagTestCase):
+ """
+ Tests for the ``clicky`` template tag.
+ """
+
+ def setUp(self):
+ super(ClickyTagTestCase, self).setUp()
+ self.settings_manager.set(CLICKY_SITE_ID='12345678')
+
+ def test_tag(self):
+ r = self.render_tag('clicky', 'clicky')
+ self.assertTrue('var clicky_site_id = 12345678;' in r, r)
+ self.assertTrue('src="http://in.getclicky.com/12345678ns.gif"' in r,
+ r)
+
+ def test_node(self):
+ r = ClickyNode().render(Context({}))
+ self.assertTrue('var clicky_site_id = 12345678;' in r, r)
+ self.assertTrue('src="http://in.getclicky.com/12345678ns.gif"' in r,
+ r)
+
+ def test_no_site_id(self):
+ self.settings_manager.delete('CLICKY_SITE_ID')
+ self.assertRaises(AnalyticalException, ClickyNode)
+
+ def test_wrong_site_id(self):
+ self.settings_manager.set(CLICKY_SITE_ID='1234567')
+ self.assertRaises(AnalyticalException, ClickyNode)
+ self.settings_manager.set(CLICKY_SITE_ID='123456789')
+ self.assertRaises(AnalyticalException, ClickyNode)
+
+ def test_identify(self):
+ self.settings_manager.set(ANALYTICAL_AUTO_IDENTIFY=True)
+ r = ClickyNode().render(Context({'user': User(username='test')}))
+ self.assertTrue(
+ 'var clicky_custom = {"session": {"username": "test"}};' in r,
+ r)
+
+ def test_custom(self):
+ r = ClickyNode().render(Context({'clicky_var1': 'val1',
+ 'clicky_var2': 'val2'}))
+ self.assertTrue(re.search('var clicky_custom = {.*'
+ '"var1": "val1", "var2": "val2".*};', r), r)
diff --git a/analytical/tests/test_tag_crazy_egg.py b/analytical/tests/test_tag_crazy_egg.py
new file mode 100644
index 0000000..755d2e2
--- /dev/null
+++ b/analytical/tests/test_tag_crazy_egg.py
@@ -0,0 +1,43 @@
+"""
+Tests for the Crazy Egg template tags and filters.
+"""
+
+from django.template import Context
+
+from analytical.templatetags.crazy_egg import CrazyEggNode
+from analytical.tests.utils import TagTestCase
+from analytical.utils import AnalyticalException
+
+
+class CrazyEggTagTestCase(TagTestCase):
+ """
+ Tests for the ``crazy_egg`` template tag.
+ """
+
+ def setUp(self):
+ super(CrazyEggTagTestCase, self).setUp()
+ self.settings_manager.set(CRAZY_EGG_ACCOUNT_NUMBER='12345678')
+
+ def test_tag(self):
+ r = self.render_tag('crazy_egg', 'crazy_egg')
+ self.assertTrue('/1234/5678.js' in r, r)
+
+ def test_node(self):
+ r = CrazyEggNode().render(Context())
+ self.assertTrue('/1234/5678.js' in r, r)
+
+ def test_no_account_number(self):
+ self.settings_manager.delete('CRAZY_EGG_ACCOUNT_NUMBER')
+ self.assertRaises(AnalyticalException, CrazyEggNode)
+
+ def test_wrong_account_number(self):
+ self.settings_manager.set(CRAZY_EGG_ACCOUNT_NUMBER='1234567')
+ self.assertRaises(AnalyticalException, CrazyEggNode)
+ self.settings_manager.set(CRAZY_EGG_ACCOUNT_NUMBER='123456789')
+ self.assertRaises(AnalyticalException, CrazyEggNode)
+
+ def test_uservars(self):
+ context = Context({'crazy_egg_var1': 'foo', 'crazy_egg_var2': 'bar'})
+ r = CrazyEggNode().render(context)
+ self.assertTrue("CE2.set(1, 'foo');" in r, r)
+ self.assertTrue("CE2.set(2, 'bar');" in r, r)
diff --git a/analytical/tests/test_tag_google_analytics.py b/analytical/tests/test_tag_google_analytics.py
new file mode 100644
index 0000000..119d441
--- /dev/null
+++ b/analytical/tests/test_tag_google_analytics.py
@@ -0,0 +1,46 @@
+"""
+Tests for the Google Analytics template tags and filters.
+"""
+
+from django.template import Context
+
+from analytical.templatetags.google_analytics import GoogleAnalyticsNode
+from analytical.tests.utils import TagTestCase
+from analytical.utils import AnalyticalException
+
+
+class GoogleAnalyticsTagTestCase(TagTestCase):
+ """
+ Tests for the ``google_analytics`` template tag.
+ """
+
+ def setUp(self):
+ super(GoogleAnalyticsTagTestCase, self).setUp()
+ self.settings_manager.set(GOOGLE_ANALYTICS_PROPERTY_ID='UA-123456-7')
+
+ def test_tag(self):
+ r = self.render_tag('google_analytics', 'google_analytics')
+ self.assertTrue("_gaq.push(['_setAccount', 'UA-123456-7']);" in r, r)
+ self.assertTrue("_gaq.push(['_trackPageview']);" in r, r)
+
+ def test_node(self):
+ r = GoogleAnalyticsNode().render(Context())
+ self.assertTrue("_gaq.push(['_setAccount', 'UA-123456-7']);" in r, r)
+ self.assertTrue("_gaq.push(['_trackPageview']);" in r, r)
+
+ def test_no_property_id(self):
+ self.settings_manager.delete('GOOGLE_ANALYTICS_PROPERTY_ID')
+ self.assertRaises(AnalyticalException, GoogleAnalyticsNode)
+
+ def test_wrong_property_id(self):
+ self.settings_manager.set(GOOGLE_ANALYTICS_PROPERTY_ID='wrong')
+ self.assertRaises(AnalyticalException, GoogleAnalyticsNode)
+
+ def test_custom_vars(self):
+ context = Context({'google_analytics_var1': ('test1', 'foo'),
+ 'google_analytics_var5': ('test2', 'bar', 1)})
+ r = GoogleAnalyticsNode().render(context)
+ self.assertTrue("_gaq.push(['_setCustomVar', 1, 'test1', 'foo', 3]);"
+ in r, r)
+ self.assertTrue("_gaq.push(['_setCustomVar', 5, 'test2', 'bar', 1]);"
+ in r, r)
diff --git a/analytical/tests/test_tag_hubspot.py b/analytical/tests/test_tag_hubspot.py
new file mode 100644
index 0000000..9d2374e
--- /dev/null
+++ b/analytical/tests/test_tag_hubspot.py
@@ -0,0 +1,46 @@
+"""
+Tests for the HubSpot template tags and filters.
+"""
+
+from django.template import Context
+
+from analytical.templatetags.hubspot import HubSpotNode
+from analytical.tests.utils import TagTestCase
+from analytical.utils import AnalyticalException
+
+
+class HubSpotTagTestCase(TagTestCase):
+ """
+ Tests for the ``hubspot`` template tag.
+ """
+
+ def setUp(self):
+ super(HubSpotTagTestCase, self).setUp()
+ self.settings_manager.set(HUBSPOT_PORTAL_ID='1234')
+ self.settings_manager.set(HUBSPOT_DOMAIN='example.com')
+
+ def test_tag(self):
+ r = self.render_tag('hubspot', 'hubspot')
+ self.assertTrue('var hs_portalid = 1234;' in r, r)
+ self.assertTrue('var hs_ppa = "example.com";' in r, r)
+
+ def test_node(self):
+ r = HubSpotNode().render(Context())
+ self.assertTrue('var hs_portalid = 1234;' in r, r)
+ self.assertTrue('var hs_ppa = "example.com";' in r, r)
+
+ def test_no_portal_id(self):
+ self.settings_manager.delete('HUBSPOT_PORTAL_ID')
+ self.assertRaises(AnalyticalException, HubSpotNode)
+
+ def test_wrong_portal_id(self):
+ self.settings_manager.set(HUBSPOT_PORTAL_ID='wrong')
+ self.assertRaises(AnalyticalException, HubSpotNode)
+
+ def test_no_domain(self):
+ self.settings_manager.delete('HUBSPOT_DOMAIN')
+ self.assertRaises(AnalyticalException, HubSpotNode)
+
+ def test_wrong_domain(self):
+ self.settings_manager.set(HUBSPOT_DOMAIN='wrong domain')
+ self.assertRaises(AnalyticalException, HubSpotNode)
diff --git a/analytical/tests/test_tag_kiss_insights.py b/analytical/tests/test_tag_kiss_insights.py
new file mode 100644
index 0000000..b678bea
--- /dev/null
+++ b/analytical/tests/test_tag_kiss_insights.py
@@ -0,0 +1,57 @@
+"""
+Tests for the KISSinsights template tags and filters.
+"""
+
+from django.contrib.auth.models import User
+from django.template import Context
+
+from analytical.templatetags.kiss_insights import KissInsightsNode
+from analytical.tests.utils import TagTestCase
+from analytical.utils import AnalyticalException
+
+
+class KissInsightsTagTestCase(TagTestCase):
+ """
+ Tests for the ``kiss_insights`` template tag.
+ """
+
+ def setUp(self):
+ super(KissInsightsTagTestCase, self).setUp()
+ self.settings_manager.set(KISS_INSIGHTS_ACCOUNT_NUMBER='12345')
+ self.settings_manager.set(KISS_INSIGHTS_SITE_CODE='abc')
+
+ def test_tag(self):
+ r = self.render_tag('kiss_insights', 'kiss_insights')
+ self.assertTrue("//s3.amazonaws.com/ki.js/12345/abc.js" in r, r)
+
+ def test_node(self):
+ r = KissInsightsNode().render(Context())
+ self.assertTrue("//s3.amazonaws.com/ki.js/12345/abc.js" in r, r)
+
+ def test_no_account_number(self):
+ self.settings_manager.delete('KISS_INSIGHTS_ACCOUNT_NUMBER')
+ self.assertRaises(AnalyticalException, KissInsightsNode)
+
+ def test_no_site_code(self):
+ self.settings_manager.delete('KISS_INSIGHTS_SITE_CODE')
+ self.assertRaises(AnalyticalException, KissInsightsNode)
+
+ def test_wrong_account_number(self):
+ self.settings_manager.set(KISS_INSIGHTS_ACCOUNT_NUMBER='abcde')
+ self.assertRaises(AnalyticalException, KissInsightsNode)
+
+ def test_wrong_site_id(self):
+ self.settings_manager.set(KISS_INSIGHTS_SITE_CODE='ab')
+ self.assertRaises(AnalyticalException, KissInsightsNode)
+ self.settings_manager.set(KISS_INSIGHTS_SITE_CODE='abcd')
+ self.assertRaises(AnalyticalException, KissInsightsNode)
+
+ def test_identify(self):
+ self.settings_manager.set(ANALYTICAL_AUTO_IDENTIFY=True)
+ r = KissInsightsNode().render(Context({'user': User(username='test')}))
+ self.assertTrue("_kiq.push(['identify', 'test']);" in r, r)
+
+ def test_show_survey(self):
+ r = KissInsightsNode().render(
+ Context({'kiss_insights_show_survey': 1234}))
+ self.assertTrue("_kiq.push(['showSurvey', 1234]);" in r, r)
diff --git a/analytical/tests/test_tag_kiss_metrics.py b/analytical/tests/test_tag_kiss_metrics.py
new file mode 100644
index 0000000..5f9ed16
--- /dev/null
+++ b/analytical/tests/test_tag_kiss_metrics.py
@@ -0,0 +1,54 @@
+"""
+Tests for the KISSmetrics tags and filters.
+"""
+
+from django.contrib.auth.models import User
+from django.template import Context
+
+from analytical.templatetags.kiss_metrics import KissMetricsNode
+from analytical.tests.utils import TagTestCase
+from analytical.utils import AnalyticalException
+
+
+class KissMetricsTagTestCase(TagTestCase):
+ """
+ Tests for the ``kiss_metrics`` template tag.
+ """
+
+ def setUp(self):
+ super(KissMetricsTagTestCase, self).setUp()
+ self.settings_manager.set(KISS_METRICS_API_KEY='0123456789abcdef012345'
+ '6789abcdef01234567')
+
+ def test_tag(self):
+ r = self.render_tag('kiss_metrics', 'kiss_metrics')
+ self.assertTrue("//doug1izaerwt3.cloudfront.net/0123456789abcdef012345"
+ "6789abcdef01234567.1.js" in r, r)
+
+ def test_node(self):
+ r = KissMetricsNode().render(Context())
+ self.assertTrue("//doug1izaerwt3.cloudfront.net/0123456789abcdef012345"
+ "6789abcdef01234567.1.js" in r, r)
+
+ def test_no_api_key(self):
+ self.settings_manager.delete('KISS_METRICS_API_KEY')
+ self.assertRaises(AnalyticalException, KissMetricsNode)
+
+ def test_wrong_api_key(self):
+ self.settings_manager.set(KISS_METRICS_API_KEY='0123456789abcdef012345'
+ '6789abcdef0123456')
+ self.assertRaises(AnalyticalException, KissMetricsNode)
+ self.settings_manager.set(KISS_METRICS_API_KEY='0123456789abcdef012345'
+ '6789abcdef012345678')
+ self.assertRaises(AnalyticalException, KissMetricsNode)
+
+ def test_identify(self):
+ self.settings_manager.set(ANALYTICAL_AUTO_IDENTIFY=True)
+ r = KissMetricsNode().render(Context({'user': User(username='test')}))
+ self.assertTrue("_kmq.push(['identify', 'test']);" in r, r)
+
+ def test_event(self):
+ r = KissMetricsNode().render(Context({'kiss_metrics_event':
+ ('test_event', {'prop1': 'val1', 'prop2': 'val2'})}))
+ self.assertTrue("_kmq.push(['record', 'test_event', "
+ '{"prop1": "val1", "prop2": "val2"}]);' in r, r)
diff --git a/analytical/tests/test_tag_mixpanel.py b/analytical/tests/test_tag_mixpanel.py
new file mode 100644
index 0000000..40d3fb2
--- /dev/null
+++ b/analytical/tests/test_tag_mixpanel.py
@@ -0,0 +1,57 @@
+"""
+Tests for the Mixpanel tags and filters.
+"""
+
+from django.contrib.auth.models import User
+from django.template import Context
+
+from analytical.templatetags.mixpanel import MixpanelNode
+from analytical.tests.utils import TagTestCase
+from analytical.utils import AnalyticalException
+
+
+class MixpanelTagTestCase(TagTestCase):
+ """
+ Tests for the ``mixpanel`` template tag.
+ """
+
+ def setUp(self):
+ super(MixpanelTagTestCase, self).setUp()
+ self.settings_manager.set(OPTIMIZELY_ACCOUNT_NUMBER='1234567')
+ self.settings_manager.set(
+ MIXPANEL_TOKEN='0123456789abcdef0123456789abcdef')
+
+ def test_tag(self):
+ r = self.render_tag('mixpanel', 'mixpanel')
+ self.assertTrue(
+ "mpq.push(['init', '0123456789abcdef0123456789abcdef']);" in r,
+ r)
+
+ def test_node(self):
+ r = MixpanelNode().render(Context())
+ self.assertTrue(
+ "mpq.push(['init', '0123456789abcdef0123456789abcdef']);" in r,
+ r)
+
+ def test_no_token(self):
+ self.settings_manager.delete('MIXPANEL_TOKEN')
+ self.assertRaises(AnalyticalException, MixpanelNode)
+
+ def test_wrong_token(self):
+ self.settings_manager.set(
+ MIXPANEL_TOKEN='0123456789abcdef0123456789abcde')
+ self.assertRaises(AnalyticalException, MixpanelNode)
+ self.settings_manager.set(
+ MIXPANEL_TOKEN='0123456789abcdef0123456789abcdef0')
+ self.assertRaises(AnalyticalException, MixpanelNode)
+
+ def test_identify(self):
+ self.settings_manager.set(ANALYTICAL_AUTO_IDENTIFY=True)
+ r = MixpanelNode().render(Context({'user': User(username='test')}))
+ self.assertTrue("mpq.push(['identify', 'test']);" in r, r)
+
+ def test_event(self):
+ r = MixpanelNode().render(Context({'mixpanel_event':
+ ('test_event', {'prop1': 'val1', 'prop2': 'val2'})}))
+ self.assertTrue("mpq.push(['track', 'test_event', "
+ '{"prop1": "val1", "prop2": "val2"}]);' in r, r)
diff --git a/analytical/tests/test_tag_optimizely.py b/analytical/tests/test_tag_optimizely.py
new file mode 100644
index 0000000..34742bf
--- /dev/null
+++ b/analytical/tests/test_tag_optimizely.py
@@ -0,0 +1,39 @@
+"""
+Tests for the Optimizely template tags and filters.
+"""
+
+from django.template import Context
+
+from analytical.templatetags.optimizely import OptimizelyNode
+from analytical.tests.utils import TagTestCase
+from analytical.utils import AnalyticalException
+
+
+class OptimizelyTagTestCase(TagTestCase):
+ """
+ Tests for the ``optimizely`` template tag.
+ """
+
+ def setUp(self):
+ super(OptimizelyTagTestCase, self).setUp()
+ self.settings_manager.set(OPTIMIZELY_ACCOUNT_NUMBER='1234567')
+
+ def test_tag(self):
+ self.assertEqual(
+ '',
+ self.render_tag('optimizely', 'optimizely'))
+
+ def test_node(self):
+ self.assertEqual(
+ '',
+ OptimizelyNode().render(Context()))
+
+ def test_no_account_number(self):
+ self.settings_manager.delete('OPTIMIZELY_ACCOUNT_NUMBER')
+ self.assertRaises(AnalyticalException, OptimizelyNode)
+
+ def test_wrong_account_number(self):
+ self.settings_manager.set(OPTIMIZELY_ACCOUNT_NUMBER='123456')
+ self.assertRaises(AnalyticalException, OptimizelyNode)
+ self.settings_manager.set(OPTIMIZELY_ACCOUNT_NUMBER='12345678')
+ self.assertRaises(AnalyticalException, OptimizelyNode)
diff --git a/analytical/tests/test_template_tags.py b/analytical/tests/test_template_tags.py
deleted file mode 100644
index f6a9d8e..0000000
--- a/analytical/tests/test_template_tags.py
+++ /dev/null
@@ -1,90 +0,0 @@
-"""
-Tests for the template tags.
-"""
-
-from django.http import HttpRequest
-from django import template
-from django.test import TestCase
-
-from analytical import services
-from analytical.tests.utils import TestSettingsManager
-
-
-class TemplateTagsTestCase(TestCase):
- """
- Tests for the template tags.
- """
-
- def setUp(self):
- self.settings_manager = TestSettingsManager()
- self.settings_manager.set(ANALYTICAL_SERVICES=[
- 'analytical.services.console.ConsoleService'])
- services.enabled_services = None
-
- def tearDown(self):
- self.settings_manager.revert()
- services.enabled_services = None
-
- def render_location_tag(self, location, context=None):
- if context is None: context = {}
- t = template.Template(
- "{%% load analytical %%}{%% analytical_setup_%s %%}"
- % location)
- return t.render(template.Context(context))
-
- def test_location_tags(self):
- for l in ['head_top', 'head_bottom', 'body_top', 'body_bottom']:
- r = self.render_location_tag(l)
- self.assertTrue('rendering analytical_%s tag' % l in r, r)
-
- def test_render_internal_ip(self):
- self.settings_manager.set(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
- req = HttpRequest()
- req.META['REMOTE_ADDR'] = '1.1.1.1'
- for l in ['head_top', 'head_bottom', 'body_top', 'body_bottom']:
- r = self.render_location_tag(l, {'request': req})
- self.assertTrue('"
-def get_required_setting(self, setting, value_re, invalid_msg):
+def validate_setting(setting, value_re, invalid_msg):
+ try:
+ get_required_setting(setting, value_re, invalid_msg)
+ except AnalyticalException, e:
+ raise ImproperlyConfigured(e)
+
+
+def get_required_setting(setting, value_re, invalid_msg):
try:
value = getattr(settings, setting)
except AttributeError:
- raise ImproperlyConfigured("%s setting: not found" % setting)
+ raise AnalyticalException("%s setting: not found" % setting)
value = str(value)
if not value_re.search(value):
- raise ImproperlyConfigured("%s setting: %s: '%s'"
+ raise AnalyticalException("%s setting: %s: '%s'"
% (setting, invalid_msg, value))
return value
-def get_identity(context):
+def get_identity(context, prefix=None):
+ if prefix is not None:
+ try:
+ return context['%s_identity' % prefix]
+ except KeyError:
+ pass
try:
- return context[IDENTITY_CONTEXT_KEY]
+ return context['analytical_identity']
except KeyError:
pass
if getattr(settings, 'ANALYTICAL_AUTO_IDENTIFY', True):
@@ -41,16 +52,33 @@ def get_identity(context):
return None
-def is_internal_ip(context):
+def is_internal_ip(context, prefix=None):
try:
request = context['request']
- remote_ip = request.META.get('HTTP_X_FORWARDED_FOR',
- request.META.get('REMOTE_ADDR', ''))
- return remote_ip in getattr(settings, 'ANALYTICAL_INTERNAL_IPS',
- getattr(settings, 'INTERNAL_IPS', []))
+ remote_ip = request.META.get('HTTP_X_FORWARDED_FOR', '')
+ if not remote_ip:
+ remote_ip = request.META.get('HTTP_X_FORWARDED_FOR', '')
+
+ internal_ips = ''
+ if prefix is not None:
+ internal_ips = getattr(settings, '%s_INTERNAL_IPS' % prefix, '')
+ if not internal_ips:
+ internal_ips = getattr(settings, 'ANALYTICAL_INTERNAL_IPS', '')
+ if not internal_ips:
+ internal_ips = getattr(settings, 'INTERNAL_IPS', '')
+
+ return remote_ip in internal_ips
except KeyError, AttributeError:
return False
def disable_html(self, html, service):
return HTML_COMMENT % locals()
+
+
+class AnalyticalException(Exception):
+ """
+ Raised when an exception occurs in any django-analytical code that should
+ be silenced in templates.
+ """
+ silent_variable_failure = True
diff --git a/setup.py b/setup.py
index 4de3786..6cedbbc 100644
--- a/setup.py
+++ b/setup.py
@@ -17,6 +17,7 @@ except ImportError:
class TestCommand(Command):
+ description = "run package tests"
user_options = []
def initialize_options(self):