1""" 2 test_ext_todo 3 ~~~~~~~~~~~~~ 4 5 Test sphinx.ext.todo extension. 6 7 :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. 8 :license: BSD, see LICENSE for details. 9""" 10 11import re 12 13import pytest 14 15from sphinx.util import docutils 16 17 18@pytest.mark.skipif(docutils.__version_info__ < (0, 13), 19 reason='docutils-0.13 or above is required') 20@pytest.mark.sphinx('html', testroot='ext-todo', freshenv=True, 21 confoverrides={'todo_include_todos': True, 'todo_emit_warnings': True}) 22def test_todo(app, status, warning): 23 todos = [] 24 25 def on_todo_defined(app, node): 26 todos.append(node) 27 28 app.connect('todo-defined', on_todo_defined) 29 app.builder.build_all() 30 31 # check todolist 32 content = (app.outdir / 'index.html').read_text() 33 assert ('<p class="admonition-title">Todo</p>\n' 34 '<p>todo in foo</p>') in content 35 36 assert ('<p class="admonition-title">Todo</p>\n' 37 '<p>todo in bar</p>') in content 38 39 # check todo 40 content = (app.outdir / 'foo.html').read_text() 41 assert ('<p class="admonition-title">Todo</p>\n' 42 '<p>todo in foo</p>') in content 43 44 assert ('<p class="admonition-title">Todo</p>\n' 45 '<p>todo in param field</p>') in content 46 47 # check emitted warnings 48 assert 'WARNING: TODO entry found: todo in foo' in warning.getvalue() 49 assert 'WARNING: TODO entry found: todo in bar' in warning.getvalue() 50 51 # check handled event 52 assert len(todos) == 3 53 assert {todo[1].astext() for todo in todos} == {'todo in foo', 54 'todo in bar', 55 'todo in param field'} 56 57 58@pytest.mark.sphinx('html', testroot='ext-todo', freshenv=True, 59 confoverrides={'todo_include_todos': False, 'todo_emit_warnings': True}) 60def test_todo_not_included(app, status, warning): 61 todos = [] 62 63 def on_todo_defined(app, node): 64 todos.append(node) 65 66 app.connect('todo-defined', on_todo_defined) 67 app.builder.build_all() 68 69 # check todolist 70 content = (app.outdir / 'index.html').read_text() 71 assert ('<p class="admonition-title">Todo</p>\n' 72 '<p>todo in foo</p>') not in content 73 74 assert ('<p class="admonition-title">Todo</p>\n' 75 '<p>todo in bar</p>') not in content 76 77 # check todo 78 content = (app.outdir / 'foo.html').read_text() 79 assert ('<p class="admonition-title">Todo</p>\n' 80 '<p>todo in foo</p>') not in content 81 82 # check emitted warnings 83 assert 'WARNING: TODO entry found: todo in foo' in warning.getvalue() 84 assert 'WARNING: TODO entry found: todo in bar' in warning.getvalue() 85 86 # check handled event 87 assert len(todos) == 3 88 assert {todo[1].astext() for todo in todos} == {'todo in foo', 89 'todo in bar', 90 'todo in param field'} 91 92 93@pytest.mark.sphinx('latex', testroot='ext-todo', freshenv=True, 94 confoverrides={'todo_include_todos': True}) 95def test_todo_valid_link(app, status, warning): 96 """ 97 Test that the inserted "original entry" links for todo items have a target 98 that exists in the LaTeX output. The target was previously incorrectly 99 omitted (GitHub issue #1020). 100 """ 101 102 # Ensure the LaTeX output is built. 103 app.builder.build_all() 104 105 content = (app.outdir / 'python.tex').read_text() 106 107 # Look for the link to foo. Note that there are two of them because the 108 # source document uses todolist twice. We could equally well look for links 109 # to bar. 110 link = (r'{\\hyperref\[\\detokenize{(.*?foo.*?)}]{\\sphinxcrossref{' 111 r'\\sphinxstyleemphasis{original entry}}}}') 112 m = re.findall(link, content) 113 assert len(m) == 4 114 target = m[0] 115 116 # Look for the targets of this link. 117 labels = re.findall(r'\\label{\\detokenize{([^}]*)}}', content) 118 matched = [l for l in labels if l == target] 119 120 # If everything is correct we should have exactly one target. 121 assert len(matched) == 1 122