RA.Aid/tests/ra_aid/tools/test_file_str_replace.py

169 lines
5.2 KiB
Python

import os
from unittest.mock import patch
import pytest
from ra_aid.tools.file_str_replace import file_str_replace
@pytest.fixture
def temp_test_dir(tmp_path):
"""Create a temporary test directory."""
test_dir = tmp_path / "test_replace_dir"
test_dir.mkdir(exist_ok=True)
return test_dir
def test_basic_replacement(temp_test_dir):
"""Test basic string replacement functionality."""
test_file = temp_test_dir / "test.txt"
initial_content = "Hello world! This is a test."
test_file.write_text(initial_content)
result = file_str_replace.invoke(
{"filepath": str(test_file), "old_str": "world", "new_str": "universe"}
)
assert result["success"] is True
assert test_file.read_text() == "Hello universe! This is a test."
assert "Successfully replaced" in result["message"]
def test_file_not_found():
"""Test handling of non-existent file."""
result = file_str_replace.invoke(
{"filepath": "nonexistent.txt", "old_str": "test", "new_str": "replacement"}
)
assert result["success"] is False
assert "File not found" in result["message"]
def test_string_not_found(temp_test_dir):
"""Test handling of string not present in file."""
test_file = temp_test_dir / "test.txt"
test_file.write_text("Hello world!")
result = file_str_replace.invoke(
{"filepath": str(test_file), "old_str": "nonexistent", "new_str": "replacement"}
)
assert result["success"] is False
assert "String not found" in result["message"]
def test_multiple_occurrences(temp_test_dir):
"""Test handling of multiple string occurrences."""
test_file = temp_test_dir / "test.txt"
test_file.write_text("test test test")
result = file_str_replace.invoke(
{"filepath": str(test_file), "old_str": "test", "new_str": "replacement"}
)
assert result["success"] is False
assert "appears" in result["message"]
assert "must be unique" in result["message"]
def test_empty_strings(temp_test_dir):
"""Test handling of empty strings."""
test_file = temp_test_dir / "test.txt"
test_file.write_text("Hello world!")
# Test empty old string
result1 = file_str_replace.invoke(
{"filepath": str(test_file), "old_str": "", "new_str": "replacement"}
)
assert result1["success"] is False
# Test empty new string
result2 = file_str_replace.invoke(
{"filepath": str(test_file), "old_str": "world", "new_str": ""}
)
assert result2["success"] is True
assert test_file.read_text() == "Hello !"
def test_special_characters(temp_test_dir):
"""Test handling of special characters."""
test_file = temp_test_dir / "test.txt"
initial_content = "Hello\nworld!\t\r\nSpecial chars: $@#%"
test_file.write_text(initial_content)
result = file_str_replace.invoke(
{
"filepath": str(test_file),
"old_str": "Special chars: $@#%",
"new_str": "Replaced!",
}
)
assert result["success"] is True
assert "Special chars: $@#%" not in test_file.read_text()
assert "Replaced!" in test_file.read_text()
@patch("pathlib.Path.read_text")
def test_io_error(mock_read_text, temp_test_dir):
"""Test handling of IO errors during read."""
# Create and write to file first
test_file = temp_test_dir / "test.txt"
test_file.write_text("some test content")
# Then mock read_text to raise error
mock_read_text.side_effect = IOError("Failed to read file")
result = file_str_replace.invoke(
{"filepath": str(test_file), "old_str": "test", "new_str": "replacement"}
)
assert result["success"] is False
assert "Failed to read file" in result["message"]
def test_permission_error(temp_test_dir):
"""Test handling of permission errors."""
test_file = temp_test_dir / "readonly.txt"
test_file.write_text("test content")
os.chmod(test_file, 0o444) # Make file read-only
try:
result = file_str_replace.invoke(
{"filepath": str(test_file), "old_str": "test", "new_str": "replacement"}
)
assert result["success"] is False
assert "Permission" in result["message"] or "Error" in result["message"]
finally:
os.chmod(test_file, 0o644) # Restore permissions for cleanup
def test_unicode_strings(temp_test_dir):
"""Test handling of Unicode strings."""
test_file = temp_test_dir / "unicode.txt"
initial_content = "Hello 世界! Unicode テスト"
test_file.write_text(initial_content)
result = file_str_replace.invoke(
{"filepath": str(test_file), "old_str": "世界", "new_str": "ワールド"}
)
assert result["success"] is True
assert "世界" not in test_file.read_text()
assert "ワールド" in test_file.read_text()
def test_long_string_truncation(temp_test_dir):
"""Test handling and truncation of very long strings."""
test_file = temp_test_dir / "test.txt"
long_string = "x" * 100
test_file.write_text(f"prefix {long_string} suffix")
result = file_str_replace.invoke(
{"filepath": str(test_file), "old_str": long_string, "new_str": "replaced"}
)
assert result["success"] is True
assert test_file.read_text() == "prefix replaced suffix"