test_assets.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. # -*- coding: utf-8 -*-
  2. # from __future__ import unicode_literals
  3. import hashlib
  4. import locale
  5. import os
  6. from codecs import open
  7. from tempfile import mkdtemp
  8. from shutil import rmtree
  9. import unittest
  10. import subprocess
  11. from pelican import Pelican
  12. from pelican.settings import read_settings
  13. CUR_DIR = os.path.dirname(__file__)
  14. THEME_DIR = os.path.join(CUR_DIR, 'test_data')
  15. CSS_REF = open(os.path.join(THEME_DIR, 'static', 'css',
  16. 'style.min.css')).read()
  17. CSS_HASH = hashlib.md5(CSS_REF).hexdigest()[0:8]
  18. def skipIfNoExecutable(executable):
  19. """Skip test if `executable` is not found
  20. Tries to run `executable` with subprocess to make sure it's in the path,
  21. and skips the tests if not found (if subprocess raises a `OSError`).
  22. """
  23. with open(os.devnull, 'w') as fnull:
  24. try:
  25. res = subprocess.call(executable, stdout=fnull, stderr=fnull)
  26. except OSError:
  27. res = None
  28. if res is None:
  29. return unittest.skip('{0} executable not found'.format(executable))
  30. return lambda func: func
  31. def module_exists(module_name):
  32. """Test if a module is importable."""
  33. try:
  34. __import__(module_name)
  35. except ImportError:
  36. return False
  37. else:
  38. return True
  39. @unittest.skipUnless(module_exists('webassets'), "webassets isn't installed")
  40. @skipIfNoExecutable(['scss', '-v'])
  41. @skipIfNoExecutable(['cssmin', '--version'])
  42. class TestWebAssets(unittest.TestCase):
  43. """Base class for testing webassets."""
  44. def setUp(self, override=None):
  45. import assets
  46. self.temp_path = mkdtemp(prefix='pelicantests.')
  47. settings = {
  48. 'PATH': os.path.join(os.path.dirname(CUR_DIR), 'test_data', 'content'),
  49. 'OUTPUT_PATH': self.temp_path,
  50. 'PLUGINS': [assets],
  51. 'THEME': THEME_DIR,
  52. 'LOCALE': locale.normalize('en_US'),
  53. }
  54. if override:
  55. settings.update(override)
  56. self.settings = read_settings(override=settings)
  57. pelican = Pelican(settings=self.settings)
  58. pelican.run()
  59. def tearDown(self):
  60. rmtree(self.temp_path)
  61. def check_link_tag(self, css_file, html_file):
  62. """Check the presence of `css_file` in `html_file`."""
  63. link_tag = ('<link rel="stylesheet" href="{css_file}">'
  64. .format(css_file=css_file))
  65. html = open(html_file).read()
  66. self.assertRegexpMatches(html, link_tag)
  67. class TestWebAssetsRelativeURLS(TestWebAssets):
  68. """Test pelican with relative urls."""
  69. def setUp(self):
  70. TestWebAssets.setUp(self, override={'RELATIVE_URLS': True})
  71. def test_jinja2_ext(self):
  72. # Test that the Jinja2 extension was correctly added.
  73. from webassets.ext.jinja2 import AssetsExtension
  74. self.assertIn(AssetsExtension, self.settings['JINJA_EXTENSIONS'])
  75. def test_compilation(self):
  76. # Compare the compiled css with the reference.
  77. gen_file = os.path.join(self.temp_path, 'theme', 'gen',
  78. 'style.{0}.min.css'.format(CSS_HASH))
  79. self.assertTrue(os.path.isfile(gen_file))
  80. css_new = open(gen_file).read()
  81. self.assertEqual(css_new, CSS_REF)
  82. def test_template(self):
  83. # Look in the output files for the link tag.
  84. css_file = './theme/gen/style.{0}.min.css'.format(CSS_HASH)
  85. html_files = ['index.html', 'archives.html',
  86. 'this-is-a-super-article.html']
  87. for f in html_files:
  88. self.check_link_tag(css_file, os.path.join(self.temp_path, f))
  89. self.check_link_tag(
  90. '../theme/gen/style.{0}.min.css'.format(CSS_HASH),
  91. os.path.join(self.temp_path, 'category/yeah.html'))
  92. class TestWebAssetsAbsoluteURLS(TestWebAssets):
  93. """Test pelican with absolute urls."""
  94. def setUp(self):
  95. TestWebAssets.setUp(self, override={'RELATIVE_URLS': False,
  96. 'SITEURL': 'http://localhost'})
  97. def test_absolute_url(self):
  98. # Look in the output files for the link tag with absolute url.
  99. css_file = ('http://localhost/theme/gen/style.{0}.min.css'
  100. .format(CSS_HASH))
  101. html_files = ['index.html', 'archives.html',
  102. 'this-is-a-super-article.html']
  103. for f in html_files:
  104. self.check_link_tag(css_file, os.path.join(self.temp_path, f))