PageRenderTime 541ms CodeModel.GetById 194ms app.highlight 114ms RepoModel.GetById 228ms app.codeStats 0ms

/tests/regressiontests/staticfiles_tests/tests.py

https://code.google.com/p/mango-py/
Python | 434 lines | 248 code | 72 blank | 114 comment | 11 complexity | 6086f907cdda445b792ebd99c37517dd MD5 | raw file
  1# -*- encoding: utf-8 -*-
  2import codecs
  3import os
  4import posixpath
  5import shutil
  6import sys
  7import tempfile
  8from StringIO import StringIO
  9
 10from django.conf import settings
 11from django.contrib.staticfiles import finders, storage
 12from django.core.exceptions import ImproperlyConfigured
 13from django.core.files.storage import default_storage
 14from django.core.management import call_command
 15from django.test import TestCase
 16from django.utils.encoding import smart_unicode
 17from django.utils._os import rmtree_errorhandler
 18
 19
 20TEST_ROOT = os.path.normcase(os.path.dirname(__file__))
 21
 22
 23class StaticFilesTestCase(TestCase):
 24    """
 25    Test case with a couple utility assertions.
 26    """
 27    def setUp(self):
 28        self.old_static_url = settings.STATIC_URL
 29        self.old_static_root = settings.STATIC_ROOT
 30        self.old_staticfiles_dirs = settings.STATICFILES_DIRS
 31        self.old_staticfiles_finders = settings.STATICFILES_FINDERS
 32        self.old_media_root = settings.MEDIA_ROOT
 33        self.old_media_url = settings.MEDIA_URL
 34        self.old_admin_media_prefix = settings.ADMIN_MEDIA_PREFIX
 35        self.old_debug = settings.DEBUG
 36        self.old_installed_apps = settings.INSTALLED_APPS
 37
 38        site_media = os.path.join(TEST_ROOT, 'project', 'site_media')
 39        settings.DEBUG = True
 40        settings.MEDIA_ROOT =  os.path.join(site_media, 'media')
 41        settings.MEDIA_URL = '/media/'
 42        settings.STATIC_ROOT = os.path.join(site_media, 'static')
 43        settings.STATIC_URL = '/static/'
 44        settings.ADMIN_MEDIA_PREFIX = '/static/admin/'
 45        settings.STATICFILES_DIRS = (
 46            os.path.join(TEST_ROOT, 'project', 'documents'),
 47        )
 48        settings.STATICFILES_FINDERS = (
 49            'django.contrib.staticfiles.finders.FileSystemFinder',
 50            'django.contrib.staticfiles.finders.AppDirectoriesFinder',
 51            'django.contrib.staticfiles.finders.DefaultStorageFinder',
 52        )
 53        settings.INSTALLED_APPS = [
 54            'django.contrib.admin',
 55            'django.contrib.staticfiles',
 56            'regressiontests.staticfiles_tests',
 57            'regressiontests.staticfiles_tests.apps.test',
 58            'regressiontests.staticfiles_tests.apps.no_label',
 59        ]
 60
 61        # Clear the cached default_storage out, this is because when it first
 62        # gets accessed (by some other test), it evaluates settings.MEDIA_ROOT,
 63        # since we're planning on changing that we need to clear out the cache.
 64        default_storage._wrapped = None
 65
 66        # To make sure SVN doesn't hangs itself with the non-ASCII characters
 67        # during checkout, we actually create one file dynamically.
 68        self._nonascii_filepath = os.path.join(
 69            TEST_ROOT, 'apps', 'test', 'static', 'test', u'fi\u015fier.txt')
 70        f = codecs.open(self._nonascii_filepath, 'w', 'utf-8')
 71        try:
 72            f.write(u"fi\u015fier in the app dir")
 73        finally:
 74            f.close()
 75
 76    def tearDown(self):
 77        settings.DEBUG = self.old_debug
 78        settings.MEDIA_ROOT = self.old_media_root
 79        settings.MEDIA_URL = self.old_media_url
 80        settings.ADMIN_MEDIA_PREFIX = self.old_admin_media_prefix
 81        settings.STATIC_ROOT = self.old_static_root
 82        settings.STATIC_URL = self.old_static_url
 83        settings.STATICFILES_DIRS = self.old_staticfiles_dirs
 84        settings.STATICFILES_FINDERS = self.old_staticfiles_finders
 85        settings.INSTALLED_APPS = self.old_installed_apps
 86        if os.path.exists(self._nonascii_filepath):
 87            os.unlink(self._nonascii_filepath)
 88
 89    def assertFileContains(self, filepath, text):
 90        self.assertTrue(text in self._get_file(smart_unicode(filepath)),
 91                        u"'%s' not in '%s'" % (text, filepath))
 92
 93    def assertFileNotFound(self, filepath):
 94        self.assertRaises(IOError, self._get_file, filepath)
 95
 96
 97class BuildStaticTestCase(StaticFilesTestCase):
 98    """
 99    Tests shared by all file-resolving features (collectstatic,
100    findstatic, and static serve view).
101
102    This relies on the asserts defined in UtilityAssertsTestCase, but
103    is separated because some test cases need those asserts without
104    all these tests.
105    """
106    def setUp(self):
107        super(BuildStaticTestCase, self).setUp()
108        self.old_root = settings.STATIC_ROOT
109        settings.STATIC_ROOT = tempfile.mkdtemp()
110        self.run_collectstatic()
111
112    def tearDown(self):
113        # Use our own error handler that can handle .svn dirs on Windows
114        shutil.rmtree(settings.STATIC_ROOT, ignore_errors=True,
115                      onerror=rmtree_errorhandler)
116        settings.STATIC_ROOT = self.old_root
117        super(BuildStaticTestCase, self).tearDown()
118
119    def run_collectstatic(self, **kwargs):
120        call_command('collectstatic', interactive=False, verbosity='0',
121                     ignore_patterns=['*.ignoreme'], **kwargs)
122
123    def _get_file(self, filepath):
124        assert filepath, 'filepath is empty.'
125        filepath = os.path.join(settings.STATIC_ROOT, filepath)
126        f = codecs.open(filepath, "r", "utf-8")
127        try:
128            return f.read()
129        finally:
130            f.close()
131
132
133class TestDefaults(object):
134    """
135    A few standard test cases.
136    """
137    def test_staticfiles_dirs(self):
138        """
139        Can find a file in a STATICFILES_DIRS directory.
140        """
141        self.assertFileContains('test.txt', 'Can we find')
142
143    def test_staticfiles_dirs_subdir(self):
144        """
145        Can find a file in a subdirectory of a STATICFILES_DIRS
146        directory.
147        """
148        self.assertFileContains('subdir/test.txt', 'Can we find')
149
150    def test_staticfiles_dirs_priority(self):
151        """
152        File in STATICFILES_DIRS has priority over file in app.
153        """
154        self.assertFileContains('test/file.txt', 'STATICFILES_DIRS')
155
156    def test_app_files(self):
157        """
158        Can find a file in an app static/ directory.
159        """
160        self.assertFileContains('test/file1.txt', 'file1 in the app dir')
161
162    def test_nonascii_filenames(self):
163        """
164        Can find a file with non-ASCII character in an app static/ directory.
165        """
166        self.assertFileContains(u'test/fi?&#x;ier.txt', u'fi?&#x;ier in the app dir')
167
168    def test_camelcase_filenames(self):
169        """
170        Can find a file with capital letters.
171        """
172        self.assertFileContains(u'test/camelCase.txt', u'camelCase')
173
174
175class TestFindStatic(BuildStaticTestCase, TestDefaults):
176    """
177    Test ``findstatic`` management command.
178    """
179    def _get_file(self, filepath):
180        _stdout = sys.stdout
181        sys.stdout = StringIO()
182        try:
183            call_command('findstatic', filepath, all=False, verbosity='0')
184            sys.stdout.seek(0)
185            lines = [l.strip() for l in sys.stdout.readlines()]
186            contents = codecs.open(
187                smart_unicode(lines[1].strip()), "r", "utf-8").read()
188        finally:
189            sys.stdout = _stdout
190        return contents
191
192    def test_all_files(self):
193        """
194        Test that findstatic returns all candidate files if run without --first.
195        """
196        _stdout = sys.stdout
197        sys.stdout = StringIO()
198        try:
199            call_command('findstatic', 'test/file.txt', verbosity='0')
200            sys.stdout.seek(0)
201            lines = [l.strip() for l in sys.stdout.readlines()]
202        finally:
203            sys.stdout = _stdout
204        self.assertEqual(len(lines), 3) # three because there is also the "Found <file> here" line
205        self.assertTrue('project' in lines[1])
206        self.assertTrue('apps' in lines[2])
207
208
209class TestBuildStatic(BuildStaticTestCase, TestDefaults):
210    """
211    Test ``collectstatic`` management command.
212    """
213    def test_ignore(self):
214        """
215        Test that -i patterns are ignored.
216        """
217        self.assertFileNotFound('test/test.ignoreme')
218
219    def test_common_ignore_patterns(self):
220        """
221        Common ignore patterns (*~, .*, CVS) are ignored.
222        """
223        self.assertFileNotFound('test/.hidden')
224        self.assertFileNotFound('test/backup~')
225        self.assertFileNotFound('test/CVS')
226
227
228class TestBuildStaticExcludeNoDefaultIgnore(BuildStaticTestCase, TestDefaults):
229    """
230    Test ``--exclude-dirs`` and ``--no-default-ignore`` options for
231    ``collectstatic`` management command.
232    """
233    def run_collectstatic(self):
234        super(TestBuildStaticExcludeNoDefaultIgnore, self).run_collectstatic(
235            use_default_ignore_patterns=False)
236
237    def test_no_common_ignore_patterns(self):
238        """
239        With --no-default-ignore, common ignore patterns (*~, .*, CVS)
240        are not ignored.
241
242        """
243        self.assertFileContains('test/.hidden', 'should be ignored')
244        self.assertFileContains('test/backup~', 'should be ignored')
245        self.assertFileContains('test/CVS', 'should be ignored')
246
247
248class TestNoFilesCreated(object):
249
250    def test_no_files_created(self):
251        """
252        Make sure no files were create in the destination directory.
253        """
254        self.assertEqual(os.listdir(settings.STATIC_ROOT), [])
255
256
257class TestBuildStaticDryRun(BuildStaticTestCase, TestNoFilesCreated):
258    """
259    Test ``--dry-run`` option for ``collectstatic`` management command.
260    """
261    def run_collectstatic(self):
262        super(TestBuildStaticDryRun, self).run_collectstatic(dry_run=True)
263
264
265class TestBuildStaticNonLocalStorage(BuildStaticTestCase, TestNoFilesCreated):
266    """
267    Tests for #15035
268    """
269    def setUp(self):
270        self.old_staticfiles_storage = settings.STATICFILES_STORAGE
271        settings.STATICFILES_STORAGE = 'regressiontests.staticfiles_tests.storage.DummyStorage'
272        super(TestBuildStaticNonLocalStorage, self).setUp()
273
274    def tearDown(self):
275        super(TestBuildStaticNonLocalStorage, self).tearDown()
276        settings.STATICFILES_STORAGE = self.old_staticfiles_storage
277
278
279if sys.platform != 'win32':
280    class TestBuildStaticLinks(BuildStaticTestCase, TestDefaults):
281        """
282        Test ``--link`` option for ``collectstatic`` management command.
283
284        Note that by inheriting ``TestDefaults`` we repeat all
285        the standard file resolving tests here, to make sure using
286        ``--link`` does not change the file-selection semantics.
287        """
288        def run_collectstatic(self):
289            super(TestBuildStaticLinks, self).run_collectstatic(link=True)
290
291        def test_links_created(self):
292            """
293            With ``--link``, symbolic links are created.
294            """
295            self.assertTrue(os.path.islink(os.path.join(settings.STATIC_ROOT, 'test.txt')))
296
297
298class TestServeStatic(StaticFilesTestCase):
299    """
300    Test static asset serving view.
301    """
302    urls = 'regressiontests.staticfiles_tests.urls.default'
303
304    def _response(self, filepath):
305        return self.client.get(
306            posixpath.join(settings.STATIC_URL, filepath))
307
308    def assertFileContains(self, filepath, text):
309        self.assertContains(self._response(filepath), text)
310
311    def assertFileNotFound(self, filepath):
312        self.assertEqual(self._response(filepath).status_code, 404)
313
314
315class TestServeDisabled(TestServeStatic):
316    """
317    Test serving static files disabled when DEBUG is False.
318    """
319    def setUp(self):
320        super(TestServeDisabled, self).setUp()
321        settings.DEBUG = False
322
323    def test_disabled_serving(self):
324        self.assertRaisesRegexp(ImproperlyConfigured, 'The staticfiles view '
325            'can only be used in debug mode ', self._response, 'test.txt')
326
327
328class TestServeStaticWithDefaultURL(TestServeStatic, TestDefaults):
329    """
330    Test static asset serving view with manually configured URLconf.
331    """
332    pass
333
334class TestServeStaticWithURLHelper(TestServeStatic, TestDefaults):
335    """
336    Test static asset serving view with staticfiles_urlpatterns helper.
337    """
338    urls = 'regressiontests.staticfiles_tests.urls.helper'
339
340
341class TestServeAdminMedia(TestServeStatic):
342    """
343    Test serving media from django.contrib.admin.
344    """
345    def _response(self, filepath):
346        return self.client.get(
347            posixpath.join(settings.ADMIN_MEDIA_PREFIX, filepath))
348
349    def test_serve_admin_media(self):
350        self.assertFileContains('css/base.css', 'body')
351
352
353class FinderTestCase(object):
354    """
355    Base finder test mixin
356    """
357    def test_find_first(self):
358        src, dst = self.find_first
359        self.assertEqual(self.finder.find(src), dst)
360
361    def test_find_all(self):
362        src, dst = self.find_all
363        self.assertEqual(self.finder.find(src, all=True), dst)
364
365
366class TestFileSystemFinder(StaticFilesTestCase, FinderTestCase):
367    """
368    Test FileSystemFinder.
369    """
370    def setUp(self):
371        super(TestFileSystemFinder, self).setUp()
372        self.finder = finders.FileSystemFinder()
373        test_file_path = os.path.join(TEST_ROOT, 'project', 'documents', 'test', 'file.txt')
374        self.find_first = (os.path.join('test', 'file.txt'), test_file_path)
375        self.find_all = (os.path.join('test', 'file.txt'), [test_file_path])
376
377
378class TestAppDirectoriesFinder(StaticFilesTestCase, FinderTestCase):
379    """
380    Test AppDirectoriesFinder.
381    """
382    def setUp(self):
383        super(TestAppDirectoriesFinder, self).setUp()
384        self.finder = finders.AppDirectoriesFinder()
385        test_file_path = os.path.join(TEST_ROOT, 'apps', 'test', 'static', 'test', 'file1.txt')
386        self.find_first = (os.path.join('test', 'file1.txt'), test_file_path)
387        self.find_all = (os.path.join('test', 'file1.txt'), [test_file_path])
388
389
390class TestDefaultStorageFinder(StaticFilesTestCase, FinderTestCase):
391    """
392    Test DefaultStorageFinder.
393    """
394    def setUp(self):
395        super(TestDefaultStorageFinder, self).setUp()
396        self.finder = finders.DefaultStorageFinder(
397            storage=storage.StaticFilesStorage(location=settings.MEDIA_ROOT))
398        test_file_path = os.path.join(settings.MEDIA_ROOT, 'media-file.txt')
399        self.find_first = ('media-file.txt', test_file_path)
400        self.find_all = ('media-file.txt', [test_file_path])
401
402
403class TestMiscFinder(TestCase):
404    """
405    A few misc finder tests.
406    """
407    def test_get_finder(self):
408        self.assertTrue(isinstance(finders.get_finder(
409            'django.contrib.staticfiles.finders.FileSystemFinder'),
410            finders.FileSystemFinder))
411
412    def test_get_finder_bad_classname(self):
413        self.assertRaises(ImproperlyConfigured,
414            finders.get_finder, 'django.contrib.staticfiles.finders.FooBarFinder')
415
416    def test_get_finder_bad_module(self):
417        self.assertRaises(ImproperlyConfigured,
418            finders.get_finder, 'foo.bar.FooBarFinder')
419
420
421class TestStaticfilesDirsType(TestCase):
422    """
423    We can't determine if STATICFILES_DIRS is set correctly just by looking at
424    the type, but we can determine if it's definitely wrong.
425    """
426    def setUp(self):
427        self.old_settings_dir = settings.STATICFILES_DIRS
428        settings.STATICFILES_DIRS = 'a string'
429
430    def tearDown(self):
431        settings.STATICFILES_DIRS = self.old_settings_dir
432
433    def test_non_tuple_raises_exception(self):
434        self.assertRaises(ImproperlyConfigured, finders.FileSystemFinder)