anki/pylib/tests/test_undo.py
Damien Elmes 57d7e3e2ab commit immediately when there's no active checkpoint
Reviews and operations on the backend that support undoing can now be
committed immediately, so they will not be lost in the event of a crash.

This required tweaks to a few places:

- don't set collection mtime on save() unless changes were made in
Python, as otherwise we end up accidentally clearing the backend undo
queue
- autosave() is now run on every reset()
- garbage collection now runs in a timer, instead of relying on
autosave() to be run periodically
2021-03-10 11:47:53 +10:00

94 lines
2.4 KiB
Python

# coding: utf-8
import time
from anki.consts import *
from tests.shared import getEmptyCol as getEmptyColOrig
def getEmptyCol():
col = getEmptyColOrig()
col.upgrade_to_v2_scheduler()
return col
def test_op():
col = getEmptyCol()
# should have no undo by default
assert not col.undoName()
# let's adjust a study option
col.save("studyopts")
col.conf["abc"] = 5
# it should be listed as undoable
assert col.undoName() == "studyopts"
# with about 5 minutes until it's clobbered
assert time.time() - col._last_checkpoint_at < 1
# undoing should restore the old value
col.undo()
assert not col.undoName()
assert "abc" not in col.conf
# an (auto)save will clear the undo
col.save("foo")
assert col.undoName() == "foo"
col.save()
assert not col.undoName()
# and a review will, too
col.save("add")
note = col.newNote()
note["Front"] = "one"
col.addNote(note)
col.reset()
assert "add" in col.undoName().lower()
c = col.sched.getCard()
col.sched.answerCard(c, 2)
assert col.undoName() == "Review"
def test_review():
col = getEmptyCol()
col.conf["counts"] = COUNT_REMAINING
note = col.newNote()
note["Front"] = "one"
col.addNote(note)
note = col.newNote()
note["Front"] = "two"
col.addNote(note)
col.reset()
# answer
assert col.sched.counts() == (2, 0, 0)
c = col.sched.getCard()
assert c.queue == QUEUE_TYPE_NEW
col.sched.answerCard(c, 3)
assert c.left % 1000 == 1
assert col.sched.counts() == (1, 1, 0)
assert c.queue == QUEUE_TYPE_LRN
# undo
assert col.undoName()
col.undo()
col.reset()
assert col.sched.counts() == (2, 0, 0)
c.load()
assert c.queue == QUEUE_TYPE_NEW
assert c.left % 1000 != 1
assert not col.undoName()
# we should be able to undo multiple answers too
c = col.sched.getCard()
col.sched.answerCard(c, 3)
c = col.sched.getCard()
col.sched.answerCard(c, 3)
assert col.sched.counts() == (0, 2, 0)
col.undo()
col.reset()
assert col.sched.counts() == (1, 1, 0)
col.undo()
col.reset()
assert col.sched.counts() == (2, 0, 0)
# performing a normal op will clear the review queue
c = col.sched.getCard()
col.sched.answerCard(c, 3)
assert col.undoName() == "Review"
col.save("foo")
assert col.undoName() == "foo"
col.undo()
assert not col.undoName()