Added get_path tests back in. Special-cased get_path if root and self are equal to...
[philo.git] / tests.py
index d9f743f..1dc48b7 100644 (file)
--- a/tests.py
+++ b/tests.py
@@ -1,6 +1,8 @@
 from django.test import TestCase
 from django import template
 from django.conf import settings
+from django.db import connection
+from philo.exceptions import AncestorDoesNotExist
 from philo.models import Node, Page, Template
 from philo.contrib.penfield.models import Blog, BlogView, BlogEntry
 
@@ -16,28 +18,26 @@ class NodeURLTestCase(TestCase):
                        command = Command()
                        command.handle(all_apps=True)
                
-               self.templates = [template.Template(string) for string in
-                       [
-                               "{% node_url %}", # 0
-                               "{% node_url for node2 %}", # 1
-                               "{% node_url as hello %}<p>{{ hello|slice:'1:' }}</p>", # 2
-                               "{% node_url for nodes|first %}", # 3
-                               "{% node_url with entry %}", # 4
-                               "{% node_url with entry for node2 %}", # 5
-                               "{% node_url with tag for node2 %}", # 6
-                               "{% node_url with date for node2 %}", # 7
-                               "{% node_url entries_by_day year=date|date:'Y' month=date|date:'m' day=date|date:'d' for node2 as goodbye %}<em>{{ goodbye|upper }}</em>", # 8
-                               "{% node_url entries_by_month year=date|date:'Y' month=date|date:'m' for node2 %}", # 9
-                               "{% node_url entries_by_year year=date|date:'Y' for node2 %}", # 10
-                       ]
+               self.templates = [
+                               ("{% node_url %}", "/root/second/"),
+                               ("{% node_url for node2 %}", "/root/second2/"),
+                               ("{% node_url as hello %}<p>{{ hello|slice:'1:' }}</p>", "<p>root/second/</p>"),
+                               ("{% node_url for nodes|first %}", "/root/"),
+                               ("{% node_url with entry %}", settings.TEMPLATE_STRING_IF_INVALID),
+                               ("{% node_url with entry for node2 %}", "/root/second2/2010/10/20/first-entry"),
+                               ("{% node_url with tag for node2 %}", "/root/second2/tags/test-tag/"),
+                               ("{% node_url with date for node2 %}", "/root/second2/2010/10/20"),
+                               ("{% node_url entries_by_day year=date|date:'Y' month=date|date:'m' day=date|date:'d' for node2 as goodbye %}<em>{{ goodbye|upper }}</em>", "<em>/ROOT/SECOND2/2010/10/20</em>"),
+                               ("{% node_url entries_by_month year=date|date:'Y' month=date|date:'m' for node2 %}", "/root/second2/2010/10"),
+                               ("{% node_url entries_by_year year=date|date:'Y' for node2 %}", "/root/second2/2010/"),
                ]
                
                nodes = Node.objects.all()
                blog = Blog.objects.all()[0]
                
                self.context = template.Context({
-                       'node': nodes[0],
-                       'node2': nodes[1],
+                       'node': nodes.get(slug='second'),
+                       'node2': nodes.get(slug='second2'),
                        'nodes': nodes,
                        'entry': BlogEntry.objects.all()[0],
                        'tag': blog.entry_tags.all()[0],
@@ -45,30 +45,84 @@ class NodeURLTestCase(TestCase):
                })
        
        def test_nodeurl(self):
-               for i, template in enumerate(self.templates):
-                       t = template.render(self.context)
-                       
-                       if i == 0:
-                               self.assertEqual(t, "/root/never/")
-                       elif i == 1:
-                               self.assertEqual(t, "/root/blog/")
-                       elif i == 2:
-                               self.assertEqual(t, "<p>root/never/</p>")
-                       elif i == 3:
-                               self.assertEqual(t, "/root/never/")
-                       elif i == 4:
-                               self.assertEqual(t, settings.TEMPLATE_STRING_IF_INVALID)
-                       elif i == 5:
-                               self.assertEqual(t, "/root/blog/2010/10/20/first-entry")
-                       elif i == 6:
-                               self.assertEqual(t, "/root/blog/tags/test-tag/")
-                       elif i == 7:
-                               self.assertEqual(t, "/root/blog/2010/10/20")
-                       elif i == 8:
-                               self.assertEqual(t, "<em>/ROOT/BLOG/2010/10/20</em>")
-                       elif i == 9:
-                               self.assertEqual(t, "/root/blog/2010/10")
-                       elif i == 10:
-                               self.assertEqual(t, "/root/blog/2010/")
+               for string, result in self.templates:
+                       self.assertEqual(template.Template(string).render(self.context), result)
+
+class TreePathTestCase(TestCase):
+       urls = 'philo.urls'
+       fixtures = ['test_fixtures.json']
+       
+       def setUp(self):
+               if 'south' in settings.INSTALLED_APPS:
+                       from south.management.commands.migrate import Command
+                       command = Command()
+                       command.handle(all_apps=True)
+       
+       def assertQueryLimit(self, max, expected_result, *args, **kwargs):
+               # As a rough measure of efficiency, limit the number of queries required for a given operation.
+               settings.DEBUG = True
+               call = kwargs.pop('callable', Node.objects.get_with_path)
+               try:
+                       queries = len(connection.queries)
+                       if isinstance(expected_result, type) and issubclass(expected_result, Exception):
+                               self.assertRaises(expected_result, call, *args, **kwargs)
                        else:
-                               print "Rendered as:\n%s\n\n" % t
\ No newline at end of file
+                               self.assertEqual(call(*args, **kwargs), expected_result)
+                       queries = len(connection.queries) - queries
+                       if queries > max:
+                               raise AssertionError('"%d" unexpectedly not less than or equal to "%s"' % (queries, max))
+               finally:
+                       settings.DEBUG = False
+       
+       def test_get_with_path(self):
+               root = Node.objects.get(slug='root')
+               third = Node.objects.get(slug='third')
+               second2 = Node.objects.get(slug='second2')
+               fifth = Node.objects.get(slug='fifth')
+               e = Node.DoesNotExist
+               
+               # Empty segments
+               self.assertQueryLimit(0, root, '', root=root)
+               self.assertQueryLimit(0, e, '')
+               self.assertQueryLimit(0, (root, None), '', root=root, absolute_result=False)
+               
+               # Absolute result
+               self.assertQueryLimit(1, third, 'root/second/third')
+               self.assertQueryLimit(1, third, 'second/third', root=root)
+               self.assertQueryLimit(1, third, 'root//////second/third///')
+               
+               self.assertQueryLimit(1, e, 'root/secont/third')
+               self.assertQueryLimit(1, e, 'second/third')
+               
+               # Non-absolute result (binary search)
+               self.assertQueryLimit(2, (second2, 'sub/path/tail'), 'root/second2/sub/path/tail', absolute_result=False)
+               self.assertQueryLimit(3, (second2, 'sub/'), 'root/second2/sub/', absolute_result=False)
+               self.assertQueryLimit(2, e, 'invalid/path/1/2/3/4/5/6/7/8/9/1/2/3/4/5/6/7/8/9/0', absolute_result=False)
+               self.assertQueryLimit(1, (root, None), 'root', absolute_result=False)
+               self.assertQueryLimit(2, (second2, None), 'root/second2', absolute_result=False)
+               self.assertQueryLimit(3, (third, None), 'root/second/third', absolute_result=False)
+               
+               # with root != None
+               self.assertQueryLimit(1, (second2, None), 'second2', root=root, absolute_result=False)
+               self.assertQueryLimit(2, (third, None), 'second/third', root=root, absolute_result=False)
+               
+               # Preserve trailing slash
+               self.assertQueryLimit(2, (second2, 'sub/path/tail/'), 'root/second2/sub/path/tail/', absolute_result=False)
+               
+               # Speed increase for leaf nodes - should this be tested?
+               self.assertQueryLimit(1, (fifth, 'sub/path/tail/len/five'), 'root/second/third/fourth/fifth/sub/path/tail/len/five', absolute_result=False)
+       
+       def test_get_path(self):
+               root = Node.objects.get(slug='root')
+               root2 = Node.objects.get(slug='root')
+               third = Node.objects.get(slug='third')
+               second2 = Node.objects.get(slug='second2')
+               fifth = Node.objects.get(slug='fifth')
+               e = AncestorDoesNotExist
+               
+               self.assertQueryLimit(0, 'root', callable=root.get_path)
+               self.assertQueryLimit(0, '', root2, callable=root.get_path)
+               self.assertQueryLimit(1, 'root/second/third', callable=third.get_path)
+               self.assertQueryLimit(1, 'second/third', root, callable=third.get_path)
+               self.assertQueryLimit(1, e, third, callable=second2.get_path)
+               self.assertQueryLimit(1, '? - ?', root, ' - ', 'title', callable=third.get_path)
\ No newline at end of file