Clean up the logic of creating new project tree items, and improve test coverage

This commit is contained in:
Veronica K. B. Olsen
2020-12-21 21:08:13 +01:00
parent 4509545214
commit 6ad132e12d
2 changed files with 117 additions and 46 deletions
+18 -17
View File
@@ -164,6 +164,11 @@ class GuiProjectTree(QTreeWidget):
logger.error("No project open") logger.error("No project open")
return False return False
if not isinstance(itemType, nwItemType):
# This would indicate an internal bug
logger.error("No itemType provided")
return False
# The item needs to be assigned an item class, so one must be # The item needs to be assigned an item class, so one must be
# provided, or it must be possible to extract it from the parent # provided, or it must be possible to extract it from the parent
# item of the new item. # item of the new item.
@@ -172,21 +177,18 @@ class GuiProjectTree(QTreeWidget):
if pItem is not None: if pItem is not None:
itemClass = pItem.itemClass itemClass = pItem.itemClass
# If class is still not set, alert the user and exit
if itemClass is None: if itemClass is None:
if itemType is not None: if itemType == nwItemType.FILE:
if itemType == nwItemType.FILE: self.makeAlert(
self.makeAlert( "Please select a valid location in the tree to add the document.",
"Please select a valid location in the tree to add a document.", nwAlert.ERROR
nwAlert.ERROR )
) else:
return False self.makeAlert(
elif itemType == nwItemType.FOLDER: "Please select a valid location in the tree to add the folder.",
self.makeAlert( nwAlert.ERROR
"Please select a valid location in the tree to add a folder.", )
nwAlert.ERROR
)
return False
self.makeAlert("Failed to add new item.", nwAlert.BUG)
return False return False
# Everything is fine, we have what we need, so we proceed # Everything is fine, we have what we need, so we proceed
@@ -259,8 +261,7 @@ class GuiProjectTree(QTreeWidget):
# Add the new item to the tree # Add the new item to the tree
if tHandle is not None: if tHandle is not None:
self.revealNewTreeItem(tHandle, nHandle) self.revealNewTreeItem(tHandle, nHandle)
if self.mainConf.showGUI: self.theParent.editItem(tHandle)
self.theParent.editItem(tHandle)
return True return True
@@ -287,7 +288,7 @@ class GuiProjectTree(QTreeWidget):
logger.error("No project open") logger.error("No project open")
return False return False
if qApp.focusWidget() != self and self.mainConf.showGUI: if qApp.focusWidget() != self:
return False return False
tHandle = self.getSelectedHandle() tHandle = self.getSelectedHandle()
+99 -29
View File
@@ -5,95 +5,133 @@
import pytest import pytest
import os import os
from tools import writeFile
from PyQt5.QtCore import QItemSelectionModel from PyQt5.QtCore import QItemSelectionModel
from PyQt5.QtWidgets import QAction, QMessageBox from PyQt5.QtWidgets import QAction, QMessageBox
from nw.constants import nwItemType, nwItemClass from nw.constants import nwItemType, nwItemClass
keyDelay = 2
typeDelay = 1
stepDelay = 20
@pytest.mark.gui @pytest.mark.gui
def testGuiProjTree_Main(qtbot, monkeypatch, nwGUI, nwMinimal): def testGuiProjTree_TreeItems(qtbot, caplog, monkeypatch, nwGUI, nwMinimal):
"""Test the project tree. """Test adding and removing items from the project tree.
""" """
# Block message box # Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
monkeypatch.setattr("nw.guimain.GuiMain.editItem", lambda *args: None)
nwGUI.theProject.projTree.setSeed(42) nwGUI.theProject.projTree.setSeed(42)
assert nwGUI.openProject(nwMinimal)
nwTree = nwGUI.treeView nwTree = nwGUI.treeView
##
# Add New Items
##
# Try to add and move item with no project
assert not nwTree.newTreeItem(nwItemType.FILE, None)
assert not nwTree.moveTreeItem(1)
# Open a project
assert nwGUI.openProject(nwMinimal)
# No location selected for new item # No location selected for new item
nwTree.clearSelection()
assert not nwTree.newTreeItem(nwItemType.FILE, None) assert not nwTree.newTreeItem(nwItemType.FILE, None)
assert not nwTree.newTreeItem(nwItemType.FOLDER, None) assert not nwTree.newTreeItem(nwItemType.FOLDER, None)
assert nwTree.newTreeItem(nwItemType.FILE, nwItemClass.NOVEL)
# No itemType set or ROOT, but no class
assert not nwTree.newTreeItem(None, None)
assert not nwTree.newTreeItem(nwItemType.ROOT, None)
# Select a location # Select a location
chItem = nwTree._getTreeItem("a6d311a93600a") chItem = nwTree._getTreeItem("a6d311a93600a")
nwTree.setCurrentItem(chItem, QItemSelectionModel.Current) nwTree.setCurrentItem(chItem, QItemSelectionModel.Current)
chItem.setExpanded(True) chItem.setExpanded(True)
# Create new item with no class set # Create new item with no class set (defaults to NOVEL)
assert nwTree.newTreeItem(nwItemType.FILE, None) assert nwTree.newTreeItem(nwItemType.FILE, None)
assert nwTree.newTreeItem(nwItemType.FOLDER, None) assert nwTree.newTreeItem(nwItemType.FOLDER, None)
# Check that we have the correct tree order
assert nwTree.getTreeFromHandle("a6d311a93600a") == [
"a6d311a93600a", "f5ab3e30151e1", "8c659a11cd429", "44cb730c42048", "71ee45a3c0db9"
]
# Add roots # Add roots
assert not nwTree.newTreeItem(nwItemType.ROOT, None) # Defaults to NOVEL
assert not nwTree.newTreeItem(nwItemType.ROOT, nwItemClass.WORLD) # Duplicate assert not nwTree.newTreeItem(nwItemType.ROOT, nwItemClass.WORLD) # Duplicate
assert nwTree.newTreeItem(nwItemType.ROOT, nwItemClass.CUSTOM) # Valid assert nwTree.newTreeItem(nwItemType.ROOT, nwItemClass.CUSTOM) # Valid
# Check that we have the correct tree order # Change max depth and try to add a subfolder that is too deep
monkeypatch.setattr("nw.constants.nwConst.MAX_DEPTH", 2)
chItem = nwTree._getTreeItem("71ee45a3c0db9")
nwTree.setCurrentItem(chItem, QItemSelectionModel.Current)
assert not nwTree.newTreeItem(nwItemType.FOLDER, None)
##
# Move Items
##
nwTree.setSelectedHandle("8c659a11cd429")
# Shift focus and try to move item
monkeypatch.setattr("PyQt5.QtWidgets.qApp.focusWidget", lambda: None)
assert not nwTree.moveTreeItem(1)
assert nwTree.getTreeFromHandle("a6d311a93600a") == [ assert nwTree.getTreeFromHandle("a6d311a93600a") == [
"a6d311a93600a", "f5ab3e30151e1", "8c659a11cd429", "73475cb40a568", "44cb730c42048" "a6d311a93600a", "f5ab3e30151e1", "8c659a11cd429", "44cb730c42048", "71ee45a3c0db9"
] ]
monkeypatch.setattr("PyQt5.QtWidgets.qApp.focusWidget", lambda: nwTree)
# Move second item up twice (should give same result) # Move second item up twice (should give same result)
nwTree.setSelectedHandle("8c659a11cd429")
nwGUI.mainMenu.aMoveUp.activate(QAction.Trigger) nwGUI.mainMenu.aMoveUp.activate(QAction.Trigger)
assert nwTree.getTreeFromHandle("a6d311a93600a") == [ assert nwTree.getTreeFromHandle("a6d311a93600a") == [
"a6d311a93600a", "8c659a11cd429", "f5ab3e30151e1", "73475cb40a568", "44cb730c42048" "a6d311a93600a", "8c659a11cd429", "f5ab3e30151e1", "44cb730c42048", "71ee45a3c0db9"
] ]
nwGUI.mainMenu.aMoveUp.activate(QAction.Trigger) nwGUI.mainMenu.aMoveUp.activate(QAction.Trigger)
assert nwTree.getTreeFromHandle("a6d311a93600a") == [ assert nwTree.getTreeFromHandle("a6d311a93600a") == [
"a6d311a93600a", "8c659a11cd429", "f5ab3e30151e1", "73475cb40a568", "44cb730c42048" "a6d311a93600a", "8c659a11cd429", "f5ab3e30151e1", "44cb730c42048", "71ee45a3c0db9"
] ]
# Move it back down four times (last to should be the same) # Move it back down four times (last two should be the same)
nwGUI.mainMenu.aMoveDown.activate(QAction.Trigger) nwGUI.mainMenu.aMoveDown.activate(QAction.Trigger)
assert nwTree.getTreeFromHandle("a6d311a93600a") == [ assert nwTree.getTreeFromHandle("a6d311a93600a") == [
"a6d311a93600a", "f5ab3e30151e1", "8c659a11cd429", "73475cb40a568", "44cb730c42048" "a6d311a93600a", "f5ab3e30151e1", "8c659a11cd429", "44cb730c42048", "71ee45a3c0db9"
] ]
nwGUI.mainMenu.aMoveDown.activate(QAction.Trigger) nwGUI.mainMenu.aMoveDown.activate(QAction.Trigger)
assert nwTree.getTreeFromHandle("a6d311a93600a") == [ assert nwTree.getTreeFromHandle("a6d311a93600a") == [
"a6d311a93600a", "f5ab3e30151e1", "73475cb40a568", "8c659a11cd429", "44cb730c42048" "a6d311a93600a", "f5ab3e30151e1", "44cb730c42048", "8c659a11cd429", "71ee45a3c0db9"
] ]
nwGUI.mainMenu.aMoveDown.activate(QAction.Trigger) nwGUI.mainMenu.aMoveDown.activate(QAction.Trigger)
assert nwTree.getTreeFromHandle("a6d311a93600a") == [ assert nwTree.getTreeFromHandle("a6d311a93600a") == [
"a6d311a93600a", "f5ab3e30151e1", "73475cb40a568", "44cb730c42048", "8c659a11cd429" "a6d311a93600a", "f5ab3e30151e1", "44cb730c42048", "71ee45a3c0db9", "8c659a11cd429"
] ]
nwGUI.mainMenu.aMoveDown.activate(QAction.Trigger) nwGUI.mainMenu.aMoveDown.activate(QAction.Trigger)
assert nwTree.getTreeFromHandle("a6d311a93600a") == [ assert nwTree.getTreeFromHandle("a6d311a93600a") == [
"a6d311a93600a", "f5ab3e30151e1", "73475cb40a568", "44cb730c42048", "8c659a11cd429" "a6d311a93600a", "f5ab3e30151e1", "44cb730c42048", "71ee45a3c0db9", "8c659a11cd429"
] ]
# Move a root item (top level items are different) twice # Move a root item (top level items are different) twice
nwTree.flushTreeOrder() nwTree.flushTreeOrder()
assert nwGUI.theProject.projTree._treeOrder.index("9d5247ab588e0") == 9 assert nwGUI.theProject.projTree._treeOrder.index("9d5247ab588e0") == 10
nwTree.setSelectedHandle("9d5247ab588e0") nwTree.setSelectedHandle("9d5247ab588e0")
nwGUI.mainMenu.aMoveDown.activate(QAction.Trigger) nwGUI.mainMenu.aMoveDown.activate(QAction.Trigger)
nwTree.flushTreeOrder() nwTree.flushTreeOrder()
assert nwGUI.theProject.projTree._treeOrder.index("9d5247ab588e0") == 10 assert nwGUI.theProject.projTree._treeOrder.index("9d5247ab588e0") == 11
nwGUI.mainMenu.aMoveDown.activate(QAction.Trigger) nwGUI.mainMenu.aMoveDown.activate(QAction.Trigger)
nwTree.flushTreeOrder() nwTree.flushTreeOrder()
assert nwGUI.theProject.projTree._treeOrder.index("9d5247ab588e0") == 10 assert nwGUI.theProject.projTree._treeOrder.index("9d5247ab588e0") == 11
##
# Delete and Trash
##
# Add some content to the new file # Add some content to the new file
nwGUI.openDocument("73475cb40a568") nwGUI.openDocument("73475cb40a568")
nwGUI.docEditor.setText("# Hello World\n") nwGUI.docEditor.setText("# Hello World\n")
nwGUI.saveDocument() nwGUI.saveDocument()
nwGUI.saveProject()
assert os.path.isfile(os.path.join(nwMinimal, "content", "73475cb40a568.nwd")) assert os.path.isfile(os.path.join(nwMinimal, "content", "73475cb40a568.nwd"))
# Delete the items we added earlier # Delete the items we added earlier
@@ -102,11 +140,11 @@ def testGuiProjTree_Main(qtbot, monkeypatch, nwGUI, nwMinimal):
assert not nwTree.deleteItem(None) assert not nwTree.deleteItem(None)
assert not nwTree.deleteItem("1111111111111") assert not nwTree.deleteItem("1111111111111")
assert nwTree.deleteItem("73475cb40a568") # New File assert nwTree.deleteItem("73475cb40a568") # New File
assert nwTree.deleteItem("44cb730c42048") # New Folder assert nwTree.deleteItem("71ee45a3c0db9") # New Folder
assert nwTree.deleteItem("71ee45a3c0db9") # Custom Root assert nwTree.deleteItem("811786ad1ae74") # Custom Root
assert "73475cb40a568" in nwGUI.theProject.projTree._treeOrder assert "73475cb40a568" in nwGUI.theProject.projTree._treeOrder
assert "44cb730c42048" not in nwGUI.theProject.projTree._treeOrder
assert "71ee45a3c0db9" not in nwGUI.theProject.projTree._treeOrder assert "71ee45a3c0db9" not in nwGUI.theProject.projTree._treeOrder
assert "811786ad1ae74" not in nwGUI.theProject.projTree._treeOrder
# The file is in trash, empty it # The file is in trash, empty it
assert os.path.isfile(os.path.join(nwMinimal, "content", "73475cb40a568.nwd")) assert os.path.isfile(os.path.join(nwMinimal, "content", "73475cb40a568.nwd"))
@@ -115,13 +153,23 @@ def testGuiProjTree_Main(qtbot, monkeypatch, nwGUI, nwMinimal):
assert not os.path.isfile(os.path.join(nwMinimal, "content", "73475cb40a568.nwd")) assert not os.path.isfile(os.path.join(nwMinimal, "content", "73475cb40a568.nwd"))
assert "73475cb40a568" not in nwGUI.theProject.projTree._treeOrder assert "73475cb40a568" not in nwGUI.theProject.projTree._treeOrder
# Should not be allowed to add files and folders to Trash
trashHandle = nwGUI.theProject.projTree.trashRoot()
chItem = nwTree._getTreeItem(trashHandle)
nwTree.setCurrentItem(chItem, QItemSelectionModel.Current)
assert not nwTree.newTreeItem(nwItemType.FILE, None)
assert not nwTree.newTreeItem(nwItemType.FOLDER, None)
# Close the project # Close the project
nwGUI.closeProject() nwGUI.closeProject()
##
# Orphaned Files
##
# Add an orphaned file # Add an orphaned file
orphFile = os.path.join(nwMinimal, "content", "1234567890abc.nwd") orphFile = os.path.join(nwMinimal, "content", "1234567890abc.nwd")
with open(orphFile, mode="w+", encoding="utf8") as outFile: writeFile(orphFile, "# Hello World\n")
outFile.write("# Hello World\n")
# Open the project again # Open the project again
nwGUI.openProject(nwMinimal) nwGUI.openProject(nwMinimal)
@@ -132,6 +180,28 @@ def testGuiProjTree_Main(qtbot, monkeypatch, nwGUI, nwMinimal):
orItem = nwTree._getTreeItem("1234567890abc") orItem = nwTree._getTreeItem("1234567890abc")
assert orItem.text(nwTree.C_NAME) == "Recovered File 1" assert orItem.text(nwTree.C_NAME) == "Recovered File 1"
# qtbot.stopForInteraction() ##
# Unexpected Error Handling
##
# END Test testGuiProjTree_Main # Add an item with an invalid type
assert not nwTree.newTreeItem(nwItemType.NO_TYPE, nwItemClass.NOVEL)
assert "Failed to add new item" in caplog.messages[-1]
# Add new file after one that has no parent handle
chItem = nwTree._getTreeItem("44cb730c42048")
nwTree.setCurrentItem(chItem, QItemSelectionModel.Current)
nwTree.theProject.projTree["44cb730c42048"].itemParent = None
assert not nwTree.newTreeItem(nwItemType.FILE, nwItemClass.NOVEL)
nwTree.clearSelection()
# Add a file with no parent, and fail to find a suitable parent item
monkeypatch.setattr("nw.core.tree.NWTree.findRoot", lambda *args: None)
assert not nwTree.newTreeItem(nwItemType.FILE, nwItemClass.NOVEL)
assert not nwTree.newTreeItem(nwItemType.FOLDER, nwItemClass.NOVEL)
# qtbot.stopForInteraction()
nwGUI.closeProject()
# END Test testGuiProjTree_TreeItems