Source

Mango / tests.py

Full commit
#!/usr/bin/python
# -*- coding: utf-8 -*-

from __future__ import with_statement
import datetime
import imp
import os
import re
import unittest

import pytz

from django.conf import settings
from django.core import mail
from django.core.urlresolvers import reverse
from django.template import Context, Template
from django.test import TestCase
from django.test.client import Client

import mango
from mango.main import Document
from mango.templatetags import mango_extras
from mango.utils import primary_author_email

document_template = Template(
'''{% load mango_extras %}{% autoescape off %}{% if meta == None %}date: 29 September 2010
time: 1:30am
tags: Markdown, Django, Mango
{% else %}{% for k, v in meta %}{{ k }}: {{ v }}
{% endfor %}{% endif %}
{% if title == None %}
Introducing Mango
=================
{% else %}
{{ title }}
===========
{% endif %}
{% firstof body 'Mango attempts to make blogging fun again.' %}
{% endautoescape %}
''')

def create_document(filename='test.text', context=None, body=None):
    if context is None:
        context = {}
    if body is not None:
        context['body'] = re.sub(r'(?m)^ +', '', body)
    filepath = os.path.join(mango.settings.MANGO_PATH, 'examples', filename)
    with open(filepath, 'w') as f:
        f.write(document_template.render(Context(context)))
    document = Document(filepath)
    os.remove(filepath)
    return document


class EmailTests(TestCase):

    def test_contact_form(self):
        name, email = 'David Chambers', 'david@mango.io'
        subject, message = 'Test message', '**Hello!**'
        sender = '%s <%s>' % (name, email)

        client = Client()
        path = reverse('mango.views.contact')
        data = {
            'sender_name': name, 'sender_email': email,
            'subject': subject, 'message': message,
        }

        client.post(path, data)
        self.assertEqual(len(mail.outbox), 1)
        self.assertEqual(len(mail.outbox[0].to), 1)
        self.assertEqual(mail.outbox[0].to[0], primary_author_email())
        self.assertEqual('Cc' in mail.outbox[0].extra_headers, False)
        self.assertEqual(mail.outbox[0].from_email, sender)
        self.assertEqual(mail.outbox[0].subject, subject)
        self.assertEqual(mail.outbox[0].body, message)
        self.assertEqual(len(mail.outbox[0].alternatives), 1)
        self.assertEqual(len(mail.outbox[0].alternatives[0]), 2)
        self.assertEqual(mail.outbox[0].alternatives[0][0], '<p><strong>Hello!</strong></p>')
        self.assertEqual(mail.outbox[0].alternatives[0][1], 'text/html')

        data['cc_sender'] = 'on'
        client.post(path, data)
        self.assertEqual(len(mail.outbox), 2)
        self.assertEqual(mail.outbox[1].extra_headers['Cc'], sender)


class ExcerptTests(unittest.TestCase):

    def test_basic_functionality(self):
        document = create_document(body='''
            | Excerpt.
            
            More text.
        ''')
        self.assertEqual(document.excerpt, '<p>Excerpt.</p>')

    def test_link_id_defined_in_inner_scope(self):
        document = create_document(body='''
            | [Mango][1].
            | 
            | [1]: http://mango.io/
            
            More text.
        ''')
        self.assertEqual(document.excerpt, '<p><a href="http://mango.io/">Mango</a>.</p>')

    def test_link_id_defined_in_outer_scope(self):
        document = create_document(body='''
            | [Mango][1].
            
            More text.
            
            [1]: http://mango.io/
        ''')
        self.assertEqual(document.excerpt, '<p><a href="http://mango.io/">Mango</a>.</p>')

    def test_link_id_defined_in_both_scopes(self):
        document = create_document(body='''
            | [Mango][1].
            | 
            | [1]: http://mango.io/
            
            [Django][1].
            
            [1]: http://www.djangoproject.com/
        ''')
        self.assertEqual(document.excerpt, '<p><a href="http://mango.io/">Mango</a>.</p>')

    def test_update_within_excerpt(self):
        document = create_document(body='''
            | Excerpt.
            | 
            | || [Markdown][] meets [Django][].
            | 
            | [Markdown]: http://daringfireball.net/projects/markdown/syntax
            
            [Django]: http://www.djangoproject.com/
        ''')
        self.assertEqual(document.excerpt, '\n'.join((
                '<p>Excerpt.</p>',
                '<div class="update"><div>',
                '<h4>Update</h4>',
                '<p><a href="http://daringfireball.net/projects/markdown/syntax">Markdown</a> meets <a href="http://www.djangoproject.com/">Django</a>.</p>',
                '</div></div>\n')))

    def test_inherits_only_from_enclosing_scopes(self):
        document = create_document(body='''
            | [Mango][1].
            | 
            | [1]: http://mango.io/
            
            More text.
            
            | [Django][1].
            
            [1]: http://www.djangoproject.com/
        ''')
        self.assertEqual(document.excerpt, '\n'.join((
                '<p><a href="http://mango.io/">Mango</a>.</p>',
                '<p><a href="http://www.djangoproject.com/">Django</a>.</p>')))


