Clean up project tests

This commit is contained in:
Veronica Berglyd Olsen
2023-12-01 17:45:25 +01:00
parent 3fe2ee3058
commit 8952bbab1d
+234 -239
View File
@@ -26,6 +26,7 @@ from shutil import copyfile
from zipfile import ZipFile
from mocked import causeOSError
from novelwriter.core.item import NWItem
from tools import C, cmpFiles, buildTestProject, XML_IGNORE
from PyQt5.QtWidgets import QMessageBox
@@ -47,45 +48,45 @@ def testCoreProject_NewRoot(fncPath, tstPaths, mockGUI, mockRnd):
testFile = tstPaths.outDir / "coreProject_NewRoot_nwProject.nwx"
compFile = tstPaths.refDir / "coreProject_NewRoot_nwProject.nwx"
theProject = NWProject()
project = NWProject()
mockRnd.reset()
buildTestProject(theProject, fncPath)
buildTestProject(project, fncPath)
assert theProject.newRoot(nwItemClass.NOVEL) == "0000000000010"
assert theProject.newRoot(nwItemClass.PLOT) == "0000000000011"
assert theProject.newRoot(nwItemClass.CHARACTER) == "0000000000012"
assert theProject.newRoot(nwItemClass.WORLD) == "0000000000013"
assert theProject.newRoot(nwItemClass.TIMELINE) == "0000000000014"
assert theProject.newRoot(nwItemClass.OBJECT) == "0000000000015"
assert theProject.newRoot(nwItemClass.CUSTOM) == "0000000000016"
assert theProject.newRoot(nwItemClass.CUSTOM) == "0000000000017"
assert project.newRoot(nwItemClass.NOVEL) == "0000000000010"
assert project.newRoot(nwItemClass.PLOT) == "0000000000011"
assert project.newRoot(nwItemClass.CHARACTER) == "0000000000012"
assert project.newRoot(nwItemClass.WORLD) == "0000000000013"
assert project.newRoot(nwItemClass.TIMELINE) == "0000000000014"
assert project.newRoot(nwItemClass.OBJECT) == "0000000000015"
assert project.newRoot(nwItemClass.CUSTOM) == "0000000000016"
assert project.newRoot(nwItemClass.CUSTOM) == "0000000000017"
assert theProject.projChanged is True
assert theProject.saveProject() is True
theProject.closeProject()
assert project.projChanged is True
assert project.saveProject() is True
project.closeProject()
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE)
assert theProject.projChanged is False
assert project.projChanged is False
# Delete the new items
assert theProject.removeItem("0000000000010") is True
assert theProject.removeItem("0000000000011") is True
assert theProject.removeItem("0000000000012") is True
assert theProject.removeItem("0000000000013") is True
assert theProject.removeItem("0000000000014") is True
assert theProject.removeItem("0000000000015") is True
assert theProject.removeItem("0000000000016") is True
assert theProject.removeItem("0000000000017") is True
assert project.removeItem("0000000000010") is True
assert project.removeItem("0000000000011") is True
assert project.removeItem("0000000000012") is True
assert project.removeItem("0000000000013") is True
assert project.removeItem("0000000000014") is True
assert project.removeItem("0000000000015") is True
assert project.removeItem("0000000000016") is True
assert project.removeItem("0000000000017") is True
assert "0000000000010" not in theProject.tree
assert "0000000000011" not in theProject.tree
assert "0000000000012" not in theProject.tree
assert "0000000000013" not in theProject.tree
assert "0000000000014" not in theProject.tree
assert "0000000000015" not in theProject.tree
assert "0000000000016" not in theProject.tree
assert "0000000000017" not in theProject.tree
assert "0000000000010" not in project.tree
assert "0000000000011" not in project.tree
assert "0000000000012" not in project.tree
assert "0000000000013" not in project.tree
assert "0000000000014" not in project.tree
assert "0000000000015" not in project.tree
assert "0000000000016" not in project.tree
assert "0000000000017" not in project.tree
# END Test testCoreProject_NewRoot
@@ -97,68 +98,68 @@ def testCoreProject_NewFileFolder(monkeypatch, fncPath, tstPaths, mockGUI, mockR
testFile = tstPaths.outDir / "coreProject_NewFileFolder_nwProject.nwx"
compFile = tstPaths.refDir / "coreProject_NewFileFolder_nwProject.nwx"
theProject = NWProject()
project = NWProject()
mockRnd.reset()
buildTestProject(theProject, fncPath)
buildTestProject(project, fncPath)
# Invalid call
assert theProject.newFolder("New Folder", "1234567890abc") is None
assert theProject.newFile("New File", "1234567890abc") is None
assert project.newFolder("New Folder", "1234567890abc") is None
assert project.newFile("New File", "1234567890abc") is None
# Add files properly
assert theProject.newFolder("Stuff", C.hNovelRoot) == "0000000000010"
assert theProject.newFile("Hello", "0000000000010") == "0000000000011"
assert theProject.newFile("Jane", C.hCharRoot) == "0000000000012"
assert project.newFolder("Stuff", C.hNovelRoot) == "0000000000010"
assert project.newFile("Hello", "0000000000010") == "0000000000011"
assert project.newFile("Jane", C.hCharRoot) == "0000000000012"
assert "0000000000010" in theProject.tree
assert "0000000000011" in theProject.tree
assert "0000000000012" in theProject.tree
assert "0000000000010" in project.tree
assert "0000000000011" in project.tree
assert "0000000000012" in project.tree
# Write to file, failed
assert theProject.writeNewFile("blabla", 1, True) is False # Not a handle
assert theProject.writeNewFile("0000000000010", 1, True) is False # Not a file
assert theProject.writeNewFile(C.hTitlePage, 1, True) is False # Already has content
assert project.writeNewFile("blabla", 1, True) is False # Not a handle
assert project.writeNewFile("0000000000010", 1, True) is False # Not a file
assert project.writeNewFile(C.hTitlePage, 1, True) is False # Already has content
# Write to file, success
assert theProject.writeNewFile("0000000000011", 2, True) is True
assert theProject.storage.getDocument("0000000000011").readDocument() == "## Hello\n\n"
assert project.writeNewFile("0000000000011", 2, True) is True
assert project.storage.getDocument("0000000000011").readDocument() == "## Hello\n\n"
# Write to file with additional text, success
assert theProject.writeNewFile("0000000000012", 1, False, "Hi Jane\n\n") is True
assert theProject.storage.getDocument("0000000000012").readDocument() == (
assert project.writeNewFile("0000000000012", 1, False, "Hi Jane\n\n") is True
assert project.storage.getDocument("0000000000012").readDocument() == (
"# Jane\n\nHi Jane\n\n"
)
# Save, close and check
assert theProject.projChanged is True
assert theProject.saveProject() is True
assert project.projChanged is True
assert project.saveProject() is True
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE)
assert theProject.projChanged is False
assert project.projChanged is False
# Delete new file, but block access
with monkeypatch.context() as mp:
mp.setattr("pathlib.Path.unlink", causeOSError)
assert theProject.removeItem("0000000000011") is False
assert "0000000000011" in theProject.tree
assert project.removeItem("0000000000011") is False
assert "0000000000011" in project.tree
# Delete new files and folders
assert (fncPath / "content" / "0000000000012.nwd").exists()
assert (fncPath / "content" / "0000000000011.nwd").exists()
assert theProject.removeItem("0000000000012") is True
assert theProject.removeItem("0000000000011") is True
assert theProject.removeItem("0000000000010") is True
assert project.removeItem("0000000000012") is True
assert project.removeItem("0000000000011") is True
assert project.removeItem("0000000000010") is True
assert not (fncPath / "content" / "0000000000012.nwd").exists()
assert not (fncPath / "content" / "0000000000011.nwd").exists()
assert "0000000000010" not in theProject.tree
assert "0000000000011" not in theProject.tree
assert "0000000000012" not in theProject.tree
assert "0000000000010" not in project.tree
assert "0000000000011" not in project.tree
assert "0000000000012" not in project.tree
theProject.closeProject()
project.closeProject()
# END Test testCoreProject_NewFileFolder
@@ -166,93 +167,85 @@ def testCoreProject_NewFileFolder(monkeypatch, fncPath, tstPaths, mockGUI, mockR
@pytest.mark.core
def testCoreProject_Open(monkeypatch, caplog, mockGUI, fncPath, mockRnd):
"""Test opening a project."""
theProject = NWProject()
project = NWProject()
mockRnd.reset()
buildTestProject(theProject, fncPath)
buildTestProject(project, fncPath)
# Initialising the storage class fails
with monkeypatch.context() as mp:
mp.setattr("novelwriter.core.storage.NWStorage.initProjectStorage", lambda *a, **k: False)
assert theProject.openProject(fncPath) is False
assert project.openProject(fncPath) is False
# Fail on lock file
theProject.storage._lockFilePath = fncPath / nwFiles.PROJ_LOCK
assert theProject.storage._writeLockFile() is True
assert theProject.openProject(fncPath) is False
assert isinstance(theProject.lockStatus, list)
# Fail to read lockfile (which still opens the project)
with monkeypatch.context() as mp:
mp.setattr("novelwriter.core.storage.NWStorage._readLockFile", lambda *a: ["ERROR"])
caplog.clear()
assert theProject.openProject(fncPath) is True
assert "Failed to check lock file" in caplog.text
theProject.closeProject()
project.storage._lockFilePath = fncPath / nwFiles.PROJ_LOCK
assert project.storage._writeLockFile() is True
assert project.openProject(fncPath) is False
assert isinstance(project.lockStatus, list)
# Force open with lockfile
theProject.storage._lockFilePath = fncPath / nwFiles.PROJ_LOCK
assert theProject.storage._writeLockFile() is True
assert theProject.openProject(fncPath, clearLock=True) is True
theProject.closeProject()
assert theProject.lockStatus is None
project.storage._lockFilePath = fncPath / nwFiles.PROJ_LOCK
assert project.storage._writeLockFile() is True
assert project.openProject(fncPath, clearLock=True) is True
project.closeProject()
assert project.lockStatus is None
# Fail getting xml reader
with monkeypatch.context() as mp:
mp.setattr("novelwriter.core.storage.NWStorage.getXmlReader", lambda *a: None)
assert theProject.openProject(fncPath) is False
assert project.openProject(fncPath) is False
# Not a novelwriter XML file
with monkeypatch.context() as mp:
mp.setattr(ProjectXMLReader, "read", lambda *a: False)
mp.setattr(ProjectXMLReader, "state", property(lambda *a: XMLReadState.NOT_NWX_FILE))
assert theProject.openProject(fncPath) is False
assert project.openProject(fncPath) is False
assert "Project file does not appear" in SHARED.lastAlert
# Unknown project file version
with monkeypatch.context() as mp:
mp.setattr(ProjectXMLReader, "read", lambda *a: False)
mp.setattr(ProjectXMLReader, "state", property(lambda *a: XMLReadState.UNKNOWN_VERSION))
assert theProject.openProject(fncPath) is False
assert project.openProject(fncPath) is False
assert "Unknown or unsupported novelWriter project file" in SHARED.lastAlert
# Other parse error
with monkeypatch.context() as mp:
mp.setattr(ProjectXMLReader, "read", lambda *a: False)
mp.setattr(ProjectXMLReader, "state", property(lambda *a: XMLReadState.CANNOT_PARSE))
assert theProject.openProject(fncPath) is False
assert project.openProject(fncPath) is False
assert "Failed to parse project xml" in SHARED.lastAlert
# Won't convert legacy file
with monkeypatch.context() as mp:
mp.setattr(ProjectXMLReader, "state", property(lambda *a: XMLReadState.WAS_LEGACY))
mp.setattr(QMessageBox, "result", lambda *a: QMessageBox.No)
assert theProject.openProject(fncPath) is False
assert project.openProject(fncPath) is False
assert "The file format of your project is about to be" in SHARED.lastAlert
# Won't open project from newer version
with monkeypatch.context() as mp:
mp.setattr(ProjectXMLReader, "hexVersion", property(lambda *a: 0x99999999))
mp.setattr(QMessageBox, "result", lambda *a: QMessageBox.No)
assert theProject.openProject(fncPath) is False
assert project.openProject(fncPath) is False
assert "This project was saved by a newer version" in SHARED.lastAlert
# Fail checking items should still pass
with monkeypatch.context() as mp:
mp.setattr("novelwriter.core.tree.NWTree.updateItemData", lambda *a: False)
assert theProject.openProject(fncPath) is True
assert project.openProject(fncPath) is True
theProject.closeProject()
project.closeProject()
# Trigger an index rebuild
with monkeypatch.context() as mp:
mp.setattr(ProjectXMLReader, "state", property(lambda *a: XMLReadState.WAS_LEGACY))
mp.setattr("novelwriter.core.index.NWIndex.loadIndex", lambda *a: True)
theProject.index._indexBroken = True
assert theProject.openProject(fncPath) is True
project.index._indexBroken = True
assert project.openProject(fncPath) is True
assert "The file format of your project is about to be" in SHARED.lastAlert
assert theProject.index._indexBroken is False
assert project.index._indexBroken is False
theProject.closeProject()
project.closeProject()
# END Test testCoreProject_Open
@@ -260,28 +253,28 @@ def testCoreProject_Open(monkeypatch, caplog, mockGUI, fncPath, mockRnd):
@pytest.mark.core
def testCoreProject_Save(monkeypatch, mockGUI, mockRnd, fncPath):
"""Test saving a project."""
theProject = NWProject()
project = NWProject()
# Nothing to save
assert theProject.saveProject() is False
assert project.saveProject() is False
mockRnd.reset()
buildTestProject(theProject, fncPath)
buildTestProject(project, fncPath)
# Fail getting xml writer
with monkeypatch.context() as mp:
mp.setattr("novelwriter.core.storage.NWStorage.getXmlWriter", lambda *a: None)
assert theProject.saveProject() is False
assert project.saveProject() is False
# Fail writing
with monkeypatch.context() as mp:
mp.setattr(ProjectXMLWriter, "write", lambda *a: False)
assert theProject.saveProject() is False
assert project.saveProject() is False
# Save with and without autosave
assert theProject.saveProject(autoSave=False) is True
assert theProject.saveProject(autoSave=True) is True
theProject.closeProject()
assert project.saveProject(autoSave=False) is True
assert project.saveProject(autoSave=True) is True
project.closeProject()
# END Test testCoreProject_Save
@@ -289,13 +282,13 @@ def testCoreProject_Save(monkeypatch, mockGUI, mockRnd, fncPath):
@pytest.mark.core
def testCoreProject_AccessItems(mockGUI, fncPath, mockRnd):
"""Test helper functions for the project folder."""
theProject = NWProject()
buildTestProject(theProject, fncPath)
project = NWProject()
buildTestProject(project, fncPath)
# Storage Objects
assert isinstance(theProject.index, NWIndex)
assert isinstance(theProject.tree, NWTree)
assert isinstance(theProject.options, OptionState)
assert isinstance(project.index, NWIndex)
assert isinstance(project.tree, NWTree)
assert isinstance(project.options, OptionState)
# Move Novel ROOT to after its files
oldOrder = [
@@ -318,20 +311,22 @@ def testCoreProject_AccessItems(mockGUI, fncPath, mockRnd):
C.hCharRoot,
C.hWorldRoot,
]
assert theProject.tree.handles() == oldOrder
theProject.setTreeOrder(newOrder)
assert theProject.tree.handles() == newOrder
assert project.tree.handles() == oldOrder
project.setTreeOrder(newOrder)
assert project.tree.handles() == newOrder
# Add a non-existing item
theProject.tree._order.append(C.hInvalid)
project.tree._order.append(C.hInvalid)
# Add an item with a non-existent parent
nHandle = theProject.newFile("Test File", C.hChapterDir)
theProject.tree[nHandle].setParent("cba9876543210")
assert theProject.tree[nHandle].itemParent == "cba9876543210"
nHandle = project.newFile("Test File", C.hChapterDir)
nItem = project.tree[nHandle]
assert isinstance(nItem, NWItem)
nItem.setParent("cba9876543210")
assert nItem.itemParent == "cba9876543210"
retOrder = []
for tItem in theProject.iterProjectItems():
for tItem in project.iterProjectItems():
retOrder.append(tItem.itemHandle)
assert retOrder == [
@@ -345,7 +340,7 @@ def testCoreProject_AccessItems(mockGUI, fncPath, mockRnd):
C.hChapterDoc,
C.hSceneDoc,
]
assert theProject.tree[nHandle].itemParent is None
assert nItem.itemParent is None
# END Test testCoreProject_AccessItems
@@ -353,9 +348,9 @@ def testCoreProject_AccessItems(mockGUI, fncPath, mockRnd):
@pytest.mark.core
def testCoreProject_StatusImport(mockGUI, fncPath, mockRnd):
"""Test the status and importance flag handling."""
theProject = NWProject()
project = NWProject()
mockRnd.reset()
buildTestProject(theProject, fncPath)
buildTestProject(project, fncPath)
statusKeys = [C.sNew, C.sNote, C.sDraft, C.sFinished]
importKeys = [C.iNew, C.iMinor, C.iMajor, C.iMain]
@@ -363,15 +358,15 @@ def testCoreProject_StatusImport(mockGUI, fncPath, mockRnd):
# Change Status
# =============
theProject.tree[C.hNovelRoot].setStatus(statusKeys[3])
theProject.tree[C.hPlotRoot].setStatus(statusKeys[2])
theProject.tree[C.hCharRoot].setStatus(statusKeys[1])
theProject.tree[C.hWorldRoot].setStatus(statusKeys[3])
project.tree[C.hNovelRoot].setStatus(statusKeys[3]) # type: ignore
project.tree[C.hPlotRoot].setStatus(statusKeys[2]) # type: ignore
project.tree[C.hCharRoot].setStatus(statusKeys[1]) # type: ignore
project.tree[C.hWorldRoot].setStatus(statusKeys[3]) # type: ignore
assert theProject.tree[C.hNovelRoot].itemStatus == statusKeys[3]
assert theProject.tree[C.hPlotRoot].itemStatus == statusKeys[2]
assert theProject.tree[C.hCharRoot].itemStatus == statusKeys[1]
assert theProject.tree[C.hWorldRoot].itemStatus == statusKeys[3]
assert project.tree[C.hNovelRoot].itemStatus == statusKeys[3] # type: ignore
assert project.tree[C.hPlotRoot].itemStatus == statusKeys[2] # type: ignore
assert project.tree[C.hCharRoot].itemStatus == statusKeys[1] # type: ignore
assert project.tree[C.hWorldRoot].itemStatus == statusKeys[3] # type: ignore
newList = [
{"key": statusKeys[0], "name": "New", "cols": (1, 1, 1)},
@@ -380,36 +375,36 @@ def testCoreProject_StatusImport(mockGUI, fncPath, mockRnd):
{"key": statusKeys[3], "name": "Edited", "cols": (4, 4, 4)}, # Renamed
{"key": None, "name": "Finished", "cols": (5, 5, 5)}, # New, reused name
]
assert theProject.setStatusColours(None, None) is False
assert theProject.setStatusColours([], []) is False
assert theProject.setStatusColours(newList, []) is True
assert project.setStatusColours(None, None) is False # type: ignore
assert project.setStatusColours([], []) is False
assert project.setStatusColours(newList, []) is True
assert theProject.data.itemStatus.name(statusKeys[0]) == "New"
assert theProject.data.itemStatus.name(statusKeys[1]) == "Draft"
assert theProject.data.itemStatus.name(statusKeys[2]) == "Note"
assert theProject.data.itemStatus.name(statusKeys[3]) == "Edited"
assert theProject.data.itemStatus.cols(statusKeys[0]) == (1, 1, 1)
assert theProject.data.itemStatus.cols(statusKeys[1]) == (2, 2, 2)
assert theProject.data.itemStatus.cols(statusKeys[2]) == (3, 3, 3)
assert theProject.data.itemStatus.cols(statusKeys[3]) == (4, 4, 4)
assert project.data.itemStatus.name(statusKeys[0]) == "New"
assert project.data.itemStatus.name(statusKeys[1]) == "Draft"
assert project.data.itemStatus.name(statusKeys[2]) == "Note"
assert project.data.itemStatus.name(statusKeys[3]) == "Edited"
assert project.data.itemStatus.cols(statusKeys[0]) == (1, 1, 1)
assert project.data.itemStatus.cols(statusKeys[1]) == (2, 2, 2)
assert project.data.itemStatus.cols(statusKeys[2]) == (3, 3, 3)
assert project.data.itemStatus.cols(statusKeys[3]) == (4, 4, 4)
# Check the new entry
lastKey = theProject.data.itemStatus.check("s000010")
lastKey = project.data.itemStatus.check("s000010")
assert lastKey == "s000010"
assert theProject.data.itemStatus.name(lastKey) == "Finished"
assert theProject.data.itemStatus.cols(lastKey) == (5, 5, 5)
assert project.data.itemStatus.name(lastKey) == "Finished"
assert project.data.itemStatus.cols(lastKey) == (5, 5, 5)
# Delete last entry
assert theProject.setStatusColours([], [lastKey]) is True
assert theProject.data.itemStatus.name(lastKey) == "New"
assert project.setStatusColours([], [lastKey]) is True
assert project.data.itemStatus.name(lastKey) == "New"
# Change Importance
# =================
fHandle = theProject.newFile("Jane Doe", C.hCharRoot)
theProject.tree[fHandle].setImport(importKeys[3])
fHandle = project.newFile("Jane Doe", C.hCharRoot)
project.tree[fHandle].setImport(importKeys[3]) # type: ignore
assert theProject.tree[fHandle].itemImport == importKeys[3]
assert project.tree[fHandle].itemImport == importKeys[3] # type: ignore
newList = [
{"key": importKeys[0], "name": "New", "cols": (1, 1, 1)},
{"key": importKeys[1], "name": "Minor", "cols": (2, 2, 2)},
@@ -417,44 +412,44 @@ def testCoreProject_StatusImport(mockGUI, fncPath, mockRnd):
{"key": importKeys[3], "name": "Min", "cols": (4, 4, 4)},
{"key": None, "name": "Max", "cols": (5, 5, 5)},
]
assert theProject.setImportColours(None, None) is False
assert theProject.setImportColours([], []) is False
assert theProject.setImportColours(newList, []) is True
assert project.setImportColours(None, None) is False # type: ignore
assert project.setImportColours([], []) is False
assert project.setImportColours(newList, []) is True
assert theProject.data.itemImport.name(importKeys[0]) == "New"
assert theProject.data.itemImport.name(importKeys[1]) == "Minor"
assert theProject.data.itemImport.name(importKeys[2]) == "Major"
assert theProject.data.itemImport.name(importKeys[3]) == "Min"
assert theProject.data.itemImport.cols(importKeys[0]) == (1, 1, 1)
assert theProject.data.itemImport.cols(importKeys[1]) == (2, 2, 2)
assert theProject.data.itemImport.cols(importKeys[2]) == (3, 3, 3)
assert theProject.data.itemImport.cols(importKeys[3]) == (4, 4, 4)
assert project.data.itemImport.name(importKeys[0]) == "New"
assert project.data.itemImport.name(importKeys[1]) == "Minor"
assert project.data.itemImport.name(importKeys[2]) == "Major"
assert project.data.itemImport.name(importKeys[3]) == "Min"
assert project.data.itemImport.cols(importKeys[0]) == (1, 1, 1)
assert project.data.itemImport.cols(importKeys[1]) == (2, 2, 2)
assert project.data.itemImport.cols(importKeys[2]) == (3, 3, 3)
assert project.data.itemImport.cols(importKeys[3]) == (4, 4, 4)
# Check the new entry
lastKey = theProject.data.itemImport.check("i000012")
lastKey = project.data.itemImport.check("i000012")
assert lastKey == "i000012"
assert theProject.data.itemImport.name(lastKey) == "Max"
assert theProject.data.itemImport.cols(lastKey) == (5, 5, 5)
assert project.data.itemImport.name(lastKey) == "Max"
assert project.data.itemImport.cols(lastKey) == (5, 5, 5)
# Delete last entry
assert theProject.setImportColours([], [lastKey]) is True
assert theProject.data.itemImport.name(lastKey) == "New"
assert project.setImportColours([], [lastKey]) is True
assert project.data.itemImport.name(lastKey) == "New"
# Delete Status/Import
# ====================
theProject.data.itemStatus.resetCounts()
for key in list(theProject.data.itemStatus.keys()):
assert theProject.data.itemStatus.remove(key) is True
project.data.itemStatus.resetCounts()
for key in list(project.data.itemStatus.keys()):
assert project.data.itemStatus.remove(key) is True
theProject.data.itemImport.resetCounts()
for key in list(theProject.data.itemImport.keys()):
assert theProject.data.itemImport.remove(key) is True
project.data.itemImport.resetCounts()
for key in list(project.data.itemImport.keys()):
assert project.data.itemImport.remove(key) is True
assert len(theProject.data.itemStatus) == 0
assert len(theProject.data.itemImport) == 0
assert theProject.saveProject() is True
theProject.closeProject()
assert len(project.data.itemStatus) == 0
assert len(project.data.itemImport) == 0
assert project.saveProject() is True
project.closeProject()
# END Test testCoreProject_StatusImport
@@ -462,96 +457,96 @@ def testCoreProject_StatusImport(mockGUI, fncPath, mockRnd):
@pytest.mark.core
def testCoreProject_Methods(monkeypatch, mockGUI, fncPath, mockRnd):
"""Test other project class methods and functions."""
theProject = NWProject()
buildTestProject(theProject, fncPath)
project = NWProject()
buildTestProject(project, fncPath)
# Project Name
theProject.data.setName(" A Name ")
assert theProject.data.name == "A Name"
project.data.setName(" A Name ")
assert project.data.name == "A Name"
# Project Title
theProject.data.setTitle(" A Title ")
assert theProject.data.title == "A Title"
project.data.setTitle(" A Title ")
assert project.data.title == "A Title"
# Project Author
theProject.data.setAuthor(" Jane\tDoe ")
assert theProject.data.author == "Jane Doe"
project.data.setAuthor(" Jane\tDoe ")
assert project.data.author == "Jane Doe"
# Edit Time
theProject.data.setEditTime(1234)
theProject._session._start = 1600000000
project.data.setEditTime(1234)
project._session._start = 1600000000
with monkeypatch.context() as mp:
mp.setattr("novelwriter.core.project.time", lambda: 1600005600)
assert theProject.currentEditTime == 6834
assert project.currentEditTime == 6834
# Trash folder
# Should create on first call, and just returned on later calls
hTrash = "0000000000010"
assert theProject.tree[hTrash] is None
assert theProject.trashFolder() == hTrash
assert theProject.trashFolder() == hTrash
assert project.tree[hTrash] is None
assert project.trashFolder() == hTrash
assert project.trashFolder() == hTrash
# Spell check
theProject.setProjectChanged(False)
theProject.data.setSpellCheck(True)
theProject.data.setSpellCheck(False)
assert theProject.projChanged is True
assert theProject.projOpened > 0
project.setProjectChanged(False)
project.data.setSpellCheck(True)
project.data.setSpellCheck(False)
assert project.projChanged is True
assert project.projOpened > 0
# Spell language
theProject.setProjectChanged(False)
assert theProject.data.spellLang is None
theProject.data.setSpellLang(None)
assert theProject.data.spellLang is None
theProject.data.setSpellLang("None") # Should be interpreted as None
assert theProject.data.spellLang is None
theProject.data.setSpellLang("en_GB")
assert theProject.data.spellLang == "en_GB"
assert theProject.projChanged is True
project.setProjectChanged(False)
assert project.data.spellLang is None
project.data.setSpellLang(None)
assert project.data.spellLang is None
project.data.setSpellLang("None") # Should be interpreted as None
assert project.data.spellLang is None
project.data.setSpellLang("en_GB")
assert project.data.spellLang == "en_GB"
assert project.projChanged is True
# Project Language
theProject.setProjectChanged(False)
theProject.data.setLanguage("en")
theProject.setProjectLang(None)
assert theProject.data.language is None
theProject.setProjectLang("en_GB")
assert theProject.data.language == "en_GB"
project.setProjectChanged(False)
project.data.setLanguage("en")
project.setProjectLang(None)
assert project.data.language is None
project.setProjectLang("en_GB")
assert project.data.language == "en_GB"
# Language Lookup
assert theProject.localLookup(1) == "One"
assert theProject.localLookup(10) == "Ten"
assert project.localLookup(1) == "One"
assert project.localLookup(10) == "Ten"
# Set invalid language
theProject.data.setLanguage("foo")
theProject._loadProjectLocalisation()
assert theProject.localLookup(1) == "One"
assert theProject.localLookup(10) == "Ten"
project.data.setLanguage("foo")
project._loadProjectLocalisation()
assert project.localLookup(1) == "One"
assert project.localLookup(10) == "Ten"
# Block reading language data
theProject.data.setLanguage("en")
project.data.setLanguage("en")
with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError)
theProject._loadProjectLocalisation()
assert theProject.localLookup(1) == "One"
assert theProject.localLookup(10) == "Ten"
project._loadProjectLocalisation()
assert project.localLookup(1) == "One"
assert project.localLookup(10) == "Ten"
# Last edited
theProject.setProjectChanged(False)
theProject._data.setLastHandle("0123456789abc", "editor")
assert theProject._data.getLastHandle("editor") == "0123456789abc"
assert theProject.projChanged
project.setProjectChanged(False)
project._data.setLastHandle("0123456789abc", "editor")
assert project._data.getLastHandle("editor") == "0123456789abc"
assert project.projChanged
# Last viewed
theProject.setProjectChanged(False)
theProject._data.setLastHandle("0123456789abc", "viewer")
assert theProject._data.getLastHandle("viewer") == "0123456789abc"
assert theProject.projChanged
project.setProjectChanged(False)
project._data.setLastHandle("0123456789abc", "viewer")
assert project._data.getLastHandle("viewer") == "0123456789abc"
assert project.projChanged
# Autoreplace
theProject.setProjectChanged(False)
theProject.data.setAutoReplace({"A": "B", "C": "D"})
assert theProject.data.autoReplace == {"A": "B", "C": "D"}
assert theProject.projChanged
# Auto Replace
project.setProjectChanged(False)
project.data.setAutoReplace({"A": "B", "C": "D"})
assert project.data.autoReplace == {"A": "B", "C": "D"}
assert project.projChanged
# Change project tree order
oldOrder = [
@@ -564,11 +559,11 @@ def testCoreProject_Methods(monkeypatch, mockGUI, fncPath, mockRnd):
"0000000000008", "0000000000009", "000000000000a",
"000000000000e", "000000000000f",
]
assert theProject.tree.handles() == oldOrder
theProject.setTreeOrder(newOrder)
assert theProject.tree.handles() == newOrder
theProject.setTreeOrder(oldOrder)
assert theProject.tree.handles() == oldOrder
assert project.tree.handles() == oldOrder
project.setTreeOrder(newOrder)
assert project.tree.handles() == newOrder
project.setTreeOrder(oldOrder)
assert project.tree.handles() == oldOrder
# END Test testCoreProject_Methods
@@ -580,38 +575,38 @@ def testCoreProject_Backup(monkeypatch, mockGUI, fncPath, tstPaths):
backup file and checks that the project XML file is identical to
the original file.
"""
theProject = NWProject()
project = NWProject()
# No Project
assert theProject.backupProject(doNotify=False) is False
assert project.backupProject(doNotify=False) is False
buildTestProject(theProject, fncPath)
buildTestProject(project, fncPath)
# Invalid Settings
# ================
# Missing project name
CONFIG._backupPath = tstPaths.tmpDir
theProject.data.setName("")
assert theProject.backupProject(doNotify=False) is False
project.data.setName("")
assert project.backupProject(doNotify=False) is False
# Valid Settings
# ==============
CONFIG._backupPath = tstPaths.tmpDir
theProject.data.setName("Test Minimal")
project.data.setName("Test Minimal")
# Can't make folder
with monkeypatch.context() as mp:
mp.setattr("pathlib.Path.mkdir", causeOSError)
assert theProject.backupProject(doNotify=False) is False
assert project.backupProject(doNotify=False) is False
# Can't write archive
with monkeypatch.context() as mp:
mp.setattr("zipfile.ZipFile.write", causeOSError)
assert theProject.backupProject(doNotify=False) is False
assert project.backupProject(doNotify=False) is False
# Test correct settings
assert theProject.backupProject(doNotify=True) is True
assert project.backupProject(doNotify=True) is True
theFiles = sorted((tstPaths.tmpDir / "Test Minimal").iterdir())
assert len(theFiles) in (1, 2) # Sometimes 2 due to clock tick