remove multiline
This commit is contained in:
@@ -5,7 +5,6 @@ Tests verify:
|
||||
- Operator class exists and is properly structured
|
||||
- PRO-only access control via poll()
|
||||
- Text processing and limit enforcement
|
||||
- Single-line validation (rejects newlines)
|
||||
- Proper Blender operator contract
|
||||
"""
|
||||
|
||||
@@ -14,62 +13,62 @@ from unittest.mock import Mock, MagicMock, patch
|
||||
|
||||
|
||||
class TestModalTextEditorOperator:
|
||||
"""Test suite for TEXT_TEXTURE_OT_edit_multiline_text operator."""
|
||||
"""Test suite for TEXT_TEXTURE_OT_edit_text operator."""
|
||||
|
||||
def test_operator_class_exists(self):
|
||||
"""Operator class must be importable and follow Blender conventions."""
|
||||
from src.operators.text_editor_ops import TEXT_TEXTURE_OT_edit_multiline_text
|
||||
from src.operators.text_editor_ops import TEXT_TEXTURE_OT_edit_text
|
||||
|
||||
assert hasattr(TEXT_TEXTURE_OT_edit_multiline_text, 'bl_idname')
|
||||
assert TEXT_TEXTURE_OT_edit_multiline_text.bl_idname == "text_texture.edit_multiline_text"
|
||||
assert hasattr(TEXT_TEXTURE_OT_edit_multiline_text, 'bl_label')
|
||||
assert hasattr(TEXT_TEXTURE_OT_edit_multiline_text, 'poll')
|
||||
assert hasattr(TEXT_TEXTURE_OT_edit_multiline_text, 'invoke')
|
||||
assert hasattr(TEXT_TEXTURE_OT_edit_multiline_text, 'execute')
|
||||
assert hasattr(TEXT_TEXTURE_OT_edit_multiline_text, 'draw')
|
||||
assert hasattr(TEXT_TEXTURE_OT_edit_text, 'bl_idname')
|
||||
assert TEXT_TEXTURE_OT_edit_text.bl_idname == "text_texture.edit_text"
|
||||
assert hasattr(TEXT_TEXTURE_OT_edit_text, 'bl_label')
|
||||
assert hasattr(TEXT_TEXTURE_OT_edit_text, 'poll')
|
||||
assert hasattr(TEXT_TEXTURE_OT_edit_text, 'invoke')
|
||||
assert hasattr(TEXT_TEXTURE_OT_edit_text, 'execute')
|
||||
assert hasattr(TEXT_TEXTURE_OT_edit_text, 'draw')
|
||||
|
||||
def test_poll_denies_access_in_free_version(self):
|
||||
"""poll() must return False when has_multiline_text() is False (FREE version)."""
|
||||
from src.operators.text_editor_ops import TEXT_TEXTURE_OT_edit_multiline_text
|
||||
"""poll() must return False when has_text_editor() is False (FREE version)."""
|
||||
from src.operators.text_editor_ops import TEXT_TEXTURE_OT_edit_text
|
||||
|
||||
mock_context = Mock()
|
||||
|
||||
with patch('src.operators.text_editor_ops.has_multiline_text', return_value=False):
|
||||
result = TEXT_TEXTURE_OT_edit_multiline_text.poll(mock_context)
|
||||
assert result is False, "FREE version should not have access to multiline editor"
|
||||
with patch('src.operators.text_editor_ops.has_text_editor', return_value=False):
|
||||
result = TEXT_TEXTURE_OT_edit_text.poll(mock_context)
|
||||
assert result is False, "FREE version should not have access to text editor"
|
||||
|
||||
def test_poll_allows_access_in_pro_version(self):
|
||||
"""poll() must return True when has_multiline_text() is True (PRO version)."""
|
||||
from src.operators.text_editor_ops import TEXT_TEXTURE_OT_edit_multiline_text
|
||||
"""poll() must return True when has_text_editor() is True (PRO version)."""
|
||||
from src.operators.text_editor_ops import TEXT_TEXTURE_OT_edit_text
|
||||
|
||||
mock_context = Mock()
|
||||
|
||||
with patch('src.operators.text_editor_ops.has_multiline_text', return_value=True):
|
||||
result = TEXT_TEXTURE_OT_edit_multiline_text.poll(mock_context)
|
||||
assert result is True, "PRO version should have access to multiline editor"
|
||||
with patch('src.operators.text_editor_ops.has_text_editor', return_value=True):
|
||||
result = TEXT_TEXTURE_OT_edit_text.poll(mock_context)
|
||||
assert result is True, "PRO version should have access to text editor"
|
||||
|
||||
def test_invoke_copies_current_text_to_temp(self):
|
||||
"""invoke() must copy scene text property to temp_text for editing."""
|
||||
from src.operators.text_editor_ops import TEXT_TEXTURE_OT_edit_multiline_text
|
||||
from src.operators.text_editor_ops import TEXT_TEXTURE_OT_edit_text
|
||||
|
||||
operator = TEXT_TEXTURE_OT_edit_multiline_text()
|
||||
operator = TEXT_TEXTURE_OT_edit_text()
|
||||
mock_context = Mock()
|
||||
mock_context.scene.text_texture_props.text = "Single line text"
|
||||
mock_context.scene.text_texture_props.text = "Test text"
|
||||
mock_context.window_manager.invoke_props_dialog.return_value = {'RUNNING_MODAL'}
|
||||
mock_event = Mock()
|
||||
|
||||
result = operator.invoke(mock_context, mock_event)
|
||||
|
||||
assert operator.temp_text == "Single line text"
|
||||
assert operator.temp_text == "Test text"
|
||||
assert result == {'RUNNING_MODAL'}
|
||||
mock_context.window_manager.invoke_props_dialog.assert_called_once()
|
||||
|
||||
def test_execute_saves_temp_text_back_to_property(self):
|
||||
"""execute() must save edited temp_text back to scene property."""
|
||||
from src.operators.text_editor_ops import TEXT_TEXTURE_OT_edit_multiline_text
|
||||
from src.operators.text_editor_ops import TEXT_TEXTURE_OT_edit_text
|
||||
|
||||
operator = TEXT_TEXTURE_OT_edit_multiline_text()
|
||||
operator.temp_text = "Edited single line"
|
||||
operator = TEXT_TEXTURE_OT_edit_text()
|
||||
operator.temp_text = "Edited text"
|
||||
|
||||
mock_context = Mock()
|
||||
mock_context.scene.text_texture_props.text = "Old text"
|
||||
@@ -77,13 +76,13 @@ class TestModalTextEditorOperator:
|
||||
result = operator.execute(mock_context)
|
||||
|
||||
assert result == {'FINISHED'}
|
||||
assert mock_context.scene.text_texture_props.text == "Edited single line"
|
||||
assert mock_context.scene.text_texture_props.text == "Edited text"
|
||||
|
||||
def test_execute_enforces_character_limit(self):
|
||||
"""execute() must truncate text exceeding max_text_length."""
|
||||
from src.operators.text_editor_ops import TEXT_TEXTURE_OT_edit_multiline_text
|
||||
from src.operators.text_editor_ops import TEXT_TEXTURE_OT_edit_text
|
||||
|
||||
operator = TEXT_TEXTURE_OT_edit_multiline_text()
|
||||
operator = TEXT_TEXTURE_OT_edit_text()
|
||||
# Create text exceeding 4096 char limit
|
||||
operator.temp_text = "x" * 5000
|
||||
|
||||
@@ -95,63 +94,11 @@ class TestModalTextEditorOperator:
|
||||
saved_text = mock_context.scene.text_texture_props.text
|
||||
assert len(saved_text) == 4096, f"Expected 4096 chars, got {len(saved_text)}"
|
||||
|
||||
def test_execute_rejects_text_with_newlines(self):
|
||||
"""execute() must reject text containing newline characters."""
|
||||
from src.operators.text_editor_ops import TEXT_TEXTURE_OT_edit_multiline_text
|
||||
|
||||
operator = TEXT_TEXTURE_OT_edit_multiline_text()
|
||||
operator.temp_text = "Line 1\nLine 2"
|
||||
|
||||
mock_context = Mock()
|
||||
mock_context.scene.text_texture_props.text = "Old text"
|
||||
|
||||
result = operator.execute(mock_context)
|
||||
|
||||
# Should return CANCELLED
|
||||
assert result == {'CANCELLED'}
|
||||
# Should not modify the original text
|
||||
assert mock_context.scene.text_texture_props.text == "Old text"
|
||||
# Should report an error
|
||||
operator.report.assert_called_once_with(
|
||||
{'ERROR'},
|
||||
"Multiline text not supported. Please use single line only."
|
||||
)
|
||||
|
||||
def test_execute_rejects_multiple_newlines(self):
|
||||
"""execute() must reject text with multiple newline characters."""
|
||||
from src.operators.text_editor_ops import TEXT_TEXTURE_OT_edit_multiline_text
|
||||
|
||||
operator = TEXT_TEXTURE_OT_edit_multiline_text()
|
||||
operator.temp_text = "Line 1\nLine 2\nLine 3\nLine 4"
|
||||
|
||||
mock_context = Mock()
|
||||
mock_context.scene.text_texture_props.text = "Old text"
|
||||
|
||||
result = operator.execute(mock_context)
|
||||
|
||||
assert result == {'CANCELLED'}
|
||||
assert mock_context.scene.text_texture_props.text == "Old text"
|
||||
|
||||
def test_execute_accepts_text_without_newlines(self):
|
||||
"""execute() must accept and save text without newlines."""
|
||||
from src.operators.text_editor_ops import TEXT_TEXTURE_OT_edit_multiline_text
|
||||
|
||||
operator = TEXT_TEXTURE_OT_edit_multiline_text()
|
||||
operator.temp_text = "This is a single line with no newlines"
|
||||
|
||||
mock_context = Mock()
|
||||
mock_context.scene.text_texture_props.text = "Old text"
|
||||
|
||||
result = operator.execute(mock_context)
|
||||
|
||||
assert result == {'FINISHED'}
|
||||
assert mock_context.scene.text_texture_props.text == "This is a single line with no newlines"
|
||||
|
||||
def test_operator_has_temp_text_property(self):
|
||||
"""Operator must have StringProperty named temp_text."""
|
||||
from src.operators.text_editor_ops import TEXT_TEXTURE_OT_edit_multiline_text
|
||||
from src.operators.text_editor_ops import TEXT_TEXTURE_OT_edit_text
|
||||
|
||||
operator = TEXT_TEXTURE_OT_edit_multiline_text()
|
||||
operator = TEXT_TEXTURE_OT_edit_text()
|
||||
# Blender properties are accessible as attributes
|
||||
assert hasattr(operator, 'temp_text')
|
||||
# Should be able to set and get
|
||||
@@ -178,50 +125,4 @@ class TestModalTextEditorOperator:
|
||||
from src.operators import text_editor_ops
|
||||
|
||||
assert hasattr(text_editor_ops, 'unregister')
|
||||
assert callable(text_editor_ops.unregister)
|
||||
|
||||
|
||||
class TestSingleLineUIBehavior:
|
||||
"""Test suite for single-line text UI display and statistics."""
|
||||
|
||||
def test_draw_calculates_character_count(self):
|
||||
"""draw() must count characters correctly."""
|
||||
from src.operators.text_editor_ops import TEXT_TEXTURE_OT_edit_multiline_text
|
||||
|
||||
operator = TEXT_TEXTURE_OT_edit_multiline_text()
|
||||
mock_context = Mock()
|
||||
|
||||
operator.temp_text = "Single line text"
|
||||
operator.draw(mock_context)
|
||||
|
||||
actual_chars = len(operator.temp_text)
|
||||
expected_chars = 16
|
||||
assert actual_chars == expected_chars, f"Expected {expected_chars} chars, got {actual_chars}"
|
||||
|
||||
def test_draw_handles_empty_text(self):
|
||||
"""draw() must handle empty text without errors."""
|
||||
from src.operators.text_editor_ops import TEXT_TEXTURE_OT_edit_multiline_text
|
||||
|
||||
operator = TEXT_TEXTURE_OT_edit_multiline_text()
|
||||
mock_context = Mock()
|
||||
|
||||
operator.temp_text = ""
|
||||
operator.draw(mock_context)
|
||||
|
||||
char_count = len(operator.temp_text)
|
||||
assert char_count == 0, f"Empty text should have 0 characters, got {char_count}"
|
||||
|
||||
def test_draw_handles_long_single_line(self):
|
||||
"""draw() must handle long single-line text correctly."""
|
||||
from src.operators.text_editor_ops import TEXT_TEXTURE_OT_edit_multiline_text
|
||||
|
||||
operator = TEXT_TEXTURE_OT_edit_multiline_text()
|
||||
mock_context = Mock()
|
||||
|
||||
# Create a very long single line
|
||||
long_text = "x" * 5000
|
||||
operator.temp_text = long_text
|
||||
operator.draw(mock_context)
|
||||
|
||||
# Should track all characters
|
||||
assert len(operator.temp_text) == 5000
|
||||
assert callable(text_editor_ops.unregister)
|
||||
Reference in New Issue
Block a user