[docs]  1# @Test suite for Sphinx extension source tracing functionality, TEST_EXT_1, test, [IMPL_LNK_1, IMPL_ONE_1, IMPL_MRST_1]
  2from collections.abc import Callable
  3from pathlib import Path
  4import shutil
  5
  6import pytest
  7from sphinx.testing.util import SphinxTestApp
  8
  9from sphinx_codelinks.analyse.projects import AnalyseProjects
 10from sphinx_codelinks.config import (
 11    SRC_TRACE_CACHE,
 12    CodeLinksConfig,
 13    check_configuration,
 14)
 15from sphinx_codelinks.sphinx_extension.source_tracing import set_config_to_sphinx
 16
 17
 18@pytest.mark.parametrize(
 19    ("codelinks_config", "result"),
 20    [
 21        (
 22            {
 23                "remote_url_field": 555,
 24                "local_url_field": 789,
 25                "set_local_url": "fdd",
 26                "set_remote_url": "TrueString",
 27                "projects": {
 28                    "dcdc": {
 29                        "remote_url_pattern": 44332,
 30                        "source_discover": {
 31                            "comment_type": "java",
 32                            "src_dir": ["../dcdc"],
 33                            "exclude": [123],
 34                            "include": [345],
 35                            "gitignore": "_true",
 36                        },
 37                        "analyse": {
 38                            "oneline_comment_style": {
 39                                "start_sequence": "[[",
 40                                "end_sequence": "]]",
 41                                "field_split_char": ",",
 42                                "needs_fields": [
 43                                    {
 44                                        "name": "title",
 45                                        "type": "list[]",
 46                                    },
 47                                    {
 48                                        "name": "type",
 49                                        "default": "impl",
 50                                        "type": "str",
 51                                    },
 52                                ],
 53                            },
 54                        },
 55                    }
 56                },
 57            },
 58            [
 59                "Project 'dcdc' has the following errors:",
 60                "Schema validation error in field 'exclude': 123 is not of type 'string'",
 61                "Schema validation error in field 'comment_type': 'java' is not one of ['cpp', 'cs', 'python', 'rust', 'yaml']",
 62                "Schema validation error in field 'gitignore': '_true' is not of type 'boolean'",
 63                "Schema validation error in field 'include': 345 is not of type 'string'",
 64                "Schema validation error in field 'src_dir': ['../dcdc'] is not of type 'string'",
 65                "Schema validation error in filed 'local_url_field': 789 is not of type 'string'",
 66                "Schema validation error in filed 'remote_url_field': 555 is not of type 'string'",
 67                "Schema validation error in filed 'set_local_url': 'fdd' is not of type 'boolean'",
 68                "Schema validation error in filed 'set_remote_url': 'TrueString' is not of type 'boolean'",
 69                "OneLineCommentStyle configuration errors:",
 70                "Schema validation error in need_fields 'title': 'list[]' is not one of ['str', 'list[str]']",
 71                "remote_url_pattern must be a string",
 72            ],
 73        ),
 74        (
 75            {
 76                "remote_url_field": "remote-url",
 77                "local_url_field": "local-url",
 78                "set_local_url": True,
 79                "set_remote_url": True,
 80                "projects": {
 81                    "dcdc": {
 82                        # intentionally not given "remote_url_pattern": "https://github.com/useblocks/sphinx-codelinks/blob/{commit}/{path}#L{line}",
 83                        "source_discover": {
 84                            "comment_type": "cpp",
 85                            "src_dir": "../dcdc",
 86                            "exclude": [],
 87                            "include": [],
 88                            "gitignore": True,
 89                        },
 90                        "analyse": {
 91                            "oneline_comment_style": {
 92                                "start_sequence": "[[",
 93                                "end_sequence": "]]",
 94                                "field_split_char": ",",
 95                                "needs_fields": [
 96                                    {
 97                                        "name": "title",
 98                                        "type": "str",
 99                                    },
100                                    {
101                                        "name": "type",
102                                        "default": "impl",
103                                        "type": "str",
104                                    },
105                                ],
106                            },
107                        },
108                    }
109                },
110            },
111            [
112                "Project 'dcdc' has the following errors:",
113                "remote_url_pattern must be given, as set_remote_url is enabled",
114            ],
115        ),
116    ],
117)
118def test_src_tracing_config_negative(
119    make_app: Callable[..., SphinxTestApp],
120    codelinks_config,
121    result,
122):
123    this_file_dir = Path(__file__).parent
124    sphinx_project = Path("data") / "sphinx"
125    app = make_app(srcdir=(this_file_dir / sphinx_project))
126    set_config_to_sphinx(codelinks_config, app.env.config)
127    codelinks_sphinx_config = CodeLinksConfig.from_sphinx(app.env.config)
128    errors = check_configuration(codelinks_sphinx_config)
129    assert sorted(errors) == sorted(result)
130
131
132def test_src_tracing_config_positive(make_app: Callable[..., SphinxTestApp], tmp_path):
133    codelinks_config = {
134        "remote_url_field": "remote-url",
135        "local_url_field": "local-url",
136        "set_local_url": True,
137        "set_remote_url": True,
138        "outdir": tmp_path,
139        "projects": {
140            "dcdc": {
141                "source_discover": {
142                    "comment_type": "cpp",
143                    "src_dir": "../dcdc",
144                    "exclude": ["**/*.hpp"],
145                    "include": ["**/*.cpp"],
146                    "gitignore": True,
147                },
148                "remote_url_pattern": "https://github.com/useblocks/sphinx-codelinks/blob/{commit}/{path}#L{line}",
149                "analyse": {
150                    "oneline_comment_style": {
151                        "start_sequence": "[[",
152                        "end_sequence": "]]",
153                        "field_split_char": ",",
154                        "needs_fields": [
155                            {
156                                "name": "title",
157                                "type": "str",
158                            },
159                            {
160                                "name": "type",
161                                "default": "impl",
162                                "type": "str",
163                            },
164                        ],
165                    },
166                },
167            }
168        },
169    }
170    this_file_dir = Path(__file__).parent
171    sphinx_project = Path("data") / "sphinx"
172    app = make_app(srcdir=(this_file_dir / sphinx_project))
173    set_config_to_sphinx(codelinks_config, app.env.config)
174    codelinks_sphinx_config = CodeLinksConfig.from_sphinx(app.env.config)
175    errors = check_configuration(codelinks_sphinx_config)
176    assert not errors
177
178
179@pytest.mark.parametrize(
180    ("sphinx_project", "source_code"),
181    [
182        (Path("data") / "sphinx", Path("data") / "dcdc"),
183        (
184            Path("doc_test") / "recursive_dirs",
185            Path("doc_test") / "recursive_dirs" / "dummy_src_lv1",
186        ),
187        (
188            Path("doc_test") / "minimum_config",
189            Path("doc_test") / "minimum_config",
190        ),
191        (
192            Path("doc_test") / "id_required",
193            Path("doc_test") / "id_required",
194        ),
195    ],
196)
197def test_build_html(
198    tmpdir: Path,
199    make_app: Callable[..., SphinxTestApp],
200    sphinx_project,
201    source_code,
202    snapshot_doctree,
203):
204    this_file_dir = Path(__file__).parent
205
206    sphinx_src_dir = tmpdir / sphinx_project
207    shutil.copytree(
208        this_file_dir / sphinx_project,
209        sphinx_src_dir,
210        dirs_exist_ok=True,
211    )
212    shutil.copytree(
213        this_file_dir / source_code,
214        tmpdir / source_code,
215        dirs_exist_ok=True,
216    )
217
218    app: SphinxTestApp = make_app(
219        srcdir=Path(sphinx_src_dir),
220        freshenv=True,
221    )
222    app.build()
223
224    html = Path(app.outdir, "index.html").read_text()
225    assert html
226
227    warnings = AnalyseProjects.load_warnings(Path(app.outdir) / SRC_TRACE_CACHE)
228    assert not warnings
229
230    assert app.env.get_doctree("index") == snapshot_doctree