add pytests
This commit is contained in:
@@ -40,6 +40,7 @@ dev = [
|
|||||||
"mypy",
|
"mypy",
|
||||||
"isort",
|
"isort",
|
||||||
"pre-commit",
|
"pre-commit",
|
||||||
|
"sphinx",
|
||||||
]
|
]
|
||||||
test = [
|
test = [
|
||||||
"pytest>=7.0.0",
|
"pytest>=7.0.0",
|
||||||
@@ -84,4 +85,5 @@ filterwarnings = [
|
|||||||
"error",
|
"error",
|
||||||
"ignore::UserWarning",
|
"ignore::UserWarning",
|
||||||
"ignore::DeprecationWarning",
|
"ignore::DeprecationWarning",
|
||||||
|
"ignore::PendingDeprecationWarning",
|
||||||
]
|
]
|
||||||
@@ -74,7 +74,9 @@ class LLMSFullManager:
|
|||||||
if toctree:
|
if toctree:
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
|
|
||||||
for node in toctree.traverse(nodes.reference):
|
# Use findall() instead of traverse() to avoid deprecation warning
|
||||||
|
# Convert generator to list for iteration
|
||||||
|
for node in list(toctree.findall(nodes.reference)):
|
||||||
if "refuri" in node.attributes:
|
if "refuri" in node.attributes:
|
||||||
refuri = node.attributes["refuri"]
|
refuri = node.attributes["refuri"]
|
||||||
if refuri and refuri.endswith(".html"):
|
if refuri and refuri.endswith(".html"):
|
||||||
@@ -239,9 +241,10 @@ def doctree_resolved(app: Sphinx, doctree, docname: str):
|
|||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
|
|
||||||
title = None
|
title = None
|
||||||
for node in doctree.traverse(nodes.title):
|
# findall() returns a generator, convert to list to check if it has elements
|
||||||
title = node.astext()
|
title_nodes = list(doctree.findall(nodes.title))
|
||||||
break
|
if title_nodes:
|
||||||
|
title = title_nodes[0].astext()
|
||||||
|
|
||||||
if title:
|
if title:
|
||||||
_manager.update_page_title(docname, title)
|
_manager.update_page_title(docname, title)
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
"""Pytest configuration for sphinx-llms-txt."""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import tempfile
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
# Use Path directly instead of sphinx_path to avoid deprecation warning
|
||||||
|
from sphinx.testing.util import SphinxTestApp
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def rootdir():
|
||||||
|
"""Get the root directory for test projects."""
|
||||||
|
return Path(os.path.dirname(__file__) or ".").absolute() / "roots"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def temp_dir():
|
||||||
|
"""Create a temporary directory and delete it after the test."""
|
||||||
|
temp_path = Path(tempfile.mkdtemp())
|
||||||
|
yield temp_path
|
||||||
|
shutil.rmtree(temp_path, ignore_errors=True)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def basic_sphinx_app(temp_dir, rootdir):
|
||||||
|
"""Create a basic Sphinx app for testing."""
|
||||||
|
src_dir = rootdir / "basic"
|
||||||
|
app = SphinxTestApp(
|
||||||
|
srcdir=src_dir,
|
||||||
|
builddir=temp_dir,
|
||||||
|
buildername="html",
|
||||||
|
freshenv=True,
|
||||||
|
)
|
||||||
|
yield app
|
||||||
|
|
||||||
|
# Custom cleanup to avoid missing_ok issue
|
||||||
|
import sys
|
||||||
|
from sphinx.testing.util import _clean_up_global_state
|
||||||
|
|
||||||
|
sys.path[:] = app._saved_path
|
||||||
|
_clean_up_global_state()
|
||||||
|
|
||||||
|
# Safe unlink that works with older Python versions
|
||||||
|
if hasattr(app, "docutils_conf_path") and app.docutils_conf_path.exists():
|
||||||
|
app.docutils_conf_path.unlink()
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
"""Configuration file for the basic Sphinx project."""
|
||||||
|
|
||||||
|
project = "Test Project"
|
||||||
|
copyright = "2025, Test"
|
||||||
|
author = "Test"
|
||||||
|
|
||||||
|
extensions = [
|
||||||
|
"sphinx_llms_txt",
|
||||||
|
]
|
||||||
|
|
||||||
|
templates_path = ["_templates"]
|
||||||
|
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
|
||||||
|
|
||||||
|
html_theme = "alabaster"
|
||||||
|
html_static_path = ["_static"]
|
||||||
|
|
||||||
|
# Configuration for sphinx-llms-txt
|
||||||
|
llms_txt_filename = "test-llms-full.txt"
|
||||||
|
llms_txt_verbose = True
|
||||||
|
|
||||||
|
# Master document
|
||||||
|
master_doc = "index"
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
"""Configuration file for the basic Sphinx project."""
|
||||||
|
|
||||||
|
project = "Test Project"
|
||||||
|
copyright = "2025, Test"
|
||||||
|
author = "Test"
|
||||||
|
|
||||||
|
extensions = [
|
||||||
|
"sphinx_llms_txt",
|
||||||
|
]
|
||||||
|
|
||||||
|
templates_path = ["_templates"]
|
||||||
|
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
|
||||||
|
|
||||||
|
html_theme = "alabaster"
|
||||||
|
html_static_path = ["_static"]
|
||||||
|
|
||||||
|
# Configuration for sphinx-llms-txt
|
||||||
|
llms_txt_filename = "custom-name.txt"
|
||||||
|
llms_txt_verbose = True
|
||||||
|
|
||||||
|
# Master document
|
||||||
|
master_doc = "index"
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
Welcome to Test Project's documentation!
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
:caption: Contents:
|
||||||
|
|
||||||
|
page1
|
||||||
|
page2
|
||||||
|
|
||||||
|
Indices and tables
|
||||||
|
==================
|
||||||
|
|
||||||
|
* :ref:`genindex`
|
||||||
|
* :ref:`modindex`
|
||||||
|
* :ref:`search`
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
Page 1 Title
|
||||||
|
===========
|
||||||
|
|
||||||
|
This is the content of page 1.
|
||||||
|
|
||||||
|
Section 1
|
||||||
|
---------
|
||||||
|
|
||||||
|
Content for section 1.
|
||||||
|
|
||||||
|
Section 2
|
||||||
|
---------
|
||||||
|
|
||||||
|
Content for section 2.
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
Page 2 Title
|
||||||
|
===========
|
||||||
|
|
||||||
|
This is the content of page 2.
|
||||||
|
|
||||||
|
Section A
|
||||||
|
---------
|
||||||
|
|
||||||
|
Content for section A.
|
||||||
|
|
||||||
|
Section B
|
||||||
|
---------
|
||||||
|
|
||||||
|
Content for section B.
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
"""Integration tests for sphinx-llms-txt."""
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def test_build_html_with_llms_txt(basic_sphinx_app):
|
||||||
|
"""Test building HTML documentation with llms-txt enabled."""
|
||||||
|
app = basic_sphinx_app
|
||||||
|
app.build()
|
||||||
|
|
||||||
|
# Check if the output file was created
|
||||||
|
output_file = Path(app.outdir) / "test-llms-full.txt"
|
||||||
|
assert output_file.exists(), f"Output file {output_file} does not exist"
|
||||||
|
|
||||||
|
# Read the content of the output file
|
||||||
|
content = output_file.read_text()
|
||||||
|
|
||||||
|
# Check that content from all pages is included
|
||||||
|
assert "Welcome to Test Project's documentation!" in content
|
||||||
|
assert "Page 1 Title" in content
|
||||||
|
assert "Page 2 Title" in content
|
||||||
|
assert "Content for section 1" in content
|
||||||
|
assert "Content for section A" in content
|
||||||
|
|
||||||
|
|
||||||
|
def test_custom_filename(temp_dir, rootdir):
|
||||||
|
"""Test using a custom filename for the output."""
|
||||||
|
from sphinx.testing.util import SphinxTestApp
|
||||||
|
|
||||||
|
src_dir = rootdir / "basic"
|
||||||
|
|
||||||
|
# Create a copy of the configuration with a different filename
|
||||||
|
custom_conf = src_dir / "conf_custom.py"
|
||||||
|
with open(src_dir / "conf.py") as f:
|
||||||
|
conf_content = f.read()
|
||||||
|
|
||||||
|
conf_content = conf_content.replace(
|
||||||
|
'llms_txt_filename = "test-llms-full.txt"',
|
||||||
|
'llms_txt_filename = "custom-name.txt"',
|
||||||
|
)
|
||||||
|
|
||||||
|
with open(custom_conf, "w") as f:
|
||||||
|
f.write(conf_content)
|
||||||
|
|
||||||
|
# Create a new test app with the custom configuration
|
||||||
|
app = SphinxTestApp(
|
||||||
|
srcdir=src_dir,
|
||||||
|
builddir=temp_dir,
|
||||||
|
buildername="html",
|
||||||
|
freshenv=True,
|
||||||
|
confoverrides={"llms_txt_filename": "custom-name.txt"},
|
||||||
|
)
|
||||||
|
|
||||||
|
app.build()
|
||||||
|
|
||||||
|
# Check if the output file with the custom name was created
|
||||||
|
output_file = Path(app.outdir) / "custom-name.txt"
|
||||||
|
assert output_file.exists(), f"Output file {output_file} does not exist"
|
||||||
|
|
||||||
|
# Custom cleanup to avoid missing_ok issue
|
||||||
|
import sys
|
||||||
|
from sphinx.testing.util import _clean_up_global_state
|
||||||
|
|
||||||
|
sys.path[:] = app._saved_path
|
||||||
|
_clean_up_global_state()
|
||||||
|
|
||||||
|
# Safe unlink that works with older Python versions
|
||||||
|
if hasattr(app, "docutils_conf_path") and app.docutils_conf_path.exists():
|
||||||
|
app.docutils_conf_path.unlink()
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
"""Test the sphinx_llms_txt extension."""
|
||||||
|
|
||||||
|
from sphinx_llms_txt import LLMSFullManager, setup
|
||||||
|
|
||||||
|
|
||||||
|
def test_version():
|
||||||
|
"""Test that the version is defined."""
|
||||||
|
from sphinx_llms_txt import __version__
|
||||||
|
|
||||||
|
assert __version__
|
||||||
|
|
||||||
|
|
||||||
|
def test_setup_returns_valid_dict():
|
||||||
|
"""Test that the setup function returns a valid dict."""
|
||||||
|
|
||||||
|
# Mock a Sphinx app
|
||||||
|
class MockApp:
|
||||||
|
def __init__(self):
|
||||||
|
self.config_values = {}
|
||||||
|
self.connections = {}
|
||||||
|
|
||||||
|
def add_config_value(self, name, default, rebuild):
|
||||||
|
self.config_values[name] = (default, rebuild)
|
||||||
|
|
||||||
|
def connect(self, event, handler):
|
||||||
|
self.connections[event] = handler
|
||||||
|
|
||||||
|
app = MockApp()
|
||||||
|
result = setup(app)
|
||||||
|
|
||||||
|
# Check that result is a dict
|
||||||
|
assert isinstance(result, dict)
|
||||||
|
assert "version" in result
|
||||||
|
assert "parallel_read_safe" in result
|
||||||
|
assert "parallel_write_safe" in result
|
||||||
|
|
||||||
|
|
||||||
|
def test_llms_full_manager_initialization():
|
||||||
|
"""Test initialization of LLMSFullManager."""
|
||||||
|
manager = LLMSFullManager()
|
||||||
|
assert manager.page_titles == {}
|
||||||
|
assert manager.config == {}
|
||||||
|
assert manager.master_doc is None
|
||||||
|
assert manager.env is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_manager_page_title_update():
|
||||||
|
"""Test updating page titles."""
|
||||||
|
manager = LLMSFullManager()
|
||||||
|
manager.update_page_title("doc1", "Title 1")
|
||||||
|
manager.update_page_title("doc2", "Title 2")
|
||||||
|
|
||||||
|
assert manager.page_titles["doc1"] == "Title 1"
|
||||||
|
assert manager.page_titles["doc2"] == "Title 2"
|
||||||
|
|
||||||
|
|
||||||
|
def test_set_config():
|
||||||
|
"""Test setting configuration."""
|
||||||
|
manager = LLMSFullManager()
|
||||||
|
config = {
|
||||||
|
"llms_txt_filename": "custom.txt",
|
||||||
|
"llms_txt_verbose": True,
|
||||||
|
}
|
||||||
|
manager.set_config(config)
|
||||||
|
assert manager.config == config
|
||||||
|
|
||||||
|
|
||||||
|
def test_set_master_doc():
|
||||||
|
"""Test setting master doc."""
|
||||||
|
manager = LLMSFullManager()
|
||||||
|
manager.set_master_doc("index")
|
||||||
|
assert manager.master_doc == "index"
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_page_order():
|
||||||
|
"""Test get_page_order returns empty list when env or master_doc not set."""
|
||||||
|
manager = LLMSFullManager()
|
||||||
|
assert manager.get_page_order() == []
|
||||||
|
|
||||||
|
# Set only master_doc, but not env
|
||||||
|
manager.set_master_doc("index")
|
||||||
|
assert manager.get_page_order() == []
|
||||||
Reference in New Issue
Block a user