anki/pylib/tests/test_decks.py
Damien Elmes 5876866565 tweaking the folder names again
hopefully that's the last of it
2020-01-03 07:48:38 +10:00

180 lines
6.4 KiB
Python

# coding: utf-8
from anki.errors import DeckRenameError
from tests.shared import assertException, getEmptyCol
def test_basic():
deck = getEmptyCol()
# we start with a standard deck
assert len(deck.decks.decks) == 1
# it should have an id of 1
assert deck.decks.name(1)
# create a new deck
parentId = deck.decks.id("new deck")
assert parentId
assert len(deck.decks.decks) == 2
# should get the same id
assert deck.decks.id("new deck") == parentId
# we start with the default deck selected
assert deck.decks.selected() == 1
assert deck.decks.active() == [1]
# we can select a different deck
deck.decks.select(parentId)
assert deck.decks.selected() == parentId
assert deck.decks.active() == [parentId]
# let's create a child
childId = deck.decks.id("new deck::child")
# it should have been added to the active list
assert deck.decks.selected() == parentId
assert deck.decks.active() == [parentId, childId]
# we can select the child individually too
deck.decks.select(childId)
assert deck.decks.selected() == childId
assert deck.decks.active() == [childId]
# parents with a different case should be handled correctly
deck.decks.id("ONE")
m = deck.models.current()
m["did"] = deck.decks.id("one::two")
deck.models.save(m, updateReqs=False)
n = deck.newNote()
n["Front"] = "abc"
deck.addNote(n)
# this will error if child and parent case don't match
deck.sched.deckDueList()
def test_remove():
deck = getEmptyCol()
# create a new deck, and add a note/card to it
g1 = deck.decks.id("g1")
f = deck.newNote()
f["Front"] = "1"
f.model()["did"] = g1
deck.addNote(f)
c = f.cards()[0]
assert c.did == g1
# by default deleting the deck leaves the cards with an invalid did
assert deck.cardCount() == 1
deck.decks.rem(g1)
assert deck.cardCount() == 1
c.load()
assert c.did == g1
# but if we try to get it, we get the default
assert deck.decks.name(c.did) == "[no deck]"
# let's create another deck and explicitly set the card to it
g2 = deck.decks.id("g2")
c.did = g2
c.flush()
# this time we'll delete the card/note too
deck.decks.rem(g2, cardsToo=True)
assert deck.cardCount() == 0
assert deck.noteCount() == 0
def test_rename():
d = getEmptyCol()
id = d.decks.id("hello::world")
# should be able to rename into a completely different branch, creating
# parents as necessary
d.decks.rename(d.decks.get(id), "foo::bar")
assert "foo" in d.decks.allNames()
assert "foo::bar" in d.decks.allNames()
assert "hello::world" not in d.decks.allNames()
# create another deck
id = d.decks.id("tmp")
# we can't rename it if it conflicts
assertException(Exception, lambda: d.decks.rename(d.decks.get(id), "foo"))
# when renaming, the children should be renamed too
d.decks.id("one::two::three")
id = d.decks.id("one")
d.decks.rename(d.decks.get(id), "yo")
for n in "yo", "yo::two", "yo::two::three":
assert n in d.decks.allNames()
# over filtered
filteredId = d.decks.newDyn("filtered")
filtered = d.decks.get(filteredId)
childId = d.decks.id("child")
child = d.decks.get(childId)
assertException(DeckRenameError, lambda: d.decks.rename(child, "filtered::child"))
assertException(DeckRenameError, lambda: d.decks.rename(child, "FILTERED::child"))
# changing case
parentId = d.decks.id("PARENT")
d.decks.id("PARENT::CHILD")
assertException(DeckRenameError, lambda: d.decks.rename(child, "PARENT::CHILD"))
assertException(DeckRenameError, lambda: d.decks.rename(child, "PARENT::child"))
def test_renameForDragAndDrop():
d = getEmptyCol()
def deckNames():
return [name for name in sorted(d.decks.allNames()) if name != "Default"]
languages_did = d.decks.id("Languages")
chinese_did = d.decks.id("Chinese")
hsk_did = d.decks.id("Chinese::HSK")
# Renaming also renames children
d.decks.renameForDragAndDrop(chinese_did, languages_did)
assert deckNames() == ["Languages", "Languages::Chinese", "Languages::Chinese::HSK"]
# Dragging a deck onto itself is a no-op
d.decks.renameForDragAndDrop(languages_did, languages_did)
assert deckNames() == ["Languages", "Languages::Chinese", "Languages::Chinese::HSK"]
# Dragging a deck onto its parent is a no-op
d.decks.renameForDragAndDrop(hsk_did, chinese_did)
assert deckNames() == ["Languages", "Languages::Chinese", "Languages::Chinese::HSK"]
# Dragging a deck onto a descendant is a no-op
d.decks.renameForDragAndDrop(languages_did, hsk_did)
assert deckNames() == ["Languages", "Languages::Chinese", "Languages::Chinese::HSK"]
# Can drag a grandchild onto its grandparent. It becomes a child
d.decks.renameForDragAndDrop(hsk_did, languages_did)
assert deckNames() == ["Languages", "Languages::Chinese", "Languages::HSK"]
# Can drag a deck onto its sibling
d.decks.renameForDragAndDrop(hsk_did, chinese_did)
assert deckNames() == ["Languages", "Languages::Chinese", "Languages::Chinese::HSK"]
# Can drag a deck back to the top level
d.decks.renameForDragAndDrop(chinese_did, None)
assert deckNames() == ["Chinese", "Chinese::HSK", "Languages"]
# Dragging a top level deck to the top level is a no-op
d.decks.renameForDragAndDrop(chinese_did, None)
assert deckNames() == ["Chinese", "Chinese::HSK", "Languages"]
# can't drack a deck where sibling have same name
new_hsk_did = d.decks.id("HSK")
assertException(
DeckRenameError, lambda: d.decks.renameForDragAndDrop(new_hsk_did, chinese_did)
)
d.decks.rem(new_hsk_did)
# can't drack a deck where sibling have same name different case
new_hsk_did = d.decks.id("hsk")
assertException(
DeckRenameError, lambda: d.decks.renameForDragAndDrop(new_hsk_did, chinese_did)
)
d.decks.rem(new_hsk_did)
# '' is a convenient alias for the top level DID
d.decks.renameForDragAndDrop(hsk_did, "")
assert deckNames() == ["Chinese", "HSK", "Languages"]
def test_check():
d = getEmptyCol()
# currently disabled - see 5418af00f733ca62b0c087d1422feae01d6571b0
# foo_did = d.decks.id("foo")
# FOO_did = d.decks.id("bar")
# FOO = d.decks.byName("bar")
# FOO["name"] = "FOO"
# d.decks.save(FOO)
# d.decks._checkDeckTree()
# assert "foo" not in d.decks.allNames() or "FOO" not in d.decks.allNames()