311 lines
9 KiB
Python
311 lines
9 KiB
Python
from PySide6.QtWidgets import QWidget, QMessageBox, QApplication
|
|
from PySide6.QtCore import Qt, QTimer
|
|
|
|
from bouquin.history_dialog import HistoryDialog
|
|
|
|
|
|
def test_history_dialog_lists_and_revert(qtbot, fresh_db):
|
|
d = "2001-01-01"
|
|
fresh_db.save_new_version(d, "v1", "first")
|
|
fresh_db.save_new_version(d, "v2", "second")
|
|
|
|
w = QWidget()
|
|
dlg = HistoryDialog(fresh_db, d, parent=w)
|
|
qtbot.addWidget(dlg)
|
|
dlg.show()
|
|
|
|
dlg.list.setCurrentRow(1)
|
|
qtbot.mouseClick(dlg.btn_revert, Qt.LeftButton)
|
|
assert fresh_db.get_entry(d) == "v1"
|
|
|
|
|
|
def test_history_dialog_no_selection_clears(qtbot, fresh_db):
|
|
d = "2001-01-01"
|
|
fresh_db.save_new_version(d, "v1", "first")
|
|
w = QWidget()
|
|
dlg = HistoryDialog(fresh_db, d, parent=w)
|
|
qtbot.addWidget(dlg)
|
|
dlg.show()
|
|
|
|
# Clear selection (no current item) and call slot
|
|
dlg.list.setCurrentItem(None)
|
|
dlg._on_select()
|
|
assert dlg.preview.toPlainText() == ""
|
|
assert dlg.diff.toPlainText() == ""
|
|
assert not dlg.btn_revert.isEnabled()
|
|
|
|
|
|
def test_history_dialog_revert_same_version_noop(qtbot, fresh_db):
|
|
d = "2001-01-01"
|
|
# Only one version; that's the current
|
|
vid, _ = fresh_db.save_new_version(d, "seed", "note")
|
|
w = QWidget()
|
|
dlg = HistoryDialog(fresh_db, d, parent=w)
|
|
qtbot.addWidget(dlg)
|
|
dlg.show()
|
|
|
|
# Pick the only item (current)
|
|
dlg.list.setCurrentRow(0)
|
|
# Clicking revert should simply return (no change)
|
|
before = fresh_db.get_entry(d)
|
|
dlg._revert()
|
|
after = fresh_db.get_entry(d)
|
|
assert before == after
|
|
|
|
|
|
def test_history_dialog_revert_error_shows_message(qtbot, fresh_db):
|
|
d = "2001-01-02"
|
|
fresh_db.save_new_version(d, "v1", "first")
|
|
w = QWidget()
|
|
dlg = HistoryDialog(fresh_db, d, parent=w)
|
|
qtbot.addWidget(dlg)
|
|
dlg.show()
|
|
|
|
# Select the row
|
|
dlg.list.setCurrentRow(0)
|
|
|
|
# Monkeypatch db to raise inside revert_to_version to hit except path
|
|
def boom(date_iso, version_id):
|
|
raise RuntimeError("nope")
|
|
|
|
dlg._db.revert_to_version = boom
|
|
|
|
# Auto-accept any QMessageBox that appears
|
|
def _pump():
|
|
for m in QMessageBox.instances():
|
|
m.accept()
|
|
|
|
t = QTimer()
|
|
t.setInterval(10)
|
|
t.timeout.connect(_pump)
|
|
t.start()
|
|
try:
|
|
dlg._revert()
|
|
finally:
|
|
t.stop()
|
|
|
|
|
|
def test_revert_returns_when_no_item_selected(qtbot, fresh_db):
|
|
d = "2000-01-01"
|
|
fresh_db.save_new_version(d, "v1", "first")
|
|
w = QWidget()
|
|
dlg = HistoryDialog(fresh_db, d, parent=w)
|
|
qtbot.addWidget(dlg)
|
|
dlg.show()
|
|
# No selection at all -> early return
|
|
dlg.list.clearSelection()
|
|
dlg._revert() # should not raise
|
|
|
|
|
|
def test_revert_returns_when_current_selected(qtbot, fresh_db):
|
|
d = "2000-01-02"
|
|
fresh_db.save_new_version(d, "v1", "first")
|
|
# Create a second version so there is a 'current'
|
|
fresh_db.save_new_version(d, "v2", "second")
|
|
w = QWidget()
|
|
dlg = HistoryDialog(fresh_db, d, parent=w)
|
|
qtbot.addWidget(dlg)
|
|
dlg.show()
|
|
# Select the current item -> early return
|
|
for i in range(dlg.list.count()):
|
|
item = dlg.list.item(i)
|
|
if item.data(Qt.UserRole) == dlg._current_id:
|
|
dlg.list.setCurrentItem(item)
|
|
break
|
|
dlg._revert() # no-op
|
|
|
|
|
|
def test_revert_exception_shows_message(qtbot, fresh_db, monkeypatch):
|
|
"""
|
|
Trigger the exception path in _revert() and auto-accept the modal
|
|
QMessageBox that HistoryDialog pops so the test doesn't hang.
|
|
"""
|
|
d = "2000-01-03"
|
|
fresh_db.save_new_version(d, "v1", "first")
|
|
fresh_db.save_new_version(d, "v2", "second")
|
|
|
|
w = QWidget()
|
|
dlg = HistoryDialog(fresh_db, d, parent=w)
|
|
qtbot.addWidget(dlg)
|
|
dlg.show()
|
|
|
|
# Select a non-current item
|
|
for i in range(dlg.list.count()):
|
|
item = dlg.list.item(i)
|
|
if item.data(Qt.UserRole) != dlg._current_id:
|
|
dlg.list.setCurrentItem(item)
|
|
break
|
|
|
|
# Make revert raise to hit the except/critical message path.
|
|
def boom(*_a, **_k):
|
|
raise RuntimeError("nope")
|
|
|
|
monkeypatch.setattr(dlg._db, "revert_to_version", boom)
|
|
|
|
# Prepare a small helper that keeps trying to close an active modal box,
|
|
# but gives up after a bounded number of attempts.
|
|
def make_closer(max_tries=50, interval_ms=10):
|
|
tries = {"n": 0}
|
|
|
|
def closer():
|
|
tries["n"] += 1
|
|
w = QApplication.activeModalWidget()
|
|
if isinstance(w, QMessageBox):
|
|
# Prefer clicking the OK button if present; otherwise accept().
|
|
ok = w.button(QMessageBox.Ok)
|
|
if ok is not None:
|
|
ok.click()
|
|
else:
|
|
w.accept()
|
|
elif tries["n"] < max_tries:
|
|
QTimer.singleShot(interval_ms, closer)
|
|
|
|
return closer
|
|
|
|
# Schedule auto-close right before we trigger the modal dialog.
|
|
QTimer.singleShot(0, make_closer())
|
|
|
|
# Should show the critical box, which our timer will accept; _revert returns.
|
|
dlg._revert()
|
|
|
|
|
|
def test_delete_version_from_history(qtbot, fresh_db):
|
|
"""Test deleting a version through the history dialog."""
|
|
d = "2001-01-01"
|
|
|
|
# Create multiple versions
|
|
vid1, _ = fresh_db.save_new_version(d, "v1", "first")
|
|
vid2, _ = fresh_db.save_new_version(d, "v2", "second")
|
|
vid3, _ = fresh_db.save_new_version(d, "v3", "third")
|
|
|
|
w = QWidget()
|
|
dlg = HistoryDialog(fresh_db, d, parent=w)
|
|
qtbot.addWidget(dlg)
|
|
dlg.show()
|
|
|
|
# Verify we have 3 versions
|
|
assert dlg.list.count() == 3
|
|
|
|
# Select the first version (oldest, not current)
|
|
dlg.list.setCurrentRow(2) # Last row is oldest version
|
|
|
|
# Call _delete
|
|
dlg._delete()
|
|
|
|
# Verify the version was deleted
|
|
assert dlg.list.count() == 2
|
|
|
|
# Verify from DB
|
|
versions = fresh_db.list_versions(d)
|
|
assert len(versions) == 2
|
|
|
|
|
|
def test_delete_current_version_returns_early(qtbot, fresh_db):
|
|
"""Test that deleting the current version returns early without deleting."""
|
|
d = "2001-01-02"
|
|
|
|
# Create versions
|
|
vid1, _ = fresh_db.save_new_version(d, "v1", "first")
|
|
vid2, _ = fresh_db.save_new_version(d, "v2", "second")
|
|
|
|
w = QWidget()
|
|
dlg = HistoryDialog(fresh_db, d, parent=w)
|
|
qtbot.addWidget(dlg)
|
|
dlg.show()
|
|
|
|
# Find and select the current version
|
|
for i in range(dlg.list.count()):
|
|
item = dlg.list.item(i)
|
|
if item.data(Qt.UserRole) == dlg._current_id:
|
|
dlg.list.setCurrentItem(item)
|
|
break
|
|
|
|
# Try to delete - should return early
|
|
dlg._delete()
|
|
|
|
# Verify nothing was deleted
|
|
versions = fresh_db.list_versions(d)
|
|
assert len(versions) == 2
|
|
|
|
|
|
def test_delete_version_with_error(qtbot, fresh_db, monkeypatch):
|
|
"""Test that delete version error shows a message box."""
|
|
d = "2001-01-03"
|
|
|
|
# Create versions
|
|
vid1, _ = fresh_db.save_new_version(d, "v1", "first")
|
|
vid2, _ = fresh_db.save_new_version(d, "v2", "second")
|
|
|
|
w = QWidget()
|
|
dlg = HistoryDialog(fresh_db, d, parent=w)
|
|
qtbot.addWidget(dlg)
|
|
dlg.show()
|
|
|
|
# Select a non-current version
|
|
for i in range(dlg.list.count()):
|
|
item = dlg.list.item(i)
|
|
if item.data(Qt.UserRole) != dlg._current_id:
|
|
dlg.list.setCurrentItem(item)
|
|
break
|
|
|
|
# Make delete_version raise an error
|
|
def boom(*args, **kwargs):
|
|
raise RuntimeError("Delete failed")
|
|
|
|
monkeypatch.setattr(dlg._db, "delete_version", boom)
|
|
|
|
# Set up auto-closer for message box
|
|
def make_closer(max_tries=50, interval_ms=10):
|
|
tries = {"n": 0}
|
|
|
|
def closer():
|
|
tries["n"] += 1
|
|
w = QApplication.activeModalWidget()
|
|
if isinstance(w, QMessageBox):
|
|
ok = w.button(QMessageBox.Ok)
|
|
if ok is not None:
|
|
ok.click()
|
|
else:
|
|
w.accept()
|
|
elif tries["n"] < max_tries:
|
|
QTimer.singleShot(interval_ms, closer)
|
|
|
|
return closer
|
|
|
|
QTimer.singleShot(0, make_closer())
|
|
|
|
# Call delete - should show error message
|
|
dlg._delete()
|
|
|
|
|
|
def test_delete_multiple_versions(qtbot, fresh_db):
|
|
"""Test deleting multiple versions at once."""
|
|
d = "2001-01-04"
|
|
|
|
# Create multiple versions
|
|
vid1, _ = fresh_db.save_new_version(d, "v1", "first")
|
|
vid2, _ = fresh_db.save_new_version(d, "v2", "second")
|
|
vid3, _ = fresh_db.save_new_version(d, "v3", "third")
|
|
vid4, _ = fresh_db.save_new_version(d, "v4", "fourth")
|
|
|
|
w = QWidget()
|
|
dlg = HistoryDialog(fresh_db, d, parent=w)
|
|
qtbot.addWidget(dlg)
|
|
dlg.show()
|
|
|
|
# Select multiple non-current items
|
|
selected_count = 0
|
|
for i in range(dlg.list.count()):
|
|
item = dlg.list.item(i)
|
|
if item.data(Qt.UserRole) != dlg._current_id:
|
|
item.setSelected(True)
|
|
selected_count += 1
|
|
if selected_count >= 2: # Select 2 items
|
|
break
|
|
|
|
# Delete them
|
|
dlg._delete()
|
|
|
|
# Verify versions were deleted (should have current + 1 remaining)
|
|
versions = fresh_db.list_versions(d)
|
|
assert len(versions) == 2 # Current + 1 that wasn't deleted
|