Merge branch 'dev' into feature/build_gui
This commit is contained in:
+69
-69
@@ -28,19 +28,60 @@ from pathlib import Path
|
||||
from mock import MockGuiMain
|
||||
from tools import cleanProject
|
||||
|
||||
from PyQt5.QtWidgets import QMessageBox
|
||||
|
||||
sys.path.insert(1, str(Path(__file__).parent.parent.absolute()))
|
||||
|
||||
import novelwriter # noqa: E402
|
||||
from novelwriter import CONFIG, main # noqa: E402
|
||||
|
||||
from PyQt5.QtWidgets import QMessageBox # noqa: E402
|
||||
|
||||
from novelwriter.config import Config # noqa: E402
|
||||
_TST_ROOT = Path(__file__).parent
|
||||
_TMP_ROOT = _TST_ROOT / "temp"
|
||||
_TMP_CONF = _TMP_ROOT / "conf"
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def initQt(qtbot):
|
||||
"""Ensures that the qt main thread is always available in all tests.
|
||||
##
|
||||
# Helper Functions
|
||||
##
|
||||
|
||||
def resetConfigVars():
|
||||
"""Reset the CONFIG object and set various values for testing to
|
||||
prevent interfering with local OS.
|
||||
"""
|
||||
CONFIG.setLastPath(_TMP_ROOT)
|
||||
CONFIG.setBackupPath(_TMP_ROOT)
|
||||
CONFIG._homePath = _TMP_ROOT
|
||||
CONFIG.guiLocale = "en_GB"
|
||||
return
|
||||
|
||||
|
||||
##
|
||||
# Auto Fixtures
|
||||
##
|
||||
|
||||
@pytest.fixture(scope="session", autouse=True)
|
||||
def sessionFixture():
|
||||
"""A session wide fixture to set up the test environment.
|
||||
"""
|
||||
if _TMP_ROOT.exists():
|
||||
shutil.rmtree(_TMP_ROOT)
|
||||
_TMP_ROOT.mkdir()
|
||||
_TMP_CONF.mkdir()
|
||||
return
|
||||
|
||||
|
||||
@pytest.fixture(scope="function", autouse=True)
|
||||
def functionFixture(qtbot):
|
||||
"""Ensures that the main Qt thread is always available, and reset
|
||||
the config object for each function and redirect its storage paths.
|
||||
"""
|
||||
if _TMP_CONF.exists():
|
||||
shutil.rmtree(_TMP_CONF)
|
||||
_TMP_CONF.mkdir()
|
||||
|
||||
CONFIG.__init__()
|
||||
CONFIG.initConfig(confPath=_TMP_CONF, dataPath=_TMP_CONF)
|
||||
resetConfigVars()
|
||||
|
||||
return
|
||||
|
||||
|
||||
@@ -49,26 +90,17 @@ def initQt(qtbot):
|
||||
##
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def tmpPath():
|
||||
"""A temporary folder for the test session. Path version.
|
||||
"""
|
||||
theTemp = Path(__file__).parent / "temp"
|
||||
if theTemp.exists():
|
||||
shutil.rmtree(theTemp)
|
||||
theTemp.mkdir(exist_ok=True)
|
||||
return theTemp
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def tstPaths(tmpPath):
|
||||
def tstPaths():
|
||||
"""Returns an object that can provide the various paths needed for
|
||||
running tests.
|
||||
"""
|
||||
class _Store:
|
||||
testDir = Path(__file__).parent
|
||||
filesDir = testDir / "files"
|
||||
refDir = testDir / "reference"
|
||||
outDir = tmpPath / "results"
|
||||
testDir = _TST_ROOT
|
||||
filesDir = _TST_ROOT / "files"
|
||||
refDir = _TST_ROOT / "reference"
|
||||
outDir = _TMP_ROOT / "results"
|
||||
tmpDir = _TMP_ROOT
|
||||
cnfDir = _TMP_CONF
|
||||
|
||||
store = _Store()
|
||||
store.outDir.mkdir(exist_ok=True)
|
||||
@@ -77,10 +109,10 @@ def tstPaths(tmpPath):
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def fncPath(tmpPath):
|
||||
"""A temporary folder for a single test function. Path version.
|
||||
def fncPath():
|
||||
"""A temporary folder for a single test function.
|
||||
"""
|
||||
fncPath = tmpPath / "function"
|
||||
fncPath = _TMP_ROOT / "function"
|
||||
if fncPath.is_dir():
|
||||
shutil.rmtree(fncPath)
|
||||
fncPath.mkdir(exist_ok=True)
|
||||
@@ -103,46 +135,17 @@ def projPath(fncPath):
|
||||
# novelWriter Objects
|
||||
##
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def tmpConf(tmpPath):
|
||||
"""Create a temporary novelWriter configuration object.
|
||||
"""
|
||||
confFile = tmpPath / "novelwriter.conf"
|
||||
if confFile.is_file():
|
||||
confFile.unlink()
|
||||
theConf = Config()
|
||||
theConf.initConfig(tmpPath, tmpPath)
|
||||
theConf.setLastPath(tmpPath)
|
||||
theConf.guiLocale = "en_GB"
|
||||
return theConf
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def fncConf(fncPath):
|
||||
"""Create a temporary novelWriter configuration object.
|
||||
"""
|
||||
confFile = fncPath / "novelwriter.conf"
|
||||
if confFile.is_file():
|
||||
confFile.unlink()
|
||||
theConf = Config()
|
||||
theConf.initConfig(fncPath, fncPath)
|
||||
theConf.setLastPath(fncPath)
|
||||
theConf.guiLocale = "en_GB"
|
||||
return theConf
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def mockGUI(monkeypatch, tmpConf):
|
||||
def mockGUI():
|
||||
"""Create a mock instance of novelWriter's main GUI class.
|
||||
"""
|
||||
monkeypatch.setattr("novelwriter.CONFIG", tmpConf)
|
||||
theGui = MockGuiMain()
|
||||
theGui.mainConf = tmpConf
|
||||
return theGui
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def nwGUI(qtbot, monkeypatch, fncPath, fncConf):
|
||||
def nwGUI(qtbot, monkeypatch, functionFixture):
|
||||
"""Create an instance of the novelWriter GUI.
|
||||
"""
|
||||
monkeypatch.setattr(QMessageBox, "warning", lambda *a: QMessageBox.Ok)
|
||||
@@ -150,14 +153,13 @@ def nwGUI(qtbot, monkeypatch, fncPath, fncConf):
|
||||
monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Ok)
|
||||
monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
|
||||
|
||||
monkeypatch.setattr("novelwriter.CONFIG", fncConf)
|
||||
nwGUI = novelwriter.main(["--testmode", f"--config={fncPath}", f"--data={fncPath}"])
|
||||
nwGUI = main(["--testmode", f"--config={_TMP_CONF}", f"--data={_TMP_CONF}"])
|
||||
qtbot.addWidget(nwGUI)
|
||||
resetConfigVars()
|
||||
|
||||
nwGUI.show()
|
||||
qtbot.wait(20)
|
||||
|
||||
nwGUI.mainConf.setLastPath(fncPath)
|
||||
|
||||
yield nwGUI
|
||||
|
||||
qtbot.wait(20)
|
||||
@@ -198,13 +200,12 @@ def mockRnd(monkeypatch):
|
||||
##
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def nwLipsum(tmpPath):
|
||||
def nwLipsum():
|
||||
"""A medium sized novelWriter example project with a lot of Lorem
|
||||
Ipsum text.
|
||||
"""
|
||||
tstDir = Path(__file__).parent
|
||||
srcDir = tstDir / "lipsum"
|
||||
dstDir = tmpPath / "lipsum"
|
||||
srcDir = _TST_ROOT / "lipsum"
|
||||
dstDir = _TMP_ROOT / "lipsum"
|
||||
if dstDir.exists():
|
||||
shutil.rmtree(dstDir)
|
||||
|
||||
@@ -220,13 +221,12 @@ def nwLipsum(tmpPath):
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def prjLipsum(tmpPath):
|
||||
def prjLipsum():
|
||||
"""A medium sized novelWriter example project with a lot of Lorem
|
||||
Ipsum text.
|
||||
"""
|
||||
tstDir = Path(__file__).parent
|
||||
srcDir = tstDir / "lipsum"
|
||||
dstDir = tmpPath / "lipsum"
|
||||
srcDir = _TST_ROOT / "lipsum"
|
||||
dstDir = _TMP_ROOT / "lipsum"
|
||||
if dstDir.exists():
|
||||
shutil.rmtree(dstDir)
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ class MockGuiMain(QObject):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self.mainConf = None
|
||||
self.hasProject = True
|
||||
self.theProject = None
|
||||
self.mainStatus = MockStatusBar()
|
||||
|
||||
+119
-109
@@ -28,6 +28,7 @@ from pathlib import Path
|
||||
from mock import causeOSError, MockApp
|
||||
from tools import cmpFiles, writeFile
|
||||
|
||||
from novelwriter import CONFIG
|
||||
from novelwriter.config import Config, RecentProjects
|
||||
from novelwriter.constants import nwFiles
|
||||
|
||||
@@ -196,197 +197,206 @@ def testBaseConfig_Localisation(fncPath, tstPaths):
|
||||
|
||||
|
||||
@pytest.mark.base
|
||||
def testBaseConfig_Methods(tmpConf, tmpPath):
|
||||
def testBaseConfig_Methods(fncPath):
|
||||
"""Check class methods.
|
||||
"""
|
||||
tstConf = Config()
|
||||
tstConf.initConfig(confPath=fncPath, dataPath=fncPath)
|
||||
|
||||
# Data Path
|
||||
assert tmpConf.dataPath() == tmpPath
|
||||
assert tmpConf.dataPath("stuff") == tmpPath / "stuff"
|
||||
assert tstConf.dataPath() == fncPath
|
||||
assert tstConf.dataPath("stuff") == fncPath / "stuff"
|
||||
|
||||
# Assets Path
|
||||
appPath = tmpConf._appPath
|
||||
assert tmpConf.assetPath() == appPath / "assets"
|
||||
assert tmpConf.assetPath("stuff") == appPath / "assets" / "stuff"
|
||||
appPath = tstConf._appPath
|
||||
assert tstConf.assetPath() == appPath / "assets"
|
||||
assert tstConf.assetPath("stuff") == appPath / "assets" / "stuff"
|
||||
|
||||
# Last Path
|
||||
assert tmpConf.lastPath() == tmpPath
|
||||
assert tstConf.lastPath() == Path.home().absolute()
|
||||
|
||||
tmpStuff = tmpPath / "stuff"
|
||||
tmpStuff = fncPath / "stuff"
|
||||
tmpStuff.mkdir()
|
||||
tmpConf.setLastPath(tmpStuff)
|
||||
assert tmpConf.lastPath() == tmpStuff
|
||||
tstConf.setLastPath(tmpStuff)
|
||||
assert tstConf.lastPath() == tmpStuff
|
||||
|
||||
fileStuff = tmpStuff / "more_stuff.txt"
|
||||
fileStuff.write_text("Stuff")
|
||||
tmpConf.setLastPath(fileStuff)
|
||||
assert tmpConf.lastPath() == tmpStuff
|
||||
tstConf.setLastPath(fileStuff)
|
||||
assert tstConf.lastPath() == tmpStuff
|
||||
|
||||
fileStuff.unlink()
|
||||
tmpStuff.rmdir()
|
||||
assert tmpConf.lastPath() == Path.home().absolute()
|
||||
assert tstConf.lastPath() == Path.home().absolute()
|
||||
|
||||
# Recent Projects
|
||||
assert isinstance(tmpConf.recentProjects, RecentProjects)
|
||||
assert isinstance(tstConf.recentProjects, RecentProjects)
|
||||
|
||||
# END Test testBaseConfig_Methods
|
||||
|
||||
|
||||
@pytest.mark.base
|
||||
def testBaseConfig_SettersGetters(tmpConf):
|
||||
def testBaseConfig_SettersGetters(fncPath):
|
||||
"""Set various sizes and positions
|
||||
"""
|
||||
tstConf = Config()
|
||||
tstConf.initConfig(confPath=fncPath, dataPath=fncPath)
|
||||
|
||||
# GUI Scaling
|
||||
# ===========
|
||||
|
||||
tmpConf.guiScale = 1.0
|
||||
assert tmpConf.pxInt(10) == 10
|
||||
assert tmpConf.pxInt(13) == 13
|
||||
assert tmpConf.rpxInt(10) == 10
|
||||
assert tmpConf.rpxInt(13) == 13
|
||||
tstConf.guiScale = 1.0
|
||||
assert tstConf.pxInt(10) == 10
|
||||
assert tstConf.pxInt(13) == 13
|
||||
assert tstConf.rpxInt(10) == 10
|
||||
assert tstConf.rpxInt(13) == 13
|
||||
|
||||
tmpConf.guiScale = 2.0
|
||||
assert tmpConf.pxInt(10) == 20
|
||||
assert tmpConf.pxInt(13) == 26
|
||||
assert tmpConf.rpxInt(10) == 5
|
||||
assert tmpConf.rpxInt(13) == 6
|
||||
tstConf.guiScale = 2.0
|
||||
assert tstConf.pxInt(10) == 20
|
||||
assert tstConf.pxInt(13) == 26
|
||||
assert tstConf.rpxInt(10) == 5
|
||||
assert tstConf.rpxInt(13) == 6
|
||||
|
||||
# Setter + Getter Combos
|
||||
# ======================
|
||||
|
||||
# Window Size
|
||||
tmpConf.guiScale = 1.0
|
||||
tmpConf.setMainWinSize(1205, 655)
|
||||
assert tmpConf.mainWinSize == [1200, 650]
|
||||
tstConf.guiScale = 1.0
|
||||
tstConf.setMainWinSize(1205, 655)
|
||||
assert tstConf.mainWinSize == [1200, 650]
|
||||
|
||||
tmpConf.guiScale = 2.0
|
||||
tmpConf.setMainWinSize(70, 70)
|
||||
assert tmpConf.mainWinSize == [70, 70]
|
||||
assert tmpConf._mainWinSize == [35, 35]
|
||||
tstConf.guiScale = 2.0
|
||||
tstConf.setMainWinSize(70, 70)
|
||||
assert tstConf.mainWinSize == [70, 70]
|
||||
assert tstConf._mainWinSize == [35, 35]
|
||||
|
||||
tmpConf.guiScale = 1.0
|
||||
tmpConf.setMainWinSize(70, 70)
|
||||
assert tmpConf.mainWinSize == [70, 70]
|
||||
assert tmpConf._mainWinSize == [70, 70]
|
||||
tstConf.guiScale = 1.0
|
||||
tstConf.setMainWinSize(70, 70)
|
||||
assert tstConf.mainWinSize == [70, 70]
|
||||
assert tstConf._mainWinSize == [70, 70]
|
||||
|
||||
tmpConf.setMainWinSize(1200, 650)
|
||||
tstConf.setMainWinSize(1200, 650)
|
||||
|
||||
# Preferences Size
|
||||
tmpConf.guiScale = 2.0
|
||||
tmpConf.setPreferencesWinSize(70, 70)
|
||||
assert tmpConf.preferencesWinSize == [70, 70]
|
||||
assert tmpConf._prefsWinSize == [35, 35]
|
||||
tstConf.guiScale = 2.0
|
||||
tstConf.setPreferencesWinSize(70, 70)
|
||||
assert tstConf.preferencesWinSize == [70, 70]
|
||||
assert tstConf._prefsWinSize == [35, 35]
|
||||
|
||||
tmpConf.guiScale = 1.0
|
||||
tmpConf.setPreferencesWinSize(70, 70)
|
||||
assert tmpConf.preferencesWinSize == [70, 70]
|
||||
assert tmpConf._prefsWinSize == [70, 70]
|
||||
tstConf.guiScale = 1.0
|
||||
tstConf.setPreferencesWinSize(70, 70)
|
||||
assert tstConf.preferencesWinSize == [70, 70]
|
||||
assert tstConf._prefsWinSize == [70, 70]
|
||||
|
||||
tmpConf.setPreferencesWinSize(700, 615)
|
||||
tstConf.setPreferencesWinSize(700, 615)
|
||||
|
||||
# Project Settings Tree Columns
|
||||
tmpConf.guiScale = 2.0
|
||||
tmpConf.setProjLoadColWidths([10, 20, 30])
|
||||
assert tmpConf.projLoadColWidths == [10, 20, 30]
|
||||
assert tmpConf._projLoadCols == [5, 10, 15]
|
||||
tstConf.guiScale = 2.0
|
||||
tstConf.setProjLoadColWidths([10, 20, 30])
|
||||
assert tstConf.projLoadColWidths == [10, 20, 30]
|
||||
assert tstConf._projLoadCols == [5, 10, 15]
|
||||
|
||||
tmpConf.guiScale = 1.0
|
||||
tmpConf.setProjLoadColWidths([10, 20, 30])
|
||||
assert tmpConf.projLoadColWidths == [10, 20, 30]
|
||||
assert tmpConf._projLoadCols == [10, 20, 30]
|
||||
tstConf.guiScale = 1.0
|
||||
tstConf.setProjLoadColWidths([10, 20, 30])
|
||||
assert tstConf.projLoadColWidths == [10, 20, 30]
|
||||
assert tstConf._projLoadCols == [10, 20, 30]
|
||||
|
||||
tmpConf.setProjLoadColWidths([200, 60, 140])
|
||||
tstConf.setProjLoadColWidths([200, 60, 140])
|
||||
|
||||
# Main Pane Splitter
|
||||
tmpConf.guiScale = 2.0
|
||||
tmpConf.setMainPanePos([200, 700])
|
||||
assert tmpConf.mainPanePos == [200, 700]
|
||||
assert tmpConf._mainPanePos == [100, 350]
|
||||
tstConf.guiScale = 2.0
|
||||
tstConf.setMainPanePos([200, 700])
|
||||
assert tstConf.mainPanePos == [200, 700]
|
||||
assert tstConf._mainPanePos == [100, 350]
|
||||
|
||||
tmpConf.guiScale = 1.0
|
||||
tmpConf.setMainPanePos([200, 700])
|
||||
assert tmpConf.mainPanePos == [200, 700]
|
||||
assert tmpConf._mainPanePos == [200, 700]
|
||||
tstConf.guiScale = 1.0
|
||||
tstConf.setMainPanePos([200, 700])
|
||||
assert tstConf.mainPanePos == [200, 700]
|
||||
assert tstConf._mainPanePos == [200, 700]
|
||||
|
||||
tmpConf.setMainPanePos([300, 800])
|
||||
tstConf.setMainPanePos([300, 800])
|
||||
|
||||
# View Pane Splitter
|
||||
tmpConf.guiScale = 2.0
|
||||
tmpConf.setViewPanePos([400, 250])
|
||||
assert tmpConf.viewPanePos == [400, 250]
|
||||
assert tmpConf._viewPanePos == [200, 125]
|
||||
tstConf.guiScale = 2.0
|
||||
tstConf.setViewPanePos([400, 250])
|
||||
assert tstConf.viewPanePos == [400, 250]
|
||||
assert tstConf._viewPanePos == [200, 125]
|
||||
|
||||
tmpConf.guiScale = 1.0
|
||||
tmpConf.setViewPanePos([400, 250])
|
||||
assert tmpConf.viewPanePos == [400, 250]
|
||||
assert tmpConf._viewPanePos == [400, 250]
|
||||
tstConf.guiScale = 1.0
|
||||
tstConf.setViewPanePos([400, 250])
|
||||
assert tstConf.viewPanePos == [400, 250]
|
||||
assert tstConf._viewPanePos == [400, 250]
|
||||
|
||||
tmpConf.setViewPanePos([500, 150])
|
||||
tstConf.setViewPanePos([500, 150])
|
||||
|
||||
# Outline Pane Splitter
|
||||
tmpConf.guiScale = 2.0
|
||||
tmpConf.setOutlinePanePos([400, 250])
|
||||
assert tmpConf.outlinePanePos == [400, 250]
|
||||
assert tmpConf._outlnPanePos == [200, 125]
|
||||
tstConf.guiScale = 2.0
|
||||
tstConf.setOutlinePanePos([400, 250])
|
||||
assert tstConf.outlinePanePos == [400, 250]
|
||||
assert tstConf._outlnPanePos == [200, 125]
|
||||
|
||||
tmpConf.guiScale = 1.0
|
||||
tmpConf.setOutlinePanePos([400, 250])
|
||||
assert tmpConf.outlinePanePos == [400, 250]
|
||||
assert tmpConf._outlnPanePos == [400, 250]
|
||||
tstConf.guiScale = 1.0
|
||||
tstConf.setOutlinePanePos([400, 250])
|
||||
assert tstConf.outlinePanePos == [400, 250]
|
||||
assert tstConf._outlnPanePos == [400, 250]
|
||||
|
||||
tmpConf.setOutlinePanePos([500, 150])
|
||||
tstConf.setOutlinePanePos([500, 150])
|
||||
|
||||
# Getters Only
|
||||
# ============
|
||||
|
||||
tmpConf.guiScale = 1.0
|
||||
assert tmpConf.getTextWidth(False) == 700
|
||||
assert tmpConf.getTextWidth(True) == 800
|
||||
assert tmpConf.getTextMargin() == 40
|
||||
assert tmpConf.getTabWidth() == 40
|
||||
tstConf.guiScale = 1.0
|
||||
assert tstConf.getTextWidth(False) == 700
|
||||
assert tstConf.getTextWidth(True) == 800
|
||||
assert tstConf.getTextMargin() == 40
|
||||
assert tstConf.getTabWidth() == 40
|
||||
|
||||
tmpConf.guiScale = 2.0
|
||||
assert tmpConf.getTextWidth(False) == 1400
|
||||
assert tmpConf.getTextWidth(True) == 1600
|
||||
assert tmpConf.getTextMargin() == 80
|
||||
assert tmpConf.getTabWidth() == 80
|
||||
tstConf.guiScale = 2.0
|
||||
assert tstConf.getTextWidth(False) == 1400
|
||||
assert tstConf.getTextWidth(True) == 1600
|
||||
assert tstConf.getTextMargin() == 80
|
||||
assert tstConf.getTabWidth() == 80
|
||||
|
||||
# END Test testBaseConfig_SettersGetters
|
||||
|
||||
|
||||
@pytest.mark.base
|
||||
def testBaseConfig_Internal(monkeypatch, tmpConf):
|
||||
def testBaseConfig_Internal(monkeypatch, fncPath):
|
||||
"""Check internal functions.
|
||||
"""
|
||||
tstConf = Config()
|
||||
tstConf.initConfig(confPath=fncPath, dataPath=fncPath)
|
||||
|
||||
# Function _packList
|
||||
assert tmpConf._packList(["A", 1, 2.0, None, False]) == "A, 1, 2.0, None, False"
|
||||
assert tstConf._packList(["A", 1, 2.0, None, False]) == "A, 1, 2.0, None, False"
|
||||
|
||||
# Function _checkNone
|
||||
assert tmpConf._checkNone(None) is None
|
||||
assert tmpConf._checkNone("None") is None
|
||||
assert tmpConf._checkNone("none") is None
|
||||
assert tmpConf._checkNone("NONE") is None
|
||||
assert tmpConf._checkNone("NoNe") is None
|
||||
assert tmpConf._checkNone(123456) == 123456
|
||||
assert tstConf._checkNone(None) is None
|
||||
assert tstConf._checkNone("None") is None
|
||||
assert tstConf._checkNone("none") is None
|
||||
assert tstConf._checkNone("NONE") is None
|
||||
assert tstConf._checkNone("NoNe") is None
|
||||
assert tstConf._checkNone(123456) == 123456
|
||||
|
||||
# Function _checkOptionalPackages
|
||||
# (Assumes enchant package exists and is importable)
|
||||
tmpConf._checkOptionalPackages()
|
||||
assert tmpConf.hasEnchant is True
|
||||
tstConf._checkOptionalPackages()
|
||||
assert tstConf.hasEnchant is True
|
||||
|
||||
with monkeypatch.context() as mp:
|
||||
mp.setitem(sys.modules, "enchant", None)
|
||||
tmpConf._checkOptionalPackages()
|
||||
assert tmpConf.hasEnchant is False
|
||||
tstConf._checkOptionalPackages()
|
||||
assert tstConf.hasEnchant is False
|
||||
|
||||
# END Test testBaseConfig_Internal
|
||||
|
||||
|
||||
@pytest.mark.base
|
||||
def testBaseConfig_RecentCache(monkeypatch, fncConf, fncPath):
|
||||
def testBaseConfig_RecentCache(monkeypatch, tstPaths):
|
||||
"""Test recent cache file.
|
||||
"""
|
||||
cacheFile = fncPath / nwFiles.RECENT_FILE
|
||||
recent = RecentProjects(fncConf)
|
||||
cacheFile = tstPaths.cnfDir / nwFiles.RECENT_FILE
|
||||
recent = RecentProjects(CONFIG)
|
||||
|
||||
# Load when there is no file should pass, but load nothing
|
||||
assert not cacheFile.exists()
|
||||
@@ -394,8 +404,8 @@ def testBaseConfig_RecentCache(monkeypatch, fncConf, fncPath):
|
||||
assert recent.listEntries() == []
|
||||
|
||||
# Add a couple of values
|
||||
pathOne = fncPath / "projPathOne" / nwFiles.PROJ_FILE
|
||||
pathTwo = fncPath / "projPathTwo" / nwFiles.PROJ_FILE
|
||||
pathOne = tstPaths.cnfDir / "projPathOne" / nwFiles.PROJ_FILE
|
||||
pathTwo = tstPaths.cnfDir / "projPathTwo" / nwFiles.PROJ_FILE
|
||||
|
||||
recent.update(pathOne, "Proj One", 100, 1600002000)
|
||||
recent.update(pathTwo, "Proj Two", 200, 1600005600)
|
||||
|
||||
@@ -22,46 +22,47 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
import sys
|
||||
import pytest
|
||||
import logging
|
||||
import novelwriter
|
||||
|
||||
from mock import MockGuiMain
|
||||
|
||||
from novelwriter import CONFIG, main, logger
|
||||
|
||||
|
||||
@pytest.mark.base
|
||||
def testBaseInit_Launch(caplog, monkeypatch, tmpPath):
|
||||
def testBaseInit_Launch(caplog, monkeypatch, fncPath):
|
||||
"""Check launching the main GUI.
|
||||
"""
|
||||
monkeypatch.setattr("novelwriter.guimain.GuiMain", MockGuiMain)
|
||||
|
||||
# TestMode Launch
|
||||
nwGUI = novelwriter.main(["--testmode", f"--config={tmpPath}", f"--data={tmpPath}"])
|
||||
nwGUI = main(["--testmode", f"--config={fncPath}", f"--data={fncPath}"])
|
||||
assert isinstance(nwGUI, MockGuiMain)
|
||||
|
||||
# Darwin Launch
|
||||
caplog.clear()
|
||||
osDarwin = novelwriter.CONFIG.osDarwin
|
||||
novelwriter.CONFIG.osDarwin = True
|
||||
osDarwin = CONFIG.osDarwin
|
||||
CONFIG.osDarwin = True
|
||||
with monkeypatch.context() as mp:
|
||||
mp.setitem(sys.modules, "Foundation", None)
|
||||
nwGUI = novelwriter.main(["--testmode", f"--config={tmpPath}", f"--data={tmpPath}"])
|
||||
nwGUI = main(["--testmode", f"--config={fncPath}", f"--data={fncPath}"])
|
||||
assert isinstance(nwGUI, MockGuiMain)
|
||||
assert "Failed" in caplog.text
|
||||
|
||||
novelwriter.CONFIG.osDarwin = osDarwin
|
||||
CONFIG.osDarwin = osDarwin
|
||||
|
||||
# Windows Launch
|
||||
caplog.clear()
|
||||
osWindows = novelwriter.CONFIG.osWindows
|
||||
novelwriter.CONFIG.osWindows = True
|
||||
osWindows = CONFIG.osWindows
|
||||
CONFIG.osWindows = True
|
||||
with monkeypatch.context() as mp:
|
||||
mp.setitem(sys.modules, "ctypes", None)
|
||||
nwGUI = novelwriter.main(["--testmode", f"--config={tmpPath}", f"--data={tmpPath}"])
|
||||
nwGUI = main(["--testmode", f"--config={fncPath}", f"--data={fncPath}"])
|
||||
assert isinstance(nwGUI, MockGuiMain)
|
||||
if not sys.platform.startswith("darwin"):
|
||||
# For some reason, the test doesn't work on macOS
|
||||
assert "Failed" in caplog.text
|
||||
|
||||
novelwriter.CONFIG.osWindows = osWindows
|
||||
CONFIG.osWindows = osWindows
|
||||
|
||||
# Normal Launch
|
||||
monkeypatch.setattr("PyQt5.QtWidgets.QApplication.__init__", lambda *a: None)
|
||||
@@ -71,72 +72,72 @@ def testBaseInit_Launch(caplog, monkeypatch, tmpPath):
|
||||
monkeypatch.setattr("PyQt5.QtWidgets.QApplication.setOrganizationDomain", lambda *a: None)
|
||||
monkeypatch.setattr("PyQt5.QtWidgets.QApplication.exec_", lambda *a: 0)
|
||||
with pytest.raises(SystemExit) as ex:
|
||||
novelwriter.main([f"--config={tmpPath}", f"--data={tmpPath}"])
|
||||
main([f"--config={fncPath}", f"--data={fncPath}"])
|
||||
assert ex.value.code == 0
|
||||
|
||||
# END Test testBaseInit_Launch
|
||||
|
||||
|
||||
@pytest.mark.base
|
||||
def testBaseInit_Options(monkeypatch, tmpPath):
|
||||
def testBaseInit_Options(monkeypatch, fncPath):
|
||||
"""Test command line options for logging level.
|
||||
"""
|
||||
monkeypatch.setattr("novelwriter.guimain.GuiMain", MockGuiMain)
|
||||
monkeypatch.setattr(sys, "argv", [
|
||||
"novelWriter.py", "--testmode", f"--config={tmpPath}", f"--data={tmpPath}"
|
||||
"novelWriter.py", "--testmode", f"--config={fncPath}", f"--data={fncPath}"
|
||||
])
|
||||
|
||||
# Defaults w/None Args
|
||||
nwGUI = novelwriter.main()
|
||||
assert novelwriter.logger.getEffectiveLevel() == logging.WARNING
|
||||
nwGUI = main()
|
||||
assert logger.getEffectiveLevel() == logging.WARNING
|
||||
assert nwGUI.closeMain() == "closeMain"
|
||||
|
||||
# Defaults
|
||||
nwGUI = novelwriter.main(
|
||||
["--testmode", f"--config={tmpPath}", f"--data={tmpPath}", "--style=Fusion"]
|
||||
nwGUI = main(
|
||||
["--testmode", f"--config={fncPath}", f"--data={fncPath}", "--style=Fusion"]
|
||||
)
|
||||
assert novelwriter.logger.getEffectiveLevel() == logging.WARNING
|
||||
assert logger.getEffectiveLevel() == logging.WARNING
|
||||
assert nwGUI.closeMain() == "closeMain"
|
||||
|
||||
# Log Levels
|
||||
nwGUI = novelwriter.main(
|
||||
["--testmode", "--info", f"--config={tmpPath}", f"--data={tmpPath}"]
|
||||
nwGUI = main(
|
||||
["--testmode", "--info", f"--config={fncPath}", f"--data={fncPath}"]
|
||||
)
|
||||
assert novelwriter.logger.getEffectiveLevel() == logging.INFO
|
||||
assert logger.getEffectiveLevel() == logging.INFO
|
||||
assert nwGUI.closeMain() == "closeMain"
|
||||
|
||||
nwGUI = novelwriter.main(
|
||||
["--testmode", "--debug", f"--config={tmpPath}", f"--data={tmpPath}"]
|
||||
nwGUI = main(
|
||||
["--testmode", "--debug", f"--config={fncPath}", f"--data={fncPath}"]
|
||||
)
|
||||
assert novelwriter.logger.getEffectiveLevel() == logging.DEBUG
|
||||
assert logger.getEffectiveLevel() == logging.DEBUG
|
||||
assert nwGUI.closeMain() == "closeMain"
|
||||
|
||||
# Help and Version
|
||||
with pytest.raises(SystemExit) as ex:
|
||||
nwGUI = novelwriter.main(
|
||||
["--testmode", "--help", f"--config={tmpPath}", f"--data={tmpPath}"]
|
||||
nwGUI = main(
|
||||
["--testmode", "--help", f"--config={fncPath}", f"--data={fncPath}"]
|
||||
)
|
||||
assert nwGUI.closeMain() == "closeMain"
|
||||
assert ex.value.code == 0
|
||||
|
||||
with pytest.raises(SystemExit) as ex:
|
||||
nwGUI = novelwriter.main(
|
||||
["--testmode", "--version", f"--config={tmpPath}", f"--data={tmpPath}"]
|
||||
nwGUI = main(
|
||||
["--testmode", "--version", f"--config={fncPath}", f"--data={fncPath}"]
|
||||
)
|
||||
assert nwGUI.closeMain() == "closeMain"
|
||||
assert ex.value.code == 0
|
||||
|
||||
# Invalid options
|
||||
with pytest.raises(SystemExit) as ex:
|
||||
nwGUI = novelwriter.main(
|
||||
["--testmode", "--invalid", f"--config={tmpPath}", f"--data={tmpPath}"]
|
||||
nwGUI = main(
|
||||
["--testmode", "--invalid", f"--config={fncPath}", f"--data={fncPath}"]
|
||||
)
|
||||
assert nwGUI.closeMain() == "closeMain"
|
||||
assert ex.value.code == 2
|
||||
|
||||
# Project Path
|
||||
nwGUI = novelwriter.main(
|
||||
["--testmode", f"--config={tmpPath}", f"--data={tmpPath}", "sample/"]
|
||||
nwGUI = main(
|
||||
["--testmode", f"--config={fncPath}", f"--data={fncPath}", "sample/"]
|
||||
)
|
||||
assert nwGUI.closeMain() == "closeMain"
|
||||
|
||||
@@ -144,7 +145,7 @@ def testBaseInit_Options(monkeypatch, tmpPath):
|
||||
|
||||
|
||||
@pytest.mark.base
|
||||
def testBaseInit_Imports(caplog, monkeypatch, tmpPath):
|
||||
def testBaseInit_Imports(caplog, monkeypatch, fncPath):
|
||||
"""Check import error handling.
|
||||
"""
|
||||
monkeypatch.setattr("novelwriter.guimain.GuiMain", MockGuiMain)
|
||||
@@ -159,8 +160,8 @@ def testBaseInit_Imports(caplog, monkeypatch, tmpPath):
|
||||
monkeypatch.setattr("novelwriter.CONFIG.verPyQtValue", 0x050000)
|
||||
|
||||
with pytest.raises(SystemExit) as ex:
|
||||
_ = novelwriter.main(
|
||||
["--testmode", f"--config={tmpPath}", f"--data={tmpPath}"]
|
||||
_ = main(
|
||||
["--testmode", f"--config={fncPath}", f"--data={fncPath}"]
|
||||
)
|
||||
|
||||
assert ex.value.code & 4 == 4 # Python version not satisfied
|
||||
|
||||
@@ -28,6 +28,7 @@ from zipfile import ZipFile
|
||||
from mock import causeOSError
|
||||
from tools import C, buildTestProject, cmpFiles, XML_IGNORE
|
||||
|
||||
from novelwriter import CONFIG
|
||||
from novelwriter.constants import nwItemClass
|
||||
from novelwriter.core.project import NWProject
|
||||
from novelwriter.core.coretools import DocMerger, DocSplitter, ProjectBuilder
|
||||
@@ -371,7 +372,7 @@ def testCoreTools_NewCustomB(monkeypatch, fncPath, tstPaths, mockGUI, mockRnd):
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreTools_NewSample(monkeypatch, fncPath, tmpConf, tmpPath, mockGUI):
|
||||
def testCoreTools_NewSample(monkeypatch, fncPath, tstPaths, mockGUI):
|
||||
"""Check that we can create a new project can be created from the
|
||||
provided sample project via a zip file.
|
||||
"""
|
||||
@@ -391,10 +392,10 @@ def testCoreTools_NewSample(monkeypatch, fncPath, tmpConf, tmpPath, mockGUI):
|
||||
assert projBuild.buildProject({"popSample": True}) is False
|
||||
|
||||
# Force the lookup path for assets to our temp folder
|
||||
srcSample = tmpConf._appRoot / "sample"
|
||||
dstSample = tmpPath / "sample.zip"
|
||||
srcSample = CONFIG._appRoot / "sample"
|
||||
dstSample = tstPaths.tmpDir / "sample.zip"
|
||||
monkeypatch.setattr(
|
||||
"novelwriter.config.Config.assetPath", lambda *a: tmpPath / "sample.zip"
|
||||
"novelwriter.config.Config.assetPath", lambda *a: tstPaths.tmpDir / "sample.zip"
|
||||
)
|
||||
|
||||
# Cannot extract when the zip does not exist
|
||||
|
||||
@@ -29,6 +29,7 @@ from zipfile import ZipFile
|
||||
from mock import causeOSError
|
||||
from tools import C, cmpFiles, writeFile, buildTestProject, XML_IGNORE
|
||||
|
||||
from novelwriter import CONFIG
|
||||
from novelwriter.enum import nwItemClass, nwItemType, nwItemLayout
|
||||
from novelwriter.common import formatTimeStamp
|
||||
from novelwriter.constants import nwFiles
|
||||
@@ -704,7 +705,7 @@ def testCoreProject_OrphanedFiles(mockGUI, prjLipsum):
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreProject_Backup(monkeypatch, mockGUI, fncPath, tmpPath):
|
||||
def testCoreProject_Backup(monkeypatch, mockGUI, fncPath, tstPaths):
|
||||
"""Test the automated backup feature of the project class. The test
|
||||
creates a backup of the Minimal test project, and then unzips the
|
||||
backupd file and checks that the project XML file is identical to
|
||||
@@ -720,23 +721,18 @@ def testCoreProject_Backup(monkeypatch, mockGUI, fncPath, tmpPath):
|
||||
# Invalid Settings
|
||||
# ================
|
||||
|
||||
# No project
|
||||
mockGUI.hasProject = False
|
||||
assert theProject.backupProject(doNotify=False) is False
|
||||
mockGUI.hasProject = True
|
||||
|
||||
# Invalid path
|
||||
theProject.mainConf._backupPath = None
|
||||
CONFIG._backupPath = None
|
||||
assert theProject.backupProject(doNotify=False) is False
|
||||
|
||||
# Missing project name
|
||||
theProject.mainConf._backupPath = tmpPath
|
||||
CONFIG._backupPath = tstPaths.tmpDir
|
||||
theProject.data.setName("")
|
||||
assert theProject.backupProject(doNotify=False) is False
|
||||
|
||||
# Valid Settings
|
||||
# ==============
|
||||
theProject.mainConf._backupPath = tmpPath
|
||||
CONFIG._backupPath = tstPaths.tmpDir
|
||||
theProject.data.setName("Test Minimal")
|
||||
|
||||
# Can't make folder
|
||||
@@ -752,7 +748,7 @@ def testCoreProject_Backup(monkeypatch, mockGUI, fncPath, tmpPath):
|
||||
# Test correct settings
|
||||
assert theProject.backupProject(doNotify=True) is True
|
||||
|
||||
theFiles = list((tmpPath / "Test Minimal").iterdir())
|
||||
theFiles = list((tstPaths.tmpDir / "Test Minimal").iterdir())
|
||||
assert len(theFiles) == 1
|
||||
|
||||
theZip = theFiles[0].name
|
||||
@@ -760,13 +756,13 @@ def testCoreProject_Backup(monkeypatch, mockGUI, fncPath, tmpPath):
|
||||
assert theZip[-4:] == ".zip"
|
||||
|
||||
# Extract the archive
|
||||
with ZipFile(tmpPath / "Test Minimal" / theZip, mode="r") as inZip:
|
||||
inZip.extractall(tmpPath / "extract")
|
||||
with ZipFile(tstPaths.tmpDir / "Test Minimal" / theZip, mode="r") as inZip:
|
||||
inZip.extractall(tstPaths.tmpDir / "extract")
|
||||
|
||||
# Check that the main project file was restored
|
||||
assert cmpFiles(
|
||||
fncPath / "nwProject.nwx",
|
||||
tmpPath / "extract" / "nwProject.nwx"
|
||||
tstPaths.tmpDir / "extract" / "nwProject.nwx"
|
||||
)
|
||||
|
||||
# END Test testCoreProject_Backup
|
||||
|
||||
@@ -40,8 +40,8 @@ class MockProject:
|
||||
|
||||
@pytest.fixture(scope="function", autouse=True)
|
||||
def mockVersion(monkeypatch):
|
||||
monkeypatch.setattr("novelwriter.__version__", "2.0-rc1")
|
||||
monkeypatch.setattr("novelwriter.__hexversion__", "0x020000c1")
|
||||
monkeypatch.setattr("novelwriter.core.projectxml.__version__", "2.0-rc1")
|
||||
monkeypatch.setattr("novelwriter.core.projectxml.__hexversion__", "0x020000c1")
|
||||
return
|
||||
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import pytest
|
||||
from mock import causeOSError
|
||||
from tools import C, buildTestProject, writeFile
|
||||
|
||||
from novelwriter import CONFIG
|
||||
from novelwriter.constants import nwFiles
|
||||
from novelwriter.core.project import NWProject
|
||||
from novelwriter.core.storage import NWStorage
|
||||
@@ -148,9 +149,9 @@ def testCoreStorage_LockFile(monkeypatch, fncPath):
|
||||
|
||||
# Successful read
|
||||
assert storage.readLockFile() == [
|
||||
storage.mainConf.hostName,
|
||||
storage.mainConf.osType,
|
||||
storage.mainConf.kernelVer,
|
||||
CONFIG.hostName,
|
||||
CONFIG.osType,
|
||||
CONFIG.kernelVer,
|
||||
"1000",
|
||||
]
|
||||
|
||||
@@ -299,10 +300,10 @@ def testCoreStorage_PrepareStorage(monkeypatch, fncPath):
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreStorage_ZipIt(monkeypatch, mockGUI, fncPath, tmpPath, mockRnd):
|
||||
def testCoreStorage_ZipIt(monkeypatch, mockGUI, fncPath, tstPaths, mockRnd):
|
||||
"""Test making a zip archive of a project.
|
||||
"""
|
||||
zipFile = tmpPath / "project.zip"
|
||||
zipFile = tstPaths.tmpDir / "project.zip"
|
||||
|
||||
theProject = NWProject(mockGUI)
|
||||
storage = theProject.storage
|
||||
|
||||
@@ -437,7 +437,7 @@ def testCoreTree_Reorder(caplog, mockGUI, mockItems):
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreTree_ToCFile(monkeypatch, mockGUI, mockItems, tmpPath):
|
||||
def testCoreTree_ToCFile(monkeypatch, tstPaths, mockGUI, mockItems):
|
||||
"""Test writing the ToC.txt file.
|
||||
"""
|
||||
theProject = NWProject(mockGUI)
|
||||
@@ -463,20 +463,20 @@ def testCoreTree_ToCFile(monkeypatch, mockGUI, mockItems, tmpPath):
|
||||
theProject._storage._runtimePath = None
|
||||
assert theTree.writeToCFile() is False
|
||||
|
||||
theProject._storage._runtimePath = tmpPath
|
||||
theProject._storage._runtimePath = tstPaths.tmpDir
|
||||
with monkeypatch.context() as mp:
|
||||
mp.setattr("builtins.open", causeOSError)
|
||||
assert theTree.writeToCFile() is False
|
||||
|
||||
theProject._storage._runtimePath = tmpPath
|
||||
(tmpPath / "content").mkdir()
|
||||
theProject._storage._runtimePath = tstPaths.tmpDir
|
||||
(tstPaths.tmpDir / "content").mkdir()
|
||||
assert theTree.writeToCFile() is True
|
||||
|
||||
pathA = str(Path("content") / "c000000000001.nwd")
|
||||
pathB = str(Path("content") / "c000000000002.nwd")
|
||||
pathC = str(Path("content") / "b000000000002.nwd")
|
||||
|
||||
assert readFile(tmpPath / nwFiles.TOC_TXT) == (
|
||||
assert readFile(tstPaths.tmpDir / nwFiles.TOC_TXT) == (
|
||||
"\n"
|
||||
"Table of Contents\n"
|
||||
"=================\n"
|
||||
|
||||
@@ -30,6 +30,7 @@ from PyQt5.QtWidgets import (
|
||||
QDialogButtonBox, QDialog, QAction, QFileDialog, QFontDialog
|
||||
)
|
||||
|
||||
from novelwriter import CONFIG
|
||||
from novelwriter.dialogs.quotes import GuiQuoteSelect
|
||||
from novelwriter.dialogs.preferences import GuiPreferences
|
||||
|
||||
@@ -37,12 +38,9 @@ KEY_DELAY = 1
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
def testDlgPreferences_Main(qtbot, monkeypatch, nwGUI, fncPath, tstPaths):
|
||||
def testDlgPreferences_Main(qtbot, monkeypatch, nwGUI, tstPaths):
|
||||
"""Test the load project wizard.
|
||||
"""
|
||||
theConf = nwGUI.mainConf
|
||||
assert theConf._confPath == fncPath
|
||||
|
||||
monkeypatch.setattr(GuiPreferences, "exec_", lambda *a: None)
|
||||
monkeypatch.setattr(GuiPreferences, "result", lambda *a: QDialog.Accepted)
|
||||
monkeypatch.setattr(nwGUI.docEditor.spEnchant, "listDictionaries", lambda: [("en", "none")])
|
||||
@@ -58,7 +56,6 @@ def testDlgPreferences_Main(qtbot, monkeypatch, nwGUI, fncPath, tstPaths):
|
||||
nwPrefs = getGuiItem("GuiPreferences")
|
||||
assert isinstance(nwPrefs, GuiPreferences)
|
||||
nwPrefs.show()
|
||||
assert nwPrefs.mainConf._confPath == fncPath
|
||||
|
||||
assert nwPrefs.updateTheme is False
|
||||
assert nwPrefs.updateSyntax is False
|
||||
@@ -215,8 +212,8 @@ def testDlgPreferences_Main(qtbot, monkeypatch, nwGUI, fncPath, tstPaths):
|
||||
qtbot.mouseClick(nwPrefs.buttonBox.button(QDialogButtonBox.Ok), Qt.LeftButton)
|
||||
nwPrefs._doClose()
|
||||
|
||||
assert nwGUI.mainConf.saveConfig()
|
||||
projFile = fncPath / "novelwriter.conf"
|
||||
assert CONFIG.saveConfig()
|
||||
projFile = tstPaths.cnfDir / "novelwriter.conf"
|
||||
testFile = tstPaths.outDir / "guiPreferences_novelwriter.conf"
|
||||
compFile = tstPaths.refDir / "guiPreferences_novelwriter.conf"
|
||||
copyfile(projFile, testFile)
|
||||
|
||||
@@ -21,13 +21,14 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import pytest
|
||||
|
||||
from novelwriter.enum import nwItemType
|
||||
from tools import C, getGuiItem, buildTestProject
|
||||
|
||||
from PyQt5.QtGui import QColor
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import QDialog, QAction, QColorDialog
|
||||
|
||||
from novelwriter import CONFIG
|
||||
from novelwriter.enum import nwItemType
|
||||
from novelwriter.dialogs.editlabel import GuiEditLabel
|
||||
from novelwriter.dialogs.projsettings import GuiProjectSettings
|
||||
|
||||
@@ -91,7 +92,7 @@ def testDlgProjSettings_Main(qtbot, monkeypatch, nwGUI, fncPath, projPath, mockR
|
||||
# Create new project
|
||||
buildTestProject(nwGUI, projPath)
|
||||
mockRnd.reset()
|
||||
nwGUI.mainConf.backupPath = fncPath
|
||||
CONFIG.setBackupPath(fncPath)
|
||||
|
||||
# Set some values
|
||||
theProject = nwGUI.theProject
|
||||
@@ -156,7 +157,7 @@ def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, fncPath, projPat
|
||||
# Create new project
|
||||
mockRnd.reset()
|
||||
buildTestProject(nwGUI, projPath)
|
||||
nwGUI.mainConf.backupPath = fncPath
|
||||
CONFIG.setBackupPath(fncPath)
|
||||
|
||||
# Set some values
|
||||
theProject = nwGUI.theProject
|
||||
@@ -357,7 +358,7 @@ def testDlgProjSettings_Replace(qtbot, monkeypatch, nwGUI, fncPath, projPath, mo
|
||||
# Create new project
|
||||
mockRnd.reset()
|
||||
buildTestProject(nwGUI, projPath)
|
||||
nwGUI.mainConf.backupPath = fncPath
|
||||
CONFIG.setBackupPath(fncPath)
|
||||
|
||||
# Set some values
|
||||
theProject = nwGUI.theProject
|
||||
|
||||
@@ -28,6 +28,7 @@ from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtGui import QTextBlock, QTextCursor, QTextOption
|
||||
from PyQt5.QtWidgets import QAction, qApp
|
||||
|
||||
from novelwriter import CONFIG
|
||||
from novelwriter.enum import nwDocAction, nwDocInsert, nwItemLayout
|
||||
from novelwriter.constants import nwKeyWords, nwUnicode
|
||||
from novelwriter.core.index import countWords
|
||||
@@ -55,18 +56,18 @@ def testGuiEditor_Init(qtbot, nwGUI, projPath, ipsumText, mockRnd):
|
||||
assert nwGUI.docEditor._typPadChar == nwUnicode.U_NBSP
|
||||
|
||||
# Check that editor handles settings
|
||||
nwGUI.mainConf.textFont = None
|
||||
nwGUI.mainConf.doJustify = True
|
||||
nwGUI.mainConf.showTabsNSpaces = True
|
||||
nwGUI.mainConf.showLineEndings = True
|
||||
nwGUI.mainConf.hideVScroll = True
|
||||
nwGUI.mainConf.hideHScroll = True
|
||||
nwGUI.mainConf.fmtPadThin = True
|
||||
CONFIG.textFont = None
|
||||
CONFIG.doJustify = True
|
||||
CONFIG.showTabsNSpaces = True
|
||||
CONFIG.showLineEndings = True
|
||||
CONFIG.hideVScroll = True
|
||||
CONFIG.hideHScroll = True
|
||||
CONFIG.fmtPadThin = True
|
||||
|
||||
assert nwGUI.docEditor.initEditor()
|
||||
|
||||
qDoc = nwGUI.docEditor.document()
|
||||
assert nwGUI.mainConf.textFont == qDoc.defaultFont().family()
|
||||
assert CONFIG.textFont == qDoc.defaultFont().family()
|
||||
assert qDoc.defaultTextOption().alignment() == Qt.AlignJustify
|
||||
assert qDoc.defaultTextOption().flags() & QTextOption.ShowTabsAndSpaces
|
||||
assert qDoc.defaultTextOption().flags() & QTextOption.ShowLineAndParagraphSeparators
|
||||
@@ -114,7 +115,7 @@ def testGuiEditor_LoadText(qtbot, monkeypatch, caplog, nwGUI, projPath, ipsumTex
|
||||
assert "The document you are trying to open is too big." in caplog.text
|
||||
|
||||
# Big doc handling
|
||||
nwGUI.mainConf.bigDocLimit = 50
|
||||
CONFIG.bigDocLimit = 50
|
||||
assert nwGUI.docEditor.loadText(C.hSceneDoc) is True
|
||||
assert nwGUI.docEditor._bigDoc is True
|
||||
|
||||
|
||||
@@ -21,11 +21,13 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import pytest
|
||||
|
||||
from mock import causeException
|
||||
|
||||
from PyQt5.QtCore import Qt, QUrl
|
||||
from PyQt5.QtGui import QTextCursor
|
||||
from PyQt5.QtWidgets import qApp, QAction
|
||||
from mock import causeException
|
||||
|
||||
from novelwriter import CONFIG
|
||||
from novelwriter.enum import nwDocAction
|
||||
from novelwriter.core.tohtml import ToHtml
|
||||
|
||||
@@ -134,10 +136,10 @@ def testGuiViewer_Main(qtbot, monkeypatch, nwGUI, nwLipsum):
|
||||
assert nwGUI.docViewer.docHeader.theTitle.text() == "Characters › Test Title"
|
||||
|
||||
# Ttile without full path
|
||||
nwGUI.mainConf.showFullPath = False
|
||||
CONFIG.showFullPath = False
|
||||
nwGUI.docViewer.updateDocInfo("4c4f28287af27")
|
||||
assert nwGUI.docViewer.docHeader.theTitle.text() == "Test Title"
|
||||
nwGUI.mainConf.showFullPath = True
|
||||
CONFIG.showFullPath = True
|
||||
|
||||
# Document footer show/hide references
|
||||
viewState = nwGUI.viewMeta.isVisible()
|
||||
|
||||
@@ -30,6 +30,7 @@ from tools import (
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import QDialog, QMessageBox, QInputDialog
|
||||
|
||||
from novelwriter import CONFIG
|
||||
from novelwriter.enum import nwItemType, nwView, nwWidget
|
||||
from novelwriter.constants import nwFiles
|
||||
from novelwriter.gui.outline import GuiOutlineView
|
||||
@@ -75,7 +76,7 @@ def testGuiMain_Launch(qtbot, monkeypatch, nwGUI, prjLipsum):
|
||||
"""
|
||||
monkeypatch.setattr(GuiProjectLoad, "exec_", lambda *a: None)
|
||||
monkeypatch.setattr(GuiProjectLoad, "result", lambda *a: QDialog.Accepted)
|
||||
nwGUI.mainConf.lastNotes = "0x0"
|
||||
CONFIG.lastNotes = "0x0"
|
||||
|
||||
# Open Lipsum project
|
||||
nwGUI.postLaunchTasks(prjLipsum)
|
||||
@@ -244,10 +245,10 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, projPath, tstPaths, mockRnd):
|
||||
assert nwGUI.mainMenu._toggleSpellCheck()
|
||||
|
||||
# Change some settings
|
||||
nwGUI.mainConf.hideHScroll = True
|
||||
nwGUI.mainConf.hideVScroll = True
|
||||
nwGUI.mainConf.autoScrollPos = 80
|
||||
nwGUI.mainConf.autoScroll = True
|
||||
CONFIG.hideHScroll = True
|
||||
CONFIG.hideVScroll = True
|
||||
CONFIG.autoScrollPos = 80
|
||||
CONFIG.autoScroll = True
|
||||
|
||||
# Add a Character File
|
||||
nwGUI.switchFocus(nwWidget.TREE)
|
||||
@@ -589,11 +590,11 @@ def testGuiMain_FocusFullMode(qtbot, nwGUI, projPath, mockRnd):
|
||||
# Full Screen Mode
|
||||
# ================
|
||||
|
||||
assert nwGUI.mainConf.isFullScreen is False
|
||||
assert CONFIG.isFullScreen is False
|
||||
nwGUI.toggleFullScreenMode()
|
||||
assert nwGUI.mainConf.isFullScreen is True
|
||||
assert CONFIG.isFullScreen is True
|
||||
nwGUI.toggleFullScreenMode()
|
||||
assert nwGUI.mainConf.isFullScreen is False
|
||||
assert CONFIG.isFullScreen is False
|
||||
|
||||
# qtbot.stop()
|
||||
|
||||
|
||||
@@ -20,20 +20,20 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import novelwriter
|
||||
|
||||
import pytest
|
||||
|
||||
from PyQt5.QtWidgets import qApp, QMessageBox
|
||||
|
||||
LANG_DATA = novelwriter.CONFIG.listLanguages(novelwriter.CONFIG.LANG_NW)
|
||||
from novelwriter import CONFIG, main
|
||||
|
||||
LANG_DATA = CONFIG.listLanguages(CONFIG.LANG_NW)
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
@pytest.mark.skipif(not sys.platform.startswith("linux"), reason="Linux Only")
|
||||
@pytest.mark.skipif(not LANG_DATA, reason="No i18n Data")
|
||||
@pytest.mark.parametrize("language", [a for a, b in LANG_DATA])
|
||||
def testI18n_Localisation(qtbot, monkeypatch, language, fncPath, fncConf):
|
||||
def testI18n_Localisation(qtbot, monkeypatch, language, fncPath):
|
||||
"""test loading the gui with a specific language.
|
||||
"""
|
||||
monkeypatch.setattr(QMessageBox, "warning", lambda *a: QMessageBox.Ok)
|
||||
@@ -42,18 +42,13 @@ def testI18n_Localisation(qtbot, monkeypatch, language, fncPath, fncConf):
|
||||
monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
|
||||
|
||||
# Set the test langauge
|
||||
monkeypatch.setattr("novelwriter.CONFIG", fncConf)
|
||||
fncConf.guiLocale = language
|
||||
fncConf.initLocalisation(qApp)
|
||||
CONFIG.guiLocale = language
|
||||
CONFIG.initLocalisation(qApp)
|
||||
|
||||
nwGUI = novelwriter.main(["--testmode", f"--config={fncPath}", f"--data={fncPath}"])
|
||||
nwGUI = main(["--testmode", f"--config={fncPath}", f"--data={fncPath}"])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.wait(20)
|
||||
nwGUI.closeMain()
|
||||
|
||||
# Reset the app language
|
||||
fncConf.guiLocale = "en_GB"
|
||||
fncConf.initLocalisation(qApp)
|
||||
|
||||
# END Test testI18n_Localisation
|
||||
|
||||
@@ -27,6 +27,7 @@ from PyQt5.QtWidgets import QAction, QFileDialog, QMessageBox
|
||||
|
||||
from tools import C, writeFile, buildTestProject
|
||||
|
||||
from novelwriter import CONFIG
|
||||
from novelwriter.enum import nwDocAction, nwDocInsert
|
||||
from novelwriter.constants import nwKeyWords, nwUnicode
|
||||
from novelwriter.gui.doceditor import GuiDocEditor
|
||||
@@ -461,19 +462,19 @@ def testGuiMenu_Insert(qtbot, monkeypatch, nwGUI, fncPath, projPath, mockRnd):
|
||||
nwGUI.docEditor.clear()
|
||||
|
||||
nwGUI.mainMenu.aInsQuoteLS.activate(QAction.Trigger)
|
||||
assert nwGUI.docEditor.getText() == nwGUI.mainConf.fmtSQuoteOpen
|
||||
assert nwGUI.docEditor.getText() == CONFIG.fmtSQuoteOpen
|
||||
nwGUI.docEditor.clear()
|
||||
|
||||
nwGUI.mainMenu.aInsQuoteRS.activate(QAction.Trigger)
|
||||
assert nwGUI.docEditor.getText() == nwGUI.mainConf.fmtSQuoteClose
|
||||
assert nwGUI.docEditor.getText() == CONFIG.fmtSQuoteClose
|
||||
nwGUI.docEditor.clear()
|
||||
|
||||
nwGUI.mainMenu.aInsQuoteLD.activate(QAction.Trigger)
|
||||
assert nwGUI.docEditor.getText() == nwGUI.mainConf.fmtDQuoteOpen
|
||||
assert nwGUI.docEditor.getText() == CONFIG.fmtDQuoteOpen
|
||||
nwGUI.docEditor.clear()
|
||||
|
||||
nwGUI.mainMenu.aInsQuoteRD.activate(QAction.Trigger)
|
||||
assert nwGUI.docEditor.getText() == nwGUI.mainConf.fmtDQuoteClose
|
||||
assert nwGUI.docEditor.getText() == CONFIG.fmtDQuoteClose
|
||||
nwGUI.docEditor.clear()
|
||||
|
||||
nwGUI.mainMenu.aInsMSApos.activate(QAction.Trigger)
|
||||
|
||||
@@ -29,6 +29,7 @@ from PyQt5.QtGui import QFocusEvent
|
||||
from PyQt5.QtCore import Qt, QEvent
|
||||
from PyQt5.QtWidgets import QInputDialog, QToolTip
|
||||
|
||||
from novelwriter import CONFIG
|
||||
from novelwriter.enum import nwWidget, nwItemType
|
||||
from novelwriter.gui.noveltree import NovelTreeColumn
|
||||
from novelwriter.dialogs.editlabel import GuiEditLabel
|
||||
@@ -67,14 +68,14 @@ def testGuiNovelTree_TreeItems(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
|
||||
# Show/Hide Scrollbars
|
||||
# ====================
|
||||
|
||||
nwGUI.mainConf.hideVScroll = True
|
||||
nwGUI.mainConf.hideHScroll = True
|
||||
CONFIG.hideVScroll = True
|
||||
CONFIG.hideHScroll = True
|
||||
novelView.initSettings()
|
||||
assert not novelTree.verticalScrollBar().isVisible()
|
||||
assert not novelTree.horizontalScrollBar().isVisible()
|
||||
|
||||
nwGUI.mainConf.hideVScroll = False
|
||||
nwGUI.mainConf.hideHScroll = False
|
||||
CONFIG.hideVScroll = False
|
||||
CONFIG.hideHScroll = False
|
||||
novelView.initSettings()
|
||||
assert novelTree.verticalScrollBar().isEnabled()
|
||||
assert novelTree.horizontalScrollBar().isEnabled()
|
||||
|
||||
@@ -28,6 +28,7 @@ from tools import buildTestProject, writeFile
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import QWidget, QAction
|
||||
|
||||
from novelwriter import CONFIG
|
||||
from novelwriter.enum import nwItemClass, nwOutline, nwView
|
||||
|
||||
|
||||
@@ -47,16 +48,16 @@ def testGuiOutline_Main(qtbot, monkeypatch, nwGUI, projPath):
|
||||
outlineMenu = outlineView.outlineBar.mColumns
|
||||
|
||||
# Toggle scrollbars
|
||||
nwGUI.mainConf.hideVScroll = True
|
||||
nwGUI.mainConf.hideHScroll = True
|
||||
CONFIG.hideVScroll = True
|
||||
CONFIG.hideHScroll = True
|
||||
outlineView.initSettings()
|
||||
assert outlineTree.verticalScrollBarPolicy() == Qt.ScrollBarAlwaysOff
|
||||
assert outlineTree.horizontalScrollBarPolicy() == Qt.ScrollBarAlwaysOff
|
||||
assert outlineData.verticalScrollBarPolicy() == Qt.ScrollBarAlwaysOff
|
||||
assert outlineData.horizontalScrollBarPolicy() == Qt.ScrollBarAlwaysOff
|
||||
|
||||
nwGUI.mainConf.hideVScroll = False
|
||||
nwGUI.mainConf.hideHScroll = False
|
||||
CONFIG.hideVScroll = False
|
||||
CONFIG.hideHScroll = False
|
||||
outlineView.initSettings()
|
||||
assert outlineTree.verticalScrollBarPolicy() == Qt.ScrollBarAsNeeded
|
||||
assert outlineTree.horizontalScrollBarPolicy() == Qt.ScrollBarAsNeeded
|
||||
|
||||
@@ -27,6 +27,7 @@ from tools import C, buildTestProject
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import QMessageBox, QMenu, QTreeWidgetItem, QDialog
|
||||
|
||||
from novelwriter import CONFIG
|
||||
from novelwriter.enum import nwItemLayout, nwItemType, nwItemClass
|
||||
from novelwriter.gui.projtree import GuiProjectTree
|
||||
from novelwriter.dialogs.docmerge import GuiDocMerge
|
||||
@@ -862,14 +863,14 @@ def testGuiProjTree_Other(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
|
||||
# ====================
|
||||
|
||||
# Test that the scrollbar setting works
|
||||
nwGUI.mainConf.hideVScroll = True
|
||||
nwGUI.mainConf.hideHScroll = True
|
||||
CONFIG.hideVScroll = True
|
||||
CONFIG.hideHScroll = True
|
||||
projView.initSettings()
|
||||
assert projTree.verticalScrollBarPolicy() == Qt.ScrollBarAlwaysOff
|
||||
assert projTree.horizontalScrollBarPolicy() == Qt.ScrollBarAlwaysOff
|
||||
|
||||
nwGUI.mainConf.hideVScroll = False
|
||||
nwGUI.mainConf.hideHScroll = False
|
||||
CONFIG.hideVScroll = False
|
||||
CONFIG.hideHScroll = False
|
||||
projView.initSettings()
|
||||
assert projTree.verticalScrollBarPolicy() == Qt.ScrollBarAsNeeded
|
||||
assert projTree.horizontalScrollBarPolicy() == Qt.ScrollBarAsNeeded
|
||||
|
||||
@@ -24,6 +24,7 @@ import pytest
|
||||
|
||||
from tools import C, buildTestProject
|
||||
|
||||
from novelwriter import CONFIG
|
||||
from novelwriter.gui.statusbar import StatusLED
|
||||
|
||||
|
||||
@@ -60,13 +61,13 @@ def testGuiStatusBar_Main(qtbot, nwGUI, projPath, mockRnd):
|
||||
assert nwGUI.mainStatus.docIcon._theCol == nwGUI.mainStatus.docIcon._colGood
|
||||
|
||||
# Idle Status
|
||||
nwGUI.mainStatus.mainConf.stopWhenIdle = False
|
||||
CONFIG.stopWhenIdle = False
|
||||
nwGUI.mainStatus.setUserIdle(True)
|
||||
nwGUI.mainStatus.updateTime()
|
||||
assert nwGUI.mainStatus.userIdle is False
|
||||
assert nwGUI.mainStatus.timeText.text() == "00:00:00"
|
||||
|
||||
nwGUI.mainStatus.mainConf.stopWhenIdle = True
|
||||
CONFIG.stopWhenIdle = True
|
||||
nwGUI.mainStatus.setUserIdle(True)
|
||||
nwGUI.mainStatus.updateTime(5)
|
||||
assert nwGUI.mainStatus.userIdle is True
|
||||
@@ -84,10 +85,10 @@ def testGuiStatusBar_Main(qtbot, nwGUI, projPath, mockRnd):
|
||||
assert nwGUI.mainStatus.langText.text() == "American English"
|
||||
|
||||
# Project Stats
|
||||
nwGUI.mainStatus.mainConf.incNotesWCount = False
|
||||
CONFIG.incNotesWCount = False
|
||||
nwGUI._updateStatusWordCount()
|
||||
assert nwGUI.mainStatus.statsText.text() == "Words: 9 (+9)"
|
||||
nwGUI.mainStatus.mainConf.incNotesWCount = True
|
||||
CONFIG.incNotesWCount = True
|
||||
nwGUI._updateStatusWordCount()
|
||||
assert nwGUI.mainStatus.statsText.text() == "Words: 11 (+11)"
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
import shutil
|
||||
import pytest
|
||||
|
||||
from pathlib import Path
|
||||
@@ -31,18 +30,17 @@ from tools import writeFile
|
||||
from PyQt5.QtGui import QIcon, QPalette, QPixmap
|
||||
from PyQt5.QtWidgets import QApplication
|
||||
|
||||
from novelwriter import CONFIG
|
||||
from novelwriter.enum import nwItemClass, nwItemLayout, nwItemType
|
||||
from novelwriter.config import Config
|
||||
from novelwriter.constants import nwLabels
|
||||
from novelwriter.gui.theme import GuiIcons, GuiTheme
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
def testGuiTheme_Main(qtbot, nwGUI, fncPath):
|
||||
def testGuiTheme_Main(qtbot, nwGUI, tstPaths):
|
||||
"""Test the theme class init.
|
||||
"""
|
||||
mainTheme: GuiTheme = nwGUI.mainTheme
|
||||
mainConf: Config = nwGUI.mainConf
|
||||
|
||||
# Methods
|
||||
# =======
|
||||
@@ -55,35 +53,35 @@ def testGuiTheme_Main(qtbot, nwGUI, fncPath):
|
||||
# ==========
|
||||
|
||||
# The defaults should be set
|
||||
defaultFont = mainConf.guiFont
|
||||
defaultSize = mainConf.guiFontSize
|
||||
defaultFont = CONFIG.guiFont
|
||||
defaultSize = CONFIG.guiFontSize
|
||||
|
||||
# CHange them to nonsense values
|
||||
mainConf.guiFont = "notafont"
|
||||
mainConf.guiFontSize = 99
|
||||
CONFIG.guiFont = "notafont"
|
||||
CONFIG.guiFontSize = 99
|
||||
|
||||
# Let the theme class set them back to default
|
||||
mainTheme._setGuiFont()
|
||||
assert mainConf.guiFont == defaultFont
|
||||
assert mainConf.guiFontSize == defaultSize
|
||||
assert CONFIG.guiFont == defaultFont
|
||||
assert CONFIG.guiFontSize == defaultSize
|
||||
|
||||
# A second call should just restore the defaults again
|
||||
mainTheme._setGuiFont()
|
||||
assert mainConf.guiFont == defaultFont
|
||||
assert mainConf.guiFontSize == defaultSize
|
||||
assert CONFIG.guiFont == defaultFont
|
||||
assert CONFIG.guiFontSize == defaultSize
|
||||
|
||||
# Scan for Themes
|
||||
# ===============
|
||||
|
||||
assert mainTheme._listConf({}, Path("not_a_path")) is False
|
||||
|
||||
themeOne = fncPath / "themes" / "themeone.conf"
|
||||
themeTwo = fncPath / "themes" / "themetwo.conf"
|
||||
themeOne = tstPaths.cnfDir / "themes" / "themeone.conf"
|
||||
themeTwo = tstPaths.cnfDir / "themes" / "themetwo.conf"
|
||||
writeFile(themeOne, "# Stuff")
|
||||
writeFile(themeTwo, "# Stuff")
|
||||
|
||||
result = {}
|
||||
assert mainTheme._listConf(result, fncPath / "themes") is True
|
||||
assert mainTheme._listConf(result, tstPaths.cnfDir / "themes") is True
|
||||
assert result["themeone"] == themeOne
|
||||
assert result["themetwo"] == themeTwo
|
||||
|
||||
@@ -123,18 +121,14 @@ def testGuiTheme_Main(qtbot, nwGUI, fncPath):
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
def testGuiTheme_Theme(qtbot, monkeypatch, nwGUI, fncPath):
|
||||
def testGuiTheme_Theme(qtbot, monkeypatch, nwGUI):
|
||||
"""Test the theme part of the class.
|
||||
"""
|
||||
mainTheme: GuiTheme = nwGUI.mainTheme
|
||||
mainConf: Config = nwGUI.mainConf
|
||||
|
||||
# List Themes
|
||||
# ===========
|
||||
|
||||
shutil.copy(mainConf.assetPath("themes") / "default_dark.conf", fncPath / "themes")
|
||||
shutil.copy(mainConf.assetPath("themes") / "default.conf", fncPath / "themes")
|
||||
|
||||
# Block the reading of the files
|
||||
with monkeypatch.context() as mp:
|
||||
mp.setattr("builtins.open", causeOSError)
|
||||
@@ -149,14 +143,14 @@ def testGuiTheme_Theme(qtbot, monkeypatch, nwGUI, fncPath):
|
||||
assert mainTheme.listThemes() == mainTheme._themeList
|
||||
|
||||
# Check handling of broken theme settings
|
||||
mainConf.guiTheme = "not_a_theme"
|
||||
CONFIG.guiTheme = "not_a_theme"
|
||||
availThemes = mainTheme._availThemes
|
||||
mainTheme._availThemes = {}
|
||||
assert mainTheme.loadTheme() is False
|
||||
mainTheme._availThemes = availThemes
|
||||
|
||||
# Check handling of unreadable file
|
||||
mainConf.guiTheme = "default"
|
||||
CONFIG.guiTheme = "default"
|
||||
with monkeypatch.context() as mp:
|
||||
mp.setattr("builtins.open", causeOSError)
|
||||
assert mainTheme.loadTheme() is False
|
||||
@@ -168,7 +162,7 @@ def testGuiTheme_Theme(qtbot, monkeypatch, nwGUI, fncPath):
|
||||
mainTheme._guiPalette.color(QPalette.Window).setRgb(0, 0, 0, 0)
|
||||
|
||||
# Load the default theme
|
||||
mainConf.guiTheme = "default"
|
||||
CONFIG.guiTheme = "default"
|
||||
assert mainTheme.loadTheme() is True
|
||||
|
||||
# This should load a standard palette
|
||||
@@ -178,7 +172,7 @@ def testGuiTheme_Theme(qtbot, monkeypatch, nwGUI, fncPath):
|
||||
# Load Default Dark Theme
|
||||
# =======================
|
||||
|
||||
mainConf.guiTheme = "default_dark"
|
||||
CONFIG.guiTheme = "default_dark"
|
||||
assert mainTheme.loadTheme() is True
|
||||
|
||||
# Check a few values
|
||||
@@ -193,18 +187,14 @@ def testGuiTheme_Theme(qtbot, monkeypatch, nwGUI, fncPath):
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
def testGuiTheme_Syntax(qtbot, monkeypatch, nwGUI, fncPath):
|
||||
def testGuiTheme_Syntax(qtbot, monkeypatch, nwGUI):
|
||||
"""Test the syntax part of the class.
|
||||
"""
|
||||
mainTheme: GuiTheme = nwGUI.mainTheme
|
||||
mainConf: Config = nwGUI.mainConf
|
||||
|
||||
# List Themes
|
||||
# ===========
|
||||
|
||||
shutil.copy(mainConf.assetPath("syntax") / "default_dark.conf", fncPath / "syntax")
|
||||
shutil.copy(mainConf.assetPath("syntax") / "default_light.conf", fncPath / "syntax")
|
||||
|
||||
# Block the reading of the files
|
||||
with monkeypatch.context() as mp:
|
||||
mp.setattr("builtins.open", causeOSError)
|
||||
@@ -221,12 +211,12 @@ def testGuiTheme_Syntax(qtbot, monkeypatch, nwGUI, fncPath):
|
||||
# Check handling of broken theme settings
|
||||
availSyntax = mainTheme._availSyntax
|
||||
mainTheme._availSyntax = {}
|
||||
mainConf.guiSyntax = "not_a_syntax"
|
||||
CONFIG.guiSyntax = "not_a_syntax"
|
||||
assert mainTheme.loadSyntax() is False
|
||||
mainTheme._availSyntax = availSyntax
|
||||
|
||||
# Check handling of unreadable file
|
||||
mainConf.guiSyntax = "default_light"
|
||||
CONFIG.guiSyntax = "default_light"
|
||||
with monkeypatch.context() as mp:
|
||||
mp.setattr("builtins.open", causeOSError)
|
||||
assert mainTheme.loadSyntax() is False
|
||||
@@ -235,7 +225,7 @@ def testGuiTheme_Syntax(qtbot, monkeypatch, nwGUI, fncPath):
|
||||
# =========================
|
||||
|
||||
# Load the default syntax
|
||||
mainConf.guiSyntax = "default_light"
|
||||
CONFIG.guiSyntax = "default_light"
|
||||
assert mainTheme.loadSyntax() is True
|
||||
|
||||
# Check some values
|
||||
@@ -248,7 +238,7 @@ def testGuiTheme_Syntax(qtbot, monkeypatch, nwGUI, fncPath):
|
||||
# =======================
|
||||
|
||||
# Load the default syntax
|
||||
mainConf.guiSyntax = "default_dark"
|
||||
CONFIG.guiSyntax = "default_dark"
|
||||
assert mainTheme.loadSyntax() is True
|
||||
|
||||
# Check some values
|
||||
@@ -263,7 +253,7 @@ def testGuiTheme_Syntax(qtbot, monkeypatch, nwGUI, fncPath):
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
def testGuiTheme_Icons(qtbot, caplog, monkeypatch, nwGUI, fncPath):
|
||||
def testGuiTheme_Icons(qtbot, caplog, monkeypatch, nwGUI, tstPaths):
|
||||
"""Test the icon cache class.
|
||||
"""
|
||||
iconCache: GuiIcons = nwGUI.mainTheme.iconCache
|
||||
@@ -280,7 +270,7 @@ def testGuiTheme_Icons(qtbot, caplog, monkeypatch, nwGUI, fncPath):
|
||||
assert iconCache.loadTheme("typicons_dark") is False
|
||||
|
||||
# Load a broken theme file
|
||||
iconsDir = fncPath / "icons"
|
||||
iconsDir = tstPaths.cnfDir / "icons"
|
||||
testIcons = iconsDir / "testicons"
|
||||
testIcons.mkdir()
|
||||
writeFile(testIcons / "icons.conf", (
|
||||
@@ -293,7 +283,7 @@ def testGuiTheme_Icons(qtbot, caplog, monkeypatch, nwGUI, fncPath):
|
||||
))
|
||||
|
||||
iconPath = iconCache._iconPath
|
||||
iconCache._iconPath = fncPath / "icons"
|
||||
iconCache._iconPath = tstPaths.cnfDir / "icons"
|
||||
|
||||
caplog.clear()
|
||||
assert iconCache.loadTheme("testicons") is True
|
||||
|
||||
@@ -28,6 +28,7 @@ from tools import ODT_IGNORE, cmpFiles, getGuiItem
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import QAction, QFileDialog
|
||||
|
||||
from novelwriter import CONFIG
|
||||
from novelwriter.tools.build import GuiBuildNovel
|
||||
|
||||
|
||||
@@ -67,7 +68,7 @@ def testToolBuild_Main(qtbot, monkeypatch, nwGUI, prjLipsum, tstPaths):
|
||||
assert not nwBuild._saveDocument(nwBuild.FMT_NWD)
|
||||
|
||||
# Default Settings
|
||||
nwGUI.mainConf._lastPath = prjLipsum
|
||||
CONFIG._lastPath = prjLipsum
|
||||
qtbot.mouseClick(nwBuild.buildNovel, Qt.LeftButton)
|
||||
|
||||
assert nwBuild._saveDocument(nwBuild.FMT_NWD)
|
||||
@@ -231,7 +232,7 @@ def testToolBuild_Main(qtbot, monkeypatch, nwGUI, prjLipsum, tstPaths):
|
||||
assert (prjLipsum / "Lorem Ipsum.odt").is_file()
|
||||
|
||||
# Print to PDF
|
||||
if not nwGUI.mainConf.osDarwin:
|
||||
if not CONFIG.osDarwin:
|
||||
assert nwBuild._saveDocument(nwBuild.FMT_PDF)
|
||||
assert (prjLipsum / "Lorem Ipsum.pdf").is_file()
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ from novelwriter.tools.writingstats import GuiWritingStats
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncPath, projPath):
|
||||
def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, projPath, tstPaths):
|
||||
"""Test the full writing stats tool.
|
||||
"""
|
||||
# Create a project to work on
|
||||
@@ -126,13 +126,10 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncPath, projPath):
|
||||
assert sessLog.listBox.topLevelItem(7).text(sessLog.C_COUNT) == "{:n}".format(200)
|
||||
|
||||
assert sessLog._saveData(sessLog.FMT_CSV)
|
||||
qtbot.wait(100)
|
||||
|
||||
assert sessLog._saveData(sessLog.FMT_JSON)
|
||||
qtbot.wait(100)
|
||||
|
||||
# Check the exported files
|
||||
jsonStats = fncPath / "sessionStats.json"
|
||||
jsonStats = tstPaths.tmpDir / "sessionStats.json"
|
||||
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
|
||||
jsonData = json.load(inFile)
|
||||
|
||||
@@ -171,7 +168,7 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncPath, projPath):
|
||||
qtbot.mouseClick(sessLog.incNovel, Qt.LeftButton)
|
||||
assert sessLog._saveData(sessLog.FMT_JSON)
|
||||
|
||||
jsonStats = fncPath / "sessionStats.json"
|
||||
jsonStats = tstPaths.tmpDir / "sessionStats.json"
|
||||
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
|
||||
jsonData = json.loads(inFile.read())
|
||||
|
||||
@@ -217,7 +214,7 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncPath, projPath):
|
||||
qtbot.mouseClick(sessLog.incNotes, Qt.LeftButton)
|
||||
assert sessLog._saveData(sessLog.FMT_JSON)
|
||||
|
||||
jsonStats = fncPath / "sessionStats.json"
|
||||
jsonStats = tstPaths.tmpDir / "sessionStats.json"
|
||||
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
|
||||
jsonData = json.load(inFile)
|
||||
|
||||
@@ -265,7 +262,7 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncPath, projPath):
|
||||
|
||||
# qtbot.stop()
|
||||
|
||||
jsonStats = fncPath / "sessionStats.json"
|
||||
jsonStats = tstPaths.tmpDir / "sessionStats.json"
|
||||
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
|
||||
jsonData = json.load(inFile)
|
||||
|
||||
@@ -295,7 +292,7 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncPath, projPath):
|
||||
qtbot.mouseClick(sessLog.hideZeros, Qt.LeftButton)
|
||||
assert sessLog._saveData(sessLog.FMT_JSON)
|
||||
|
||||
jsonStats = fncPath / "sessionStats.json"
|
||||
jsonStats = tstPaths.tmpDir / "sessionStats.json"
|
||||
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
|
||||
jsonData = json.load(inFile)
|
||||
|
||||
@@ -348,7 +345,7 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncPath, projPath):
|
||||
qtbot.mouseClick(sessLog.groupByDay, Qt.LeftButton)
|
||||
assert sessLog._saveData(sessLog.FMT_JSON)
|
||||
|
||||
jsonStats = fncPath / "sessionStats.json"
|
||||
jsonStats = tstPaths.tmpDir / "sessionStats.json"
|
||||
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
|
||||
jsonData = json.load(inFile)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user