Files

130 lines
3.8 KiB
Python

from __future__ import annotations
import importlib.util
from pathlib import Path
from types import ModuleType
import pytest
SCRIPT_PATH = Path(__file__).resolve().parents[2] / "docs" / "scripts" / "translate_docs.py"
SOURCE = """# Agents
## Dynamic instructions
Text.
## Example
```python
# not a heading
```
## Example
"""
TRANSLATED = """# エージェント
## 動的な指示
本文。
## 例
```python
# not a heading
```
## 例
"""
@pytest.fixture
def translate_docs(monkeypatch: pytest.MonkeyPatch) -> ModuleType:
# The script builds an OpenAI client at import time; nothing here sends a request.
monkeypatch.setenv("OPENAI_API_KEY", "test-key")
spec = importlib.util.spec_from_file_location("translate_docs", SCRIPT_PATH)
assert spec is not None and spec.loader is not None
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
def test_translated_headings_carry_the_english_ids(translate_docs: ModuleType) -> None:
result = translate_docs.preserve_heading_anchors(SOURCE, TRANSLATED)
assert "## 動的な指示 {#dynamic-instructions}\n" in result
assert "## 例 {#example}\n" in result
assert "## 例 {#example_1}\n" in result
# The H1 is left for mkdocs to read the page title from.
assert result.startswith("# エージェント\n")
# A comment inside a fenced block is not a heading.
assert "# not a heading\n" in result
assert "# not a heading {#" not in result
def test_heading_ids_come_from_the_rendered_english_headings(translate_docs: ModuleType) -> None:
source = (
"## Using `Agent` with [tools](tools.md)\n\n"
"## [API][ref]\n\n"
"## A & B\n\n"
"## <code>run</code> loop\n\n"
"[ref]: https://example.com\n"
)
translated = "## `Agent` とツール\n\n## API\n\n## A と B\n\n## 実行ループ\n"
result = translate_docs.preserve_heading_anchors(source, translated)
assert result == (
"## `Agent` とツール {#using-agent-with-tools}\n\n"
"## API {#api}\n\n"
"## A と B {#a-b}\n\n"
"## 実行ループ {#run-loop}\n"
)
def test_preserve_heading_anchors_is_idempotent(translate_docs: ModuleType) -> None:
once = translate_docs.preserve_heading_anchors(SOURCE, TRANSLATED)
assert translate_docs.preserve_heading_anchors(SOURCE, once) == once
def test_an_id_written_earlier_follows_the_english_heading(translate_docs: ModuleType) -> None:
result = translate_docs.preserve_heading_anchors("## Alpha\n", "## アルファ {#old}\n")
assert result == "## アルファ {#alpha}\n"
def test_mismatched_headings_are_left_alone(translate_docs: ModuleType) -> None:
missing_one_heading = TRANSLATED.replace("\n## 例\n", "\n", 1)
result = translate_docs.preserve_heading_anchors(SOURCE, missing_one_heading)
assert result == missing_one_heading
def test_an_english_setext_heading_still_yields_its_id(translate_docs: ModuleType) -> None:
# The English side goes through the parser, so setext is just another heading there.
source = "Alpha\n-----\n\n## Beta\n"
translated = "## アルファ\n\n## ベータ\n"
result = translate_docs.preserve_heading_anchors(source, translated)
assert result == "## アルファ {#alpha}\n\n## ベータ {#beta}\n"
def test_a_setext_heading_in_the_translation_is_outside_the_contract(
translate_docs: ModuleType,
) -> None:
source = "## Alpha\n\n## Beta\n"
translated = "アルファ\n-----\n\n## ベータ\n"
assert translate_docs.preserve_heading_anchors(source, translated) == translated
def test_a_heading_with_its_own_attribute_list_is_not_rewritten(translate_docs: ModuleType) -> None:
source = "## Alpha\n\n## Beta\n"
translated = "## アルファ {.lead}\n\n## ベータ\n"
assert translate_docs.preserve_heading_anchors(source, translated) == translated