diff options
Diffstat (limited to 'tests/test_build_html.py')
-rw-r--r-- | tests/test_build_html.py | 191 |
1 files changed, 141 insertions, 50 deletions
diff --git a/tests/test_build_html.py b/tests/test_build_html.py index 3ee89b72b..b1181fbeb 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -5,7 +5,7 @@ Test the HTML builder and check output against XPath. - :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -16,7 +16,7 @@ from six import PY3, iteritems from six.moves import html_entities from sphinx import __display_version__ -from util import remove_unicode_literals, gen_with_app +from util import remove_unicode_literals, gen_with_app, with_app from etree13 import ElementTree as ET @@ -31,18 +31,16 @@ http://www.python.org/logo.png reading included file u'.*?wrongenc.inc' seems to be wrong, try giving an \ :encoding: option\\n? %(root)s/includes.txt:4: WARNING: download file not readable: .*?nonexisting.png -(%(root)s/markup.txt:\\d+: WARNING: Malformed :option: u'&option', does \ -not contain option marker - or -- or / or \\+ -%(root)s/undecodable.txt:3: WARNING: undecodable source characters, replacing \ +(%(root)s/markup.txt:359: WARNING: invalid single index entry u'')? +(%(root)s/undecodable.txt:3: WARNING: undecodable source characters, replacing \ with "\\?": b?'here: >>>(\\\\|/)xbb<<<' )?""" HTML_WARNINGS = ENV_WARNINGS + """\ %(root)s/images.txt:20: WARNING: no matching candidate for image URI u'foo.\\*' -None:\\d+: WARNING: citation not found: missing -%(root)s/markup.txt:: WARNING: invalid single index entry u'' -%(root)s/markup.txt:: WARNING: invalid pair index entry u'' -%(root)s/markup.txt:: WARNING: invalid pair index entry u'keyword; ' +%(root)s/markup.txt:271: WARNING: Could not lex literal_block as "c". Highlighting skipped. +%(root)s/footnote.txt:60: WARNING: citation not found: missing +%(root)s/markup.txt:160: WARNING: unknown option: &option """ if PY3: @@ -83,9 +81,9 @@ HTML_XPATH = { (".//pre", u'Max Strauß'), (".//a[@href='_downloads/img.png']", ''), (".//a[@href='_downloads/img1.png']", ''), - (".//pre", u'"quotes"'), - (".//pre", u"'included'"), - (".//pre/span[@class='s']", u'üöä'), + (".//pre/span", u'"quotes"'), + (".//pre/span", u"'included'"), + (".//pre/span[@class='s2']", u'üöä'), (".//div[@class='inc-pyobj1 highlight-text']//pre", r'^class Foo:\n pass\n\s*$'), (".//div[@class='inc-pyobj2 highlight-text']//pre", @@ -154,7 +152,7 @@ HTML_XPATH = { (".//a[@href='#grammar-token-try_stmt']" "[@class='reference internal']/code/span", '^statement$'), (".//a[@href='subdir/includes.html']" - "[@class='reference internal']/em", 'Including in subdir'), + "[@class='reference internal']/span", 'Including in subdir'), (".//a[@href='objects.html#cmdoption-python-c']" "[@class='reference internal']/code/span[@class='pre']", '-c'), # abbreviations @@ -234,6 +232,23 @@ HTML_XPATH = { (".//td[@class='field-body']/ul/li/strong", '^hour$'), (".//td[@class='field-body']/ul/li/em", '^DuplicateType$'), (".//td[@class='field-body']/ul/li/em", tail_check(r'.* Some parameter')), + # others + (".//a[@class='reference internal'][@href='#cmdoption-perl-arg-+p']/code/span", + 'perl'), + (".//a[@class='reference internal'][@href='#cmdoption-perl-arg-+p']/code/span", + '\+p'), + (".//a[@class='reference internal'][@href='#cmdoption-perl-arg-arg']/code/span", + 'arg'), + (".//a[@class='reference internal'][@href='#cmdoption-hg-arg-commit']/code/span", + 'hg'), + (".//a[@class='reference internal'][@href='#cmdoption-hg-arg-commit']/code/span", + 'commit'), + (".//a[@class='reference internal'][@href='#cmdoption-git-commit-p']/code/span", + 'git'), + (".//a[@class='reference internal'][@href='#cmdoption-git-commit-p']/code/span", + 'commit'), + (".//a[@class='reference internal'][@href='#cmdoption-git-commit-p']/code/span", + '-p'), ], 'contents.html': [ (".//meta[@name='hc'][@content='hcval']", ''), @@ -280,14 +295,18 @@ HTML_XPATH = { (".//dt/a", "double"), ], 'footnote.html': [ - (".//a[@class='footnote-reference'][@href='#id5'][@id='id1']", r"\[1\]"), - (".//a[@class='footnote-reference'][@href='#id6'][@id='id2']", r"\[2\]"), + (".//a[@class='footnote-reference'][@href='#id7'][@id='id1']", r"\[1\]"), + (".//a[@class='footnote-reference'][@href='#id8'][@id='id2']", r"\[2\]"), (".//a[@class='footnote-reference'][@href='#foo'][@id='id3']", r"\[3\]"), (".//a[@class='reference internal'][@href='#bar'][@id='id4']", r"\[bar\]"), + (".//a[@class='footnote-reference'][@href='#id9'][@id='id5']", r"\[4\]"), + (".//a[@class='footnote-reference'][@href='#id10'][@id='id6']", r"\[5\]"), (".//a[@class='fn-backref'][@href='#id1']", r"\[1\]"), (".//a[@class='fn-backref'][@href='#id2']", r"\[2\]"), (".//a[@class='fn-backref'][@href='#id3']", r"\[3\]"), (".//a[@class='fn-backref'][@href='#id4']", r"\[bar\]"), + (".//a[@class='fn-backref'][@href='#id5']", r"\[4\]"), + (".//a[@class='fn-backref'][@href='#id6']", r"\[5\]"), ], 'otherext.html': [ (".//h1", "Generated section"), @@ -325,12 +344,23 @@ def check_xpath(etree, fname, path, check, be_found=True): # only check for node presence pass else: + def get_text(node): + if node.text is not None: + return node.text + else: + # Since pygments-2.1.1, empty <span> tag is inserted at top of + # highlighting block + if len(node) == 1 and node[0].tag == 'span' and node[0].text is None: + return node[0].tail + else: + return '' + rex = re.compile(check) if be_found: - if any(node.text and rex.search(node.text) for node in nodes): + if any(rex.search(get_text(node)) for node in nodes): return else: - if all(node.text and not rex.search(node.text) for node in nodes): + if all(not rex.search(get_text(node)) for node in nodes): return assert False, ('%r not found in any node matching ' @@ -356,7 +386,7 @@ def check_extra_entries(outdir): assert (outdir / 'robots.txt').isfile() -@gen_with_app(buildername='html', +@gen_with_app(buildername='html', freshenv=True, # use freshenv to check warnings confoverrides={'html_context.hckey_co': 'hcval_co'}, tags=['testtag']) def test_html_output(app, status, warning): @@ -372,11 +402,8 @@ def test_html_output(app, status, warning): for fname, paths in iteritems(HTML_XPATH): parser = NslessParser() parser.entity.update(html_entities.entitydefs) - fp = open(os.path.join(app.outdir, fname), 'rb') - try: + with (app.outdir / fname).open('rb') as fp: etree = ET.parse(fp, parser) - finally: - fp.close() for path, check in paths: yield check_xpath, etree, fname, path, check @@ -425,11 +452,8 @@ def test_tocdepth(app, status, warning): for fname, paths in iteritems(expects): parser = NslessParser() parser.entity.update(html_entities.entitydefs) - fp = open(os.path.join(app.outdir, fname), 'rb') - try: + with (app.outdir / fname).open('rb') as fp: etree = ET.parse(fp, parser) - finally: - fp.close() for xpath, check, be_found in paths: yield check_xpath, etree, fname, xpath, check, be_found @@ -470,11 +494,8 @@ def test_tocdepth_singlehtml(app, status, warning): for fname, paths in iteritems(expects): parser = NslessParser() parser.entity.update(html_entities.entitydefs) - fp = open(os.path.join(app.outdir, fname), 'rb') - try: + with (app.outdir / fname).open('rb') as fp: etree = ET.parse(fp, parser) - finally: - fp.close() for xpath, check, be_found in paths: yield check_xpath, etree, fname, xpath, check, be_found @@ -484,6 +505,11 @@ def test_tocdepth_singlehtml(app, status, warning): def test_numfig_disabled(app, status, warning): app.builder.build_all() + assert ('index.rst:45: WARNING: numfig is disabled. :numref: is ignored.' + in warning.getvalue()) + assert 'index.rst:51: WARNING: invalid numfig_format: invalid' not in warning.getvalue() + assert 'index.rst:52: WARNING: invalid numfig_format: Fig %s %s' not in warning.getvalue() + expects = { 'index.html': [ (".//div[@class='figure']/p[@class='caption']/" @@ -524,11 +550,8 @@ def test_numfig_disabled(app, status, warning): for fname, paths in iteritems(expects): parser = NslessParser() parser.entity.update(html_entities.entitydefs) - fp = open(os.path.join(app.outdir, fname), 'rb') - try: + with (app.outdir / fname).open('rb') as fp: etree = ET.parse(fp, parser) - finally: - fp.close() for xpath, check, be_found in paths: yield check_xpath, etree, fname, xpath, check, be_found @@ -543,6 +566,11 @@ def test_numfig_without_numbered_toctree(app, status, warning): (app.srcdir / 'index.rst').write_text(index, encoding='utf-8') app.builder.build_all() + assert ('index.rst:45: WARNING: numfig is disabled. :numref: is ignored.' + not in warning.getvalue()) + assert 'index.rst:51: WARNING: invalid numfig_format: invalid' in warning.getvalue() + assert 'index.rst:52: WARNING: invalid numfig_format: Fig %s %s' in warning.getvalue() + expects = { 'index.html': [ (".//div[@class='figure']/p[@class='caption']/" @@ -623,11 +651,8 @@ def test_numfig_without_numbered_toctree(app, status, warning): for fname, paths in iteritems(expects): parser = NslessParser() parser.entity.update(html_entities.entitydefs) - fp = open(os.path.join(app.outdir, fname), 'rb') - try: + with (app.outdir / fname).open('rb') as fp: etree = ET.parse(fp, parser) - finally: - fp.close() for xpath, check, be_found in paths: yield check_xpath, etree, fname, xpath, check, be_found @@ -638,6 +663,11 @@ def test_numfig_without_numbered_toctree(app, status, warning): def test_numfig_with_numbered_toctree(app, status, warning): app.builder.build_all() + assert ('index.rst:45: WARNING: numfig is disabled. :numref: is ignored.' + not in warning.getvalue()) + assert 'index.rst:51: WARNING: invalid numfig_format: invalid' in warning.getvalue() + assert 'index.rst:52: WARNING: invalid numfig_format: Fig %s %s' in warning.getvalue() + expects = { 'index.html': [ (".//div[@class='figure']/p[@class='caption']/" @@ -718,11 +748,8 @@ def test_numfig_with_numbered_toctree(app, status, warning): for fname, paths in iteritems(expects): parser = NslessParser() parser.entity.update(html_entities.entitydefs) - fp = open(os.path.join(app.outdir, fname), 'rb') - try: + with (app.outdir / fname).open('rb') as fp: etree = ET.parse(fp, parser) - finally: - fp.close() for xpath, check, be_found in paths: yield check_xpath, etree, fname, xpath, check, be_found @@ -736,6 +763,11 @@ def test_numfig_with_numbered_toctree(app, status, warning): def test_numfig_with_prefix(app, status, warning): app.builder.build_all() + assert ('index.rst:45: WARNING: numfig is disabled. :numref: is ignored.' + not in warning.getvalue()) + assert 'index.rst:51: WARNING: invalid numfig_format: invalid' in warning.getvalue() + assert 'index.rst:52: WARNING: invalid numfig_format: Fig %s %s' in warning.getvalue() + expects = { 'index.html': [ (".//div[@class='figure']/p[@class='caption']/" @@ -816,11 +848,8 @@ def test_numfig_with_prefix(app, status, warning): for fname, paths in iteritems(expects): parser = NslessParser() parser.entity.update(html_entities.entitydefs) - fp = open(os.path.join(app.outdir, fname), 'rb') - try: + with (app.outdir / fname).open('rb') as fp: etree = ET.parse(fp, parser) - finally: - fp.close() for xpath, check, be_found in paths: yield check_xpath, etree, fname, xpath, check, be_found @@ -831,6 +860,11 @@ def test_numfig_with_prefix(app, status, warning): def test_numfig_with_secnum_depth(app, status, warning): app.builder.build_all() + assert ('index.rst:45: WARNING: numfig is disabled. :numref: is ignored.' + not in warning.getvalue()) + assert 'index.rst:51: WARNING: invalid numfig_format: invalid' in warning.getvalue() + assert 'index.rst:52: WARNING: invalid numfig_format: Fig %s %s' in warning.getvalue() + expects = { 'index.html': [ (".//div[@class='figure']/p[@class='caption']/" @@ -911,11 +945,68 @@ def test_numfig_with_secnum_depth(app, status, warning): for fname, paths in iteritems(expects): parser = NslessParser() parser.entity.update(html_entities.entitydefs) - fp = open(os.path.join(app.outdir, fname), 'rb') - try: + with (app.outdir / fname).open('rb') as fp: + etree = ET.parse(fp, parser) + + for xpath, check, be_found in paths: + yield check_xpath, etree, fname, xpath, check, be_found + + +@gen_with_app(buildername='html', testroot='add_enumerable_node') +def test_enumerable_node(app, status, warning): + app.builder.build_all() + + expects = { + 'index.html': [ + (".//div[@class='figure']/p[@class='caption']/span[@class='caption-number']", + "Fig. 1", True), + (".//div[@class='figure']/p[@class='caption']/span[@class='caption-number']", + "Fig. 2", True), + (".//div[@class='figure']/p[@class='caption']/span[@class='caption-number']", + "Fig. 3", True), + (".//div//span[@class='caption-number']", "No.1 ", True), + (".//div//span[@class='caption-number']", "No.2 ", True), + (".//li/a/span", 'Fig. 1', True), + (".//li/a/span", 'Fig. 2', True), + (".//li/a/span", 'Fig. 3', True), + (".//li/a/span", 'No.1', True), + (".//li/a/span", 'No.2', True), + ], + } + + for fname, paths in iteritems(expects): + parser = NslessParser() + parser.entity.update(html_entities.entitydefs) + with (app.outdir / fname).open('rb') as fp: etree = ET.parse(fp, parser) - finally: - fp.close() for xpath, check, be_found in paths: yield check_xpath, etree, fname, xpath, check, be_found + + +@with_app(buildername='html') +def test_jsmath(app, status, warning): + app.builder.build_all() + content = (app.outdir / 'math.html').text() + + assert '<div class="math">\na^2 + b^2 = c^2</div>' in content + assert '<div class="math">\n\\begin{split}a + 1 < b\\end{split}</div>' in content + assert ('<span class="eqno">(1)</span><div class="math" id="equation-foo">\n' + 'e^{i\\pi} = 1</div>' in content) + assert ('<span class="eqno">(2)</span><div class="math">\n' + 'e^{ix} = \\cos x + i\\sin x</div>' in content) + assert '<div class="math">\nn \\in \\mathbb N</div>' in content + assert '<div class="math">\na + 1 < b</div>' in content + + +@with_app(buildername='html', testroot='html_extra_path') +def test_html_extra_path(app, status, warning): + app.builder.build_all() + + assert (app.outdir / '.htaccess').exists() + assert not (app.outdir / '.htpasswd').exists() + assert (app.outdir / 'API.html_t').exists() + assert (app.outdir / 'css/style.css').exists() + assert (app.outdir / 'rimg.png').exists() + assert not (app.outdir / '_build/index.html').exists() + assert (app.outdir / 'background.png').exists() |