diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/base.py | 63 | ||||
| -rw-r--r-- | tests/conftest.py | 1 | ||||
| -rw-r--r-- | tests/data/translated_titles/conf.py | 12 | ||||
| -rw-r--r-- | tests/data/translated_titles/pages/1.pl.txt (renamed from tests/data/translated_titles/stories/1.pl.txt) | 0 | ||||
| -rw-r--r-- | tests/data/translated_titles/pages/1.txt (renamed from tests/data/translated_titles/stories/1.txt) | 0 | ||||
| -rw-r--r-- | tests/test_command_import_wordpress.py | 31 | ||||
| -rw-r--r-- | tests/test_compile_markdown.py | 44 | ||||
| -rw-r--r-- | tests/test_integration.py | 85 | ||||
| -rw-r--r-- | tests/test_locale.py | 2 | ||||
| -rw-r--r-- | tests/test_rss_feeds.py | 16 | ||||
| -rw-r--r-- | tests/test_rst_compiler.py | 72 | ||||
| -rw-r--r-- | tests/test_shortcodes.py | 76 | ||||
| -rw-r--r-- | tests/test_slugify.py | 16 | ||||
| -rw-r--r-- | tests/test_template_shortcodes.py | 86 | ||||
| -rw-r--r-- | tests/test_utils.py | 18 |
15 files changed, 258 insertions, 264 deletions
diff --git a/tests/base.py b/tests/base.py index 14af18a..2322c15 100644 --- a/tests/base.py +++ b/tests/base.py @@ -20,6 +20,7 @@ import unittest import logbook import nikola.utils +import nikola.shortcodes nikola.utils.LOGGER.handlers.append(logbook.TestHandler()) from yapsy.PluginManager import PluginManager @@ -35,51 +36,7 @@ from nikola.plugin_categories import ( RestExtension ) - -if sys.version_info < (2, 7): - - try: - import unittest2 - _unittest2 = True - except ImportError: - _unittest2 = False - - if _unittest2: - BaseTestCase = unittest2.TestCase - - else: - - class BaseTestCase(unittest.TestCase): - """ Base class for providing 2.6 compatibility """ - - def assertIs(self, first, second, msg=None): - self.assertTrue(first is second) - - def assertIsNot(self, first, second, msg=None): - self.assertTrue(first is not second) - - def assertIsNone(self, expr, msg=None): - self.assertTrue(expr is None) - - def assertIsNotNone(self, expr, msg=None): - self.assertTrue(expr is not None) - - def assertIn(self, first, second, msg=None): - self.assertTrue(first in second) - - def assertNotIn(self, first, second, msg=None): - self.assertTrue(first not in second) - - def assertIsInstance(self, obj, cls, msg=None): - self.assertTrue(isinstance(obj, cls)) - - def assertNotIsInstance(self, obj, cls, msg=None): - self.assertFalse(isinstance(obj, cls)) - - -else: - BaseTestCase = unittest.TestCase - +BaseTestCase = unittest.TestCase @contextmanager def cd(path): @@ -183,6 +140,8 @@ class FakePost(object): self._title = title self._slug = slug self._meta = {'slug': slug} + self.default_lang = 'en' + self._depfile = {} def title(self): return self._title @@ -219,6 +178,7 @@ class FakeSite(object): "RestExtension": RestExtension }) self.loghandlers = nikola.utils.STDERR_HANDLER # TODO remove on v8 + self.shortcode_registry = {} self.plugin_manager.setPluginInfoExtension('plugin') if sys.version_info[0] == 3: places = [ @@ -238,6 +198,7 @@ class FakeSite(object): ] self.debug = True self.rst_transforms = [] + self.post_per_input_file = {} # This is to make plugin initialization happy self.template_system = self self.name = 'mako' @@ -257,3 +218,15 @@ class FakeSite(object): def render_template(self, name, _, context): return('<img src="IMG.jpg">') + + # this code duplicated in nikola/nikola.py + def register_shortcode(self, name, f): + """Register function f to handle shortcode "name".""" + if name in self.shortcode_registry: + nikola.utils.LOGGER.warn('Shortcode name conflict: %s', name) + return + self.shortcode_registry[name] = f + + def apply_shortcodes(self, data, *a, **kw): + """Apply shortcodes from the registry on data.""" + return nikola.shortcodes.apply_shortcodes(data, self.shortcode_registry, **kw) diff --git a/tests/conftest.py b/tests/conftest.py index fbb09c8..68309d5 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,7 @@ import os import pytest + @pytest.yield_fixture(autouse=True) def ensure_chdir(): x = os.getcwd() diff --git a/tests/data/translated_titles/conf.py b/tests/data/translated_titles/conf.py index 3d0d829..8faa7a9 100644 --- a/tests/data/translated_titles/conf.py +++ b/tests/data/translated_titles/conf.py @@ -141,8 +141,8 @@ POSTS = ( ("posts/*.txt", "posts", "post.tmpl"), ) PAGES = ( - ("stories/*.rst", "stories", "story.tmpl"), - ("stories/*.txt", "stories", "story.tmpl"), + ("pages/*.rst", "pages", "story.tmpl"), + ("pages/*.txt", "pages", "story.tmpl"), ) # One or more folders containing files to be copied as-is into the output. @@ -436,10 +436,10 @@ COMMENT_SYSTEM_ID = "nikolademo" # the "noannotations" metadata. # ANNOTATIONS = False -# Create index.html for story folders? -# STORY_INDEX = False -# Enable comments on story pages? -# COMMENTS_IN_STORIES = False +# Create index.html for page folders? +# PAGE_INDEX = False +# Enable comments on page pages? +# COMMENTS_IN_PAGES = False # Enable comments on picture gallery pages? # COMMENTS_IN_GALLERIES = False diff --git a/tests/data/translated_titles/stories/1.pl.txt b/tests/data/translated_titles/pages/1.pl.txt index a888c1f..a888c1f 100644 --- a/tests/data/translated_titles/stories/1.pl.txt +++ b/tests/data/translated_titles/pages/1.pl.txt diff --git a/tests/data/translated_titles/stories/1.txt b/tests/data/translated_titles/pages/1.txt index 45fb214..45fb214 100644 --- a/tests/data/translated_titles/stories/1.txt +++ b/tests/data/translated_titles/pages/1.txt diff --git a/tests/test_command_import_wordpress.py b/tests/test_command_import_wordpress.py index c1c7836..c05188f 100644 --- a/tests/test_command_import_wordpress.py +++ b/tests/test_command_import_wordpress.py @@ -15,6 +15,7 @@ class BasicCommandImportWordpress(BaseTestCase): def setUp(self): self.module = nikola.plugins.command.import_wordpress self.import_command = self.module.CommandImportWordpress() + self.import_command.onefile = False self.import_filename = os.path.abspath(os.path.join( os.path.dirname(__file__), 'wordpress_export_example.xml')) @@ -170,6 +171,8 @@ class CommandImportWordpressTest(BasicCommandImportWordpress): def test_populate_context(self): channel = self.import_command.get_channel_from_file( self.import_filename) + self.import_command.html2text = False + self.import_command.transform_to_markdown = False self.import_command.transform_to_html = False self.import_command.use_wordpress_compiler = False context = self.import_command.populate_context(channel) @@ -194,8 +197,11 @@ class CommandImportWordpressTest(BasicCommandImportWordpress): self.import_command.no_downloads = False self.import_command.export_categories_as_categories = False self.import_command.export_comments = False + self.import_command.html2text = False + self.import_command.transform_to_markdown = False self.import_command.transform_to_html = False self.import_command.use_wordpress_compiler = False + self.import_command.tag_saniziting_strategy = 'first' self.import_command.context = self.import_command.populate_context( channel) @@ -205,6 +211,7 @@ class CommandImportWordpressTest(BasicCommandImportWordpress): write_metadata = mock.MagicMock() write_content = mock.MagicMock() + write_post = mock.MagicMock() write_attachments_info = mock.MagicMock() download_mock = mock.MagicMock() @@ -223,7 +230,7 @@ class CommandImportWordpressTest(BasicCommandImportWordpress): self.assertTrue(write_metadata.called) write_metadata.assert_any_call( - 'new_site/stories/kontakt.meta'.replace('/', os.sep), 'Kontakt', + 'new_site/pages/kontakt.meta'.replace('/', os.sep), 'Kontakt', 'kontakt', '2009-07-16 20:20:32', '', [], **{'wp-status': 'publish'}) self.assertTrue(write_content.called) @@ -237,51 +244,39 @@ Some source code. ```Python import sys - print sys.version ``` The end. - """, True) self.assertTrue(write_attachments_info.called) write_attachments_info.assert_any_call('new_site/posts/2008/07/arzt-und-pfusch-s-i-c-k.attachments.json'.replace('/', os.sep), {10: {'wordpress_user_name': 'Niko', 'files_meta': [{'width': 300, 'height': 299}, - {'width': b'150', 'size': 'thumbnail', 'height': b'150'}], + {'width': 150, 'size': 'thumbnail', 'height': 150}], 'excerpt': 'Arzt+Pfusch - S.I.C.K.', 'date_utc': '2009-07-16 19:40:37', 'content': 'Das Cover von Arzt+Pfusch - S.I.C.K.', 'files': ['/wp-content/uploads/2008/07/arzt_und_pfusch-sick-cover.png', '/wp-content/uploads/2008/07/arzt_und_pfusch-sick-cover-150x150.png'], - 'title': 'Arzt+Pfusch - S.I.C.K.'}}) + 'title': 'Arzt+Pfusch - S.I.C.K.'}}) write_content.assert_any_call( 'new_site/posts/2008/07/arzt-und-pfusch-s-i-c-k.md'.replace('/', os.sep), '''<img class="size-full wp-image-10 alignright" title="Arzt+Pfusch - S.I.C.K." src="http://some.blog/wp-content/uploads/2008/07/arzt_und_pfusch-sick-cover.png" alt="Arzt+Pfusch - S.I.C.K." width="210" height="209" />Arzt+Pfusch - S.I.C.K.Gerade bin ich \xfcber das Album <em>S.I.C.K</em> von <a title="Arzt+Pfusch" href="http://www.arztpfusch.com/" target="_blank">Arzt+Pfusch</a> gestolpert, welches Arzt+Pfusch zum Download f\xfcr lau anbieten. Das Album steht unter einer Creative Commons <a href="http://creativecommons.org/licenses/by-nc-nd/3.0/de/">BY-NC-ND</a>-Lizenz. - Die Ladung <em>noisebmstupidevildustrial</em> gibts als MP3s mit <a href="http://www.archive.org/download/dmp005/dmp005_64kb_mp3.zip">64kbps</a> und <a href="http://www.archive.org/download/dmp005/dmp005_vbr_mp3.zip">VBR</a>, als Ogg Vorbis und als FLAC (letztere <a href="http://www.archive.org/details/dmp005">hier</a>). <a href="http://www.archive.org/download/dmp005/dmp005-artwork.zip">Artwork</a> und <a href="http://www.archive.org/download/dmp005/dmp005-lyrics.txt">Lyrics</a> gibts nochmal einzeln zum Download.''', True) write_content.assert_any_call( - 'new_site/stories/kontakt.md'.replace('/', os.sep), """<h1>Datenschutz</h1> - + 'new_site/pages/kontakt.md'.replace('/', os.sep), """<h1>Datenschutz</h1> Ich erhebe und speichere automatisch in meine Server Log Files Informationen, die dein Browser an mich \xfcbermittelt. Dies sind: - <ul> - <li>Browsertyp und -version</li> - <li>verwendetes Betriebssystem</li> - <li>Referrer URL (die zuvor besuchte Seite)</li> - <li>IP Adresse des zugreifenden Rechners</li> - <li>Uhrzeit der Serveranfrage.</li> - </ul> - Diese Daten sind f\xfcr mich nicht bestimmten Personen zuordenbar. Eine Zusammenf\xfchrung dieser Daten mit anderen Datenquellen wird nicht vorgenommen, die Daten werden einzig zu statistischen Zwecken erhoben.""", True) self.assertTrue(len(self.import_command.url_map) > 0) @@ -295,7 +290,7 @@ Diese Daten sind f\xfcr mich nicht bestimmten Personen zuordenbar. Eine Zusammen 'http://some.blog/posts/2008/07/arzt-und-pfusch-s-i-c-k.html') self.assertEqual( self.import_command.url_map['http://some.blog/kontakt/'], - 'http://some.blog/stories/kontakt.html') + 'http://some.blog/pages/kontakt.html') image_thumbnails = [ 'http://some.blog/wp-content/uploads/2012/12/2012-12-19-1355925145_1024x600_scrot-64x64.png', @@ -324,6 +319,8 @@ Diese Daten sind f\xfcr mich nicht bestimmten Personen zuordenbar. Eine Zusammen transform_caption = mock.MagicMock() transform_newlines = mock.MagicMock() + self.import_command.html2text = False + self.import_command.transform_to_markdown = False self.import_command.transform_to_html = False self.import_command.use_wordpress_compiler = False diff --git a/tests/test_compile_markdown.py b/tests/test_compile_markdown.py index 47cbdbb..99f44fd 100644 --- a/tests/test_compile_markdown.py +++ b/tests/test_compile_markdown.py @@ -52,7 +52,7 @@ class CompileMarkdownTests(BaseTestCase): expected_output = '''\ <table class="codehilitetable"><tr><td class="linenos">\ <div class="linenodiv"><pre>1</pre></div>\ -</td><td class="code"><pre class="code literal-block">\ +</td><td class="code"><pre class="code literal-block"><span></span>\ <span class="kn">from</span> <span class="nn">this</span> </pre> </td></tr></table> @@ -61,48 +61,12 @@ class CompileMarkdownTests(BaseTestCase): actual_output = self.compile(input_str) self.assertEquals(actual_output.strip(), expected_output.strip()) - def test_compile_html_gist(self): - input_str = '''\ -Here's a gist file inline: -[:gist: 4747847 zen.py] + def test_compile_strikethrough(self): + input_str = '~~striked out text~~' + expected_output = '<p><del>striked out text</del></p>' -Cool, eh? -''' - expected_output = '''\ -<p>Here's a gist file inline: -<div class="gist"> -<script src="https://gist.github.com/4747847.js?file=zen.py"></script> -<noscript> -<pre>import this</pre> -</noscript> -</div> -</p> -<p>Cool, eh?</p> -''' actual_output = self.compile(input_str) self.assertEquals(actual_output.strip(), expected_output.strip()) - def test_compile_html_gist_2(self): - input_str = '''\ -Here's a gist file inline, using reStructuredText syntax: -..gist:: 4747847 zen.py - -Cool, eh? -''' - expected_output = '''\ -<p>Here's a gist file inline, using reStructuredText syntax: -<div class="gist"> -<script src="https://gist.github.com/4747847.js?file=zen.py"></script> -<noscript> -<pre>import this</pre> -</noscript> -</div> -</p> -<p>Cool, eh?</p> -''' - actual_output = self.compile(input_str) - self.assertEquals(actual_output.strip(), expected_output.strip()) - - if __name__ == '__main__': unittest.main() diff --git a/tests/test_integration.py b/tests/test_integration.py index 4bfd1d2..87a3eba 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -203,8 +203,8 @@ class TranslatedBuildTest(EmptyBuildTest): def test_translated_titles(self): """Check that translated title is picked up.""" - en_file = os.path.join(self.target_dir, "output", "stories", "1.html") - pl_file = os.path.join(self.target_dir, "output", self.ol, "stories", "1.html") + en_file = os.path.join(self.target_dir, "output", "pages", "1.html") + pl_file = os.path.join(self.target_dir, "output", self.ol, "pages", "1.html") # Files should be created self.assertTrue(os.path.isfile(en_file)) self.assertTrue(os.path.isfile(pl_file)) @@ -223,8 +223,8 @@ class TranslationsPatternTest1(TranslatedBuildTest): @classmethod def patch_site(self): """Set the TRANSLATIONS_PATTERN to the old v6 default""" - os.rename(os.path.join(self.target_dir, "stories", "1.%s.txt" % self.ol), - os.path.join(self.target_dir, "stories", "1.txt.%s" % self.ol) + os.rename(os.path.join(self.target_dir, "pages", "1.%s.txt" % self.ol), + os.path.join(self.target_dir, "pages", "1.txt.%s" % self.ol) ) conf_path = os.path.join(self.target_dir, "conf.py") with io.open(conf_path, "r", encoding="utf-8") as inf: @@ -241,7 +241,7 @@ class MissingDefaultLanguageTest(TranslatedBuildTest): @classmethod def fill_site(self): super(MissingDefaultLanguageTest, self).fill_site() - os.unlink(os.path.join(self.target_dir, "stories", "1.txt")) + os.unlink(os.path.join(self.target_dir, "pages", "1.txt")) def test_translated_titles(self): """Do not test titles as we just removed the translation""" @@ -255,8 +255,8 @@ class TranslationsPatternTest2(TranslatedBuildTest): def patch_site(self): """Set the TRANSLATIONS_PATTERN to the old v6 default""" conf_path = os.path.join(self.target_dir, "conf.py") - os.rename(os.path.join(self.target_dir, "stories", "1.%s.txt" % self.ol), - os.path.join(self.target_dir, "stories", "1.txt.%s" % self.ol) + os.rename(os.path.join(self.target_dir, "pages", "1.%s.txt" % self.ol), + os.path.join(self.target_dir, "pages", "1.txt.%s" % self.ol) ) with io.open(conf_path, "r", encoding="utf-8") as inf: data = inf.read() @@ -307,17 +307,11 @@ class TestCheck(DemoBuildTest): def test_check_links(self): with cd(self.target_dir): - try: - __main__.main(['check', '-l']) - except SystemExit as e: - self.assertEqual(e.code, 0) + self.assertIsNone(__main__.main(['check', '-l'])) def test_check_files(self): with cd(self.target_dir): - try: - __main__.main(['check', '-f']) - except SystemExit as e: - self.assertEqual(e.code, 0) + self.assertIsNone(__main__.main(['check', '-f'])) class TestCheckAbsoluteSubFolder(TestCheck): @@ -390,7 +384,7 @@ class TestCheckFailure(DemoBuildTest): class RelativeLinkTest2(DemoBuildTest): - """Check that dropping stories to the root doesn't break links.""" + """Check that dropping pages to the root doesn't break links.""" @classmethod def patch_site(self): @@ -398,10 +392,10 @@ class RelativeLinkTest2(DemoBuildTest): conf_path = os.path.join(self.target_dir, "conf.py") with io.open(conf_path, "r", encoding="utf-8") as inf: data = inf.read() - data = data.replace('("stories/*.txt", "stories", "story.tmpl"),', - '("stories/*.txt", "", "story.tmpl"),') - data = data.replace('("stories/*.rst", "stories", "story.tmpl"),', - '("stories/*.rst", "", "story.tmpl"),') + data = data.replace('("pages/*.txt", "pages", "story.tmpl"),', + '("pages/*.txt", "", "story.tmpl"),') + data = data.replace('("pages/*.rst", "pages", "story.tmpl"),', + '("pages/*.rst", "", "story.tmpl"),') data = data.replace('# INDEX_PATH = ""', 'INDEX_PATH = "blog"') with io.open(conf_path, "w+", encoding="utf8") as outf: @@ -409,7 +403,7 @@ class RelativeLinkTest2(DemoBuildTest): outf.flush() def test_relative_links(self): - """Check that the links in a story are correct""" + """Check that the links in a page are correct""" test_path = os.path.join(self.target_dir, "output", "about-nikola.html") flag = False with open(test_path, "rb") as inf: @@ -504,53 +498,6 @@ class SubdirRunningTest(DemoBuildTest): self.assertEquals(result, 0) -class InvariantBuildTest(EmptyBuildTest): - """Test that a default build of --demo works.""" - - @classmethod - def build(self): - """Build the site.""" - try: - self.oldlocale = locale.getlocale() - locale.setlocale(locale.LC_ALL, ("en_US", "utf8")) - except: - pytest.skip('no en_US locale!') - else: - with cd(self.target_dir): - __main__.main(["build", "--invariant"]) - finally: - try: - locale.setlocale(locale.LC_ALL, self.oldlocale) - except: - pass - - @classmethod - def fill_site(self): - """Fill the site with demo content.""" - self.init_command.copy_sample_site(self.target_dir) - self.init_command.create_configuration(self.target_dir) - src1 = os.path.join(os.path.dirname(__file__), 'data', '1-nolinks.rst') - dst1 = os.path.join(self.target_dir, 'posts', '1.rst') - shutil.copy(src1, dst1) - os.system('rm "{0}/stories/creating-a-theme.rst" "{0}/stories/extending.txt" "{0}/stories/internals.txt" "{0}/stories/manual.rst" "{0}/stories/social_buttons.txt" "{0}/stories/theming.rst" "{0}/stories/upgrading-to-v6.txt"'.format(self.target_dir)) - - def test_invariance(self): - """Compare the output to the canonical output.""" - if sys.version_info[0:2] != (2, 7): - pytest.skip('only python 2.7 is supported right now') - good_path = os.path.join(os.path.dirname(__file__), 'data', 'baseline{0[0]}.{0[1]}'.format(sys.version_info)) - if not os.path.exists(good_path): - pytest.skip('no baseline found') - with cd(self.target_dir): - try: - diff = subprocess.check_output(['diff', '-ubwr', good_path, 'output']) - self.assertEqual(diff.strip(), '') - except subprocess.CalledProcessError as exc: - print('Unexplained diff for the invariance test. (-canonical +built)') - print(exc.output.decode('utf-8')) - self.assertEqual(exc.returncode, 0, 'Unexplained diff for the invariance test.') - - class RedirectionsTest1(TestCheck): """Check REDIRECTIONS""" @@ -568,6 +515,7 @@ class RedirectionsTest1(TestCheck): with io.open(target_path, "w+", encoding="utf8") as outf: outf.write("foo") + class RedirectionsTest2(TestCheck): """Check external REDIRECTIONS""" @@ -578,6 +526,7 @@ class RedirectionsTest2(TestCheck): with io.open(conf_path, "a", encoding="utf8") as outf: outf.write("""\n\nREDIRECTIONS = [ ("foo.html", "http://www.example.com/"), ]\n\n""") + class RedirectionsTest3(TestCheck): """Check relative REDIRECTIONS""" diff --git a/tests/test_locale.py b/tests/test_locale.py index d24fdfb..8ffa112 100644 --- a/tests/test_locale.py +++ b/tests/test_locale.py @@ -214,8 +214,8 @@ class TestLocaleBorg(unittest.TestCase): def test_services_reject_dumb_wrong_call(self): lang_11, loc_11 = LocaleSupportInTesting.langlocales['default'] nikola.utils.LocaleBorg.reset() + self.assertRaises(Exception, nikola.utils.LocaleBorg) self.assertRaises(Exception, nikola.utils.LocaleBorg.set_locale, lang_11) - self.assertRaises(Exception, getattr, nikola.utils.LocaleBorg, 'current_lang') def test_set_locale_raises_on_invalid_lang(self): lang_11, loc_11 = LocaleSupportInTesting.langlocales['default'] diff --git a/tests/test_rss_feeds.py b/tests/test_rss_feeds.py index f67ed40..d44cd7b 100644 --- a/tests/test_rss_feeds.py +++ b/tests/test_rss_feeds.py @@ -50,13 +50,15 @@ class RSSFeedTest(unittest.TestCase): with mock.patch('nikola.post.get_meta', mock.Mock(return_value=( ({'title': 'post title', - 'slug': 'awesome_article', - 'date': '2012-10-01 22:41', - 'author': None, - 'tags': 'tags', - 'link': 'link', - 'description': 'description', - 'enclosure': 'http://www.example.org/foo.mp3'}, True) + 'slug': 'awesome_article', + 'date': '2012-10-01 22:41', + 'author': None, + 'tags': 'tags', + 'link': 'link', + 'description': 'description', + 'enclosure': 'http://www.example.org/foo.mp3', + 'enclosure_length': '5'}, + True) ))): with mock.patch('nikola.nikola.utils.os.path.isdir', mock.Mock(return_value=True)): diff --git a/tests/test_rst_compiler.py b/tests/test_rst_compiler.py index 5bbd617..5b33db7 100644 --- a/tests/test_rst_compiler.py +++ b/tests/test_rst_compiler.py @@ -4,7 +4,7 @@ """ Test cases for Nikola ReST extensions. -A base class ReSTExtensionTestCase provides the tests basic behaivor. +A base class ReSTExtensionTestCase provides the tests basic behaviour. Subclasses must override the "sample" class attribute with the ReST markup. The sample will be rendered as HTML using publish_parts() by setUp(). One method is provided for checking the resulting HTML: @@ -44,12 +44,11 @@ import pytest import unittest import nikola.plugins.compile.rest -from nikola.plugins.compile.rest import gist from nikola.plugins.compile.rest import vimeo import nikola.plugins.compile.rest.listing from nikola.plugins.compile.rest.doc import Plugin as DocPlugin from nikola.utils import _reload -from .base import BaseTestCase, FakeSite +from .base import BaseTestCase, FakeSite, FakePost class ReSTExtensionTestCase(BaseTestCase): @@ -72,20 +71,20 @@ class ReSTExtensionTestCase(BaseTestCase): tmpdir = tempfile.mkdtemp() inf = os.path.join(tmpdir, 'inf') outf = os.path.join(tmpdir, 'outf') - depf = os.path.join(tmpdir, 'outf.dep') with io.open(inf, 'w+', encoding='utf8') as f: f.write(rst) + p = FakePost('', '') + p._depfile[outf] = [] + self.compiler.site.post_per_input_file[inf] = p self.html = self.compiler.compile_html(inf, outf) with io.open(outf, 'r', encoding='utf8') as f: self.html = f.read() os.unlink(inf) os.unlink(outf) - if os.path.isfile(depf): - with io.open(depf, 'r', encoding='utf8') as f: - self.assertEqual(self.deps, f.read()) - os.unlink(depf) - else: - self.assertEqual(self.deps, None) + depfile = [p for p in p._depfile[outf] if p != outf] + depfile = '\n'.join(depfile) + if depfile: + self.assertEqual(self.deps.strip(), depfile) os.rmdir(tmpdir) self.html_doc = html.parse(StringIO(self.html)) @@ -129,55 +128,6 @@ class MathTestCase(ReSTExtensionTestCase): text="\(e^{ix} = \cos x + i\sin x\)") -class GistTestCase(ReSTExtensionTestCase): - """ Test GitHubGist. - We will replace get_raw_gist() and get_raw_gist_with_filename() - monkeypatching the GitHubGist class for avoiding network dependency - - """ - gist_type = gist.GitHubGist - sample = '.. gist:: fake_id\n :file: spam.py' - sample_without_filename = '.. gist:: fake_id2' - - def setUp(self): - """ Patch GitHubGist for avoiding network dependency """ - super(GistTestCase, self).setUp() - self.gist_type.get_raw_gist_with_filename = lambda *_: 'raw_gist_file' - self.gist_type.get_raw_gist = lambda *_: "raw_gist" - _reload(nikola.plugins.compile.rest) - - @pytest.mark.skipif(True, reason="This test indefinitely skipped.") - def test_gist(self): - """ Test the gist directive with filename """ - self.setHtmlFromRst(self.sample) - output = 'https://gist.github.com/fake_id.js?file=spam.py' - self.assertHTMLContains("script", attributes={"src": output}) - self.assertHTMLContains("pre", text="raw_gist_file") - - @pytest.mark.skipif(True, reason="This test indefinitely skipped.") - def test_gist_without_filename(self): - """ Test the gist directive without filename """ - self.setHtmlFromRst(self.sample_without_filename) - output = 'https://gist.github.com/fake_id2.js' - self.assertHTMLContains("script", attributes={"src": output}) - self.assertHTMLContains("pre", text="raw_gist") - - -class GistIntegrationTestCase(ReSTExtensionTestCase): - """ Test requests integration. The gist plugin uses requests to fetch gist - contents and place it in a noscript tag. - - """ - sample = '.. gist:: 1812835' - - def test_gist_integration(self): - """ Fetch contents of the gist from GH and render in a noscript tag """ - self.basic_test() - text = ('Be alone, that is the secret of invention: be alone, that is' - ' when ideas are born. -- Nikola Tesla') - self.assertHTMLContains('pre', text=text) - - class SlidesTestCase(ReSTExtensionTestCase): """ Slides test case """ @@ -223,7 +173,7 @@ class VimeoTestCase(ReSTExtensionTestCase): """ Test Vimeo iframe tag generation """ self.basic_test() self.assertHTMLContains("iframe", - attributes={"src": ("//player.vimeo.com/" + attributes={"src": ("https://player.vimeo.com/" "video/VID"), "height": "400", "width": "600"}) @@ -237,7 +187,7 @@ class YoutubeTestCase(ReSTExtensionTestCase): """ Test Youtube iframe tag generation """ self.basic_test() self.assertHTMLContains("iframe", - attributes={"src": ("//www.youtube.com/" + attributes={"src": ("https://www.youtube.com/" "embed/YID?rel=0&hd=1&" "wmode=transparent"), "height": "400", "width": "600"}) diff --git a/tests/test_shortcodes.py b/tests/test_shortcodes.py new file mode 100644 index 0000000..22f603e --- /dev/null +++ b/tests/test_shortcodes.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +# vim: set wrap textwidth=300 + +u"""Test shortcodes.""" + +from __future__ import unicode_literals +import pytest +from nikola import shortcodes +from .base import FakeSite, BaseTestCase +import sys + +def noargs(site, data='', lang=''): + return "noargs {0} success!".format(data) + +def arg(*args, **kwargs): + # don’t clutter the kwargs dict + _ = kwargs.pop('site') + data = kwargs.pop('data') + lang = kwargs.pop('lang') + # TODO hack for Python 2.7 -- remove when possible + if sys.version_info[0] == 2: + args = tuple(i.encode('utf-8') for i in args) + kwargs = {k.encode('utf-8'): v.encode('utf-8') for k, v in kwargs.items()} + return "arg {0}/{1}/{2}".format(args, sorted(kwargs.items()), data) + + +@pytest.fixture(scope="module") +def fakesite(): + s = FakeSite() + s.register_shortcode('noargs', noargs) + s.register_shortcode('arg', arg) + return s + +def test_noargs(fakesite): + assert shortcodes.apply_shortcodes('test({{% noargs %}})', fakesite.shortcode_registry) == 'test(noargs success!)' + assert shortcodes.apply_shortcodes('test({{% noargs %}}\\hello world/{{% /noargs %}})', fakesite.shortcode_registry) == 'test(noargs \\hello world/ success!)' + +def test_arg_pos(fakesite): + assert shortcodes.apply_shortcodes('test({{% arg 1 %}})', fakesite.shortcode_registry) == "test(arg ('1',)/[]/)" + assert shortcodes.apply_shortcodes('test({{% arg 1 2aa %}})', fakesite.shortcode_registry) == "test(arg ('1', '2aa')/[]/)" + assert shortcodes.apply_shortcodes('test({{% arg "hello world" %}})', fakesite.shortcode_registry) == "test(arg ('hello world',)/[]/)" + assert shortcodes.apply_shortcodes('test({{% arg back\ slash arg2 %}})', fakesite.shortcode_registry) == "test(arg ('back slash', 'arg2')/[]/)" + assert shortcodes.apply_shortcodes('test({{% arg "%}}" %}})', fakesite.shortcode_registry) == "test(arg ('%}}',)/[]/)" + +def test_arg_keyword(fakesite): + assert shortcodes.apply_shortcodes('test({{% arg 1a=2b %}})', fakesite.shortcode_registry) == "test(arg ()/[('1a', '2b')]/)" + assert shortcodes.apply_shortcodes('test({{% arg 1a="2b 3c" 4d=5f %}})', fakesite.shortcode_registry) == "test(arg ()/[('1a', '2b 3c'), ('4d', '5f')]/)" + assert shortcodes.apply_shortcodes('test({{% arg 1a="2b 3c" 4d=5f back=slash\ slash %}})', fakesite.shortcode_registry) == "test(arg ()/[('1a', '2b 3c'), ('4d', '5f'), ('back', 'slash slash')]/)" + +def test_data(fakesite): + assert shortcodes.apply_shortcodes('test({{% arg 123 %}}Hello!{{% /arg %}})', fakesite.shortcode_registry) == "test(arg ('123',)/[]/Hello!)" + assert shortcodes.apply_shortcodes('test({{% arg 123 456 foo=bar %}}Hello world!{{% /arg %}})', fakesite.shortcode_registry) == "test(arg ('123', '456')/[('foo', 'bar')]/Hello world!)" + assert shortcodes.apply_shortcodes('test({{% arg 123 456 foo=bar baz="quotes rock." %}}Hello test suite!{{% /arg %}})', fakesite.shortcode_registry) == "test(arg ('123', '456')/[('baz', 'quotes rock.'), ('foo', 'bar')]/Hello test suite!)" + assert shortcodes.apply_shortcodes('test({{% arg "123 foo" foobar foo=bar baz="quotes rock." %}}Hello test suite!!{{% /arg %}})', fakesite.shortcode_registry) == "test(arg ('123 foo', 'foobar')/[('baz', 'quotes rock.'), ('foo', 'bar')]/Hello test suite!!)" + + +class TestErrors(BaseTestCase): + def setUp(self): + self.fakesite = fakesite() + + def test_errors(self): + self.assertRaisesRegexp(shortcodes.ParsingError, "^Shortcode 'start' starting at .* is not terminated correctly with '%}}'!", shortcodes.apply_shortcodes, '{{% start', self.fakesite.shortcode_registry, raise_exceptions=True) + self.assertRaisesRegexp(shortcodes.ParsingError, "^Syntax error in shortcode 'wrong' at .*: expecting whitespace!", shortcodes.apply_shortcodes, '{{% wrong ending %%}', self.fakesite.shortcode_registry, raise_exceptions=True) + self.assertRaisesRegexp(shortcodes.ParsingError, "^Found shortcode ending '{{% /end %}}' which isn't closing a started shortcode", shortcodes.apply_shortcodes, '{{% start %}} {{% /end %}}', self.fakesite.shortcode_registry, raise_exceptions=True) + self.assertRaisesRegexp(shortcodes.ParsingError, "^Unexpected end of unquoted string", shortcodes.apply_shortcodes, '{{% start "asdf %}}', self.fakesite.shortcode_registry, raise_exceptions=True) + self.assertRaisesRegexp(shortcodes.ParsingError, "^String starting at .* must be non-empty!", shortcodes.apply_shortcodes, '{{% start =b %}}', self.fakesite.shortcode_registry, raise_exceptions=True) + self.assertRaisesRegexp(shortcodes.ParsingError, "^Unexpected end of data while escaping", shortcodes.apply_shortcodes, '{{% start "a\\', self.fakesite.shortcode_registry, raise_exceptions=True) + self.assertRaisesRegexp(shortcodes.ParsingError, "^Unexpected end of data while escaping", shortcodes.apply_shortcodes, '{{% start a\\', self.fakesite.shortcode_registry, raise_exceptions=True) + self.assertRaisesRegexp(shortcodes.ParsingError, "^Unexpected quotation mark in unquoted string", shortcodes.apply_shortcodes, '{{% start a"b" %}}', self.fakesite.shortcode_registry, raise_exceptions=True) + self.assertRaisesRegexp(shortcodes.ParsingError, "^Syntax error in shortcode 'start' at .*: expecting whitespace!", shortcodes.apply_shortcodes, '{{% start "a"b %}}', self.fakesite.shortcode_registry, raise_exceptions=True) + self.assertRaisesRegexp(shortcodes.ParsingError, "^Syntax error: '{{%' must be followed by shortcode name", shortcodes.apply_shortcodes, '{{% %}}', self.fakesite.shortcode_registry, raise_exceptions=True) + self.assertRaisesRegexp(shortcodes.ParsingError, "^Syntax error: '{{%' must be followed by shortcode name", shortcodes.apply_shortcodes, '{{%', self.fakesite.shortcode_registry, raise_exceptions=True) + self.assertRaisesRegexp(shortcodes.ParsingError, "^Syntax error: '{{%' must be followed by shortcode name", shortcodes.apply_shortcodes, '{{% ', self.fakesite.shortcode_registry, raise_exceptions=True) + self.assertRaisesRegexp(shortcodes.ParsingError, "^Found shortcode ending '{{% / %}}' which isn't closing a started shortcode", shortcodes.apply_shortcodes, '{{% / %}}', self.fakesite.shortcode_registry, raise_exceptions=True) + self.assertRaisesRegexp(shortcodes.ParsingError, "^Syntax error: '{{% /' must be followed by ' %}}'", shortcodes.apply_shortcodes, '{{% / a %}}', self.fakesite.shortcode_registry, raise_exceptions=True) + self.assertRaisesRegexp(shortcodes.ParsingError, "^Shortcode '<==' starting at .* is not terminated correctly with '%}}'!", shortcodes.apply_shortcodes, '==> {{% <==', self.fakesite.shortcode_registry, raise_exceptions=True) diff --git a/tests/test_slugify.py b/tests/test_slugify.py index 9dec5a6..c910aaa 100644 --- a/tests/test_slugify.py +++ b/tests/test_slugify.py @@ -8,41 +8,41 @@ import nikola.utils def test_ascii(): """Test an ASCII-only string.""" - o = nikola.utils.slugify(u'hello') + o = nikola.utils.slugify(u'hello', lang='en') assert o == u'hello' assert isinstance(o, nikola.utils.unicode_str) def test_ascii_dash(): """Test an ASCII string, with dashes.""" - o = nikola.utils.slugify(u'hello-world') + o = nikola.utils.slugify(u'hello-world', lang='en') assert o == u'hello-world' assert isinstance(o, nikola.utils.unicode_str) def test_ascii_fancy(): """Test an ASCII string, with fancy characters.""" - o = nikola.utils.slugify(u'The quick brown fox jumps over the lazy dog!-123.456') + o = nikola.utils.slugify(u'The quick brown fox jumps over the lazy dog!-123.456', lang='en') assert o == u'the-quick-brown-fox-jumps-over-the-lazy-dog-123456' assert isinstance(o, nikola.utils.unicode_str) def test_pl(): """Test a string with Polish diacritical characters.""" - o = nikola.utils.slugify(u'zażółćgęśląjaźń') + o = nikola.utils.slugify(u'zażółćgęśląjaźń', lang='pl') assert o == u'zazolcgeslajazn' assert isinstance(o, nikola.utils.unicode_str) def test_pl_dash(): """Test a string with Polish diacritical characters and dashes.""" - o = nikola.utils.slugify(u'zażółć-gęślą-jaźń') + o = nikola.utils.slugify(u'zażółć-gęślą-jaźń', lang='pl') assert o == u'zazolc-gesla-jazn' def test_pl_fancy(): """Test a string with Polish diacritical characters and fancy characters.""" - o = nikola.utils.slugify(u'Zażółć gęślą jaźń!-123.456') + o = nikola.utils.slugify(u'Zażółć gęślą jaźń!-123.456', lang='pl') assert o == u'zazolc-gesla-jazn-123456' assert isinstance(o, nikola.utils.unicode_str) @@ -50,7 +50,7 @@ def test_pl_fancy(): def test_disarmed(): """Test disarmed slugify.""" nikola.utils.USE_SLUGIFY = False - o = nikola.utils.slugify(u'Zażółć gęślą jaźń!-123.456') + o = nikola.utils.slugify(u'Zażółć gęślą jaźń!-123.456', lang='pl') assert o == u'Zażółć gęślą jaźń!-123.456' assert isinstance(o, nikola.utils.unicode_str) nikola.utils.USE_SLUGIFY = True @@ -59,7 +59,7 @@ def test_disarmed(): def test_disarmed_weird(): """Test disarmed slugify with banned characters.""" nikola.utils.USE_SLUGIFY = False - o = nikola.utils.slugify(u'Zażółć gęślą jaźń!-123.456 "Hello World"?#H<e>l/l\\o:W\'o\rr*l\td|!\n') + o = nikola.utils.slugify(u'Zażółć gęślą jaźń!-123.456 "Hello World"?#H<e>l/l\\o:W\'o\rr*l\td|!\n', lang='pl') assert o == u'Zażółć gęślą jaźń!-123.456 -Hello World---H-e-l-l-o-W-o-r-l-d-!-' assert isinstance(o, nikola.utils.unicode_str) nikola.utils.USE_SLUGIFY = True diff --git a/tests/test_template_shortcodes.py b/tests/test_template_shortcodes.py new file mode 100644 index 0000000..a1d3a91 --- /dev/null +++ b/tests/test_template_shortcodes.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +# vim: set wrap textwidth=100 +"""Test template-based shortcodes.""" + +from __future__ import unicode_literals + +import pytest +from nikola import Nikola + + +class ShortcodeFakeSite(Nikola): + def _get_template_system(self): + if self._template_system is None: + # Load template plugin + self._template_system = self.plugin_manager.getPluginByName( + 'jinja', "TemplateSystem").plugin_object + self._template_system.set_directories('.', 'cache') + self._template_system.set_site(self) + + return self._template_system + + template_system = property(_get_template_system) + + +@pytest.fixture(scope="module") +def fakesite(): + s = ShortcodeFakeSite() + s.init_plugins() + s._template_system = None + return s + + +def test_mixedargs(fakesite): + TEST_TMPL = """ +arg1: {{ _args[0] }} +arg2: {{ _args[1] }} +kwarg1: {{ kwarg1 }} +kwarg2: {{ kwarg2 }} +""" + + fakesite.shortcode_registry['test1'] = \ + fakesite._make_renderfunc(TEST_TMPL) + fakesite.shortcode_registry['test2'] = \ + fakesite._make_renderfunc('Something completely different') + + res = fakesite.apply_shortcodes( + '{{% test1 kwarg1=spamm arg1 kwarg2=foo,bar arg2 %}}') + + assert res.strip() == """ +arg1: arg1 +arg2: arg2 +kwarg1: spamm +kwarg2: foo,bar""".strip() + + +def test_onearg(fakesite): + fakesite.shortcode_registry['test1'] = \ + fakesite._make_renderfunc('arg={{ _args[0] }}') + + assert fakesite.apply_shortcodes('{{% test1 onearg %}}') == 'arg=onearg' + assert fakesite.apply_shortcodes('{{% test1 "one two" %}}') == 'arg=one two' + + +def test_kwarg(fakesite): + fakesite.shortcode_registry['test1'] = \ + fakesite._make_renderfunc('foo={{ foo }}') + + res = fakesite.apply_shortcodes('{{% test1 foo=bar %}}') + assert res == 'foo=bar' + res = fakesite.apply_shortcodes('{{% test1 foo="bar baz" %}}') + assert res == 'foo=bar baz' + res = fakesite.apply_shortcodes('{{% test1 foo="bar baz" spamm=ham %}}') + assert res == 'foo=bar baz' + + +def test_data(fakesite): + fakesite.shortcode_registry['test1'] = \ + fakesite._make_renderfunc('data={{ data }}') + + res = fakesite.apply_shortcodes('{{% test1 %}}spamm spamm{{% /test1 %}}') + assert res == 'data=spamm spamm' + res = fakesite.apply_shortcodes('{{% test1 spamm %}}') + assert res == 'data=' + # surprise! + res = fakesite.apply_shortcodes('{{% test1 data=dummy %}}') + assert res == 'data=' diff --git a/tests/test_utils.py b/tests/test_utils.py index 9507de2..225ff13 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,10 +1,5 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals - -import os -import sys - - import unittest import mock import lxml.html @@ -13,7 +8,7 @@ from nikola.utils import demote_headers, TranslatableSetting class dummy(object): - pass + default_lang = 'en' class GetMetaTest(unittest.TestCase): @@ -323,13 +318,14 @@ def test_get_metadata_from_file(): from nikola.post import _get_metadata_from_file g = _get_metadata_from_file assert list(g([]).values()) == [] - assert str(g(["======","FooBar","======"])["title"]) == 'FooBar' - assert str(g(["FooBar","======"])["title"]) == 'FooBar' + assert str(g(["======", "FooBar", "======"])["title"]) == 'FooBar' + assert str(g(["FooBar", "======"])["title"]) == 'FooBar' assert str(g(["#FooBar"])["title"]) == 'FooBar' assert str(g([".. title: FooBar"])["title"]) == 'FooBar' - assert 'title' not in g(["","",".. title: FooBar"]) - assert 'title' in g(["",".. title: FooBar"]) - assert 'title' in g([".. foo: bar","","FooBar", "------"]) + assert 'title' not in g(["", "", ".. title: FooBar"]) + assert 'title' in g(["", ".. title: FooBar"]) + assert 'title' in g([".. foo: bar", "", "FooBar", "------"]) + if __name__ == '__main__': unittest.main() |
