This is an automated email from the ASF dual-hosted git repository. imbajin pushed a commit to branch feat/oink-community-content in repository https://gitbox.apache.org/repos/asf/hugegraph-doc.git
commit 4d02fcb627e4ab9e6161e9976f82547e6e66dd3b Author: dark <[email protected]> AuthorDate: Fri Sep 4 21:16:56 2026 +0800 test(community): prove section-order guard - swap complete role sections without changing their labels or links - cover both locales across HTML and Print outputs - require the dedicated role-order validation error --- scripts/community_roster.py | 2 +- scripts/test_community_roster.py | 64 +++++++++++++++++++++++++++------------- 2 files changed, 44 insertions(+), 22 deletions(-) diff --git a/scripts/community_roster.py b/scripts/community_roster.py index 89389c084..72c30aae2 100644 --- a/scripts/community_roster.py +++ b/scripts/community_roster.py @@ -506,7 +506,7 @@ def _rendered_role_links(rendered: str, html_output: bool) -> dict[str, list[str parser = _CommunityLinkParser() parser.feed(rendered) if parser.section_order != ["pmc", "committers"]: - return {"pmc": [], "committers": []} + raise RosterError("Community role section order drift") return parser.links starts = {} for role, heading in (("pmc", "PMC"), ("committers", "Committers")): diff --git a/scripts/test_community_roster.py b/scripts/test_community_roster.py index b9644635c..dfe60dde3 100644 --- a/scripts/test_community_roster.py +++ b/scripts/test_community_roster.py @@ -3,6 +3,7 @@ import importlib.util import json import os import pathlib +import re import shutil import subprocess import sys @@ -633,27 +634,48 @@ class CommunityContentContractTests(unittest.TestCase): self.assertEqual(0, result.returncode, result.stderr) def test_artifact_validator_rejects_swapped_role_sections(self): - with tempfile.TemporaryDirectory(prefix="community-role-output-") as directory: - destination = pathlib.Path(directory) - for relative in ( - "community/index.html", - "_print/community/index.html", - "community/index.md", - "cn/community/index.html", - "cn/_print/community/index.html", - "cn/community/index.md", - ): - target = destination / relative - target.parent.mkdir(parents=True, exist_ok=True) - shutil.copyfile(self.site / relative, target) - path = destination / "community/index.html" - rendered = path.read_text(encoding="utf-8") - rendered = rendered.replace('data-community-role="pmc"', 'data-community-role="temporary"', 1) - rendered = rendered.replace('data-community-role="committers"', 'data-community-role="pmc"', 1) - rendered = rendered.replace('data-community-role="temporary"', 'data-community-role="committers"', 1) - path.write_text(rendered, encoding="utf-8") - with self.assertRaisesRegex(roster.RosterError, "link parity drift"): - roster.validate_rendered_outputs(destination) + outputs = ( + "community/index.html", + "_print/community/index.html", + "community/index.md", + "cn/community/index.html", + "cn/_print/community/index.html", + "cn/community/index.md", + ) + for swapped_relative in ( + "community/index.html", + "_print/community/index.html", + "cn/community/index.html", + "cn/_print/community/index.html", + ): + with self.subTest(output=swapped_relative), tempfile.TemporaryDirectory( + prefix="community-role-output-" + ) as directory: + destination = pathlib.Path(directory) + for relative in outputs: + target = destination / relative + target.parent.mkdir(parents=True, exist_ok=True) + shutil.copyfile(self.site / relative, target) + path = destination / swapped_relative + rendered = path.read_text(encoding="utf-8") + match = re.search( + r'(<section[^>]*data-community-role=(?:"pmc"|pmc)[^>]*>.*?</section>)' + r"(\s*)" + r'(<section[^>]*data-community-role=(?:"committers"|committers)[^>]*>.*?</section>)', + rendered, + flags=re.DOTALL, + ) + self.assertIsNotNone(match) + rendered = ( + rendered[: match.start()] + + match.group(3) + + match.group(2) + + match.group(1) + + rendered[match.end() :] + ) + path.write_text(rendered, encoding="utf-8") + with self.assertRaisesRegex(roster.RosterError, "role section order drift"): + roster.validate_rendered_outputs(destination) def test_artifact_validator_rejects_plain_text_profile_urls(self): with tempfile.TemporaryDirectory(prefix="community-fake-output-") as directory:
