tests.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. import tempfile
  2. import shutil
  3. import os
  4. import sys
  5. import posixpath
  6. from StringIO import StringIO
  7. from django.test import TestCase
  8. from django.conf import settings
  9. from django.contrib.staticfiles import finders, storage
  10. from django.core.files.storage import default_storage
  11. from django.core.exceptions import ImproperlyConfigured
  12. from django.core.management import call_command
  13. from django.db.models.loading import load_app
  14. from django.template import Template, Context
  15. TEST_ROOT = os.path.dirname(__file__)
  16. class StaticFilesTestCase(TestCase):
  17. """
  18. Test case with a couple utility assertions.
  19. """
  20. def setUp(self):
  21. self.old_static_url = settings.STATIC_URL
  22. self.old_static_root = settings.STATIC_ROOT
  23. self.old_staticfiles_dirs = settings.STATICFILES_DIRS
  24. self.old_staticfiles_finders = settings.STATICFILES_FINDERS
  25. self.old_media_root = settings.MEDIA_ROOT
  26. self.old_media_url = settings.MEDIA_URL
  27. self.old_admin_media_prefix = settings.ADMIN_MEDIA_PREFIX
  28. self.old_debug = settings.DEBUG
  29. self.old_installed_apps = settings.INSTALLED_APPS
  30. # We have to load these apps to test staticfiles.
  31. load_app('regressiontests.staticfiles_tests.apps.test')
  32. load_app('regressiontests.staticfiles_tests.apps.no_label')
  33. site_media = os.path.join(TEST_ROOT, 'project', 'site_media')
  34. settings.DEBUG = True
  35. settings.MEDIA_ROOT = os.path.join(site_media, 'media')
  36. settings.MEDIA_URL = '/media/'
  37. settings.STATIC_ROOT = os.path.join(site_media, 'static')
  38. settings.STATIC_URL = '/static/'
  39. settings.ADMIN_MEDIA_PREFIX = '/static/admin/'
  40. settings.STATICFILES_DIRS = (
  41. os.path.join(TEST_ROOT, 'project', 'documents'),
  42. )
  43. settings.STATICFILES_FINDERS = (
  44. 'django.contrib.staticfiles.finders.FileSystemFinder',
  45. 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
  46. 'django.contrib.staticfiles.finders.DefaultStorageFinder',
  47. )
  48. settings.INSTALLED_APPS = [
  49. "django.contrib.staticfiles",
  50. "regressiontests.staticfiles_tests",
  51. ]
  52. # Clear the cached default_storage out, this is because when it first
  53. # gets accessed (by some other test), it evaluates settings.MEDIA_ROOT,
  54. # since we're planning on changing that we need to clear out the cache.
  55. default_storage._wrapped = None
  56. def tearDown(self):
  57. settings.DEBUG = self.old_debug
  58. settings.MEDIA_ROOT = self.old_media_root
  59. settings.MEDIA_URL = self.old_media_url
  60. settings.ADMIN_MEDIA_PREFIX = self.old_admin_media_prefix
  61. settings.STATIC_ROOT = self.old_static_root
  62. settings.STATIC_URL = self.old_static_url
  63. settings.STATICFILES_DIRS = self.old_staticfiles_dirs
  64. settings.STATICFILES_FINDERS = self.old_staticfiles_finders
  65. settings.INSTALLED_APPS = self.old_installed_apps
  66. def assertFileContains(self, filepath, text):
  67. self.failUnless(text in self._get_file(filepath),
  68. "'%s' not in '%s'" % (text, filepath))
  69. def assertFileNotFound(self, filepath):
  70. self.assertRaises(IOError, self._get_file, filepath)
  71. class BuildStaticTestCase(StaticFilesTestCase):
  72. """
  73. Tests shared by all file-resolving features (collectstatic,
  74. findstatic, and static serve view).
  75. This relies on the asserts defined in UtilityAssertsTestCase, but
  76. is separated because some test cases need those asserts without
  77. all these tests.
  78. """
  79. def setUp(self):
  80. super(BuildStaticTestCase, self).setUp()
  81. self.old_staticfiles_storage = settings.STATICFILES_STORAGE
  82. self.old_root = settings.STATIC_ROOT
  83. settings.STATIC_ROOT = tempfile.mkdtemp()
  84. self.run_collectstatic()
  85. def tearDown(self):
  86. shutil.rmtree(settings.STATIC_ROOT)
  87. settings.STATIC_ROOT = self.old_root
  88. super(BuildStaticTestCase, self).tearDown()
  89. def run_collectstatic(self, **kwargs):
  90. call_command('collectstatic', interactive=False, verbosity='0',
  91. ignore_patterns=['*.ignoreme'], **kwargs)
  92. def _get_file(self, filepath):
  93. assert filepath, 'filepath is empty.'
  94. filepath = os.path.join(settings.STATIC_ROOT, filepath)
  95. f = open(filepath)
  96. try:
  97. return f.read()
  98. finally:
  99. f.close()
  100. class TestDefaults(object):
  101. """
  102. A few standard test cases.
  103. """
  104. def test_staticfiles_dirs(self):
  105. """
  106. Can find a file in a STATICFILES_DIRS directory.
  107. """
  108. self.assertFileContains('test.txt', 'Can we find')
  109. def test_staticfiles_dirs_subdir(self):
  110. """
  111. Can find a file in a subdirectory of a STATICFILES_DIRS
  112. directory.
  113. """
  114. self.assertFileContains('subdir/test.txt', 'Can we find')
  115. def test_staticfiles_dirs_priority(self):
  116. """
  117. File in STATICFILES_DIRS has priority over file in app.
  118. """
  119. self.assertFileContains('test/file.txt', 'STATICFILES_DIRS')
  120. def test_app_files(self):
  121. """
  122. Can find a file in an app media/ directory.
  123. """
  124. self.assertFileContains('test/file1.txt', 'file1 in the app dir')
  125. class TestFindStatic(BuildStaticTestCase, TestDefaults):
  126. """
  127. Test ``findstatic`` management command.
  128. """
  129. def _get_file(self, filepath):
  130. _stdout = sys.stdout
  131. sys.stdout = StringIO()
  132. try:
  133. call_command('findstatic', filepath, all=False, verbosity='0')
  134. sys.stdout.seek(0)
  135. lines = [l.strip() for l in sys.stdout.readlines()]
  136. contents = open(lines[1].strip()).read()
  137. finally:
  138. sys.stdout = _stdout
  139. return contents
  140. def test_all_files(self):
  141. """
  142. Test that findstatic returns all candidate files if run without --first.
  143. """
  144. _stdout = sys.stdout
  145. sys.stdout = StringIO()
  146. try:
  147. call_command('findstatic', 'test/file.txt', verbosity='0')
  148. sys.stdout.seek(0)
  149. lines = [l.strip() for l in sys.stdout.readlines()]
  150. finally:
  151. sys.stdout = _stdout
  152. self.assertEquals(len(lines), 3) # three because there is also the "Found <file> here" line
  153. self.failUnless('project' in lines[1])
  154. self.failUnless('apps' in lines[2])
  155. class TestBuildStatic(BuildStaticTestCase, TestDefaults):
  156. """
  157. Test ``collectstatic`` management command.
  158. """
  159. def test_ignore(self):
  160. """
  161. Test that -i patterns are ignored.
  162. """
  163. self.assertFileNotFound('test/test.ignoreme')
  164. def test_common_ignore_patterns(self):
  165. """
  166. Common ignore patterns (*~, .*, CVS) are ignored.
  167. """
  168. self.assertFileNotFound('test/.hidden')
  169. self.assertFileNotFound('test/backup~')
  170. self.assertFileNotFound('test/CVS')
  171. class TestBuildStaticExcludeNoDefaultIgnore(BuildStaticTestCase, TestDefaults):
  172. """
  173. Test ``--exclude-dirs`` and ``--no-default-ignore`` options for
  174. ``collectstatic`` management command.
  175. """
  176. def run_collectstatic(self):
  177. super(TestBuildStaticExcludeNoDefaultIgnore, self).run_collectstatic(
  178. use_default_ignore_patterns=False)
  179. def test_no_common_ignore_patterns(self):
  180. """
  181. With --no-default-ignore, common ignore patterns (*~, .*, CVS)
  182. are not ignored.
  183. """
  184. self.assertFileContains('test/.hidden', 'should be ignored')
  185. self.assertFileContains('test/backup~', 'should be ignored')
  186. self.assertFileContains('test/CVS', 'should be ignored')
  187. class TestBuildStaticDryRun(BuildStaticTestCase):
  188. """
  189. Test ``--dry-run`` option for ``collectstatic`` management command.
  190. """
  191. def run_collectstatic(self):
  192. super(TestBuildStaticDryRun, self).run_collectstatic(dry_run=True)
  193. def test_no_files_created(self):
  194. """
  195. With --dry-run, no files created in destination dir.
  196. """
  197. self.assertEquals(os.listdir(settings.STATIC_ROOT), [])
  198. if sys.platform != 'win32':
  199. class TestBuildStaticLinks(BuildStaticTestCase, TestDefaults):
  200. """
  201. Test ``--link`` option for ``collectstatic`` management command.
  202. Note that by inheriting ``TestDefaults`` we repeat all
  203. the standard file resolving tests here, to make sure using
  204. ``--link`` does not change the file-selection semantics.
  205. """
  206. def run_collectstatic(self):
  207. super(TestBuildStaticLinks, self).run_collectstatic(link=True)
  208. def test_links_created(self):
  209. """
  210. With ``--link``, symbolic links are created.
  211. """
  212. self.failUnless(os.path.islink(os.path.join(settings.STATIC_ROOT, 'test.txt')))
  213. class TestServeStatic(StaticFilesTestCase):
  214. """
  215. Test static asset serving view.
  216. """
  217. urls = "regressiontests.staticfiles_tests.urls.default"
  218. def _response(self, filepath):
  219. return self.client.get(
  220. posixpath.join(settings.STATIC_URL, filepath))
  221. def assertFileContains(self, filepath, text):
  222. self.assertContains(self._response(filepath), text)
  223. def assertFileNotFound(self, filepath):
  224. self.assertEquals(self._response(filepath).status_code, 404)
  225. class TestServeDisabled(TestServeStatic):
  226. """
  227. Test serving media from django.contrib.admin.
  228. """
  229. def setUp(self):
  230. super(TestServeDisabled, self).setUp()
  231. settings.DEBUG = False
  232. def test_disabled_serving(self):
  233. self.assertRaisesRegexp(ImproperlyConfigured, "The view to serve "
  234. "static files can only be used if the DEBUG setting is True",
  235. self._response, 'test.txt')
  236. class TestServeStaticWithDefaultURL(TestServeStatic, TestDefaults):
  237. """
  238. Test static asset serving view with staticfiles_urlpatterns helper.
  239. """
  240. pass
  241. class TestServeStaticWithURLHelper(TestServeStatic, TestDefaults):
  242. """
  243. Test static asset serving view with staticfiles_urlpatterns helper.
  244. """
  245. urls = "regressiontests.staticfiles_tests.urls.helper"
  246. class TestServeAdminMedia(TestServeStatic):
  247. """
  248. Test serving media from django.contrib.admin.
  249. """
  250. def _response(self, filepath):
  251. return self.client.get(
  252. posixpath.join(settings.ADMIN_MEDIA_PREFIX, filepath))
  253. def test_serve_admin_media(self):
  254. self.assertFileContains('css/base.css', 'body')
  255. class FinderTestCase(object):
  256. """
  257. Base finder test mixin
  258. """
  259. def test_find_first(self):
  260. src, dst = self.find_first
  261. self.assertEquals(self.finder.find(src), dst)
  262. def test_find_all(self):
  263. src, dst = self.find_all
  264. self.assertEquals(self.finder.find(src, all=True), dst)
  265. class TestFileSystemFinder(StaticFilesTestCase, FinderTestCase):
  266. """
  267. Test FileSystemFinder.
  268. """
  269. def setUp(self):
  270. super(TestFileSystemFinder, self).setUp()
  271. self.finder = finders.FileSystemFinder()
  272. test_file_path = os.path.join(TEST_ROOT, 'project/documents/test/file.txt')
  273. self.find_first = ("test/file.txt", test_file_path)
  274. self.find_all = ("test/file.txt", [test_file_path])
  275. class TestAppDirectoriesFinder(StaticFilesTestCase, FinderTestCase):
  276. """
  277. Test AppDirectoriesFinder.
  278. """
  279. def setUp(self):
  280. super(TestAppDirectoriesFinder, self).setUp()
  281. self.finder = finders.AppDirectoriesFinder()
  282. test_file_path = os.path.join(TEST_ROOT, 'apps/test/static/test/file1.txt')
  283. self.find_first = ("test/file1.txt", test_file_path)
  284. self.find_all = ("test/file1.txt", [test_file_path])
  285. class TestDefaultStorageFinder(StaticFilesTestCase, FinderTestCase):
  286. """
  287. Test DefaultStorageFinder.
  288. """
  289. def setUp(self):
  290. super(TestDefaultStorageFinder, self).setUp()
  291. self.finder = finders.DefaultStorageFinder(
  292. storage=storage.StaticFilesStorage(location=settings.MEDIA_ROOT))
  293. test_file_path = os.path.join(settings.MEDIA_ROOT, 'media-file.txt')
  294. self.find_first = ("media-file.txt", test_file_path)
  295. self.find_all = ("media-file.txt", [test_file_path])
  296. class TestMiscFinder(TestCase):
  297. """
  298. A few misc finder tests.
  299. """
  300. def test_get_finder(self):
  301. self.assertTrue(isinstance(finders.get_finder(
  302. "django.contrib.staticfiles.finders.FileSystemFinder"),
  303. finders.FileSystemFinder))
  304. self.assertRaises(ImproperlyConfigured,
  305. finders.get_finder, "django.contrib.staticfiles.finders.FooBarFinder")
  306. self.assertRaises(ImproperlyConfigured,
  307. finders.get_finder, "foo.bar.FooBarFinder")