@@ -26,12 +26,13 @@ jobs:
|
||||
pip install --upgrade pip
|
||||
pip install -r requirements.txt
|
||||
pip install PyVirtualDisplay
|
||||
pip install pytest-timeout
|
||||
pip install pytest-cov
|
||||
pip install pytest-xvfb
|
||||
pip install pytest-qt
|
||||
pip install codecov
|
||||
- name: Run Tests
|
||||
run: xvfb-run pytest -v --cov=nw
|
||||
run: xvfb-run pytest -v --cov=nw --timeout=60
|
||||
- name: Upload to Codecov
|
||||
uses: codecov/codecov-action@v1
|
||||
|
||||
@@ -58,7 +59,8 @@ jobs:
|
||||
pip install --upgrade pip
|
||||
pip install -r requirements.txt
|
||||
pip install PyVirtualDisplay
|
||||
pip install pytest-timeout
|
||||
pip install pytest-xvfb
|
||||
pip install pytest-qt
|
||||
- name: Run Tests
|
||||
run: xvfb-run pytest -v
|
||||
run: xvfb-run pytest -v --timeout=60
|
||||
|
||||
@@ -243,8 +243,6 @@ def fuzzyTime(secDiff):
|
||||
else:
|
||||
return "%d years ago" % int(round(secDiff/31557600))
|
||||
|
||||
return "beyond time and space"
|
||||
|
||||
def makeFileNameSafe(theText):
|
||||
"""Returns a filename safe version of the text.
|
||||
"""
|
||||
|
||||
+3
-1
@@ -54,9 +54,11 @@ class Config:
|
||||
# Set Application Variables
|
||||
self.appName = "novelWriter"
|
||||
self.appHandle = self.appName.lower()
|
||||
self.cmdOpen = None
|
||||
|
||||
# Debug Settings
|
||||
self.showGUI = True
|
||||
self.debugInfo = False
|
||||
self.cmdOpen = None
|
||||
|
||||
# Config Error Handling
|
||||
self.hasError = False
|
||||
|
||||
+5
-2
@@ -41,7 +41,7 @@ from nw.core.document import NWDoc
|
||||
from nw.core.status import NWStatus
|
||||
from nw.core.options import OptionState
|
||||
from nw.common import (
|
||||
checkString, checkBool, checkInt, formatTimeStamp, makeFileNameSafe
|
||||
checkString, checkBool, checkInt, isHandle, formatTimeStamp, makeFileNameSafe
|
||||
)
|
||||
from nw.constants import (
|
||||
nwFiles, nwItemType, nwItemClass, nwItemLayout, nwLabels, nwAlert
|
||||
@@ -1288,10 +1288,13 @@ class NWProject():
|
||||
logger.warning("Skipping file %s" % fileItem)
|
||||
continue
|
||||
fHandle = fileItem[:13]
|
||||
if not isHandle(fHandle):
|
||||
logger.warning("Skipping file %s" % fileItem)
|
||||
continue
|
||||
if fHandle in self.projTree:
|
||||
logger.debug("Checking file %s, handle %s: OK" % (fileItem, fHandle))
|
||||
else:
|
||||
logger.debug("Checking file %s, handle %s: Orphaned" % (fileItem, fHandle))
|
||||
logger.warning("Checking file %s, handle %s: Orphaned" % (fileItem, fHandle))
|
||||
orphanFiles.append(fHandle)
|
||||
|
||||
# Report status
|
||||
|
||||
+9
-7
@@ -35,6 +35,7 @@ class NWErrorMessage(QDialog):
|
||||
|
||||
def __init__(self, parent):
|
||||
QDialog.__init__(self, parent=parent)
|
||||
self.setObjectName("NWErrorMessage")
|
||||
|
||||
# Widgets
|
||||
self.msgIcon = QLabel()
|
||||
@@ -134,21 +135,18 @@ class NWErrorMessage(QDialog):
|
||||
# END Class NWErrorMessage
|
||||
|
||||
|
||||
def exceptionHandler(exType, exValue, exTrace):
|
||||
def exceptionHandler(exType, exValue, exTrace, testMode=False):
|
||||
"""Function to catch unhandled global exceptions.
|
||||
"""
|
||||
import nw
|
||||
import logging
|
||||
from traceback import print_tb
|
||||
from nw import CONFIG
|
||||
from PyQt5.QtWidgets import qApp
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.critical("%s: %s" % (exType.__name__, str(exValue)))
|
||||
print_tb(exTrace)
|
||||
|
||||
if not CONFIG.showGUI:
|
||||
return
|
||||
|
||||
try:
|
||||
nwGUI = None
|
||||
for qWin in qApp.topLevelWidgets():
|
||||
@@ -162,7 +160,8 @@ def exceptionHandler(exType, exValue, exTrace):
|
||||
|
||||
errMsg = NWErrorMessage(nwGUI)
|
||||
errMsg.setMessage(exType, exValue, exTrace)
|
||||
errMsg.exec_()
|
||||
if nw.CONFIG.showGUI:
|
||||
errMsg.exec_()
|
||||
|
||||
try:
|
||||
# Try a controlled shudown
|
||||
@@ -174,7 +173,10 @@ def exceptionHandler(exType, exValue, exTrace):
|
||||
logger.critical("Could not close the project before exiting")
|
||||
logger.critical(str(e))
|
||||
|
||||
qApp.exit(1)
|
||||
if testMode:
|
||||
return errMsg.msgBody.toPlainText()
|
||||
else:
|
||||
qApp.exit(1)
|
||||
|
||||
except Exception as e:
|
||||
logger.critical(str(e))
|
||||
|
||||
+41
-79
@@ -39,7 +39,6 @@ from PyQt5.QtWidgets import (
|
||||
|
||||
from nw.gui.custom import QSwitch, QConfigLayout, PagedDialog, QuotesDialog
|
||||
from nw.core import NWSpellCheck, NWSpellSimple, NWSpellEnchant
|
||||
from nw.constants import nwQuotes
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -104,7 +103,7 @@ class GuiPreferences(PagedDialog):
|
||||
validEntries &= retA
|
||||
needsRestart |= retB
|
||||
|
||||
if needsRestart:
|
||||
if needsRestart and self.mainConf.showGUI:
|
||||
msgBox = QMessageBox()
|
||||
msgBox.information(
|
||||
self, "Preferences",
|
||||
@@ -817,69 +816,70 @@ class GuiConfigEditAutoReplaceTab(QWidget):
|
||||
|
||||
qWidth = self.mainConf.pxInt(40)
|
||||
bWidth = int(2.5*self.theTheme.getTextWidth("..."))
|
||||
self.quoteSym = {}
|
||||
|
||||
## Single Quote Style
|
||||
self.quoteSingleStyleO = QLineEdit()
|
||||
self.quoteSingleStyleO.setMaxLength(1)
|
||||
self.quoteSingleStyleO.setReadOnly(True)
|
||||
self.quoteSingleStyleO.setFixedWidth(qWidth)
|
||||
self.quoteSingleStyleO.setAlignment(Qt.AlignCenter)
|
||||
self.quoteSingleStyleO.setText(self.mainConf.fmtSingleQuotes[0])
|
||||
self.quoteSym["SO"] = QLineEdit()
|
||||
self.quoteSym["SO"].setMaxLength(1)
|
||||
self.quoteSym["SO"].setReadOnly(True)
|
||||
self.quoteSym["SO"].setFixedWidth(qWidth)
|
||||
self.quoteSym["SO"].setAlignment(Qt.AlignCenter)
|
||||
self.quoteSym["SO"].setText(self.mainConf.fmtSingleQuotes[0])
|
||||
self.btnSingleStyleO = QPushButton("...")
|
||||
self.btnSingleStyleO.setMaximumWidth(bWidth)
|
||||
self.btnSingleStyleO.clicked.connect(self._getSingleOpen)
|
||||
self.btnSingleStyleO.clicked.connect(lambda: self._getQuote("SO"))
|
||||
self.mainForm.addRow(
|
||||
"Single quote open style",
|
||||
self.quoteSingleStyleO,
|
||||
self.quoteSym["SO"],
|
||||
"Auto-replaces apostrophe before words.",
|
||||
theButton=self.btnSingleStyleO
|
||||
)
|
||||
|
||||
self.quoteSingleStyleC = QLineEdit()
|
||||
self.quoteSingleStyleC.setMaxLength(1)
|
||||
self.quoteSingleStyleC.setReadOnly(True)
|
||||
self.quoteSingleStyleC.setFixedWidth(qWidth)
|
||||
self.quoteSingleStyleC.setAlignment(Qt.AlignCenter)
|
||||
self.quoteSingleStyleC.setText(self.mainConf.fmtSingleQuotes[1])
|
||||
self.quoteSym["SC"] = QLineEdit()
|
||||
self.quoteSym["SC"].setMaxLength(1)
|
||||
self.quoteSym["SC"].setReadOnly(True)
|
||||
self.quoteSym["SC"].setFixedWidth(qWidth)
|
||||
self.quoteSym["SC"].setAlignment(Qt.AlignCenter)
|
||||
self.quoteSym["SC"].setText(self.mainConf.fmtSingleQuotes[1])
|
||||
self.btnSingleStyleC = QPushButton("...")
|
||||
self.btnSingleStyleC.setMaximumWidth(bWidth)
|
||||
self.btnSingleStyleC.clicked.connect(self._getSingleClose)
|
||||
self.btnSingleStyleC.clicked.connect(lambda: self._getQuote("SC"))
|
||||
self.mainForm.addRow(
|
||||
"Single quote close style",
|
||||
self.quoteSingleStyleC,
|
||||
self.quoteSym["SC"],
|
||||
"Auto-replaces apostrophe after words.",
|
||||
theButton=self.btnSingleStyleC
|
||||
)
|
||||
|
||||
## Double Quote Style
|
||||
self.quoteDoubleStyleO = QLineEdit()
|
||||
self.quoteDoubleStyleO.setMaxLength(1)
|
||||
self.quoteDoubleStyleO.setReadOnly(True)
|
||||
self.quoteDoubleStyleO.setFixedWidth(qWidth)
|
||||
self.quoteDoubleStyleO.setAlignment(Qt.AlignCenter)
|
||||
self.quoteDoubleStyleO.setText(self.mainConf.fmtDoubleQuotes[0])
|
||||
self.quoteSym["DO"] = QLineEdit()
|
||||
self.quoteSym["DO"].setMaxLength(1)
|
||||
self.quoteSym["DO"].setReadOnly(True)
|
||||
self.quoteSym["DO"].setFixedWidth(qWidth)
|
||||
self.quoteSym["DO"].setAlignment(Qt.AlignCenter)
|
||||
self.quoteSym["DO"].setText(self.mainConf.fmtDoubleQuotes[0])
|
||||
self.btnDoubleStyleO = QPushButton("...")
|
||||
self.btnDoubleStyleO.setMaximumWidth(bWidth)
|
||||
self.btnDoubleStyleO.clicked.connect(self._getDoubleOpen)
|
||||
self.btnDoubleStyleO.clicked.connect(lambda: self._getQuote("DO"))
|
||||
self.mainForm.addRow(
|
||||
"Double quote open style",
|
||||
self.quoteDoubleStyleO,
|
||||
self.quoteSym["DO"],
|
||||
"Auto-replaces straight quotes before words.",
|
||||
theButton=self.btnDoubleStyleO
|
||||
)
|
||||
|
||||
self.quoteDoubleStyleC = QLineEdit()
|
||||
self.quoteDoubleStyleC.setMaxLength(1)
|
||||
self.quoteDoubleStyleC.setReadOnly(True)
|
||||
self.quoteDoubleStyleC.setFixedWidth(qWidth)
|
||||
self.quoteDoubleStyleC.setAlignment(Qt.AlignCenter)
|
||||
self.quoteDoubleStyleC.setText(self.mainConf.fmtDoubleQuotes[1])
|
||||
self.quoteSym["DC"] = QLineEdit()
|
||||
self.quoteSym["DC"].setMaxLength(1)
|
||||
self.quoteSym["DC"].setReadOnly(True)
|
||||
self.quoteSym["DC"].setFixedWidth(qWidth)
|
||||
self.quoteSym["DC"].setAlignment(Qt.AlignCenter)
|
||||
self.quoteSym["DC"].setText(self.mainConf.fmtDoubleQuotes[1])
|
||||
self.btnDoubleStyleC = QPushButton("...")
|
||||
self.btnDoubleStyleC.setMaximumWidth(bWidth)
|
||||
self.btnDoubleStyleC.clicked.connect(self._getDoubleClose)
|
||||
self.btnDoubleStyleC.clicked.connect(lambda: self._getQuote("DC"))
|
||||
self.mainForm.addRow(
|
||||
"Double quote close style",
|
||||
self.quoteDoubleStyleC,
|
||||
self.quoteSym["DC"],
|
||||
"Auto-replaces straight quotes after words.",
|
||||
theButton=self.btnDoubleStyleC
|
||||
)
|
||||
@@ -906,10 +906,10 @@ class GuiConfigEditAutoReplaceTab(QWidget):
|
||||
self.mainConf.doReplaceDash = doReplaceDash
|
||||
self.mainConf.doReplaceDots = doReplaceDots
|
||||
|
||||
fmtSingleQuotesO = self.quoteSingleStyleO.text()
|
||||
fmtSingleQuotesC = self.quoteSingleStyleC.text()
|
||||
fmtDoubleQuotesO = self.quoteDoubleStyleO.text()
|
||||
fmtDoubleQuotesC = self.quoteDoubleStyleC.text()
|
||||
fmtSingleQuotesO = self.quoteSym["SO"].text()
|
||||
fmtSingleQuotesC = self.quoteSym["SC"].text()
|
||||
fmtDoubleQuotesO = self.quoteSym["DO"].text()
|
||||
fmtDoubleQuotesC = self.quoteSym["DC"].text()
|
||||
|
||||
self.mainConf.fmtSingleQuotes[0] = fmtSingleQuotesO
|
||||
self.mainConf.fmtSingleQuotes[1] = fmtSingleQuotesC
|
||||
@@ -934,50 +934,12 @@ class GuiConfigEditAutoReplaceTab(QWidget):
|
||||
self.autoReplaceDots.setEnabled(theState)
|
||||
return
|
||||
|
||||
def _getSingleOpen(self):
|
||||
def _getQuote(self, qType):
|
||||
"""Dialog for single quote open.
|
||||
"""
|
||||
qtBox = QuotesDialog(self, currentQuote=self.quoteSingleStyleO.text())
|
||||
qtBox = QuotesDialog(self, currentQuote=self.quoteSym[qType].text())
|
||||
if qtBox.exec_() == QDialog.Accepted:
|
||||
self.quoteSingleStyleO.setText(qtBox.selectedQuote)
|
||||
self.quoteSym[qType].setText(qtBox.selectedQuote)
|
||||
return
|
||||
|
||||
def _getSingleClose(self):
|
||||
"""Dialog for single quote close.
|
||||
"""
|
||||
qtBox = QuotesDialog(self, currentQuote=self.quoteSingleStyleC.text())
|
||||
if qtBox.exec_() == QDialog.Accepted:
|
||||
self.quoteSingleStyleC.setText(qtBox.selectedQuote)
|
||||
return
|
||||
|
||||
def _getDoubleOpen(self):
|
||||
"""Dialog for double quote open.
|
||||
"""
|
||||
qtBox = QuotesDialog(self, currentQuote=self.quoteDoubleStyleO.text())
|
||||
if qtBox.exec_() == QDialog.Accepted:
|
||||
self.quoteDoubleStyleO.setText(qtBox.selectedQuote)
|
||||
return
|
||||
|
||||
def _getDoubleClose(self):
|
||||
"""Dialog for double quote close.
|
||||
"""
|
||||
qtBox = QuotesDialog(self, currentQuote=self.quoteDoubleStyleC.text())
|
||||
if qtBox.exec_() == QDialog.Accepted:
|
||||
self.quoteDoubleStyleC.setText(qtBox.selectedQuote)
|
||||
return
|
||||
|
||||
##
|
||||
# Internal Functions
|
||||
##
|
||||
|
||||
def _checkQuoteSymbol(self, toCheck):
|
||||
"""Check that the quote symbols entered are in nwQuotes and is
|
||||
therefore a valid quote symbol for this app.
|
||||
"""
|
||||
if len(toCheck) != 1:
|
||||
return False
|
||||
if toCheck in nwQuotes.SYMBOLS:
|
||||
return True
|
||||
return False
|
||||
|
||||
# END Class GuiConfigEditAutoReplaceTab
|
||||
|
||||
+14
-6
@@ -855,24 +855,32 @@ class GuiMain(QMainWindow):
|
||||
popMsg = theMessage
|
||||
logMsg = [theMessage]
|
||||
|
||||
msgBox = QMessageBox()
|
||||
# Write to Log
|
||||
if theLevel == nwAlert.INFO:
|
||||
for msgLine in logMsg:
|
||||
logger.info(msgLine)
|
||||
msgBox.information(self, "Information", popMsg)
|
||||
elif theLevel == nwAlert.WARN:
|
||||
for msgLine in logMsg:
|
||||
logger.warning(msgLine)
|
||||
msgBox.warning(self, "Warning", popMsg)
|
||||
elif theLevel == nwAlert.ERROR:
|
||||
for msgLine in logMsg:
|
||||
logger.error(msgLine)
|
||||
msgBox.critical(self, "Error", popMsg)
|
||||
elif theLevel == nwAlert.BUG:
|
||||
for msgLine in logMsg:
|
||||
logger.error(msgLine)
|
||||
popMsg += "<br>This is a bug!"
|
||||
msgBox.critical(self, "Internal Error", popMsg)
|
||||
|
||||
# Popup
|
||||
if self.mainConf.showGUI:
|
||||
msgBox = QMessageBox()
|
||||
if theLevel == nwAlert.INFO:
|
||||
msgBox.information(self, "Information", popMsg)
|
||||
elif theLevel == nwAlert.WARN:
|
||||
msgBox.warning(self, "Warning", popMsg)
|
||||
elif theLevel == nwAlert.ERROR:
|
||||
msgBox.critical(self, "Error", popMsg)
|
||||
elif theLevel == nwAlert.BUG:
|
||||
popMsg += "<br>This is a bug!"
|
||||
msgBox.critical(self, "Internal Error", popMsg)
|
||||
|
||||
return
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
[pytest]
|
||||
markers =
|
||||
project: Project classes tests
|
||||
error: Test various error handling scenarios
|
||||
core: Core functionality tests
|
||||
gui: Qt5 GUI tests
|
||||
serial
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ def nwConf(nwRef, nwTemp):
|
||||
return theConf
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def tmpConf(nwRef, nwTemp):
|
||||
def tmpConf(nwTemp):
|
||||
theConf = Config()
|
||||
theConf.initConfig(nwTemp, nwTemp)
|
||||
theConf.setLastPath("")
|
||||
|
||||
@@ -10,6 +10,7 @@ class DummyMain():
|
||||
return
|
||||
|
||||
def makeAlert(self, theMessage, theLevel):
|
||||
print("%s: %s" % (str(theLevel), theMessage))
|
||||
return
|
||||
|
||||
def setStatus(self, theMessage):
|
||||
|
||||
@@ -67,3 +67,4 @@ def getGuiItem(theName):
|
||||
for qWidget in qApp.topLevelWidgets():
|
||||
if qWidget.objectName() == theName:
|
||||
return qWidget
|
||||
return None
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
[Main]
|
||||
timestamp = 2020-06-29 17:34:15
|
||||
theme = default
|
||||
syntax = default_light
|
||||
icons = typicons_colour_light
|
||||
guidark = True
|
||||
guifont = Cantarell
|
||||
guifontsize = 12
|
||||
|
||||
[Sizes]
|
||||
geometry = 1100, 650
|
||||
treecols = 120, 30, 50
|
||||
projcols = 140, 55, 140
|
||||
mainpane = 300, 800
|
||||
docpane = 400, 400
|
||||
viewpane = 500, 150
|
||||
outlinepane = 500, 150
|
||||
fullscreen = False
|
||||
|
||||
[Project]
|
||||
autosaveproject = 40
|
||||
autosavedoc = 20
|
||||
|
||||
[Editor]
|
||||
textfont = Cantarell
|
||||
textsize = 13
|
||||
fixedwidth = False
|
||||
width = 700
|
||||
margin = 45
|
||||
tabwidth = 45
|
||||
focuswidth = 900
|
||||
hidefocusfooter = True
|
||||
justify = False
|
||||
autoselect = False
|
||||
autoreplace = False
|
||||
repsquotes = True
|
||||
repdquotes = True
|
||||
repdash = True
|
||||
repdots = True
|
||||
fmtsinglequote = ‘, ’
|
||||
fmtdoublequote = “, ”
|
||||
spelltool = internal
|
||||
spellcheck = en
|
||||
showtabsnspaces = True
|
||||
showlineendings = True
|
||||
bigdoclimit = 500
|
||||
showfullpath = False
|
||||
highlightquotes = False
|
||||
highlightemph = False
|
||||
|
||||
[Backup]
|
||||
backuppath =
|
||||
backuponclose = True
|
||||
askbeforebackup = True
|
||||
|
||||
[State]
|
||||
showrefpanel = False
|
||||
viewcomments = True
|
||||
viewsynopsis = True
|
||||
searchcase = False
|
||||
searchword = False
|
||||
searchregex = False
|
||||
searchloop = False
|
||||
searchnextfile = False
|
||||
searchmatchcap = False
|
||||
|
||||
[Path]
|
||||
lastpath =
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
"""novelWriter Common Class Tester
|
||||
"""
|
||||
|
||||
import time
|
||||
import pytest
|
||||
|
||||
from nw.common import (
|
||||
checkString, checkBool, checkInt, colRange, formatInt, transferCase,
|
||||
fuzzyTime, checkHandle
|
||||
fuzzyTime, checkHandle, formatTimeStamp
|
||||
)
|
||||
from nwtools import cmpList
|
||||
|
||||
@@ -75,6 +77,12 @@ def testColRange():
|
||||
[[200, 50, 0], [162, 87, 0], [124, 124, 0], [86, 161, 0], [50, 200, 0]]
|
||||
)
|
||||
|
||||
@pytest.mark.core
|
||||
def testFormatTime():
|
||||
tTime = time.mktime(time.gmtime(0))
|
||||
assert formatTimeStamp(tTime, False) == "1970-01-01 00:00:00"
|
||||
assert formatTimeStamp(tTime, True) == "1970-01-01 00.00.00"
|
||||
|
||||
@pytest.mark.core
|
||||
def testFormatInt():
|
||||
assert formatInt(1000) == "1000"
|
||||
|
||||
+54
-4
@@ -40,6 +40,7 @@ def testConfigSetDataPath(tmpConf, nwTemp):
|
||||
def testConfigSetWinSize(tmpConf, nwTemp, nwRef):
|
||||
refConf = path.join(nwRef, "novelwriter.conf")
|
||||
testConf = path.join(tmpConf.confPath, "novelwriter.conf")
|
||||
tmpConf.guiScale = 1.0
|
||||
|
||||
assert tmpConf.confPath == nwTemp
|
||||
assert tmpConf.setWinSize(1105, 655)
|
||||
@@ -58,10 +59,17 @@ def testConfigSetTreeColWidths(tmpConf, nwTemp, nwRef):
|
||||
testConf = path.join(tmpConf.confPath, "novelwriter.conf")
|
||||
|
||||
assert tmpConf.confPath == nwTemp
|
||||
assert tmpConf.setTreeColWidths([0, 0, 0])
|
||||
assert tmpConf.confChanged
|
||||
tmpConf.guiScale = 1.0
|
||||
|
||||
assert tmpConf.setTreeColWidths([10, 20, 30])
|
||||
assert tmpConf.treeColWidth == [10, 20, 30]
|
||||
assert tmpConf.setTreeColWidths([120, 30, 50])
|
||||
|
||||
assert tmpConf.setProjColWidths([10, 20, 30])
|
||||
assert tmpConf.projColWidth == [10, 20, 30]
|
||||
assert tmpConf.setProjColWidths([140, 55, 140])
|
||||
|
||||
assert tmpConf.confChanged
|
||||
assert tmpConf.saveConfig()
|
||||
|
||||
assert cmpFiles(testConf, refConf, [2])
|
||||
@@ -73,12 +81,31 @@ def testConfigSetPanePos(tmpConf, nwTemp, nwRef):
|
||||
testConf = path.join(tmpConf.confPath, "novelwriter.conf")
|
||||
|
||||
assert tmpConf.confPath == nwTemp
|
||||
assert tmpConf.setMainPanePos([0, 0])
|
||||
assert tmpConf.confChanged
|
||||
|
||||
tmpConf.guiScale = 2.0
|
||||
assert tmpConf.setMainPanePos([200, 700])
|
||||
assert tmpConf.mainPanePos == [100, 350]
|
||||
assert tmpConf.getMainPanePos() == [200, 700]
|
||||
|
||||
assert tmpConf.setDocPanePos([300, 300])
|
||||
assert tmpConf.docPanePos == [150, 150]
|
||||
assert tmpConf.getDocPanePos() == [300, 300]
|
||||
|
||||
assert tmpConf.setViewPanePos([400, 250])
|
||||
assert tmpConf.viewPanePos == [200, 125]
|
||||
assert tmpConf.getViewPanePos() == [400, 250]
|
||||
|
||||
assert tmpConf.setOutlinePanePos([400, 250])
|
||||
assert tmpConf.outlnPanePos == [200, 125]
|
||||
assert tmpConf.getOutlinePanePos() == [400, 250]
|
||||
|
||||
tmpConf.guiScale = 1.0
|
||||
assert tmpConf.setMainPanePos([300, 800])
|
||||
assert tmpConf.setDocPanePos([400, 400])
|
||||
assert tmpConf.setViewPanePos([500, 150])
|
||||
assert tmpConf.setOutlinePanePos([500, 150])
|
||||
|
||||
assert tmpConf.confChanged
|
||||
assert tmpConf.saveConfig()
|
||||
|
||||
assert cmpFiles(testConf, refConf, [2])
|
||||
@@ -90,14 +117,37 @@ def testConfigFlags(tmpConf, nwTemp, nwRef):
|
||||
testConf = path.join(tmpConf.confPath, "novelwriter.conf")
|
||||
|
||||
assert tmpConf.confPath == nwTemp
|
||||
|
||||
assert not tmpConf.setShowRefPanel(False)
|
||||
assert tmpConf.setShowRefPanel(True)
|
||||
|
||||
assert not tmpConf.setViewComments(False)
|
||||
assert not tmpConf.viewComments
|
||||
assert tmpConf.setViewComments(True)
|
||||
|
||||
assert not tmpConf.setViewSynopsis(False)
|
||||
assert not tmpConf.viewSynopsis
|
||||
assert tmpConf.setViewSynopsis(True)
|
||||
|
||||
assert tmpConf.confChanged
|
||||
assert tmpConf.saveConfig()
|
||||
|
||||
assert cmpFiles(testConf, refConf, [2])
|
||||
assert not tmpConf.confChanged
|
||||
|
||||
@pytest.mark.core
|
||||
def testTextSizes(tmpConf, nwTemp, nwRef):
|
||||
assert tmpConf.confPath == nwTemp
|
||||
|
||||
tmpConf.guiScale = 2.0
|
||||
assert tmpConf.getTextWidth() == 1200
|
||||
assert tmpConf.getTextMargin() == 80
|
||||
assert tmpConf.getTabWidth() == 80
|
||||
assert tmpConf.getFocusWidth() == 1600
|
||||
tmpConf.guiScale = 1.0
|
||||
|
||||
assert not tmpConf.confChanged
|
||||
|
||||
@pytest.mark.core
|
||||
def testConfigErrors(tmpConf):
|
||||
nonPath = path.join("somewhere", "over", "the", "rainbow")
|
||||
|
||||
@@ -0,0 +1,915 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""novelWriter Dialog Class Tester
|
||||
"""
|
||||
|
||||
import nw
|
||||
import pytest
|
||||
import json
|
||||
from shutil import copyfile
|
||||
from nwtools import cmpFiles
|
||||
|
||||
from os import path
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import QDialogButtonBox, QTreeWidgetItem
|
||||
|
||||
from nw.gui import (
|
||||
GuiProjectSettings, GuiItemEditor, GuiAbout, GuiBuildNovel,
|
||||
GuiDocMerge, GuiDocSplit, GuiWritingStats, GuiProjectWizard,
|
||||
GuiProjectLoad, GuiPreferences
|
||||
)
|
||||
from nw.constants import nwItemType, nwItemLayout, nwItemClass
|
||||
|
||||
keyDelay = 2
|
||||
stepDelay = 20
|
||||
|
||||
@pytest.mark.gui
|
||||
def testProjectEditor(qtbot, nwFuncTemp, nwTempGUI, nwRef, nwTemp):
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwFuncTemp, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
# Create new, save, open project
|
||||
nwGUI.theProject.projTree.setSeed(42)
|
||||
assert nwGUI.newProject({"projPath": nwFuncTemp}, True)
|
||||
nwGUI.mainConf.backupPath = nwFuncTemp
|
||||
|
||||
projEdit = GuiProjectSettings(nwGUI, nwGUI.theProject)
|
||||
projEdit.show()
|
||||
qtbot.addWidget(projEdit)
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
projEdit.tabMain.editName.setText("")
|
||||
for c in "Project Name":
|
||||
qtbot.keyClick(projEdit.tabMain.editName, c, delay=keyDelay)
|
||||
for c in "Project Title":
|
||||
qtbot.keyClick(projEdit.tabMain.editTitle, c, delay=keyDelay)
|
||||
for c in "Jane Doe":
|
||||
qtbot.keyClick(projEdit.tabMain.editAuthors, c, delay=keyDelay)
|
||||
qtbot.keyClick(projEdit.tabMain.editAuthors, Qt.Key_Return, delay=keyDelay)
|
||||
for c in "John Doh":
|
||||
qtbot.keyClick(projEdit.tabMain.editAuthors, c, delay=keyDelay)
|
||||
|
||||
# Test Status Tab
|
||||
qtbot.wait(stepDelay)
|
||||
projEdit._tabBox.setCurrentWidget(projEdit.tabStatus)
|
||||
projEdit.tabStatus.listBox.item(2).setSelected(True)
|
||||
qtbot.mouseClick(projEdit.tabStatus.delButton, Qt.LeftButton)
|
||||
qtbot.mouseClick(projEdit.tabStatus.newButton, Qt.LeftButton)
|
||||
projEdit.tabStatus.listBox.item(3).setSelected(True)
|
||||
for n in range(8):
|
||||
qtbot.keyClick(projEdit.tabStatus.editName, Qt.Key_Backspace, delay=keyDelay)
|
||||
for c in "Final":
|
||||
qtbot.keyClick(projEdit.tabStatus.editName, c, delay=keyDelay)
|
||||
qtbot.mouseClick(projEdit.tabStatus.saveButton, Qt.LeftButton)
|
||||
|
||||
# Auto-Replace Tab
|
||||
qtbot.wait(stepDelay)
|
||||
projEdit._tabBox.setCurrentWidget(projEdit.tabReplace)
|
||||
|
||||
qtbot.mouseClick(projEdit.tabReplace.addButton, Qt.LeftButton)
|
||||
projEdit.tabReplace.listBox.topLevelItem(0).setSelected(True)
|
||||
for c in "Th is ":
|
||||
qtbot.keyClick(projEdit.tabReplace.editKey, c, delay=keyDelay)
|
||||
for c in "With This Stuff ":
|
||||
qtbot.keyClick(projEdit.tabReplace.editValue, c, delay=keyDelay)
|
||||
qtbot.mouseClick(projEdit.tabReplace.saveButton, Qt.LeftButton)
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
projEdit.tabReplace.listBox.clearSelection()
|
||||
qtbot.mouseClick(projEdit.tabReplace.addButton, Qt.LeftButton)
|
||||
|
||||
newIdx = -1
|
||||
for i in range(projEdit.tabReplace.listBox.topLevelItemCount()):
|
||||
if projEdit.tabReplace.listBox.topLevelItem(i).text(0) == "<keyword2>":
|
||||
newIdx = i
|
||||
break
|
||||
|
||||
assert newIdx >= 0
|
||||
newItem = projEdit.tabReplace.listBox.topLevelItem(newIdx)
|
||||
projEdit.tabReplace.listBox.setCurrentItem(newItem)
|
||||
qtbot.mouseClick(projEdit.tabReplace.delButton, Qt.LeftButton)
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
projEdit._doSave()
|
||||
|
||||
# Open again, and check project settings
|
||||
projEdit = GuiProjectSettings(nwGUI, nwGUI.theProject)
|
||||
qtbot.addWidget(projEdit)
|
||||
assert projEdit.tabMain.editName.text() == "Project Name"
|
||||
assert projEdit.tabMain.editTitle.text() == "Project Title"
|
||||
theAuth = projEdit.tabMain.editAuthors.toPlainText().strip().splitlines()
|
||||
assert len(theAuth) == 2
|
||||
assert theAuth[0] == "Jane Doe"
|
||||
assert theAuth[1] == "John Doh"
|
||||
|
||||
projEdit._doClose()
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
assert nwGUI.saveProject()
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
# Check the files
|
||||
projFile = path.join(nwFuncTemp, "nwProject.nwx")
|
||||
testFile = path.join(nwTempGUI, "2_nwProject.nwx")
|
||||
refFile = path.join(nwRef, "gui", "2_nwProject.nwx")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile, [2, 8, 9, 10])
|
||||
|
||||
# qtbot.stopForInteraction()
|
||||
nwGUI.closeMain()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testItemEditor(qtbot, nwFuncTemp, nwTempGUI, nwRef, nwTemp):
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwFuncTemp, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
# Create new, save, open project
|
||||
nwGUI.theProject.projTree.setSeed(42)
|
||||
assert nwGUI.newProject({"projPath": nwFuncTemp}, True)
|
||||
assert nwGUI.openDocument("0e17daca5f3e1")
|
||||
|
||||
itemEdit = GuiItemEditor(nwGUI, nwGUI.theProject, "0e17daca5f3e1")
|
||||
qtbot.addWidget(itemEdit)
|
||||
|
||||
assert itemEdit.editName.text() == "New Scene"
|
||||
assert itemEdit.editStatus.currentData() == "New"
|
||||
assert itemEdit.editLayout.currentData() == nwItemLayout.SCENE
|
||||
|
||||
for c in "Just a Page":
|
||||
qtbot.keyClick(itemEdit.editName, c, delay=keyDelay)
|
||||
itemEdit.editStatus.setCurrentIndex(1)
|
||||
layoutIdx = itemEdit.editLayout.findData(nwItemLayout.PAGE)
|
||||
itemEdit.editLayout.setCurrentIndex(layoutIdx)
|
||||
|
||||
itemEdit.editExport.setChecked(False)
|
||||
assert not itemEdit.editExport.isChecked()
|
||||
itemEdit._doSave()
|
||||
|
||||
itemEdit = GuiItemEditor(nwGUI, nwGUI.theProject, "0e17daca5f3e1")
|
||||
qtbot.addWidget(itemEdit)
|
||||
assert itemEdit.editName.text() == "Just a Page"
|
||||
assert itemEdit.editStatus.currentData() == "Note"
|
||||
assert itemEdit.editLayout.currentData() == nwItemLayout.PAGE
|
||||
itemEdit._doClose()
|
||||
|
||||
# Check that the header is updated
|
||||
nwGUI.docEditor.updateDocInfo("0e17daca5f3e1")
|
||||
assert nwGUI.docEditor.docHeader.theTitle.text() == "Novel › New Chapter › Just a Page"
|
||||
assert not nwGUI.docEditor.setCursorLine("where?")
|
||||
assert nwGUI.docEditor.setCursorLine(2)
|
||||
qtbot.wait(stepDelay)
|
||||
assert nwGUI.docEditor.getCursorPosition() == 15
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
assert nwGUI.saveProject()
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
# Check the files
|
||||
projFile = path.join(nwFuncTemp, "nwProject.nwx")
|
||||
testFile = path.join(nwTempGUI, "3_nwProject.nwx")
|
||||
refFile = path.join(nwRef, "gui", "3_nwProject.nwx")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile, [2, 6, 7, 8])
|
||||
|
||||
nwGUI.closeMain()
|
||||
# qtbot.stopForInteraction()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testWritingStatsExport(qtbot, nwFuncTemp, nwTemp):
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwFuncTemp, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
# Create new, save, close project
|
||||
nwGUI.theProject.projTree.setSeed(42)
|
||||
assert nwGUI.newProject({"projPath": nwFuncTemp}, True)
|
||||
assert nwGUI.saveProject()
|
||||
assert nwGUI.closeProject()
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
assert nwGUI.openProject(nwFuncTemp)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
# Add some text to the scene file
|
||||
assert nwGUI.openDocument("0e17daca5f3e1")
|
||||
assert nwGUI.docEditor.insertText(
|
||||
"# Scene One\n\n"
|
||||
"It was the best of times, it was the worst of times, it was the age of wisdom, it was "
|
||||
"the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it "
|
||||
"was the season of Light, it was the season of Darkness, it was the spring of hope, it "
|
||||
"was the winter of despair, we had everything before us, we had nothing before us, we "
|
||||
"were all going direct to Heaven, we were all going direct the other way – in short, the "
|
||||
"period was so far like the present period, that some of its noisiest authorities "
|
||||
"insisted on its being received, for good or for evil, in the superlative degree of "
|
||||
"comparison only.\n\n"
|
||||
)
|
||||
assert nwGUI.saveDocument()
|
||||
|
||||
# Add a note file with some text
|
||||
nwGUI.setFocus(1)
|
||||
nwGUI.treeView.clearSelection()
|
||||
nwGUI.treeView._getTreeItem("71ee45a3c0db9").setSelected(True)
|
||||
nwGUI.treeView.newTreeItem(nwItemType.FILE, None)
|
||||
assert nwGUI.openSelectedItem()
|
||||
assert nwGUI.docEditor.insertText(
|
||||
"# Jane Doe\n\n"
|
||||
"All about Jane.\n\n"
|
||||
)
|
||||
assert nwGUI.saveDocument()
|
||||
qtbot.wait(500) # Ensures that the session length is > 0
|
||||
|
||||
assert nwGUI.saveProject()
|
||||
assert nwGUI.closeProject()
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
# Open again, and check the stats
|
||||
assert nwGUI.openProject(nwFuncTemp)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
nwGUI.mainConf.lastPath = nwFuncTemp
|
||||
sessLog = GuiWritingStats(nwGUI, nwGUI.theProject)
|
||||
sessLog.show()
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
assert sessLog._saveData(sessLog.FMT_CSV)
|
||||
qtbot.wait(stepDelay)
|
||||
assert sessLog._saveData(sessLog.FMT_JSON)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
jsonStats = path.join(nwFuncTemp, "sessionStats.json")
|
||||
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
|
||||
jsonData = json.loads(inFile.read())
|
||||
|
||||
assert len(jsonData) == 2
|
||||
assert jsonData[1]["length"] >= 0
|
||||
assert jsonData[1]["newWords"] == 126
|
||||
assert jsonData[1]["novelWords"] == 127
|
||||
assert jsonData[1]["noteWords"] == 5
|
||||
|
||||
# No Novel Files
|
||||
qtbot.mouseClick(sessLog.incNovel, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
assert sessLog._saveData(sessLog.FMT_JSON)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
jsonStats = path.join(nwFuncTemp, "sessionStats.json")
|
||||
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
|
||||
jsonData = json.loads(inFile.read())
|
||||
|
||||
assert len(jsonData) == 1
|
||||
assert jsonData[0]["length"] >= 0
|
||||
assert jsonData[0]["newWords"] == 5
|
||||
assert jsonData[0]["novelWords"] == 127
|
||||
assert jsonData[0]["noteWords"] == 5
|
||||
|
||||
# No Note Files
|
||||
qtbot.mouseClick(sessLog.incNovel, Qt.LeftButton)
|
||||
qtbot.mouseClick(sessLog.incNotes, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
assert sessLog._saveData(sessLog.FMT_JSON)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
jsonStats = path.join(nwFuncTemp, "sessionStats.json")
|
||||
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
|
||||
jsonData = json.loads(inFile.read())
|
||||
|
||||
assert len(jsonData) == 2
|
||||
assert jsonData[1]["length"] >= 0
|
||||
assert jsonData[1]["newWords"] == 121
|
||||
assert jsonData[1]["novelWords"] == 127
|
||||
assert jsonData[1]["noteWords"] == 5
|
||||
|
||||
# No Negative Entries
|
||||
qtbot.mouseClick(sessLog.incNotes, Qt.LeftButton)
|
||||
qtbot.mouseClick(sessLog.hideNegative, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
assert sessLog._saveData(sessLog.FMT_JSON)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
jsonStats = path.join(nwFuncTemp, "sessionStats.json")
|
||||
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
|
||||
jsonData = json.loads(inFile.read())
|
||||
|
||||
assert len(jsonData) == 2
|
||||
|
||||
# Un-hide Zero Entries
|
||||
qtbot.mouseClick(sessLog.hideNegative, Qt.LeftButton)
|
||||
qtbot.mouseClick(sessLog.hideZeros, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
assert sessLog._saveData(sessLog.FMT_JSON)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
jsonStats = path.join(nwFuncTemp, "sessionStats.json")
|
||||
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
|
||||
jsonData = json.loads(inFile.read())
|
||||
|
||||
assert len(jsonData) == 2
|
||||
|
||||
# Group by Day
|
||||
qtbot.mouseClick(sessLog.groupByDay, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
assert sessLog._saveData(sessLog.FMT_JSON)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
jsonStats = path.join(nwFuncTemp, "sessionStats.json")
|
||||
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
|
||||
jsonData = json.loads(inFile.read())
|
||||
|
||||
# Check against both 1 and 2 as this can be 2 if test was started just before midnight.
|
||||
# A failed test should in any case produce a 4
|
||||
assert len(jsonData) in (1, 2)
|
||||
|
||||
# qtbot.stopForInteraction()
|
||||
|
||||
sessLog._doClose()
|
||||
nwGUI.closeMain()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testAboutBox(qtbot, nwFuncTemp, nwTemp):
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwFuncTemp, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
msgAbout = GuiAbout(nwGUI)
|
||||
assert msgAbout.pageAbout.document().characterCount() > 100
|
||||
assert msgAbout.pageLicense.document().characterCount() > 100
|
||||
|
||||
# qtbot.stopForInteraction()
|
||||
msgAbout._doClose()
|
||||
nwGUI.closeMain()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testBuildTool(qtbot, nwTempBuild, nwLipsum, nwRef, nwTemp):
|
||||
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwLipsum, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
assert nwGUI.openProject(nwLipsum)
|
||||
|
||||
nwGUI.mainConf.lastPath = nwLipsum
|
||||
|
||||
nwBuild = GuiBuildNovel(nwGUI, nwGUI.theProject)
|
||||
|
||||
# Default Settings
|
||||
qtbot.mouseClick(nwBuild.buildNovel, Qt.LeftButton)
|
||||
|
||||
assert nwBuild._saveDocument(nwBuild.FMT_NWD)
|
||||
assert nwBuild._saveDocument(nwBuild.FMT_HTM)
|
||||
|
||||
projFile = path.join(nwLipsum, "Lorem Ipsum.nwd")
|
||||
testFile = path.join(nwTempBuild, "1_LoremIpsum.nwd")
|
||||
refFile = path.join(nwRef, "build", "1_LoremIpsum.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
projFile = path.join(nwLipsum, "Lorem Ipsum.htm")
|
||||
testFile = path.join(nwTempBuild, "1_LoremIpsum.htm")
|
||||
refFile = path.join(nwRef, "build", "1_LoremIpsum.htm")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
# Change Title Formats and Flip Switches
|
||||
nwBuild.fmtChapter.setText(r"Chapter %chw%: %title%")
|
||||
qtbot.wait(stepDelay)
|
||||
nwBuild.fmtScene.setText(r"Scene %ch%.%sc%: %title%")
|
||||
qtbot.wait(stepDelay)
|
||||
nwBuild.fmtSection.setText(r"%ch%.%sc%.1: %title%")
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
qtbot.mouseClick(nwBuild.justifyText, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwBuild.includeSynopsis, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwBuild.includeComments, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwBuild.includeKeywords, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
qtbot.mouseClick(nwBuild.noteFiles, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwBuild.ignoreFlag, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
qtbot.mouseClick(nwBuild.buildNovel, Qt.LeftButton)
|
||||
|
||||
assert nwBuild._saveDocument(nwBuild.FMT_NWD)
|
||||
assert nwBuild._saveDocument(nwBuild.FMT_HTM)
|
||||
|
||||
projFile = path.join(nwLipsum, "Lorem Ipsum.nwd")
|
||||
testFile = path.join(nwTempBuild, "2_LoremIpsum.nwd")
|
||||
refFile = path.join(nwRef, "build", "2_LoremIpsum.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
projFile = path.join(nwLipsum, "Lorem Ipsum.htm")
|
||||
testFile = path.join(nwTempBuild, "2_LoremIpsum.htm")
|
||||
refFile = path.join(nwRef, "build", "2_LoremIpsum.htm")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
# Putline Mode
|
||||
nwBuild.fmtChapter.setText(r"Chapter %chw%: %title%")
|
||||
qtbot.wait(stepDelay)
|
||||
nwBuild.fmtScene.setText(r"Scene %sca%: %title%")
|
||||
qtbot.wait(stepDelay)
|
||||
nwBuild.fmtSection.setText(r"Section: %title%")
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
qtbot.mouseClick(nwBuild.includeComments, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwBuild.noteFiles, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwBuild.ignoreFlag, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwBuild.includeBody, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
qtbot.mouseClick(nwBuild.buildNovel, Qt.LeftButton)
|
||||
|
||||
assert nwBuild._saveDocument(nwBuild.FMT_NWD)
|
||||
assert nwBuild._saveDocument(nwBuild.FMT_HTM)
|
||||
|
||||
projFile = path.join(nwLipsum, "Lorem Ipsum.nwd")
|
||||
testFile = path.join(nwTempBuild, "3_LoremIpsum.nwd")
|
||||
refFile = path.join(nwRef, "build", "3_LoremIpsum.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
projFile = path.join(nwLipsum, "Lorem Ipsum.htm")
|
||||
testFile = path.join(nwTempBuild, "3_LoremIpsum.htm")
|
||||
refFile = path.join(nwRef, "build", "3_LoremIpsum.htm")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
# qtbot.stopForInteraction()
|
||||
nwBuild._doClose()
|
||||
nwGUI.closeMain()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testMergeSplitTools(qtbot, nwTempGUI, nwLipsum, nwRef, nwTemp):
|
||||
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwLipsum, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
nwGUI.theProject.projTree.setSeed(42)
|
||||
assert nwGUI.openProject(nwLipsum)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
assert nwGUI.treeView.setSelectedHandle("45e6b01ca35c1")
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
nwMerge = GuiDocMerge(nwGUI, nwGUI.theProject)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
nwMerge._doMerge()
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
assert nwGUI.theProject.projTree["73475cb40a568"] is not None
|
||||
|
||||
projFile = path.join(nwLipsum, "content", "73475cb40a568.nwd")
|
||||
testFile = path.join(nwTempGUI, "4_73475cb40a568.nwd")
|
||||
refFile = path.join(nwRef, "gui", "4_73475cb40a568.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
# Split By Chapter
|
||||
assert nwGUI.treeView.setSelectedHandle("73475cb40a568")
|
||||
qtbot.wait(stepDelay)
|
||||
nwSplit = GuiDocSplit(nwGUI, nwGUI.theProject)
|
||||
qtbot.wait(stepDelay)
|
||||
nwSplit.splitLevel.setCurrentIndex(1)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
nwSplit._doSplit()
|
||||
assert nwGUI.theProject.projTree["71ee45a3c0db9"] is not None
|
||||
|
||||
# This should give us back the file as it was before
|
||||
projFile = path.join(nwLipsum, "content", "71ee45a3c0db9.nwd")
|
||||
testFile = path.join(nwTempGUI, "4_71ee45a3c0db9.nwd")
|
||||
refFile = path.join(nwRef, "gui", "4_73475cb40a568.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile, [1])
|
||||
|
||||
# Split By Scene
|
||||
assert nwGUI.treeView.setSelectedHandle("73475cb40a568")
|
||||
qtbot.wait(stepDelay)
|
||||
nwSplit = GuiDocSplit(nwGUI, nwGUI.theProject)
|
||||
qtbot.wait(stepDelay)
|
||||
nwSplit.splitLevel.setCurrentIndex(2)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
nwSplit._doSplit()
|
||||
|
||||
assert nwGUI.theProject.projTree["25fc0e7096fc6"] is not None
|
||||
assert nwGUI.theProject.projTree["31489056e0916"] is not None
|
||||
assert nwGUI.theProject.projTree["98010bd9270f9"] is not None
|
||||
|
||||
projFile = path.join(nwLipsum, "content", "25fc0e7096fc6.nwd")
|
||||
testFile = path.join(nwTempGUI, "5_25fc0e7096fc6.nwd")
|
||||
refFile = path.join(nwRef, "gui", "5_25fc0e7096fc6.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
projFile = path.join(nwLipsum, "content", "31489056e0916.nwd")
|
||||
testFile = path.join(nwTempGUI, "5_31489056e0916.nwd")
|
||||
refFile = path.join(nwRef, "gui", "5_31489056e0916.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
projFile = path.join(nwLipsum, "content", "98010bd9270f9.nwd")
|
||||
testFile = path.join(nwTempGUI, "5_98010bd9270f9.nwd")
|
||||
refFile = path.join(nwRef, "gui", "5_98010bd9270f9.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
# Split By Section
|
||||
assert nwGUI.treeView.setSelectedHandle("73475cb40a568")
|
||||
qtbot.wait(stepDelay)
|
||||
nwSplit = GuiDocSplit(nwGUI, nwGUI.theProject)
|
||||
qtbot.wait(stepDelay)
|
||||
nwSplit.splitLevel.setCurrentIndex(3)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
nwSplit._doSplit()
|
||||
|
||||
assert nwGUI.theProject.projTree["1a6562590ef19"] is not None
|
||||
assert nwGUI.theProject.projTree["031b4af5197ec"] is not None
|
||||
assert nwGUI.theProject.projTree["41cfc0d1f2d12"] is not None
|
||||
assert nwGUI.theProject.projTree["2858dcd1057d3"] is not None
|
||||
assert nwGUI.theProject.projTree["2fca346db6561"] is not None
|
||||
|
||||
projFile = path.join(nwLipsum, "content", "1a6562590ef19.nwd")
|
||||
testFile = path.join(nwTempGUI, "5_25fc0e7096fc6.nwd")
|
||||
refFile = path.join(nwRef, "gui", "5_25fc0e7096fc6.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile, [1])
|
||||
|
||||
projFile = path.join(nwLipsum, "content", "031b4af5197ec.nwd")
|
||||
testFile = path.join(nwTempGUI, "5_031b4af5197ec.nwd")
|
||||
refFile = path.join(nwRef, "gui", "5_031b4af5197ec.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
projFile = path.join(nwLipsum, "content", "41cfc0d1f2d12.nwd")
|
||||
testFile = path.join(nwTempGUI, "5_41cfc0d1f2d12.nwd")
|
||||
refFile = path.join(nwRef, "gui", "5_41cfc0d1f2d12.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
projFile = path.join(nwLipsum, "content", "2858dcd1057d3.nwd")
|
||||
testFile = path.join(nwTempGUI, "5_2858dcd1057d3.nwd")
|
||||
refFile = path.join(nwRef, "gui", "5_2858dcd1057d3.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
projFile = path.join(nwLipsum, "content", "2fca346db6561.nwd")
|
||||
testFile = path.join(nwTempGUI, "5_2fca346db6561.nwd")
|
||||
refFile = path.join(nwRef, "gui", "5_2fca346db6561.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
# qtbot.stopForInteraction()
|
||||
nwGUI.closeMain()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testNewProjectWizard(qtbot, nwLipsum, nwTemp):
|
||||
|
||||
from PyQt5.QtWidgets import QWizard
|
||||
from nw.gui.projwizard import (
|
||||
ProjWizardIntroPage, ProjWizardFolderPage, ProjWizardPopulatePage,
|
||||
ProjWizardCustomPage, ProjWizardFinalPage
|
||||
)
|
||||
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwLipsum, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
for wStep in range(3):
|
||||
|
||||
# The Wizard
|
||||
nwWiz = GuiProjectWizard(nwGUI)
|
||||
nwWiz.show()
|
||||
qtbot.waitForWindowShown(nwWiz)
|
||||
|
||||
# Intro Page
|
||||
introPage = nwWiz.currentPage()
|
||||
assert isinstance(introPage, ProjWizardIntroPage)
|
||||
assert not nwWiz.button(QWizard.NextButton).isEnabled()
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
for c in "Test Minimal":
|
||||
qtbot.keyClick(introPage.projName, c, delay=keyDelay)
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
for c in "Minimal Novel":
|
||||
qtbot.keyClick(introPage.projTitle, c, delay=keyDelay)
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
for c in "Jane Doe":
|
||||
qtbot.keyClick(introPage.projAuthors, c, delay=keyDelay)
|
||||
|
||||
# Setting projName should activate the button
|
||||
assert nwWiz.button(QWizard.NextButton).isEnabled()
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwWiz.button(QWizard.NextButton), Qt.LeftButton)
|
||||
|
||||
# Folder Page
|
||||
storagePage = nwWiz.currentPage()
|
||||
assert isinstance(storagePage, ProjWizardFolderPage)
|
||||
assert not nwWiz.button(QWizard.NextButton).isEnabled()
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
projPath = path.join(nwTemp, "dummy")
|
||||
for c in projPath:
|
||||
qtbot.keyClick(storagePage.projPath, c, delay=keyDelay)
|
||||
|
||||
# Setting projPath should activate the button
|
||||
assert nwWiz.button(QWizard.NextButton).isEnabled()
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwWiz.button(QWizard.NextButton), Qt.LeftButton)
|
||||
|
||||
# Populate Page
|
||||
popPage = nwWiz.currentPage()
|
||||
assert isinstance(popPage, ProjWizardPopulatePage)
|
||||
assert nwWiz.button(QWizard.NextButton).isEnabled()
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
if wStep == 0:
|
||||
popPage.popMinimal.setChecked(True)
|
||||
elif wStep == 1:
|
||||
popPage.popCustom.setChecked(True)
|
||||
elif wStep == 2:
|
||||
popPage.popSample.setChecked(True)
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwWiz.button(QWizard.NextButton), Qt.LeftButton)
|
||||
|
||||
# Custom Page
|
||||
if wStep == 1:
|
||||
customPage = nwWiz.currentPage()
|
||||
assert isinstance(customPage, ProjWizardCustomPage)
|
||||
assert nwWiz.button(QWizard.NextButton).isEnabled()
|
||||
|
||||
customPage.addPlot.setChecked(True)
|
||||
customPage.addChar.setChecked(True)
|
||||
customPage.addWorld.setChecked(True)
|
||||
customPage.addTime.setChecked(True)
|
||||
customPage.addObject.setChecked(True)
|
||||
customPage.addEntity.setChecked(True)
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwWiz.button(QWizard.NextButton), Qt.LeftButton)
|
||||
|
||||
# Final Page
|
||||
finalPage = nwWiz.currentPage()
|
||||
assert isinstance(finalPage, ProjWizardFinalPage)
|
||||
assert nwWiz.button(QWizard.FinishButton).isEnabled()
|
||||
qtbot.mouseClick(nwWiz.button(QWizard.FinishButton), Qt.LeftButton)
|
||||
|
||||
# Check Data
|
||||
projData = nwGUI._assembleProjectWizardData(nwWiz)
|
||||
assert projData["projName"] == "Test Minimal"
|
||||
assert projData["projTitle"] == "Minimal Novel"
|
||||
assert projData["projAuthors"] == "Jane Doe"
|
||||
assert projData["projPath"] == projPath
|
||||
assert projData["popMinimal"] == (wStep == 0)
|
||||
assert projData["popCustom"] == (wStep == 1)
|
||||
assert projData["popSample"] == (wStep == 2)
|
||||
if wStep == 1:
|
||||
assert projData["addRoots"] == [
|
||||
nwItemClass.PLOT,
|
||||
nwItemClass.CHARACTER,
|
||||
nwItemClass.WORLD,
|
||||
nwItemClass.TIMELINE,
|
||||
nwItemClass.OBJECT,
|
||||
nwItemClass.ENTITY,
|
||||
]
|
||||
assert projData["numChapters"] == 5
|
||||
assert projData["numScenes"] == 5
|
||||
assert projData["chFolders"]
|
||||
else:
|
||||
assert projData["addRoots"] == []
|
||||
assert projData["numChapters"] == 0
|
||||
assert projData["numScenes"] == 0
|
||||
assert not projData["chFolders"]
|
||||
|
||||
# qtbot.stopForInteraction()
|
||||
nwGUI.closeMain()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testLoadProject(qtbot, nwMinimal, nwTemp):
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwMinimal, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
assert nwGUI.openProject(nwMinimal)
|
||||
assert nwGUI.closeProject()
|
||||
|
||||
nwLoad = GuiProjectLoad(nwGUI)
|
||||
nwLoad.show()
|
||||
|
||||
recentCount = nwLoad.listBox.topLevelItemCount()
|
||||
assert recentCount > 0
|
||||
|
||||
selItem = nwLoad.listBox.topLevelItem(0)
|
||||
selPath = selItem.data(nwLoad.C_NAME, Qt.UserRole)
|
||||
assert isinstance(selItem, QTreeWidgetItem)
|
||||
|
||||
nwLoad.selPath.setText("")
|
||||
nwLoad.listBox.setCurrentItem(selItem)
|
||||
nwLoad._doSelectRecent()
|
||||
assert nwLoad.selPath.text() == selPath
|
||||
|
||||
qtbot.mouseClick(nwLoad.buttonBox.button(QDialogButtonBox.Open), Qt.LeftButton)
|
||||
assert nwLoad.openPath == selPath
|
||||
assert nwLoad.openState == nwLoad.OPEN_STATE
|
||||
|
||||
del nwLoad
|
||||
nwLoad = GuiProjectLoad(nwGUI)
|
||||
nwLoad.show()
|
||||
|
||||
qtbot.mouseClick(nwLoad.buttonBox.button(QDialogButtonBox.Cancel), Qt.LeftButton)
|
||||
assert nwLoad.openPath is None
|
||||
assert nwLoad.openState == nwLoad.NONE_STATE
|
||||
|
||||
nwLoad.show()
|
||||
qtbot.mouseClick(nwLoad.newButton, Qt.LeftButton)
|
||||
assert nwLoad.openPath is None
|
||||
assert nwLoad.openState == nwLoad.NEW_STATE
|
||||
|
||||
nwLoad.show()
|
||||
nwLoad._keyPressDelete()
|
||||
assert nwLoad.listBox.topLevelItemCount() == recentCount - 1
|
||||
|
||||
nwLoad.close()
|
||||
# qtbot.stopForInteraction()
|
||||
nwGUI.closeMain()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testPreferences(qtbot, nwMinimal, nwTemp, nwRef, tmpConf):
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwMinimal, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
assert nwGUI.openProject(nwMinimal)
|
||||
nwPrefs = GuiPreferences(nwGUI, nwGUI.theProject)
|
||||
nwPrefs.show()
|
||||
|
||||
# Override Config
|
||||
tmpConf.showGUI = False
|
||||
tmpConf.confPath = nwMinimal
|
||||
nwGUI.mainConf = tmpConf
|
||||
nwPrefs.mainConf = tmpConf
|
||||
nwPrefs.tabGeneral.mainConf = tmpConf
|
||||
nwPrefs.tabLayout.mainConf = tmpConf
|
||||
nwPrefs.tabEditing.mainConf = tmpConf
|
||||
nwPrefs.tabAutoRep.mainConf = tmpConf
|
||||
|
||||
# General Settings
|
||||
qtbot.wait(keyDelay)
|
||||
tabGeneral = nwPrefs.tabGeneral
|
||||
nwPrefs._tabBox.setCurrentWidget(tabGeneral)
|
||||
tabGeneral.backupPath = nwTemp
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert not tabGeneral.preferDarkIcons.isChecked()
|
||||
qtbot.mouseClick(tabGeneral.preferDarkIcons, Qt.LeftButton)
|
||||
assert tabGeneral.preferDarkIcons.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert tabGeneral.showFullPath.isChecked()
|
||||
qtbot.mouseClick(tabGeneral.showFullPath, Qt.LeftButton)
|
||||
assert not tabGeneral.showFullPath.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert not tabGeneral.backupOnClose.isChecked()
|
||||
qtbot.mouseClick(tabGeneral.backupOnClose, Qt.LeftButton)
|
||||
assert tabGeneral.backupOnClose.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
tabGeneral.guiFontSize.setValue(12)
|
||||
tabGeneral.autoSaveDoc.setValue(20)
|
||||
tabGeneral.autoSaveProj.setValue(40)
|
||||
|
||||
# Text Layour Settings
|
||||
qtbot.wait(keyDelay)
|
||||
tabLayout = nwPrefs.tabLayout
|
||||
nwPrefs._tabBox.setCurrentWidget(tabLayout)
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
tabLayout.textStyleSize.setValue(13)
|
||||
tabLayout.textFlowMax.setValue(700)
|
||||
tabLayout.focusDocWidth.setValue(900)
|
||||
tabLayout.textMargin.setValue(45)
|
||||
tabLayout.tabWidth.setValue(45)
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert not tabLayout.textFlowFixed.isChecked()
|
||||
qtbot.mouseClick(tabLayout.textFlowFixed, Qt.LeftButton)
|
||||
assert tabLayout.textFlowFixed.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert not tabLayout.hideFocusFooter.isChecked()
|
||||
qtbot.mouseClick(tabLayout.hideFocusFooter, Qt.LeftButton)
|
||||
assert tabLayout.hideFocusFooter.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert tabLayout.textJustify.isChecked()
|
||||
qtbot.mouseClick(tabLayout.textJustify, Qt.LeftButton)
|
||||
assert not tabLayout.textJustify.isChecked()
|
||||
|
||||
# Editor Settings
|
||||
qtbot.wait(keyDelay)
|
||||
tabEditing = nwPrefs.tabEditing
|
||||
nwPrefs._tabBox.setCurrentWidget(tabEditing)
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert tabEditing.highlightQuotes.isChecked()
|
||||
qtbot.mouseClick(tabEditing.highlightQuotes, Qt.LeftButton)
|
||||
assert not tabEditing.highlightQuotes.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert tabEditing.highlightEmph.isChecked()
|
||||
qtbot.mouseClick(tabEditing.highlightEmph, Qt.LeftButton)
|
||||
assert not tabEditing.highlightEmph.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert not tabEditing.showTabsNSpaces.isChecked()
|
||||
qtbot.mouseClick(tabEditing.showTabsNSpaces, Qt.LeftButton)
|
||||
assert tabEditing.showTabsNSpaces.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert not tabEditing.showLineEndings.isChecked()
|
||||
qtbot.mouseClick(tabEditing.showLineEndings, Qt.LeftButton)
|
||||
assert tabEditing.showLineEndings.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
tabEditing.bigDocLimit.setValue(500)
|
||||
|
||||
# Auto-Replace Settings
|
||||
qtbot.wait(keyDelay)
|
||||
tabAutoRep = nwPrefs.tabAutoRep
|
||||
nwPrefs._tabBox.setCurrentWidget(tabAutoRep)
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert tabAutoRep.autoSelect.isChecked()
|
||||
qtbot.mouseClick(tabAutoRep.autoSelect, Qt.LeftButton)
|
||||
assert not tabAutoRep.autoSelect.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert tabAutoRep.autoReplaceMain.isChecked()
|
||||
qtbot.mouseClick(tabAutoRep.autoReplaceMain, Qt.LeftButton)
|
||||
assert not tabAutoRep.autoReplaceMain.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert not tabAutoRep.autoReplaceSQ.isEnabled()
|
||||
assert not tabAutoRep.autoReplaceDQ.isEnabled()
|
||||
assert not tabAutoRep.autoReplaceDash.isEnabled()
|
||||
assert not tabAutoRep.autoReplaceDots.isEnabled()
|
||||
|
||||
# Save and Check Config
|
||||
# qtbot.stopForInteraction()
|
||||
qtbot.mouseClick(nwPrefs.buttonBox.button(QDialogButtonBox.Ok), Qt.LeftButton)
|
||||
|
||||
assert tmpConf.confChanged
|
||||
assert tmpConf.backupPath == nwTemp
|
||||
tmpConf.backupPath = ""
|
||||
tmpConf.lastPath = ""
|
||||
|
||||
assert nwGUI.mainConf.saveConfig()
|
||||
|
||||
nwGUI.closeMain()
|
||||
|
||||
refConf = path.join(nwRef, "novelwriter_prefs.conf")
|
||||
projConf = path.join(nwGUI.mainConf.confPath, "novelwriter.conf")
|
||||
testConf = path.join(nwTemp, "novelwriter_prefs.conf")
|
||||
copyfile(projConf, testConf)
|
||||
ignoreLines = [
|
||||
2, # Timestamp
|
||||
11, 12, 13, 14, 15, 16, 17, # Window sizes
|
||||
7, 25, # Fonts (depends in system default)
|
||||
]
|
||||
assert cmpFiles(testConf, refConf, ignoreLines)
|
||||
@@ -0,0 +1,44 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""novelWriter Error Tester
|
||||
"""
|
||||
|
||||
import nw
|
||||
import pytest
|
||||
|
||||
from PyQt5.QtWidgets import qApp
|
||||
|
||||
from nw.error import NWErrorMessage, exceptionHandler
|
||||
|
||||
@pytest.mark.error
|
||||
def testErrorDialog(qtbot, nwFuncTemp, nwTemp):
|
||||
qApp.closeAllWindows()
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwFuncTemp, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
|
||||
nwErr = NWErrorMessage(nwGUI)
|
||||
qtbot.addWidget(nwErr)
|
||||
nwErr.show()
|
||||
|
||||
# Invalid Error
|
||||
nwErr.setMessage(Exception, "Faulty Error", 123)
|
||||
assert nwErr.msgBody.toPlainText() == "Failed to generate error report ..."
|
||||
|
||||
# Valid Error
|
||||
nwErr.setMessage(Exception, "First Error", None)
|
||||
theMessage = nwErr.msgBody.toPlainText()
|
||||
assert theMessage
|
||||
assert "First Error" in theMessage
|
||||
assert "Exception" in theMessage
|
||||
nwErr._doClose()
|
||||
nwErr.close()
|
||||
|
||||
theMessage = exceptionHandler(Exception, "Second Error", None, testMode=True)
|
||||
assert theMessage
|
||||
assert "Second Error" in theMessage
|
||||
assert "Exception" in theMessage
|
||||
|
||||
nwGUI.closeMain()
|
||||
|
||||
# qtbot.stopForInteraction()
|
||||
+3
-755
@@ -4,29 +4,21 @@
|
||||
|
||||
import nw
|
||||
import pytest
|
||||
import json
|
||||
from shutil import copyfile
|
||||
from nwtools import cmpFiles
|
||||
|
||||
from os import path
|
||||
from PyQt5.QtCore import Qt, QPoint
|
||||
from PyQt5.QtGui import QTextCursor
|
||||
from PyQt5.QtWidgets import QAction, QDialogButtonBox, QTreeWidgetItem
|
||||
from PyQt5.QtWidgets import QAction, QTreeWidgetItem
|
||||
|
||||
from nw.gui import (
|
||||
GuiProjectSettings, GuiItemEditor, GuiAbout, GuiBuildNovel,
|
||||
GuiDocMerge, GuiDocSplit, GuiWritingStats, GuiProjectWizard,
|
||||
GuiProjectLoad
|
||||
)
|
||||
from nw.constants import (
|
||||
nwItemType, nwItemLayout, nwItemClass, nwDocAction, nwUnicode, nwOutline
|
||||
)
|
||||
from nw.constants import nwItemType, nwDocAction, nwUnicode, nwOutline
|
||||
|
||||
keyDelay = 2
|
||||
stepDelay = 20
|
||||
|
||||
@pytest.mark.gui
|
||||
def testMainWindows(qtbot, nwFuncTemp, nwTempGUI, nwRef, nwTemp):
|
||||
def testMainWindow(qtbot, nwFuncTemp, nwTempGUI, nwRef, nwTemp):
|
||||
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwFuncTemp, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
@@ -305,699 +297,6 @@ def testMainWindows(qtbot, nwFuncTemp, nwTempGUI, nwRef, nwTemp):
|
||||
nwGUI.closeMain()
|
||||
# qtbot.stopForInteraction()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testProjectEditor(qtbot, nwFuncTemp, nwTempGUI, nwRef, nwTemp):
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwFuncTemp, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
# Create new, save, open project
|
||||
nwGUI.theProject.projTree.setSeed(42)
|
||||
assert nwGUI.newProject({"projPath": nwFuncTemp}, True)
|
||||
nwGUI.mainConf.backupPath = nwFuncTemp
|
||||
|
||||
projEdit = GuiProjectSettings(nwGUI, nwGUI.theProject)
|
||||
projEdit.show()
|
||||
qtbot.addWidget(projEdit)
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
projEdit.tabMain.editName.setText("")
|
||||
for c in "Project Name":
|
||||
qtbot.keyClick(projEdit.tabMain.editName, c, delay=keyDelay)
|
||||
for c in "Project Title":
|
||||
qtbot.keyClick(projEdit.tabMain.editTitle, c, delay=keyDelay)
|
||||
for c in "Jane Doe":
|
||||
qtbot.keyClick(projEdit.tabMain.editAuthors, c, delay=keyDelay)
|
||||
qtbot.keyClick(projEdit.tabMain.editAuthors, Qt.Key_Return, delay=keyDelay)
|
||||
for c in "John Doh":
|
||||
qtbot.keyClick(projEdit.tabMain.editAuthors, c, delay=keyDelay)
|
||||
|
||||
# Test Status Tab
|
||||
qtbot.wait(stepDelay)
|
||||
projEdit._tabBox.setCurrentWidget(projEdit.tabStatus)
|
||||
projEdit.tabStatus.listBox.item(2).setSelected(True)
|
||||
qtbot.mouseClick(projEdit.tabStatus.delButton, Qt.LeftButton)
|
||||
qtbot.mouseClick(projEdit.tabStatus.newButton, Qt.LeftButton)
|
||||
projEdit.tabStatus.listBox.item(3).setSelected(True)
|
||||
for n in range(8):
|
||||
qtbot.keyClick(projEdit.tabStatus.editName, Qt.Key_Backspace, delay=keyDelay)
|
||||
for c in "Final":
|
||||
qtbot.keyClick(projEdit.tabStatus.editName, c, delay=keyDelay)
|
||||
qtbot.mouseClick(projEdit.tabStatus.saveButton, Qt.LeftButton)
|
||||
|
||||
# Auto-Replace Tab
|
||||
qtbot.wait(stepDelay)
|
||||
projEdit._tabBox.setCurrentWidget(projEdit.tabReplace)
|
||||
|
||||
qtbot.mouseClick(projEdit.tabReplace.addButton, Qt.LeftButton)
|
||||
projEdit.tabReplace.listBox.topLevelItem(0).setSelected(True)
|
||||
for c in "Th is ":
|
||||
qtbot.keyClick(projEdit.tabReplace.editKey, c, delay=keyDelay)
|
||||
for c in "With This Stuff ":
|
||||
qtbot.keyClick(projEdit.tabReplace.editValue, c, delay=keyDelay)
|
||||
qtbot.mouseClick(projEdit.tabReplace.saveButton, Qt.LeftButton)
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
projEdit.tabReplace.listBox.clearSelection()
|
||||
qtbot.mouseClick(projEdit.tabReplace.addButton, Qt.LeftButton)
|
||||
|
||||
newIdx = -1
|
||||
for i in range(projEdit.tabReplace.listBox.topLevelItemCount()):
|
||||
if projEdit.tabReplace.listBox.topLevelItem(i).text(0) == "<keyword2>":
|
||||
newIdx = i
|
||||
break
|
||||
|
||||
assert newIdx >= 0
|
||||
newItem = projEdit.tabReplace.listBox.topLevelItem(newIdx)
|
||||
projEdit.tabReplace.listBox.setCurrentItem(newItem)
|
||||
qtbot.mouseClick(projEdit.tabReplace.delButton, Qt.LeftButton)
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
projEdit._doSave()
|
||||
|
||||
# Open again, and check project settings
|
||||
projEdit = GuiProjectSettings(nwGUI, nwGUI.theProject)
|
||||
qtbot.addWidget(projEdit)
|
||||
assert projEdit.tabMain.editName.text() == "Project Name"
|
||||
assert projEdit.tabMain.editTitle.text() == "Project Title"
|
||||
theAuth = projEdit.tabMain.editAuthors.toPlainText().strip().splitlines()
|
||||
assert len(theAuth) == 2
|
||||
assert theAuth[0] == "Jane Doe"
|
||||
assert theAuth[1] == "John Doh"
|
||||
|
||||
projEdit._doClose()
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
assert nwGUI.saveProject()
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
# Check the files
|
||||
projFile = path.join(nwFuncTemp, "nwProject.nwx")
|
||||
testFile = path.join(nwTempGUI, "2_nwProject.nwx")
|
||||
refFile = path.join(nwRef, "gui", "2_nwProject.nwx")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile, [2, 8, 9, 10])
|
||||
|
||||
# qtbot.stopForInteraction()
|
||||
nwGUI.closeMain()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testItemEditor(qtbot, nwFuncTemp, nwTempGUI, nwRef, nwTemp):
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwFuncTemp, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
# Create new, save, open project
|
||||
nwGUI.theProject.projTree.setSeed(42)
|
||||
assert nwGUI.newProject({"projPath": nwFuncTemp}, True)
|
||||
assert nwGUI.openDocument("0e17daca5f3e1")
|
||||
|
||||
itemEdit = GuiItemEditor(nwGUI, nwGUI.theProject, "0e17daca5f3e1")
|
||||
qtbot.addWidget(itemEdit)
|
||||
|
||||
assert itemEdit.editName.text() == "New Scene"
|
||||
assert itemEdit.editStatus.currentData() == "New"
|
||||
assert itemEdit.editLayout.currentData() == nwItemLayout.SCENE
|
||||
|
||||
for c in "Just a Page":
|
||||
qtbot.keyClick(itemEdit.editName, c, delay=keyDelay)
|
||||
itemEdit.editStatus.setCurrentIndex(1)
|
||||
layoutIdx = itemEdit.editLayout.findData(nwItemLayout.PAGE)
|
||||
itemEdit.editLayout.setCurrentIndex(layoutIdx)
|
||||
|
||||
itemEdit.editExport.setChecked(False)
|
||||
assert not itemEdit.editExport.isChecked()
|
||||
itemEdit._doSave()
|
||||
|
||||
itemEdit = GuiItemEditor(nwGUI, nwGUI.theProject, "0e17daca5f3e1")
|
||||
qtbot.addWidget(itemEdit)
|
||||
assert itemEdit.editName.text() == "Just a Page"
|
||||
assert itemEdit.editStatus.currentData() == "Note"
|
||||
assert itemEdit.editLayout.currentData() == nwItemLayout.PAGE
|
||||
itemEdit._doClose()
|
||||
|
||||
# Check that the header is updated
|
||||
nwGUI.docEditor.updateDocInfo("0e17daca5f3e1")
|
||||
assert nwGUI.docEditor.docHeader.theTitle.text() == "Novel › New Chapter › Just a Page"
|
||||
assert not nwGUI.docEditor.setCursorLine("where?")
|
||||
assert nwGUI.docEditor.setCursorLine(2)
|
||||
qtbot.wait(stepDelay)
|
||||
assert nwGUI.docEditor.getCursorPosition() == 15
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
assert nwGUI.saveProject()
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
# Check the files
|
||||
projFile = path.join(nwFuncTemp, "nwProject.nwx")
|
||||
testFile = path.join(nwTempGUI, "3_nwProject.nwx")
|
||||
refFile = path.join(nwRef, "gui", "3_nwProject.nwx")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile, [2, 6, 7, 8])
|
||||
|
||||
nwGUI.closeMain()
|
||||
# qtbot.stopForInteraction()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testWritingStatsExport(qtbot, nwFuncTemp, nwTemp):
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwFuncTemp, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
# Create new, save, close project
|
||||
nwGUI.theProject.projTree.setSeed(42)
|
||||
assert nwGUI.newProject({"projPath": nwFuncTemp}, True)
|
||||
assert nwGUI.saveProject()
|
||||
assert nwGUI.closeProject()
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
assert nwGUI.openProject(nwFuncTemp)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
# Add some text to the scene file
|
||||
assert nwGUI.openDocument("0e17daca5f3e1")
|
||||
assert nwGUI.docEditor.insertText(
|
||||
"# Scene One\n\n"
|
||||
"It was the best of times, it was the worst of times, it was the age of wisdom, it was "
|
||||
"the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it "
|
||||
"was the season of Light, it was the season of Darkness, it was the spring of hope, it "
|
||||
"was the winter of despair, we had everything before us, we had nothing before us, we "
|
||||
"were all going direct to Heaven, we were all going direct the other way – in short, the "
|
||||
"period was so far like the present period, that some of its noisiest authorities "
|
||||
"insisted on its being received, for good or for evil, in the superlative degree of "
|
||||
"comparison only.\n\n"
|
||||
)
|
||||
assert nwGUI.saveDocument()
|
||||
|
||||
# Add a note file with some text
|
||||
nwGUI.setFocus(1)
|
||||
nwGUI.treeView.clearSelection()
|
||||
nwGUI.treeView._getTreeItem("71ee45a3c0db9").setSelected(True)
|
||||
nwGUI.treeView.newTreeItem(nwItemType.FILE, None)
|
||||
assert nwGUI.openSelectedItem()
|
||||
assert nwGUI.docEditor.insertText(
|
||||
"# Jane Doe\n\n"
|
||||
"All about Jane.\n\n"
|
||||
)
|
||||
assert nwGUI.saveDocument()
|
||||
qtbot.wait(500) # Ensures that the session length is > 0
|
||||
|
||||
assert nwGUI.saveProject()
|
||||
assert nwGUI.closeProject()
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
# Open again, and check the stats
|
||||
assert nwGUI.openProject(nwFuncTemp)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
nwGUI.mainConf.lastPath = nwFuncTemp
|
||||
sessLog = GuiWritingStats(nwGUI, nwGUI.theProject)
|
||||
sessLog.show()
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
assert sessLog._saveData(sessLog.FMT_CSV)
|
||||
qtbot.wait(stepDelay)
|
||||
assert sessLog._saveData(sessLog.FMT_JSON)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
jsonStats = path.join(nwFuncTemp, "sessionStats.json")
|
||||
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
|
||||
jsonData = json.loads(inFile.read())
|
||||
|
||||
assert len(jsonData) == 2
|
||||
assert jsonData[1]["length"] >= 0
|
||||
assert jsonData[1]["newWords"] == 126
|
||||
assert jsonData[1]["novelWords"] == 127
|
||||
assert jsonData[1]["noteWords"] == 5
|
||||
|
||||
# No Novel Files
|
||||
qtbot.mouseClick(sessLog.incNovel, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
assert sessLog._saveData(sessLog.FMT_JSON)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
jsonStats = path.join(nwFuncTemp, "sessionStats.json")
|
||||
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
|
||||
jsonData = json.loads(inFile.read())
|
||||
|
||||
assert len(jsonData) == 1
|
||||
assert jsonData[0]["length"] >= 0
|
||||
assert jsonData[0]["newWords"] == 5
|
||||
assert jsonData[0]["novelWords"] == 127
|
||||
assert jsonData[0]["noteWords"] == 5
|
||||
|
||||
# No Note Files
|
||||
qtbot.mouseClick(sessLog.incNovel, Qt.LeftButton)
|
||||
qtbot.mouseClick(sessLog.incNotes, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
assert sessLog._saveData(sessLog.FMT_JSON)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
jsonStats = path.join(nwFuncTemp, "sessionStats.json")
|
||||
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
|
||||
jsonData = json.loads(inFile.read())
|
||||
|
||||
assert len(jsonData) == 2
|
||||
assert jsonData[1]["length"] >= 0
|
||||
assert jsonData[1]["newWords"] == 121
|
||||
assert jsonData[1]["novelWords"] == 127
|
||||
assert jsonData[1]["noteWords"] == 5
|
||||
|
||||
# No Negative Entries
|
||||
qtbot.mouseClick(sessLog.incNotes, Qt.LeftButton)
|
||||
qtbot.mouseClick(sessLog.hideNegative, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
assert sessLog._saveData(sessLog.FMT_JSON)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
jsonStats = path.join(nwFuncTemp, "sessionStats.json")
|
||||
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
|
||||
jsonData = json.loads(inFile.read())
|
||||
|
||||
assert len(jsonData) == 2
|
||||
|
||||
# Un-hide Zero Entries
|
||||
qtbot.mouseClick(sessLog.hideNegative, Qt.LeftButton)
|
||||
qtbot.mouseClick(sessLog.hideZeros, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
assert sessLog._saveData(sessLog.FMT_JSON)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
jsonStats = path.join(nwFuncTemp, "sessionStats.json")
|
||||
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
|
||||
jsonData = json.loads(inFile.read())
|
||||
|
||||
assert len(jsonData) == 2
|
||||
|
||||
# Group by Day
|
||||
qtbot.mouseClick(sessLog.groupByDay, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
assert sessLog._saveData(sessLog.FMT_JSON)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
jsonStats = path.join(nwFuncTemp, "sessionStats.json")
|
||||
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
|
||||
jsonData = json.loads(inFile.read())
|
||||
|
||||
# Check against both 1 and 2 as this can be 2 if test was started just before midnight.
|
||||
# A failed test should in any case produce a 4
|
||||
assert len(jsonData) in (1, 2)
|
||||
|
||||
# qtbot.stopForInteraction()
|
||||
|
||||
sessLog._doClose()
|
||||
nwGUI.closeMain()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testAboutBox(qtbot, nwFuncTemp, nwTemp):
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwFuncTemp, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
msgAbout = GuiAbout(nwGUI)
|
||||
assert msgAbout.pageAbout.document().characterCount() > 100
|
||||
assert msgAbout.pageLicense.document().characterCount() > 100
|
||||
|
||||
# qtbot.stopForInteraction()
|
||||
msgAbout._doClose()
|
||||
nwGUI.closeMain()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testBuildTool(qtbot, nwTempBuild, nwLipsum, nwRef, nwTemp):
|
||||
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwLipsum, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
assert nwGUI.openProject(nwLipsum)
|
||||
|
||||
nwGUI.mainConf.lastPath = nwLipsum
|
||||
|
||||
nwBuild = GuiBuildNovel(nwGUI, nwGUI.theProject)
|
||||
|
||||
# Default Settings
|
||||
qtbot.mouseClick(nwBuild.buildNovel, Qt.LeftButton)
|
||||
|
||||
assert nwBuild._saveDocument(nwBuild.FMT_NWD)
|
||||
assert nwBuild._saveDocument(nwBuild.FMT_HTM)
|
||||
|
||||
projFile = path.join(nwLipsum, "Lorem Ipsum.nwd")
|
||||
testFile = path.join(nwTempBuild, "1_LoremIpsum.nwd")
|
||||
refFile = path.join(nwRef, "build", "1_LoremIpsum.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
projFile = path.join(nwLipsum, "Lorem Ipsum.htm")
|
||||
testFile = path.join(nwTempBuild, "1_LoremIpsum.htm")
|
||||
refFile = path.join(nwRef, "build", "1_LoremIpsum.htm")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
# Change Title Formats and Flip Switches
|
||||
nwBuild.fmtChapter.setText(r"Chapter %chw%: %title%")
|
||||
qtbot.wait(stepDelay)
|
||||
nwBuild.fmtScene.setText(r"Scene %ch%.%sc%: %title%")
|
||||
qtbot.wait(stepDelay)
|
||||
nwBuild.fmtSection.setText(r"%ch%.%sc%.1: %title%")
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
qtbot.mouseClick(nwBuild.justifyText, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwBuild.includeSynopsis, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwBuild.includeComments, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwBuild.includeKeywords, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
qtbot.mouseClick(nwBuild.noteFiles, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwBuild.ignoreFlag, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
qtbot.mouseClick(nwBuild.buildNovel, Qt.LeftButton)
|
||||
|
||||
assert nwBuild._saveDocument(nwBuild.FMT_NWD)
|
||||
assert nwBuild._saveDocument(nwBuild.FMT_HTM)
|
||||
|
||||
projFile = path.join(nwLipsum, "Lorem Ipsum.nwd")
|
||||
testFile = path.join(nwTempBuild, "2_LoremIpsum.nwd")
|
||||
refFile = path.join(nwRef, "build", "2_LoremIpsum.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
projFile = path.join(nwLipsum, "Lorem Ipsum.htm")
|
||||
testFile = path.join(nwTempBuild, "2_LoremIpsum.htm")
|
||||
refFile = path.join(nwRef, "build", "2_LoremIpsum.htm")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
# Putline Mode
|
||||
nwBuild.fmtChapter.setText(r"Chapter %chw%: %title%")
|
||||
qtbot.wait(stepDelay)
|
||||
nwBuild.fmtScene.setText(r"Scene %sca%: %title%")
|
||||
qtbot.wait(stepDelay)
|
||||
nwBuild.fmtSection.setText(r"Section: %title%")
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
qtbot.mouseClick(nwBuild.includeComments, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwBuild.noteFiles, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwBuild.ignoreFlag, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwBuild.includeBody, Qt.LeftButton)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
qtbot.mouseClick(nwBuild.buildNovel, Qt.LeftButton)
|
||||
|
||||
assert nwBuild._saveDocument(nwBuild.FMT_NWD)
|
||||
assert nwBuild._saveDocument(nwBuild.FMT_HTM)
|
||||
|
||||
projFile = path.join(nwLipsum, "Lorem Ipsum.nwd")
|
||||
testFile = path.join(nwTempBuild, "3_LoremIpsum.nwd")
|
||||
refFile = path.join(nwRef, "build", "3_LoremIpsum.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
projFile = path.join(nwLipsum, "Lorem Ipsum.htm")
|
||||
testFile = path.join(nwTempBuild, "3_LoremIpsum.htm")
|
||||
refFile = path.join(nwRef, "build", "3_LoremIpsum.htm")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
# qtbot.stopForInteraction()
|
||||
nwBuild._doClose()
|
||||
nwGUI.closeMain()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testMergeSplitTools(qtbot, nwTempGUI, nwLipsum, nwRef, nwTemp):
|
||||
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwLipsum, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
nwGUI.theProject.projTree.setSeed(42)
|
||||
assert nwGUI.openProject(nwLipsum)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
assert nwGUI.treeView.setSelectedHandle("45e6b01ca35c1")
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
nwMerge = GuiDocMerge(nwGUI, nwGUI.theProject)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
nwMerge._doMerge()
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
assert nwGUI.theProject.projTree["73475cb40a568"] is not None
|
||||
|
||||
projFile = path.join(nwLipsum, "content", "73475cb40a568.nwd")
|
||||
testFile = path.join(nwTempGUI, "4_73475cb40a568.nwd")
|
||||
refFile = path.join(nwRef, "gui", "4_73475cb40a568.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
# Split By Chapter
|
||||
assert nwGUI.treeView.setSelectedHandle("73475cb40a568")
|
||||
qtbot.wait(stepDelay)
|
||||
nwSplit = GuiDocSplit(nwGUI, nwGUI.theProject)
|
||||
qtbot.wait(stepDelay)
|
||||
nwSplit.splitLevel.setCurrentIndex(1)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
nwSplit._doSplit()
|
||||
assert nwGUI.theProject.projTree["71ee45a3c0db9"] is not None
|
||||
|
||||
# This should give us back the file as it was before
|
||||
projFile = path.join(nwLipsum, "content", "71ee45a3c0db9.nwd")
|
||||
testFile = path.join(nwTempGUI, "4_71ee45a3c0db9.nwd")
|
||||
refFile = path.join(nwRef, "gui", "4_73475cb40a568.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile, [1])
|
||||
|
||||
# Split By Scene
|
||||
assert nwGUI.treeView.setSelectedHandle("73475cb40a568")
|
||||
qtbot.wait(stepDelay)
|
||||
nwSplit = GuiDocSplit(nwGUI, nwGUI.theProject)
|
||||
qtbot.wait(stepDelay)
|
||||
nwSplit.splitLevel.setCurrentIndex(2)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
nwSplit._doSplit()
|
||||
|
||||
assert nwGUI.theProject.projTree["25fc0e7096fc6"] is not None
|
||||
assert nwGUI.theProject.projTree["31489056e0916"] is not None
|
||||
assert nwGUI.theProject.projTree["98010bd9270f9"] is not None
|
||||
|
||||
projFile = path.join(nwLipsum, "content", "25fc0e7096fc6.nwd")
|
||||
testFile = path.join(nwTempGUI, "5_25fc0e7096fc6.nwd")
|
||||
refFile = path.join(nwRef, "gui", "5_25fc0e7096fc6.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
projFile = path.join(nwLipsum, "content", "31489056e0916.nwd")
|
||||
testFile = path.join(nwTempGUI, "5_31489056e0916.nwd")
|
||||
refFile = path.join(nwRef, "gui", "5_31489056e0916.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
projFile = path.join(nwLipsum, "content", "98010bd9270f9.nwd")
|
||||
testFile = path.join(nwTempGUI, "5_98010bd9270f9.nwd")
|
||||
refFile = path.join(nwRef, "gui", "5_98010bd9270f9.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
# Split By Section
|
||||
assert nwGUI.treeView.setSelectedHandle("73475cb40a568")
|
||||
qtbot.wait(stepDelay)
|
||||
nwSplit = GuiDocSplit(nwGUI, nwGUI.theProject)
|
||||
qtbot.wait(stepDelay)
|
||||
nwSplit.splitLevel.setCurrentIndex(3)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
nwSplit._doSplit()
|
||||
|
||||
assert nwGUI.theProject.projTree["1a6562590ef19"] is not None
|
||||
assert nwGUI.theProject.projTree["031b4af5197ec"] is not None
|
||||
assert nwGUI.theProject.projTree["41cfc0d1f2d12"] is not None
|
||||
assert nwGUI.theProject.projTree["2858dcd1057d3"] is not None
|
||||
assert nwGUI.theProject.projTree["2fca346db6561"] is not None
|
||||
|
||||
projFile = path.join(nwLipsum, "content", "1a6562590ef19.nwd")
|
||||
testFile = path.join(nwTempGUI, "5_25fc0e7096fc6.nwd")
|
||||
refFile = path.join(nwRef, "gui", "5_25fc0e7096fc6.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile, [1])
|
||||
|
||||
projFile = path.join(nwLipsum, "content", "031b4af5197ec.nwd")
|
||||
testFile = path.join(nwTempGUI, "5_031b4af5197ec.nwd")
|
||||
refFile = path.join(nwRef, "gui", "5_031b4af5197ec.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
projFile = path.join(nwLipsum, "content", "41cfc0d1f2d12.nwd")
|
||||
testFile = path.join(nwTempGUI, "5_41cfc0d1f2d12.nwd")
|
||||
refFile = path.join(nwRef, "gui", "5_41cfc0d1f2d12.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
projFile = path.join(nwLipsum, "content", "2858dcd1057d3.nwd")
|
||||
testFile = path.join(nwTempGUI, "5_2858dcd1057d3.nwd")
|
||||
refFile = path.join(nwRef, "gui", "5_2858dcd1057d3.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
projFile = path.join(nwLipsum, "content", "2fca346db6561.nwd")
|
||||
testFile = path.join(nwTempGUI, "5_2fca346db6561.nwd")
|
||||
refFile = path.join(nwRef, "gui", "5_2fca346db6561.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
# qtbot.stopForInteraction()
|
||||
nwGUI.closeMain()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testNewProjectWizard(qtbot, nwLipsum, nwTemp):
|
||||
|
||||
from PyQt5.QtWidgets import QWizard
|
||||
from nw.gui.projwizard import (
|
||||
ProjWizardIntroPage, ProjWizardFolderPage, ProjWizardPopulatePage,
|
||||
ProjWizardCustomPage, ProjWizardFinalPage
|
||||
)
|
||||
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwLipsum, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
for wStep in range(3):
|
||||
|
||||
# The Wizard
|
||||
nwWiz = GuiProjectWizard(nwGUI)
|
||||
nwWiz.show()
|
||||
qtbot.waitForWindowShown(nwWiz)
|
||||
|
||||
# Intro Page
|
||||
introPage = nwWiz.currentPage()
|
||||
assert isinstance(introPage, ProjWizardIntroPage)
|
||||
assert not nwWiz.button(QWizard.NextButton).isEnabled()
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
for c in "Test Minimal":
|
||||
qtbot.keyClick(introPage.projName, c, delay=keyDelay)
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
for c in "Minimal Novel":
|
||||
qtbot.keyClick(introPage.projTitle, c, delay=keyDelay)
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
for c in "Jane Doe":
|
||||
qtbot.keyClick(introPage.projAuthors, c, delay=keyDelay)
|
||||
|
||||
# Setting projName should activate the button
|
||||
assert nwWiz.button(QWizard.NextButton).isEnabled()
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwWiz.button(QWizard.NextButton), Qt.LeftButton)
|
||||
|
||||
# Folder Page
|
||||
storagePage = nwWiz.currentPage()
|
||||
assert isinstance(storagePage, ProjWizardFolderPage)
|
||||
assert not nwWiz.button(QWizard.NextButton).isEnabled()
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
projPath = path.join(nwTemp, "dummy")
|
||||
for c in projPath:
|
||||
qtbot.keyClick(storagePage.projPath, c, delay=keyDelay)
|
||||
|
||||
# Setting projPath should activate the button
|
||||
assert nwWiz.button(QWizard.NextButton).isEnabled()
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwWiz.button(QWizard.NextButton), Qt.LeftButton)
|
||||
|
||||
# Populate Page
|
||||
popPage = nwWiz.currentPage()
|
||||
assert isinstance(popPage, ProjWizardPopulatePage)
|
||||
assert nwWiz.button(QWizard.NextButton).isEnabled()
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
if wStep == 0:
|
||||
popPage.popMinimal.setChecked(True)
|
||||
elif wStep == 1:
|
||||
popPage.popCustom.setChecked(True)
|
||||
elif wStep == 2:
|
||||
popPage.popSample.setChecked(True)
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwWiz.button(QWizard.NextButton), Qt.LeftButton)
|
||||
|
||||
# Custom Page
|
||||
if wStep == 1:
|
||||
customPage = nwWiz.currentPage()
|
||||
assert isinstance(customPage, ProjWizardCustomPage)
|
||||
assert nwWiz.button(QWizard.NextButton).isEnabled()
|
||||
|
||||
customPage.addPlot.setChecked(True)
|
||||
customPage.addChar.setChecked(True)
|
||||
customPage.addWorld.setChecked(True)
|
||||
customPage.addTime.setChecked(True)
|
||||
customPage.addObject.setChecked(True)
|
||||
customPage.addEntity.setChecked(True)
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwWiz.button(QWizard.NextButton), Qt.LeftButton)
|
||||
|
||||
# Final Page
|
||||
finalPage = nwWiz.currentPage()
|
||||
assert isinstance(finalPage, ProjWizardFinalPage)
|
||||
assert nwWiz.button(QWizard.FinishButton).isEnabled()
|
||||
qtbot.mouseClick(nwWiz.button(QWizard.FinishButton), Qt.LeftButton)
|
||||
|
||||
# Check Data
|
||||
projData = nwGUI._assembleProjectWizardData(nwWiz)
|
||||
assert projData["projName"] == "Test Minimal"
|
||||
assert projData["projTitle"] == "Minimal Novel"
|
||||
assert projData["projAuthors"] == "Jane Doe"
|
||||
assert projData["projPath"] == projPath
|
||||
assert projData["popMinimal"] == (wStep == 0)
|
||||
assert projData["popCustom"] == (wStep == 1)
|
||||
assert projData["popSample"] == (wStep == 2)
|
||||
if wStep == 1:
|
||||
assert projData["addRoots"] == [
|
||||
nwItemClass.PLOT,
|
||||
nwItemClass.CHARACTER,
|
||||
nwItemClass.WORLD,
|
||||
nwItemClass.TIMELINE,
|
||||
nwItemClass.OBJECT,
|
||||
nwItemClass.ENTITY,
|
||||
]
|
||||
assert projData["numChapters"] == 5
|
||||
assert projData["numScenes"] == 5
|
||||
assert projData["chFolders"]
|
||||
else:
|
||||
assert projData["addRoots"] == []
|
||||
assert projData["numChapters"] == 0
|
||||
assert projData["numScenes"] == 0
|
||||
assert not projData["chFolders"]
|
||||
|
||||
# qtbot.stopForInteraction()
|
||||
nwGUI.closeMain()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testDocAction(qtbot, nwLipsum, nwTemp):
|
||||
|
||||
@@ -1260,57 +559,6 @@ def testInsertMenu(qtbot, nwFuncTemp, nwTemp):
|
||||
# qtbot.stopForInteraction()
|
||||
nwGUI.closeMain()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testLoadProject(qtbot, nwMinimal, nwTemp):
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwMinimal, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
assert nwGUI.openProject(nwMinimal)
|
||||
assert nwGUI.closeProject()
|
||||
|
||||
nwLoad = GuiProjectLoad(nwGUI)
|
||||
nwLoad.show()
|
||||
|
||||
recentCount = nwLoad.listBox.topLevelItemCount()
|
||||
assert recentCount > 0
|
||||
|
||||
selItem = nwLoad.listBox.topLevelItem(0)
|
||||
selPath = selItem.data(nwLoad.C_NAME, Qt.UserRole)
|
||||
assert isinstance(selItem, QTreeWidgetItem)
|
||||
|
||||
nwLoad.selPath.setText("")
|
||||
nwLoad.listBox.setCurrentItem(selItem)
|
||||
nwLoad._doSelectRecent()
|
||||
assert nwLoad.selPath.text() == selPath
|
||||
|
||||
qtbot.mouseClick(nwLoad.buttonBox.button(QDialogButtonBox.Open), Qt.LeftButton)
|
||||
assert nwLoad.openPath == selPath
|
||||
assert nwLoad.openState == nwLoad.OPEN_STATE
|
||||
|
||||
del nwLoad
|
||||
nwLoad = GuiProjectLoad(nwGUI)
|
||||
nwLoad.show()
|
||||
|
||||
qtbot.mouseClick(nwLoad.buttonBox.button(QDialogButtonBox.Cancel), Qt.LeftButton)
|
||||
assert nwLoad.openPath is None
|
||||
assert nwLoad.openState == nwLoad.NONE_STATE
|
||||
|
||||
nwLoad.show()
|
||||
qtbot.mouseClick(nwLoad.newButton, Qt.LeftButton)
|
||||
assert nwLoad.openPath is None
|
||||
assert nwLoad.openState == nwLoad.NEW_STATE
|
||||
|
||||
nwLoad.show()
|
||||
nwLoad._keyPressDelete()
|
||||
assert nwLoad.listBox.topLevelItemCount() == recentCount - 1
|
||||
|
||||
nwLoad.close()
|
||||
# qtbot.stopForInteraction()
|
||||
nwGUI.closeMain()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testOutline(qtbot, nwLipsum, nwTemp):
|
||||
|
||||
|
||||
@@ -237,3 +237,34 @@ def testItemXMLPackUnpack(nwDummy):
|
||||
assert theItem.itemClass == nwItemClass.NOVEL
|
||||
assert theItem.itemType == nwItemType.FILE
|
||||
assert theItem.itemLayout == nwItemLayout.NOTE
|
||||
|
||||
# Errors
|
||||
|
||||
## Not an Item
|
||||
xDummy = etree.SubElement(nwXML, "stuff")
|
||||
assert not theItem.unpackXML(xDummy)
|
||||
|
||||
## Item without Handle
|
||||
xDummy = etree.SubElement(nwXML, "item", attrib={"stuff": "nah"})
|
||||
assert not theItem.unpackXML(xDummy)
|
||||
|
||||
## Item with Invalid SubElement
|
||||
xDummy = etree.SubElement(nwXML, "item", attrib={"handle": "0123456789abc"})
|
||||
xParam = etree.SubElement(xDummy, "invalid")
|
||||
xParam.text = "stuff"
|
||||
assert theItem.unpackXML(xDummy) # Passes, but not saved
|
||||
|
||||
# Pack Valid Item
|
||||
xDummy = etree.SubElement(nwXML, "group")
|
||||
theItem._subPack(xDummy, "subGroup", {"one": "two"}, "value", False)
|
||||
assert etree.tostring(xDummy, pretty_print=False, encoding="utf-8") == (
|
||||
b"<group><subGroup one=\"two\">value</subGroup></group>"
|
||||
)
|
||||
|
||||
# Pack Not Allowed None
|
||||
xDummy = etree.SubElement(nwXML, "group")
|
||||
assert theItem._subPack(xDummy, "subGroup", {}, None, False) is None
|
||||
assert theItem._subPack(xDummy, "subGroup", {}, "None", False) is None
|
||||
assert etree.tostring(xDummy, pretty_print=False, encoding="utf-8") == (
|
||||
b"<group/>"
|
||||
)
|
||||
|
||||
+62
-1
@@ -12,7 +12,7 @@ from nw.core.project import NWProject
|
||||
from nw.core.document import NWDoc
|
||||
from nw.core.index import NWIndex
|
||||
from nw.core.spellcheck import NWSpellEnchant, NWSpellSimple
|
||||
from nw.constants import nwItemClass, nwItemLayout, nwFiles
|
||||
from nw.constants import nwItemClass, nwItemType, nwItemLayout, nwFiles
|
||||
|
||||
@pytest.mark.project
|
||||
def testProjectNewOpenSave(nwFuncTemp, nwTempProj, nwRef, nwTemp, nwDummy):
|
||||
@@ -431,3 +431,64 @@ def testProjectOptions(nwDummy, nwLipsum):
|
||||
assert theOpts.getFloat("GuiWritingStats", "NoName", False) is False
|
||||
assert theOpts.setValue("GuiWritingStats", "winWidth", "True")
|
||||
assert theOpts.getFloat("GuiWritingStats", "winWidth", False) is False
|
||||
|
||||
@pytest.mark.project
|
||||
def testOrphanedFiles(nwDummy, nwLipsum):
|
||||
theProject = NWProject(nwDummy)
|
||||
assert theProject.openProject(nwLipsum)
|
||||
assert theProject.projTree["636b6aa9b697b"] is None
|
||||
assert theProject.closeProject()
|
||||
|
||||
# First Item with Meta Data
|
||||
orphPath = path.join(nwLipsum, "content", "636b6aa9b697b.nwd")
|
||||
with open(orphPath, mode="w", encoding="utf8") as outFile:
|
||||
outFile.write(r"%%~ 5eaea4e8cdee8:15c4492bd5107:WORLD:NOTE:Mars")
|
||||
outFile.write("\n")
|
||||
|
||||
# Second Item without Meta Data
|
||||
orphPath = path.join(nwLipsum, "content", "736b6aa9b697b.nwd")
|
||||
with open(orphPath, mode="w", encoding="utf8") as outFile:
|
||||
outFile.write("\n")
|
||||
|
||||
# Invalid File Name
|
||||
dummyPath = path.join(nwLipsum, "content", "636b6aa9b697b.txt")
|
||||
with open(dummyPath, mode="w", encoding="utf8") as outFile:
|
||||
outFile.write("\n")
|
||||
|
||||
# Invalid File Name
|
||||
dummyPath = path.join(nwLipsum, "content", "636b6aa9b697bb.nwd")
|
||||
with open(dummyPath, mode="w", encoding="utf8") as outFile:
|
||||
outFile.write("\n")
|
||||
|
||||
# Invalid File Name
|
||||
dummyPath = path.join(nwLipsum, "content", "abcdefghijklm.nwd")
|
||||
with open(dummyPath, mode="w", encoding="utf8") as outFile:
|
||||
outFile.write("\n")
|
||||
|
||||
assert theProject.openProject(nwLipsum)
|
||||
assert theProject.projPath is not None
|
||||
assert theProject.projTree["636b6aa9b697bb"] is None
|
||||
assert theProject.projTree["abcdefghijklm"] is None
|
||||
|
||||
# First Item with Meta Data
|
||||
oItem = theProject.projTree["636b6aa9b697b"]
|
||||
assert oItem is not None
|
||||
assert oItem.itemName == "Mars"
|
||||
assert oItem.itemHandle == "636b6aa9b697b"
|
||||
assert oItem.parHandle is None
|
||||
assert oItem.itemClass == nwItemClass.WORLD
|
||||
assert oItem.itemType == nwItemType.FILE
|
||||
assert oItem.itemLayout == nwItemLayout.NOTE
|
||||
|
||||
# Second Item without Meta Data
|
||||
oItem = theProject.projTree["736b6aa9b697b"]
|
||||
assert oItem is not None
|
||||
assert oItem.itemName == "Orphaned File 1"
|
||||
assert oItem.itemHandle == "736b6aa9b697b"
|
||||
assert oItem.parHandle is None
|
||||
assert oItem.itemClass == nwItemClass.NO_CLASS
|
||||
assert oItem.itemType == nwItemType.FILE
|
||||
assert oItem.itemLayout == nwItemLayout.NO_LAYOUT
|
||||
|
||||
assert theProject.saveProject(nwLipsum)
|
||||
assert theProject.closeProject()
|
||||
|
||||
Reference in New Issue
Block a user