""" Detailed test for backward navigation issues. This test explores the backward navigation behavior more thoroughly to understand if the issue is: 1. Complete failure (previous_page returns None) 2. Imprecise positioning (lands on wrong block) 3. Only occurs after resume 4. Occurs during continuous navigation """ import unittest import tempfile import shutil from pathlib import Path from dreader.application import EbookReader class TestBackwardNavigationDetailed(unittest.TestCase): """Detailed backward navigation tests""" def setUp(self): """Set up test environment""" self.temp_dir = tempfile.mkdtemp() self.epub_path = "tests/data/test.epub" if not Path(self.epub_path).exists(): self.skipTest(f"Test EPUB not found at {self.epub_path}") def tearDown(self): """Clean up test environment""" shutil.rmtree(self.temp_dir, ignore_errors=True) def test_continuous_backward_navigation_no_resume(self): """ Test backward navigation without closing/resuming. This checks if the issue is specific to resume or general. """ reader = EbookReader( page_size=(800, 1000), bookmarks_dir=self.temp_dir, buffer_size=0 ) reader.load_epub(self.epub_path) print("\n=== Test: Continuous backward navigation (no resume) ===") # Record starting position pos0 = reader.manager.current_position.copy() print(f"Starting position: {pos0}") # Go forward 5 pages, recording positions forward_positions = [pos0] for i in range(5): page = reader.next_page() if page is None: print(f"Reached end at page {i}") break pos = reader.manager.current_position.copy() forward_positions.append(pos) print(f"Forward page {i+1}: block_index={pos.block_index}") num_forward = len(forward_positions) - 1 print(f"\nNavigated forward {num_forward} pages") # Now go backward the same number of times print("\n--- Going backward ---") backward_positions = [] for i in range(num_forward): page = reader.previous_page() if page is None: print(f"ERROR: previous_page() returned None at step {i+1}") self.fail(f"Backward navigation failed at step {i+1}") pos = reader.manager.current_position.copy() backward_positions.append(pos) print(f"Backward step {i+1}: block_index={pos.block_index}") # Check final position final_pos = reader.manager.current_position.copy() print(f"\nFinal position: {final_pos}") print(f"Expected (pos0): {pos0}") if final_pos != pos0: print(f"WARNING: Position mismatch!") print(f" Expected block_index: {pos0.block_index}") print(f" Actual block_index: {final_pos.block_index}") print(f" Difference: {final_pos.block_index - pos0.block_index} blocks") self.assertEqual( final_pos, pos0, f"After {num_forward} forward and {num_forward} backward, should be at start" ) reader.close() def test_backward_navigation_at_start(self): """ Test that previous_page() behaves correctly when at the start of the book. """ reader = EbookReader( page_size=(800, 1000), bookmarks_dir=self.temp_dir, buffer_size=0 ) reader.load_epub(self.epub_path) print("\n=== Test: Backward navigation at start ===") pos_start = reader.manager.current_position.copy() print(f"At start: {pos_start}") # Try to go back from the very first page page = reader.previous_page() print(f"previous_page() returned: {page is not None}") pos_after = reader.manager.current_position.copy() print(f"Position after previous_page(): {pos_after}") # Should either return None or stay at same position if page is not None: self.assertEqual( pos_after, pos_start, "If previous_page() returns a page at start, position should not change" ) reader.close() def test_alternating_navigation(self): """ Test alternating forward/backward navigation. """ reader = EbookReader( page_size=(800, 1000), bookmarks_dir=self.temp_dir, buffer_size=0 ) reader.load_epub(self.epub_path) print("\n=== Test: Alternating forward/backward navigation ===") pos0 = reader.manager.current_position.copy() print(f"Start: block_index={pos0.block_index}") # Go forward, back, forward, back pattern operations = [ ("forward", 1), ("backward", 1), ("forward", 2), ("backward", 1), ("forward", 1), ("backward", 2), ] for op, count in operations: for i in range(count): if op == "forward": page = reader.next_page() else: page = reader.previous_page() self.assertIsNotNone( page, f"{op} navigation failed at iteration {i+1}" ) pos = reader.manager.current_position.copy() print(f"After {count}x {op}: block_index={pos.block_index}") # We should end up at the starting position (net: +5 -4 = +1, then +1 -2 = -1, total = 0) # Actually: +1 -1 +2 -1 +1 -2 = 0 final_pos = reader.manager.current_position.copy() print(f"\nFinal: block_index={final_pos.block_index}") print(f"Expected: block_index={pos0.block_index}") self.assertEqual( final_pos, pos0, "Alternating navigation should return to start" ) reader.close() def test_backward_then_forward(self): """ Test that forward navigation works correctly after backward navigation. """ reader = EbookReader( page_size=(800, 1000), bookmarks_dir=self.temp_dir, buffer_size=0 ) reader.load_epub(self.epub_path) print("\n=== Test: Backward then forward ===") # Go forward 3 pages positions = [reader.manager.current_position.copy()] for i in range(3): reader.next_page() positions.append(reader.manager.current_position.copy()) print(f"Forward positions: {[p.block_index for p in positions]}") # Go back 3 pages for i in range(3): reader.previous_page() pos_after_back = reader.manager.current_position.copy() print(f"After going back: block_index={pos_after_back.block_index}") # Now go forward 3 pages again for i in range(3): reader.next_page() final_pos = reader.manager.current_position.copy() print(f"After going forward again: block_index={final_pos.block_index}") print(f"Expected: block_index={positions[3].block_index}") self.assertEqual( final_pos, positions[3], "Forward after backward should reach same position" ) reader.close() if __name__ == '__main__': unittest.main()