Skip to content

Commit

Permalink
Add test coverage of template feature
Browse files Browse the repository at this point in the history
  • Loading branch information
vkbo committed Feb 8, 2024
1 parent 4113be7 commit 8ff292f
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 10 deletions.
10 changes: 6 additions & 4 deletions novelwriter/gui/projtree.py
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,10 @@ def newTreeItem(self, itemType: nwItemType, itemClass: nwItemClass | None = None
# Set default label and determine if new item is to be added
# as child or sibling to the selected item
if itemType == nwItemType.FILE:
if isNote:
if copyDoc and (cItem := SHARED.project.tree[copyDoc]):
newLabel = cItem.itemName
asChild = sIsParent and pItem.isDocumentLayout()
elif isNote:
newLabel = self.tr("New Note")
asChild = sIsParent
elif hLevel == 2:
Expand Down Expand Up @@ -804,8 +807,7 @@ def moveToLevel(self, step: int) -> None:

def renameTreeItem(self, tHandle: str, name: str = "") -> None:
"""Open a dialog to edit the label of an item."""
tItem = SHARED.project.tree[tHandle]
if tItem:
if tItem := SHARED.project.tree[tHandle]:
newLabel, dlgOk = GuiEditLabel.getLabel(self, text=name or tItem.itemName)
if dlgOk:
tItem.setName(newLabel)
Expand Down Expand Up @@ -1707,7 +1709,7 @@ def remove(self, tHandle: str) -> None:
if action := self._map.pop(tHandle, None):
self.removeAction(action)
if not self._map:
self.setActionsVisible(True)
self.setActionsVisible(False)
return

def clearMenu(self) -> None:
Expand Down
19 changes: 19 additions & 0 deletions tests/test_core/test_core_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ def testCoreItem_ClassSetter(mockGUI):
"""
project = NWProject()
item = NWItem(project, "0000000000000")
item.setType(nwItemType.FILE)

# Class
item.setClass(None)
Expand All @@ -377,66 +378,84 @@ def testCoreItem_ClassSetter(mockGUI):
assert item.isNovelLike() is False
assert item.documentAllowed() is False
assert item.isInactiveClass() is True
assert item.isTemplateFile() is False

item.setClass("NOVEL")
assert item.itemClass == nwItemClass.NOVEL
assert item.isNovelLike() is True
assert item.documentAllowed() is True
assert item.isInactiveClass() is False
assert item.isTemplateFile() is False

item.setClass("PLOT")
assert item.itemClass == nwItemClass.PLOT
assert item.isNovelLike() is False
assert item.documentAllowed() is False
assert item.isInactiveClass() is False
assert item.isTemplateFile() is False

item.setClass("CHARACTER")
assert item.itemClass == nwItemClass.CHARACTER
assert item.isNovelLike() is False
assert item.documentAllowed() is False
assert item.isInactiveClass() is False
assert item.isTemplateFile() is False

item.setClass("WORLD")
assert item.itemClass == nwItemClass.WORLD
assert item.isNovelLike() is False
assert item.documentAllowed() is False
assert item.isInactiveClass() is False
assert item.isTemplateFile() is False

item.setClass("TIMELINE")
assert item.itemClass == nwItemClass.TIMELINE
assert item.isNovelLike() is False
assert item.documentAllowed() is False
assert item.isInactiveClass() is False
assert item.isTemplateFile() is False

item.setClass("OBJECT")
assert item.itemClass == nwItemClass.OBJECT
assert item.isNovelLike() is False
assert item.documentAllowed() is False
assert item.isInactiveClass() is False
assert item.isTemplateFile() is False

item.setClass("ENTITY")
assert item.itemClass == nwItemClass.ENTITY
assert item.isNovelLike() is False
assert item.documentAllowed() is False
assert item.isInactiveClass() is False
assert item.isTemplateFile() is False

item.setClass("CUSTOM")
assert item.itemClass == nwItemClass.CUSTOM
assert item.isNovelLike() is False
assert item.documentAllowed() is False
assert item.isInactiveClass() is False
assert item.isTemplateFile() is False

item.setClass("ARCHIVE")
assert item.itemClass == nwItemClass.ARCHIVE
assert item.isNovelLike() is True
assert item.documentAllowed() is True
assert item.isInactiveClass() is True
assert item.isTemplateFile() is False

item.setClass("TEMPLATE")
assert item.itemClass == nwItemClass.TEMPLATE
assert item.isNovelLike() is True
assert item.documentAllowed() is True
assert item.isInactiveClass() is True
assert item.isTemplateFile() is True

item.setClass("TRASH")
assert item.itemClass == nwItemClass.TRASH
assert item.isNovelLike() is False
assert item.documentAllowed() is True
assert item.isInactiveClass() is True
assert item.isTemplateFile() is False

# Alternative
item.setClass(nwItemClass.NOVEL)
Expand Down
120 changes: 114 additions & 6 deletions tests/test_gui/test_gui_projtree.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,28 @@ def testGuiProjTree_NewItems(qtbot, caplog, monkeypatch, nwGUI, projPath, mockRn
assert nwGUI.docEditor.getText() == "### New Scene\n\n"
assert projTree._getItemWordCount("0000000000014") == 2

# Add a new scene with the content copied from the previous
assert nwGUI.openDocument("0000000000014")
nwGUI.docEditor.setPlainText("### New Scene\n\nWith Stuff\n\n")
nwGUI.saveDocument()
projView.setSelectedHandle("0000000000014")
assert projTree.newTreeItem(nwItemType.FILE, copyDoc="0000000000014") is True
assert project.tree["0000000000015"].itemParent == "0000000000011" # type: ignore
assert project.tree["0000000000015"].itemRoot == C.hNovelRoot # type: ignore
assert project.tree["0000000000015"].itemClass == nwItemClass.NOVEL # type: ignore
assert nwGUI.openDocument("0000000000015")
assert nwGUI.docEditor.getText() == "### New Scene\n\nWith Stuff\n\n"
assert projTree._getItemWordCount("0000000000015") == 4

# Add a new file to the characters folder
projView.setSelectedHandle(C.hCharRoot)
assert projTree.newTreeItem(nwItemType.FILE, hLevel=1, isNote=True) is True
assert project.tree["0000000000015"].itemParent == C.hCharRoot # type: ignore
assert project.tree["0000000000015"].itemRoot == C.hCharRoot # type: ignore
assert project.tree["0000000000015"].itemClass == nwItemClass.CHARACTER # type: ignore
assert nwGUI.openDocument("0000000000015")
assert project.tree["0000000000016"].itemParent == C.hCharRoot # type: ignore
assert project.tree["0000000000016"].itemRoot == C.hCharRoot # type: ignore
assert project.tree["0000000000016"].itemClass == nwItemClass.CHARACTER # type: ignore
assert nwGUI.openDocument("0000000000016")
assert nwGUI.docEditor.getText() == "# New Note\n\n"
assert projTree._getItemWordCount("0000000000015") == 2
assert projTree._getItemWordCount("0000000000016") == 2

# Make sure the sibling folder bug trap works
projView.setSelectedHandle("0000000000013")
Expand Down Expand Up @@ -1112,7 +1125,7 @@ def testGuiProjTree_Other(qtbot, monkeypatch, nwGUI: GuiMain, projPath, mockRnd)
@pytest.mark.gui
def testGuiProjTree_ContextMenu(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
"""Test the building of the project tree context menu. All this does
is test that the menu builds. It doesn't open the actual menu,
is test that the menu builds. It doesn't open the actual menu.
"""
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))

Expand Down Expand Up @@ -1392,3 +1405,98 @@ def getTransformSubMenu(menu: QMenu) -> list[str]:
# qtbot.stop()

# END Test testGuiProjTree_ContextMenu


@pytest.mark.gui
def testGuiProjTree_Templates(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
"""Test the templates feature of the project tree."""
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))

# Create a project
buildTestProject(nwGUI, projPath)
nwGUI.openProject(projPath)
nwGUI.switchFocus(nwWidget.TREE)
nwGUI.show()

project = SHARED.project

projView = nwGUI.projView
projTree = projView.projTree
projBar = projView.projBar

# Handles for new objects
hTemplatesRoot = "0000000000010"
hSceneTemplate = "0000000000011"
hNoteTemplate = "0000000000012"
hNewScene = "0000000000013"
hNewCharacter = "0000000000014"

# Add template folder
projTree.newTreeItem(nwItemType.ROOT, nwItemClass.TEMPLATE)
nwTemplateRoot = project.tree[hTemplatesRoot]
assert nwTemplateRoot is not None
assert nwTemplateRoot.itemName == "Templates"

# Add a scene template
projTree.setSelectedHandle(hTemplatesRoot)
projTree.newTreeItem(nwItemType.FILE, hLevel=3, isNote=False)
nwSceneTemplate = project.tree[hSceneTemplate]
assert nwSceneTemplate is not None
assert nwSceneTemplate.itemName == "New Scene"
assert projBar.mTemplates.actions()[0].text() == "New Scene"

# Rename the scene template
with qtbot.waitSignal(projTree.itemRefreshed, timeout=1000) as signal:
projTree.renameTreeItem(hSceneTemplate, name="Scene")
assert signal.args[0] == hSceneTemplate
assert signal.args[1].itemName == "Scene"
assert projBar.mTemplates.actions()[0].text() == "Scene"

# Add a note template
projTree.setSelectedHandle(hTemplatesRoot)
projTree.newTreeItem(nwItemType.FILE, hLevel=1, isNote=True)
nwNoteTemplate = project.tree[hNoteTemplate]
assert nwNoteTemplate is not None
assert nwNoteTemplate.itemName == "New Note"
assert projBar.mTemplates.actions()[1].text() == "New Note"

# Rename the note template
with qtbot.waitSignal(projTree.itemRefreshed, timeout=1000) as signal:
projTree.renameTreeItem(hNoteTemplate, name="Note")
assert signal.args[0] == hNoteTemplate
assert signal.args[1].itemName == "Note"
assert projBar.mTemplates.actions()[1].text() == "Note"

# Add new content to template files
(projPath / "content" / f"{hSceneTemplate}.nwd").write_text("### Scene\n\n@pov: Jane\n\n")
(projPath / "content" / f"{hNoteTemplate}.nwd").write_text("# Jane\n\n@tag: Jane\n\n")

# Add a new scene using the template
projTree.setSelectedHandle(C.hSceneDoc, doScroll=True)
projBar.mTemplates.actions()[0].trigger()
nwNewScene = project.tree[hNewScene]
assert nwNewScene is not None
assert nwNewScene.itemName == "Scene"
assert project.storage.getDocument(hNewScene).readDocument() == "### Scene\n\n@pov: Jane\n\n"

# Add a new note using the template
projTree.setSelectedHandle(C.hCharRoot, doScroll=True)
projBar.mTemplates.actions()[1].trigger()
nwNewCharacter = project.tree[hNewCharacter]
assert nwNewCharacter is not None
assert nwNewCharacter.itemName == "Note"
assert project.storage.getDocument(hNewCharacter).readDocument() == "# Jane\n\n@tag: Jane\n\n"

# Remove the templates
with qtbot.waitSignal(projTree.itemRefreshed, timeout=1000) as signal:
assert projBar.mTemplates.menuAction().isVisible() is True
assert len(projBar.mTemplates.actions()) == 2
projTree.moveItemToTrash(hNoteTemplate)
assert len(projBar.mTemplates.actions()) == 1
projTree.moveItemToTrash(hSceneTemplate)
assert len(projBar.mTemplates.actions()) == 0
assert projBar.mTemplates.menuAction().isVisible() is False

# qtbot.stop()

# END Test testGuiProjTree_Templates

0 comments on commit 8ff292f

Please sign in to comment.