diff --git a/novelwriter/common.py b/novelwriter/common.py
index 7eb1ec59..8b4c2da8 100644
--- a/novelwriter/common.py
+++ b/novelwriter/common.py
@@ -23,12 +23,12 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-import os
import json
import uuid
import hashlib
import logging
+from pathlib import Path
from datetime import datetime
from configparser import ConfigParser
@@ -36,7 +36,7 @@ from PyQt5.QtCore import QCoreApplication
from PyQt5.QtWidgets import qApp
from novelwriter.enum import nwItemClass, nwItemType, nwItemLayout
-from novelwriter.error import formatException, logException
+from novelwriter.error import logException
from novelwriter.constants import nwConst, nwUnicode
logger = logging.getLogger(__name__)
@@ -458,20 +458,16 @@ def jsonEncode(data, n=0, nmax=0):
def readTextFile(path):
"""Read the content of a text file in a robust manner.
"""
- if not os.path.isfile(path):
+ path = Path(path)
+ if not path.is_file():
return ""
-
- text = ""
try:
- with open(path, mode="r", encoding="utf-8") as inFile:
- text = inFile.read()
+ return path.read_text(encoding="utf-8")
except Exception:
logger.error("Could not read file: %s", path)
logException()
return ""
- return text
-
def makeFileNameSafe(value):
"""Returns a filename safe string of the value.
@@ -483,25 +479,6 @@ def makeFileNameSafe(value):
return clean
-def ensureFolder(path, parent=None, errLog=None):
- """Make sure a folder exists, and if it doesn't, create it.
- """
- try:
- if parent:
- path = os.path.join(parent, path)
- if not os.path.isdir(path):
- os.mkdir(path)
- except Exception as exc:
- logger.error("Could not create folder: %s", path)
- logException()
- if isinstance(errLog, list):
- errLog.append(f"Could not create folder: {path}")
- errLog.append(formatException(exc))
- return False
-
- return True
-
-
def sha256sum(path):
"""Make a shasum of a file using a buffer.
Based on: https://stackoverflow.com/a/44873382/5825851
diff --git a/novelwriter/config.py b/novelwriter/config.py
index 8c21dc99..454e54d1 100644
--- a/novelwriter/config.py
+++ b/novelwriter/config.py
@@ -23,7 +23,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-import os
import sys
import json
import logging
@@ -184,7 +183,7 @@ class Config:
self.searchMatchCap = False
# Backup Settings
- self.backupPath = ""
+ self._backupPath = None
self.backupOnClose = False
self.askBeforeBackup = True
@@ -296,6 +295,14 @@ class Config:
return self._lastPath
return Path.home().absolute()
+ def backupPath(self):
+ """Return the backup path.
+ """
+ if isinstance(self._backupPath, Path):
+ if self._backupPath.is_dir():
+ return self._backupPath
+ return None
+
def errorText(self):
"""Compile and return error messages from the initialisation of
the Config class, and clear the error buffer.
@@ -369,7 +376,7 @@ class Config:
lngFile = "%s_%s" % (lngBase, lngCode.replace("-", "_"))
if lngFile not in self._qtTrans:
if qTrans.load(lngFile, str(lngPath)):
- logger.debug("Loaded: %s", os.path.join(lngPath, lngFile))
+ logger.debug("Loaded: %s/%s", lngPath, lngFile)
nwApp.installTranslator(qTrans)
self._qtTrans[lngFile] = qTrans
@@ -489,9 +496,10 @@ class Config:
# Backup
cnfSec = "Backup"
- self.backupPath = theConf.rdStr(cnfSec, "backuppath", self.backupPath)
+ backupPath = theConf.rdStr(cnfSec, "backuppath", None)
self.backupOnClose = theConf.rdBool(cnfSec, "backuponclose", self.backupOnClose)
self.askBeforeBackup = theConf.rdBool(cnfSec, "askbeforebackup", self.askBeforeBackup)
+ self.setBackupPath(backupPath)
# State
cnfSec = "State"
@@ -599,7 +607,7 @@ class Config:
}
theConf["Backup"] = {
- "backuppath": str(self.backupPath),
+ "backuppath": str(self._backupPath or ""),
"backuponclose": str(self.backupOnClose),
"askbeforebackup": str(self.askBeforeBackup),
}
@@ -653,6 +661,14 @@ class Config:
logger.debug("Last path updated: %s" % self._lastPath)
return
+ def setBackupPath(self, backupPath):
+ """Set the current backup path.
+ """
+ self._backupPath = None
+ if isinstance(backupPath, (str, Path)):
+ self._backupPath = Path(backupPath)
+ return
+
def setWinSize(self, newWidth, newHeight):
"""Set the size of the main window, but only if the change is
larger than 5 pixels. The OS window manager will sometimes
diff --git a/novelwriter/core/project.py b/novelwriter/core/project.py
index ae4f7bab..7f01f632 100644
--- a/novelwriter/core/project.py
+++ b/novelwriter/core/project.py
@@ -456,7 +456,8 @@ class NWProject(QObject):
logger.info("Backing up project")
self.mainGui.setStatus(self.tr("Backing up project ..."))
- if not self.mainConf.backupPath:
+ backupPath = self.mainConf.backupPath()
+ if not isinstance(backupPath, Path):
self.mainGui.makeAlert(self.tr(
"Cannot backup project because no valid backup path is set. "
"Please set a valid backup location in Preferences."
@@ -471,7 +472,7 @@ class NWProject(QObject):
return False
cleanName = makeFileNameSafe(self._data.name)
- baseDir = Path(self.mainConf.backupPath) / cleanName
+ baseDir = backupPath / cleanName
try:
baseDir.mkdir(exist_ok=True)
except Exception as exc:
diff --git a/novelwriter/dialogs/preferences.py b/novelwriter/dialogs/preferences.py
index 72498421..81e62649 100644
--- a/novelwriter/dialogs/preferences.py
+++ b/novelwriter/dialogs/preferences.py
@@ -23,7 +23,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-import os
import logging
import novelwriter
@@ -384,7 +383,7 @@ class GuiPreferencesProjects(QWidget):
self.mainForm.addGroupLabel(self.tr("Project Backup"))
# Backup Path
- self.backupPath = self.mainConf.backupPath
+ self.backupPath = self.mainConf.backupPath()
self.backupGetPath = QPushButton(self.tr("Browse"))
self.backupGetPath.clicked.connect(self._backupFolder)
self.backupPathRow = self.mainForm.addRow(
@@ -451,7 +450,7 @@ class GuiPreferencesProjects(QWidget):
self.mainConf.autoSaveProj = self.autoSaveProj.value()
# Project Backup
- self.mainConf.backupPath = self.backupPath
+ self.mainConf.setBackupPath(self.backupPath)
self.mainConf.backupOnClose = self.backupOnClose.isChecked()
self.mainConf.askBeforeBackup = self.askBeforeBackup.isChecked()
@@ -470,12 +469,9 @@ class GuiPreferencesProjects(QWidget):
def _backupFolder(self):
"""Open a dialog to select the backup folder.
"""
- currDir = self.backupPath
- if not os.path.isdir(currDir):
- currDir = ""
-
+ currDir = self.backupPath or ""
newDir = QFileDialog.getExistingDirectory(
- self, self.tr("Backup Directory"), currDir, options=QFileDialog.ShowDirsOnly
+ self, self.tr("Backup Directory"), str(currDir), options=QFileDialog.ShowDirsOnly
)
if newDir:
self.backupPath = newDir
diff --git a/novelwriter/dialogs/projload.py b/novelwriter/dialogs/projload.py
index ecd2f9f4..e646a0b0 100644
--- a/novelwriter/dialogs/projload.py
+++ b/novelwriter/dialogs/projload.py
@@ -23,10 +23,10 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-import os
import logging
import novelwriter
+from pathlib import Path
from datetime import datetime
from PyQt5.QtGui import QKeySequence
@@ -190,8 +190,8 @@ class GuiProjectLoad(QDialog):
self, self.tr("Open Project"), "", filter=";;".join(extFilter)
)
if projFile:
- thePath = os.path.abspath(os.path.dirname(projFile))
- self.selPath.setText(thePath)
+ thePath = Path(projFile).absolute()
+ self.selPath.setText(str(thePath))
self.openPath = thePath
self.openState = self.OPEN_STATE
self.accept()
diff --git a/novelwriter/gui/mainmenu.py b/novelwriter/gui/mainmenu.py
index b4acd6f2..77eff2b1 100644
--- a/novelwriter/gui/mainmenu.py
+++ b/novelwriter/gui/mainmenu.py
@@ -826,7 +826,7 @@ class GuiMainMenu(QMenuBar):
# Tools > Backup
self.aBackupProject = QAction(self.tr("Backup Project"), self)
- self.aBackupProject.triggered.connect(lambda: self.theProject.backupProject(doNoify=True))
+ self.aBackupProject.triggered.connect(lambda: self.theProject.backupProject(True))
self.toolsMenu.addAction(self.aBackupProject)
# Tools > Export Project
diff --git a/novelwriter/guimain.py b/novelwriter/guimain.py
index 09df46fb..4acb2952 100644
--- a/novelwriter/guimain.py
+++ b/novelwriter/guimain.py
@@ -23,7 +23,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-import os
import logging
import novelwriter
@@ -362,7 +361,7 @@ class GuiMain(QMainWindow):
logger.error("No projData or projPath set")
return False
- if os.path.isfile(os.path.join(projPath, nwFiles.PROJ_FILE)):
+ if (Path(projPath) / nwFiles.PROJ_FILE).is_file():
self.makeAlert(self.tr(
"A project already exists in that location. "
"Please choose another folder."
@@ -414,7 +413,7 @@ class GuiMain(QMainWindow):
if not msgYes:
doBackup = False
if doBackup:
- self.theProject.backupProject(doNotify=False)
+ self.theProject.backupProject(False)
else:
saveOK = True
diff --git a/tests/conftest.py b/tests/conftest.py
index 696d416e..28034a18 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -19,7 +19,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-import os
import sys
import pytest
import shutil
@@ -50,25 +49,14 @@ def initQt(qtbot):
##
@pytest.fixture(scope="session")
-def tmpDir():
- """A temporary folder for the test session. This folder is
- presistent after the test so that the status of generated files can
- be checked. The folder is instead cleared before a new test session.
- """
- testDir = os.path.dirname(__file__)
- theDir = os.path.join(testDir, "temp")
- if os.path.isdir(theDir):
- shutil.rmtree(theDir)
- if not os.path.isdir(theDir):
- os.mkdir(theDir)
- return theDir
-
-
-@pytest.fixture(scope="session")
-def tmpPath(tmpDir):
+def tmpPath():
"""A temporary folder for the test session. Path version.
"""
- return Path(tmpDir)
+ theTemp = Path(__file__).parent / "temp"
+ if theTemp.exists():
+ shutil.rmtree(theTemp)
+ theTemp.mkdir(exist_ok=True)
+ return theTemp
@pytest.fixture(scope="session")
@@ -99,57 +87,15 @@ def fncPath(tmpPath):
return fncPath
-@pytest.fixture(scope="session")
-def refDir():
- """The folder where all the reference files are stored for verifying
- the results of tests.
- """
- testDir = os.path.dirname(__file__)
- theDir = os.path.join(testDir, "reference")
- return theDir
-
-
-@pytest.fixture(scope="session")
-def filesDir():
- """The folder where additional test files are stored.
- """
- testDir = os.path.dirname(__file__)
- theDir = os.path.join(testDir, "files")
- return theDir
-
-
-@pytest.fixture(scope="session")
-def outDir(tmpDir):
- """An output folder for test results
- """
- theDir = os.path.join(tmpDir, "results")
- if not os.path.isdir(theDir):
- os.mkdir(theDir)
- return theDir
-
-
@pytest.fixture(scope="function")
-def fncDir(tmpDir):
- """A temporary folder for a single test function.
- """
- fncDir = os.path.join(tmpDir, "function")
- if os.path.isdir(fncDir):
- shutil.rmtree(fncDir)
- if not os.path.isdir(fncDir):
- os.mkdir(fncDir)
- return fncDir
-
-
-@pytest.fixture(scope="function")
-def fncProj(fncDir):
+def projPath(fncPath):
"""A temporary folder for a single test function,
with a project folder.
"""
- prjDir = os.path.join(fncDir, "project")
- if os.path.isdir(prjDir):
+ prjDir = fncPath / "project"
+ if prjDir.exists():
shutil.rmtree(prjDir)
- if not os.path.isdir(prjDir):
- os.mkdir(prjDir)
+ prjDir.mkdir(exist_ok=True)
return prjDir
@@ -252,14 +198,36 @@ def mockRnd(monkeypatch):
##
@pytest.fixture(scope="function")
-def nwLipsum(tmpDir):
+def nwLipsum(tmpPath):
"""A medium sized novelWriter example project with a lot of Lorem
Ipsum text.
"""
- tstDir = os.path.dirname(__file__)
- srcDir = os.path.join(tstDir, "lipsum")
- dstDir = os.path.join(tmpDir, "lipsum")
- if os.path.isdir(dstDir):
+ tstDir = Path(__file__).parent
+ srcDir = tstDir / "lipsum"
+ dstDir = tmpPath / "lipsum"
+ if dstDir.exists():
+ shutil.rmtree(dstDir)
+
+ shutil.copytree(srcDir, dstDir)
+ cleanProject(dstDir)
+
+ yield str(dstDir)
+
+ if dstDir.exists():
+ shutil.rmtree(dstDir)
+
+ return
+
+
+@pytest.fixture(scope="function")
+def prjLipsum(tmpPath):
+ """A medium sized novelWriter example project with a lot of Lorem
+ Ipsum text.
+ """
+ tstDir = Path(__file__).parent
+ srcDir = tstDir / "lipsum"
+ dstDir = tmpPath / "lipsum"
+ if dstDir.exists():
shutil.rmtree(dstDir)
shutil.copytree(srcDir, dstDir)
@@ -267,7 +235,7 @@ def nwLipsum(tmpDir):
yield dstDir
- if os.path.isdir(dstDir):
+ if dstDir.exists():
shutil.rmtree(dstDir)
return
diff --git a/tests/test_base/test_base_common.py b/tests/test_base/test_base_common.py
index f6d60a1c..adabbfe7 100644
--- a/tests/test_base/test_base_common.py
+++ b/tests/test_base/test_base_common.py
@@ -19,10 +19,9 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-import hashlib
-import os
import time
import pytest
+import hashlib
from mock import causeOSError
from tools import writeFile
@@ -33,8 +32,8 @@ from novelwriter.common import (
checkUuid, isHandle, isTitleTag, isItemClass, isItemType, isItemLayout,
hexToInt, minmax, checkIntTuple, formatInt, formatTimeStamp, formatTime,
simplified, yesNo, splitVersionNumber, transferCase, fuzzyTime,
- numberToRoman, jsonEncode, readTextFile, makeFileNameSafe, ensureFolder,
- sha256sum, getGuiItem, NWConfigParser
+ numberToRoman, jsonEncode, readTextFile, makeFileNameSafe, sha256sum,
+ getGuiItem, NWConfigParser
)
@@ -591,18 +590,18 @@ def testBaseCommon_JsonEncode():
@pytest.mark.base
-def testBaseCommon_ReadTextFile(monkeypatch, fncDir, ipsumText):
+def testBaseCommon_ReadTextFile(monkeypatch, fncPath, ipsumText):
"""Test the readTextFile function.
"""
testText = "\n\n".join(ipsumText) + "\n"
- testFile = os.path.join(fncDir, "ipsum.txt")
+ testFile = fncPath / "ipsum.txt"
writeFile(testFile, testText)
- assert readTextFile(os.path.join(fncDir, "not_a_file.txt")) == ""
+ assert readTextFile(fncPath / "not_a_file.txt") == ""
assert readTextFile(testFile) == testText
with monkeypatch.context() as mp:
- mp.setattr("builtins.open", causeOSError)
+ mp.setattr("pathlib.Path.read_text", causeOSError)
assert readTextFile(testFile) == ""
# END Test testBaseCommon_ReadTextFile
@@ -621,33 +620,7 @@ def testBaseCommon_MakeFileNameSafe():
@pytest.mark.base
-def testBaseCommon_EnsureFolder(monkeypatch, fncDir):
- """Test the ensureFolder function.
- """
- newDir1 = os.path.join(fncDir, "newDir1")
- newDir2 = os.path.join(fncDir, "newDir2")
- newDir3 = os.path.join(fncDir, "newDir3")
-
- assert ensureFolder(None) is False
-
- assert ensureFolder(newDir1) is True
- assert os.path.isdir(newDir1)
-
- assert ensureFolder("newDir2", parent=fncDir) is True
- assert os.path.isdir(newDir2)
-
- with monkeypatch.context() as mp:
- mp.setattr("os.mkdir", causeOSError)
- errLog = []
- assert ensureFolder("newDir3", parent=fncDir, errLog=errLog) is False
- assert errLog[0] == f"Could not create folder: {newDir3}"
- assert not os.path.isdir(newDir3)
-
-# END Test testBaseCommon_EnsureFolder
-
-
-@pytest.mark.base
-def testBaseCommon_Sha256Sum(monkeypatch, fncDir, ipsumText):
+def testBaseCommon_Sha256Sum(monkeypatch, fncPath, ipsumText):
"""Test the sha256sum function.
"""
longText = 50*(" ".join(ipsumText) + " ")
@@ -656,9 +629,9 @@ def testBaseCommon_Sha256Sum(monkeypatch, fncDir, ipsumText):
assert len(longText) == 175650
- longFile = os.path.join(fncDir, "long_file.txt")
- shortFile = os.path.join(fncDir, "short_file.txt")
- noneFile = os.path.join(fncDir, "none_file.txt")
+ longFile = fncPath / "long_file.txt"
+ shortFile = fncPath / "short_file.txt"
+ noneFile = fncPath / "none_file.txt"
writeFile(longFile, longText)
writeFile(shortFile, shortText)
@@ -697,10 +670,10 @@ def testBaseCommon_GetGuiItem(nwGUI):
@pytest.mark.base
-def testBaseCommon_NWConfigParser(fncDir):
+def testBaseCommon_NWConfigParser(fncPath):
"""Test the NWConfigParser subclass.
"""
- tstConf = os.path.join(fncDir, "test.cfg")
+ tstConf = fncPath / "test.cfg"
writeFile(tstConf, (
"[main]\n"
"stropt = value\n"
diff --git a/tests/test_base/test_base_error.py b/tests/test_base/test_base_error.py
index d2707b29..9ba9b9b2 100644
--- a/tests/test_base/test_base_error.py
+++ b/tests/test_base/test_base_error.py
@@ -20,9 +20,6 @@ along with this program. If not, see .
"""
import pytest
-import novelwriter
-
-from PyQt5.QtWidgets import QMessageBox, qApp
from mock import causeException
@@ -30,18 +27,9 @@ from novelwriter.error import NWErrorMessage, exceptionHandler
@pytest.mark.base
-def testBaseError_Dialog(qtbot, monkeypatch, fncDir, tmpDir):
+def testBaseError_Dialog(qtbot, monkeypatch, nwGUI):
"""Test the error dialog.
"""
- # Block message box
- monkeypatch.setattr(QMessageBox, "warning", lambda *a: QMessageBox.Yes)
-
- qApp.closeAllWindows()
- nwGUI = novelwriter.main(["--testmode", "--config=%s" % fncDir, "--data=%s" % tmpDir])
- qtbot.addWidget(nwGUI)
- nwGUI.show()
- qtbot.wait(20)
-
nwErr = NWErrorMessage(nwGUI)
qtbot.addWidget(nwErr)
nwErr.show()
@@ -76,19 +64,11 @@ def testBaseError_Dialog(qtbot, monkeypatch, fncDir, tmpDir):
@pytest.mark.base
-def testBaseError_Handler(qtbot, monkeypatch, fncDir, tmpDir):
+def testBaseError_Handler(qtbot, monkeypatch, nwGUI):
"""Test the error handler. This test doesn'thave any asserts, but it
checks that the error handler handles potential exceptions. The test
will fail if excpetions are not handled.
"""
- monkeypatch.setattr(QMessageBox, "warning", lambda *a: QMessageBox.Yes)
-
- qApp.closeAllWindows()
- nwGUI = novelwriter.main(["--testmode", "--config=%s" % fncDir, "--data=%s" % tmpDir])
- qtbot.addWidget(nwGUI)
- nwGUI.show()
- qtbot.wait(20)
-
# Normal shutdown
with monkeypatch.context() as mp:
mp.setattr(NWErrorMessage, "exec_", lambda *a: None)
diff --git a/tests/test_base/test_base_init.py b/tests/test_base/test_base_init.py
index 4cebcb6a..2a41ea38 100644
--- a/tests/test_base/test_base_init.py
+++ b/tests/test_base/test_base_init.py
@@ -28,13 +28,13 @@ from mock import MockGuiMain
@pytest.mark.base
-def testBaseInit_Launch(caplog, monkeypatch, tmpDir):
+def testBaseInit_Launch(caplog, monkeypatch, tmpPath):
"""Check launching the main GUI.
"""
monkeypatch.setattr("novelwriter.guimain.GuiMain", MockGuiMain)
# TestMode Launch
- nwGUI = novelwriter.main(["--testmode", "--config=%s" % tmpDir, "--data=%s" % tmpDir])
+ nwGUI = novelwriter.main(["--testmode", f"--config={tmpPath}", f"--data={tmpPath}"])
assert isinstance(nwGUI, MockGuiMain)
# Darwin Launch
@@ -43,7 +43,7 @@ def testBaseInit_Launch(caplog, monkeypatch, tmpDir):
novelwriter.CONFIG.osDarwin = True
with monkeypatch.context() as mp:
mp.setitem(sys.modules, "Foundation", None)
- nwGUI = novelwriter.main(["--testmode", "--config=%s" % tmpDir, "--data=%s" % tmpDir])
+ nwGUI = novelwriter.main(["--testmode", f"--config={tmpPath}", f"--data={tmpPath}"])
assert isinstance(nwGUI, MockGuiMain)
assert "Failed" in caplog.text
@@ -55,7 +55,7 @@ def testBaseInit_Launch(caplog, monkeypatch, tmpDir):
novelwriter.CONFIG.osWindows = True
with monkeypatch.context() as mp:
mp.setitem(sys.modules, "ctypes", None)
- nwGUI = novelwriter.main(["--testmode", "--config=%s" % tmpDir, "--data=%s" % tmpDir])
+ nwGUI = novelwriter.main(["--testmode", f"--config={tmpPath}", f"--data={tmpPath}"])
assert isinstance(nwGUI, MockGuiMain)
if not sys.platform.startswith("darwin"):
# For some reason, the test doesn't work on macOS
@@ -71,19 +71,19 @@ def testBaseInit_Launch(caplog, monkeypatch, tmpDir):
monkeypatch.setattr("PyQt5.QtWidgets.QApplication.setOrganizationDomain", lambda *a: None)
monkeypatch.setattr("PyQt5.QtWidgets.QApplication.exec_", lambda *a: 0)
with pytest.raises(SystemExit) as ex:
- novelwriter.main(["--config=%s" % tmpDir, "--data=%s" % tmpDir])
+ novelwriter.main([f"--config={tmpPath}", f"--data={tmpPath}"])
assert ex.value.code == 0
# END Test testBaseInit_Launch
@pytest.mark.base
-def testBaseInit_Options(monkeypatch, tmpDir):
+def testBaseInit_Options(monkeypatch, tmpPath):
"""Test command line options for logging level.
"""
monkeypatch.setattr("novelwriter.guimain.GuiMain", MockGuiMain)
monkeypatch.setattr(sys, "argv", [
- "novelWriter.py", "--testmode", "--config=%s" % tmpDir, "--data=%s" % tmpDir
+ "novelWriter.py", "--testmode", f"--config={tmpPath}", f"--data={tmpPath}"
])
# Defaults w/None Args
@@ -93,20 +93,20 @@ def testBaseInit_Options(monkeypatch, tmpDir):
# Defaults
nwGUI = novelwriter.main(
- ["--testmode", "--config=%s" % tmpDir, "--data=%s" % tmpDir, "--style=Fusion"]
+ ["--testmode", f"--config={tmpPath}", f"--data={tmpPath}", "--style=Fusion"]
)
assert novelwriter.logger.getEffectiveLevel() == logging.WARNING
assert nwGUI.closeMain() == "closeMain"
# Log Levels
nwGUI = novelwriter.main(
- ["--testmode", "--info", "--config=%s" % tmpDir, "--data=%s" % tmpDir]
+ ["--testmode", "--info", f"--config={tmpPath}", f"--data={tmpPath}"]
)
assert novelwriter.logger.getEffectiveLevel() == logging.INFO
assert nwGUI.closeMain() == "closeMain"
nwGUI = novelwriter.main(
- ["--testmode", "--debug", "--config=%s" % tmpDir, "--data=%s" % tmpDir]
+ ["--testmode", "--debug", f"--config={tmpPath}", f"--data={tmpPath}"]
)
assert novelwriter.logger.getEffectiveLevel() == logging.DEBUG
assert nwGUI.closeMain() == "closeMain"
@@ -114,14 +114,14 @@ def testBaseInit_Options(monkeypatch, tmpDir):
# Help and Version
with pytest.raises(SystemExit) as ex:
nwGUI = novelwriter.main(
- ["--testmode", "--help", "--config=%s" % tmpDir, "--data=%s" % tmpDir]
+ ["--testmode", "--help", f"--config={tmpPath}", f"--data={tmpPath}"]
)
assert nwGUI.closeMain() == "closeMain"
assert ex.value.code == 0
with pytest.raises(SystemExit) as ex:
nwGUI = novelwriter.main(
- ["--testmode", "--version", "--config=%s" % tmpDir, "--data=%s" % tmpDir]
+ ["--testmode", "--version", f"--config={tmpPath}", f"--data={tmpPath}"]
)
assert nwGUI.closeMain() == "closeMain"
assert ex.value.code == 0
@@ -129,14 +129,14 @@ def testBaseInit_Options(monkeypatch, tmpDir):
# Invalid options
with pytest.raises(SystemExit) as ex:
nwGUI = novelwriter.main(
- ["--testmode", "--invalid", "--config=%s" % tmpDir, "--data=%s" % tmpDir]
+ ["--testmode", "--invalid", f"--config={tmpPath}", f"--data={tmpPath}"]
)
assert nwGUI.closeMain() == "closeMain"
assert ex.value.code == 2
# Project Path
nwGUI = novelwriter.main(
- ["--testmode", "--config=%s" % tmpDir, "--data=%s" % tmpDir, "sample/"]
+ ["--testmode", f"--config={tmpPath}", f"--data={tmpPath}", "sample/"]
)
assert novelwriter.CONFIG.cmdOpen == "sample/"
assert nwGUI.closeMain() == "closeMain"
@@ -145,7 +145,7 @@ def testBaseInit_Options(monkeypatch, tmpDir):
@pytest.mark.base
-def testBaseInit_Imports(caplog, monkeypatch, tmpDir):
+def testBaseInit_Imports(caplog, monkeypatch, tmpPath):
"""Check import error handling.
"""
monkeypatch.setattr("novelwriter.guimain.GuiMain", MockGuiMain)
@@ -161,7 +161,7 @@ def testBaseInit_Imports(caplog, monkeypatch, tmpDir):
with pytest.raises(SystemExit) as ex:
_ = novelwriter.main(
- ["--testmode", "--config=%s" % tmpDir, "--data=%s" % tmpDir]
+ ["--testmode", f"--config={tmpPath}", f"--data={tmpPath}"]
)
assert ex.value.code & 4 == 4 # Python version not satisfied
diff --git a/tests/test_core/test_core_coretools.py b/tests/test_core/test_core_coretools.py
index 39d95a7a..0f9a54f0 100644
--- a/tests/test_core/test_core_coretools.py
+++ b/tests/test_core/test_core_coretools.py
@@ -19,7 +19,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-import os
import uuid
import pytest
@@ -35,12 +34,12 @@ from novelwriter.core.coretools import DocMerger, DocSplitter, ProjectBuilder
@pytest.mark.core
-def testCoreTools_DocMerger(monkeypatch, mockGUI, fncDir, outDir, refDir, mockRnd, ipsumText):
+def testCoreTools_DocMerger(monkeypatch, mockGUI, fncPath, tstPaths, mockRnd, ipsumText):
"""Test the DocMerger utility.
"""
theProject = NWProject(mockGUI)
mockRnd.reset()
- buildTestProject(theProject, fncDir)
+ buildTestProject(theProject, fncPath)
# Create Files to Merge
# =====================
@@ -77,9 +76,9 @@ def testCoreTools_DocMerger(monkeypatch, mockGUI, fncDir, outDir, refDir, mockRn
# Merge to New
# ============
- saveFile = os.path.join(fncDir, "content", "0000000000014.nwd")
- testFile = os.path.join(outDir, "coreDocTools_DocMerger_0000000000014.nwd")
- compFile = os.path.join(refDir, "coreDocTools_DocMerger_0000000000014.nwd")
+ saveFile = fncPath / "content" / "0000000000014.nwd"
+ testFile = tstPaths.outDir / "coreDocTools_DocMerger_0000000000014.nwd"
+ compFile = tstPaths.refDir / "coreDocTools_DocMerger_0000000000014.nwd"
assert docMerger.newTargetDoc(hChapter1, "All of Chapter 1") == "0000000000014"
@@ -92,7 +91,7 @@ def testCoreTools_DocMerger(monkeypatch, mockGUI, fncDir, outDir, refDir, mockRn
with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError)
assert docMerger.writeTargetDoc() is False
- assert not os.path.isfile(saveFile)
+ assert not saveFile.exists()
assert docMerger.getError() != ""
# Write properly, and compare
@@ -103,9 +102,9 @@ def testCoreTools_DocMerger(monkeypatch, mockGUI, fncDir, outDir, refDir, mockRn
# Merge into Existing
# ===================
- saveFile = os.path.join(fncDir, "content", "0000000000010.nwd")
- testFile = os.path.join(outDir, "coreDocTools_DocMerger_0000000000010.nwd")
- compFile = os.path.join(refDir, "coreDocTools_DocMerger_0000000000010.nwd")
+ saveFile = fncPath / "content" / "0000000000010.nwd"
+ testFile = tstPaths.outDir / "coreDocTools_DocMerger_0000000000010.nwd"
+ compFile = tstPaths.refDir / "coreDocTools_DocMerger_0000000000010.nwd"
docMerger.setTargetDoc(hChapter1)
@@ -124,12 +123,12 @@ def testCoreTools_DocMerger(monkeypatch, mockGUI, fncDir, outDir, refDir, mockRn
@pytest.mark.core
-def testCoreTools_DocSplitter(monkeypatch, mockGUI, fncDir, outDir, refDir, mockRnd, ipsumText):
+def testCoreTools_DocSplitter(monkeypatch, mockGUI, fncPath, mockRnd, ipsumText):
"""Test the DocSplitter utility.
"""
theProject = NWProject(mockGUI)
mockRnd.reset()
- buildTestProject(theProject, fncDir)
+ buildTestProject(theProject, fncPath)
# Create File to Split
# ====================
@@ -264,15 +263,15 @@ def testCoreTools_DocSplitter(monkeypatch, mockGUI, fncDir, outDir, refDir, mock
@pytest.mark.core
-def testCoreTools_NewMinimal(monkeypatch, fncDir, outDir, refDir, mockGUI, mockRnd):
+def testCoreTools_NewMinimal(monkeypatch, fncPath, tstPaths, mockGUI, mockRnd):
"""Create a new project from a project wizard dictionary. With
default setting, creating a Minimal project.
"""
monkeypatch.setattr("uuid.uuid4", lambda *a: uuid.UUID("d0f3fe10-c6e6-4310-8bfd-181eb4224eed"))
- projFile = os.path.join(fncDir, "nwProject.nwx")
- testFile = os.path.join(outDir, "coreTools_NewMinimal_nwProject.nwx")
- compFile = os.path.join(refDir, "coreTools_NewMinimal_nwProject.nwx")
+ projFile = fncPath / "nwProject.nwx"
+ testFile = tstPaths.outDir / "coreTools_NewMinimal_nwProject.nwx"
+ compFile = tstPaths.refDir / "coreTools_NewMinimal_nwProject.nwx"
projBuild = ProjectBuilder(mockGUI)
@@ -283,10 +282,10 @@ def testCoreTools_NewMinimal(monkeypatch, fncDir, outDir, refDir, mockGUI, mockR
assert projBuild.buildProject("stuff") is False
# Try again with a proper path
- assert projBuild.buildProject({"projPath": fncDir}) is True
+ assert projBuild.buildProject({"projPath": fncPath}) is True
# Creating the project once more should fail
- assert projBuild.buildProject({"projPath": fncDir}) is False
+ assert projBuild.buildProject({"projPath": fncPath}) is False
# Save and close
copyfile(projFile, testFile)
@@ -296,21 +295,21 @@ def testCoreTools_NewMinimal(monkeypatch, fncDir, outDir, refDir, mockGUI, mockR
@pytest.mark.core
-def testCoreTools_NewCustomA(monkeypatch, fncDir, outDir, refDir, mockGUI, mockRnd):
+def testCoreTools_NewCustomA(monkeypatch, fncPath, tstPaths, mockGUI, mockRnd):
"""Create a new project from a project wizard dictionary.
Custom type with chapters and scenes.
"""
monkeypatch.setattr("uuid.uuid4", lambda *a: uuid.UUID("d0f3fe10-c6e6-4310-8bfd-181eb4224eed"))
- projFile = os.path.join(fncDir, "nwProject.nwx")
- testFile = os.path.join(outDir, "coreTools_NewCustomA_nwProject.nwx")
- compFile = os.path.join(refDir, "coreTools_NewCustomA_nwProject.nwx")
+ projFile = fncPath / "nwProject.nwx"
+ testFile = tstPaths.outDir / "coreTools_NewCustomA_nwProject.nwx"
+ compFile = tstPaths.refDir / "coreTools_NewCustomA_nwProject.nwx"
projData = {
"projName": "Test Custom",
"projTitle": "Test Novel",
"projAuthors": "Jane Doe\nJohn Doh\n",
- "projPath": fncDir,
+ "projPath": fncPath,
"popSample": False,
"popMinimal": False,
"popCustom": True,
@@ -334,21 +333,21 @@ def testCoreTools_NewCustomA(monkeypatch, fncDir, outDir, refDir, mockGUI, mockR
@pytest.mark.core
-def testCoreTools_NewCustomB(monkeypatch, fncDir, outDir, refDir, mockGUI, mockRnd):
+def testCoreTools_NewCustomB(monkeypatch, fncPath, tstPaths, mockGUI, mockRnd):
"""Create a new project from a project wizard dictionary.
Custom type without chapters, but with scenes.
"""
monkeypatch.setattr("uuid.uuid4", lambda *a: uuid.UUID("d0f3fe10-c6e6-4310-8bfd-181eb4224eed"))
- projFile = os.path.join(fncDir, "nwProject.nwx")
- testFile = os.path.join(outDir, "coreTools_NewCustomB_nwProject.nwx")
- compFile = os.path.join(refDir, "coreTools_NewCustomB_nwProject.nwx")
+ projFile = fncPath / "nwProject.nwx"
+ testFile = tstPaths.outDir / "coreTools_NewCustomB_nwProject.nwx"
+ compFile = tstPaths.refDir / "coreTools_NewCustomB_nwProject.nwx"
projData = {
"projName": "Test Custom",
"projTitle": "Test Novel",
"projAuthors": "Jane Doe\nJohn Doh\n",
- "projPath": fncDir,
+ "projPath": fncPath,
"popSample": False,
"popMinimal": False,
"popCustom": True,
@@ -406,16 +405,15 @@ def testCoreTools_NewSample(monkeypatch, fncPath, tmpConf, tmpPath, mockGUI):
outFile.write("foo")
assert projBuild.buildProject(projData) is False
- os.unlink(dstSample)
+ dstSample.unlink()
# Create a real zip file, and unpack it
with ZipFile(dstSample, "w") as zipObj:
- zipObj.write(os.path.join(srcSample, "nwProject.nwx"), "nwProject.nwx")
- for docFile in os.listdir(os.path.join(srcSample, "content")):
- srcDoc = os.path.join(srcSample, "content", docFile)
- zipObj.write(srcDoc, "content/"+docFile)
+ zipObj.write(srcSample / "nwProject.nwx", "nwProject.nwx")
+ for docFile in (srcSample / "content").iterdir():
+ zipObj.write(docFile, f"content/{docFile.name}")
assert projBuild.buildProject(projData) is True
- os.unlink(dstSample)
+ dstSample.unlink()
# END Test testCoreTools_NewSample
diff --git a/tests/test_core/test_core_index.py b/tests/test_core/test_core_index.py
index d08577d7..82bf53c8 100644
--- a/tests/test_core/test_core_index.py
+++ b/tests/test_core/test_core_index.py
@@ -23,7 +23,6 @@ import json
import pytest
from shutil import copyfile
-from pathlib import Path
from mock import causeException
from tools import C, buildTestProject, cmpFiles, writeFile
@@ -35,16 +34,16 @@ from novelwriter.core.project import NWProject
@pytest.mark.core
-def testCoreIndex_LoadSave(monkeypatch, nwLipsum, mockGUI, tstPaths):
+def testCoreIndex_LoadSave(monkeypatch, prjLipsum, mockGUI, tstPaths):
"""Test core functionality of scaning, saving, loading and checking
the index cache file.
"""
- projFile = Path(nwLipsum) / "meta" / nwFiles.INDEX_FILE
+ projFile = prjLipsum / "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)
+ assert theProject.openProject(prjLipsum)
theIndex = NWIndex(theProject)
assert repr(theIndex) == ""
@@ -196,12 +195,12 @@ def testCoreIndex_ScanThis(mockGUI):
@pytest.mark.core
-def testCoreIndex_CheckThese(mockGUI, fncDir, mockRnd):
+def testCoreIndex_CheckThese(mockGUI, fncPath, mockRnd):
"""Test the tag checker function checkThese.
"""
theProject = NWProject(mockGUI)
mockRnd.reset()
- buildTestProject(theProject, fncDir)
+ buildTestProject(theProject, fncPath)
theIndex = theProject.index
theIndex.clearIndex()
@@ -274,12 +273,12 @@ def testCoreIndex_CheckThese(mockGUI, fncDir, mockRnd):
@pytest.mark.core
-def testCoreIndex_ScanText(mockGUI, fncDir, mockRnd):
+def testCoreIndex_ScanText(mockGUI, fncPath, mockRnd):
"""Check the index text scanner.
"""
theProject = NWProject(mockGUI)
mockRnd.reset()
- buildTestProject(theProject, fncDir)
+ buildTestProject(theProject, fncPath)
theIndex = theProject.index
# Some items for fail to scan tests
@@ -486,12 +485,12 @@ def testCoreIndex_ScanText(mockGUI, fncDir, mockRnd):
@pytest.mark.core
-def testCoreIndex_ExtractData(mockGUI, fncDir, mockRnd):
+def testCoreIndex_ExtractData(mockGUI, fncPath, mockRnd):
"""Check the index data extraction functions.
"""
theProject = NWProject(mockGUI)
mockRnd.reset()
- buildTestProject(theProject, fncDir)
+ buildTestProject(theProject, fncPath)
theIndex = theProject.index
theIndex.reIndexHandle(C.hNovelRoot)
@@ -940,12 +939,12 @@ def testCoreIndex_TagsIndex():
@pytest.mark.core
-def testCoreIndex_ItemIndex(mockGUI, fncDir, mockRnd):
+def testCoreIndex_ItemIndex(mockGUI, fncPath, mockRnd):
"""Check the ItemIndex class.
"""
theProject = NWProject(mockGUI)
mockRnd.reset()
- buildTestProject(theProject, fncDir)
+ buildTestProject(theProject, fncPath)
theProject.index.clearIndex()
nHandle = C.hTitlePage
diff --git a/tests/test_core/test_core_item.py b/tests/test_core/test_core_item.py
index 16d2ffe2..6ee0837e 100644
--- a/tests/test_core/test_core_item.py
+++ b/tests/test_core/test_core_item.py
@@ -31,12 +31,12 @@ from novelwriter.enum import nwItemClass, nwItemType, nwItemLayout
@pytest.mark.core
-def testCoreItem_Setters(mockGUI, mockRnd, fncDir):
+def testCoreItem_Setters(mockGUI, mockRnd, fncPath):
"""Test all the simple setters for the NWItem class.
"""
theProject = NWProject(mockGUI)
mockRnd.reset()
- buildTestProject(theProject, fncDir)
+ buildTestProject(theProject, fncPath)
theItem = NWItem(theProject)
statusKeys = ["s000000", "s000001", "s000002", "s000003"]
@@ -192,12 +192,12 @@ def testCoreItem_Setters(mockGUI, mockRnd, fncDir):
@pytest.mark.core
-def testCoreItem_Methods(mockGUI, mockRnd, fncDir):
+def testCoreItem_Methods(mockGUI, mockRnd, fncPath):
"""Test the simple methods of the NWItem class.
"""
theProject = NWProject(mockGUI)
mockRnd.reset()
- buildTestProject(theProject, fncDir)
+ buildTestProject(theProject, fncPath)
theItem = NWItem(theProject)
# Describe Me
diff --git a/tests/test_core/test_core_project.py b/tests/test_core/test_core_project.py
index 377273da..d2931fd8 100644
--- a/tests/test_core/test_core_project.py
+++ b/tests/test_core/test_core_project.py
@@ -180,6 +180,7 @@ def testCoreProject_Open(monkeypatch, caplog, mockGUI, fncPath, mockRnd):
# Fail on lock file
assert theProject._storage.writeLockFile()
assert theProject.openProject(fncPath) is False
+ assert isinstance(theProject.getLockStatus(), list)
# Fail to read lockfile (which still opens the project)
with monkeypatch.context() as mp:
@@ -193,6 +194,7 @@ def testCoreProject_Open(monkeypatch, caplog, mockGUI, fncPath, mockRnd):
assert theProject._storage.writeLockFile()
assert theProject.openProject(fncPath, overrideLock=True) is True
assert theProject.closeProject()
+ assert theProject.getLockStatus() is None
# Fail getting xml reader
with monkeypatch.context() as mp:
@@ -625,7 +627,7 @@ def testCoreProject_Methods(monkeypatch, mockGUI, fncPath, mockRnd):
@pytest.mark.core
-def testCoreProject_OrphanedFiles(mockGUI, nwLipsum):
+def testCoreProject_OrphanedFiles(mockGUI, prjLipsum):
"""Check that files in the content folder that are not tracked in
the project XML file are handled correctly by the orphaned files
function. It should also restore as much meta data as possible from
@@ -633,7 +635,7 @@ def testCoreProject_OrphanedFiles(mockGUI, nwLipsum):
"""
theProject = NWProject(mockGUI)
- assert theProject.openProject(nwLipsum) is True
+ assert theProject.openProject(prjLipsum) is True
assert theProject.tree["636b6aa9b697b"] is None
# Add a file with non-existent parent
@@ -646,7 +648,7 @@ def testCoreProject_OrphanedFiles(mockGUI, nwLipsum):
assert theProject.closeProject() is True
# First Item with Meta Data
- orphPath = Path(nwLipsum) / "content" / "636b6aa9b697b.nwd"
+ orphPath = prjLipsum / "content" / "636b6aa9b697b.nwd"
writeFile(orphPath, (
"%%~name:[Recovered] Mars\n"
"%%~path:5eaea4e8cdee8/636b6aa9b697b\n"
@@ -656,22 +658,22 @@ def testCoreProject_OrphanedFiles(mockGUI, nwLipsum):
))
# Second Item without Meta Data
- orphPath = Path(nwLipsum) / "content" / "736b6aa9b697b.nwd"
+ orphPath = prjLipsum / "content" / "736b6aa9b697b.nwd"
writeFile(orphPath, "\n")
# Invalid File Name
- tstPath = Path(nwLipsum) / "content" / "636b6aa9b697b.txt"
+ tstPath = prjLipsum / "content" / "636b6aa9b697b.txt"
writeFile(tstPath, "\n")
# Invalid File Name
- tstPath = Path(nwLipsum) / "content" / "636b6aa9b697bb.nwd"
+ tstPath = prjLipsum / "content" / "636b6aa9b697bb.nwd"
writeFile(tstPath, "\n")
# Invalid File Name
- tstPath = Path(nwLipsum) / "content" / "abcdefghijklm.nwd"
+ tstPath = prjLipsum / "content" / "abcdefghijklm.nwd"
writeFile(tstPath, "\n")
- assert theProject.openProject(nwLipsum)
+ assert theProject.openProject(prjLipsum)
assert theProject.storage.storagePath is not None
assert theProject.storage.runtimePath is not None
assert theProject.tree["636b6aa9b697bb"] is None
@@ -697,7 +699,7 @@ def testCoreProject_OrphanedFiles(mockGUI, nwLipsum):
assert oItem.itemType == nwItemType.FILE
assert oItem.itemLayout == nwItemLayout.NOTE
- assert theProject.saveProject(nwLipsum)
+ assert theProject.saveProject(prjLipsum)
assert theProject.closeProject()
# Finally, check that the orphaned files function returns
@@ -730,17 +732,17 @@ def testCoreProject_Backup(monkeypatch, mockGUI, fncPath, tmpPath):
mockGUI.hasProject = True
# Invalid path
- theProject.mainConf.backupPath = None
+ theProject.mainConf._backupPath = None
assert theProject.backupProject(doNotify=False) is False
# Missing project name
- theProject.mainConf.backupPath = str(tmpPath)
+ theProject.mainConf._backupPath = tmpPath
theProject.data.setName("")
assert theProject.backupProject(doNotify=False) is False
# Valid Settings
# ==============
- theProject.mainConf.backupPath = str(tmpPath)
+ theProject.mainConf._backupPath = tmpPath
theProject.data.setName("Test Minimal")
# Can't make folder
diff --git a/tests/test_core/test_core_tohtml.py b/tests/test_core/test_core_tohtml.py
index 8880206c..44f16673 100644
--- a/tests/test_core/test_core_tohtml.py
+++ b/tests/test_core/test_core_tohtml.py
@@ -19,7 +19,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-import os
import pytest
from tools import readFile
@@ -441,7 +440,7 @@ def testCoreToHtml_SpecialCases(mockGUI):
@pytest.mark.core
-def testCoreToHtml_Complex(mockGUI, fncDir):
+def testCoreToHtml_Complex(mockGUI, fncPath):
"""Test the save method of the ToHtml class.
"""
theProject = NWProject(mockGUI)
@@ -529,7 +528,7 @@ def testCoreToHtml_Complex(mockGUI, fncDir):
bodyText="".join(resText).rstrip()
)
- saveFile = os.path.join(fncDir, "outFile.htm")
+ saveFile = fncPath / "outFile.htm"
theHtml.saveHTML5(saveFile)
assert readFile(saveFile) == htmlDoc
diff --git a/tests/test_core/test_core_tokenizer.py b/tests/test_core/test_core_tokenizer.py
index dfe9cf25..f2e939a2 100644
--- a/tests/test_core/test_core_tokenizer.py
+++ b/tests/test_core/test_core_tokenizer.py
@@ -19,7 +19,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-import os
import pytest
from tools import C, buildTestProject, readFile
@@ -132,12 +131,12 @@ def testCoreToken_Setters(mockGUI):
@pytest.mark.core
-def testCoreToken_TextOps(monkeypatch, mockGUI, mockRnd, fncDir):
+def testCoreToken_TextOps(monkeypatch, mockGUI, mockRnd, fncPath):
"""Test handling files and text in the Tokenizer class.
"""
theProject = NWProject(mockGUI)
mockRnd.reset()
- buildTestProject(theProject, fncDir)
+ buildTestProject(theProject, fncPath)
theProject.data.setLanguage("en")
theProject._loadProjectLocalisation()
@@ -210,7 +209,7 @@ def testCoreToken_TextOps(monkeypatch, mockGUI, mockRnd, fncDir):
assert theToken.theResult == "This is text with escapes: ** ~~ __"
# Save File
- savePath = os.path.join(fncDir, "dump.nwd")
+ savePath = fncPath / "dump.nwd"
theToken.saveRawMarkdown(savePath)
assert readFile(savePath) == (
"# Notes: Plot\n\n"
diff --git a/tests/test_core/test_core_tomd.py b/tests/test_core/test_core_tomd.py
index 3ec56a6b..aec51566 100644
--- a/tests/test_core/test_core_tomd.py
+++ b/tests/test_core/test_core_tomd.py
@@ -19,7 +19,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-import os
import pytest
from tools import readFile
@@ -208,7 +207,7 @@ def testCoreToMarkdown_ConvertDirect(mockGUI):
@pytest.mark.core
-def testCoreToMarkdown_Complex(mockGUI, fncDir):
+def testCoreToMarkdown_Complex(mockGUI, fncPath):
"""Test the save method of the ToMarkdown class.
"""
theProject = NWProject(mockGUI)
@@ -253,7 +252,7 @@ def testCoreToMarkdown_Complex(mockGUI, fncDir):
# Check File
# ==========
- saveFile = os.path.join(fncDir, "outFile.md")
+ saveFile = fncPath / "outFile.md"
theMD.saveMarkdown(saveFile)
assert readFile(saveFile) == "".join(resText)
diff --git a/tests/test_core/test_core_toodt.py b/tests/test_core/test_core_toodt.py
index a564a053..cbc9ce17 100644
--- a/tests/test_core/test_core_toodt.py
+++ b/tests/test_core/test_core_toodt.py
@@ -19,7 +19,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-import os
import pytest
import zipfile
@@ -612,7 +611,7 @@ def testCoreToOdt_ConvertDirect(mockGUI):
@pytest.mark.core
-def testCoreToOdt_SaveFlat(mockGUI, fncDir, outDir, refDir):
+def testCoreToOdt_SaveFlat(mockGUI, fncPath, tstPaths):
"""Test the document save functions.
"""
theProject = NWProject(mockGUI)
@@ -634,12 +633,12 @@ def testCoreToOdt_SaveFlat(mockGUI, fncDir, outDir, refDir):
theDoc.doConvert()
theDoc.closeDocument()
- flatFile = os.path.join(fncDir, "document.fodt")
- testFile = os.path.join(outDir, "coreToOdt_SaveFlat_document.fodt")
- compFile = os.path.join(refDir, "coreToOdt_SaveFlat_document.fodt")
+ flatFile = fncPath / "document.fodt"
+ testFile = tstPaths.outDir / "coreToOdt_SaveFlat_document.fodt"
+ compFile = tstPaths.refDir / "coreToOdt_SaveFlat_document.fodt"
theDoc.saveFlatXML(flatFile)
- assert os.path.isfile(flatFile)
+ assert flatFile.exists()
copyfile(flatFile, testFile)
assert cmpFiles(testFile, compFile, [4, 5])
@@ -648,7 +647,7 @@ def testCoreToOdt_SaveFlat(mockGUI, fncDir, outDir, refDir):
@pytest.mark.core
-def testCoreToOdt_SaveFull(mockGUI, fncDir, outDir, refDir):
+def testCoreToOdt_SaveFull(mockGUI, fncPath, tstPaths):
"""Test the document save functions.
"""
theProject = NWProject(mockGUI)
@@ -667,25 +666,25 @@ def testCoreToOdt_SaveFull(mockGUI, fncDir, outDir, refDir):
theDoc.doConvert()
theDoc.closeDocument()
- fullFile = os.path.join(fncDir, "document.odt")
+ fullFile = fncPath / "document.odt"
theDoc.saveOpenDocText(fullFile)
- assert os.path.isfile(fullFile)
+ assert fullFile.exists()
assert zipfile.is_zipfile(fullFile)
- maniFile = os.path.join(outDir, "coreToOdt_SaveFull_manifest.xml")
- settFile = os.path.join(outDir, "coreToOdt_SaveFull_settings.xml")
- contFile = os.path.join(outDir, "coreToOdt_SaveFull_content.xml")
- metaFile = os.path.join(outDir, "coreToOdt_SaveFull_meta.xml")
- stylFile = os.path.join(outDir, "coreToOdt_SaveFull_styles.xml")
+ maniFile = tstPaths.outDir / "coreToOdt_SaveFull_manifest.xml"
+ settFile = tstPaths.outDir / "coreToOdt_SaveFull_settings.xml"
+ contFile = tstPaths.outDir / "coreToOdt_SaveFull_content.xml"
+ metaFile = tstPaths.outDir / "coreToOdt_SaveFull_meta.xml"
+ stylFile = tstPaths.outDir / "coreToOdt_SaveFull_styles.xml"
- maniComp = os.path.join(refDir, "coreToOdt_SaveFull_manifest.xml")
- settComp = os.path.join(refDir, "coreToOdt_SaveFull_settings.xml")
- contComp = os.path.join(refDir, "coreToOdt_SaveFull_content.xml")
- metaComp = os.path.join(refDir, "coreToOdt_SaveFull_meta.xml")
- stylComp = os.path.join(refDir, "coreToOdt_SaveFull_styles.xml")
+ maniComp = tstPaths.refDir / "coreToOdt_SaveFull_manifest.xml"
+ settComp = tstPaths.refDir / "coreToOdt_SaveFull_settings.xml"
+ contComp = tstPaths.refDir / "coreToOdt_SaveFull_content.xml"
+ metaComp = tstPaths.refDir / "coreToOdt_SaveFull_meta.xml"
+ stylComp = tstPaths.refDir / "coreToOdt_SaveFull_styles.xml"
- extaxtTo = os.path.join(outDir, "coreToOdt_SaveFull")
+ extaxtTo = tstPaths.outDir / "coreToOdt_SaveFull"
with zipfile.ZipFile(fullFile, mode="r") as theZip:
theZip.extract("META-INF/manifest.xml", extaxtTo)
@@ -694,17 +693,17 @@ def testCoreToOdt_SaveFull(mockGUI, fncDir, outDir, refDir):
theZip.extract("meta.xml", extaxtTo)
theZip.extract("styles.xml", extaxtTo)
- maniOut = os.path.join(outDir, "coreToOdt_SaveFull", "META-INF", "manifest.xml")
- settOut = os.path.join(outDir, "coreToOdt_SaveFull", "settings.xml")
- contOut = os.path.join(outDir, "coreToOdt_SaveFull", "content.xml")
- metaOut = os.path.join(outDir, "coreToOdt_SaveFull", "meta.xml")
- stylOut = os.path.join(outDir, "coreToOdt_SaveFull", "styles.xml")
+ maniOut = tstPaths.outDir / "coreToOdt_SaveFull" / "META-INF" / "manifest.xml"
+ settOut = tstPaths.outDir / "coreToOdt_SaveFull" / "settings.xml"
+ contOut = tstPaths.outDir / "coreToOdt_SaveFull" / "content.xml"
+ metaOut = tstPaths.outDir / "coreToOdt_SaveFull" / "meta.xml"
+ stylOut = tstPaths.outDir / "coreToOdt_SaveFull" / "styles.xml"
def prettifyXml(inFile, outFile):
with open(outFile, mode="wb") as fileStream:
fileStream.write(
etree.tostring(
- etree.parse(inFile),
+ etree.parse(str(inFile)),
pretty_print=True,
encoding="utf-8",
xml_declaration=True
diff --git a/tests/test_dialogs/test_dlg_docmerge.py b/tests/test_dialogs/test_dlg_docmerge.py
index 1cf4768c..134ed5a2 100644
--- a/tests/test_dialogs/test_dlg_docmerge.py
+++ b/tests/test_dialogs/test_dlg_docmerge.py
@@ -29,11 +29,11 @@ from novelwriter.dialogs.docmerge import GuiDocMerge
@pytest.mark.gui
-def testDlgMerge_Main(qtbot, nwGUI, fncProj, mockRnd):
+def testDlgMerge_Main(qtbot, nwGUI, projPath, mockRnd):
"""Test the merge documents tool.
"""
# Create a new project
- buildTestProject(nwGUI, fncProj)
+ buildTestProject(nwGUI, projPath)
# Check that the dialog kan handle invalid items
nwMerge = GuiDocMerge(nwGUI, C.hInvalid, [C.hInvalid])
diff --git a/tests/test_dialogs/test_dlg_docsplit.py b/tests/test_dialogs/test_dlg_docsplit.py
index 05092c67..9eb296f2 100644
--- a/tests/test_dialogs/test_dlg_docsplit.py
+++ b/tests/test_dialogs/test_dlg_docsplit.py
@@ -28,13 +28,13 @@ from novelwriter.dialogs.editlabel import GuiEditLabel
@pytest.mark.gui
-def testDlgSplit_Main(qtbot, monkeypatch, nwGUI, fncProj, mockRnd):
+def testDlgSplit_Main(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
"""Test the split document tool.
"""
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
# Create a new project
- buildTestProject(nwGUI, fncProj)
+ buildTestProject(nwGUI, projPath)
theProject = nwGUI.theProject
projTree = nwGUI.projView.projTree
diff --git a/tests/test_dialogs/test_dlg_projload.py b/tests/test_dialogs/test_dlg_projload.py
index 7ccf683a..d5019f11 100644
--- a/tests/test_dialogs/test_dlg_projload.py
+++ b/tests/test_dialogs/test_dlg_projload.py
@@ -20,7 +20,6 @@ along with this program. If not, see .
"""
import pytest
-import os
from tools import buildTestProject, getGuiItem
@@ -33,10 +32,10 @@ from novelwriter.dialogs.projload import GuiProjectLoad
@pytest.mark.gui
-def testDlgLoadProject_Main(qtbot, monkeypatch, nwGUI, fncProj):
+def testDlgLoadProject_Main(qtbot, monkeypatch, nwGUI, projPath):
"""Test the load project wizard.
"""
- buildTestProject(nwGUI, fncProj)
+ buildTestProject(nwGUI, projPath)
assert nwGUI.closeProject()
monkeypatch.setattr(GuiProjectLoad, "exec_", lambda *a: None)
@@ -87,10 +86,10 @@ def testDlgLoadProject_Main(qtbot, monkeypatch, nwGUI, fncProj):
nwLoad._doDeleteRecent()
assert nwLoad.listBox.topLevelItemCount() == recentCount - 1
- getFile = os.path.join(fncProj, "nwProject.nwx")
+ getFile = str(projPath / "nwProject.nwx")
monkeypatch.setattr(QFileDialog, "getOpenFileName", lambda *a, **k: (getFile, None))
qtbot.mouseClick(nwLoad.browseButton, Qt.LeftButton)
- assert nwLoad.openPath == fncProj
+ assert nwLoad.openPath == projPath / "nwProject.nwx"
assert nwLoad.openState == nwLoad.OPEN_STATE
nwLoad.close()
diff --git a/tests/test_dialogs/test_dlg_projsettings.py b/tests/test_dialogs/test_dlg_projsettings.py
index 085e5398..2f51da30 100644
--- a/tests/test_dialogs/test_dlg_projsettings.py
+++ b/tests/test_dialogs/test_dlg_projsettings.py
@@ -82,16 +82,16 @@ def testDlgProjSettings_Dialog(qtbot, monkeypatch, nwGUI):
@pytest.mark.gui
-def testDlgProjSettings_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj, mockRnd):
+def testDlgProjSettings_Main(qtbot, monkeypatch, nwGUI, fncPath, projPath, mockRnd):
"""Test the main tab of the project settings dialog.
"""
# Mock components
monkeypatch.setattr(nwGUI.docEditor.spEnchant, "listDictionaries", lambda: [("en", "none")])
# Create new project
- buildTestProject(nwGUI, fncProj)
+ buildTestProject(nwGUI, projPath)
mockRnd.reset()
- nwGUI.mainConf.backupPath = fncDir
+ nwGUI.mainConf.backupPath = fncPath
# Set some values
theProject = nwGUI.theProject
@@ -148,7 +148,7 @@ def testDlgProjSettings_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj, mockRnd
@pytest.mark.gui
-def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, fncDir, fncProj, mockRnd):
+def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, fncPath, projPath, mockRnd):
"""Test the status and importance tabs of the project settings
dialog.
"""
@@ -159,8 +159,8 @@ def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, fncDir, fncProj,
# Create new project
mockRnd.reset()
- buildTestProject(nwGUI, fncProj)
- nwGUI.mainConf.backupPath = fncDir
+ buildTestProject(nwGUI, projPath)
+ nwGUI.mainConf.backupPath = fncPath
# Set some values
theProject = nwGUI.theProject
@@ -350,7 +350,7 @@ def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, fncDir, fncProj,
@pytest.mark.gui
-def testDlgProjSettings_Replace(qtbot, monkeypatch, nwGUI, fncDir, fncProj, mockRnd):
+def testDlgProjSettings_Replace(qtbot, monkeypatch, nwGUI, fncPath, projPath, mockRnd):
"""Test the auto-replace tab of the project settings dialog.
"""
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
@@ -360,8 +360,8 @@ def testDlgProjSettings_Replace(qtbot, monkeypatch, nwGUI, fncDir, fncProj, mock
# Create new project
mockRnd.reset()
- buildTestProject(nwGUI, fncProj)
- nwGUI.mainConf.backupPath = fncDir
+ buildTestProject(nwGUI, projPath)
+ nwGUI.mainConf.backupPath = fncPath
# Set some values
theProject = nwGUI.theProject
diff --git a/tests/test_dialogs/test_dlg_wordlist.py b/tests/test_dialogs/test_dlg_wordlist.py
index 3a088934..7f8d989c 100644
--- a/tests/test_dialogs/test_dlg_wordlist.py
+++ b/tests/test_dialogs/test_dlg_wordlist.py
@@ -19,7 +19,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-import os
import pytest
from PyQt5.QtCore import Qt
@@ -33,18 +32,18 @@ from novelwriter.dialogs.wordlist import GuiWordList
@pytest.mark.gui
-def testDlgWordList_Dialog(qtbot, monkeypatch, nwGUI, fncProj):
+def testDlgWordList_Dialog(qtbot, monkeypatch, nwGUI, projPath):
"""test the word list editor.
"""
- buildTestProject(nwGUI, fncProj)
+ buildTestProject(nwGUI, projPath)
monkeypatch.setattr(GuiWordList, "exec_", lambda *a: None)
monkeypatch.setattr(GuiWordList, "result", lambda *a: QDialog.Accepted)
monkeypatch.setattr(GuiWordList, "accept", lambda *a: None)
# Open project
- nwGUI.openProject(fncProj)
- dictFile = os.path.join(fncProj, "meta", nwFiles.PROJ_DICT)
+ nwGUI.openProject(projPath)
+ dictFile = projPath / "meta" / nwFiles.PROJ_DICT
# Load the dialog
nwGUI.mainMenu.aEditWordList.activate(QAction.Trigger)
diff --git a/tests/test_gui/test_gui_doceditor.py b/tests/test_gui/test_gui_doceditor.py
index 193fda9e..7f47fd60 100644
--- a/tests/test_gui/test_gui_doceditor.py
+++ b/tests/test_gui/test_gui_doceditor.py
@@ -37,11 +37,11 @@ KEY_DELAY = 1
@pytest.mark.gui
-def testGuiEditor_Init(qtbot, nwGUI, fncProj, ipsumText, mockRnd):
+def testGuiEditor_Init(qtbot, nwGUI, projPath, ipsumText, mockRnd):
"""Test initialising the editor.
"""
# Open project
- buildTestProject(nwGUI, fncProj)
+ buildTestProject(nwGUI, projPath)
assert nwGUI.openDocument(C.hSceneDoc)
nwGUI.docEditor.setText("### Lorem Ipsum\n\n%s" % ipsumText[0])
@@ -80,10 +80,10 @@ def testGuiEditor_Init(qtbot, nwGUI, fncProj, ipsumText, mockRnd):
@pytest.mark.gui
-def testGuiEditor_LoadText(qtbot, monkeypatch, caplog, nwGUI, fncProj, ipsumText, mockRnd):
+def testGuiEditor_LoadText(qtbot, monkeypatch, caplog, nwGUI, projPath, ipsumText, mockRnd):
"""Test loading text into the editor.
"""
- buildTestProject(nwGUI, fncProj)
+ buildTestProject(nwGUI, projPath)
assert nwGUI.openDocument(C.hSceneDoc) is True
longText = "### Lorem Ipsum\n\n%s" % "\n\n".join(ipsumText*20)
@@ -135,10 +135,10 @@ def testGuiEditor_LoadText(qtbot, monkeypatch, caplog, nwGUI, fncProj, ipsumText
@pytest.mark.gui
-def testGuiEditor_SaveText(qtbot, monkeypatch, caplog, nwGUI, fncProj, ipsumText, mockRnd):
+def testGuiEditor_SaveText(qtbot, monkeypatch, caplog, nwGUI, projPath, ipsumText, mockRnd):
"""Test saving text from the editor.
"""
- buildTestProject(nwGUI, fncProj)
+ buildTestProject(nwGUI, projPath)
assert nwGUI.openDocument(C.hSceneDoc) is True
# Save Text
@@ -179,10 +179,10 @@ def testGuiEditor_SaveText(qtbot, monkeypatch, caplog, nwGUI, fncProj, ipsumText
@pytest.mark.gui
-def testGuiEditor_MetaData(qtbot, nwGUI, fncProj, mockRnd):
+def testGuiEditor_MetaData(qtbot, nwGUI, projPath, mockRnd):
"""Test extracting various meta data and other values.
"""
- buildTestProject(nwGUI, fncProj)
+ buildTestProject(nwGUI, projPath)
assert nwGUI.openDocument(C.hSceneDoc) is True
# Get Text
@@ -226,13 +226,13 @@ def testGuiEditor_MetaData(qtbot, nwGUI, fncProj, mockRnd):
@pytest.mark.gui
-def testGuiEditor_Actions(qtbot, nwGUI, fncProj, ipsumText, mockRnd):
+def testGuiEditor_Actions(qtbot, nwGUI, projPath, ipsumText, mockRnd):
"""Test the document actions. This is not an extensive test of the
action features, just that the actions are actually called. The
various action features are tested when their respective functions
are tested.
"""
- buildTestProject(nwGUI, fncProj)
+ buildTestProject(nwGUI, projPath)
assert nwGUI.openDocument(C.hSceneDoc) is True
theText = "### A Scene\n\n%s" % "\n\n".join(ipsumText)
@@ -459,10 +459,10 @@ def testGuiEditor_Actions(qtbot, nwGUI, fncProj, ipsumText, mockRnd):
@pytest.mark.gui
-def testGuiEditor_Insert(qtbot, monkeypatch, nwGUI, fncProj, ipsumText, mockRnd):
+def testGuiEditor_Insert(qtbot, monkeypatch, nwGUI, projPath, ipsumText, mockRnd):
"""Test the document insert functions.
"""
- buildTestProject(nwGUI, fncProj)
+ buildTestProject(nwGUI, projPath)
assert nwGUI.openDocument(C.hSceneDoc) is True
theText = "### A Scene\n\n%s" % "\n\n".join(ipsumText)
@@ -542,10 +542,10 @@ def testGuiEditor_Insert(qtbot, monkeypatch, nwGUI, fncProj, ipsumText, mockRnd)
@pytest.mark.gui
-def testGuiEditor_TextManipulation(qtbot, monkeypatch, nwGUI, fncProj, ipsumText, mockRnd):
+def testGuiEditor_TextManipulation(qtbot, monkeypatch, nwGUI, projPath, ipsumText, mockRnd):
"""Test the text manipulation functions.
"""
- buildTestProject(nwGUI, fncProj)
+ buildTestProject(nwGUI, projPath)
assert nwGUI.openDocument(C.hSceneDoc) is True
theText = "### A Scene\n\n%s" % "\n\n".join(ipsumText)
@@ -749,10 +749,10 @@ def testGuiEditor_TextManipulation(qtbot, monkeypatch, nwGUI, fncProj, ipsumText
@pytest.mark.gui
-def testGuiEditor_BlockFormatting(qtbot, monkeypatch, nwGUI, fncProj, ipsumText, mockRnd):
+def testGuiEditor_BlockFormatting(qtbot, monkeypatch, nwGUI, projPath, ipsumText, mockRnd):
"""Test the block formatting function.
"""
- buildTestProject(nwGUI, fncProj)
+ buildTestProject(nwGUI, projPath)
assert nwGUI.openDocument(C.hSceneDoc) is True
theText = "### A Scene\n\n%s" % "\n\n".join(ipsumText)
@@ -1062,10 +1062,10 @@ def testGuiEditor_BlockFormatting(qtbot, monkeypatch, nwGUI, fncProj, ipsumText,
@pytest.mark.gui
-def testGuiEditor_Tags(qtbot, nwGUI, fncProj, ipsumText, mockRnd):
+def testGuiEditor_Tags(qtbot, nwGUI, projPath, ipsumText, mockRnd):
"""Test the document editor tags functionality.
"""
- buildTestProject(nwGUI, fncProj)
+ buildTestProject(nwGUI, projPath)
assert nwGUI.openDocument(C.hSceneDoc) is True
# Create Scene
@@ -1121,7 +1121,7 @@ def testGuiEditor_Tags(qtbot, nwGUI, fncProj, ipsumText, mockRnd):
@pytest.mark.gui
-def testGuiEditor_WordCounters(qtbot, monkeypatch, nwGUI, fncProj, ipsumText, mockRnd):
+def testGuiEditor_WordCounters(qtbot, monkeypatch, nwGUI, projPath, ipsumText, mockRnd):
"""Test saving text from the editor.
"""
class MockThreadPool:
@@ -1139,7 +1139,7 @@ def testGuiEditor_WordCounters(qtbot, monkeypatch, nwGUI, fncProj, ipsumText, mo
nwGUI.docEditor.wcTimerDoc.blockSignals(True)
nwGUI.docEditor.wcTimerSel.blockSignals(True)
- buildTestProject(nwGUI, fncProj)
+ buildTestProject(nwGUI, projPath)
# Run on an empty document
nwGUI.docEditor._runDocCounter()
diff --git a/tests/test_gui/test_gui_guimain.py b/tests/test_gui/test_gui_guimain.py
index 4ec1ed5e..8c5670a8 100644
--- a/tests/test_gui/test_gui_guimain.py
+++ b/tests/test_gui/test_gui_guimain.py
@@ -19,7 +19,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-import os
import pytest
from tools import C, cmpFiles, buildTestProject, XML_IGNORE, writeFile
@@ -67,7 +66,7 @@ def testGuiMain_ProjectBlocker(nwGUI):
@pytest.mark.gui
-def testGuiMain_NewProject(monkeypatch, nwGUI, fncProj):
+def testGuiMain_NewProject(monkeypatch, nwGUI, projPath):
"""Test creating a new project.
"""
# No data
@@ -79,34 +78,34 @@ def testGuiMain_NewProject(monkeypatch, nwGUI, fncProj):
with monkeypatch.context() as mp:
nwGUI.hasProject = True
mp.setattr(QMessageBox, "question", lambda *a: QMessageBox.No)
- assert nwGUI.newProject(projData={"projPath": fncProj}) is False
+ assert nwGUI.newProject(projData={"projPath": projPath}) is False
# No project path
assert nwGUI.newProject(projData={}) is False
# Project file already exists
- projFile = os.path.join(fncProj, nwFiles.PROJ_FILE)
+ projFile = projPath / nwFiles.PROJ_FILE
writeFile(projFile, "Stuff")
- assert nwGUI.newProject(projData={"projPath": fncProj}) is False
- os.unlink(projFile)
+ assert nwGUI.newProject(projData={"projPath": projPath}) is False
+ projFile.unlink()
# An unreachable path should also fail
- projPath = os.path.join(fncProj, "stuff", "stuff", "stuff")
- assert nwGUI.newProject(projData={"projPath": projPath}) is False
+ stuffPath = projPath / "stuff" / "stuff" / "stuff"
+ assert nwGUI.newProject(projData={"projPath": stuffPath}) is False
# This one should work just fine
- assert nwGUI.newProject(projData={"projPath": fncProj}) is True
- assert os.path.isfile(os.path.join(fncProj, nwFiles.PROJ_FILE))
- assert os.path.isdir(os.path.join(fncProj, "content"))
+ assert nwGUI.newProject(projData={"projPath": projPath}) is True
+ assert (projPath / nwFiles.PROJ_FILE).is_file()
+ assert (projPath / "content").is_dir()
# END Test testGuiMain_NewProject
@pytest.mark.gui
-def testGuiMain_ProjectTreeItems(qtbot, monkeypatch, nwGUI, fncProj, mockRnd):
+def testGuiMain_ProjectTreeItems(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
"""Test handling of project tree items based on GUI focus states.
"""
- buildTestProject(nwGUI, fncProj)
+ buildTestProject(nwGUI, projPath)
sHandle = "000000000000f"
assert nwGUI.openSelectedItem() is False
@@ -153,7 +152,7 @@ def testGuiMain_ProjectTreeItems(qtbot, monkeypatch, nwGUI, fncProj, mockRnd):
@pytest.mark.gui
-def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir, mockRnd):
+def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, projPath, tstPaths, mockRnd):
"""Test the document editor.
"""
monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *a: True)
@@ -162,7 +161,7 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir, mock
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
# Create new, save, close project
- buildTestProject(nwGUI, fncProj)
+ buildTestProject(nwGUI, projPath)
assert nwGUI.saveProject()
assert nwGUI.closeProject()
@@ -176,14 +175,14 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir, mock
assert nwGUI.theProject.data.spellCheck is False
# Check the files
- projFile = os.path.join(fncProj, "nwProject.nwx")
- testFile = os.path.join(outDir, "guiEditor_Main_Initial_nwProject.nwx")
- compFile = os.path.join(refDir, "guiEditor_Main_Initial_nwProject.nwx")
+ projFile = projPath / "nwProject.nwx"
+ testFile = tstPaths.outDir / "guiEditor_Main_Initial_nwProject.nwx"
+ compFile = tstPaths.refDir / "guiEditor_Main_Initial_nwProject.nwx"
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE)
# Re-open project
- assert nwGUI.openProject(fncProj)
+ assert nwGUI.openProject(projPath)
# Check that we loaded the data
assert len(nwGUI.theProject.tree) == 8
@@ -494,33 +493,33 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir, mock
assert nwGUI.saveProject()
# Check the files
- projFile = os.path.join(fncProj, "nwProject.nwx")
- testFile = os.path.join(outDir, "guiEditor_Main_Final_nwProject.nwx")
- compFile = os.path.join(refDir, "guiEditor_Main_Final_nwProject.nwx")
+ projFile = projPath / "nwProject.nwx"
+ testFile = tstPaths.outDir / "guiEditor_Main_Final_nwProject.nwx"
+ compFile = tstPaths.refDir / "guiEditor_Main_Final_nwProject.nwx"
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile, ignoreStart=(*XML_IGNORE, ".
"""
import pytest
-import os
-from PyQt5.QtCore import Qt
from PyQt5.QtGui import QTextCursor, QTextBlock
+from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QAction, QFileDialog, QMessageBox
from tools import C, writeFile, buildTestProject
@@ -422,10 +421,10 @@ def testGuiMenu_ContextMenus(qtbot, nwGUI, nwLipsum):
@pytest.mark.gui
-def testGuiMenu_Insert(qtbot, monkeypatch, nwGUI, fncDir, fncProj, mockRnd):
+def testGuiMenu_Insert(qtbot, monkeypatch, nwGUI, fncPath, projPath, mockRnd):
"""Test the Insert menu.
"""
- buildTestProject(nwGUI, fncProj)
+ buildTestProject(nwGUI, projPath)
assert nwGUI.projView.projTree._getTreeItem(C.hSceneDoc) is not None
assert nwGUI.openDocument(C.hSceneDoc) is True
@@ -626,8 +625,8 @@ def testGuiMenu_Insert(qtbot, monkeypatch, nwGUI, fncDir, fncProj, mockRnd):
assert not nwGUI.importDocument()
# Then a valid path, but bot a file that exists
- theFile = os.path.join(fncDir, "import.txt")
- monkeypatch.setattr(QFileDialog, "getOpenFileName", lambda *a, **k: (theFile, ""))
+ theFile = fncPath / "import.txt"
+ monkeypatch.setattr(QFileDialog, "getOpenFileName", lambda *a, **k: (str(theFile), ""))
assert not nwGUI.importDocument()
# Create the file and try again, but with no target document open
@@ -666,7 +665,7 @@ def testGuiMenu_Insert(qtbot, monkeypatch, nwGUI, fncDir, fncProj, mockRnd):
theBits = theMessage.split("
")
assert len(theBits) == 2
assert theBits[0] == "The currently open file is saved in:"
- assert theBits[1] == os.path.join(fncProj, "content", "000000000000f.nwd")
+ assert theBits[1] == str(projPath / "content" / "000000000000f.nwd")
# qtbot.stop()
diff --git a/tests/test_gui/test_gui_noveltree.py b/tests/test_gui/test_gui_noveltree.py
index cfaeecc4..20c38d03 100644
--- a/tests/test_gui/test_gui_noveltree.py
+++ b/tests/test_gui/test_gui_noveltree.py
@@ -35,12 +35,12 @@ from novelwriter.dialogs.editlabel import GuiEditLabel
@pytest.mark.gui
-def testGuiNovelTree_TreeItems(qtbot, monkeypatch, nwGUI, fncProj, mockRnd):
+def testGuiNovelTree_TreeItems(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
"""Test navigating the novel tree.
"""
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
- buildTestProject(nwGUI, fncProj)
+ buildTestProject(nwGUI, projPath)
nwGUI.switchFocus(nwWidget.TREE)
nwGUI.projView.projTree.clearSelection()
diff --git a/tests/test_gui/test_gui_outline.py b/tests/test_gui/test_gui_outline.py
index 77d9e739..23f61c5b 100644
--- a/tests/test_gui/test_gui_outline.py
+++ b/tests/test_gui/test_gui_outline.py
@@ -32,12 +32,11 @@ from novelwriter.enum import nwItemClass, nwOutline, nwView
@pytest.mark.gui
-def testGuiOutline_Main(qtbot, monkeypatch, nwGUI, fncDir):
+def testGuiOutline_Main(qtbot, monkeypatch, nwGUI, projPath):
"""Test the outline view.
"""
# Create a project
- prjDir = os.path.join(fncDir, "project")
- buildTestProject(nwGUI, prjDir)
+ buildTestProject(nwGUI, projPath)
nwGUI.rebuildIndex()
nwGUI._changeView(nwView.OUTLINE)
diff --git a/tests/test_gui/test_gui_projtree.py b/tests/test_gui/test_gui_projtree.py
index 13d27382..cbf607d8 100644
--- a/tests/test_gui/test_gui_projtree.py
+++ b/tests/test_gui/test_gui_projtree.py
@@ -19,7 +19,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-import os
import pytest
from mock import causeOSError
@@ -36,7 +35,7 @@ from novelwriter.dialogs.editlabel import GuiEditLabel
@pytest.mark.gui
-def testGuiProjTree_NewItems(qtbot, caplog, monkeypatch, nwGUI, fncDir, mockRnd):
+def testGuiProjTree_NewItems(qtbot, caplog, monkeypatch, nwGUI, projPath, mockRnd):
"""Test adding and removing items from the project tree.
"""
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
@@ -49,8 +48,7 @@ def testGuiProjTree_NewItems(qtbot, caplog, monkeypatch, nwGUI, fncDir, mockRnd)
assert projView.projTree.newTreeItem(nwItemType.FILE) is False
# Create a project
- prjDir = os.path.join(fncDir, "project")
- buildTestProject(nwGUI, prjDir)
+ buildTestProject(nwGUI, projPath)
# No itemType set
projView.projTree.clearSelection()
@@ -168,7 +166,7 @@ def testGuiProjTree_NewItems(qtbot, caplog, monkeypatch, nwGUI, fncDir, mockRnd)
@pytest.mark.gui
-def testGuiProjTree_MoveItems(qtbot, monkeypatch, nwGUI, fncDir, mockRnd):
+def testGuiProjTree_MoveItems(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
"""Test adding and removing items from the project tree.
"""
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
@@ -180,8 +178,7 @@ def testGuiProjTree_MoveItems(qtbot, monkeypatch, nwGUI, fncDir, mockRnd):
assert projView.projTree.moveTreeItem(1) is False
# Create a project
- prjDir = os.path.join(fncDir, "project")
- buildTestProject(nwGUI, prjDir)
+ buildTestProject(nwGUI, projPath)
# Move Documents
# ==============
@@ -279,7 +276,7 @@ def testGuiProjTree_MoveItems(qtbot, monkeypatch, nwGUI, fncDir, mockRnd):
@pytest.mark.gui
-def testGuiProjTree_RequestDeleteItem(qtbot, caplog, monkeypatch, nwGUI, fncDir, mockRnd):
+def testGuiProjTree_RequestDeleteItem(qtbot, caplog, monkeypatch, nwGUI, projPath, mockRnd):
"""Test external requests for removing items from project tree.
"""
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
@@ -291,8 +288,7 @@ def testGuiProjTree_RequestDeleteItem(qtbot, caplog, monkeypatch, nwGUI, fncDir,
assert projView.requestDeleteItem() is False
# Create a project
- prjDir = os.path.join(fncDir, "project")
- buildTestProject(nwGUI, prjDir)
+ buildTestProject(nwGUI, projPath)
# Try emptying the trash already now, when there is no trash folder
assert projView.emptyTrash() is False
@@ -363,7 +359,7 @@ def testGuiProjTree_RequestDeleteItem(qtbot, caplog, monkeypatch, nwGUI, fncDir,
@pytest.mark.gui
-def testGuiProjTree_MoveItemToTrash(qtbot, caplog, monkeypatch, nwGUI, fncDir, mockRnd):
+def testGuiProjTree_MoveItemToTrash(qtbot, caplog, monkeypatch, nwGUI, projPath, mockRnd):
"""Test moving items to Trash.
"""
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
@@ -372,8 +368,7 @@ def testGuiProjTree_MoveItemToTrash(qtbot, caplog, monkeypatch, nwGUI, fncDir, m
projTree = nwGUI.projView.projTree
# Create a project
- prjDir = os.path.join(fncDir, "project")
- buildTestProject(nwGUI, prjDir)
+ buildTestProject(nwGUI, projPath)
# Invalid item
caplog.clear()
@@ -417,7 +412,7 @@ def testGuiProjTree_MoveItemToTrash(qtbot, caplog, monkeypatch, nwGUI, fncDir, m
@pytest.mark.gui
-def testGuiProjTree_PermanentlyDeleteItem(qtbot, caplog, monkeypatch, nwGUI, fncDir, mockRnd):
+def testGuiProjTree_PermanentlyDeleteItem(qtbot, caplog, monkeypatch, nwGUI, projPath, mockRnd):
"""Test permanently deleting items.
"""
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
@@ -426,8 +421,7 @@ def testGuiProjTree_PermanentlyDeleteItem(qtbot, caplog, monkeypatch, nwGUI, fnc
projTree = nwGUI.projView.projTree
# Create a project
- prjDir = os.path.join(fncDir, "project")
- buildTestProject(nwGUI, prjDir)
+ buildTestProject(nwGUI, projPath)
# Invalid item
caplog.clear()
@@ -470,7 +464,7 @@ def testGuiProjTree_PermanentlyDeleteItem(qtbot, caplog, monkeypatch, nwGUI, fnc
@pytest.mark.gui
-def testGuiProjTree_EmptyTrash(qtbot, caplog, monkeypatch, nwGUI, fncDir, mockRnd):
+def testGuiProjTree_EmptyTrash(qtbot, caplog, monkeypatch, nwGUI, projPath, mockRnd):
"""Test emptying Trash.
"""
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
@@ -484,8 +478,7 @@ def testGuiProjTree_EmptyTrash(qtbot, caplog, monkeypatch, nwGUI, fncDir, mockRn
assert "No project open" in caplog.text
# Create a project
- prjDir = os.path.join(fncDir, "project")
- buildTestProject(nwGUI, prjDir)
+ buildTestProject(nwGUI, projPath)
# No Trash folder
assert projTree.emptyTrash() is False
@@ -524,7 +517,7 @@ def testGuiProjTree_EmptyTrash(qtbot, caplog, monkeypatch, nwGUI, fncDir, mockRn
@pytest.mark.gui
-def testGuiProjTree_ContextMenu(qtbot, monkeypatch, nwGUI, fncDir, mockRnd):
+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,
"""
@@ -532,8 +525,7 @@ def testGuiProjTree_ContextMenu(qtbot, monkeypatch, nwGUI, fncDir, mockRnd):
monkeypatch.setattr(QMenu, "exec_", lambda *a: None)
# Create a project
- prjDir = os.path.join(fncDir, "project")
- buildTestProject(nwGUI, prjDir)
+ buildTestProject(nwGUI, projPath)
# Handles for new objects
hCharNote = "0000000000011"
@@ -643,7 +635,7 @@ def testGuiProjTree_ContextMenu(qtbot, monkeypatch, nwGUI, fncDir, mockRnd):
@pytest.mark.gui
-def testGuiProjTree_MergeDocuments(qtbot, monkeypatch, nwGUI, fncDir, mockRnd, ipsumText):
+def testGuiProjTree_MergeDocuments(qtbot, monkeypatch, nwGUI, projPath, mockRnd, ipsumText):
"""Test the merge document function.
"""
mergeData = {}
@@ -654,8 +646,7 @@ def testGuiProjTree_MergeDocuments(qtbot, monkeypatch, nwGUI, fncDir, mockRnd, i
monkeypatch.setattr(GuiDocMerge, "getData", lambda *a: mergeData)
# Create a project
- prjDir = os.path.join(fncDir, "project")
- buildTestProject(nwGUI, prjDir)
+ buildTestProject(nwGUI, projPath)
theProject = nwGUI.theProject
projTree = nwGUI.projView.projTree
@@ -746,7 +737,7 @@ def testGuiProjTree_MergeDocuments(qtbot, monkeypatch, nwGUI, fncDir, mockRnd, i
@pytest.mark.gui
-def testGuiProjTree_SplitDocument(qtbot, monkeypatch, nwGUI, fncDir, mockRnd, ipsumText):
+def testGuiProjTree_SplitDocument(qtbot, monkeypatch, nwGUI, projPath, mockRnd, ipsumText):
"""Test the split document function.
"""
splitData = {}
@@ -758,8 +749,7 @@ def testGuiProjTree_SplitDocument(qtbot, monkeypatch, nwGUI, fncDir, mockRnd, ip
monkeypatch.setattr(GuiDocSplit, "getData", lambda *a: (splitData, splitText))
# Create a project
- prjDir = os.path.join(fncDir, "project")
- buildTestProject(nwGUI, prjDir)
+ buildTestProject(nwGUI, projPath)
theProject = nwGUI.theProject
projTree = nwGUI.projView.projTree
@@ -828,13 +818,13 @@ def testGuiProjTree_SplitDocument(qtbot, monkeypatch, nwGUI, fncDir, mockRnd, ip
assert projTree._splitDocument(hSplitDoc) is True
for tHandle in fstSet:
assert tHandle in theProject.tree
- assert not os.path.isfile(os.path.join(prjDir, "content", f"{tHandle}.nwd"))
+ assert not (projPath / "content" / f"{tHandle}.nwd").is_file()
# Writing succeeds
assert projTree._splitDocument(hSplitDoc) is True
for tHandle in sndSet:
assert tHandle in theProject.tree
- assert os.path.isfile(os.path.join(prjDir, "content", f"{tHandle}.nwd"))
+ assert (projPath / "content" / f"{tHandle}.nwd").is_file()
# Add to a folder and move source to trash
splitData["intoFolder"] = True
@@ -843,7 +833,7 @@ def testGuiProjTree_SplitDocument(qtbot, monkeypatch, nwGUI, fncDir, mockRnd, ip
assert "0000000000029" in theProject.tree # The folder
for tHandle in trdSet:
assert tHandle in theProject.tree
- assert os.path.isfile(os.path.join(prjDir, "content", f"{tHandle}.nwd"))
+ assert (projPath / "content" / f"{tHandle}.nwd").is_file()
assert theProject.tree.isTrash(hSplitDoc) is True
@@ -858,13 +848,12 @@ def testGuiProjTree_SplitDocument(qtbot, monkeypatch, nwGUI, fncDir, mockRnd, ip
@pytest.mark.gui
-def testGuiProjTree_Other(qtbot, monkeypatch, nwGUI, fncDir, mockRnd):
+def testGuiProjTree_Other(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
"""Test various parts of the project tree class not covered by
other tests.
"""
# Create a project
- prjDir = os.path.join(fncDir, "project")
- buildTestProject(nwGUI, prjDir)
+ buildTestProject(nwGUI, projPath)
projView = nwGUI.projView
projTree = nwGUI.projView.projTree
diff --git a/tests/test_gui/test_gui_statusbar.py b/tests/test_gui/test_gui_statusbar.py
index 3f04acda..a057fb36 100644
--- a/tests/test_gui/test_gui_statusbar.py
+++ b/tests/test_gui/test_gui_statusbar.py
@@ -28,10 +28,10 @@ from novelwriter.enum import nwState
@pytest.mark.gui
-def testGuiStatusBar_Main(qtbot, nwGUI, fncProj, mockRnd):
+def testGuiStatusBar_Main(qtbot, nwGUI, projPath, mockRnd):
"""Test the the various features of the status bar.
"""
- buildTestProject(nwGUI, fncProj)
+ buildTestProject(nwGUI, projPath)
cHandle = nwGUI.theProject.newFile("A Note", C.hCharRoot)
newDoc = nwGUI.theProject.storage.getDocument(cHandle)
newDoc.writeDocument("# A Note\n\n")
diff --git a/tests/test_tools/test_tools_build.py b/tests/test_tools/test_tools_build.py
index 5cb93229..33bd8ecc 100644
--- a/tests/test_tools/test_tools_build.py
+++ b/tests/test_tools/test_tools_build.py
@@ -20,10 +20,8 @@ along with this program. If not, see .
"""
import pytest
-import os
from shutil import copyfile
-from pathlib import Path
from tools import cmpFiles, getGuiItem
@@ -34,7 +32,7 @@ from novelwriter.tools import GuiBuildNovel
@pytest.mark.gui
-def testToolBuild_Main(qtbot, monkeypatch, nwGUI, nwLipsum, refDir, outDir):
+def testToolBuild_Main(qtbot, monkeypatch, nwGUI, prjLipsum, tstPaths):
"""Test the build tool.
"""
# Block message box
@@ -45,7 +43,7 @@ def testToolBuild_Main(qtbot, monkeypatch, nwGUI, nwLipsum, refDir, outDir):
assert getGuiItem("GuiBuildNovel") is None
# Open a project
- assert nwGUI.openProject(nwLipsum)
+ assert nwGUI.openProject(prjLipsum)
# Open the tool
nwGUI.mainMenu.aBuildProject.activate(QAction.Trigger)
@@ -69,41 +67,41 @@ def testToolBuild_Main(qtbot, monkeypatch, nwGUI, nwLipsum, refDir, outDir):
assert not nwBuild._saveDocument(nwBuild.FMT_NWD)
# Default Settings
- nwGUI.mainConf._lastPath = Path(nwLipsum)
+ nwGUI.mainConf._lastPath = prjLipsum
qtbot.mouseClick(nwBuild.buildNovel, Qt.LeftButton)
assert nwBuild._saveDocument(nwBuild.FMT_NWD)
- projFile = os.path.join(nwLipsum, "Lorem Ipsum.nwd")
- testFile = os.path.join(outDir, "guiBuild_Tool_Step1_Lorem_Ipsum.nwd")
- compFile = os.path.join(refDir, "guiBuild_Tool_Step1_Lorem_Ipsum.nwd")
+ projFile = prjLipsum / "Lorem Ipsum.nwd"
+ testFile = tstPaths.outDir / "guiBuild_Tool_Step1_Lorem_Ipsum.nwd"
+ compFile = tstPaths.refDir / "guiBuild_Tool_Step1_Lorem_Ipsum.nwd"
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile)
assert nwBuild._saveDocument(nwBuild.FMT_HTM)
- projFile = os.path.join(nwLipsum, "Lorem Ipsum.htm")
- testFile = os.path.join(outDir, "guiBuild_Tool_Step1_Lorem_Ipsum.htm")
- compFile = os.path.join(refDir, "guiBuild_Tool_Step1_Lorem_Ipsum.htm")
+ projFile = prjLipsum / "Lorem Ipsum.htm"
+ testFile = tstPaths.outDir / "guiBuild_Tool_Step1_Lorem_Ipsum.htm"
+ compFile = tstPaths.refDir / "guiBuild_Tool_Step1_Lorem_Ipsum.htm"
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile)
assert nwBuild._saveDocument(nwBuild.FMT_MD)
- projFile = os.path.join(nwLipsum, "Lorem Ipsum.md")
- testFile = os.path.join(outDir, "guiBuild_Tool_Step1_Lorem_Ipsum.md")
- compFile = os.path.join(refDir, "guiBuild_Tool_Step1_Lorem_Ipsum.md")
+ projFile = prjLipsum / "Lorem Ipsum.md"
+ testFile = tstPaths.outDir / "guiBuild_Tool_Step1_Lorem_Ipsum.md"
+ compFile = tstPaths.refDir / "guiBuild_Tool_Step1_Lorem_Ipsum.md"
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile)
assert nwBuild._saveDocument(nwBuild.FMT_GH)
- projFile = os.path.join(nwLipsum, "Lorem Ipsum.md")
- testFile = os.path.join(outDir, "guiBuild_Tool_Step1G_Lorem_Ipsum.md")
- compFile = os.path.join(refDir, "guiBuild_Tool_Step1G_Lorem_Ipsum.md")
+ projFile = prjLipsum / "Lorem Ipsum.md"
+ testFile = tstPaths.outDir / "guiBuild_Tool_Step1G_Lorem_Ipsum.md"
+ compFile = tstPaths.refDir / "guiBuild_Tool_Step1G_Lorem_Ipsum.md"
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile)
assert nwBuild._saveDocument(nwBuild.FMT_FODT)
- projFile = os.path.join(nwLipsum, "Lorem Ipsum.fodt")
- testFile = os.path.join(outDir, "guiBuild_Tool_Step1_Lorem_Ipsum.fodt")
- compFile = os.path.join(refDir, "guiBuild_Tool_Step1_Lorem_Ipsum.fodt")
+ projFile = prjLipsum / "Lorem Ipsum.fodt"
+ testFile = tstPaths.outDir / "guiBuild_Tool_Step1_Lorem_Ipsum.fodt"
+ compFile = tstPaths.refDir / "guiBuild_Tool_Step1_Lorem_Ipsum.fodt"
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile, [4, 5])
@@ -124,30 +122,30 @@ def testToolBuild_Main(qtbot, monkeypatch, nwGUI, nwLipsum, refDir, outDir):
qtbot.mouseClick(nwBuild.buildNovel, Qt.LeftButton)
assert nwBuild._saveDocument(nwBuild.FMT_NWD)
- projFile = os.path.join(nwLipsum, "Lorem Ipsum.nwd")
- testFile = os.path.join(outDir, "guiBuild_Tool_Step2_Lorem_Ipsum.nwd")
- compFile = os.path.join(refDir, "guiBuild_Tool_Step2_Lorem_Ipsum.nwd")
+ projFile = prjLipsum / "Lorem Ipsum.nwd"
+ testFile = tstPaths.outDir / "guiBuild_Tool_Step2_Lorem_Ipsum.nwd"
+ compFile = tstPaths.refDir / "guiBuild_Tool_Step2_Lorem_Ipsum.nwd"
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile)
assert nwBuild._saveDocument(nwBuild.FMT_HTM)
- projFile = os.path.join(nwLipsum, "Lorem Ipsum.htm")
- testFile = os.path.join(outDir, "guiBuild_Tool_Step2_Lorem_Ipsum.htm")
- compFile = os.path.join(refDir, "guiBuild_Tool_Step2_Lorem_Ipsum.htm")
+ projFile = prjLipsum / "Lorem Ipsum.htm"
+ testFile = tstPaths.outDir / "guiBuild_Tool_Step2_Lorem_Ipsum.htm"
+ compFile = tstPaths.refDir / "guiBuild_Tool_Step2_Lorem_Ipsum.htm"
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile)
assert nwBuild._saveDocument(nwBuild.FMT_MD)
- projFile = os.path.join(nwLipsum, "Lorem Ipsum.md")
- testFile = os.path.join(outDir, "guiBuild_Tool_Step2_Lorem_Ipsum.md")
- compFile = os.path.join(refDir, "guiBuild_Tool_Step2_Lorem_Ipsum.md")
+ projFile = prjLipsum / "Lorem Ipsum.md"
+ testFile = tstPaths.outDir / "guiBuild_Tool_Step2_Lorem_Ipsum.md"
+ compFile = tstPaths.refDir / "guiBuild_Tool_Step2_Lorem_Ipsum.md"
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile)
assert nwBuild._saveDocument(nwBuild.FMT_FODT)
- projFile = os.path.join(nwLipsum, "Lorem Ipsum.fodt")
- testFile = os.path.join(outDir, "guiBuild_Tool_Step2_Lorem_Ipsum.fodt")
- compFile = os.path.join(refDir, "guiBuild_Tool_Step2_Lorem_Ipsum.fodt")
+ projFile = prjLipsum / "Lorem Ipsum.fodt"
+ testFile = tstPaths.outDir / "guiBuild_Tool_Step2_Lorem_Ipsum.fodt"
+ compFile = tstPaths.refDir / "guiBuild_Tool_Step2_Lorem_Ipsum.fodt"
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile, [4, 5])
@@ -158,30 +156,30 @@ def testToolBuild_Main(qtbot, monkeypatch, nwGUI, nwLipsum, refDir, outDir):
# Save files that can be compared
assert nwBuild._saveDocument(nwBuild.FMT_NWD)
- projFile = os.path.join(nwLipsum, "Lorem Ipsum.nwd")
- testFile = os.path.join(outDir, "guiBuild_Tool_Step3_Lorem_Ipsum.nwd")
- compFile = os.path.join(refDir, "guiBuild_Tool_Step3_Lorem_Ipsum.nwd")
+ projFile = prjLipsum / "Lorem Ipsum.nwd"
+ testFile = tstPaths.outDir / "guiBuild_Tool_Step3_Lorem_Ipsum.nwd"
+ compFile = tstPaths.refDir / "guiBuild_Tool_Step3_Lorem_Ipsum.nwd"
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile)
assert nwBuild._saveDocument(nwBuild.FMT_HTM)
- projFile = os.path.join(nwLipsum, "Lorem Ipsum.htm")
- testFile = os.path.join(outDir, "guiBuild_Tool_Step3_Lorem_Ipsum.htm")
- compFile = os.path.join(refDir, "guiBuild_Tool_Step3_Lorem_Ipsum.htm")
+ projFile = prjLipsum / "Lorem Ipsum.htm"
+ testFile = tstPaths.outDir / "guiBuild_Tool_Step3_Lorem_Ipsum.htm"
+ compFile = tstPaths.refDir / "guiBuild_Tool_Step3_Lorem_Ipsum.htm"
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile)
assert nwBuild._saveDocument(nwBuild.FMT_MD)
- projFile = os.path.join(nwLipsum, "Lorem Ipsum.md")
- testFile = os.path.join(outDir, "guiBuild_Tool_Step3_Lorem_Ipsum.md")
- compFile = os.path.join(refDir, "guiBuild_Tool_Step3_Lorem_Ipsum.md")
+ projFile = prjLipsum / "Lorem Ipsum.md"
+ testFile = tstPaths.outDir / "guiBuild_Tool_Step3_Lorem_Ipsum.md"
+ compFile = tstPaths.refDir / "guiBuild_Tool_Step3_Lorem_Ipsum.md"
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile)
assert nwBuild._saveDocument(nwBuild.FMT_FODT)
- projFile = os.path.join(nwLipsum, "Lorem Ipsum.fodt")
- testFile = os.path.join(outDir, "guiBuild_Tool_Step3_Lorem_Ipsum.fodt")
- compFile = os.path.join(refDir, "guiBuild_Tool_Step3_Lorem_Ipsum.fodt")
+ projFile = prjLipsum / "Lorem Ipsum.fodt"
+ testFile = tstPaths.outDir / "guiBuild_Tool_Step3_Lorem_Ipsum.fodt"
+ compFile = tstPaths.refDir / "guiBuild_Tool_Step3_Lorem_Ipsum.fodt"
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile, [4, 5])
@@ -199,43 +197,43 @@ def testToolBuild_Main(qtbot, monkeypatch, nwGUI, nwLipsum, refDir, outDir):
# Save files that can be compared
assert nwBuild._saveDocument(nwBuild.FMT_NWD)
- projFile = os.path.join(nwLipsum, "Lorem Ipsum.nwd")
- testFile = os.path.join(outDir, "guiBuild_Tool_Step4_Lorem_Ipsum.nwd")
- compFile = os.path.join(refDir, "guiBuild_Tool_Step4_Lorem_Ipsum.nwd")
+ projFile = prjLipsum / "Lorem Ipsum.nwd"
+ testFile = tstPaths.outDir / "guiBuild_Tool_Step4_Lorem_Ipsum.nwd"
+ compFile = tstPaths.refDir / "guiBuild_Tool_Step4_Lorem_Ipsum.nwd"
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile)
assert nwBuild._saveDocument(nwBuild.FMT_HTM)
- projFile = os.path.join(nwLipsum, "Lorem Ipsum.htm")
- testFile = os.path.join(outDir, "guiBuild_Tool_Step4_Lorem_Ipsum.htm")
- compFile = os.path.join(refDir, "guiBuild_Tool_Step4_Lorem_Ipsum.htm")
+ projFile = prjLipsum / "Lorem Ipsum.htm"
+ testFile = tstPaths.outDir / "guiBuild_Tool_Step4_Lorem_Ipsum.htm"
+ compFile = tstPaths.refDir / "guiBuild_Tool_Step4_Lorem_Ipsum.htm"
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile)
# Check the JSON files too at this stage
assert nwBuild._saveDocument(nwBuild.FMT_JSON_H)
- projFile = os.path.join(nwLipsum, "Lorem Ipsum.json")
- testFile = os.path.join(outDir, "guiBuild_Tool_Step4H_Lorem_Ipsum.json")
- compFile = os.path.join(refDir, "guiBuild_Tool_Step4H_Lorem_Ipsum.json")
+ projFile = prjLipsum / "Lorem Ipsum.json"
+ testFile = tstPaths.outDir / "guiBuild_Tool_Step4H_Lorem_Ipsum.json"
+ compFile = tstPaths.refDir / "guiBuild_Tool_Step4H_Lorem_Ipsum.json"
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile, [8])
assert nwBuild._saveDocument(nwBuild.FMT_JSON_M)
- projFile = os.path.join(nwLipsum, "Lorem Ipsum.json")
- testFile = os.path.join(outDir, "guiBuild_Tool_Step4M_Lorem_Ipsum.json")
- compFile = os.path.join(refDir, "guiBuild_Tool_Step4M_Lorem_Ipsum.json")
+ projFile = prjLipsum / "Lorem Ipsum.json"
+ testFile = tstPaths.outDir / "guiBuild_Tool_Step4M_Lorem_Ipsum.json"
+ compFile = tstPaths.refDir / "guiBuild_Tool_Step4M_Lorem_Ipsum.json"
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile, [8])
# Since odt and fodt is built by the same code, we don't check the
# output. but just that the different format can be written as well
assert nwBuild._saveDocument(nwBuild.FMT_ODT)
- assert os.path.isfile(os.path.join(nwLipsum, "Lorem Ipsum.odt"))
+ assert (prjLipsum / "Lorem Ipsum.odt").is_file()
# Print to PDF
if not nwGUI.mainConf.osDarwin:
assert nwBuild._saveDocument(nwBuild.FMT_PDF)
- assert os.path.isfile(os.path.join(nwLipsum, "Lorem Ipsum.pdf"))
+ assert (prjLipsum / "Lorem Ipsum.pdf").is_file()
# Close the build tool
htmlText = nwBuild.htmlText
diff --git a/tests/test_tools/test_tools_lipsum.py b/tests/test_tools/test_tools_lipsum.py
index 0bd07f97..409a168b 100644
--- a/tests/test_tools/test_tools_lipsum.py
+++ b/tests/test_tools/test_tools_lipsum.py
@@ -29,7 +29,7 @@ from novelwriter.tools import GuiLipsum
@pytest.mark.gui
-def testToolLipsum_Main(qtbot, nwGUI, fncProj, mockRnd):
+def testToolLipsum_Main(qtbot, nwGUI, projPath, mockRnd):
"""Test the Lorem Ipsum tool.
"""
# Check that we cannot open when there is no project
@@ -37,7 +37,7 @@ def testToolLipsum_Main(qtbot, nwGUI, fncProj, mockRnd):
assert getGuiItem("GuiLipsum") is None
# Create a new project
- buildTestProject(nwGUI, fncProj)
+ buildTestProject(nwGUI, projPath)
assert nwGUI.openDocument(C.hSceneDoc) is True
assert len(nwGUI.docEditor.getText()) == 15
diff --git a/tests/test_tools/test_tools_projwizard.py b/tests/test_tools/test_tools_projwizard.py
index ed9d8a58..336e4b1b 100644
--- a/tests/test_tools/test_tools_projwizard.py
+++ b/tests/test_tools/test_tools_projwizard.py
@@ -19,7 +19,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-import os
import sys
import pytest
@@ -37,7 +36,7 @@ from novelwriter.tools.projwizard import (
@pytest.mark.gui
@pytest.mark.skipif(sys.platform.startswith("darwin"), reason="Not running on Darwin")
-def testToolProjectWizard_Handling(qtbot, monkeypatch, nwGUI, fncProj):
+def testToolProjectWizard_Handling(qtbot, monkeypatch, nwGUI, projPath):
"""Test the launch of the project wizard.
Disabled for macOS because the test segfaults on QWizard.show()
"""
@@ -45,7 +44,7 @@ def testToolProjectWizard_Handling(qtbot, monkeypatch, nwGUI, fncProj):
# ========================
# New with a project open should cause an error
- buildTestProject(nwGUI, fncProj)
+ buildTestProject(nwGUI, projPath)
with monkeypatch.context() as mp:
mp.setattr(nwGUI, "closeProject", lambda *a: False)
assert nwGUI.newProject() is False
@@ -61,7 +60,7 @@ def testToolProjectWizard_Handling(qtbot, monkeypatch, nwGUI, fncProj):
assert nwGUI.newProject() is False
# Now, with a non-empty folder
- mp.setattr(nwGUI, "showNewProjectDialog", lambda *a: {"projPath": fncProj})
+ mp.setattr(nwGUI, "showNewProjectDialog", lambda *a: {"projPath": projPath})
assert nwGUI.newProject() is False
# Test the Wizard Launching
@@ -96,7 +95,7 @@ def testToolProjectWizard_Handling(qtbot, monkeypatch, nwGUI, fncProj):
@pytest.mark.gui
@pytest.mark.parametrize("prjType", ["minimal", "custom1", "custom2", "sample"])
@pytest.mark.skipif(sys.platform.startswith("darwin"), reason="Not running on Darwin")
-def testToolProjectWizard_Run(qtbot, monkeypatch, nwGUI, fncDir, prjType):
+def testToolProjectWizard_Run(qtbot, monkeypatch, nwGUI, fncPath, prjType):
"""Test the new project wizard with a set of selection scenarios.
"""
monkeypatch.setattr(GuiProjectWizard, "exec_", lambda *a: None)
@@ -130,12 +129,12 @@ def testToolProjectWizard_Run(qtbot, monkeypatch, nwGUI, fncDir, prjType):
assert storagePage.errLabel.text() == ""
# Set an invalid path
- storagePage.projPath.setText(os.path.join(fncDir, "not", "a", "path"))
+ storagePage.projPath.setText(str(fncPath / "not" / "a" / "path"))
assert not nwWiz.button(QWizard.NextButton).isEnabled()
assert storagePage.errLabel.text().startswith("Error")
# Set an existing path
- storagePage.projPath.setText(fncDir)
+ storagePage.projPath.setText(str(fncPath))
assert not nwWiz.button(QWizard.NextButton).isEnabled()
assert storagePage.errLabel.text().startswith("Error")
@@ -146,12 +145,12 @@ def testToolProjectWizard_Run(qtbot, monkeypatch, nwGUI, fncDir, prjType):
assert storagePage.errLabel.text() == ""
# Let the browse feature handle it
- projPath = os.path.join(fncDir, "Test Wizard")
+ projPath = fncPath / "Test Wizard"
with monkeypatch.context() as mp:
- mp.setattr(QFileDialog, "getExistingDirectory", lambda *a, **k: fncDir)
+ mp.setattr(QFileDialog, "getExistingDirectory", lambda *a, **k: str(fncPath))
qtbot.mouseClick(storagePage.browseButton, Qt.LeftButton, delay=100)
- assert storagePage.projPath.text() == projPath
+ assert storagePage.projPath.text() == str(projPath)
assert storagePage.errLabel.text() == ""
# Setting projPath should activate the button
@@ -216,7 +215,7 @@ def testToolProjectWizard_Run(qtbot, monkeypatch, nwGUI, fncDir, prjType):
assert projData["projName"] == "Test Wizard"
assert projData["projTitle"] == "My Novel"
assert projData["projAuthors"] == "Jane Doe"
- assert projData["projPath"] == projPath
+ assert projData["projPath"] == str(projPath)
assert projData["popMinimal"] == prjType.startswith("minimal")
assert projData["popCustom"] == prjType.startswith("custom")
assert projData["popSample"] == prjType.startswith("sample")
diff --git a/tests/test_tools/test_tools_writingstats.py b/tests/test_tools/test_tools_writingstats.py
index 60f59750..a02d386a 100644
--- a/tests/test_tools/test_tools_writingstats.py
+++ b/tests/test_tools/test_tools_writingstats.py
@@ -19,9 +19,8 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-import pytest
import json
-import os
+import pytest
from mock import causeOSError
from tools import getGuiItem, writeFile, buildTestProject
@@ -34,14 +33,14 @@ from novelwriter.constants import nwFiles
@pytest.mark.gui
-def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj):
+def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncPath, projPath):
"""Test the full writing stats tool.
"""
# Create a project to work on
- buildTestProject(nwGUI, fncProj)
+ buildTestProject(nwGUI, projPath)
qtbot.wait(100)
assert nwGUI.saveProject()
- sessFile = os.path.join(fncProj, "meta", nwFiles.SESS_STATS)
+ sessFile = projPath / "meta" / nwFiles.SESS_STATS
# Open the Writing Stats dialog
nwGUI.mainMenu.aWritingStats.activate(QAction.Trigger)
@@ -54,7 +53,7 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj):
# ============
# No initial logfile
- assert not os.path.isfile(sessFile)
+ assert not sessFile.is_file()
assert not sessLog._loadLogFile()
# Make a test log file
@@ -66,7 +65,7 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj):
"2020-01-03 21:30:00 2020-01-03 21:30:15 125 5\n"
"2020-01-06 21:00:00 2020-01-06 21:00:10 125 5\n"
))
- assert os.path.isfile(sessFile)
+ assert sessFile.is_file()
assert sessLog._loadLogFile()
assert sessLog.wordOffset == 123
assert len(sessLog.logData) == 4
@@ -110,9 +109,7 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj):
assert not sessLog._saveData(None)
# Make the save succeed
- monkeypatch.setattr("os.path.expanduser", lambda *a: fncDir)
monkeypatch.setattr(QFileDialog, "getSaveFileName", lambda ss, tt, pp, options: (pp, ""))
-
sessLog.listBox.sortByColumn(sessLog.C_TIME, 0)
assert sessLog.novelWords.text() == "{:n}".format(600)
@@ -135,7 +132,7 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj):
qtbot.wait(100)
# Check the exported files
- jsonStats = os.path.join(fncDir, "sessionStats.json")
+ jsonStats = fncPath / "sessionStats.json"
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
jsonData = json.load(inFile)
@@ -174,7 +171,7 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj):
qtbot.mouseClick(sessLog.incNovel, Qt.LeftButton)
assert sessLog._saveData(sessLog.FMT_JSON)
- jsonStats = os.path.join(fncDir, "sessionStats.json")
+ jsonStats = fncPath / "sessionStats.json"
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
jsonData = json.loads(inFile.read())
@@ -220,7 +217,7 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj):
qtbot.mouseClick(sessLog.incNotes, Qt.LeftButton)
assert sessLog._saveData(sessLog.FMT_JSON)
- jsonStats = os.path.join(fncDir, "sessionStats.json")
+ jsonStats = fncPath / "sessionStats.json"
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
jsonData = json.load(inFile)
@@ -268,7 +265,7 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj):
# qtbot.stop()
- jsonStats = os.path.join(fncDir, "sessionStats.json")
+ jsonStats = fncPath / "sessionStats.json"
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
jsonData = json.load(inFile)
@@ -298,7 +295,7 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj):
qtbot.mouseClick(sessLog.hideZeros, Qt.LeftButton)
assert sessLog._saveData(sessLog.FMT_JSON)
- jsonStats = os.path.join(fncDir, "sessionStats.json")
+ jsonStats = fncPath / "sessionStats.json"
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
jsonData = json.load(inFile)
@@ -351,7 +348,7 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj):
qtbot.mouseClick(sessLog.groupByDay, Qt.LeftButton)
assert sessLog._saveData(sessLog.FMT_JSON)
- jsonStats = os.path.join(fncDir, "sessionStats.json")
+ jsonStats = fncPath / "sessionStats.json"
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
jsonData = json.load(inFile)
diff --git a/tests/tools.py b/tests/tools.py
index c2511b28..0883dc14 100644
--- a/tests/tools.py
+++ b/tests/tools.py
@@ -19,10 +19,11 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-import os
import time
import shutil
+from pathlib import Path
+
from PyQt5.QtWidgets import qApp
XML_IGNORE = ("