Files
wehub-resource-sync 7a0da7932b
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:08:55 +08:00

170 lines
6.0 KiB
Python

"""Tests for the check-readme-links pre-commit hook.
Verifies that the hook flags broken relative links, dangling heading
anchors, non-runnable ``python -m`` examples, and unregistered
``engine="..."`` names in README.md and docs/**/*.md, while accepting
files whose references all resolve — including GitHub-style anchors for
headings that contain emoji and links inside fenced code blocks (which
GitHub does not render and must therefore be exempt).
"""
import subprocess
import sys
from pathlib import Path
HOOK_SCRIPT = (
Path(__file__).parent.parent.parent
/ ".pre-commit-hooks"
/ "check-readme-links.py"
)
REGISTRY_REL = Path("src/local_deep_research/web_search_engines")
VALID_README = """# Test Project
[a doc](docs/real.md)
[an anchor](docs/real.md#real-heading)
[emoji same-file anchor](#-benchmarks)
[line anchor](docs/real.md#L1)
## 📊 Benchmarks
```bash
python -m local_deep_research.pkg
python -m local_deep_research.tool.cli run --flag
```
`search(query="x", engine="arxiv")`
"""
def _make_repo(tmp_path: Path, readme: str) -> Path:
"""Build a minimal fake repo the hook can be pointed at via --root."""
(tmp_path / "README.md").write_text(readme, encoding="utf-8")
(tmp_path / "SECURITY.md").write_text("# Security\n", encoding="utf-8")
(tmp_path / "CONTRIBUTING.md").write_text(
"# Contributing\n", encoding="utf-8"
)
docs = tmp_path / "docs"
docs.mkdir()
(docs / "real.md").write_text("## Real Heading\n", encoding="utf-8")
pkg = tmp_path / "src" / "local_deep_research" / "pkg"
pkg.mkdir(parents=True)
(pkg / "__main__.py").write_text("", encoding="utf-8")
tool = tmp_path / "src" / "local_deep_research" / "tool"
tool.mkdir()
(tool / "cli.py").write_text("", encoding="utf-8")
registry_dir = tmp_path / REGISTRY_REL
registry_dir.mkdir(parents=True)
(registry_dir / "engine_registry.py").write_text(
'ENGINE_REGISTRY = {\n "arxiv": EngineEntry(\n', encoding="utf-8"
)
return tmp_path
def _run_hook(root: Path):
return subprocess.run(
[sys.executable, str(HOOK_SCRIPT), "--root", str(root)],
capture_output=True,
text=True,
)
class TestAcceptsValidReadme:
def test_all_references_resolve(self, tmp_path):
result = _run_hook(_make_repo(tmp_path, VALID_README))
assert result.returncode == 0, result.stdout
def test_external_links_are_ignored(self, tmp_path):
readme = "[ext](https://example.com/gone) [m](mailto:a@b.c)\n"
result = _run_hook(_make_repo(tmp_path, readme))
assert result.returncode == 0, result.stdout
def test_non_ldr_modules_are_ignored(self, tmp_path):
result = _run_hook(_make_repo(tmp_path, "`python -m http.server`\n"))
assert result.returncode == 0, result.stdout
def test_links_inside_code_fences_are_ignored(self, tmp_path):
# GitHub renders no links inside fenced blocks, so example markup
# with runtime paths must not be flagged.
readme = (
"# T\n\n```html\n"
'<link href="/static/css/nope.css">\n'
"[fake](docs/nope.md)\n"
"```\n"
)
result = _run_hook(_make_repo(tmp_path, readme))
assert result.returncode == 0, result.stdout
class TestFlagsBrokenReferences:
def test_missing_link_target(self, tmp_path):
result = _run_hook(_make_repo(tmp_path, "[x](docs/nope.md)\n"))
assert result.returncode == 1
assert "docs/nope.md" in result.stdout
def test_dangling_heading_anchor(self, tmp_path):
result = _run_hook(_make_repo(tmp_path, "[x](docs/real.md#gone)\n"))
assert result.returncode == 1
assert "#gone" in result.stdout
def test_dangling_same_file_anchor(self, tmp_path):
result = _run_hook(_make_repo(tmp_path, "# T\n[x](#missing)\n"))
assert result.returncode == 1
assert "#missing" in result.stdout
def test_line_anchor_beyond_eof(self, tmp_path):
result = _run_hook(_make_repo(tmp_path, "[x](docs/real.md#L999)\n"))
assert result.returncode == 1
assert "L999" in result.stdout
def test_unrunnable_python_module(self, tmp_path):
readme = "`python -m local_deep_research.missing.mod`\n"
result = _run_hook(_make_repo(tmp_path, readme))
assert result.returncode == 1
assert "local_deep_research.missing.mod" in result.stdout
def test_package_without_dunder_main(self, tmp_path):
# src/local_deep_research/pkg exists but we point one level up,
# at a directory that has no __main__.py.
readme = "`python -m local_deep_research`\n"
result = _run_hook(_make_repo(tmp_path, readme))
assert result.returncode == 1
def test_unregistered_engine_name(self, tmp_path):
readme = 'search(query="x", engine="ghost")\n'
result = _run_hook(_make_repo(tmp_path, readme))
assert result.returncode == 1
assert 'engine="ghost"' in result.stdout
def test_missing_registry_fails_loudly(self, tmp_path):
root = _make_repo(tmp_path, 'search(query="x", engine="arxiv")\n')
(root / REGISTRY_REL / "engine_registry.py").unlink()
result = _run_hook(root)
assert result.returncode == 1
assert "cannot verify engine names" in result.stdout
def test_broken_link_in_docs_file(self, tmp_path):
# docs/**/*.md is covered, not just README.md.
root = _make_repo(tmp_path, "# T\n")
(root / "docs" / "real.md").write_text(
"## Real Heading\n[gone](missing.md)\n", encoding="utf-8"
)
result = _run_hook(root)
assert result.returncode == 1
assert "docs/real.md" in result.stdout
assert "missing.md" in result.stdout
class TestRealRepo:
def test_actual_readme_and_docs_pass(self):
"""The repo's own README and docs must satisfy their own check."""
result = subprocess.run(
[sys.executable, str(HOOK_SCRIPT)],
capture_output=True,
text=True,
)
assert result.returncode == 0, result.stdout