Files
wehub-resource-sync b7f52be4c9
CI / Run CI (push) Has been cancelled
CI / check-backend (push) Has been cancelled
CI / check-frontend (push) Has been cancelled
CI / tests (push) Has been cancelled
CI / e2e-tests (push) Has been cancelled
Copilot Setup Steps / copilot-setup-steps (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:48:47 +08:00

323 lines
13 KiB
Python

import os
import tempfile
from unittest.mock import patch
import pytest
from chainlit.markdown import DEFAULT_MARKDOWN_STR, get_markdown_str, init_markdown
class TestInitMarkdown:
"""Test suite for init_markdown function."""
def test_init_markdown_creates_file(self):
"""Test that init_markdown creates chainlit.md if it doesn't exist."""
with tempfile.TemporaryDirectory() as tmpdir:
init_markdown(tmpdir)
chainlit_md_path = os.path.join(tmpdir, "chainlit.md")
assert os.path.exists(chainlit_md_path)
# Verify content is the default markdown
with open(chainlit_md_path, encoding="utf-8") as f:
content = f.read()
assert content == DEFAULT_MARKDOWN_STR
def test_init_markdown_does_not_overwrite_existing(self):
"""Test that init_markdown doesn't overwrite existing chainlit.md."""
with tempfile.TemporaryDirectory() as tmpdir:
chainlit_md_path = os.path.join(tmpdir, "chainlit.md")
custom_content = "# My Custom Markdown"
# Create existing file
with open(chainlit_md_path, "w", encoding="utf-8") as f:
f.write(custom_content)
# Call init_markdown
init_markdown(tmpdir)
# Verify content is unchanged
with open(chainlit_md_path, encoding="utf-8") as f:
content = f.read()
assert content == custom_content
def test_init_markdown_with_nonexistent_directory(self):
"""Test init_markdown with a directory that doesn't exist."""
with tempfile.TemporaryDirectory() as tmpdir:
nonexistent_dir = os.path.join(tmpdir, "nonexistent")
# Should raise an error when trying to create file in nonexistent dir
with pytest.raises(FileNotFoundError):
init_markdown(nonexistent_dir)
def test_init_markdown_creates_utf8_file(self):
"""Test that init_markdown creates file with UTF-8 encoding."""
with tempfile.TemporaryDirectory() as tmpdir:
init_markdown(tmpdir)
chainlit_md_path = os.path.join(tmpdir, "chainlit.md")
# Verify UTF-8 encoding by reading with explicit encoding
with open(chainlit_md_path, encoding="utf-8") as f:
content = f.read()
# Should contain emoji characters from DEFAULT_MARKDOWN_STR
assert "🚀" in content
assert "🤖" in content
class TestGetMarkdownStr:
"""Test suite for get_markdown_str function."""
def test_get_markdown_str_returns_default(self):
"""Test get_markdown_str returns default chainlit.md content."""
with tempfile.TemporaryDirectory() as tmpdir:
chainlit_md_path = os.path.join(tmpdir, "chainlit.md")
content = "# Default Chainlit Markdown"
with open(chainlit_md_path, "w", encoding="utf-8") as f:
f.write(content)
result = get_markdown_str(tmpdir, "en")
assert result == content
def test_get_markdown_str_returns_translated(self):
"""Test get_markdown_str returns translated markdown when available."""
with tempfile.TemporaryDirectory() as tmpdir:
# Create default markdown
default_content = "# Default English"
with open(os.path.join(tmpdir, "chainlit.md"), "w", encoding="utf-8") as f:
f.write(default_content)
# Create translated markdown
translated_content = "# Français"
with open(
os.path.join(tmpdir, "chainlit_fr.md"), "w", encoding="utf-8"
) as f:
f.write(translated_content)
result = get_markdown_str(tmpdir, "fr")
assert result == translated_content
def test_get_markdown_str_falls_back_to_default(self):
"""Test get_markdown_str falls back to default when translation missing."""
with tempfile.TemporaryDirectory() as tmpdir:
default_content = "# Default English"
with open(os.path.join(tmpdir, "chainlit.md"), "w", encoding="utf-8") as f:
f.write(default_content)
# Request non-existent translation
with patch("chainlit.markdown.logger") as mock_logger:
result = get_markdown_str(tmpdir, "es")
assert result == default_content
mock_logger.warning.assert_called_once()
assert "es" in str(mock_logger.warning.call_args)
def test_get_markdown_str_returns_none_when_no_file(self):
"""Test get_markdown_str returns None when no markdown file exists."""
with tempfile.TemporaryDirectory() as tmpdir:
result = get_markdown_str(tmpdir, "en")
assert result is None
def test_get_markdown_str_with_utf8_content(self):
"""Test get_markdown_str handles UTF-8 content correctly."""
with tempfile.TemporaryDirectory() as tmpdir:
content = "# Welcome 欢迎 🎉\n\nこんにちは"
with open(os.path.join(tmpdir, "chainlit.md"), "w", encoding="utf-8") as f:
f.write(content)
result = get_markdown_str(tmpdir, "en")
assert result == content
assert "欢迎" in result
assert "こんにちは" in result
def test_get_markdown_str_prevents_path_traversal(self):
"""Test get_markdown_str prevents path traversal attacks."""
with tempfile.TemporaryDirectory() as tmpdir:
# Create default markdown
default_content = "# Default"
with open(os.path.join(tmpdir, "chainlit.md"), "w", encoding="utf-8") as f:
f.write(default_content)
# Try to access file outside root using path traversal
# The is_path_inside check should prevent this
result = get_markdown_str(tmpdir, "../../../etc/passwd")
# Should fall back to default since traversal is blocked
assert result == default_content
def test_get_markdown_str_with_multiple_languages(self):
"""Test get_markdown_str with multiple language files."""
with tempfile.TemporaryDirectory() as tmpdir:
# Create multiple language files
languages = {
"en": "# English",
"fr": "# Français",
"es": "# Español",
"ja": "# 日本語",
}
# Create default
with open(os.path.join(tmpdir, "chainlit.md"), "w", encoding="utf-8") as f:
f.write(languages["en"])
# Create translations
for lang, content in languages.items():
if lang != "en":
path = os.path.join(tmpdir, f"chainlit_{lang}.md")
with open(path, "w", encoding="utf-8") as f:
f.write(content)
# Test each language
for lang, expected_content in languages.items():
result = get_markdown_str(tmpdir, lang)
assert result == expected_content
def test_get_markdown_str_with_empty_file(self):
"""Test get_markdown_str with empty markdown file."""
with tempfile.TemporaryDirectory() as tmpdir:
# Create empty file
with open(os.path.join(tmpdir, "chainlit.md"), "w", encoding="utf-8") as f:
f.write("")
result = get_markdown_str(tmpdir, "en")
assert result == ""
def test_get_markdown_str_with_large_file(self):
"""Test get_markdown_str with large markdown file."""
with tempfile.TemporaryDirectory() as tmpdir:
# Create large content
large_content = "# Header\n" + ("Lorem ipsum dolor sit amet.\n" * 1000)
with open(os.path.join(tmpdir, "chainlit.md"), "w", encoding="utf-8") as f:
f.write(large_content)
result = get_markdown_str(tmpdir, "en")
assert result == large_content
assert len(result) > 10000
class TestDefaultMarkdownStr:
"""Test suite for DEFAULT_MARKDOWN_STR constant."""
def test_default_markdown_str_is_string(self):
"""Test that DEFAULT_MARKDOWN_STR is a string."""
assert isinstance(DEFAULT_MARKDOWN_STR, str)
def test_default_markdown_str_not_empty(self):
"""Test that DEFAULT_MARKDOWN_STR is not empty."""
assert len(DEFAULT_MARKDOWN_STR) > 0
def test_default_markdown_str_contains_welcome(self):
"""Test that DEFAULT_MARKDOWN_STR contains welcome message."""
assert "Welcome to Chainlit" in DEFAULT_MARKDOWN_STR
def test_default_markdown_str_contains_links(self):
"""Test that DEFAULT_MARKDOWN_STR contains useful links."""
assert "Documentation" in DEFAULT_MARKDOWN_STR
assert "Discord" in DEFAULT_MARKDOWN_STR
assert "https://docs.chainlit.io" in DEFAULT_MARKDOWN_STR
def test_default_markdown_str_is_valid_markdown(self):
"""Test that DEFAULT_MARKDOWN_STR contains valid markdown syntax."""
assert "#" in DEFAULT_MARKDOWN_STR # Headers
assert "**" in DEFAULT_MARKDOWN_STR # Bold
assert "[" in DEFAULT_MARKDOWN_STR # Links
assert "](" in DEFAULT_MARKDOWN_STR # Link syntax
class TestMarkdownEdgeCases:
"""Test suite for markdown edge cases."""
def test_init_markdown_with_special_characters_in_path(self):
"""Test init_markdown with special characters in directory path."""
with tempfile.TemporaryDirectory() as tmpdir:
special_dir = os.path.join(tmpdir, "test dir with spaces")
os.makedirs(special_dir)
init_markdown(special_dir)
chainlit_md_path = os.path.join(special_dir, "chainlit.md")
assert os.path.exists(chainlit_md_path)
def test_get_markdown_str_with_symlink(self):
"""Test get_markdown_str with symlinked markdown file."""
with tempfile.TemporaryDirectory() as tmpdir:
# Create original file
original_dir = os.path.join(tmpdir, "original")
os.makedirs(original_dir)
original_file = os.path.join(original_dir, "chainlit.md")
content = "# Original Content"
with open(original_file, "w", encoding="utf-8") as f:
f.write(content)
# Create symlink directory
link_dir = os.path.join(tmpdir, "link")
os.makedirs(link_dir)
link_file = os.path.join(link_dir, "chainlit.md")
# Create symlink (skip on Windows if no permissions)
try:
os.symlink(original_file, link_file)
result = get_markdown_str(link_dir, "en")
assert result == content
except OSError:
pytest.skip("Symlink creation not supported")
def test_get_markdown_str_with_relative_path(self):
"""Test get_markdown_str with relative path."""
with tempfile.TemporaryDirectory() as tmpdir:
content = "# Test Content"
with open(os.path.join(tmpdir, "chainlit.md"), "w", encoding="utf-8") as f:
f.write(content)
# Use relative path
original_cwd = os.getcwd()
try:
os.chdir(tmpdir)
result = get_markdown_str(".", "en")
assert result == content
finally:
os.chdir(original_cwd)
def test_get_markdown_str_language_case_sensitivity(self):
"""Test get_markdown_str language code is used as-is in filename."""
with tempfile.TemporaryDirectory() as tmpdir:
default_content = "# Default"
with open(os.path.join(tmpdir, "chainlit.md"), "w", encoding="utf-8") as f:
f.write(default_content)
# Create a language file
fr_content = "# Français"
with open(
os.path.join(tmpdir, "chainlit_fr.md"), "w", encoding="utf-8"
) as f:
f.write(fr_content)
# Test exact match - should get the file
result = get_markdown_str(tmpdir, "fr")
assert result == fr_content
# Test different case that doesn't exist - should fall back to default
# Note: On case-insensitive file systems (Windows), this might still find the file
# On case-sensitive file systems (Linux), it will fall back to default
with patch("chainlit.markdown.logger"):
result_different = get_markdown_str(tmpdir, "es")
assert result_different == default_content
def test_init_markdown_concurrent_calls(self):
"""Test init_markdown with concurrent calls (race condition)."""
with tempfile.TemporaryDirectory() as tmpdir:
# Call init_markdown multiple times
init_markdown(tmpdir)
init_markdown(tmpdir)
init_markdown(tmpdir)
# Should only have one file with default content
chainlit_md_path = os.path.join(tmpdir, "chainlit.md")
assert os.path.exists(chainlit_md_path)
with open(chainlit_md_path, encoding="utf-8") as f:
content = f.read()
assert content == DEFAULT_MARKDOWN_STR