Repository: useblocks/sphinx-needs
Pull request #1296 (2024-09-12 10:12:16)

✨ add `tags` option for `list2need` directive
The list2need directive is updated to support tags definition at list level (affecting all items defined in the list)

The PR includes :
- updated code
- updated tests
- updated documentation

The update addresses the issue #1146



chrisjsewell: Cool cheers, I think this sounds good in principle, will get round to a proper review soon

Patch:
diff --git a/docs/directives/list2need.rst b/docs/directives/list2need.rst
index 99e21bab..924a3182 100644
--- a/docs/directives/list2need.rst
+++ b/docs/directives/list2need.rst
@@ -149,6 +149,26 @@ The amount of given link-types must be the amount of used levels minus 1.
        * (NEED-D)Recalculate hash and compare
 
 
+tags
+~~~~
+
+``tags`` sets tags globally to all items in the list.
+
+.. code-block:: rst
+
+   .. list2need::
+      :types: req, spec
+      :tags: A, B
+
+      * (NEED-A)Login user
+        * (NEED-B)Provide login screen
+        * (NEED-C)Create password hash
+          * (NEED-D)Recalculate hash and compare
+
+
+The tags ``A`` and ``B`` are attached to all ``NEED-A``, ``NEED-B``, ``NEED-C`` and ``NEED-D``.
+
+
 List examples
 -------------
 
diff --git a/sphinx_needs/directives/list2need.py b/sphinx_needs/directives/list2need.py
index 3f2a1d79..ec50b6b1 100644
--- a/sphinx_needs/directives/list2need.py
+++ b/sphinx_needs/directives/list2need.py
@@ -57,6 +57,7 @@ class List2NeedDirective(SphinxDirective):
         "delimiter": directives.unchanged,
         "presentation": directives.unchanged,
         "links-down": directives.unchanged,
+        "tags": directives.unchanged,
     }
 
     def run(self) -> Sequence[nodes.Node]:
@@ -106,6 +107,10 @@ class List2NeedDirective(SphinxDirective):
                     f"Unknown link configured: {down_link_raw}. "
                     f"Allowed are {', '.join(link_types)}"
                 )
+
+        # Retrieve tags defined at list level
+        tags = self.options.get("tags", "")
+
         list_needs = []
         # Storing the data in a sorted list
         for content_line in content_raw.split("\n"):
@@ -190,6 +195,16 @@ class List2NeedDirective(SphinxDirective):
                 list_need["title"] = OPTION_AREA_REGEX.sub("", list_need["title"])
                 list_need["content"] = OPTION_AREA_REGEX.sub("", list_need["content"])
 
+            # Add tags defined at list level (if exists) to the ones potentially defined in the content
+            if tags:
+                if "options" not in list_need:
+                    list_need["options"] = {}
+                current_tags = list_need["options"].get("tags", "")
+                if current_tags:
+                    list_need["options"]["tags"] = current_tags + "," + tags
+                else:
+                    list_need["options"]["tags"] = tags
+
             template = Template(NEED_TEMPLATE, autoescape=True)
 
             data = list_need


