diff --git a/README.rst b/README.rst index 1a2553c..c21a44d 100644 --- a/README.rst +++ b/README.rst @@ -161,7 +161,7 @@ object, so you can use them with many other apps that add Django mail functionality (such as Django template-based messages). If you have any questions about the python syntax for any of these properties, -see ``DjrillMandrillFeatureTests`` in tests.py for examples. +see ``DjrillMandrillFeatureTests`` in tests/test_mandrill_send.py for examples. Testing @@ -180,11 +180,11 @@ calls, without actually calling Mandrill or sending any email. So the tests don't require a Mandrill API key, but they *do* require mock_ (``pip install mock``). To run the tests, either:: - python setup.py test + python -Wall setup.py test or:: - python runtests.py + python -Wall runtests.py Release Notes diff --git a/djrill/tests/__init__.py b/djrill/tests/__init__.py new file mode 100644 index 0000000..82248c1 --- /dev/null +++ b/djrill/tests/__init__.py @@ -0,0 +1,3 @@ +from test_admin import * +from test_legacy import * +from test_mandrill_send import * diff --git a/djrill/test_admin_urls.py b/djrill/tests/admin_urls.py similarity index 100% rename from djrill/test_admin_urls.py rename to djrill/tests/admin_urls.py diff --git a/djrill/tests/mock_backend.py b/djrill/tests/mock_backend.py new file mode 100644 index 0000000..3e4546b --- /dev/null +++ b/djrill/tests/mock_backend.py @@ -0,0 +1,44 @@ +from mock import patch + +from django.conf import settings +from django.test import TestCase +from django.utils import simplejson as json + +class DjrillBackendMockAPITestCase(TestCase): + """TestCase that uses Djrill EmailBackend with a mocked Mandrill API""" + + class MockResponse: + """requests.post return value mock sufficient for DjrillBackend""" + def __init__(self, status_code=200, content="{}"): + self.status_code = status_code + self.content = content + + def setUp(self): + self.patch = patch('requests.post') + self.mock_post = self.patch.start() + self.mock_post.return_value = self.MockResponse() + + settings.MANDRILL_API_KEY = "FAKE_API_KEY_FOR_TESTING" + + # Django TestCase sets up locmem EmailBackend; override it here + self.original_email_backend = settings.EMAIL_BACKEND + settings.EMAIL_BACKEND = "djrill.mail.backends.djrill.DjrillBackend" + + def tearDown(self): + self.patch.stop() + settings.EMAIL_BACKEND = self.original_email_backend + + def get_api_call_data(self): + """Returns the data posted to the Mandrill API. + + Fails test if API wasn't called. + """ + if self.mock_post.call_args is None: + raise AssertionError("Mandrill API was not called") + (args, kwargs) = self.mock_post.call_args + if 'data' not in kwargs: + raise AssertionError("requests.post was called without data kwarg " + "-- Maybe tests need to be updated for backend changes?") + return json.loads(kwargs['data']) + + diff --git a/djrill/tests/test_admin.py b/djrill/tests/test_admin.py new file mode 100644 index 0000000..d27f871 --- /dev/null +++ b/djrill/tests/test_admin.py @@ -0,0 +1,72 @@ +import sys + +from django.test import TestCase +from django.contrib.auth.models import User +from django.contrib import admin + +from djrill.tests.mock_backend import DjrillBackendMockAPITestCase + + +def reset_admin_site(): + """Return the Django admin globals to their original state""" + admin.site = admin.AdminSite() # restore default + if 'djrill.admin' in sys.modules: + del sys.modules['djrill.admin'] # force autodiscover to re-import + + +class DjrillAdminTests(DjrillBackendMockAPITestCase): + """Test the Djrill admin site""" + + # These tests currently just verify that the admin site pages load + # without error -- they don't test any Mandrill-supplied content. + # (Future improvements could mock the Mandrill responses.) + + # These urls set up the DjrillAdminSite as suggested in the readme + urls = 'djrill.tests.admin_urls' + + @classmethod + def setUpClass(cls): + # Other test cases may muck with the Django admin site globals, + # so return it to the default state before loading test_admin_urls + reset_admin_site() + + def setUp(self): + super(DjrillAdminTests, self).setUp() + # Must be authenticated staff to access admin site... + admin = User.objects.create_user('admin', 'admin@example.com', 'secret') + admin.is_staff = True + admin.save() + self.client.login(username='admin', password='secret') + + def test_admin_senders(self): + response = self.client.get('/admin/djrill/senders/') + self.assertEqual(response.status_code, 200) + self.assertContains(response, "Senders") + + def test_admin_status(self): + response = self.client.get('/admin/djrill/status/') + self.assertEqual(response.status_code, 200) + self.assertContains(response, "Status") + + def test_admin_tags(self): + response = self.client.get('/admin/djrill/tags/') + self.assertEqual(response.status_code, 200) + self.assertContains(response, "Tags") + + def test_admin_urls(self): + response = self.client.get('/admin/djrill/urls/') + self.assertEqual(response.status_code, 200) + self.assertContains(response, "URLs") + + def test_admin_index(self): + """Make sure Djrill section is included in the admin index page""" + response = self.client.get('/admin/') + self.assertEqual(response.status_code, 200) + self.assertContains(response, "Djrill") + + +class DjrillNoAdminTests(TestCase): + def test_admin_autodiscover_without_djrill(self): + """Make sure autodiscover doesn't die without DjrillAdminSite""" + reset_admin_site() + admin.autodiscover() # test: this shouldn't error diff --git a/djrill/tests/test_legacy.py b/djrill/tests/test_legacy.py new file mode 100644 index 0000000..c8b39c6 --- /dev/null +++ b/djrill/tests/test_legacy.py @@ -0,0 +1,74 @@ +# Tests deprecated Djrill features + +from django.test import TestCase + +from djrill.mail import DjrillMessage + + +class DjrillMessageTests(TestCase): + """Test the DjrillMessage class (deprecated as of Djrill v0.2.0) + + Maintained for compatibility with older code. + + """ + + def setUp(self): + self.subject = "Djrill baby djrill." + self.from_name = "Tarzan" + self.from_email = "test@example" + self.to = ["King Kong ", + "Cheetah ", - "Cheetah