Files
langgraph/docs/tests/unit_tests/test_auto_links.py
T
Eugene YurtsevandGitHub d68bac3865 chore(docs): Support custom link titles (#5706)
Support custom link titles for custom link syntax
2025-07-29 14:17:03 -04:00

217 lines
6.6 KiB
Python

"""Unit tests for cross-reference preprocessing functionality."""
from unittest.mock import patch
import pytest
from _scripts.handle_auto_links import _transform_link, _replace_autolinks
@pytest.fixture
def mock_link_maps():
"""Fixture providing mock link maps for testing."""
mock_scope_maps = {
"python": {"py-link": "https://example.com/python"},
"js": {"js-link": "https://example.com/js"},
}
with patch("_scripts.handle_auto_links.SCOPE_LINK_MAPS", mock_scope_maps):
yield mock_scope_maps
def test_transform_link_basic(mock_link_maps) -> None:
"""Test basic link transformation."""
# Test with a known link
result = _transform_link("py-link", "python", "test.md", 1)
assert result == "[py-link](https://example.com/python)"
# Test with an unknown link (returns None)
result = _transform_link("unknown-link", "global", "test.md", 1)
assert result is None
def test_transform_link_with_custom_title(mock_link_maps) -> None:
"""Test link transformation with custom title."""
# Test with a known link and custom title
result = _transform_link("py-link", "python", "test.md", 1, "Custom Python Link")
assert result == "[Custom Python Link](https://example.com/python)"
# Test with unknown link and custom title (should still return None)
result = _transform_link("unknown-link", "python", "test.md", 1, "Custom Title")
assert result is None
def test_no_cross_refs(mock_link_maps) -> None:
"""Test markdown with no @[references]."""
lines = ["# Title\n", "Regular text.\n"]
markdown = "".join(lines)
result = _replace_autolinks(markdown, "test.md")
expected = "".join(["# Title\n", "Regular text.\n"])
assert result == expected
def test_global_cross_refs(mock_link_maps) -> None:
"""Test @[references] in global scope (no conditional blocks)."""
lines = ["@[global-link]\n", "Text with @[unknown-link].\n"]
markdown = "".join(lines)
result = _replace_autolinks(markdown, "test.md")
expected = "".join(["@[global-link]\n", "Text with @[unknown-link].\n"])
assert result == expected
def test_python_conditional_block(mock_link_maps) -> None:
"""Test @[references] inside Python conditional block."""
lines = [":::python\n", "@[py-link]\n", ":::\n"]
markdown = "".join(lines)
result = _replace_autolinks(markdown, "test.md")
expected = "".join(
[":::python\n", "[py-link](https://example.com/python)\n", ":::\n"]
)
assert result == expected
def test_js_conditional_block(mock_link_maps) -> None:
"""Test @[references] inside JavaScript conditional block."""
lines = [":::js\n", "@[js-link]\n", ":::\n"]
markdown = "".join(lines)
result = _replace_autolinks(markdown, "test.md")
expected = "".join([":::js\n", "[js-link](https://example.com/js)\n", ":::\n"])
assert result == expected
def test_all_scopes(mock_link_maps) -> None:
"""Test @[references] in global, Python, and JavaScript scopes."""
lines = [
"@[global-link]\n",
":::python\n",
"@[py-link]\n",
":::\n",
"@[global-link]\n",
":::js\n",
"@[js-link]\n",
":::\n",
"@[global-link]\n",
]
markdown = "".join(lines)
result = _replace_autolinks(markdown, "test.md")
expected = "".join(
[
"@[global-link]\n",
":::python\n",
"[py-link](https://example.com/python)\n",
":::\n",
"@[global-link]\n",
":::js\n",
"[js-link](https://example.com/js)\n",
":::\n",
"@[global-link]\n",
]
)
assert result == expected
def test_fence_resets_to_global(mock_link_maps) -> None:
"""Test that closing fence resets scope to global."""
lines = [":::python\n", "@[py-link]\n", ":::\n", "@[global-link]\n"]
markdown = "".join(lines)
result = _replace_autolinks(markdown, "test.md")
expected = "".join(
[
":::python\n",
"[py-link](https://example.com/python)\n",
":::\n",
"@[global-link]\n",
]
)
assert result == expected
def test_indented_conditional_fences(mock_link_maps) -> None:
"""Test @[references] inside indented conditional fences (e.g., in tabs or admonitions)."""
lines = [
"@[global-link]\n",
" :::python\n",
" @[py-link]\n",
" :::\n",
"@[global-link]\n",
"\t\t:::js\n",
"\t\t@[js-link]\n",
"\t\t:::\n",
"@[global-link]\n",
]
markdown = "".join(lines)
result = _replace_autolinks(markdown, "test.md")
expected = "".join(
[
"@[global-link]\n",
" :::python\n",
" [py-link](https://example.com/python)\n",
" :::\n",
"@[global-link]\n",
"\t\t:::js\n",
"\t\t[js-link](https://example.com/js)\n",
"\t\t:::\n",
"@[global-link]\n",
]
)
assert result == expected
def test_custom_title_syntax(mock_link_maps) -> None:
"""Test @[title][ref] syntax with custom titles."""
lines = [
":::python\n",
"@[Custom Python Title][py-link]\n",
":::\n",
":::js\n",
"@[Custom JS Title][js-link]\n",
":::\n"
]
markdown = "".join(lines)
result = _replace_autolinks(markdown, "test.md")
expected = "".join([
":::python\n",
"[Custom Python Title](https://example.com/python)\n",
":::\n",
":::js\n",
"[Custom JS Title](https://example.com/js)\n",
":::\n"
])
assert result == expected
def test_mixed_syntax_compatibility(mock_link_maps) -> None:
"""Test that both @[ref] and @[title][ref] syntax work together."""
lines = [
":::python\n",
"@[py-link]\n", # Old syntax
"@[Custom Title][py-link]\n", # New syntax
":::\n"
]
markdown = "".join(lines)
result = _replace_autolinks(markdown, "test.md")
expected = "".join([
":::python\n",
"[py-link](https://example.com/python)\n",
"[Custom Title](https://example.com/python)\n",
":::\n"
])
assert result == expected
def test_custom_title_with_unknown_link(mock_link_maps) -> None:
"""Test @[title][ref] syntax with unknown reference."""
lines = [
":::python\n",
"@[Custom Title][unknown-link]\n",
":::\n"
]
markdown = "".join(lines)
result = _replace_autolinks(markdown, "test.md")
expected = "".join([
":::python\n",
"@[Custom Title][unknown-link]\n", # Should remain unchanged
":::\n"
])
assert result == expected