231 lines
7.4 KiB
Python
231 lines
7.4 KiB
Python
"""
|
|
Test backward navigation after resuming from a saved position.
|
|
|
|
This test specifically checks if backward navigation works correctly
|
|
after opening an epub, navigating forward, closing it, then resuming
|
|
and attempting to navigate backward.
|
|
|
|
This may reveal issues with pyWebLayout's backward navigation handling.
|
|
"""
|
|
|
|
import unittest
|
|
import tempfile
|
|
import shutil
|
|
from pathlib import Path
|
|
import numpy as np
|
|
from PIL import Image
|
|
|
|
from dreader.application import EbookReader
|
|
|
|
|
|
class TestBackwardNavigationAfterResume(unittest.TestCase):
|
|
"""Test backward navigation behavior after resume"""
|
|
|
|
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 compare_images(self, img1: Image.Image, img2: Image.Image) -> bool:
|
|
"""
|
|
Check if two PIL Images are pixel-perfect identical.
|
|
"""
|
|
if img1 is None or img2 is None:
|
|
return False
|
|
|
|
if img1.size != img2.size:
|
|
return False
|
|
|
|
arr1 = np.array(img1)
|
|
arr2 = np.array(img2)
|
|
|
|
return np.array_equal(arr1, arr2)
|
|
|
|
def test_backward_navigation_after_resume(self):
|
|
"""
|
|
Test that backward navigation works after closing and resuming.
|
|
|
|
Steps:
|
|
1. Open EPUB
|
|
2. Navigate forward 3 pages
|
|
3. Save positions and pages
|
|
4. Close reader
|
|
5. Open new reader (resume)
|
|
6. Try to navigate backward
|
|
7. Verify we can reach previous pages
|
|
"""
|
|
# Phase 1: Initial session - navigate forward
|
|
reader1 = EbookReader(
|
|
page_size=(800, 1000),
|
|
bookmarks_dir=self.temp_dir,
|
|
buffer_size=0 # Disable buffering for consistent testing
|
|
)
|
|
|
|
success = reader1.load_epub(self.epub_path)
|
|
self.assertTrue(success, "Failed to load test EPUB")
|
|
|
|
# Capture initial page
|
|
page0 = reader1.get_current_page()
|
|
self.assertIsNotNone(page0, "Initial page should not be None")
|
|
pos0 = reader1.manager.current_position.copy()
|
|
|
|
print(f"\nInitial position: {pos0}")
|
|
|
|
# Navigate forward 3 pages, capturing each page
|
|
pages = [page0]
|
|
positions = [pos0]
|
|
|
|
for i in range(3):
|
|
page = reader1.next_page()
|
|
self.assertIsNotNone(page, f"Page {i+1} should not be None")
|
|
pages.append(page)
|
|
positions.append(reader1.manager.current_position.copy())
|
|
print(f"Forward page {i+1} position: {positions[-1]}")
|
|
|
|
# We should now be at page 3 (0-indexed)
|
|
self.assertEqual(len(pages), 4, "Should have 4 pages total (0-3)")
|
|
|
|
# Save the current position before closing
|
|
final_position = reader1.manager.current_position.copy()
|
|
print(f"Final position before close: {final_position}")
|
|
|
|
# Close reader (this should save the position)
|
|
reader1.close()
|
|
|
|
# Phase 2: Resume session - navigate backward
|
|
reader2 = EbookReader(
|
|
page_size=(800, 1000),
|
|
bookmarks_dir=self.temp_dir,
|
|
buffer_size=0
|
|
)
|
|
|
|
success = reader2.load_epub(self.epub_path)
|
|
self.assertTrue(success, "Failed to load test EPUB on resume")
|
|
|
|
# Verify we resumed at the correct position
|
|
resumed_position = reader2.manager.current_position.copy()
|
|
print(f"Resumed at position: {resumed_position}")
|
|
self.assertEqual(
|
|
resumed_position,
|
|
final_position,
|
|
"Should resume at the last saved position"
|
|
)
|
|
|
|
# Get the current page (should match page 3)
|
|
resumed_page = reader2.get_current_page()
|
|
self.assertIsNotNone(resumed_page, "Resumed page should not be None")
|
|
|
|
# Now try to navigate backward
|
|
print("\nAttempting backward navigation...")
|
|
|
|
backward_pages = []
|
|
backward_positions = []
|
|
|
|
# Try to go back 3 times
|
|
for i in range(3):
|
|
prev_page = reader2.previous_page()
|
|
print(f"Backward step {i+1}: page={'Not None' if prev_page else 'None'}")
|
|
|
|
if prev_page is None:
|
|
print(f"WARNING: previous_page() returned None at step {i+1}")
|
|
# This is the bug we're testing for!
|
|
self.fail(f"Backward navigation failed at step {i+1}: previous_page() returned None")
|
|
|
|
backward_pages.append(prev_page)
|
|
backward_positions.append(reader2.manager.current_position.copy())
|
|
print(f" Position after backward: {backward_positions[-1]}")
|
|
|
|
# We should have successfully gone back 3 pages
|
|
self.assertEqual(len(backward_pages), 3, "Should have navigated back 3 pages")
|
|
|
|
# Verify final position matches original position
|
|
final_backward_position = reader2.manager.current_position.copy()
|
|
print(f"\nFinal position after backward navigation: {final_backward_position}")
|
|
print(f"Original position (page 0): {pos0}")
|
|
|
|
self.assertEqual(
|
|
final_backward_position,
|
|
pos0,
|
|
"After going forward 3 and back 3, should be at initial position"
|
|
)
|
|
|
|
# Verify the page content matches
|
|
final_page = reader2.get_current_page()
|
|
self.assertTrue(
|
|
self.compare_images(page0, final_page),
|
|
"Final page should match initial page after forward/backward navigation"
|
|
)
|
|
|
|
reader2.close()
|
|
|
|
print("\n✓ Test passed: Backward navigation works correctly after resume")
|
|
|
|
def test_backward_navigation_single_step(self):
|
|
"""
|
|
Simplified test: Open, go forward 1 page, close, resume, go back 1 page.
|
|
This is a minimal reproduction case.
|
|
"""
|
|
# Session 1: Navigate forward one page
|
|
reader1 = EbookReader(
|
|
page_size=(800, 1000),
|
|
bookmarks_dir=self.temp_dir,
|
|
buffer_size=0
|
|
)
|
|
|
|
reader1.load_epub(self.epub_path)
|
|
|
|
page0 = reader1.get_current_page()
|
|
pos0 = reader1.manager.current_position.copy()
|
|
|
|
page1 = reader1.next_page()
|
|
self.assertIsNotNone(page1, "Should be able to navigate forward")
|
|
pos1 = reader1.manager.current_position.copy()
|
|
|
|
reader1.close()
|
|
|
|
# Session 2: Resume and navigate backward
|
|
reader2 = EbookReader(
|
|
page_size=(800, 1000),
|
|
bookmarks_dir=self.temp_dir,
|
|
buffer_size=0
|
|
)
|
|
|
|
reader2.load_epub(self.epub_path)
|
|
|
|
# Verify we're at page 1
|
|
self.assertEqual(
|
|
reader2.manager.current_position,
|
|
pos1,
|
|
"Should resume at page 1"
|
|
)
|
|
|
|
# Try to go back
|
|
prev_page = reader2.previous_page()
|
|
|
|
# This is the critical assertion - if this fails, backward nav is broken
|
|
self.assertIsNotNone(
|
|
prev_page,
|
|
"CRITICAL: previous_page() returned None after resume - this indicates a pyWebLayout bug"
|
|
)
|
|
|
|
# Verify we're back at page 0
|
|
final_pos = reader2.manager.current_position.copy()
|
|
self.assertEqual(
|
|
final_pos,
|
|
pos0,
|
|
"Should be back at initial position"
|
|
)
|
|
|
|
reader2.close()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|