aboutsummaryrefslogtreecommitdiffstats
path: root/tests/test_rst_extensions.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_rst_extensions.py')
-rw-r--r--tests/test_rst_extensions.py223
1 files changed, 223 insertions, 0 deletions
diff --git a/tests/test_rst_extensions.py b/tests/test_rst_extensions.py
new file mode 100644
index 0000000..845d6a7
--- /dev/null
+++ b/tests/test_rst_extensions.py
@@ -0,0 +1,223 @@
+# coding: utf8
+# Author: Rodrigo Bistolfi
+# Date: 03/2013
+
+
+""" Test cases for Nikola ReST extensions.
+A base class ReSTExtensionTestCase provides the tests basic behaivor.
+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:
+
+ * assertHTMLContains(element, attributes=None, text=None)
+
+The HTML is parsed with lxml for checking against the data you provide. The
+method takes an element argument, a string representing the *name* of an HTML
+tag, like "script" or "iframe". We will try to find this tag in the document
+and perform the tests on it. You can pass a dictionary to the attributes kwarg
+representing the name and the value of the tag attributes. The text kwarg takes
+a string argument, which will be tested against the contents of the HTML
+element.
+One last caveat: you need to url unquote your urls if you are going to test
+attributes like "src" or "link", since the HTML rendered by docutils will be
+always unquoted.
+
+"""
+
+
+from __future__ import unicode_literals
+
+try:
+ from io import StringIO
+except ImportError:
+ from StringIO import StringIO # NOQA
+
+from docutils.core import publish_parts
+from lxml import html
+import mock
+
+import unittest
+import nikola.plugins.compile_rest
+from nikola.utils import _reload
+from base import BaseTestCase
+
+
+class ReSTExtensionTestCase(BaseTestCase):
+ """ Base class for testing ReST extensions """
+
+ sample = None
+
+ def setUp(self):
+ """ Parse cls.sample into a HTML document tree """
+ super(ReSTExtensionTestCase, self).setUp()
+ self.setHtmlFromRst(self.sample)
+
+ def setHtmlFromRst(self, rst):
+ """ Create html output from rst string """
+ self.html = publish_parts(rst, writer_name="html")["body"]
+ self.html_doc = html.parse(StringIO(self.html))
+
+ def assertHTMLContains(self, element, attributes=None, text=None):
+ """ Test if HTML document includes an element with the given
+ attributes and text content
+
+ """
+ try:
+ tag = next(self.html_doc.iter(element))
+ except StopIteration:
+ raise Exception("<{}> not in {}".format(element, self.html))
+ else:
+ if attributes:
+ arg_attrs = set(attributes.items())
+ tag_attrs = set(tag.items())
+ self.assertTrue(arg_attrs.issubset(tag_attrs))
+ if text:
+ self.assertIn(text, tag.text)
+
+
+class ReSTExtensionTestCaseTestCase(ReSTExtensionTestCase):
+ """ Simple test for our base class :) """
+
+ sample = '.. raw:: html\n\n <iframe src="foo" height="bar">spam</iframe>'
+
+ def test_test(self):
+ self.assertHTMLContains("iframe", attributes={"src": "foo"},
+ text="spam")
+ self.assertRaises(Exception, self.assertHTMLContains, "eggs", {})
+
+
+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 = nikola.plugins.compile_rest.GitHubGist
+ sample = '.. gist:: fake_id\n :file: spam.py'
+ sample_without_filename = '.. gist:: fake_id2'
+
+ def setUp(self):
+ """ Patch GitHubGist for avoiding network dependency """
+ 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)
+
+ 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")
+
+ 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 """
+ 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 """
+
+ sample = '.. slides:: IMG.jpg\n'
+
+ def test_slides(self):
+ """ Test the slides js generation and img tag creation """
+ self.assertHTMLContains("img", attributes={"src": "IMG.jpg"})
+
+
+class SoundCloudTestCase(ReSTExtensionTestCase):
+ """ SoundCloud test case """
+
+ sample = '.. soundcloud:: SID\n :height: 400\n :width: 600'
+
+ def test_soundcloud(self):
+ """ Test SoundCloud iframe tag generation """
+ self.assertHTMLContains("iframe",
+ attributes={"src": ("https://w.soundcloud.com"
+ "/player/?url=http://"
+ "api.soundcloud.com/"
+ "tracks/SID"),
+ "height": "400", "width": "600"})
+
+
+class VimeoTestCase(ReSTExtensionTestCase):
+ """Vimeo test.
+ Set Vimeo.request_size to False for avoiding querying the Vimeo api
+ over the network
+
+ """
+ sample = '.. vimeo:: VID\n :height: 400\n :width: 600'
+
+ def setUp(self):
+ """ Disable query of the vimeo api over the wire """
+ nikola.plugins.compile_rest.Vimeo.request_size = False
+ super(VimeoTestCase, self).setUp()
+ _reload(nikola.plugins.compile_rest)
+
+ def test_vimeo(self):
+ """ Test Vimeo iframe tag generation """
+ self.assertHTMLContains("iframe",
+ attributes={"src": ("http://player.vimeo.com/"
+ "video/VID"),
+ "height": "400", "width": "600"})
+
+
+class YoutubeTestCase(ReSTExtensionTestCase):
+ """ Youtube test case """
+
+ sample = '.. youtube:: YID\n :height: 400\n :width: 600'
+
+ def test_youtube(self):
+ """ Test Youtube iframe tag generation """
+ self.assertHTMLContains("iframe",
+ attributes={"src": ("http://www.youtube.com/"
+ "embed/YID?rel=0&hd=1&"
+ "wmode=transparent"),
+ "height": "400", "width": "600"})
+
+
+class ListingTestCase(ReSTExtensionTestCase):
+ """ Listing test case and CodeBlock alias tests """
+
+ sample = '.. listing:: nikola.py python'
+ sample2 = '.. code-block:: python\n\n import antigravity'
+ sample3 = '.. sourcecode:: python\n\n import antigravity'
+
+ opener_mock = mock.mock_open(read_data="import antigravity\n")
+ opener_mock.return_value.readlines.return_value = "import antigravity\n"
+
+ def setUp(self):
+ """ Inject a mock open function for not generating a test site """
+ self.f = StringIO("import antigravity\n")
+ #_reload(nikola.plugins.compile_rest)
+
+ def test_listing(self):
+ """ Test that we can render a file object contents without errors """
+ with mock.patch("nikola.plugins.compile_rest.listing.codecs_open", self.opener_mock, create=True):
+ self.setHtmlFromRst(self.sample)
+
+ def test_codeblock_alias(self):
+ """ Test CodeBlock aliases """
+ with mock.patch("nikola.plugins.compile_rest.listing.codecs_open", self.opener_mock, create=True):
+ self.setHtmlFromRst(self.sample2)
+ self.setHtmlFromRst(self.sample3)
+
+
+if __name__ == "__main__":
+ unittest.main()