Initial commit
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
from unittest.mock import MagicMock
|
||||
from src.bilingual_builder import BilingualEPUBBuilder
|
||||
from src.chinese_builder import ChineseEPUBBuilder
|
||||
|
||||
# Mock classes to avoid full EPUB dependencies
|
||||
class MockItem:
|
||||
def __init__(self, name, content):
|
||||
self.name = name
|
||||
self.content = content
|
||||
self.title = "Mock Title"
|
||||
self.id = "item_1"
|
||||
|
||||
def get_name(self): return self.name
|
||||
def get_content(self): return self.content.encode('utf-8')
|
||||
def get_type(self): return 9 # ITEM_DOCUMENT
|
||||
|
||||
def test_bilingual_builder_misalignment():
|
||||
"""
|
||||
Reproduces the off-by-one misalignment bug.
|
||||
|
||||
Scenario:
|
||||
1. HTML contains: [Para1], [Nav], [Para2]
|
||||
2. Ordered IDs passed to builder: [ID1, ID2] (assuming Nav is validly ignored by extractor logic but maybe ID list is different?
|
||||
Actually, let's trace the bug logic:
|
||||
Extractor:
|
||||
- Para1 -> Clean -> Valid -> Added to Manifest (Status: Pending) -> ID1
|
||||
- Nav -> Clean -> Valid -> Added to Manifest (Status: Ignored) -> ID2
|
||||
- Para2 -> Clean -> Valid -> Added to Manifest (Status: Pending) -> ID3
|
||||
|
||||
Builder Input:
|
||||
- translation_map: {ID1: "Trans1", ID3: "Trans3"} (Nav ignored so no trans)
|
||||
- paragraph_map: {ID1: ..., ID2: ..., ID3: ...}
|
||||
- ordered_ids: [ID1, ID2, ID3] (All items in file)
|
||||
|
||||
Builder Loop (Current Broken Logic):
|
||||
- Scans Para1: Valid, Not Nav.
|
||||
- Match with ordered_ids[0] (ID1). OK.
|
||||
- Incr index -> 1.
|
||||
- Scans Nav: is_navigation_element() == True -> CONTINUE
|
||||
- Index remains 1.
|
||||
- Scans Para2: Valid, Not Nav.
|
||||
- Match with ordered_ids[1] (ID2).
|
||||
- ID2 is the Nav item!
|
||||
- translation_map.get(ID2) -> None (or wrong if ID2 had a translation).
|
||||
- Result: Para2 gets NO translation or WRONG translation.
|
||||
- Expected: Para2 should match ID3.
|
||||
"""
|
||||
|
||||
# Setup
|
||||
html_content = """
|
||||
<html>
|
||||
<body>
|
||||
<p>Paragraph 1</p>
|
||||
<div class="nav">Navigation Content</div>
|
||||
<p>Paragraph 2</p>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
mock_item = MockItem("test.xhtml", html_content)
|
||||
|
||||
# IDs corresponding to the elements as they would be in Manifest
|
||||
# ID1: Para1, ID2: Nav, ID3: Para2
|
||||
ordered_ids = ["p_001", "p_002", "p_003"]
|
||||
|
||||
translation_map = {
|
||||
"p_001": "翻译1",
|
||||
"p_003": "翻译2" # p_002 is ignored, so no translation
|
||||
}
|
||||
|
||||
# Config
|
||||
config = {'output': {}}
|
||||
mock_book = MagicMock()
|
||||
mock_book.get_metadata.return_value = None
|
||||
|
||||
builder = BilingualEPUBBuilder(mock_book, config)
|
||||
|
||||
# Execute private method directly for testing
|
||||
# We mock _add_style_link to do nothing
|
||||
builder._add_style_link = MagicMock()
|
||||
|
||||
new_item = builder._create_bilingual_document(mock_item, ordered_ids, translation_map)
|
||||
new_content = new_item.get_content().decode('utf-8')
|
||||
soup = BeautifulSoup(new_content, 'html.parser')
|
||||
|
||||
# Analyze results
|
||||
paragraphs = soup.find_all('p', class_='translation-text')
|
||||
|
||||
print(f"Generated Paragraphs: {len(paragraphs)}")
|
||||
for p in paragraphs:
|
||||
print(f" - {p.get_text()}")
|
||||
|
||||
# Assertions
|
||||
# We expect 2 translated paragraphs.
|
||||
# Current BUG: Likely only 1 found (Para1), and Para2 missed because it matched with p_002 which has no translation.
|
||||
|
||||
assert len(paragraphs) == 2, f"Expected 2 translated paragraphs, found {len(paragraphs)}"
|
||||
assert paragraphs[0].get_text() == "翻译1"
|
||||
assert paragraphs[1].get_text() == "翻译2"
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
test_bilingual_builder_misalignment()
|
||||
print("Test PASSED")
|
||||
except AssertionError as e:
|
||||
print(f"Test FAILED: {e}")
|
||||
except Exception as e:
|
||||
print(f"Test ERROR: {e}")
|
||||
Reference in New Issue
Block a user