Test patch:
diff --git a/tests/__snapshots__/test_list2need.ambr b/tests/__snapshots__/test_list2need.ambr
new file mode 100644
index 00000000..6c44aa23
--- /dev/null
+++ b/tests/__snapshots__/test_list2need.ambr
@@ -0,0 +1,1453 @@
+# name: test_doc_list2need_html[test_app0]
+  dict({
+    'NEED-002': dict({
+      'arch': dict({
+      }),
+      'avatar': '',
+      'checks': list([
+      ]),
+      'checks_back': list([
+      ]),
+      'closed_at': '',
+      'collapse': False,
+      'completion': '',
+      'constraints': list([
+      ]),
+      'constraints_passed': True,
+      'constraints_results': dict({
+      }),
+      'content': '''
+        .. spec::  Sub-Need on level 2
+           :id: NEED-003
+           
+        
+           
+        
+        .. spec:: Another Sub-Need on level 2
+           :id: SP_69FFD
+           
+        
+           Where this sentence will be used
+           as content, the first one as title.
+        
+           .. test:: Sub-Need on level 3
+              :id: TC_EA5AF
+              
+           
+              With some rst-syntax supported for
+              the **content** by :ref:`test`
+      ''',
+      'created_at': '',
+      'delete': False,
+      'docname': 'index',
+      'doctype': '.rst',
+      'duration': '',
+      'external_css': 'external_link',
+      'external_url': None,
+      'full_title': 'Another Need example on level 1 with a given ID',
+      'has_dead_links': False,
+      'has_forbidden_dead_links': False,
+      'hide': False,
+      'id': 'NEED-002',
+      'id_complete': 'NEED-002',
+      'id_parent': 'NEED-002',
+      'id_prefix': '',
+      'is_external': False,
+      'is_modified': False,
+      'is_need': True,
+      'is_part': False,
+      'jinja_content': False,
+      'layout': '',
+      'lineno': 26,
+      'lineno_content': 32,
+      'links': list([
+      ]),
+      'links_back': list([
+      ]),
+      'max_amount': '',
+      'max_content_lines': '',
+      'modifications': 0,
+      'params': '',
+      'parent_need': '',
+      'parent_needs': list([
+      ]),
+      'parent_needs_back': list([
+        'NEED-003',
+        'SP_69FFD',
+      ]),
+      'parts': dict({
+      }),
+      'post_template': None,
+      'pre_template': None,
+      'prefix': '',
+      'query': '',
+      'section_name': 'TEST DOCUMENT LIST2NEED',
+      'sections': list([
+        'TEST DOCUMENT LIST2NEED',
+      ]),
+      'service': '',
+      'signature': '',
+      'specific': '',
+      'status': None,
+      'style': None,
+      'tags': list([
+      ]),
+      'template': None,
+      'title': 'Another Need example on level 1 with a given ID',
+      'triggers': list([
+      ]),
+      'triggers_back': list([
+      ]),
+      'type': 'story',
+      'type_color': '#BFD8D2',
+      'type_name': 'User Story',
+      'type_prefix': 'US_',
+      'type_style': 'node',
+      'updated_at': '',
+      'url': '',
+      'url_postfix': '',
+      'user': '',
+    }),
+    'NEED-003': dict({
+      'arch': dict({
+      }),
+      'avatar': '',
+      'checks': list([
+      ]),
+      'checks_back': list([
+      ]),
+      'closed_at': '',
+      'collapse': False,
+      'completion': '',
+      'constraints': list([
+      ]),
+      'constraints_passed': True,
+      'constraints_results': dict({
+      }),
+      'content': '',
+      'created_at': '',
+      'delete': False,
+      'docname': 'index',
+      'doctype': '.rst',
+      'duration': '',
+      'external_css': 'external_link',
+      'external_url': None,
+      'full_title': 'Sub-Need on level 2',
+      'has_dead_links': False,
+      'has_forbidden_dead_links': False,
+      'hide': False,
+      'id': 'NEED-003',
+      'id_complete': 'NEED-003',
+      'id_parent': 'NEED-003',
+      'id_prefix': '',
+      'is_external': False,
+      'is_modified': False,
+      'is_need': True,
+      'is_part': False,
+      'jinja_content': False,
+      'layout': '',
+      'lineno': 32,
+      'lineno_content': 35,
+      'links': list([
+      ]),
+      'links_back': list([
+      ]),
+      'max_amount': '',
+      'max_content_lines': '',
+      'modifications': 0,
+      'params': '',
+      'parent_need': 'NEED-002',
+      'parent_needs': list([
+        'NEED-002',
+      ]),
+      'parent_needs_back': list([
+      ]),
+      'parts': dict({
+      }),
+      'post_template': None,
+      'pre_template': None,
+      'prefix': '',
+      'query': '',
+      'section_name': 'TEST DOCUMENT LIST2NEED',
+      'sections': list([
+        'TEST DOCUMENT LIST2NEED',
+      ]),
+      'service': '',
+      'signature': '',
+      'specific': '',
+      'status': None,
+      'style': None,
+      'tags': list([
+      ]),
+      'template': None,
+      'title': 'Sub-Need on level 2',
+      'triggers': list([
+      ]),
+      'triggers_back': list([
+      ]),
+      'type': 'spec',
+      'type_color': '#FEDCD2',
+      'type_name': 'Specification',
+      'type_prefix': 'SP_',
+      'type_style': 'node',
+      'updated_at': '',
+      'url': '',
+      'url_postfix': '',
+      'user': '',
+    }),
+    'NEED-1': dict({
+      'arch': dict({
+      }),
+      'avatar': '',
+      'checks': list([
+      ]),
+      'checks_back': list([
+      ]),
+      'closed_at': '',
+      'collapse': False,
+      'completion': '',
+      'constraints': list([
+      ]),
+      'constraints_passed': True,
+      'constraints_results': dict({
+      }),
+      'content': '',
+      'created_at': '',
+      'delete': False,
+      'docname': 'options',
+      'doctype': '.rst',
+      'duration': '',
+      'external_css': 'external_link',
+      'external_url': None,
+      'full_title': 'Need example on level 1 ',
+      'has_dead_links': False,
+      'has_forbidden_dead_links': False,
+      'hide': False,
+      'id': 'NEED-1',
+      'id_complete': 'NEED-1',
+      'id_parent': 'NEED-1',
+      'id_prefix': '',
+      'is_external': False,
+      'is_modified': False,
+      'is_need': True,
+      'is_part': False,
+      'jinja_content': False,
+      'layout': '',
+      'lineno': 20,
+      'lineno_content': 24,
+      'links': list([
+      ]),
+      'links_back': list([
+        'NEED-3',
+      ]),
+      'max_amount': '',
+      'max_content_lines': '',
+      'modifications': 0,
+      'params': '',
+      'parent_need': '',
+      'parent_needs': list([
+      ]),
+      'parent_needs_back': list([
+      ]),
+      'parts': dict({
+      }),
+      'post_template': None,
+      'pre_template': None,
+      'prefix': '',
+      'query': '',
+      'section_name': 'LIST2NEED OPTIONS',
+      'sections': list([
+        'LIST2NEED OPTIONS',
+      ]),
+      'service': '',
+      'signature': '',
+      'specific': '',
+      'status': 'open',
+      'style': None,
+      'tags': list([
+      ]),
+      'template': None,
+      'title': 'Need example on level 1 ',
+      'triggers': list([
+      ]),
+      'triggers_back': list([
+      ]),
+      'type': 'story',
+      'type_color': '#BFD8D2',
+      'type_name': 'User Story',
+      'type_prefix': 'US_',
+      'type_style': 'node',
+      'updated_at': '',
+      'url': '',
+      'url_postfix': '',
+      'user': '',
+    }),
+    'NEED-2': dict({
+      'arch': dict({
+      }),
+      'avatar': '',
+      'checks': list([
+      ]),
+      'checks_back': list([
+      ]),
+      'closed_at': '',
+      'collapse': False,
+      'completion': '',
+      'constraints': list([
+      ]),
+      'constraints_passed': True,
+      'constraints_results': dict({
+      }),
+      'content': '',
+      'created_at': '',
+      'delete': False,
+      'docname': 'options',
+      'doctype': '.rst',
+      'duration': '',
+      'external_css': 'external_link',
+      'external_url': None,
+      'full_title': 'Need example on level 1 ',
+      'has_dead_links': False,
+      'has_forbidden_dead_links': False,
+      'hide': False,
+      'id': 'NEED-2',
+      'id_complete': 'NEED-2',
+      'id_parent': 'NEED-2',
+      'id_prefix': '',
+      'is_external': False,
+      'is_modified': False,
+      'is_need': True,
+      'is_part': False,
+      'jinja_content': False,
+      'layout': '',
+      'lineno': 27,
+      'lineno_content': 32,
+      'links': list([
+      ]),
+      'links_back': list([
+        'NEED-3',
+      ]),
+      'max_amount': '',
+      'max_content_lines': '',
+      'modifications': 0,
+      'params': '',
+      'parent_need': '',
+      'parent_needs': list([
+      ]),
+      'parent_needs_back': list([
+      ]),
+      'parts': dict({
+      }),
+      'post_template': None,
+      'pre_template': None,
+      'prefix': '',
+      'query': '',
+      'section_name': 'LIST2NEED OPTIONS',
+      'sections': list([
+        'LIST2NEED OPTIONS',
+      ]),
+      'service': '',
+      'signature': '',
+      'specific': '',
+      'status': 'done',
+      'style': None,
+      'tags': list([
+        'tag1',
+        'tag2',
+        'tag3',
+      ]),
+      'template': None,
+      'title': 'Need example on level 1 ',
+      'triggers': list([
+      ]),
+      'triggers_back': list([
+      ]),
+      'type': 'story',
+      'type_color': '#BFD8D2',
+      'type_name': 'User Story',
+      'type_prefix': 'US_',
+      'type_style': 'node',
+      'updated_at': '',
+      'url': '',
+      'url_postfix': '',
+      'user': '',
+    }),
+    'NEED-3': dict({
+      'arch': dict({
+      }),
+      'avatar': '',
+      'checks': list([
+      ]),
+      'checks_back': list([
+      ]),
+      'closed_at': '',
+      'collapse': False,
+      'completion': '',
+      'constraints': list([
+      ]),
+      'constraints_passed': True,
+      'constraints_results': dict({
+      }),
+      'content': '',
+      'created_at': '',
+      'delete': False,
+      'docname': 'options',
+      'doctype': '.rst',
+      'duration': '',
+      'external_css': 'external_link',
+      'external_url': None,
+      'full_title': 'Link example ',
+      'has_dead_links': False,
+      'has_forbidden_dead_links': False,
+      'hide': False,
+      'id': 'NEED-3',
+      'id_complete': 'NEED-3',
+      'id_parent': 'NEED-3',
+      'id_prefix': '',
+      'is_external': False,
+      'is_modified': False,
+      'is_need': True,
+      'is_part': False,
+      'jinja_content': False,
+      'layout': '',
+      'lineno': 35,
+      'lineno_content': 39,
+      'links': list([
+        'NEED-1',
+        'NEED-2',
+      ]),
+      'links_back': list([
+        'NEED-Z',
+        'NEED-4',
+      ]),
+      'max_amount': '',
+      'max_content_lines': '',
+      'modifications': 0,
+      'params': '',
+      'parent_need': '',
+      'parent_needs': list([
+      ]),
+      'parent_needs_back': list([
+      ]),
+      'parts': dict({
+      }),
+      'post_template': None,
+      'pre_template': None,
+      'prefix': '',
+      'query': '',
+      'section_name': 'LIST2NEED OPTIONS',
+      'sections': list([
+        'LIST2NEED OPTIONS',
+      ]),
+      'service': '',
+      'signature': '',
+      'specific': '',
+      'status': None,
+      'style': None,
+      'tags': list([
+      ]),
+      'template': None,
+      'title': 'Link example ',
+      'triggers': list([
+      ]),
+      'triggers_back': list([
+      ]),
+      'type': 'story',
+      'type_color': '#BFD8D2',
+      'type_name': 'User Story',
+      'type_prefix': 'US_',
+      'type_style': 'node',
+      'updated_at': '',
+      'url': '',
+      'url_postfix': '',
+      'user': '',
+    }),
+    'NEED-4': dict({
+      'arch': dict({
+      }),
+      'avatar': '',
+      'checks': list([
+      ]),
+      'checks_back': list([
+      ]),
+      'closed_at': '',
+      'collapse': False,
+      'completion': '',
+      'constraints': list([
+      ]),
+      'constraints_passed': True,
+      'constraints_results': dict({
+      }),
+      'content': 'With some content in the next line.',
+      'created_at': '',
+      'delete': False,
+      'docname': 'options',
+      'doctype': '.rst',
+      'duration': '',
+      'external_css': 'external_link',
+      'external_url': None,
+      'full_title': 'New line example',
+      'has_dead_links': False,
+      'has_forbidden_dead_links': False,
+      'hide': False,
+      'id': 'NEED-4',
+      'id_complete': 'NEED-4',
+      'id_parent': 'NEED-4',
+      'id_prefix': '',
+      'is_external': False,
+      'is_modified': False,
+      'is_need': True,
+      'is_part': False,
+      'jinja_content': False,
+      'layout': '',
+      'lineno': 42,
+      'lineno_content': 49,
+      'links': list([
+        'NEED-3',
+      ]),
+      'links_back': list([
+      ]),
+      'max_amount': '',
+      'max_content_lines': '',
+      'modifications': 0,
+      'params': '',
+      'parent_need': '',
+      'parent_needs': list([
+      ]),
+      'parent_needs_back': list([
+      ]),
+      'parts': dict({
+      }),
+      'post_template': None,
+      'pre_template': None,
+      'prefix': '',
+      'query': '',
+      'section_name': 'LIST2NEED OPTIONS',
+      'sections': list([
+        'LIST2NEED OPTIONS',
+      ]),
+      'service': '',
+      'signature': '',
+      'specific': '',
+      'status': 'in progress',
+      'style': None,
+      'tags': list([
+      ]),
+      'template': None,
+      'title': 'New line example',
+      'triggers': list([
+      ]),
+      'triggers_back': list([
+      ]),
+      'type': 'story',
+      'type_color': '#BFD8D2',
+      'type_name': 'User Story',
+      'type_prefix': 'US_',
+      'type_style': 'node',
+      'updated_at': '',
+      'url': '',
+      'url_postfix': '',
+      'user': '',
+    }),
+    'NEED-A': dict({
+      'arch': dict({
+      }),
+      'avatar': '',
+      'checks': list([
+        'NEED-B',
+      ]),
+      'checks_back': list([
+      ]),
+      'closed_at': '',
+      'collapse': False,
+      'completion': '',
+      'constraints': list([
+      ]),
+      'constraints_passed': True,
+      'constraints_results': dict({
+      }),
+      'content': '',
+      'created_at': '',
+      'delete': False,
+      'docname': 'links_down',
+      'doctype': '.rst',
+      'duration': '',
+      'external_css': 'external_link',
+      'external_url': None,
+      'full_title': 'Need example on level 1',
+      'has_dead_links': False,
+      'has_forbidden_dead_links': False,
+      'hide': False,
+      'id': 'NEED-A',
+      'id_complete': 'NEED-A',
+      'id_parent': 'NEED-A',
+      'id_prefix': '',
+      'is_external': False,
+      'is_modified': False,
+      'is_need': True,
+      'is_part': False,
+      'jinja_content': False,
+      'layout': '',
+      'lineno': 19,
+      'lineno_content': 23,
+      'links': list([
+      ]),
+      'links_back': list([
+      ]),
+      'max_amount': '',
+      'max_content_lines': '',
+      'modifications': 0,
+      'params': '',
+      'parent_need': '',
+      'parent_needs': list([
+      ]),
+      'parent_needs_back': list([
+      ]),
+      'parts': dict({
+      }),
+      'post_template': None,
+      'pre_template': None,
+      'prefix': '',
+      'query': '',
+      'section_name': 'LIST2NEED LINKS_DOWN',
+      'sections': list([
+        'LIST2NEED LINKS_DOWN',
+      ]),
+      'service': '',
+      'signature': '',
+      'specific': '',
+      'status': None,
+      'style': None,
+      'tags': list([
+      ]),
+      'template': None,
+      'title': 'Need example on level 1',
+      'triggers': list([
+      ]),
+      'triggers_back': list([
+      ]),
+      'type': 'story',
+      'type_color': '#BFD8D2',
+      'type_name': 'User Story',
+      'type_prefix': 'US_',
+      'type_style': 'node',
+      'updated_at': '',
+      'url': '',
+      'url_postfix': '',
+      'user': '',
+    }),
+    'NEED-B': dict({
+      'arch': dict({
+      }),
+      'avatar': '',
+      'checks': list([
+      ]),
+      'checks_back': list([
+        'NEED-A',
+      ]),
+      'closed_at': '',
+      'collapse': False,
+      'completion': '',
+      'constraints': list([
+      ]),
+      'constraints_passed': True,
+      'constraints_results': dict({
+      }),
+      'content': '',
+      'created_at': '',
+      'delete': False,
+      'docname': 'links_down',
+      'doctype': '.rst',
+      'duration': '',
+      'external_css': 'external_link',
+      'external_url': None,
+      'full_title': 'Need example on level 2',
+      'has_dead_links': False,
+      'has_forbidden_dead_links': False,
+      'hide': False,
+      'id': 'NEED-B',
+      'id_complete': 'NEED-B',
+      'id_parent': 'NEED-B',
+      'id_prefix': '',
+      'is_external': False,
+      'is_modified': False,
+      'is_need': True,
+      'is_part': False,
+      'jinja_content': False,
+      'layout': '',
+      'lineno': 25,
+      'lineno_content': 29,
+      'links': list([
+      ]),
+      'links_back': list([
+      ]),
+      'max_amount': '',
+      'max_content_lines': '',
+      'modifications': 0,
+      'params': '',
+      'parent_need': '',
+      'parent_needs': list([
+      ]),
+      'parent_needs_back': list([
+      ]),
+      'parts': dict({
+      }),
+      'post_template': None,
+      'pre_template': None,
+      'prefix': '',
+      'query': '',
+      'section_name': 'LIST2NEED LINKS_DOWN',
+      'sections': list([
+        'LIST2NEED LINKS_DOWN',
+      ]),
+      'service': '',
+      'signature': '',
+      'specific': '',
+      'status': None,
+      'style': None,
+      'tags': list([
+      ]),
+      'template': None,
+      'title': 'Need example on level 2',
+      'triggers': list([
+        'NEED-C',
+      ]),
+      'triggers_back': list([
+      ]),
+      'type': 'spec',
+      'type_color': '#FEDCD2',
+      'type_name': 'Specification',
+      'type_prefix': 'SP_',
+      'type_style': 'node',
+      'updated_at': '',
+      'url': '',
+      'url_postfix': '',
+      'user': '',
+    }),
+    'NEED-C': dict({
+      'arch': dict({
+      }),
+      'avatar': '',
+      'checks': list([
+      ]),
+      'checks_back': list([
+      ]),
+      'closed_at': '',
+      'collapse': False,
+      'completion': '',
+      'constraints': list([
+      ]),
+      'constraints_passed': True,
+      'constraints_results': dict({
+      }),
+      'content': '',
+      'created_at': '',
+      'delete': False,
+      'docname': 'links_down',
+      'doctype': '.rst',
+      'duration': '',
+      'external_css': 'external_link',
+      'external_url': None,
+      'full_title': 'Need example on level 3',
+      'has_dead_links': False,
+      'has_forbidden_dead_links': False,
+      'hide': False,
+      'id': 'NEED-C',
+      'id_complete': 'NEED-C',
+      'id_parent': 'NEED-C',
+      'id_prefix': '',
+      'is_external': False,
+      'is_modified': False,
+      'is_need': True,
+      'is_part': False,
+      'jinja_content': False,
+      'layout': '',
+      'lineno': 31,
+      'lineno_content': 34,
+      'links': list([
+      ]),
+      'links_back': list([
+      ]),
+      'max_amount': '',
+      'max_content_lines': '',
+      'modifications': 0,
+      'params': '',
+      'parent_need': '',
+      'parent_needs': list([
+      ]),
+      'parent_needs_back': list([
+      ]),
+      'parts': dict({
+      }),
+      'post_template': None,
+      'pre_template': None,
+      'prefix': '',
+      'query': '',
+      'section_name': 'LIST2NEED LINKS_DOWN',
+      'sections': list([
+        'LIST2NEED LINKS_DOWN',
+      ]),
+      'service': '',
+      'signature': '',
+      'specific': '',
+      'status': None,
+      'style': None,
+      'tags': list([
+      ]),
+      'template': None,
+      'title': 'Need example on level 3',
+      'triggers': list([
+      ]),
+      'triggers_back': list([
+        'NEED-B',
+      ]),
+      'type': 'test',
+      'type_color': '#DCB239',
+      'type_name': 'Test Case',
+      'type_prefix': 'TC_',
+      'type_style': 'node',
+      'updated_at': '',
+      'url': '',
+      'url_postfix': '',
+      'user': '',
+    }),
+    'NEED-W': dict({
+      'arch': dict({
+      }),
+      'avatar': '',
+      'checks': list([
+      ]),
+      'checks_back': list([
+      ]),
+      'closed_at': '',
+      'collapse': False,
+      'completion': '',
+      'constraints': list([
+      ]),
+      'constraints_passed': True,
+      'constraints_results': dict({
+      }),
+      'content': '',
+      'created_at': '',
+      'delete': False,
+      'docname': 'global_tags',
+      'doctype': '.rst',
+      'duration': '',
+      'external_css': 'external_link',
+      'external_url': None,
+      'full_title': 'Need example on level 1 ',
+      'has_dead_links': False,
+      'has_forbidden_dead_links': False,
+      'hide': False,
+      'id': 'NEED-W',
+      'id_complete': 'NEED-W',
+      'id_parent': 'NEED-W',
+      'id_prefix': '',
+      'is_external': False,
+      'is_modified': False,
+      'is_need': True,
+      'is_part': False,
+      'jinja_content': False,
+      'layout': '',
+      'lineno': 21,
+      'lineno_content': 26,
+      'links': list([
+      ]),
+      'links_back': list([
+        'NEED-Y',
+      ]),
+      'max_amount': '',
+      'max_content_lines': '',
+      'modifications': 0,
+      'params': '',
+      'parent_need': '',
+      'parent_needs': list([
+      ]),
+      'parent_needs_back': list([
+      ]),
+      'parts': dict({
+      }),
+      'post_template': None,
+      'pre_template': None,
+      'prefix': '',
+      'query': '',
+      'section_name': 'LIST2NEED GLOBAL TAGS',
+      'sections': list([
+        'LIST2NEED GLOBAL TAGS',
+      ]),
+      'service': '',
+      'signature': '',
+      'specific': '',
+      'status': 'open',
+      'style': None,
+      'tags': list([
+        'global_tag1',
+        'global_tag2',
+        'global_tag3',
+      ]),
+      'template': None,
+      'title': 'Need example on level 1 ',
+      'triggers': list([
+      ]),
+      'triggers_back': list([
+      ]),
+      'type': 'story',
+      'type_color': '#BFD8D2',
+      'type_name': 'User Story',
+      'type_prefix': 'US_',
+      'type_style': 'node',
+      'updated_at': '',
+      'url': '',
+      'url_postfix': '',
+      'user': '',
+    }),
+    'NEED-X': dict({
+      'arch': dict({
+      }),
+      'avatar': '',
+      'checks': list([
+      ]),
+      'checks_back': list([
+      ]),
+      'closed_at': '',
+      'collapse': False,
+      'completion': '',
+      'constraints': list([
+      ]),
+      'constraints_passed': True,
+      'constraints_results': dict({
+      }),
+      'content': '',
+      'created_at': '',
+      'delete': False,
+      'docname': 'global_tags',
+      'doctype': '.rst',
+      'duration': '',
+      'external_css': 'external_link',
+      'external_url': None,
+      'full_title': 'Need example on level 1 ',
+      'has_dead_links': False,
+      'has_forbidden_dead_links': False,
+      'hide': False,
+      'id': 'NEED-X',
+      'id_complete': 'NEED-X',
+      'id_parent': 'NEED-X',
+      'id_prefix': '',
+      'is_external': False,
+      'is_modified': False,
+      'is_need': True,
+      'is_part': False,
+      'jinja_content': False,
+      'layout': '',
+      'lineno': 29,
+      'lineno_content': 34,
+      'links': list([
+      ]),
+      'links_back': list([
+      ]),
+      'max_amount': '',
+      'max_content_lines': '',
+      'modifications': 0,
+      'params': '',
+      'parent_need': '',
+      'parent_needs': list([
+      ]),
+      'parent_needs_back': list([
+      ]),
+      'parts': dict({
+      }),
+      'post_template': None,
+      'pre_template': None,
+      'prefix': '',
+      'query': '',
+      'section_name': 'LIST2NEED GLOBAL TAGS',
+      'sections': list([
+        'LIST2NEED GLOBAL TAGS',
+      ]),
+      'service': '',
+      'signature': '',
+      'specific': '',
+      'status': 'done',
+      'style': None,
+      'tags': list([
+        'tag1',
+        'tag2',
+        'tag3',
+        'global_tag1',
+        'global_tag2',
+        'global_tag3',
+      ]),
+      'template': None,
+      'title': 'Need example on level 1 ',
+      'triggers': list([
+      ]),
+      'triggers_back': list([
+      ]),
+      'type': 'story',
+      'type_color': '#BFD8D2',
+      'type_name': 'User Story',
+      'type_prefix': 'US_',
+      'type_style': 'node',
+      'updated_at': '',
+      'url': '',
+      'url_postfix': '',
+      'user': '',
+    }),
+    'NEED-Y': dict({
+      'arch': dict({
+      }),
+      'avatar': '',
+      'checks': list([
+      ]),
+      'checks_back': list([
+      ]),
+      'closed_at': '',
+      'collapse': False,
+      'completion': '',
+      'constraints': list([
+      ]),
+      'constraints_passed': True,
+      'constraints_results': dict({
+      }),
+      'content': '',
+      'created_at': '',
+      'delete': False,
+      'docname': 'global_tags',
+      'doctype': '.rst',
+      'duration': '',
+      'external_css': 'external_link',
+      'external_url': None,
+      'full_title': 'Link example ',
+      'has_dead_links': False,
+      'has_forbidden_dead_links': False,
+      'hide': False,
+      'id': 'NEED-Y',
+      'id_complete': 'NEED-Y',
+      'id_parent': 'NEED-Y',
+      'id_prefix': '',
+      'is_external': False,
+      'is_modified': False,
+      'is_need': True,
+      'is_part': False,
+      'jinja_content': False,
+      'layout': '',
+      'lineno': 37,
+      'lineno_content': 42,
+      'links': list([
+        'NEED-W',
+        'NEED-Y',
+      ]),
+      'links_back': list([
+        'NEED-Y',
+      ]),
+      'max_amount': '',
+      'max_content_lines': '',
+      'modifications': 0,
+      'params': '',
+      'parent_need': '',
+      'parent_needs': list([
+      ]),
+      'parent_needs_back': list([
+      ]),
+      'parts': dict({
+      }),
+      'post_template': None,
+      'pre_template': None,
+      'prefix': '',
+      'query': '',
+      'section_name': 'LIST2NEED GLOBAL TAGS',
+      'sections': list([
+        'LIST2NEED GLOBAL TAGS',
+      ]),
+      'service': '',
+      'signature': '',
+      'specific': '',
+      'status': None,
+      'style': None,
+      'tags': list([
+        'global_tag1',
+        'global_tag2',
+        'global_tag3',
+      ]),
+      'template': None,
+      'title': 'Link example ',
+      'triggers': list([
+      ]),
+      'triggers_back': list([
+      ]),
+      'type': 'story',
+      'type_color': '#BFD8D2',
+      'type_name': 'User Story',
+      'type_prefix': 'US_',
+      'type_style': 'node',
+      'updated_at': '',
+      'url': '',
+      'url_postfix': '',
+      'user': '',
+    }),
+    'NEED-Z': dict({
+      'arch': dict({
+      }),
+      'avatar': '',
+      'checks': list([
+      ]),
+      'checks_back': list([
+      ]),
+      'closed_at': '',
+      'collapse': False,
+      'completion': '',
+      'constraints': list([
+      ]),
+      'constraints_passed': True,
+      'constraints_results': dict({
+      }),
+      'content': 'With some content in the next line.',
+      'created_at': '',
+      'delete': False,
+      'docname': 'global_tags',
+      'doctype': '.rst',
+      'duration': '',
+      'external_css': 'external_link',
+      'external_url': None,
+      'full_title': 'New line example',
+      'has_dead_links': False,
+      'has_forbidden_dead_links': False,
+      'hide': False,
+      'id': 'NEED-Z',
+      'id_complete': 'NEED-Z',
+      'id_parent': 'NEED-Z',
+      'id_prefix': '',
+      'is_external': False,
+      'is_modified': False,
+      'is_need': True,
+      'is_part': False,
+      'jinja_content': False,
+      'layout': '',
+      'lineno': 45,
+      'lineno_content': 53,
+      'links': list([
+        'NEED-3',
+      ]),
+      'links_back': list([
+      ]),
+      'max_amount': '',
+      'max_content_lines': '',
+      'modifications': 0,
+      'params': '',
+      'parent_need': '',
+      'parent_needs': list([
+      ]),
+      'parent_needs_back': list([
+      ]),
+      'parts': dict({
+      }),
+      'post_template': None,
+      'pre_template': None,
+      'prefix': '',
+      'query': '',
+      'section_name': 'LIST2NEED GLOBAL TAGS',
+      'sections': list([
+        'LIST2NEED GLOBAL TAGS',
+      ]),
+      'service': '',
+      'signature': '',
+      'specific': '',
+      'status': 'in progress',
+      'style': None,
+      'tags': list([
+        'global_tag1',
+        'global_tag2',
+        'global_tag3',
+      ]),
+      'template': None,
+      'title': 'New line example',
+      'triggers': list([
+      ]),
+      'triggers_back': list([
+      ]),
+      'type': 'story',
+      'type_color': '#BFD8D2',
+      'type_name': 'User Story',
+      'type_prefix': 'US_',
+      'type_style': 'node',
+      'updated_at': '',
+      'url': '',
+      'url_postfix': '',
+      'user': '',
+    }),
+    'SP_69FFD': dict({
+      'arch': dict({
+      }),
+      'avatar': '',
+      'checks': list([
+      ]),
+      'checks_back': list([
+      ]),
+      'closed_at': '',
+      'collapse': False,
+      'completion': '',
+      'constraints': list([
+      ]),
+      'constraints_passed': True,
+      'constraints_results': dict({
+      }),
+      'content': '''
+        Where this sentence will be used
+        as content, the first one as title.
+        
+        .. test:: Sub-Need on level 3
+           :id: TC_EA5AF
+           
+        
+           With some rst-syntax supported for
+           the **content** by :ref:`test`
+      ''',
+      'created_at': '',
+      'delete': False,
+      'docname': 'index',
+      'doctype': '.rst',
+      'duration': '',
+      'external_css': 'external_link',
+      'external_url': None,
+      'full_title': 'Another Sub-Need on level 2',
+      'has_dead_links': False,
+      'has_forbidden_dead_links': False,
+      'hide': False,
+      'id': 'SP_69FFD',
+      'id_complete': 'SP_69FFD',
+      'id_parent': 'SP_69FFD',
+      'id_prefix': '',
+      'is_external': False,
+      'is_modified': False,
+      'is_need': True,
+      'is_part': False,
+      'jinja_content': False,
+      'layout': '',
+      'lineno': 38,
+      'lineno_content': 42,
+      'links': list([
+      ]),
+      'links_back': list([
+      ]),
+      'max_amount': '',
+      'max_content_lines': '',
+      'modifications': 0,
+      'params': '',
+      'parent_need': 'NEED-002',
+      'parent_needs': list([
+        'NEED-002',
+      ]),
+      'parent_needs_back': list([
+        'TC_EA5AF',
+      ]),
+      'parts': dict({
+      }),
+      'post_template': None,
+      'pre_template': None,
+      'prefix': '',
+      'query': '',
+      'section_name': 'TEST DOCUMENT LIST2NEED',
+      'sections': list([
+        'TEST DOCUMENT LIST2NEED',
+      ]),
+      'service': '',
+      'signature': '',
+      'specific': '',
+      'status': None,
+      'style': None,
+      'tags': list([
+      ]),
+      'template': None,
+      'title': 'Another Sub-Need on level 2',
+      'triggers': list([
+      ]),
+      'triggers_back': list([
+      ]),
+      'type': 'spec',
+      'type_color': '#FEDCD2',
+      'type_name': 'Specification',
+      'type_prefix': 'SP_',
+      'type_style': 'node',
+      'updated_at': '',
+      'url': '',
+      'url_postfix': '',
+      'user': '',
+    }),
+    'TC_EA5AF': dict({
+      'arch': dict({
+      }),
+      'avatar': '',
+      'checks': list([
+      ]),
+      'checks_back': list([
+      ]),
+      'closed_at': '',
+      'collapse': False,
+      'completion': '',
+      'constraints': list([
+      ]),
+      'constraints_passed': True,
+      'constraints_results': dict({
+      }),
+      'content': '''
+        With some rst-syntax supported for
+        the **content** by :ref:`test`
+      ''',
+      'created_at': '',
+      'delete': False,
+      'docname': 'index',
+      'doctype': '.rst',
+      'duration': '',
+      'external_css': 'external_link',
+      'external_url': None,
+      'full_title': 'Sub-Need on level 3',
+      'has_dead_links': False,
+      'has_forbidden_dead_links': False,
+      'hide': False,
+      'id': 'TC_EA5AF',
+      'id_complete': 'TC_EA5AF',
+      'id_parent': 'TC_EA5AF',
+      'id_prefix': '',
+      'is_external': False,
+      'is_modified': False,
+      'is_need': True,
+      'is_part': False,
+      'jinja_content': False,
+      'layout': '',
+      'lineno': 45,
+      'lineno_content': 49,
+      'links': list([
+      ]),
+      'links_back': list([
+      ]),
+      'max_amount': '',
+      'max_content_lines': '',
+      'modifications': 0,
+      'params': '',
+      'parent_need': 'SP_69FFD',
+      'parent_needs': list([
+        'SP_69FFD',
+      ]),
+      'parent_needs_back': list([
+      ]),
+      'parts': dict({
+      }),
+      'post_template': None,
+      'pre_template': None,
+      'prefix': '',
+      'query': '',
+      'section_name': 'TEST DOCUMENT LIST2NEED',
+      'sections': list([
+        'TEST DOCUMENT LIST2NEED',
+      ]),
+      'service': '',
+      'signature': '',
+      'specific': '',
+      'status': None,
+      'style': None,
+      'tags': list([
+      ]),
+      'template': None,
+      'title': 'Sub-Need on level 3',
+      'triggers': list([
+      ]),
+      'triggers_back': list([
+      ]),
+      'type': 'test',
+      'type_color': '#DCB239',
+      'type_name': 'Test Case',
+      'type_prefix': 'TC_',
+      'type_style': 'node',
+      'updated_at': '',
+      'url': '',
+      'url_postfix': '',
+      'user': '',
+    }),
+    'US_F1B63': dict({
+      'arch': dict({
+      }),
+      'avatar': '',
+      'checks': list([
+      ]),
+      'checks_back': list([
+      ]),
+      'closed_at': '',
+      'collapse': False,
+      'completion': '',
+      'constraints': list([
+      ]),
+      'constraints_passed': True,
+      'constraints_results': dict({
+      }),
+      'content': '',
+      'created_at': '',
+      'delete': False,
+      'docname': 'index',
+      'doctype': '.rst',
+      'duration': '',
+      'external_css': 'external_link',
+      'external_url': None,
+      'full_title': 'Need example on level 1',
+      'has_dead_links': False,
+      'has_forbidden_dead_links': False,
+      'hide': False,
+      'id': 'US_F1B63',
+      'id_complete': 'US_F1B63',
+      'id_parent': 'US_F1B63',
+      'id_prefix': '',
+      'is_external': False,
+      'is_modified': False,
+      'is_need': True,
+      'is_part': False,
+      'jinja_content': False,
+      'layout': '',
+      'lineno': 20,
+      'lineno_content': 23,
+      'links': list([
+      ]),
+      'links_back': list([
+      ]),
+      'max_amount': '',
+      'max_content_lines': '',
+      'modifications': 0,
+      'params': '',
+      'parent_need': '',
+      'parent_needs': list([
+      ]),
+      'parent_needs_back': list([
+      ]),
+      'parts': dict({
+      }),
+      'post_template': None,
+      'pre_template': None,
+      'prefix': '',
+      'query': '',
+      'section_name': 'TEST DOCUMENT LIST2NEED',
+      'sections': list([
+        'TEST DOCUMENT LIST2NEED',
+      ]),
+      'service': '',
+      'signature': '',
+      'specific': '',
+      'status': None,
+      'style': None,
+      'tags': list([
+      ]),
+      'template': None,
+      'title': 'Need example on level 1',
+      'triggers': list([
+      ]),
+      'triggers_back': list([
+      ]),
+      'type': 'story',
+      'type_color': '#BFD8D2',
+      'type_name': 'User Story',
+      'type_prefix': 'US_',
+      'type_style': 'node',
+      'updated_at': '',
+      'url': '',
+      'url_postfix': '',
+      'user': '',
+    }),
+  })
+# ---
diff --git a/tests/doc_test/doc_list2need/global_tags.rst b/tests/doc_test/doc_list2need/global_tags.rst
new file mode 100644
index 00000000..fc1129e4
--- /dev/null
+++ b/tests/doc_test/doc_list2need/global_tags.rst
@@ -0,0 +1,19 @@
+LIST2NEED GLOBAL TAGS
+=====================
+
+
+.. list2need::
+   :types: story, spec, test
+   :presentation: nested
+   :delimiter: .
+   :tags: global_tag1, global_tag2, global_tag3
+
+   * (NEED-W)Need example on level 1 ((status="open"))
+   * (NEED-X)Need example on level 1 ((status="done", tags="tag1, tag2, tag3"))
+   * (NEED-Y)Link example ((links="NEED-W, NEED-Y"))
+   * (NEED-Z)New line example.
+     With some content in the next line.
+     ((status="in progress", links="NEED-3"))
+
+
+
diff --git a/tests/doc_test/doc_list2need/index.rst b/tests/doc_test/doc_list2need/index.rst
index bd56d3c5..3c9e009c 100644
--- a/tests/doc_test/doc_list2need/index.rst
+++ b/tests/doc_test/doc_list2need/index.rst
@@ -27,4 +27,5 @@ Foo Bar.
 .. toctree::
 
    options
-   links_down
\ No newline at end of file
+   links_down
+   global_tags
\ No newline at end of file
diff --git a/tests/test_list2need.py b/tests/test_list2need.py
index 605f4331..d4c27222 100644
--- a/tests/test_list2need.py
+++ b/tests/test_list2need.py
@@ -2,15 +2,22 @@ from pathlib import Path
 
 import pytest
 
+from sphinx_needs.api import get_needs_view
+
 
 @pytest.mark.parametrize(
     "test_app",
     [{"buildername": "html", "srcdir": "doc_test/doc_list2need"}],
     indirect=True,
 )
-def test_doc_list2need_html(test_app):
+def test_doc_list2need_html(test_app, snapshot):
     app = test_app
     app.build()
+    assert app._warning.getvalue() == ""
+
+    view = get_needs_view(app)
+    assert dict(view) == snapshot
+
     index_html = Path(app.outdir, "index.html").read_text()
     assert "NEED-002" in index_html
     assert "Sub-Need on level 3" in index_html