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