'),
],
'genindex.html': [
# index entries
(".//a/strong", "Main"),
(".//a/strong", "[1]"),
(".//a/strong", "Other"),
(".//a", "entry"),
(".//dt/a", "double"),
],
'footnote.html': [
(".//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"),
]
}
class NslessParser(ET.XMLParser):
"""XMLParser that throws away namespaces in tag names."""
def _fixname(self, key):
try:
return self._names[key]
except KeyError:
name = key
br = name.find('}')
if br > 0:
name = name[br+1:]
self._names[key] = name = self._fixtext(name)
return name
def check_xpath(etree, fname, path, check, be_found=True):
nodes = list(etree.findall(path))
if check is None:
assert nodes == [], ('found any nodes matching xpath '
'%r in file %s' % (path, fname))
return
else:
assert nodes != [], ('did not find any node matching xpath '
'%r in file %s' % (path, fname))
if hasattr(check, '__call__'):
check(nodes)
elif not check:
# only check for node presence
pass
else:
rex = re.compile(check)
if be_found:
if any(node.text and rex.search(node.text) for node in nodes):
return
else:
if all(node.text and not rex.search(node.text) for node in nodes):
return
assert False, ('%r not found in any node matching '
'path %s in %s: %r' % (check, path, fname,
[node.text for node in nodes]))
def check_static_entries(outdir):
staticdir = outdir / '_static'
assert staticdir.isdir()
# a file from a directory entry in html_static_path
assert (staticdir / 'README').isfile()
# a directory from a directory entry in html_static_path
assert (staticdir / 'subdir' / 'foo.css').isfile()
# a file from a file entry in html_static_path
assert (staticdir / 'templated.css').isfile()
assert (staticdir / 'templated.css').text().splitlines()[1] == __display_version__
# a file from _static, but matches exclude_patterns
assert not (staticdir / 'excluded.css').exists()
def check_extra_entries(outdir):
assert (outdir / 'robots.txt').isfile()
@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):
app.builder.build_all()
html_warnings = warning.getvalue().replace(os.sep, '/')
html_warnings_exp = HTML_WARNINGS % {
'root': re.escape(app.srcdir.replace(os.sep, '/'))}
assert re.match(html_warnings_exp + '$', html_warnings), \
'Warnings don\'t match:\n' + \
'--- Expected (regex):\n' + html_warnings_exp + \
'--- Got:\n' + html_warnings
for fname, paths in iteritems(HTML_XPATH):
parser = NslessParser()
parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
etree = ET.parse(fp, parser)
for path, check in paths:
yield check_xpath, etree, fname, path, check
check_static_entries(app.builder.outdir)
check_extra_entries(app.builder.outdir)
@gen_with_app(buildername='html', testroot='tocdepth')
def test_tocdepth(app, status, warning):
# issue #1251
app.builder.build_all()
expects = {
'index.html': [
(".//li[@class='toctree-l3']/a", '1.1.1. Foo A1', True),
(".//li[@class='toctree-l3']/a", '1.2.1. Foo B1', True),
(".//li[@class='toctree-l3']/a", '2.1.1. Bar A1', False),
(".//li[@class='toctree-l3']/a", '2.2.1. Bar B1', False),
],
'foo.html': [
(".//h1", '1. Foo', True),
(".//h2", '1.1. Foo A', True),
(".//h3", '1.1.1. Foo A1', True),
(".//h2", '1.2. Foo B', True),
(".//h3", '1.2.1. Foo B1', True),
(".//div[@class='sphinxsidebarwrapper']//li/a", '1.1. Foo A', True),
(".//div[@class='sphinxsidebarwrapper']//li/a", '1.1.1. Foo A1', True),
(".//div[@class='sphinxsidebarwrapper']//li/a", '1.2. Foo B', True),
(".//div[@class='sphinxsidebarwrapper']//li/a", '1.2.1. Foo B1', True),
],
'bar.html': [
(".//h1", '2. Bar', True),
(".//h2", '2.1. Bar A', True),
(".//h2", '2.2. Bar B', True),
(".//h3", '2.2.1. Bar B1', True),
(".//div[@class='sphinxsidebarwrapper']//li/a", '2. Bar', True),
(".//div[@class='sphinxsidebarwrapper']//li/a", '2.1. Bar A', True),
(".//div[@class='sphinxsidebarwrapper']//li/a", '2.2. Bar B', True),
(".//div[@class='sphinxsidebarwrapper']//li/a", '2.2.1. Bar B1', False),
],
'baz.html': [
(".//h1", '2.1.1. Baz A', 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)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@gen_with_app(buildername='singlehtml', testroot='tocdepth')
def test_tocdepth_singlehtml(app, status, warning):
app.builder.build_all()
expects = {
'index.html': [
(".//li[@class='toctree-l3']/a", '1.1.1. Foo A1', True),
(".//li[@class='toctree-l3']/a", '1.2.1. Foo B1', True),
(".//li[@class='toctree-l3']/a", '2.1.1. Bar A1', False),
(".//li[@class='toctree-l3']/a", '2.2.1. Bar B1', False),
# index.rst
(".//h1", 'test-tocdepth', True),
# foo.rst
(".//h2", '1. Foo', True),
(".//h3", '1.1. Foo A', True),
(".//h4", '1.1.1. Foo A1', True),
(".//h3", '1.2. Foo B', True),
(".//h4", '1.2.1. Foo B1', True),
# bar.rst
(".//h2", '2. Bar', True),
(".//h3", '2.1. Bar A', True),
(".//h3", '2.2. Bar B', True),
(".//h4", '2.2.1. Bar B1', True),
# baz.rst
(".//h4", '2.1.1. Baz A', 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)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@gen_with_app(buildername='html', testroot='numfig')
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']/"
"span[@class='caption-number']", None, True),
(".//table/caption/span[@class='caption-number']", None, True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", None, True),
(".//li/code/span", '^fig1$', True),
(".//li/code/span", '^Figure%s$', True),
(".//li/code/span", '^table-1$', True),
(".//li/code/span", '^Table:%s$', True),
(".//li/code/span", '^CODE_1$', True),
(".//li/code/span", '^Code-%s$', True),
],
'foo.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", None, True),
(".//table/caption/span[@class='caption-number']", None, True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", None, True),
],
'bar.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", None, True),
(".//table/caption/span[@class='caption-number']", None, True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", None, True),
],
'baz.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", None, True),
(".//table/caption/span[@class='caption-number']", None, True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", None, 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)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@gen_with_app(buildername='html', testroot='numfig',
confoverrides={'numfig': True})
def test_numfig_without_numbered_toctree(app, status, warning):
# remove :numbered: option
index = (app.srcdir / 'index.rst').text()
index = re.sub(':numbered:.*', '', index, re.MULTILINE)
(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']/"
"span[@class='caption-number']", '^Fig. 9 $', True),
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 10 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 9 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 10 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 9 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 10 $', True),
(".//li/a/span", '^Fig. 9$', True),
(".//li/a/span", '^Figure6$', True),
(".//li/a/span", '^Table 9$', True),
(".//li/a/span", '^Table:6$', True),
(".//li/a/span", '^Listing 9$', True),
(".//li/a/span", '^Code-6$', True),
],
'foo.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[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 4 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 1 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 2 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 3 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 4 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 1 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 2 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 3 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 4 $', True),
],
'bar.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 5 $', True),
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 7 $', True),
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 8 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 5 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 7 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 8 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 5 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 7 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 8 $', True),
],
'baz.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 6 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 6 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 6 $', 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)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@gen_with_app(buildername='html', testroot='numfig',
confoverrides={'numfig': True})
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']/"
"span[@class='caption-number']", '^Fig. 1 $', True),
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 2 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 1 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 2 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 1 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 2 $', True),
(".//li/a/span", '^Fig. 1$', True),
(".//li/a/span", '^Figure2.2$', True),
(".//li/a/span", '^Table 1$', True),
(".//li/a/span", '^Table:2.2$', True),
(".//li/a/span", '^Listing 1$', True),
(".//li/a/span", '^Code-2.2$', True),
],
'foo.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 1.1 $', True),
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 1.2 $', True),
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 1.3 $', True),
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 1.4 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 1.1 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 1.2 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 1.3 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 1.4 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 1.1 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 1.2 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 1.3 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 1.4 $', True),
],
'bar.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 2.1 $', True),
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 2.3 $', True),
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 2.4 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 2.1 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 2.3 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 2.4 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 2.1 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 2.3 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 2.4 $', True),
],
'baz.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 2.2 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 2.2 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 2.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)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@gen_with_app(buildername='html', testroot='numfig',
confoverrides={'numfig': True,
'numfig_format': {'figure': 'Figure:%s',
'table': 'Tab_%s',
'code-block': 'Code-%s'}})
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']/"
"span[@class='caption-number']", '^Figure:1 $', True),
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Figure:2 $', True),
(".//table/caption/span[@class='caption-number']",
'^Tab_1 $', True),
(".//table/caption/span[@class='caption-number']",
'^Tab_2 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Code-1 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Code-2 $', True),
(".//li/a/span", '^Figure:1$', True),
(".//li/a/span", '^Figure2.2$', True),
(".//li/a/span", '^Tab_1$', True),
(".//li/a/span", '^Table:2.2$', True),
(".//li/a/span", '^Code-1$', True),
(".//li/a/span", '^Code-2.2$', True),
],
'foo.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Figure:1.1 $', True),
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Figure:1.2 $', True),
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Figure:1.3 $', True),
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Figure:1.4 $', True),
(".//table/caption/span[@class='caption-number']",
'^Tab_1.1 $', True),
(".//table/caption/span[@class='caption-number']",
'^Tab_1.2 $', True),
(".//table/caption/span[@class='caption-number']",
'^Tab_1.3 $', True),
(".//table/caption/span[@class='caption-number']",
'^Tab_1.4 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Code-1.1 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Code-1.2 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Code-1.3 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Code-1.4 $', True),
],
'bar.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Figure:2.1 $', True),
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Figure:2.3 $', True),
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Figure:2.4 $', True),
(".//table/caption/span[@class='caption-number']",
'^Tab_2.1 $', True),
(".//table/caption/span[@class='caption-number']",
'^Tab_2.3 $', True),
(".//table/caption/span[@class='caption-number']",
'^Tab_2.4 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Code-2.1 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Code-2.3 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Code-2.4 $', True),
],
'baz.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Figure:2.2 $', True),
(".//table/caption/span[@class='caption-number']",
'^Tab_2.2 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Code-2.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)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@gen_with_app(buildername='html', testroot='numfig',
confoverrides={'numfig': True, 'numfig_secnum_depth': 2})
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']/"
"span[@class='caption-number']", '^Fig. 1 $', True),
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 2 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 1 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 2 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 1 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 2 $', True),
(".//li/a/span", '^Fig. 1$', True),
(".//li/a/span", '^Figure2.1.2$', True),
(".//li/a/span", '^Table 1$', True),
(".//li/a/span", '^Table:2.1.2$', True),
(".//li/a/span", '^Listing 1$', True),
(".//li/a/span", '^Code-2.1.2$', True),
],
'foo.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 1.1 $', True),
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 1.1.1 $', True),
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 1.1.2 $', True),
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 1.2.1 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 1.1 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 1.1.1 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 1.1.2 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 1.2.1 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 1.1 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 1.1.1 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 1.1.2 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 1.2.1 $', True),
],
'bar.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 2.1.1 $', True),
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 2.1.3 $', True),
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 2.2.1 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 2.1.1 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 2.1.3 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 2.2.1 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 2.1.1 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 2.1.3 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 2.2.1 $', True),
],
'baz.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 2.1.2 $', True),
(".//table/caption/span[@class='caption-number']",
'^Table 2.1.2 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 2.1.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)
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 '\na^2 + b^2 = c^2
' in content
assert '\n\\begin{split}a + 1 < b\\end{split}
' in content
assert ('(1)\n'
'e^{i\\pi} = 1
' in content)
assert ('(2)\n'
'e^{ix} = \\cos x + i\\sin x
' in content)
assert '\nn \\in \\mathbb N
' in content
assert '\na + 1 < b
' in content