class FileNameTests(unittest.TestCase):

    def setUp(self):
        self.mount_point = reverse('mango.views.index')
        mango.settings.UNIX_DOCUMENTS_PATH = os.path.join(mango.settings.MANGO_PATH, 'examples')

    def test_standard_separator(self):
        urls = create_document('1=test.text').urls
        self.assertEqual((urls['canon']['rel'], urls['short']['rel']),
                ('%stest/' % self.mount_point, '%s1/' % self.mount_point))

    def test_deprecated_separator(self):
        urls = create_document('1=>test.text').urls
        self.assertEqual((urls['canon']['rel'], urls['short']['rel']),
                ('%stest/' % self.mount_point, '%s1/' % self.mount_point))

    def test_padded_numeric_separator(self):
        urls = create_document('01=test.text').urls
        self.assertEqual(urls['short']['rel'], '%s1/' % self.mount_point)

    def test_equals_sign_in_slug(self):
        urls = create_document('1=mangoes=tasty.text').urls
        self.assertEqual(urls['canon']['rel'], '%smangoes=tasty/' % self.mount_point)

    def test_escapement(self):
        urls = create_document('=2+2=5.text').urls
        self.assertEqual(urls['canon']['rel'], '%s2+2=5/' % self.mount_point)

    def test_no_extension(self):
        urls = create_document('test').urls
        self.assertEqual(urls['canon']['rel'], '%stest/' % self.mount_point)

    def test_multiple_full_stops(self):
        urls = create_document('mango-0.5-released.text').urls
        self.assertEqual(urls['canon']['rel'], '%smango-0.5-released/' % self.mount_point)


class TimeZoneTests(unittest.TestCase):

    def setUp(self):
        settings.TIME_ZONE = 'Pacific/Auckland'

    def test_converts_to_utc(self):
        self.assertEqual(create_document().datetime.tzinfo, pytz.utc)

    def test_date(self):
        self.assertEqual(create_document().datetime.day, 28)

    def test_hour(self):
        self.assertEqual(create_document().datetime.hour, 12)

    def test_sanity(self):
        tz = pytz.timezone(settings.TIME_ZONE)
        self.assertEqual(create_document().datetime.astimezone(tz),
                tz.localize(datetime.datetime(2010, 9, 29, 1, 30)))


class MetaListsTests(unittest.TestCase):

    def test_in_list(self):
        mango.settings.META_LISTS = ('tags',)
        document = create_document()

        self.assertEqual(len(document.meta['tags']), 3)
        self.assertEqual(document.meta['tags'][0], 'Markdown')
        self.assertEqual(document.meta['tags'][1], 'Django')
        self.assertEqual(document.meta['tags'][2], 'Mango')

        self.assertEqual(len(document.tags()), 3)
        self.assertEqual(document.tags()[0], 'Django')
        self.assertEqual(document.tags()[1], 'Mango')
        self.assertEqual(document.tags()[2], 'Markdown')

    def test_not_in_list(self):
        mango.settings.META_LISTS = ()
        document = create_document()
        self.assertEqual(document.meta['tags'], 'Markdown, Django, Mango')
        self.assertEqual(document.tags(), None)

    def test_irregular_spacing(self):
        mango.settings.META_LISTS = ('tags',)
        document = create_document(context={'meta': [('tags', ' Linux,Mac OS X , Windows ')]})
        self.assertEqual(len(document.meta['tags']), 3)
        self.assertEqual(document.meta['tags'][0], 'Linux')
        self.assertEqual(document.meta['tags'][1], 'Mac OS X')
        self.assertEqual(document.meta['tags'][2], 'Windows')


