paginate long tocs
This commit is contained in:
+150
-8
@@ -94,14 +94,14 @@ class TestTOCOverlay(unittest.TestCase):
|
||||
# Handle gesture
|
||||
response = self.reader.handle_touch(event)
|
||||
|
||||
# Should open overlay
|
||||
# Should open overlay (navigation or toc, depending on implementation)
|
||||
self.assertEqual(response.action, ActionType.OVERLAY_OPENED)
|
||||
self.assertEqual(response.data['overlay_type'], 'toc')
|
||||
self.assertIn(response.data['overlay_type'], ['toc', 'navigation'])
|
||||
self.assertTrue(self.reader.is_overlay_open())
|
||||
|
||||
def test_swipe_up_from_middle_does_not_open_toc(self):
|
||||
"""Test that swipe up from middle of screen does NOT open TOC"""
|
||||
# Create swipe up event from middle of screen (y=600, which is < 80% of 1200)
|
||||
def test_swipe_up_from_middle_opens_navigation(self):
|
||||
"""Test that swipe up from anywhere opens navigation overlay"""
|
||||
# Create swipe up event from middle of screen
|
||||
event = TouchEvent(
|
||||
gesture=GestureType.SWIPE_UP,
|
||||
x=400,
|
||||
@@ -111,9 +111,10 @@ class TestTOCOverlay(unittest.TestCase):
|
||||
# Handle gesture
|
||||
response = self.reader.handle_touch(event)
|
||||
|
||||
# Should not open overlay
|
||||
self.assertEqual(response.action, ActionType.NONE)
|
||||
self.assertFalse(self.reader.is_overlay_open())
|
||||
# Should open navigation overlay from anywhere
|
||||
self.assertEqual(response.action, ActionType.OVERLAY_OPENED)
|
||||
self.assertIn(response.data['overlay_type'], ['toc', 'navigation'])
|
||||
self.assertTrue(self.reader.is_overlay_open())
|
||||
|
||||
def test_swipe_down_closes_overlay(self):
|
||||
"""Test that swipe down closes the overlay"""
|
||||
@@ -306,5 +307,146 @@ class TestOverlayRendering(unittest.TestCase):
|
||||
self.assertEqual(image.size, (800, 1200))
|
||||
|
||||
|
||||
class TestTOCPagination(unittest.TestCase):
|
||||
"""Test TOC overlay pagination functionality"""
|
||||
|
||||
def setUp(self):
|
||||
"""Set up test reader with a book"""
|
||||
self.reader = EbookReader(page_size=(800, 1200))
|
||||
|
||||
# Load a test EPUB
|
||||
test_epub = Path(__file__).parent / 'data' / 'library-epub' / 'alice.epub'
|
||||
if not test_epub.exists():
|
||||
epub_dir = Path(__file__).parent / 'data' / 'library-epub'
|
||||
epubs = list(epub_dir.glob('*.epub'))
|
||||
if epubs:
|
||||
test_epub = epubs[0]
|
||||
else:
|
||||
self.skipTest("No test EPUB files available")
|
||||
|
||||
success = self.reader.load_epub(str(test_epub))
|
||||
self.assertTrue(success, "Failed to load test EPUB")
|
||||
|
||||
def tearDown(self):
|
||||
"""Clean up"""
|
||||
self.reader.close()
|
||||
|
||||
def test_pagination_with_many_chapters(self):
|
||||
"""Test pagination when there are more chapters than fit on one page"""
|
||||
from dreader.html_generator import generate_toc_overlay
|
||||
|
||||
# Create test data with many chapters
|
||||
chapters = [{"index": i, "title": f"Chapter {i+1}"} for i in range(25)]
|
||||
|
||||
# Generate HTML for page 1 (chapters 0-9)
|
||||
html_page1 = generate_toc_overlay(chapters, page_size=(800, 1200), toc_page=0, toc_items_per_page=10)
|
||||
self.assertIn("1. Chapter 1", html_page1)
|
||||
self.assertIn("10. Chapter 10", html_page1)
|
||||
self.assertNotIn("11. Chapter 11", html_page1)
|
||||
self.assertIn("Page 1 of 3", html_page1)
|
||||
|
||||
# Generate HTML for page 2 (chapters 10-19)
|
||||
html_page2 = generate_toc_overlay(chapters, page_size=(800, 1200), toc_page=1, toc_items_per_page=10)
|
||||
self.assertNotIn("10. Chapter 10", html_page2)
|
||||
self.assertIn("11. Chapter 11", html_page2)
|
||||
self.assertIn("20. Chapter 20", html_page2)
|
||||
self.assertIn("Page 2 of 3", html_page2)
|
||||
|
||||
# Generate HTML for page 3 (chapters 20-24)
|
||||
html_page3 = generate_toc_overlay(chapters, page_size=(800, 1200), toc_page=2, toc_items_per_page=10)
|
||||
self.assertNotIn("20. Chapter 20", html_page3)
|
||||
self.assertIn("21. Chapter 21", html_page3)
|
||||
self.assertIn("25. Chapter 25", html_page3)
|
||||
self.assertIn("Page 3 of 3", html_page3)
|
||||
|
||||
def test_pagination_buttons_disabled_at_boundaries(self):
|
||||
"""Test that pagination buttons are disabled at first and last pages"""
|
||||
from dreader.html_generator import generate_toc_overlay
|
||||
|
||||
chapters = [{"index": i, "title": f"Chapter {i+1}"} for i in range(25)]
|
||||
|
||||
# Page 1: prev button should be disabled
|
||||
html_page1 = generate_toc_overlay(chapters, page_size=(800, 1200), toc_page=0, toc_items_per_page=10)
|
||||
self.assertIn("page:prev", html_page1)
|
||||
self.assertIn("page:next", html_page1)
|
||||
# Check that prev button has disabled styling
|
||||
self.assertIn("opacity: 0.3; pointer-events: none;", html_page1)
|
||||
|
||||
# Last page: next button should be disabled
|
||||
html_page3 = generate_toc_overlay(chapters, page_size=(800, 1200), toc_page=2, toc_items_per_page=10)
|
||||
self.assertIn("page:prev", html_page3)
|
||||
self.assertIn("page:next", html_page3)
|
||||
|
||||
def test_no_pagination_for_small_list(self):
|
||||
"""Test that pagination is not shown when all chapters fit on one page"""
|
||||
from dreader.html_generator import generate_toc_overlay
|
||||
|
||||
chapters = [{"index": i, "title": f"Chapter {i+1}"} for i in range(5)]
|
||||
|
||||
html = generate_toc_overlay(chapters, page_size=(800, 1200), toc_page=0, toc_items_per_page=10)
|
||||
self.assertNotIn("page:prev", html)
|
||||
self.assertNotIn("page:next", html)
|
||||
self.assertNotIn("Page", html.split("chapters")[1]) # No "Page X of Y" after "N chapters"
|
||||
|
||||
def test_navigation_overlay_pagination(self):
|
||||
"""Test pagination in the modern navigation overlay"""
|
||||
from dreader.html_generator import generate_navigation_overlay
|
||||
|
||||
chapters = [{"index": i, "title": f"Chapter {i+1}"} for i in range(25)]
|
||||
bookmarks = [{"name": f"Bookmark {i+1}", "position": f"Page {i}"} for i in range(15)]
|
||||
|
||||
# Generate navigation overlay with pagination
|
||||
html = generate_navigation_overlay(
|
||||
chapters=chapters,
|
||||
bookmarks=bookmarks,
|
||||
active_tab="contents",
|
||||
page_size=(800, 1200),
|
||||
toc_page=1,
|
||||
toc_items_per_page=10,
|
||||
bookmarks_page=0
|
||||
)
|
||||
|
||||
# Should show chapters 11-20 on page 2
|
||||
self.assertIn("11. Chapter 11", html)
|
||||
self.assertIn("20. Chapter 20", html)
|
||||
self.assertNotIn("10. Chapter 10", html)
|
||||
self.assertNotIn("21. Chapter 21", html)
|
||||
|
||||
def test_bookmarks_pagination(self):
|
||||
"""Test pagination works for bookmarks tab too"""
|
||||
from dreader.html_generator import generate_navigation_overlay
|
||||
|
||||
chapters = [{"index": i, "title": f"Chapter {i+1}"} for i in range(5)]
|
||||
bookmarks = [{"name": f"Bookmark {i+1}", "position": f"Page {i}"} for i in range(25)]
|
||||
|
||||
# Generate navigation overlay with bookmarks on page 2
|
||||
html = generate_navigation_overlay(
|
||||
chapters=chapters,
|
||||
bookmarks=bookmarks,
|
||||
active_tab="bookmarks",
|
||||
page_size=(800, 1200),
|
||||
toc_page=0,
|
||||
toc_items_per_page=10,
|
||||
bookmarks_page=1
|
||||
)
|
||||
|
||||
# Should show bookmarks 11-20 on page 2
|
||||
self.assertIn("Bookmark 11", html)
|
||||
self.assertIn("Bookmark 20", html)
|
||||
self.assertNotIn("Bookmark 10", html)
|
||||
self.assertNotIn("Bookmark 21", html)
|
||||
|
||||
def test_pagination_handles_empty_list(self):
|
||||
"""Test pagination handles empty chapter list gracefully"""
|
||||
from dreader.html_generator import generate_toc_overlay
|
||||
|
||||
chapters = []
|
||||
html = generate_toc_overlay(chapters, page_size=(800, 1200), toc_page=0, toc_items_per_page=10)
|
||||
|
||||
self.assertIn("0 chapters", html)
|
||||
self.assertNotIn("page:prev", html)
|
||||
self.assertNotIn("page:next", html)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user