From b077bac502e4045b91239defed0903d6f531aab0 Mon Sep 17 00:00:00 2001 From: Chris Sewell Date: Mon, 28 Oct 2024 11:44:37 +0000 Subject: [PATCH 01/11] =?UTF-8?q?=F0=9F=90=9B=20FIX=20needflow=20graphviz?= =?UTF-8?q?=20links?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/directives/needflow.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/directives/needflow.rst b/docs/directives/needflow.rst index 2b506153b..528e9be25 100644 --- a/docs/directives/needflow.rst +++ b/docs/directives/needflow.rst @@ -517,3 +517,12 @@ common filters * :ref:`option_types` * :ref:`option_filter` +.. needflow:: Engineering plan to develop a car + :alt: Engineering plan to develop a car + :root_id: T_CAR + :config: tutorial + :show_link_names: + :border_color: + [status == 'open']:FF0000, + [status == 'in progress']:0000FF, + [status == 'closed']:00FF00 \ No newline at end of file From 1d443124b677fcecf95c48896cfb14972fe13c34 Mon Sep 17 00:00:00 2001 From: Chris Sewell Date: Mon, 28 Oct 2024 15:09:38 +0000 Subject: [PATCH 02/11] update --- docs/directives/needflow.rst | 10 ------- docs/directives/other/page.rst | 14 ++++++++++ sphinx_needs/directives/needflow/_graphviz.py | 27 ++++++++++++++++--- 3 files changed, 37 insertions(+), 14 deletions(-) create mode 100644 docs/directives/other/page.rst diff --git a/docs/directives/needflow.rst b/docs/directives/needflow.rst index 528e9be25..6ffea58a4 100644 --- a/docs/directives/needflow.rst +++ b/docs/directives/needflow.rst @@ -516,13 +516,3 @@ common filters * :ref:`option_tags` * :ref:`option_types` * :ref:`option_filter` - -.. needflow:: Engineering plan to develop a car - :alt: Engineering plan to develop a car - :root_id: T_CAR - :config: tutorial - :show_link_names: - :border_color: - [status == 'open']:FF0000, - [status == 'in progress']:0000FF, - [status == 'closed']:00FF00 \ No newline at end of file diff --git a/docs/directives/other/page.rst b/docs/directives/other/page.rst new file mode 100644 index 000000000..609a614a6 --- /dev/null +++ b/docs/directives/other/page.rst @@ -0,0 +1,14 @@ +:orphan: + +Other +===== + +.. needflow:: Engineering plan to develop a car yep + :alt: Engineering plan to develop a car + :root_id: T_CAR + :config: tutorial + :engine: graphviz + :border_color: + [status == 'open']:FF0069, + [status == 'in progress']:0000FF, + [status == 'closed']:00FF00 diff --git a/sphinx_needs/directives/needflow/_graphviz.py b/sphinx_needs/directives/needflow/_graphviz.py index aa2572921..0d88f1b5c 100644 --- a/sphinx_needs/directives/needflow/_graphviz.py +++ b/sphinx_needs/directives/needflow/_graphviz.py @@ -20,6 +20,7 @@ from sphinx_needs.diagrams_common import calculate_link from sphinx_needs.directives.needflow._directive import NeedflowGraphiz from sphinx_needs.directives.utils import no_needs_found_paragraph +from sphinx_needs.errors import NoUri from sphinx_needs.filter_common import ( filter_single_need, process_filters, @@ -159,7 +160,7 @@ def process_needflow_graphviz( node, needs_view, needs_config, - lambda n: calculate_link(app, n, fromdocname, relative="."), + lambda n: _get_link_to_need(app, fromdocname, n), id_comp_to_need, rendered_nodes, ) @@ -191,6 +192,24 @@ def process_needflow_graphviz( node.parent.parent.insert(node.parent.parent.index(node.parent) + 1, code) +def _get_link_to_need( + app: Sphinx, docname: str, need_info: NeedsInfoType +) -> str | None: + """Compute the link to a need, relative to a document.""" + if need_info["is_external"]: + return None # TODO: external links + elif to_docname := need_info["docname"]: + try: + return ( + app.builder.get_relative_uri(docname, to_docname) + + "#" + + need_info["id_complete"] + ) + except NoUri: + return None + return None + + class _RenderedNode(TypedDict): cluster_id: str | None need: NeedsInfoType @@ -206,7 +225,7 @@ def _render_node( node: NeedflowGraphiz, needs_view: NeedsView, config: NeedsSphinxConfig, - calc_link: Callable[[NeedsInfoType], str], + calc_link: Callable[[NeedsInfoType], str | None], id_comp_to_need: dict[str, NeedsInfoType], rendered_nodes: dict[str, _RenderedNode], subgraph: bool = True, @@ -285,7 +304,7 @@ def _render_subgraph( node: NeedflowGraphiz, needs_view: NeedsView, config: NeedsSphinxConfig, - calc_link: Callable[[NeedsInfoType], str], + calc_link: Callable[[NeedsInfoType], str | None], id_comp_to_need: dict[str, NeedsInfoType], rendered_nodes: dict[str, _RenderedNode], ) -> str: @@ -606,7 +625,7 @@ def html_visit_needflow_graphviz(self: HTML5Translator, node: NeedflowGraphiz) - log_warning(LOGGER, "Content has not been resolved", "needflow", location=node) raise nodes.SkipNode attrributes = node.attributes - format = self.builder.config.graphviz_output_format + format: Literal["png", "svg"] = self.builder.config.graphviz_output_format if format not in ("png", "svg"): log_warning( LOGGER, From 0d7e699895d373a5db89f54a4be5ac6a7bc8d724 Mon Sep 17 00:00:00 2001 From: Chris Sewell Date: Mon, 28 Oct 2024 15:10:18 +0000 Subject: [PATCH 03/11] Update _graphviz.py --- sphinx_needs/directives/needflow/_graphviz.py | 1 - 1 file changed, 1 deletion(-) diff --git a/sphinx_needs/directives/needflow/_graphviz.py b/sphinx_needs/directives/needflow/_graphviz.py index 0d88f1b5c..dc27104b4 100644 --- a/sphinx_needs/directives/needflow/_graphviz.py +++ b/sphinx_needs/directives/needflow/_graphviz.py @@ -17,7 +17,6 @@ from sphinx_needs.config import LinkOptionsType, NeedsSphinxConfig from sphinx_needs.data import NeedsInfoType, SphinxNeedsData from sphinx_needs.debug import measure_time -from sphinx_needs.diagrams_common import calculate_link from sphinx_needs.directives.needflow._directive import NeedflowGraphiz from sphinx_needs.directives.utils import no_needs_found_paragraph from sphinx_needs.errors import NoUri From d8df2017588534c1983dab0d3d70cd7f4da7d933 Mon Sep 17 00:00:00 2001 From: Chris Sewell Date: Mon, 28 Oct 2024 15:12:39 +0000 Subject: [PATCH 04/11] Delete page.rst --- docs/directives/other/page.rst | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 docs/directives/other/page.rst diff --git a/docs/directives/other/page.rst b/docs/directives/other/page.rst deleted file mode 100644 index 609a614a6..000000000 --- a/docs/directives/other/page.rst +++ /dev/null @@ -1,14 +0,0 @@ -:orphan: - -Other -===== - -.. needflow:: Engineering plan to develop a car yep - :alt: Engineering plan to develop a car - :root_id: T_CAR - :config: tutorial - :engine: graphviz - :border_color: - [status == 'open']:FF0069, - [status == 'in progress']:0000FF, - [status == 'closed']:00FF00 From b48ddc9e756f479d9c4c975d5805eb14808574f6 Mon Sep 17 00:00:00 2001 From: Chris Sewell Date: Mon, 28 Oct 2024 15:20:30 +0000 Subject: [PATCH 05/11] Update _graphviz.py --- sphinx_needs/directives/needflow/_graphviz.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sphinx_needs/directives/needflow/_graphviz.py b/sphinx_needs/directives/needflow/_graphviz.py index dc27104b4..b17adc599 100644 --- a/sphinx_needs/directives/needflow/_graphviz.py +++ b/sphinx_needs/directives/needflow/_graphviz.py @@ -4,6 +4,7 @@ import textwrap from functools import lru_cache from typing import Callable, Literal, TypedDict +from urllib.parse import urlparse from docutils import nodes from sphinx.application import Sphinx @@ -196,11 +197,12 @@ def _get_link_to_need( ) -> str | None: """Compute the link to a need, relative to a document.""" if need_info["is_external"]: - return None # TODO: external links - elif to_docname := need_info["docname"]: + if need_info["external_url"] and urlparse(need_info["external_url"]).scheme: + return need_info["external_url"] + elif need_info["docname"]: try: return ( - app.builder.get_relative_uri(docname, to_docname) + app.builder.get_relative_uri(docname, need_info["docname"]) + "#" + need_info["id_complete"] ) From 5892b083c29522bff403a459a0143816aaf78ede Mon Sep 17 00:00:00 2001 From: Chris Sewell Date: Mon, 28 Oct 2024 15:22:52 +0000 Subject: [PATCH 06/11] Update needflow.rst --- docs/directives/needflow.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/directives/needflow.rst b/docs/directives/needflow.rst index 6ffea58a4..2b506153b 100644 --- a/docs/directives/needflow.rst +++ b/docs/directives/needflow.rst @@ -516,3 +516,4 @@ common filters * :ref:`option_tags` * :ref:`option_types` * :ref:`option_filter` + From be82a44f886e9caa249bf43bb8dc72dd4f72dbbe Mon Sep 17 00:00:00 2001 From: Chris Sewell Date: Mon, 28 Oct 2024 15:29:03 +0000 Subject: [PATCH 07/11] Update _graphviz.py --- sphinx_needs/directives/needflow/_graphviz.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sphinx_needs/directives/needflow/_graphviz.py b/sphinx_needs/directives/needflow/_graphviz.py index b17adc599..97f13db0c 100644 --- a/sphinx_needs/directives/needflow/_graphviz.py +++ b/sphinx_needs/directives/needflow/_graphviz.py @@ -195,7 +195,13 @@ def process_needflow_graphviz( def _get_link_to_need( app: Sphinx, docname: str, need_info: NeedsInfoType ) -> str | None: - """Compute the link to a need, relative to a document.""" + """Compute the link to a need, relative to a document. + + It is of note that the links are computed relative to the document that the graph is in. + For PNGs, the links are defined as https://developer.mozilla.org/en-US/docs/Web/HTML/Element/map in the document, so this correct. + For SVGs, the graphs are extracted to external files, and in this case the links are modified to be relative to the SVG file + (from sphinx 7.2 onwards, see: https://github.com/sphinx-doc/sphinx/pull/11078) + """ if need_info["is_external"]: if need_info["external_url"] and urlparse(need_info["external_url"]).scheme: return need_info["external_url"] From 6ff362fa41d6bed9b2346fe1e6d183b8baa0b01c Mon Sep 17 00:00:00 2001 From: Chris Sewell Date: Mon, 28 Oct 2024 16:39:32 +0000 Subject: [PATCH 08/11] fix --- sphinx_needs/directives/needflow/_graphviz.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sphinx_needs/directives/needflow/_graphviz.py b/sphinx_needs/directives/needflow/_graphviz.py index 97f13db0c..39b05805a 100644 --- a/sphinx_needs/directives/needflow/_graphviz.py +++ b/sphinx_needs/directives/needflow/_graphviz.py @@ -207,13 +207,13 @@ def _get_link_to_need( return need_info["external_url"] elif need_info["docname"]: try: - return ( - app.builder.get_relative_uri(docname, need_info["docname"]) - + "#" - + need_info["id_complete"] - ) + rel_uri = app.builder.get_relative_uri(docname, need_info["docname"]) + if not rel_uri: + # svg relative path fix cannot yet handle empty paths https://github.com/sphinx-doc/sphinx/issues/13078 + rel_uri = app.builder.get_target_uri(docname.split("/")[-1]) except NoUri: return None + return rel_uri + "#" + need_info["id_complete"] return None From 6440b386514596def16ecd83445c5e06b8c1fc48 Mon Sep 17 00:00:00 2001 From: Chris Sewell Date: Mon, 28 Oct 2024 17:10:06 +0000 Subject: [PATCH 09/11] update tests --- docs/index.rst | 7 ++ tests/test_needflow.py | 144 +++++++++++++++++++++-------------------- 2 files changed, 82 insertions(+), 69 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index e71c75452..2595cb31a 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -4,6 +4,13 @@ Introduction ============ +.. spec:: blah blah + :id: SPEC_1234 + +.. needflow:: + :engine: graphviz + :root_id: SPEC_1234 + .. grid:: :gutter: 2 3 3 3 :margin: 4 4 1 2 diff --git a/tests/test_needflow.py b/tests/test_needflow.py index a0aa492eb..4681d1b22 100644 --- a/tests/test_needflow.py +++ b/tests/test_needflow.py @@ -36,6 +36,7 @@ def _get_svg(config: Config, outdir: Path, file: str, id: str) -> str: }, }, ], + ids=["plantuml", "graphviz"], indirect=True, ) def test_doc_build_html(test_app): @@ -52,28 +53,28 @@ def test_doc_build_html(test_app): outdir = Path(app.outdir) svg = _get_svg(app.config, outdir, "index.html", "needflow-index-0") for link in ( - "./index.html#SPEC_1", - "./index.html#SPEC_2", - "./index.html#STORY_1", - "./index.html#STORY_1.1", - "./index.html#STORY_1.2", - "./index.html#STORY_1.subspec", - "./index.html#STORY_2", - "./index.html#STORY_2.another_one", + '"../index.html#SPEC_1"', + '"../index.html#SPEC_2"', + '"../index.html#STORY_1"', + '"../index.html#STORY_1.1"', + '"../index.html#STORY_1.2"', + '"../index.html#STORY_1.subspec"', + '"../index.html#STORY_2"', + '"../index.html#STORY_2.another_one"', ): assert link in svg assert "No needs passed the filters" in Path(app.outdir, "index.html").read_text() svg = _get_svg(app.config, outdir, "page.html", "needflow-page-0") for link in ( - "./index.html#SPEC_1", - "./index.html#SPEC_2", - "./index.html#STORY_1", - "./index.html#STORY_1.1", - "./index.html#STORY_1.2", - "./index.html#STORY_1.subspec", - "./index.html#STORY_2", - "./index.html#STORY_2.another_one", + '"../index.html#SPEC_1"', + '"../index.html#SPEC_2"', + '"../index.html#STORY_1"', + '"../index.html#STORY_1.1"', + '"../index.html#STORY_1.2"', + '"../index.html#STORY_1.subspec"', + '"../index.html#STORY_2"', + '"../index.html#STORY_2.another_one"', ): assert link in svg @@ -112,6 +113,7 @@ def test_doc_build_html(test_app): }, }, ], + ids=["plantuml", "graphviz"], indirect=True, ) def test_doc_build_needflow_incl_child_needs(test_app): @@ -129,17 +131,17 @@ def test_doc_build_needflow_incl_child_needs(test_app): svg = _get_svg(app.config, outdir, "index.html", "needflow-index-0") for link in ( - "./index.html#STORY_1", - "./index.html#STORY_1.1", - "./index.html#STORY_1.2", - "./index.html#STORY_2", - "./index.html#STORY_2.3", - "./index.html#SPEC_1", - "./index.html#SPEC_2", - "./index.html#SPEC_3", - "./index.html#SPEC_4", - "./index.html#STORY_3", - "./index.html#SPEC_5", + '"../index.html#STORY_1"', + '"../index.html#STORY_1.1"', + '"../index.html#STORY_1.2"', + '"../index.html#STORY_2"', + '"../index.html#STORY_2.3"', + '"../index.html#SPEC_1"', + '"../index.html#SPEC_2"', + '"../index.html#SPEC_3"', + '"../index.html#SPEC_4"', + '"../index.html#STORY_3"', + '"../index.html#SPEC_5"', ): assert link in svg @@ -149,18 +151,18 @@ def test_doc_build_needflow_incl_child_needs(test_app): "single_parent_need_filer.html", "needflow-single_parent_need_filer-0", ) - assert "./index.html#STORY_3" in svg + assert '"../index.html#STORY_3"' in svg for link in ( - "./index.html#STORY_1", - "./index.html#STORY_1.1", - "./index.html#STORY_1.2", - "./index.html#STORY_2", - "./index.html#STORY_2.3", - "./index.html#SPEC_1", - "./index.html#SPEC_2", - "./index.html#SPEC_3", - "./index.html#SPEC_4", - "./index.html#SPEC_5", + '"../index.html#STORY_1"', + '"../index.html#STORY_1.1"', + '"../index.html#STORY_1.2"', + '"../index.html#STORY_2"', + '"../index.html#STORY_2.3"', + '"../index.html#SPEC_1"', + '"../index.html#SPEC_2"', + '"../index.html#SPEC_3"', + '"../index.html#SPEC_4"', + '"../index.html#SPEC_5"', ): assert link not in svg @@ -170,18 +172,18 @@ def test_doc_build_needflow_incl_child_needs(test_app): "single_child_with_child_need_filter.html", "needflow-single_child_with_child_need_filter-0", ) - assert "./index.html#STORY_2" in svg + assert '"../index.html#STORY_2"' in svg for link in ( - "./index.html#STORY_1", - "./index.html#STORY_1.1", - "./index.html#STORY_1.2", - "./index.html#STORY_2.3", - "./index.html#SPEC_1", - "./index.html#SPEC_2", - "./index.html#SPEC_3", - "./index.html#SPEC_4", - "./index.html#STORY_3", - "./index.html#SPEC_5", + '"../index.html#STORY_1"', + '"../index.html#STORY_1.1"', + '"../index.html#STORY_1.2"', + '"../index.html#STORY_2.3"', + '"../index.html#SPEC_1"', + '"../index.html#SPEC_2"', + '"../index.html#SPEC_3"', + '"../index.html#SPEC_4"', + '"../index.html#STORY_3"', + '"../index.html#SPEC_5"', ): assert link not in svg @@ -191,34 +193,38 @@ def test_doc_build_needflow_incl_child_needs(test_app): "single_child_need_filter.html", "needflow-single_child_need_filter-0", ) - assert "./index.html#SPEC_1" in svg + assert '"../index.html#SPEC_1"' in svg for link in ( - "./index.html#STORY_1", - "./index.html#STORY_1.1", - "./index.html#STORY_1.2", - "./index.html#STORY_2", - "./index.html#STORY_2.3", - "./index.html#SPEC_2", - "./index.html#SPEC_3", - "./index.html#SPEC_4", - "./index.html#STORY_3", - "./index.html#SPEC_5", + '"../index.html#STORY_1"', + '"../index.html#STORY_1.1"', + '"../index.html#STORY_1.2"', + '"../index.html#STORY_2"', + '"../index.html#STORY_2.3"', + '"../index.html#SPEC_2"', + '"../index.html#SPEC_3"', + '"../index.html#SPEC_4"', + '"../index.html#STORY_3"', + '"../index.html#SPEC_5"', ): assert link not in svg svg = _get_svg( app.config, outdir, "grandy_and_child.html", "needflow-grandy_and_child-0" ) - for link in ("./index.html#STORY_1", "./index.html#SPEC_1", "./index.html#SPEC_2"): + for link in ( + '"../index.html#STORY_1"', + '"../index.html#SPEC_1"', + '"../index.html#SPEC_2"', + ): assert link in svg for link in ( - "./index.html#STORY_1.1", - "./index.html#STORY_1.2", - "./index.html#STORY_2", - "./index.html#STORY_2.3", - "./index.html#SPEC_3", - "./index.html#SPEC_4", - "./index.html#STORY_3", - "./index.html#SPEC_5", + '"../index.html#STORY_1.1"', + '"../index.html#STORY_1.2"', + '"../index.html#STORY_2"', + '"../index.html#STORY_2.3"', + '"../index.html#SPEC_3"', + '"../index.html#SPEC_4"', + '"../index.html#STORY_3"', + '"../index.html#SPEC_5"', ): assert link not in svg From 7b36f2710561af69122061412c18868d6e3f973f Mon Sep 17 00:00:00 2001 From: Chris Sewell Date: Mon, 28 Oct 2024 17:10:33 +0000 Subject: [PATCH 10/11] Update index.rst --- docs/index.rst | 7 ------- 1 file changed, 7 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 2595cb31a..e71c75452 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -4,13 +4,6 @@ Introduction ============ -.. spec:: blah blah - :id: SPEC_1234 - -.. needflow:: - :engine: graphviz - :root_id: SPEC_1234 - .. grid:: :gutter: 2 3 3 3 :margin: 4 4 1 2 From 25af27cffbecccfd3d49c39fb3030195f8bdadd9 Mon Sep 17 00:00:00 2001 From: Chris Sewell Date: Mon, 28 Oct 2024 17:26:23 +0000 Subject: [PATCH 11/11] Update test_needflow.py --- tests/test_needflow.py | 257 ++++++++++++++++++++++------------------- 1 file changed, 137 insertions(+), 120 deletions(-) diff --git a/tests/test_needflow.py b/tests/test_needflow.py index 4681d1b22..66afa968c 100644 --- a/tests/test_needflow.py +++ b/tests/test_needflow.py @@ -3,6 +3,7 @@ import pytest from lxml import html as html_parser +from sphinx import version_info from sphinx.config import Config from sphinx.util.console import strip_colors @@ -51,32 +52,42 @@ def test_doc_build_html(test_app): assert warnings == "" outdir = Path(app.outdir) + svg = _get_svg(app.config, outdir, "index.html", "needflow-index-0") - for link in ( - '"../index.html#SPEC_1"', - '"../index.html#SPEC_2"', - '"../index.html#STORY_1"', - '"../index.html#STORY_1.1"', - '"../index.html#STORY_1.2"', - '"../index.html#STORY_1.subspec"', - '"../index.html#STORY_2"', - '"../index.html#STORY_2.another_one"', - ): - assert link in svg + + if test_app.config.needs_flow_engine == "graphviz" and version_info < (7, 2): + pass # links will be wrong due to https://github.com/sphinx-doc/sphinx/pull/11078 + else: + for link in ( + '"../index.html#SPEC_1"', + '"../index.html#SPEC_2"', + '"../index.html#STORY_1"', + '"../index.html#STORY_1.1"', + '"../index.html#STORY_1.2"', + '"../index.html#STORY_1.subspec"', + '"../index.html#STORY_2"', + '"../index.html#STORY_2.another_one"', + ): + assert link in svg + assert "No needs passed the filters" in Path(app.outdir, "index.html").read_text() svg = _get_svg(app.config, outdir, "page.html", "needflow-page-0") - for link in ( - '"../index.html#SPEC_1"', - '"../index.html#SPEC_2"', - '"../index.html#STORY_1"', - '"../index.html#STORY_1.1"', - '"../index.html#STORY_1.2"', - '"../index.html#STORY_1.subspec"', - '"../index.html#STORY_2"', - '"../index.html#STORY_2.another_one"', - ): - assert link in svg + + if test_app.config.needs_flow_engine == "graphviz" and version_info < (7, 2): + pass # links will be wrong due to https://github.com/sphinx-doc/sphinx/pull/11078 + else: + for link in ( + '"../index.html#SPEC_1"', + '"../index.html#SPEC_2"', + '"../index.html#STORY_1"', + '"../index.html#STORY_1.1"', + '"../index.html#STORY_1.2"', + '"../index.html#STORY_1.subspec"', + '"../index.html#STORY_2"', + '"../index.html#STORY_2.another_one"', + ): + assert link in svg svg = _get_svg( app.config, @@ -84,7 +95,7 @@ def test_doc_build_html(test_app): "needflow_with_root_id.html", "needflow-needflow_with_root_id-0", ) - print(svg) + for link in ("SPEC_1", "STORY_1", "STORY_2"): assert link in svg @@ -130,101 +141,107 @@ def test_doc_build_needflow_incl_child_needs(test_app): outdir = Path(app.outdir) svg = _get_svg(app.config, outdir, "index.html", "needflow-index-0") - for link in ( - '"../index.html#STORY_1"', - '"../index.html#STORY_1.1"', - '"../index.html#STORY_1.2"', - '"../index.html#STORY_2"', - '"../index.html#STORY_2.3"', - '"../index.html#SPEC_1"', - '"../index.html#SPEC_2"', - '"../index.html#SPEC_3"', - '"../index.html#SPEC_4"', - '"../index.html#STORY_3"', - '"../index.html#SPEC_5"', - ): - assert link in svg - - svg = _get_svg( - app.config, - outdir, - "single_parent_need_filer.html", - "needflow-single_parent_need_filer-0", - ) - assert '"../index.html#STORY_3"' in svg - for link in ( - '"../index.html#STORY_1"', - '"../index.html#STORY_1.1"', - '"../index.html#STORY_1.2"', - '"../index.html#STORY_2"', - '"../index.html#STORY_2.3"', - '"../index.html#SPEC_1"', - '"../index.html#SPEC_2"', - '"../index.html#SPEC_3"', - '"../index.html#SPEC_4"', - '"../index.html#SPEC_5"', - ): - assert link not in svg - svg = _get_svg( - app.config, - outdir, - "single_child_with_child_need_filter.html", - "needflow-single_child_with_child_need_filter-0", - ) - assert '"../index.html#STORY_2"' in svg - for link in ( - '"../index.html#STORY_1"', - '"../index.html#STORY_1.1"', - '"../index.html#STORY_1.2"', - '"../index.html#STORY_2.3"', - '"../index.html#SPEC_1"', - '"../index.html#SPEC_2"', - '"../index.html#SPEC_3"', - '"../index.html#SPEC_4"', - '"../index.html#STORY_3"', - '"../index.html#SPEC_5"', - ): - assert link not in svg - - svg = _get_svg( - app.config, - outdir, - "single_child_need_filter.html", - "needflow-single_child_need_filter-0", - ) - assert '"../index.html#SPEC_1"' in svg - for link in ( - '"../index.html#STORY_1"', - '"../index.html#STORY_1.1"', - '"../index.html#STORY_1.2"', - '"../index.html#STORY_2"', - '"../index.html#STORY_2.3"', - '"../index.html#SPEC_2"', - '"../index.html#SPEC_3"', - '"../index.html#SPEC_4"', - '"../index.html#STORY_3"', - '"../index.html#SPEC_5"', - ): - assert link not in svg - - svg = _get_svg( - app.config, outdir, "grandy_and_child.html", "needflow-grandy_and_child-0" - ) - for link in ( - '"../index.html#STORY_1"', - '"../index.html#SPEC_1"', - '"../index.html#SPEC_2"', - ): - assert link in svg - for link in ( - '"../index.html#STORY_1.1"', - '"../index.html#STORY_1.2"', - '"../index.html#STORY_2"', - '"../index.html#STORY_2.3"', - '"../index.html#SPEC_3"', - '"../index.html#SPEC_4"', - '"../index.html#STORY_3"', - '"../index.html#SPEC_5"', - ): - assert link not in svg + if test_app.config.needs_flow_engine == "graphviz" and version_info < (7, 2): + pass # links will be wrong due to https://github.com/sphinx-doc/sphinx/pull/11078 + else: + for link in ( + '"../index.html#STORY_1"', + '"../index.html#STORY_1.1"', + '"../index.html#STORY_1.2"', + '"../index.html#STORY_2"', + '"../index.html#STORY_2.3"', + '"../index.html#SPEC_1"', + '"../index.html#SPEC_2"', + '"../index.html#SPEC_3"', + '"../index.html#SPEC_4"', + '"../index.html#STORY_3"', + '"../index.html#SPEC_5"', + ): + assert link in svg + + svg = _get_svg( + app.config, + outdir, + "single_parent_need_filer.html", + "needflow-single_parent_need_filer-0", + ) + + assert '"../index.html#STORY_3"' in svg + for link in ( + '"../index.html#STORY_1"', + '"../index.html#STORY_1.1"', + '"../index.html#STORY_1.2"', + '"../index.html#STORY_2"', + '"../index.html#STORY_2.3"', + '"../index.html#SPEC_1"', + '"../index.html#SPEC_2"', + '"../index.html#SPEC_3"', + '"../index.html#SPEC_4"', + '"../index.html#SPEC_5"', + ): + assert link not in svg + + svg = _get_svg( + app.config, + outdir, + "single_child_with_child_need_filter.html", + "needflow-single_child_with_child_need_filter-0", + ) + + assert '"../index.html#STORY_2"' in svg + for link in ( + '"../index.html#STORY_1"', + '"../index.html#STORY_1.1"', + '"../index.html#STORY_1.2"', + '"../index.html#STORY_2.3"', + '"../index.html#SPEC_1"', + '"../index.html#SPEC_2"', + '"../index.html#SPEC_3"', + '"../index.html#SPEC_4"', + '"../index.html#STORY_3"', + '"../index.html#SPEC_5"', + ): + assert link not in svg + + svg = _get_svg( + app.config, + outdir, + "single_child_need_filter.html", + "needflow-single_child_need_filter-0", + ) + assert '"../index.html#SPEC_1"' in svg + for link in ( + '"../index.html#STORY_1"', + '"../index.html#STORY_1.1"', + '"../index.html#STORY_1.2"', + '"../index.html#STORY_2"', + '"../index.html#STORY_2.3"', + '"../index.html#SPEC_2"', + '"../index.html#SPEC_3"', + '"../index.html#SPEC_4"', + '"../index.html#STORY_3"', + '"../index.html#SPEC_5"', + ): + assert link not in svg + + svg = _get_svg( + app.config, outdir, "grandy_and_child.html", "needflow-grandy_and_child-0" + ) + for link in ( + '"../index.html#STORY_1"', + '"../index.html#SPEC_1"', + '"../index.html#SPEC_2"', + ): + assert link in svg + for link in ( + '"../index.html#STORY_1.1"', + '"../index.html#STORY_1.2"', + '"../index.html#STORY_2"', + '"../index.html#STORY_2.3"', + '"../index.html#SPEC_3"', + '"../index.html#SPEC_4"', + '"../index.html#STORY_3"', + '"../index.html#SPEC_5"', + ): + assert link not in svg