Fix tests for core classes

This commit is contained in:
Veronica Berglyd Olsen
2022-11-08 19:48:06 +01:00
parent b024c0996d
commit ee79d3d6d6
9 changed files with 163 additions and 124 deletions
+2 -2
View File
@@ -138,7 +138,7 @@ class NWDocument:
contentPath = self.theProject.storage.contentPath
if not isinstance(contentPath, Path):
logger.error("No content path set")
return None
return False
docFile = self._docHandle+".nwd"
logger.debug("Saving document: %s", docFile)
@@ -195,7 +195,7 @@ class NWDocument:
contentPath = self.theProject.storage.contentPath
if not isinstance(contentPath, Path):
logger.error("No content path set")
return None
return False
docPath = contentPath / f"{self._docHandle}.nwd"
docTemp = docPath.with_suffix(".tmp")
-2
View File
@@ -820,8 +820,6 @@ class ItemIndex:
elif tItem.itemRoot == rootHandle:
for sTitle in self._items[tHandle].headings():
yield tHandle, sTitle, self._items[tHandle][sTitle]
else:
continue
return
+12 -18
View File
@@ -25,7 +25,6 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
from __future__ import annotations
import os
import json
import logging
import novelwriter
@@ -82,8 +81,7 @@ class NWProject(QObject):
self.lockedBy = None # Data on which computer has the project open
# Class Settings
self.projDict = None # The spell check dictionary
self.projFiles = [] # A list of all files in the content folder on load
self.projFiles = [] # A list of all files in the content folder on load
# Internal Mapping
self.tr = partial(QCoreApplication.translate, "NWProject")
@@ -248,7 +246,6 @@ class NWProject(QObject):
self._data = NWProjectData(self)
# Project Settings
self.projDict = None
self.projFiles = []
return
@@ -265,8 +262,6 @@ class NWProject(QObject):
logger.info("Opening project: %s", projPath)
self.projDict = str(self._storage.getMetaFile(nwFiles.PROJ_DICT))
# Project Lock
# ============
@@ -367,11 +362,12 @@ class NWProject(QObject):
# Check the project tree consistency
for tItem in self._tree:
tHandle = tItem.itemHandle
logger.debug("Checking item '%s'", tHandle)
if not self._tree.updateItemData(tHandle):
logger.error("There was a problem item '%s', and it has been removed", tHandle)
del self._tree[tHandle] # The file will be re-added as orphaned
if tItem:
tHandle = tItem.itemHandle
logger.debug("Checking item '%s'", tHandle)
if not self._tree.updateItemData(tHandle):
logger.error("There was a problem the item, and it has been removed")
del self._tree[tHandle] # The file will be re-added as orphaned
self._scanProjectFolder()
self._index.loadIndex()
@@ -694,20 +690,18 @@ class NWProject(QObject):
def _loadProjectLocalisation(self):
"""Load the language data for the current project language.
"""
if self._data.language is None:
if self._data.language is None or self.mainConf.nwLangPath is None:
self._langData = {}
return False
langFile = os.path.join(
self.mainConf.nwLangPath, "project_%s.json" % self._data.language
)
if not os.path.isfile(langFile):
langFile = os.path.join(self.mainConf.nwLangPath, "project_en_GB.json")
langFile = Path(self.mainConf.nwLangPath) / f"project_{self._data.language}.json"
if not langFile.is_file():
langFile = Path(self.mainConf.nwLangPath) / "project_en_GB.json"
try:
with open(langFile, mode="r", encoding="utf-8") as inFile:
self._langData = json.load(inFile)
logger.debug("Loaded project language file: %s", os.path.basename(langFile))
logger.debug("Loaded project language file: %s", langFile.name)
except Exception:
logger.error("Failed to project language file")
+3 -3
View File
@@ -23,10 +23,10 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
import os
import logging
from collections import namedtuple
from pathlib import Path
from novelwriter.error import logException
@@ -173,10 +173,10 @@ class NWSpellEnchant:
self._projDict = set()
self._projectDict = projectDict
if projectDict is None:
if not isinstance(projectDict, Path):
return False
if not os.path.isfile(projectDict):
if not projectDict.exists():
return False
try:
+3 -2
View File
@@ -53,7 +53,7 @@ from PyQt5.QtWidgets import (
from novelwriter.core import NWSpellEnchant, countWords
from novelwriter.enum import nwAlert, nwDocAction, nwDocInsert, nwDocMode
from novelwriter.common import transferCase
from novelwriter.constants import nwConst, nwKeyWords, nwUnicode
from novelwriter.constants import nwConst, nwFiles, nwKeyWords, nwUnicode
from novelwriter.gui.dochighlight import GuiDocHighlighter
logger = logging.getLogger(__name__)
@@ -689,7 +689,8 @@ class GuiDocEditor(QTextEdit):
else:
theLang = self.theProject.data.spellLang
self.spEnchant.setLanguage(theLang, self.theProject.projDict)
projDict = self.theProject.storage.getMetaFile(nwFiles.PROJ_DICT)
self.spEnchant.setLanguage(theLang, projDict)
_, theProvider = self.spEnchant.describeDict()
self.spellDictionaryChanged.emit(str(theLang), str(theProvider))
+30 -13
View File
@@ -19,7 +19,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
import os
import pytest
from mock import causeOSError
@@ -31,12 +30,12 @@ from novelwriter.core.document import NWDocument
@pytest.mark.core
def testCoreDocument_LoadSave(monkeypatch, mockGUI, fncDir, mockRnd):
def testCoreDocument_LoadSave(monkeypatch, mockGUI, fncPath, mockRnd):
"""Test loading and saving a document with the NWDocument class.
"""
theProject = NWProject(mockGUI)
mockRnd.reset()
buildTestProject(theProject, fncDir)
buildTestProject(theProject, fncPath)
# Read Document
# =============
@@ -51,6 +50,12 @@ def testCoreDocument_LoadSave(monkeypatch, mockGUI, fncDir, mockRnd):
assert theDoc.readDocument() is None
assert theDoc._currHash is None
# No content path
with monkeypatch.context() as mp:
mp.setattr("novelwriter.core.storage.NWStorage.contentPath", property(lambda *a: None))
theDoc = NWDocument(theProject, C.hSceneDoc)
assert theDoc.readDocument() is None
# Cause open() to fail while loading
with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError)
@@ -72,17 +77,23 @@ def testCoreDocument_LoadSave(monkeypatch, mockGUI, fncDir, mockRnd):
# Write Document
# ==============
# Set handle and save again
# No content path
with monkeypatch.context() as mp:
mp.setattr("novelwriter.core.storage.NWStorage.contentPath", property(lambda *a: None))
theDoc = NWDocument(theProject, xHandle)
assert theDoc.writeDocument("") is False
# Set handle and save
theText = "### Test File\n\nText ...\n\n"
theDoc = NWDocument(theProject, xHandle)
assert theDoc.readDocument(xHandle) == ""
assert theDoc.writeDocument(theText) is True
# Save again to ensure temp file and previous file is handled
assert theDoc.writeDocument(theText)
assert theDoc.writeDocument(theText) is True
# Check file content
docPath = os.path.join(fncDir, "content", xHandle+".nwd")
docPath = fncPath / "content" / f"{xHandle}.nwd"
assert readFile(docPath) == (
"%%~name: New File\n"
f"%%~path: {C.hNovelRoot}/{xHandle}\n"
@@ -128,10 +139,16 @@ def testCoreDocument_LoadSave(monkeypatch, mockGUI, fncDir, mockRnd):
# Delete Document
# ===============
# Delete the last document
# Delete a non-existing document
theDoc = NWDocument(theProject, "stuff")
assert theDoc.deleteDocument() is False
assert os.path.isfile(docPath)
assert docPath.exists()
# No content path
with monkeypatch.context() as mp:
mp.setattr("novelwriter.core.storage.NWStorage.contentPath", property(lambda *a: None))
theDoc = NWDocument(theProject, xHandle)
assert theDoc.deleteDocument() is False
# Cause the delete to fail
with monkeypatch.context() as mp:
@@ -143,26 +160,26 @@ def testCoreDocument_LoadSave(monkeypatch, mockGUI, fncDir, mockRnd):
# Make the delete pass
theDoc = NWDocument(theProject, xHandle)
assert theDoc.deleteDocument() is True
assert not os.path.isfile(docPath)
assert not docPath.exists()
# END Test testCoreDocument_Load
@pytest.mark.core
def testCoreDocument_Methods(mockGUI, fncDir, mockRnd):
def testCoreDocument_Methods(mockGUI, fncPath, mockRnd):
"""Test other methods of the NWDocument class.
"""
theProject = NWProject(mockGUI)
mockRnd.reset()
buildTestProject(theProject, fncDir)
buildTestProject(theProject, fncPath)
theDoc = NWDocument(theProject, C.hSceneDoc)
docPath = os.path.join(fncDir, "content", C.hSceneDoc+".nwd")
docPath = fncPath / "content" / f"{C.hSceneDoc}.nwd"
assert theDoc.readDocument() == "### New Scene\n\n"
# Check location
assert theDoc.getFileLocation() == docPath
assert theDoc.getFileLocation() == str(docPath)
# Check the item
assert theDoc.getCurrentItem() is not None
+15 -5
View File
@@ -19,11 +19,11 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
import os
import json
import pytest
from shutil import copyfile
from pathlib import Path
from mock import causeException
from tools import C, buildTestProject, cmpFiles, writeFile
@@ -35,13 +35,13 @@ from novelwriter.core.project import NWProject
@pytest.mark.core
def testCoreIndex_LoadSave(monkeypatch, nwLipsum, mockGUI, outDir, refDir):
def testCoreIndex_LoadSave(monkeypatch, nwLipsum, mockGUI, tstPaths):
"""Test core functionality of scaning, saving, loading and checking
the index cache file.
"""
projFile = os.path.join(nwLipsum, "meta", nwFiles.INDEX_FILE)
testFile = os.path.join(outDir, "coreIndex_LoadSave_tagsIndex.json")
compFile = os.path.join(refDir, "coreIndex_LoadSave_tagsIndex.json")
projFile = Path(nwLipsum) / "meta" / nwFiles.INDEX_FILE
testFile = tstPaths.outDir / "coreIndex_LoadSave_tagsIndex.json"
compFile = tstPaths.refDir / "coreIndex_LoadSave_tagsIndex.json"
theProject = NWProject(mockGUI)
assert theProject.openProject(nwLipsum)
@@ -62,6 +62,11 @@ def testCoreIndex_LoadSave(monkeypatch, nwLipsum, mockGUI, outDir, refDir):
assert theIndex.reIndexHandle(None) is False
# No folder for saving
with monkeypatch.context() as mp:
mp.setattr("novelwriter.core.storage.NWStorage.getMetaFile", lambda *a: None)
assert theIndex.saveIndex() is False
# Make the save fail
with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeException)
@@ -86,6 +91,11 @@ def testCoreIndex_LoadSave(monkeypatch, nwLipsum, mockGUI, outDir, refDir):
assert theIndex._tagsIndex._tags == {}
assert theIndex._itemIndex._items == {}
# No folder for sloading
with monkeypatch.context() as mp:
mp.setattr("novelwriter.core.storage.NWStorage.getMetaFile", lambda *a: None)
assert theIndex.loadIndex() is False
# Make the load fail
with monkeypatch.context() as mp:
mp.setattr(json, "load", causeException)
+93 -73
View File
@@ -19,8 +19,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
import os
import shutil
import pytest
from time import time
@@ -42,16 +40,16 @@ from novelwriter.core.projectxml import ProjectXMLReader, ProjectXMLWriter, XMLR
@pytest.mark.core
def testCoreProject_NewRoot(fncDir, outDir, refDir, mockGUI, mockRnd):
def testCoreProject_NewRoot(fncPath, tstPaths, mockGUI, mockRnd):
"""Check that new root folders can be added to the project.
"""
projFile = os.path.join(fncDir, "nwProject.nwx")
testFile = os.path.join(outDir, "coreProject_NewRoot_nwProject.nwx")
compFile = os.path.join(refDir, "coreProject_NewRoot_nwProject.nwx")
projFile = fncPath / "nwProject.nwx"
testFile = tstPaths.outDir / "coreProject_NewRoot_nwProject.nwx"
compFile = tstPaths.refDir / "coreProject_NewRoot_nwProject.nwx"
theProject = NWProject(mockGUI)
mockRnd.reset()
buildTestProject(theProject, fncDir)
buildTestProject(theProject, fncPath)
assert theProject.newRoot(nwItemClass.NOVEL) == "0000000000010"
assert theProject.newRoot(nwItemClass.PLOT) == "0000000000011"
@@ -93,16 +91,16 @@ def testCoreProject_NewRoot(fncDir, outDir, refDir, mockGUI, mockRnd):
@pytest.mark.core
def testCoreProject_NewFileFolder(monkeypatch, fncDir, outDir, refDir, mockGUI, mockRnd):
def testCoreProject_NewFileFolder(monkeypatch, fncPath, tstPaths, mockGUI, mockRnd):
"""Check that new files can be added to the project.
"""
projFile = os.path.join(fncDir, "nwProject.nwx")
testFile = os.path.join(outDir, "coreProject_NewFileFolder_nwProject.nwx")
compFile = os.path.join(refDir, "coreProject_NewFileFolder_nwProject.nwx")
projFile = fncPath / "nwProject.nwx"
testFile = tstPaths.outDir / "coreProject_NewFileFolder_nwProject.nwx"
compFile = tstPaths.refDir / "coreProject_NewFileFolder_nwProject.nwx"
theProject = NWProject(mockGUI)
mockRnd.reset()
buildTestProject(theProject, fncDir)
buildTestProject(theProject, fncPath)
# Invalid call
assert theProject.newFolder("New Folder", "1234567890abc") is None
@@ -147,15 +145,15 @@ def testCoreProject_NewFileFolder(monkeypatch, fncDir, outDir, refDir, mockGUI,
assert "0000000000011" in theProject.tree
# Delete new files and folders
assert os.path.isfile(os.path.join(fncDir, "content", "0000000000012.nwd"))
assert os.path.isfile(os.path.join(fncDir, "content", "0000000000011.nwd"))
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 not os.path.isfile(os.path.join(fncDir, "content", "0000000000012.nwd"))
assert not os.path.isfile(os.path.join(fncDir, "content", "0000000000011.nwd"))
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
@@ -167,69 +165,66 @@ def testCoreProject_NewFileFolder(monkeypatch, fncDir, outDir, refDir, mockGUI,
@pytest.mark.core
def testCoreProject_Open(monkeypatch, caplog, mockGUI, fncDir, mockRnd):
def testCoreProject_Open(monkeypatch, caplog, mockGUI, fncPath, mockRnd):
"""Test opening a project.
"""
theProject = NWProject(mockGUI)
mockRnd.reset()
buildTestProject(theProject, fncDir)
buildTestProject(theProject, fncPath)
# Rename the project file to check handling
rName = os.path.join(fncDir, nwFiles.PROJ_FILE)
wName = os.path.join(fncDir, nwFiles.PROJ_FILE+"_sdfghj")
os.rename(rName, wName)
assert theProject.openProject(fncDir) is False
os.rename(wName, rName)
# Fail on folder structure check
# Initialising the storage class fails
with monkeypatch.context() as mp:
mp.setattr("os.mkdir", causeOSError)
shutil.rmtree(os.path.join(fncDir, "meta"))
assert theProject.openProject(fncDir) is False
mp.setattr("novelwriter.core.storage.NWStorage.openProjectInPlace", lambda *a, **k: False)
assert theProject.openProject(fncPath) is False
# Fail on lock file
assert theProject._storage.writeLockFile()
assert theProject.openProject(fncDir) is False
assert theProject.openProject(fncPath) is False
# 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(fncDir) is True
assert theProject.openProject(fncPath) is True
assert "Failed to check lock file" in caplog.text
assert theProject.closeProject()
assert theProject.closeProject()
# Force open with lockfile
assert theProject._storage.writeLockFile()
assert theProject.openProject(fncDir, overrideLock=True) is True
assert theProject.openProject(fncPath, overrideLock=True) is True
assert theProject.closeProject()
# 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
# 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(fncDir) is False
assert theProject.openProject(fncPath) is False
assert "Project file does not appear" in mockGUI.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(fncDir) is False
assert theProject.openProject(fncPath) is False
assert "Unknown or unsupported novelWriter project file" in mockGUI.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(fncDir) is False
assert theProject.openProject(fncPath) is False
assert "Failed to parse project xml" in mockGUI.lastAlert
# Won't convert legacy file
with monkeypatch.context() as mp:
mp.setattr(ProjectXMLReader, "state", property(lambda *a: XMLReadState.WAS_LEGACY))
mockGUI.askResponse = False
assert theProject.openProject(fncDir) is False
assert theProject.openProject(fncPath) is False
assert "The file format of your project is about to be" in mockGUI.lastQuestion[1]
mockGUI.askResponse = True
@@ -237,17 +232,22 @@ def testCoreProject_Open(monkeypatch, caplog, mockGUI, fncDir, mockRnd):
with monkeypatch.context() as mp:
mp.setattr(ProjectXMLReader, "hexVersion", property(lambda *a: 0x99999999))
mockGUI.askResponse = False
assert theProject.openProject(fncDir) is False
assert theProject.openProject(fncPath) is False
assert "This project was saved by a newer version" in mockGUI.lastQuestion[1]
mockGUI.askResponse = True
# 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 theProject.closeProject()
# END Test testCoreProject_Open
@pytest.mark.core
def testCoreProject_Save(monkeypatch, mockGUI, mockRnd, fncDir, refDir):
def testCoreProject_Save(monkeypatch, mockGUI, mockRnd, fncPath):
"""Test saving a project.
"""
theProject = NWProject(mockGUI)
@@ -256,7 +256,12 @@ def testCoreProject_Save(monkeypatch, mockGUI, mockRnd, fncDir, refDir):
assert theProject.saveProject() is False
mockRnd.reset()
buildTestProject(theProject, fncDir)
buildTestProject(theProject, 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
# Fail writing
with monkeypatch.context() as mp:
@@ -272,11 +277,11 @@ def testCoreProject_Save(monkeypatch, mockGUI, mockRnd, fncDir, refDir):
@pytest.mark.core
def testCoreProject_AccessItems(mockGUI, fncDir, mockRnd):
def testCoreProject_AccessItems(mockGUI, fncPath, mockRnd):
"""Test helper functions for the project folder.
"""
theProject = NWProject(mockGUI)
buildTestProject(theProject, fncDir)
buildTestProject(theProject, fncPath)
# Storage Objects
assert isinstance(theProject.index, NWIndex)
@@ -337,12 +342,12 @@ def testCoreProject_AccessItems(mockGUI, fncDir, mockRnd):
@pytest.mark.core
def testCoreProject_StatusImport(mockGUI, fncDir, mockRnd):
def testCoreProject_StatusImport(mockGUI, fncPath, mockRnd):
"""Test the status and importance flag handling.
"""
theProject = NWProject(mockGUI)
mockRnd.reset()
buildTestProject(theProject, fncDir)
buildTestProject(theProject, fncPath)
statusKeys = [C.sNew, C.sNote, C.sDraft, C.sFinished]
importKeys = [C.iNew, C.iMinor, C.iMajor, C.iMain]
@@ -447,11 +452,11 @@ def testCoreProject_StatusImport(mockGUI, fncDir, mockRnd):
@pytest.mark.core
def testCoreProject_Methods(monkeypatch, mockGUI, fncDir, mockRnd):
def testCoreProject_Methods(monkeypatch, mockGUI, fncPath, mockRnd):
"""Test other project class methods and functions.
"""
theProject = NWProject(mockGUI)
buildTestProject(theProject, fncDir)
buildTestProject(theProject, fncPath)
# Project Name
theProject.data.setName(" A Name ")
@@ -497,9 +502,12 @@ def testCoreProject_Methods(monkeypatch, mockGUI, fncDir, mockRnd):
# Spell check
theProject.setProjectChanged(False)
theProject._projAltered = False
theProject.data.setSpellCheck(True)
theProject.data.setSpellCheck(False)
assert theProject.projChanged
assert theProject.projChanged is True
assert theProject.projAltered is True
assert theProject.projOpened > 0
# Spell language
theProject.setProjectChanged(False)
@@ -510,7 +518,7 @@ def testCoreProject_Methods(monkeypatch, mockGUI, fncDir, mockRnd):
assert theProject.data.spellLang is None
theProject.data.setSpellLang("en_GB")
assert theProject.data.spellLang == "en_GB"
assert theProject.projChanged
assert theProject.projChanged is True
# Project Language
theProject.setProjectChanged(False)
@@ -524,6 +532,20 @@ def testCoreProject_Methods(monkeypatch, mockGUI, fncDir, mockRnd):
assert theProject.localLookup(1) == "One"
assert theProject.localLookup(10) == "Ten"
# Set invalid language
theProject.data.setLanguage("foo")
theProject._loadProjectLocalisation()
assert theProject.localLookup(1) == "One"
assert theProject.localLookup(10) == "Ten"
# Block reading language data
theProject.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"
# Last edited
theProject.setProjectChanged(False)
theProject._data.setLastHandle("0123456789abc", "editor")
@@ -624,7 +646,7 @@ def testCoreProject_OrphanedFiles(mockGUI, nwLipsum):
assert theProject.closeProject() is True
# First Item with Meta Data
orphPath = os.path.join(nwLipsum, "content", "636b6aa9b697b.nwd")
orphPath = Path(nwLipsum) / "content" / "636b6aa9b697b.nwd"
writeFile(orphPath, (
"%%~name:[Recovered] Mars\n"
"%%~path:5eaea4e8cdee8/636b6aa9b697b\n"
@@ -634,19 +656,19 @@ def testCoreProject_OrphanedFiles(mockGUI, nwLipsum):
))
# Second Item without Meta Data
orphPath = os.path.join(nwLipsum, "content", "736b6aa9b697b.nwd")
orphPath = Path(nwLipsum) / "content" / "736b6aa9b697b.nwd"
writeFile(orphPath, "\n")
# Invalid File Name
tstPath = os.path.join(nwLipsum, "content", "636b6aa9b697b.txt")
tstPath = Path(nwLipsum) / "content" / "636b6aa9b697b.txt"
writeFile(tstPath, "\n")
# Invalid File Name
tstPath = os.path.join(nwLipsum, "content", "636b6aa9b697bb.nwd")
tstPath = Path(nwLipsum) / "content" / "636b6aa9b697bb.nwd"
writeFile(tstPath, "\n")
# Invalid File Name
tstPath = os.path.join(nwLipsum, "content", "abcdefghijklm.nwd")
tstPath = Path(nwLipsum) / "content" / "abcdefghijklm.nwd"
writeFile(tstPath, "\n")
assert theProject.openProject(nwLipsum)
@@ -686,16 +708,21 @@ def testCoreProject_OrphanedFiles(mockGUI, nwLipsum):
@pytest.mark.core
def testCoreProject_Backup(monkeypatch, mockGUI, fncDir, tmpDir):
def testCoreProject_Backup(monkeypatch, mockGUI, fncPath, tmpPath):
"""Test the automated backup feature of the project class. The test
creates a backup of the Minimal test project, and then unzips the
backupd file and checks that the project XML file is identical to
the original file.
"""
theProject = NWProject(mockGUI)
buildTestProject(theProject, fncDir)
# Test faulty settings
# No Project
assert theProject.backupProject(doNotify=False) is False
buildTestProject(theProject, fncPath)
# Invalid Settings
# ================
# No project
mockGUI.hasProject = False
@@ -707,21 +734,14 @@ def testCoreProject_Backup(monkeypatch, mockGUI, fncDir, tmpDir):
assert theProject.backupProject(doNotify=False) is False
# Missing project name
theProject.mainConf.backupPath = tmpDir
theProject.mainConf.backupPath = str(tmpPath)
theProject.data.setName("")
assert theProject.backupProject(doNotify=False) is False
# Non-existent folder
theProject.mainConf.backupPath = os.path.join(tmpDir, "nonexistent")
# Valid Settings
# ==============
theProject.mainConf.backupPath = str(tmpPath)
theProject.data.setName("Test Minimal")
assert theProject.backupProject(doNotify=False) is False
# Subfolder of project (causes infinite loop in zipping)
theProject.mainConf.backupPath = os.path.join(fncDir, "subdir")
assert theProject.backupProject(doNotify=False) is False
# Set a valid folder
theProject.mainConf.backupPath = tmpDir
# Can't make folder
with monkeypatch.context() as mp:
@@ -736,21 +756,21 @@ def testCoreProject_Backup(monkeypatch, mockGUI, fncDir, tmpDir):
# Test correct settings
assert theProject.backupProject(doNotify=True) is True
theFiles = os.listdir(os.path.join(tmpDir, "Test Minimal"))
theFiles = list((tmpPath / "Test Minimal").iterdir())
assert len(theFiles) == 1
theZip = theFiles[0]
theZip = theFiles[0].name
assert theZip[:12] == "Backup from "
assert theZip[-4:] == ".zip"
# Extract the archive
with ZipFile(os.path.join(tmpDir, "Test Minimal", theZip), "r") as inZip:
inZip.extractall(os.path.join(tmpDir, "extract"))
with ZipFile(tmpPath / "Test Minimal" / theZip, mode="r") as inZip:
inZip.extractall(tmpPath / "extract")
# Check that the main project file was restored
assert cmpFiles(
os.path.join(fncDir, "nwProject.nwx"),
os.path.join(tmpDir, "extract", "nwProject.nwx")
fncPath / "nwProject.nwx",
tmpPath / "extract" / "nwProject.nwx"
)
# END Test testCoreProject_Backup
+5 -6
View File
@@ -19,7 +19,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
import os
import sys
import pytest
@@ -63,10 +62,10 @@ def testCoreSpell_FakeEnchant(monkeypatch):
@pytest.mark.core
def testCoreSpell_Enchant(monkeypatch, fncDir):
def testCoreSpell_Enchant(monkeypatch, fncPath):
"""Test the pyenchant spell checker.
"""
wList = os.path.join(fncDir, "wordlist.txt")
wList = fncPath / "wordlist.txt"
writeFile(wList, "a_word\nb_word\nc_word\n")
# Break the enchant package, and check error handling
@@ -134,13 +133,13 @@ def testCoreSpell_Enchant(monkeypatch, fncDir):
@pytest.mark.core
def testCoreSpell_SessionWords(fncDir):
def testCoreSpell_SessionWords(fncPath):
"""Test the handling of the custom word list in the spell checker.
New project sessions should not inherit the project word list from
other sessions, so this test checks that they don't bleed through.
"""
wList1 = os.path.join(fncDir, "wordlist1.txt")
wList2 = os.path.join(fncDir, "wordlist2.txt")
wList1 = fncPath / "wordlist1.txt"
wList2 = fncPath / "wordlist2.txt"
writeFile(wList1, "a_word\nb_word\nc_word\n")
writeFile(wList2, "d_word\ne_word\nf_word\n")