class TemplateFilterTests(unittest.TestCase):

    def test_month_zero(self):
        self.assertEqual(mango_extras.month(0), '')

    def test_month_one(self):
        self.assertEqual(mango_extras.month(1), 'January')

    def test_month_twelve(self):
        self.assertEqual(mango_extras.month(12), 'December')


class TitleTests(unittest.TestCase):

    def test_backticks(self):
        title = 'Simulating `nonlocal` in Python 2.x'
        document = create_document(context={'title': title})
        self.assertEqual(document.title, 'Simulating <code>nonlocal</code> in Python 2.x')
        self.assertEqual(document.title_text, title)

    def test_html_chars(self):
        title = '1 > 0 && 1 < 2'
        document = create_document(context={'title': title})
        self.assertEqual(document.title, '1 &gt; 0 &amp;&amp; 1 &lt; 2')
        self.assertEqual(document.title_text, title)

    def test_meta_title(self):
        title = 'Hello, world!'
        document = create_document(context={'meta': [('title', title)]})
        self.assertEqual(document.title, title)
        self.assertEqual(document.title_text, title)

    def test_meta_title_with_backticks(self):
        title = 'Simulating `nonlocal` in Python 2.x'
        document = create_document(context={'meta': [('title', title)]})
        self.assertEqual(document.title, title)
        self.assertEqual(document.title_text, title)

    def test_meta_title_with_html_chars(self):
        title = '1 > 0 && 1 < 2'
        document = create_document(context={'meta': [('title', title)]})
        self.assertEqual(document.title, '1 &gt; 0 &amp;&amp; 1 &lt; 2')
        self.assertEqual(document.title_text, title)


class UpdateTests(unittest.TestCase):

    def setUp(self):
        self.expected = '\n'.join((
            '<p>%s</p>',
            '<div class="update"><div>',
            '<h4>Update</h4>',
            '<p><a href="http://mango.io/">Mango</a>.</p>',
            '</div></div>\n',
        ))

    def test_link_id_defined_in_inner_scope(self):
        document = create_document(body='''
            Text.
            
            || [Mango][1].
            || 
            || [1]: http://mango.io/
        ''')
        self.assertEqual(document.html, self.expected % 'Text.')

    def test_link_id_defined_in_outer_scope(self):
        document = create_document(body='''
            Text.
            
            || [Mango][1].
            
            [1]: http://mango.io/
        ''')
        self.assertEqual(document.html, self.expected % 'Text.')

    def test_link_id_defined_in_both_scopes(self):
        document = create_document(body='''
            [Django][1].
            
            || [Mango][1].
            || 
            || [1]: http://mango.io/
            
            [1]: http://www.djangoproject.com/
        ''')
        self.assertEqual(document.html, self.expected %
                '<a href="http://www.djangoproject.com/">Django</a>.')


class VideoTests(unittest.TestCase):

    def test_youtube(self):
        document = create_document(context={'body': '[Soda Pop Stop](http://www.youtube.com/watch?v=gPbh6Ru7VVM)'})
        self.assertEqual(document.html,
                '<iframe class="youtube" type="text/html" src="http://www.youtube.com/embed/gPbh6Ru7VVM?rel=0"></iframe>\n')


# This code is taken from http://stackoverflow.com/questions/1615406/configure-django-to-find-all-doctests-in-all-modules

# Django already runs these, don't include them again
ALREADY_RUN = ['tests.py', 'models.py']

def find_untested_modules(package):
    """ Gets all modules not already included in Django's test suite """
    files = []
    for f in os.listdir(os.path.dirname(package.__file__)):
        if f.endswith('.py') and os.path.basename(f) not in ALREADY_RUN:
            files.append(re.sub(r'\.py$', '', f))
    return [imp.load_module(f, *imp.find_module(f, package.__path__)) for f in files]

def modules_callables(module):
    return [m for m in dir(module) if callable(getattr(module, m))]

def has_doctest(docstring):
    return '>>>' in docstring

__test__ = {}
for module in find_untested_modules(mango):
    for method in modules_callables(module):
        docstring = str(getattr(module, method).__doc__)
        if has_doctest(docstring):
            print 'Mango found doctest: %s.%s' % (module.__name__, method)

            # import the method itself, so doctest can find it
            _temp = __import__(module.__name__, globals(), locals(), [method])
            locals()[method] = getattr(_temp, method)

            # Django looks in __test__ for doctests to run
            __test__[method] = getattr(module, method)