diff options
-rw-r--r-- | tests/__init__.py | 44 | ||||
-rw-r--r-- | tests/base.py | 62 | ||||
-rw-r--r-- | tests/extensions-x-abbr/test.cfg | 2 | ||||
-rw-r--r-- | tests/extensions-x-codehilite/test.cfg | 2 | ||||
-rw-r--r-- | tests/extensions-x-def_list/markdown-syntax.html | 10 | ||||
-rw-r--r-- | tests/extensions-x-def_list/test.cfg | 2 | ||||
-rw-r--r-- | tests/extensions-x-footnotes/test.cfg | 2 | ||||
-rw-r--r-- | tests/extensions-x-tables/test.cfg | 2 | ||||
-rw-r--r-- | tests/extensions-x-toc/syntax-toc.html | 10 | ||||
-rw-r--r-- | tests/extensions-x-toc/test.cfg | 2 | ||||
-rw-r--r-- | tests/extensions-x-wikilinks/test.cfg | 2 | ||||
-rw-r--r-- | tests/extensions-x-wikilinks/wikilinks.html | 3 | ||||
-rw-r--r-- | tests/html4/test.cfg | 2 | ||||
-rw-r--r-- | tests/markdown-test/markdown-syntax.html | 10 | ||||
-rw-r--r-- | tests/markdown-test/tabs.html | 4 | ||||
-rw-r--r-- | tests/misc/em-around-links.html | 13 | ||||
-rw-r--r-- | tests/misc/multi-paragraph-block-quote.html | 2 | ||||
-rw-r--r-- | tests/misc/tabs-in-lists.html | 2 | ||||
-rw-r--r-- | tests/plugins.py | 113 | ||||
-rw-r--r-- | tests/safe_mode/test.cfg | 2 | ||||
-rwxr-xr-x | tests/test_apis.py | 234 | ||||
-rw-r--r-- | tests/util.py | 15 |
22 files changed, 513 insertions, 27 deletions
diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..63ddf5b --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1,44 @@ +import os +import markdown +import codecs +import difflib +import nose +import util +from plugins import MdSyntaxError, HtmlOutput, MdSyntaxErrorPlugin +from test_apis import * + +test_dir = os.path.abspath(os.path.dirname(__file__)) + +def normalize(text): + return ['%s\n' % l for l in text.strip().split('\n')] + +def check_syntax(file, config): + input_file = file + ".txt" + input = codecs.open(input_file, encoding="utf-8").read() + output_file = file + ".html" + expected_output = codecs.open(output_file, encoding="utf-8").read() + output = normalize(markdown.markdown(input, + config.get('DEFAULT', 'extensions'), + config.get('DEFAULT', 'safe_mode'), + config.get('DEFAULT', 'output_format'))) + diff = [l for l in difflib.unified_diff(normalize(expected_output), + output, output_file, + 'actual_output.html', n=3)] + if diff: + raise util.MdSyntaxError('Output from "%s" failed to match expected ' + 'output.\n\n%s' % (input_file, ''.join(diff))) + +def test_markdown_syntax(): + for dir_name, sub_dirs, files in os.walk(test_dir): + # Get dir specific config settings. + config = util.CustomConfigParser({'extensions': '', + 'safe_mode': False, + 'output_format': 'xhtml1'}) + config.read(os.path.join(dir_name, 'test.cfg')) + # Loop through files and generate tests. + for file in files: + root, ext = os.path.splitext(file) + if ext == '.txt': + yield check_syntax, os.path.join(dir_name, root), config + +nose.main(addplugins=[HtmlOutput(), MdSyntaxErrorPlugin()]) diff --git a/tests/base.py b/tests/base.py new file mode 100644 index 0000000..9e70996 --- /dev/null +++ b/tests/base.py @@ -0,0 +1,62 @@ +import os, codecs +import markdown +from nose.tools import assert_equal +import difflib +from plugins import MdSyntaxError + +class SyntaxBase: + """ + Generator that steps through all files in a dir and runs each text file + (*.txt) as a seperate unit test. + + Each subclass of SyntaxBase should define `dir` as a string containing the + name of the directory which holds the test files. For example: + + dir = "path/to/mytests" + + A subclass may redefine the `setUp` method to create a custom `Markdown` + instance specific to that batch of tests. + + """ + + dir = "" + + def __init__(self): + self.files = [x.replace(".txt", "") + for x in os.listdir(self.dir) if x.endswith(".txt")] + + def setUp(self): + """ + Create Markdown instance. + + Override this method to create a custom `Markdown` instance assigned to + `self.md`. For example: + + self.md = markdown.Markdown(extensions=["footnotes"], safe_mode="replace") + + """ + self.md = markdown.Markdown() + + def tearDown(self): + """ tearDown is not implemented. """ + pass + + def test_syntax(self): + for file in self.files: + yield self.check_syntax, file + + def check_syntax(self, file): + input_file = os.path.join(self.dir, file + ".txt") + input = codecs.open(input_file, encoding="utf-8").read() + output_file = os.path.join(self.dir, file + ".html") + expected_output = codecs.open(output_file, encoding="utf-8").read() + output = self.normalize(self.md.convert(input)) + diff = [l for l in difflib.unified_diff(self.normalize(expected_output), + output, output_file, + 'actual_output.html', n=3)] + if diff: + #assert False, + raise MdSyntaxError('Output from "%s" failed to match expected output.\n\n%s' % (input_file, ''.join(diff))) + + def normalize(self, text): + return ['%s\n' % l for l in text.strip().split('\n')] diff --git a/tests/extensions-x-abbr/test.cfg b/tests/extensions-x-abbr/test.cfg new file mode 100644 index 0000000..32d437f --- /dev/null +++ b/tests/extensions-x-abbr/test.cfg @@ -0,0 +1,2 @@ +[DEFAULT] +extensions=abbr diff --git a/tests/extensions-x-codehilite/test.cfg b/tests/extensions-x-codehilite/test.cfg new file mode 100644 index 0000000..6ed10a2 --- /dev/null +++ b/tests/extensions-x-codehilite/test.cfg @@ -0,0 +1,2 @@ +[DEFAULT] +extensions=codehilite diff --git a/tests/extensions-x-def_list/markdown-syntax.html b/tests/extensions-x-def_list/markdown-syntax.html index 2f63b4b..038c9d1 100644 --- a/tests/extensions-x-def_list/markdown-syntax.html +++ b/tests/extensions-x-def_list/markdown-syntax.html @@ -484,12 +484,12 @@ on a line by itself:</p> <p>That is:</p> <ul> <li>Square brackets containing the link identifier (optionally -indented from the left margin using up to three spaces);</li> + indented from the left margin using up to three spaces);</li> <li>followed by a colon;</li> <li>followed by one or more spaces (or tabs);</li> <li>followed by the URL for the link;</li> <li>optionally followed by a title attribute for the link, enclosed -in double or single quotes.</li> + in double or single quotes.</li> </ul> <p>The link URL may, optionally, be surrounded by angle brackets:</p> <pre><code>[id]: <http://example.com/> "Optional Title Here" @@ -660,10 +660,10 @@ for links, allowing for two styles: <em>inline</em> and <em>reference</em>.</p> <ul> <li>An exclamation mark: <code>!</code>;</li> <li>followed by a set of square brackets, containing the <code>alt</code> -attribute text for the image;</li> + attribute text for the image;</li> <li>followed by a set of parentheses, containing the URL or path to -the image, and an optional <code>title</code> attribute enclosed in double -or single quotes.</li> + the image, and an optional <code>title</code> attribute enclosed in double + or single quotes.</li> </ul> <p>Reference-style image syntax looks like this:</p> <pre><code>![Alt text][id] diff --git a/tests/extensions-x-def_list/test.cfg b/tests/extensions-x-def_list/test.cfg new file mode 100644 index 0000000..c9f352d --- /dev/null +++ b/tests/extensions-x-def_list/test.cfg @@ -0,0 +1,2 @@ +[DEFAULT] +extensions=def_list diff --git a/tests/extensions-x-footnotes/test.cfg b/tests/extensions-x-footnotes/test.cfg new file mode 100644 index 0000000..a5f0818 --- /dev/null +++ b/tests/extensions-x-footnotes/test.cfg @@ -0,0 +1,2 @@ +[DEFAULT] +extensions=footnotes diff --git a/tests/extensions-x-tables/test.cfg b/tests/extensions-x-tables/test.cfg new file mode 100644 index 0000000..ce5a83d --- /dev/null +++ b/tests/extensions-x-tables/test.cfg @@ -0,0 +1,2 @@ +[DEFAULT] +extensions=tables diff --git a/tests/extensions-x-toc/syntax-toc.html b/tests/extensions-x-toc/syntax-toc.html index eea5347..3559d45 100644 --- a/tests/extensions-x-toc/syntax-toc.html +++ b/tests/extensions-x-toc/syntax-toc.html @@ -461,12 +461,12 @@ on a line by itself:</p> <p>That is:</p> <ul> <li>Square brackets containing the link identifier (optionally -indented from the left margin using up to three spaces);</li> + indented from the left margin using up to three spaces);</li> <li>followed by a colon;</li> <li>followed by one or more spaces (or tabs);</li> <li>followed by the URL for the link;</li> <li>optionally followed by a title attribute for the link, enclosed -in double or single quotes.</li> + in double or single quotes.</li> </ul> <p>The link URL may, optionally, be surrounded by angle brackets:</p> <pre><code>[id]: <http://example.com/> "Optional Title Here" @@ -634,10 +634,10 @@ for links, allowing for two styles: <em>inline</em> and <em>reference</em>.</p> <ul> <li>An exclamation mark: <code>!</code>;</li> <li>followed by a set of square brackets, containing the <code>alt</code> -attribute text for the image;</li> + attribute text for the image;</li> <li>followed by a set of parentheses, containing the URL or path to -the image, and an optional <code>title</code> attribute enclosed in double -or single quotes.</li> + the image, and an optional <code>title</code> attribute enclosed in double + or single quotes.</li> </ul> <p>Reference-style image syntax looks like this:</p> <pre><code>![Alt text][id] diff --git a/tests/extensions-x-toc/test.cfg b/tests/extensions-x-toc/test.cfg new file mode 100644 index 0000000..e4bc0fe --- /dev/null +++ b/tests/extensions-x-toc/test.cfg @@ -0,0 +1,2 @@ +[DEFAULT] +extensions=toc diff --git a/tests/extensions-x-wikilinks/test.cfg b/tests/extensions-x-wikilinks/test.cfg new file mode 100644 index 0000000..959f38a --- /dev/null +++ b/tests/extensions-x-wikilinks/test.cfg @@ -0,0 +1,2 @@ +[DEFAULT] +extensions=wikilinks diff --git a/tests/extensions-x-wikilinks/wikilinks.html b/tests/extensions-x-wikilinks/wikilinks.html index 1a38535..a76a693 100644 --- a/tests/extensions-x-wikilinks/wikilinks.html +++ b/tests/extensions-x-wikilinks/wikilinks.html @@ -1,5 +1,8 @@ <p>Some text with a <a class="wikilink" href="/WikiLink/">WikiLink</a>.</p> <p>A link with <a class="wikilink" href="/white_space_and_underscores/">white space and_underscores</a> and a empty one.</p> +<p>Another with <a class="wikilink" href="/double_spaces/">double spaces</a> and <a class="wikilink" href="/double__underscores/">double__underscores</a> and +one that <a class="wikilink" href="/has_emphasis_inside/">has <em>emphasis</em> inside</a> and one <a class="wikilink" href="/with_multiple_underscores/">with_multiple_underscores</a> +and one that is <em><a class="wikilink" href="/emphasised/">emphasised</a></em>.</p> <p>And a <a href="http://example.com/RealLink">RealLink</a>.</p> <p><a href="http://example.com/And_A_AutoLink">http://example.com/And_A_AutoLink</a></p> <p>And a <a href="/MarkdownLink/" title="A MarkdownLink">MarkdownLink</a> for diff --git a/tests/html4/test.cfg b/tests/html4/test.cfg new file mode 100644 index 0000000..a3fc498 --- /dev/null +++ b/tests/html4/test.cfg @@ -0,0 +1,2 @@ +[DEFAULT] +output_format=html4 diff --git a/tests/markdown-test/markdown-syntax.html b/tests/markdown-test/markdown-syntax.html index 2f63b4b..038c9d1 100644 --- a/tests/markdown-test/markdown-syntax.html +++ b/tests/markdown-test/markdown-syntax.html @@ -484,12 +484,12 @@ on a line by itself:</p> <p>That is:</p> <ul> <li>Square brackets containing the link identifier (optionally -indented from the left margin using up to three spaces);</li> + indented from the left margin using up to three spaces);</li> <li>followed by a colon;</li> <li>followed by one or more spaces (or tabs);</li> <li>followed by the URL for the link;</li> <li>optionally followed by a title attribute for the link, enclosed -in double or single quotes.</li> + in double or single quotes.</li> </ul> <p>The link URL may, optionally, be surrounded by angle brackets:</p> <pre><code>[id]: <http://example.com/> "Optional Title Here" @@ -660,10 +660,10 @@ for links, allowing for two styles: <em>inline</em> and <em>reference</em>.</p> <ul> <li>An exclamation mark: <code>!</code>;</li> <li>followed by a set of square brackets, containing the <code>alt</code> -attribute text for the image;</li> + attribute text for the image;</li> <li>followed by a set of parentheses, containing the URL or path to -the image, and an optional <code>title</code> attribute enclosed in double -or single quotes.</li> + the image, and an optional <code>title</code> attribute enclosed in double + or single quotes.</li> </ul> <p>Reference-style image syntax looks like this:</p> <pre><code>![Alt text][id] diff --git a/tests/markdown-test/tabs.html b/tests/markdown-test/tabs.html index b26391b..3c11f14 100644 --- a/tests/markdown-test/tabs.html +++ b/tests/markdown-test/tabs.html @@ -1,11 +1,11 @@ <ul> <li> <p>this is a list item -indented with tabs</p> + indented with tabs</p> </li> <li> <p>this is a list item -indented with spaces</p> + indented with spaces</p> </li> </ul> <p>Code:</p> diff --git a/tests/misc/em-around-links.html b/tests/misc/em-around-links.html index 06bfa8e..fafac28 100644 --- a/tests/misc/em-around-links.html +++ b/tests/misc/em-around-links.html @@ -1,16 +1,13 @@ <h1>Title</h1> - <ul> - <li><em><a href="http://www.freewisdom.org/projects/python-markdown/">Python in Markdown</a> by some +<li><em><a href="http://www.freewisdom.org/projects/python-markdown/">Python in Markdown</a> by some great folks</em> - This <em>does</em> work as expected.</li> - <li><em><a href="http://www.freewisdom.org/projects/python-markdown/">Python in Markdown</a> by some +<li><em><a href="http://www.freewisdom.org/projects/python-markdown/">Python in Markdown</a> by some great folks</em> - This <em>does</em> work as expected.</li> - <li><a href="http://www.freewisdom.org/projects/python-markdown/"><em>Python in Markdown</em></a> by some +<li><a href="http://www.freewisdom.org/projects/python-markdown/"><em>Python in Markdown</em></a> by some great folks - This <em>does</em> work as expected.</li> - <li><a href="http://www.freewisdom.org/projects/python-markdown/"><em>Python in Markdown</em></a> <em>by some +<li><a href="http://www.freewisdom.org/projects/python-markdown/"><em>Python in Markdown</em></a> <em>by some great folks</em> - This <em>does</em> work as expected.</li> </ul> - <p><em><a href="http://www.freewisdom.org/projects/python-markdown/">Python in Markdown</a> by some - great folks</em> - This <em>does</em> work as expected.</p> - +great folks</em> - This <em>does</em> work as expected.</p>
\ No newline at end of file diff --git a/tests/misc/multi-paragraph-block-quote.html b/tests/misc/multi-paragraph-block-quote.html index e13986a..f01b5e4 100644 --- a/tests/misc/multi-paragraph-block-quote.html +++ b/tests/misc/multi-paragraph-block-quote.html @@ -1,6 +1,6 @@ <blockquote> <p>This is line one of paragraph one - This is line two of paragraph one</p> +This is line two of paragraph one</p> <p>This is line one of paragraph two</p> <p>This is another blockquote.</p> </blockquote>
\ No newline at end of file diff --git a/tests/misc/tabs-in-lists.html b/tests/misc/tabs-in-lists.html index a1a92ec..fdb7cb6 100644 --- a/tests/misc/tabs-in-lists.html +++ b/tests/misc/tabs-in-lists.html @@ -19,7 +19,7 @@ <p>Now a list with 4 spaces and some text:</p> <ul> <li>A -abcdef</li> + abcdef</li> <li>B</li> </ul> <p>Now with a tab and an extra space:</p> diff --git a/tests/plugins.py b/tests/plugins.py new file mode 100644 index 0000000..d0cb7f8 --- /dev/null +++ b/tests/plugins.py @@ -0,0 +1,113 @@ +import traceback +from util import MdSyntaxError +from nose.plugins import Plugin +from nose.plugins.errorclass import ErrorClass, ErrorClassPlugin + +class MdSyntaxErrorPlugin(ErrorClassPlugin): + """ Add MdSyntaxError and ensure proper formatting. """ + mdsyntax = ErrorClass(MdSyntaxError, label='MdSyntaxError', isfailure=True) + enabled = True + + def configure(self, options, conf): + self.conf = conf + + def addError(self, test, err): + """ Ensure other plugins see the error by returning nothing here. """ + pass + + def formatError(self, test, err): + """ Remove unnessecary and unhelpful traceback from error report. """ + et, ev, tb = err + if et.__name__ == 'MdSyntaxError': + return et, ev, '' + return err + + +def escape(html): + """ Escape HTML for display as source within HTML. """ + html = html.replace('&', '&') + html = html.replace('<', '<') + html = html.replace('>', '>') + return html + + +class HtmlOutput(Plugin): + """Output test results as ugly, unstyled html. """ + + name = 'html-output' + score = 2 # run late + enabled = True + + def __init__(self): + super(HtmlOutput, self).__init__() + self.html = [ '<html><head>', + '<title>Test output</title>', + '</head><body>' ] + + def configure(self, options, conf): + self.conf = conf + + def addSuccess(self, test): + self.html.append('<span>ok</span>') + + def addError(self, test, err): + err = self.formatErr(err) + self.html.append('<span>ERROR</span>') + self.html.append('<pre>%s</pre>' % escape(err)) + + def addFailure(self, test, err): + err = self.formatErr(err) + self.html.append('<span>FAIL</span>') + self.html.append('<pre>%s</pre>' % escape(err)) + + def finalize(self, result): + self.html.append('<div>') + self.html.append("Ran %d test%s" % + (result.testsRun, result.testsRun != 1 and "s" +or "")) + self.html.append('</div>') + self.html.append('<div>') + if not result.wasSuccessful(): + self.html.extend(['<span>FAILED (', + 'failures=%d ' % len(result.failures), + 'errors=%d' % len(result.errors)]) + for cls in result.errorClasses.keys(): + storage, label, isfail = result.errorClasses[cls] + if isfail: + self.html.append(' %ss=%d' % (label, len(storage))) + self.html.append(')</span>') + else: + self.html.append('OK') + self.html.append('</div></body></html>') + f = open('tmp/test-output.html', 'w') + for l in self.html: + f.write(l) + f.close() + + def formatErr(self, err): + exctype, value, tb = err + return ''.join(traceback.format_exception(exctype, value, tb)) + + def startContext(self, ctx): + try: + n = ctx.__name__ + except AttributeError: + n = str(ctx).replace('<', '').replace('>', '') + self.html.extend(['<fieldset>', '<legend>', n, '</legend>']) + try: + path = ctx.__file__.replace('.pyc', '.py') + self.html.extend(['<div>', path, '</div>']) + except AttributeError: + pass + + def stopContext(self, ctx): + self.html.append('</fieldset>') + + def startTest(self, test): + self.html.extend([ '<div><span>', + test.shortDescription() or str(test), + '</span>' ]) + + def stopTest(self, test): + self.html.append('</div>') + diff --git a/tests/safe_mode/test.cfg b/tests/safe_mode/test.cfg new file mode 100644 index 0000000..d23e418 --- /dev/null +++ b/tests/safe_mode/test.cfg @@ -0,0 +1,2 @@ +[DEFAULT] +safe_mode=escape diff --git a/tests/test_apis.py b/tests/test_apis.py new file mode 100755 index 0000000..59b5a2e --- /dev/null +++ b/tests/test_apis.py @@ -0,0 +1,234 @@ +#!/usr/bin/python +""" +Python-Markdown Regression Tests +================================ + +Tests of the various APIs with the python markdown lib. + +""" + +import unittest +from doctest import DocTestSuite +import os +import markdown + +class TestMarkdownBasics(unittest.TestCase): + """ Tests basics of the Markdown class. """ + + def setUp(self): + """ Create instance of Markdown. """ + self.md = markdown.Markdown() + + def testBlankInput(self): + """ Test blank input. """ + self.assertEqual(self.md.convert(''), '') + + def testWhitespaceOnly(self): + """ Test input of only whitespace. """ + self.assertEqual(self.md.convert(' '), '') + + def testSimpleInput(self): + """ Test simple input. """ + self.assertEqual(self.md.convert('foo'), '<p>foo</p>') + +class TestBlockParser(unittest.TestCase): + """ Tests of the BlockParser class. """ + + def setUp(self): + """ Create instance of BlockParser. """ + self.parser = markdown.Markdown().parser + + def testParseChunk(self): + """ Test BlockParser.parseChunk. """ + root = markdown.etree.Element("div") + text = 'foo' + self.parser.parseChunk(root, text) + self.assertEqual(markdown.etree.tostring(root), "<div><p>foo</p></div>") + + def testParseDocument(self): + """ Test BlockParser.parseDocument. """ + lines = ['#foo', '', 'bar', '', ' baz'] + tree = self.parser.parseDocument(lines) + self.assert_(isinstance(tree, markdown.etree.ElementTree)) + self.assert_(markdown.etree.iselement(tree.getroot())) + self.assertEqual(markdown.etree.tostring(tree.getroot()), + "<div><h1>foo</h1><p>bar</p><pre><code>baz\n</code></pre></div>") + + +class TestBlockParserState(unittest.TestCase): + """ Tests of the State class for BlockParser. """ + + def setUp(self): + self.state = markdown.blockparser.State() + + def testBlankState(self): + """ Test State when empty. """ + self.assertEqual(self.state, []) + + def testSetSate(self): + """ Test State.set(). """ + self.state.set('a_state') + self.assertEqual(self.state, ['a_state']) + self.state.set('state2') + self.assertEqual(self.state, ['a_state', 'state2']) + + def testIsSate(self): + """ Test State.isstate(). """ + self.assertEqual(self.state.isstate('anything'), False) + self.state.set('a_state') + self.assertEqual(self.state.isstate('a_state'), True) + self.state.set('state2') + self.assertEqual(self.state.isstate('state2'), True) + self.assertEqual(self.state.isstate('a_state'), False) + self.assertEqual(self.state.isstate('missing'), False) + + def testReset(self): + """ Test State.reset(). """ + self.state.set('a_state') + self.state.reset() + self.assertEqual(self.state, []) + self.state.set('state1') + self.state.set('state2') + self.state.reset() + self.assertEqual(self.state, ['state1']) + +class TestHtmlStash(unittest.TestCase): + """ Test Markdown's HtmlStash. """ + + def setUp(self): + self.stash = markdown.preprocessors.HtmlStash() + self.placeholder = self.stash.store('foo') + + def testSimpleStore(self): + """ Test HtmlStash.store. """ + self.assertEqual(self.placeholder, + markdown.preprocessors.HTML_PLACEHOLDER % 0) + self.assertEqual(self.stash.html_counter, 1) + self.assertEqual(self.stash.rawHtmlBlocks, [('foo', False)]) + + def testStoreMore(self): + """ Test HtmlStash.store with additional blocks. """ + placeholder = self.stash.store('bar') + self.assertEqual(placeholder, + markdown.preprocessors.HTML_PLACEHOLDER % 1) + self.assertEqual(self.stash.html_counter, 2) + self.assertEqual(self.stash.rawHtmlBlocks, + [('foo', False), ('bar', False)]) + + def testSafeStore(self): + """ Test HtmlStash.store with 'safe' html. """ + self.stash.store('bar', True) + self.assertEqual(self.stash.rawHtmlBlocks, + [('foo', False), ('bar', True)]) + + def testReset(self): + """ Test HtmlStash.reset. """ + self.stash.reset() + self.assertEqual(self.stash.html_counter, 0) + self.assertEqual(self.stash.rawHtmlBlocks, []) + +class TestOrderedDict(unittest.TestCase): + """ Test OrderedDict storage class. """ + + def setUp(self): + self.odict = markdown.odict.OrderedDict() + self.odict['first'] = 'This' + self.odict['third'] = 'a' + self.odict['fourth'] = 'self' + self.odict['fifth'] = 'test' + + def testValues(self): + """ Test output of OrderedDict.values(). """ + self.assertEqual(self.odict.values(), ['This', 'a', 'self', 'test']) + + def testKeys(self): + """ Test output of OrderedDict.keys(). """ + self.assertEqual(self.odict.keys(), + ['first', 'third', 'fourth', 'fifth']) + + def testItems(self): + """ Test output of OrderedDict.items(). """ + self.assertEqual(self.odict.items(), + [('first', 'This'), ('third', 'a'), + ('fourth', 'self'), ('fifth', 'test')]) + + def testAddBefore(self): + """ Test adding an OrderedDict item before a given key. """ + self.odict.add('second', 'is', '<third') + self.assertEqual(self.odict.items(), + [('first', 'This'), ('second', 'is'), ('third', 'a'), + ('fourth', 'self'), ('fifth', 'test')]) + + def testAddAfter(self): + """ Test adding an OrderDict item after a given key. """ + self.odict.add('second', 'is', '>first') + self.assertEqual(self.odict.items(), + [('first', 'This'), ('second', 'is'), ('third', 'a'), + ('fourth', 'self'), ('fifth', 'test')]) + + def testAddAfterEnd(self): + """ Test adding an OrderedDict item after the last key. """ + self.odict.add('sixth', '.', '>fifth') + self.assertEqual(self.odict.items(), + [('first', 'This'), ('third', 'a'), + ('fourth', 'self'), ('fifth', 'test'), ('sixth', '.')]) + + def testAdd_begin(self): + """ Test adding an OrderedDict item using "_begin". """ + self.odict.add('zero', 'CRAZY', '_begin') + self.assertEqual(self.odict.items(), + [('zero', 'CRAZY'), ('first', 'This'), ('third', 'a'), + ('fourth', 'self'), ('fifth', 'test')]) + + def testAdd_end(self): + """ Test adding an OrderedDict item using "_end". """ + self.odict.add('sixth', '.', '_end') + self.assertEqual(self.odict.items(), + [('first', 'This'), ('third', 'a'), + ('fourth', 'self'), ('fifth', 'test'), ('sixth', '.')]) + + def testAddBadLocation(self): + """ Test Error on bad location in OrderedDict.add(). """ + self.assertRaises(ValueError, self.odict.add, 'sixth', '.', '<seventh') + self.assertRaises(ValueError, self.odict.add, 'second', 'is', 'third') + + def testDeleteItem(self): + """ Test deletion of an OrderedDict item. """ + del self.odict['fourth'] + self.assertEqual(self.odict.items(), + [('first', 'This'), ('third', 'a'), ('fifth', 'test')]) + + def testChangeValue(self): + """ Test OrderedDict change value. """ + self.odict['fourth'] = 'CRAZY' + self.assertEqual(self.odict.items(), + [('first', 'This'), ('third', 'a'), + ('fourth', 'CRAZY'), ('fifth', 'test')]) + + def testChangeOrder(self): + """ Test OrderedDict change order. """ + self.odict.link('fourth', '<third') + self.assertEqual(self.odict.items(), + [('first', 'This'), ('fourth', 'self'), + ('third', 'a'), ('fifth', 'test')]) + +def suite(): + """ Build a test suite of the above tests and extension doctests. """ + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(TestMarkdown)) + suite.addTest(unittest.makeSuite(TestBlockParser)) + suite.addTest(unittest.makeSuite(TestBlockParserState)) + suite.addTest(unittest.makeSuite(TestHtmlStash)) + suite.addTest(unittest.makeSuite(TestOrderedDict)) + + for filename in os.listdir('markdown/extensions'): + if filename.endswith('.py'): + module = 'markdown.extensions.%s' % filename[:-3] + try: + suite.addTest(DocTestSuite(module)) + except: ValueError + # No tests + return suite + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite()) diff --git a/tests/util.py b/tests/util.py new file mode 100644 index 0000000..3b0175d --- /dev/null +++ b/tests/util.py @@ -0,0 +1,15 @@ +from ConfigParser import SafeConfigParser + +class MdSyntaxError(Exception): + pass + + +class CustomConfigParser(SafeConfigParser): + def get(self, section, option): + value = SafeConfigParser.get(self, section, option) + if option == 'extensions': + if len(value.strip()): + return value.split(',') + else: + return [] + return value |