diff --git a/tests/conftest.py b/tests/conftest.py index be3c243f..c55eca06 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -118,6 +118,8 @@ def fncPath(): fncPath = _TMP_ROOT / "function" if fncPath.is_dir(): shutil.rmtree(fncPath) + elif fncPath.is_file(): + fncPath.unlink() fncPath.mkdir(exist_ok=True) return fncPath diff --git a/tests/test_core/test_core_options.py b/tests/test_core/test_core_options.py index 44ac84dc..60c826ca 100644 --- a/tests/test_core/test_core_options.py +++ b/tests/test_core/test_core_options.py @@ -34,8 +34,8 @@ from novelwriter.gui.noveltree import NovelTreeColumn @pytest.mark.core def testCoreOptions_LoadSave(monkeypatch, mockGUI, fncPath): """Test loading and saving from the OptionState class.""" - theProject = NWProject() - theOpts = OptionState(theProject) + project = NWProject() + options = OptionState(project) metaDir = fncPath / "meta" metaDir.mkdir() @@ -58,25 +58,26 @@ def testCoreOptions_LoadSave(monkeypatch, mockGUI, fncPath): }), encoding="utf-8") # Load and save with no path set - theProject.storage._runtimePath = None - assert theOpts.loadSettings() is False - assert theOpts.saveSettings() is False + project.storage._runtimePath = None + assert options.loadSettings() is False + assert options.saveSettings() is False # Set path - theProject.storage._runtimePath = fncPath - assert theProject.storage.getMetaFile(nwFiles.OPTS_FILE) == optFile + project.storage._runtimePath = fncPath + project.storage._ready = True + assert project.storage.getMetaFile(nwFiles.OPTS_FILE) == optFile # Cause open() to fail with monkeypatch.context() as mp: mp.setattr("builtins.open", causeOSError) - assert theOpts.loadSettings() is False - assert theOpts.saveSettings() is False + assert options.loadSettings() is False + assert options.saveSettings() is False # Load proper - assert theOpts.loadSettings() + assert options.loadSettings() # Check that unwanted items have been removed - assert theOpts._state == { + assert options._state == { "GuiProjectSettings": { "winWidth": 570, "winHeight": 375, @@ -87,11 +88,11 @@ def testCoreOptions_LoadSave(monkeypatch, mockGUI, fncPath): } # Save proper - assert theOpts.saveSettings() + assert options.saveSettings() # Load again to check we get the values back - assert theOpts.loadSettings() - assert theOpts._state == { + assert options.loadSettings() + assert options._state == { "GuiProjectSettings": { "winWidth": 570, "winHeight": 375, @@ -107,48 +108,48 @@ def testCoreOptions_LoadSave(monkeypatch, mockGUI, fncPath): @pytest.mark.core def testCoreOptions_SetGet(mockGUI): """Test setting and getting values from the OptionState class.""" - theProject = NWProject() - theOpts = OptionState(theProject) + project = NWProject() + options = OptionState(project) nwColHidden = NovelTreeColumn.HIDDEN # Set invalid values - assert theOpts.setValue("MockGroup", "mockItem", None) is False - assert theOpts.setValue("GuiProjectSettings", "mockItem", None) is False + assert options.setValue("MockGroup", "mockItem", None) is False + assert options.setValue("GuiProjectSettings", "mockItem", None) is False # Set valid value - assert theOpts.setValue("GuiProjectSettings", "winWidth", 100) is True + assert options.setValue("GuiProjectSettings", "winWidth", 100) is True # Set some values of different types - assert theOpts.setValue("GuiProjectDetails", "winWidth", 100) is True - assert theOpts.setValue("GuiProjectDetails", "winHeight", 12.34) is True - assert theOpts.setValue("GuiProjectDetails", "clearDouble", True) is True - assert theOpts.setValue("GuiNovelView", "lastCol", nwColHidden) is True + assert options.setValue("GuiProjectDetails", "winWidth", 100) is True + assert options.setValue("GuiProjectDetails", "winHeight", 12.34) is True + assert options.setValue("GuiProjectDetails", "clearDouble", True) is True + assert options.setValue("GuiNovelView", "lastCol", nwColHidden) is True # Generic get, doesn't check type - assert theOpts.getValue("GuiProjectDetails", "winWidth", None) == 100 - assert theOpts.getValue("GuiProjectDetails", "winHeight", None) == 12.34 - assert theOpts.getValue("GuiProjectDetails", "clearDouble", None) is True - assert theOpts.getValue("GuiProjectDetails", "mockItem", None) is None + assert options.getValue("GuiProjectDetails", "winWidth", None) == 100 + assert options.getValue("GuiProjectDetails", "winHeight", None) == 12.34 + assert options.getValue("GuiProjectDetails", "clearDouble", None) is True + assert options.getValue("GuiProjectDetails", "mockItem", None) is None # Get type-specific - assert theOpts.getString("GuiProjectDetails", "winWidth", None) is None - assert theOpts.getString("GuiProjectDetails", "mockItem", None) is None - assert theOpts.getInt("GuiProjectDetails", "winWidth", None) == 100 - assert theOpts.getInt("GuiProjectDetails", "textFont", None) is None - assert theOpts.getInt("GuiProjectDetails", "mockItem", None) is None - assert theOpts.getFloat("GuiProjectDetails", "winWidth", None) == 100.0 - assert theOpts.getFloat("GuiProjectDetails", "mockItem", None) is None - assert theOpts.getBool("GuiProjectDetails", "clearDouble", None) is True - assert theOpts.getBool("GuiProjectDetails", "mockItem", None) is None - assert theOpts.getEnum("GuiNovelView", "lastCol", NovelTreeColumn, nwColHidden) == nwColHidden + assert options.getString("GuiProjectDetails", "winWidth", None) is None # type: ignore + assert options.getString("GuiProjectDetails", "mockItem", None) is None # type: ignore + assert options.getInt("GuiProjectDetails", "winWidth", None) == 100 # type: ignore + assert options.getInt("GuiProjectDetails", "textFont", None) is None # type: ignore + assert options.getInt("GuiProjectDetails", "mockItem", None) is None # type: ignore + assert options.getFloat("GuiProjectDetails", "winWidth", None) == 100.0 # type: ignore + assert options.getFloat("GuiProjectDetails", "mockItem", None) is None # type: ignore + assert options.getBool("GuiProjectDetails", "clearDouble", None) is True # type: ignore + assert options.getBool("GuiProjectDetails", "mockItem", None) is None # type: ignore + assert options.getEnum("GuiNovelView", "lastCol", NovelTreeColumn, nwColHidden) == nwColHidden # Get from non-existent groups - assert theOpts.getValue("SomeGroup", "mockItem", None) is None - assert theOpts.getString("SomeGroup", "mockItem", None) is None - assert theOpts.getInt("SomeGroup", "mockItem", None) is None - assert theOpts.getFloat("SomeGroup", "mockItem", None) is None - assert theOpts.getBool("SomeGroup", "mockItem", None) is None - assert theOpts.getEnum("SomeGroup", "mockItem", NovelTreeColumn, None) is None + assert options.getValue("SomeGroup", "mockItem", None) is None + assert options.getString("SomeGroup", "mockItem", None) is None # type: ignore + assert options.getInt("SomeGroup", "mockItem", None) is None # type: ignore + assert options.getFloat("SomeGroup", "mockItem", None) is None # type: ignore + assert options.getBool("SomeGroup", "mockItem", None) is None # type: ignore + assert options.getEnum("SomeGroup", "mockItem", NovelTreeColumn, None) is None # type: ignore # END Test testCoreOptions_SetGet diff --git a/tests/test_core/test_core_project.py b/tests/test_core/test_core_project.py index 6cf3b04a..5f06a674 100644 --- a/tests/test_core/test_core_project.py +++ b/tests/test_core/test_core_project.py @@ -172,18 +172,18 @@ def testCoreProject_Open(monkeypatch, caplog, mockGUI, fncPath, mockRnd): # Initialising the storage class fails with monkeypatch.context() as mp: - mp.setattr("novelwriter.core.storage.NWStorage.openProjectInPlace", lambda *a, **k: False) + mp.setattr("novelwriter.core.storage.NWStorage.initProjectStorage", lambda *a, **k: False) assert theProject.openProject(fncPath) is False # Fail on lock file theProject.storage._lockFilePath = fncPath / nwFiles.PROJ_LOCK - assert theProject.storage.writeLockFile() is True + 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"]) + 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 @@ -191,7 +191,7 @@ def testCoreProject_Open(monkeypatch, caplog, mockGUI, fncPath, mockRnd): # Force open with lockfile theProject.storage._lockFilePath = fncPath / nwFiles.PROJ_LOCK - assert theProject.storage.writeLockFile() is True + assert theProject.storage._writeLockFile() is True assert theProject.openProject(fncPath, clearLock=True) is True theProject.closeProject() assert theProject.lockStatus is None diff --git a/tests/test_core/test_core_projectxml.py b/tests/test_core/test_core_projectxml.py index 6b43ca06..b16d60da 100644 --- a/tests/test_core/test_core_projectxml.py +++ b/tests/test_core/test_core_projectxml.py @@ -25,6 +25,7 @@ import pytest from shutil import copyfile from datetime import datetime +from novelwriter.constants import nwFiles from tools import cmpFiles, writeFile from mocked import causeOSError @@ -62,7 +63,7 @@ def testCoreProjectXML_ReadCurrent(monkeypatch, tstPaths, fncPath): xmlReader = ProjectXMLReader(xmlFile) assert xmlReader.state == XMLReadState.NO_ACTION - data = NWProjectData(MockProject()) + data = NWProjectData(MockProject()) # type: ignore content = [] # With no valid files, the read should fail @@ -132,7 +133,7 @@ def testCoreProjectXML_ReadCurrent(monkeypatch, tstPaths, fncPath): assert xmlReader.state == XMLReadState.WAS_LEGACY # Reset data objects - data = NWProjectData(MockProject()) + data = NWProjectData(MockProject()) # type: ignore content = [] # Parse a valid, complete file @@ -215,13 +216,13 @@ def testCoreProjectXML_ReadCurrent(monkeypatch, tstPaths, fncPath): mockProject = MockProject() mockProject.__setattr__("data", data) for entry in content: - item = NWItem(mockProject, "0000000000000") + item = NWItem(mockProject, "0000000000000") # type: ignore item.unpack(entry) packedContent.append(item.pack()) # Save the project again, which should produce an identical project xml timeStamp = int(datetime.fromisoformat(xmlReader.timeStamp).timestamp()) - xmlWriter = ProjectXMLWriter(fncPath) + xmlWriter = ProjectXMLWriter(fncPath / nwFiles.PROJ_FILE) # Fail saving with monkeypatch.context() as mp: @@ -254,7 +255,7 @@ def testCoreProjectXML_ReadLegacy10(tstPaths, fncPath, mockRnd): xmlReader = ProjectXMLReader(xmlFile) assert xmlReader.state == XMLReadState.NO_ACTION - data = NWProjectData(MockProject()) + data = NWProjectData(MockProject()) # type: ignore content = [] assert xmlReader.read(data, content) is True @@ -335,7 +336,7 @@ def testCoreProjectXML_ReadLegacy10(tstPaths, fncPath, mockRnd): mockProject.__setattr__("data", data) status = {} for entry in content: - item = NWItem(mockProject, "0000000000000") + item = NWItem(mockProject, "0000000000000") # type: ignore item.unpack(entry) status[item.itemHandle] = item.getImportStatus(incIcon=False)[0] packedContent.append(item.pack()) @@ -367,7 +368,7 @@ def testCoreProjectXML_ReadLegacy10(tstPaths, fncPath, mockRnd): # Save the project again, which should produce an identical project xml timeStamp = int(datetime.fromisoformat(xmlReader.timeStamp).timestamp()) - xmlWriter = ProjectXMLWriter(fncPath) + xmlWriter = ProjectXMLWriter(fncPath / nwFiles.PROJ_FILE) data.setUuid("d0f3fe10-c6e6-4310-8bfd-181eb4224eed") assert xmlWriter.write(data, packedContent, timeStamp, 1000) is True testFile = tstPaths.outDir / "projectXML_ReadLegacy10.nwx" @@ -389,7 +390,7 @@ def testCoreProjectXML_ReadLegacy11(tstPaths, fncPath, mockRnd): xmlReader = ProjectXMLReader(xmlFile) assert xmlReader.state == XMLReadState.NO_ACTION - data = NWProjectData(MockProject()) + data = NWProjectData(MockProject()) # type: ignore content = [] assert xmlReader.read(data, content) is True @@ -470,7 +471,7 @@ def testCoreProjectXML_ReadLegacy11(tstPaths, fncPath, mockRnd): mockProject.__setattr__("data", data) status = {} for entry in content: - item = NWItem(mockProject, "0000000000000") + item = NWItem(mockProject, "0000000000000") # type: ignore item.unpack(entry) status[item.itemHandle] = item.getImportStatus(incIcon=False)[0] packedContent.append(item.pack()) @@ -502,7 +503,7 @@ def testCoreProjectXML_ReadLegacy11(tstPaths, fncPath, mockRnd): # Save the project again, which should produce an identical project xml timeStamp = int(datetime.fromisoformat(xmlReader.timeStamp).timestamp()) - xmlWriter = ProjectXMLWriter(fncPath) + xmlWriter = ProjectXMLWriter(fncPath / nwFiles.PROJ_FILE) data.setUuid("d0f3fe10-c6e6-4310-8bfd-181eb4224eed") assert xmlWriter.write(data, packedContent, timeStamp, 1000) is True testFile = tstPaths.outDir / "projectXML_ReadLegacy11.nwx" @@ -524,7 +525,7 @@ def testCoreProjectXML_ReadLegacy12(tstPaths, fncPath, mockRnd): xmlReader = ProjectXMLReader(xmlFile) assert xmlReader.state == XMLReadState.NO_ACTION - data = NWProjectData(MockProject()) + data = NWProjectData(MockProject()) # type: ignore content = [] assert xmlReader.read(data, content) is True @@ -605,7 +606,7 @@ def testCoreProjectXML_ReadLegacy12(tstPaths, fncPath, mockRnd): mockProject.__setattr__("data", data) status = {} for entry in content: - item = NWItem(mockProject, "0000000000000") + item = NWItem(mockProject, "0000000000000") # type: ignore item.unpack(entry) status[item.itemHandle] = item.getImportStatus(incIcon=False)[0] packedContent.append(item.pack()) @@ -640,7 +641,7 @@ def testCoreProjectXML_ReadLegacy12(tstPaths, fncPath, mockRnd): # Save the project again, which should produce an identical project xml timeStamp = int(datetime.fromisoformat(xmlReader.timeStamp).timestamp()) - xmlWriter = ProjectXMLWriter(fncPath) + xmlWriter = ProjectXMLWriter(fncPath / nwFiles.PROJ_FILE) data.setUuid("d0f3fe10-c6e6-4310-8bfd-181eb4224eed") assert xmlWriter.write(data, packedContent, timeStamp, 1000) is True testFile = tstPaths.outDir / "projectXML_ReadLegacy12.nwx" @@ -662,7 +663,7 @@ def testCoreProjectXML_ReadLegacy13(tstPaths, fncPath, mockRnd): xmlReader = ProjectXMLReader(xmlFile) assert xmlReader.state == XMLReadState.NO_ACTION - data = NWProjectData(MockProject()) + data = NWProjectData(MockProject()) # type: ignore content = [] assert xmlReader.read(data, content) is True @@ -743,7 +744,7 @@ def testCoreProjectXML_ReadLegacy13(tstPaths, fncPath, mockRnd): mockProject.__setattr__("data", data) status = {} for entry in content: - item = NWItem(mockProject, "0000000000000") + item = NWItem(mockProject, "0000000000000") # type: ignore item.unpack(entry) status[item.itemHandle] = item.getImportStatus(incIcon=False)[0] packedContent.append(item.pack()) @@ -778,7 +779,7 @@ def testCoreProjectXML_ReadLegacy13(tstPaths, fncPath, mockRnd): # Save the project again, which should produce an identical project xml timeStamp = int(datetime.fromisoformat(xmlReader.timeStamp).timestamp()) - xmlWriter = ProjectXMLWriter(fncPath) + xmlWriter = ProjectXMLWriter(fncPath / nwFiles.PROJ_FILE) data.setUuid("d0f3fe10-c6e6-4310-8bfd-181eb4224eed") assert xmlWriter.write(data, packedContent, timeStamp, 1000) is True testFile = tstPaths.outDir / "projectXML_ReadLegacy13.nwx" @@ -800,7 +801,7 @@ def testCoreProjectXML_ReadLegacy14(tstPaths, fncPath, mockRnd): xmlReader = ProjectXMLReader(xmlFile) assert xmlReader.state == XMLReadState.NO_ACTION - data = NWProjectData(MockProject()) + data = NWProjectData(MockProject()) # type: ignore content = [] assert xmlReader.read(data, content) is True @@ -881,7 +882,7 @@ def testCoreProjectXML_ReadLegacy14(tstPaths, fncPath, mockRnd): mockProject.__setattr__("data", data) status = {} for entry in content: - item = NWItem(mockProject, "0000000000000") + item = NWItem(mockProject, "0000000000000") # type: ignore item.unpack(entry) status[item.itemHandle] = item.getImportStatus(incIcon=False)[0] packedContent.append(item.pack()) @@ -918,7 +919,7 @@ def testCoreProjectXML_ReadLegacy14(tstPaths, fncPath, mockRnd): # Save the project again, which should produce an identical project xml timeStamp = int(datetime.fromisoformat(xmlReader.timeStamp).timestamp()) - xmlWriter = ProjectXMLWriter(fncPath) + xmlWriter = ProjectXMLWriter(fncPath / nwFiles.PROJ_FILE) data.setUuid("d0f3fe10-c6e6-4310-8bfd-181eb4224eed") assert xmlWriter.write(data, packedContent, timeStamp, 1000) is True testFile = tstPaths.outDir / "projectXML_ReadLegacy14.nwx" diff --git a/tests/test_core/test_core_storage.py b/tests/test_core/test_core_storage.py index 50770539..8ff9d879 100644 --- a/tests/test_core/test_core_storage.py +++ b/tests/test_core/test_core_storage.py @@ -67,16 +67,16 @@ def testCoreStorage_OpenProjectInPlace(mockGUI, fncPath, mockRnd): assert storage.scanContent() == [] # Open project as a new project should fail - assert storage.openProjectInPlace(fncPath, newProject=True) is False + assert storage.initProjectStorage(fncPath, newProject=True) is False # Opening as a non-new project is fine - assert storage.openProjectInPlace(fncPath, newProject=False) is True + assert storage.initProjectStorage(fncPath, newProject=False) is True # Opening the project file is also fine - assert storage.openProjectInPlace(fncPath / nwFiles.PROJ_FILE, newProject=False) is True + assert storage.initProjectStorage(fncPath / nwFiles.PROJ_FILE, newProject=False) is True # Opening as a non-new project on a non-existing folder should fail - assert storage.openProjectInPlace(fncPath / "foobar", newProject=False) is False + assert storage.initProjectStorage(fncPath / "foobar", newProject=False) is False # Check settings assert storage.storagePath == fncPath @@ -123,36 +123,36 @@ def testCoreStorage_LockFile(monkeypatch, fncPath): assert storage.isOpen() is False # Project not open, so cannot read/write lock file - assert storage.readLockFile() == ["ERROR"] - assert storage.writeLockFile() is False - assert storage.clearLockFile() is False + assert storage._readLockFile() == ["ERROR"] + assert storage._writeLockFile() is False + assert storage._clearLockFile() is False # Set a path to work with lockFilePath = fncPath / nwFiles.PROJ_LOCK storage._lockFilePath = lockFilePath # Path is set, but there is no lockfile - assert storage.readLockFile() == [] + assert storage._readLockFile() == [] # Write lockfile fails with monkeypatch.context() as mp: mp.setattr("pathlib.Path.write_text", causeOSError) - assert storage.writeLockFile() is False + assert storage._writeLockFile() is False assert not lockFilePath.exists() # Successful write - assert storage.writeLockFile() is True + assert storage._writeLockFile() is True assert lockFilePath.exists() assert lockFilePath.read_text().split(";")[3] == "1000" # Read lockfile fails with monkeypatch.context() as mp: mp.setattr("pathlib.Path.read_text", causeOSError) - assert storage.readLockFile() == ["ERROR"] + assert storage._readLockFile() == ["ERROR"] assert lockFilePath.exists() # Successful read - assert storage.readLockFile() == [ + assert storage._readLockFile() == [ CONFIG.hostName, CONFIG.osType, CONFIG.kernelVer, @@ -161,16 +161,16 @@ def testCoreStorage_LockFile(monkeypatch, fncPath): # Write an invalid lockfile writeFile(lockFilePath, "a;b;c") - assert storage.readLockFile() == ["ERROR"] + assert storage._readLockFile() == ["ERROR"] # Fail to remove lockfile with monkeypatch.context() as mp: mp.setattr("pathlib.Path.unlink", causeOSError) - assert storage.clearLockFile() is False + assert storage._clearLockFile() is False assert lockFilePath.exists() # Successful remove - assert storage.clearLockFile() is True + assert storage._clearLockFile() is True assert not lockFilePath.exists() # END Test testCoreStorage_LockFile diff --git a/tests/tools.py b/tests/tools.py index 1eb4e11c..7a397386 100644 --- a/tests/tools.py +++ b/tests/tools.py @@ -171,7 +171,7 @@ def buildTestProject(obj, projPath): nwGUI = obj project = SHARED.project - project.storage.openProjectInPlace(projPath) + project.storage.createNewProject(projPath) project.setDefaultStatusImport() project.data.setUuid("d0f3fe10-c6e6-4310-8bfd-181eb4224eed")