Remove code for mocking CONFIG object and instead reset it for each test

This commit is contained in:
Veronica Berglyd Olsen
2023-05-16 00:34:11 +02:00
parent 76daa3f463
commit e8c6e50e92
12 changed files with 268 additions and 284 deletions
+69 -69
View File
@@ -28,19 +28,60 @@ from pathlib import Path
from mock import MockGuiMain from mock import MockGuiMain
from tools import cleanProject from tools import cleanProject
from PyQt5.QtWidgets import QMessageBox
sys.path.insert(1, str(Path(__file__).parent.parent.absolute())) 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 _TST_ROOT = Path(__file__).parent
_TMP_ROOT = _TST_ROOT / "temp"
from novelwriter.config import Config # noqa: E402 _TMP_CONF = _TMP_ROOT / "conf"
@pytest.fixture(autouse=True) ##
def initQt(qtbot): # Helper Functions
"""Ensures that the qt main thread is always available in all tests. ##
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 return
@@ -49,26 +90,17 @@ def initQt(qtbot):
## ##
@pytest.fixture(scope="session") @pytest.fixture(scope="session")
def tmpPath(): def tstPaths():
"""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):
"""Returns an object that can provide the various paths needed for """Returns an object that can provide the various paths needed for
running tests. running tests.
""" """
class _Store: class _Store:
testDir = Path(__file__).parent testDir = _TST_ROOT
filesDir = testDir / "files" filesDir = _TST_ROOT / "files"
refDir = testDir / "reference" refDir = _TST_ROOT / "reference"
outDir = tmpPath / "results" outDir = _TMP_ROOT / "results"
tmpDir = _TMP_ROOT
cnfDir = _TMP_CONF
store = _Store() store = _Store()
store.outDir.mkdir(exist_ok=True) store.outDir.mkdir(exist_ok=True)
@@ -77,10 +109,10 @@ def tstPaths(tmpPath):
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def fncPath(tmpPath): def fncPath():
"""A temporary folder for a single test function. Path version. """A temporary folder for a single test function.
""" """
fncPath = tmpPath / "function" fncPath = _TMP_ROOT / "function"
if fncPath.is_dir(): if fncPath.is_dir():
shutil.rmtree(fncPath) shutil.rmtree(fncPath)
fncPath.mkdir(exist_ok=True) fncPath.mkdir(exist_ok=True)
@@ -103,46 +135,17 @@ def projPath(fncPath):
# novelWriter Objects # 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") @pytest.fixture(scope="function")
def fncConf(fncPath): def mockGUI():
"""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):
"""Create a mock instance of novelWriter's main GUI class. """Create a mock instance of novelWriter's main GUI class.
""" """
monkeypatch.setattr("novelwriter.CONFIG", tmpConf)
theGui = MockGuiMain() theGui = MockGuiMain()
theGui.mainConf = tmpConf
return theGui return theGui
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def nwGUI(qtbot, monkeypatch, fncPath, fncConf): def nwGUI(qtbot, monkeypatch, functionFixture):
"""Create an instance of the novelWriter GUI. """Create an instance of the novelWriter GUI.
""" """
monkeypatch.setattr(QMessageBox, "warning", lambda *a: QMessageBox.Ok) 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, "information", lambda *a: QMessageBox.Ok)
monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
monkeypatch.setattr("novelwriter.CONFIG", fncConf) nwGUI = main(["--testmode", f"--config={_TMP_CONF}", f"--data={_TMP_CONF}"])
nwGUI = novelwriter.main(["--testmode", f"--config={fncPath}", f"--data={fncPath}"])
qtbot.addWidget(nwGUI) qtbot.addWidget(nwGUI)
resetConfigVars()
nwGUI.show() nwGUI.show()
qtbot.wait(20) qtbot.wait(20)
nwGUI.mainConf.setLastPath(fncPath)
yield nwGUI yield nwGUI
qtbot.wait(20) qtbot.wait(20)
@@ -198,13 +200,12 @@ def mockRnd(monkeypatch):
## ##
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def nwLipsum(tmpPath): def nwLipsum():
"""A medium sized novelWriter example project with a lot of Lorem """A medium sized novelWriter example project with a lot of Lorem
Ipsum text. Ipsum text.
""" """
tstDir = Path(__file__).parent srcDir = _TST_ROOT / "lipsum"
srcDir = tstDir / "lipsum" dstDir = _TMP_ROOT / "lipsum"
dstDir = tmpPath / "lipsum"
if dstDir.exists(): if dstDir.exists():
shutil.rmtree(dstDir) shutil.rmtree(dstDir)
@@ -220,13 +221,12 @@ def nwLipsum(tmpPath):
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def prjLipsum(tmpPath): def prjLipsum():
"""A medium sized novelWriter example project with a lot of Lorem """A medium sized novelWriter example project with a lot of Lorem
Ipsum text. Ipsum text.
""" """
tstDir = Path(__file__).parent srcDir = _TST_ROOT / "lipsum"
srcDir = tstDir / "lipsum" dstDir = _TMP_ROOT / "lipsum"
dstDir = tmpPath / "lipsum"
if dstDir.exists(): if dstDir.exists():
shutil.rmtree(dstDir) shutil.rmtree(dstDir)
+119 -109
View File
@@ -28,6 +28,7 @@ from pathlib import Path
from mock import causeOSError, MockApp from mock import causeOSError, MockApp
from tools import cmpFiles, writeFile from tools import cmpFiles, writeFile
from novelwriter import CONFIG
from novelwriter.config import Config, RecentProjects from novelwriter.config import Config, RecentProjects
from novelwriter.constants import nwFiles from novelwriter.constants import nwFiles
@@ -196,197 +197,206 @@ def testBaseConfig_Localisation(fncPath, tstPaths):
@pytest.mark.base @pytest.mark.base
def testBaseConfig_Methods(tmpConf, tmpPath): def testBaseConfig_Methods(fncPath):
"""Check class methods. """Check class methods.
""" """
tstConf = Config()
tstConf.initConfig(confPath=fncPath, dataPath=fncPath)
# Data Path # Data Path
assert tmpConf.dataPath() == tmpPath assert tstConf.dataPath() == fncPath
assert tmpConf.dataPath("stuff") == tmpPath / "stuff" assert tstConf.dataPath("stuff") == fncPath / "stuff"
# Assets Path # Assets Path
appPath = tmpConf._appPath appPath = tstConf._appPath
assert tmpConf.assetPath() == appPath / "assets" assert tstConf.assetPath() == appPath / "assets"
assert tmpConf.assetPath("stuff") == appPath / "assets" / "stuff" assert tstConf.assetPath("stuff") == appPath / "assets" / "stuff"
# Last Path # Last Path
assert tmpConf.lastPath() == tmpPath assert tstConf.lastPath() == Path.home().absolute()
tmpStuff = tmpPath / "stuff" tmpStuff = fncPath / "stuff"
tmpStuff.mkdir() tmpStuff.mkdir()
tmpConf.setLastPath(tmpStuff) tstConf.setLastPath(tmpStuff)
assert tmpConf.lastPath() == tmpStuff assert tstConf.lastPath() == tmpStuff
fileStuff = tmpStuff / "more_stuff.txt" fileStuff = tmpStuff / "more_stuff.txt"
fileStuff.write_text("Stuff") fileStuff.write_text("Stuff")
tmpConf.setLastPath(fileStuff) tstConf.setLastPath(fileStuff)
assert tmpConf.lastPath() == tmpStuff assert tstConf.lastPath() == tmpStuff
fileStuff.unlink() fileStuff.unlink()
tmpStuff.rmdir() tmpStuff.rmdir()
assert tmpConf.lastPath() == Path.home().absolute() assert tstConf.lastPath() == Path.home().absolute()
# Recent Projects # Recent Projects
assert isinstance(tmpConf.recentProjects, RecentProjects) assert isinstance(tstConf.recentProjects, RecentProjects)
# END Test testBaseConfig_Methods # END Test testBaseConfig_Methods
@pytest.mark.base @pytest.mark.base
def testBaseConfig_SettersGetters(tmpConf): def testBaseConfig_SettersGetters(fncPath):
"""Set various sizes and positions """Set various sizes and positions
""" """
tstConf = Config()
tstConf.initConfig(confPath=fncPath, dataPath=fncPath)
# GUI Scaling # GUI Scaling
# =========== # ===========
tmpConf.guiScale = 1.0 tstConf.guiScale = 1.0
assert tmpConf.pxInt(10) == 10 assert tstConf.pxInt(10) == 10
assert tmpConf.pxInt(13) == 13 assert tstConf.pxInt(13) == 13
assert tmpConf.rpxInt(10) == 10 assert tstConf.rpxInt(10) == 10
assert tmpConf.rpxInt(13) == 13 assert tstConf.rpxInt(13) == 13
tmpConf.guiScale = 2.0 tstConf.guiScale = 2.0
assert tmpConf.pxInt(10) == 20 assert tstConf.pxInt(10) == 20
assert tmpConf.pxInt(13) == 26 assert tstConf.pxInt(13) == 26
assert tmpConf.rpxInt(10) == 5 assert tstConf.rpxInt(10) == 5
assert tmpConf.rpxInt(13) == 6 assert tstConf.rpxInt(13) == 6
# Setter + Getter Combos # Setter + Getter Combos
# ====================== # ======================
# Window Size # Window Size
tmpConf.guiScale = 1.0 tstConf.guiScale = 1.0
tmpConf.setMainWinSize(1205, 655) tstConf.setMainWinSize(1205, 655)
assert tmpConf.mainWinSize == [1200, 650] assert tstConf.mainWinSize == [1200, 650]
tmpConf.guiScale = 2.0 tstConf.guiScale = 2.0
tmpConf.setMainWinSize(70, 70) tstConf.setMainWinSize(70, 70)
assert tmpConf.mainWinSize == [70, 70] assert tstConf.mainWinSize == [70, 70]
assert tmpConf._mainWinSize == [35, 35] assert tstConf._mainWinSize == [35, 35]
tmpConf.guiScale = 1.0 tstConf.guiScale = 1.0
tmpConf.setMainWinSize(70, 70) tstConf.setMainWinSize(70, 70)
assert tmpConf.mainWinSize == [70, 70] assert tstConf.mainWinSize == [70, 70]
assert tmpConf._mainWinSize == [70, 70] assert tstConf._mainWinSize == [70, 70]
tmpConf.setMainWinSize(1200, 650) tstConf.setMainWinSize(1200, 650)
# Preferences Size # Preferences Size
tmpConf.guiScale = 2.0 tstConf.guiScale = 2.0
tmpConf.setPreferencesWinSize(70, 70) tstConf.setPreferencesWinSize(70, 70)
assert tmpConf.preferencesWinSize == [70, 70] assert tstConf.preferencesWinSize == [70, 70]
assert tmpConf._prefsWinSize == [35, 35] assert tstConf._prefsWinSize == [35, 35]
tmpConf.guiScale = 1.0 tstConf.guiScale = 1.0
tmpConf.setPreferencesWinSize(70, 70) tstConf.setPreferencesWinSize(70, 70)
assert tmpConf.preferencesWinSize == [70, 70] assert tstConf.preferencesWinSize == [70, 70]
assert tmpConf._prefsWinSize == [70, 70] assert tstConf._prefsWinSize == [70, 70]
tmpConf.setPreferencesWinSize(700, 615) tstConf.setPreferencesWinSize(700, 615)
# Project Settings Tree Columns # Project Settings Tree Columns
tmpConf.guiScale = 2.0 tstConf.guiScale = 2.0
tmpConf.setProjLoadColWidths([10, 20, 30]) tstConf.setProjLoadColWidths([10, 20, 30])
assert tmpConf.projLoadColWidths == [10, 20, 30] assert tstConf.projLoadColWidths == [10, 20, 30]
assert tmpConf._projLoadCols == [5, 10, 15] assert tstConf._projLoadCols == [5, 10, 15]
tmpConf.guiScale = 1.0 tstConf.guiScale = 1.0
tmpConf.setProjLoadColWidths([10, 20, 30]) tstConf.setProjLoadColWidths([10, 20, 30])
assert tmpConf.projLoadColWidths == [10, 20, 30] assert tstConf.projLoadColWidths == [10, 20, 30]
assert tmpConf._projLoadCols == [10, 20, 30] assert tstConf._projLoadCols == [10, 20, 30]
tmpConf.setProjLoadColWidths([200, 60, 140]) tstConf.setProjLoadColWidths([200, 60, 140])
# Main Pane Splitter # Main Pane Splitter
tmpConf.guiScale = 2.0 tstConf.guiScale = 2.0
tmpConf.setMainPanePos([200, 700]) tstConf.setMainPanePos([200, 700])
assert tmpConf.mainPanePos == [200, 700] assert tstConf.mainPanePos == [200, 700]
assert tmpConf._mainPanePos == [100, 350] assert tstConf._mainPanePos == [100, 350]
tmpConf.guiScale = 1.0 tstConf.guiScale = 1.0
tmpConf.setMainPanePos([200, 700]) tstConf.setMainPanePos([200, 700])
assert tmpConf.mainPanePos == [200, 700] assert tstConf.mainPanePos == [200, 700]
assert tmpConf._mainPanePos == [200, 700] assert tstConf._mainPanePos == [200, 700]
tmpConf.setMainPanePos([300, 800]) tstConf.setMainPanePos([300, 800])
# View Pane Splitter # View Pane Splitter
tmpConf.guiScale = 2.0 tstConf.guiScale = 2.0
tmpConf.setViewPanePos([400, 250]) tstConf.setViewPanePos([400, 250])
assert tmpConf.viewPanePos == [400, 250] assert tstConf.viewPanePos == [400, 250]
assert tmpConf._viewPanePos == [200, 125] assert tstConf._viewPanePos == [200, 125]
tmpConf.guiScale = 1.0 tstConf.guiScale = 1.0
tmpConf.setViewPanePos([400, 250]) tstConf.setViewPanePos([400, 250])
assert tmpConf.viewPanePos == [400, 250] assert tstConf.viewPanePos == [400, 250]
assert tmpConf._viewPanePos == [400, 250] assert tstConf._viewPanePos == [400, 250]
tmpConf.setViewPanePos([500, 150]) tstConf.setViewPanePos([500, 150])
# Outline Pane Splitter # Outline Pane Splitter
tmpConf.guiScale = 2.0 tstConf.guiScale = 2.0
tmpConf.setOutlinePanePos([400, 250]) tstConf.setOutlinePanePos([400, 250])
assert tmpConf.outlinePanePos == [400, 250] assert tstConf.outlinePanePos == [400, 250]
assert tmpConf._outlnPanePos == [200, 125] assert tstConf._outlnPanePos == [200, 125]
tmpConf.guiScale = 1.0 tstConf.guiScale = 1.0
tmpConf.setOutlinePanePos([400, 250]) tstConf.setOutlinePanePos([400, 250])
assert tmpConf.outlinePanePos == [400, 250] assert tstConf.outlinePanePos == [400, 250]
assert tmpConf._outlnPanePos == [400, 250] assert tstConf._outlnPanePos == [400, 250]
tmpConf.setOutlinePanePos([500, 150]) tstConf.setOutlinePanePos([500, 150])
# Getters Only # Getters Only
# ============ # ============
tmpConf.guiScale = 1.0 tstConf.guiScale = 1.0
assert tmpConf.getTextWidth(False) == 700 assert tstConf.getTextWidth(False) == 700
assert tmpConf.getTextWidth(True) == 800 assert tstConf.getTextWidth(True) == 800
assert tmpConf.getTextMargin() == 40 assert tstConf.getTextMargin() == 40
assert tmpConf.getTabWidth() == 40 assert tstConf.getTabWidth() == 40
tmpConf.guiScale = 2.0 tstConf.guiScale = 2.0
assert tmpConf.getTextWidth(False) == 1400 assert tstConf.getTextWidth(False) == 1400
assert tmpConf.getTextWidth(True) == 1600 assert tstConf.getTextWidth(True) == 1600
assert tmpConf.getTextMargin() == 80 assert tstConf.getTextMargin() == 80
assert tmpConf.getTabWidth() == 80 assert tstConf.getTabWidth() == 80
# END Test testBaseConfig_SettersGetters # END Test testBaseConfig_SettersGetters
@pytest.mark.base @pytest.mark.base
def testBaseConfig_Internal(monkeypatch, tmpConf): def testBaseConfig_Internal(monkeypatch, fncPath):
"""Check internal functions. """Check internal functions.
""" """
tstConf = Config()
tstConf.initConfig(confPath=fncPath, dataPath=fncPath)
# Function _packList # 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 # Function _checkNone
assert tmpConf._checkNone(None) is None assert tstConf._checkNone(None) is None
assert tmpConf._checkNone("None") is None assert tstConf._checkNone("None") is None
assert tmpConf._checkNone("none") is None assert tstConf._checkNone("none") is None
assert tmpConf._checkNone("NONE") is None assert tstConf._checkNone("NONE") is None
assert tmpConf._checkNone("NoNe") is None assert tstConf._checkNone("NoNe") is None
assert tmpConf._checkNone(123456) == 123456 assert tstConf._checkNone(123456) == 123456
# Function _checkOptionalPackages # Function _checkOptionalPackages
# (Assumes enchant package exists and is importable) # (Assumes enchant package exists and is importable)
tmpConf._checkOptionalPackages() tstConf._checkOptionalPackages()
assert tmpConf.hasEnchant is True assert tstConf.hasEnchant is True
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setitem(sys.modules, "enchant", None) mp.setitem(sys.modules, "enchant", None)
tmpConf._checkOptionalPackages() tstConf._checkOptionalPackages()
assert tmpConf.hasEnchant is False assert tstConf.hasEnchant is False
# END Test testBaseConfig_Internal # END Test testBaseConfig_Internal
@pytest.mark.base @pytest.mark.base
def testBaseConfig_RecentCache(monkeypatch, fncConf, fncPath): def testBaseConfig_RecentCache(monkeypatch, tstPaths):
"""Test recent cache file. """Test recent cache file.
""" """
cacheFile = fncPath / nwFiles.RECENT_FILE cacheFile = tstPaths.cnfDir / nwFiles.RECENT_FILE
recent = RecentProjects(fncConf) recent = RecentProjects(CONFIG)
# Load when there is no file should pass, but load nothing # Load when there is no file should pass, but load nothing
assert not cacheFile.exists() assert not cacheFile.exists()
@@ -394,8 +404,8 @@ def testBaseConfig_RecentCache(monkeypatch, fncConf, fncPath):
assert recent.listEntries() == [] assert recent.listEntries() == []
# Add a couple of values # Add a couple of values
pathOne = fncPath / "projPathOne" / nwFiles.PROJ_FILE pathOne = tstPaths.cnfDir / "projPathOne" / nwFiles.PROJ_FILE
pathTwo = fncPath / "projPathTwo" / nwFiles.PROJ_FILE pathTwo = tstPaths.cnfDir / "projPathTwo" / nwFiles.PROJ_FILE
recent.update(pathOne, "Proj One", 100, 1600002000) recent.update(pathOne, "Proj One", 100, 1600002000)
recent.update(pathTwo, "Proj Two", 200, 1600005600) recent.update(pathTwo, "Proj Two", 200, 1600005600)
+16 -16
View File
@@ -28,13 +28,13 @@ from mock import MockGuiMain
@pytest.mark.base @pytest.mark.base
def testBaseInit_Launch(caplog, monkeypatch, tmpPath): def testBaseInit_Launch(caplog, monkeypatch, fncPath):
"""Check launching the main GUI. """Check launching the main GUI.
""" """
monkeypatch.setattr("novelwriter.guimain.GuiMain", MockGuiMain) monkeypatch.setattr("novelwriter.guimain.GuiMain", MockGuiMain)
# TestMode Launch # TestMode Launch
nwGUI = novelwriter.main(["--testmode", f"--config={tmpPath}", f"--data={tmpPath}"]) nwGUI = novelwriter.main(["--testmode", f"--config={fncPath}", f"--data={fncPath}"])
assert isinstance(nwGUI, MockGuiMain) assert isinstance(nwGUI, MockGuiMain)
# Darwin Launch # Darwin Launch
@@ -43,7 +43,7 @@ def testBaseInit_Launch(caplog, monkeypatch, tmpPath):
novelwriter.CONFIG.osDarwin = True novelwriter.CONFIG.osDarwin = True
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setitem(sys.modules, "Foundation", None) mp.setitem(sys.modules, "Foundation", None)
nwGUI = novelwriter.main(["--testmode", f"--config={tmpPath}", f"--data={tmpPath}"]) nwGUI = novelwriter.main(["--testmode", f"--config={fncPath}", f"--data={fncPath}"])
assert isinstance(nwGUI, MockGuiMain) assert isinstance(nwGUI, MockGuiMain)
assert "Failed" in caplog.text assert "Failed" in caplog.text
@@ -55,7 +55,7 @@ def testBaseInit_Launch(caplog, monkeypatch, tmpPath):
novelwriter.CONFIG.osWindows = True novelwriter.CONFIG.osWindows = True
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setitem(sys.modules, "ctypes", None) mp.setitem(sys.modules, "ctypes", None)
nwGUI = novelwriter.main(["--testmode", f"--config={tmpPath}", f"--data={tmpPath}"]) nwGUI = novelwriter.main(["--testmode", f"--config={fncPath}", f"--data={fncPath}"])
assert isinstance(nwGUI, MockGuiMain) assert isinstance(nwGUI, MockGuiMain)
if not sys.platform.startswith("darwin"): if not sys.platform.startswith("darwin"):
# For some reason, the test doesn't work on macOS # For some reason, the test doesn't work on macOS
@@ -71,19 +71,19 @@ def testBaseInit_Launch(caplog, monkeypatch, tmpPath):
monkeypatch.setattr("PyQt5.QtWidgets.QApplication.setOrganizationDomain", lambda *a: None) monkeypatch.setattr("PyQt5.QtWidgets.QApplication.setOrganizationDomain", lambda *a: None)
monkeypatch.setattr("PyQt5.QtWidgets.QApplication.exec_", lambda *a: 0) monkeypatch.setattr("PyQt5.QtWidgets.QApplication.exec_", lambda *a: 0)
with pytest.raises(SystemExit) as ex: with pytest.raises(SystemExit) as ex:
novelwriter.main([f"--config={tmpPath}", f"--data={tmpPath}"]) novelwriter.main([f"--config={fncPath}", f"--data={fncPath}"])
assert ex.value.code == 0 assert ex.value.code == 0
# END Test testBaseInit_Launch # END Test testBaseInit_Launch
@pytest.mark.base @pytest.mark.base
def testBaseInit_Options(monkeypatch, tmpPath): def testBaseInit_Options(monkeypatch, fncPath):
"""Test command line options for logging level. """Test command line options for logging level.
""" """
monkeypatch.setattr("novelwriter.guimain.GuiMain", MockGuiMain) monkeypatch.setattr("novelwriter.guimain.GuiMain", MockGuiMain)
monkeypatch.setattr(sys, "argv", [ monkeypatch.setattr(sys, "argv", [
"novelWriter.py", "--testmode", f"--config={tmpPath}", f"--data={tmpPath}" "novelWriter.py", "--testmode", f"--config={fncPath}", f"--data={fncPath}"
]) ])
# Defaults w/None Args # Defaults w/None Args
@@ -93,20 +93,20 @@ def testBaseInit_Options(monkeypatch, tmpPath):
# Defaults # Defaults
nwGUI = novelwriter.main( nwGUI = novelwriter.main(
["--testmode", f"--config={tmpPath}", f"--data={tmpPath}", "--style=Fusion"] ["--testmode", f"--config={fncPath}", f"--data={fncPath}", "--style=Fusion"]
) )
assert novelwriter.logger.getEffectiveLevel() == logging.WARNING assert novelwriter.logger.getEffectiveLevel() == logging.WARNING
assert nwGUI.closeMain() == "closeMain" assert nwGUI.closeMain() == "closeMain"
# Log Levels # Log Levels
nwGUI = novelwriter.main( nwGUI = novelwriter.main(
["--testmode", "--info", f"--config={tmpPath}", f"--data={tmpPath}"] ["--testmode", "--info", f"--config={fncPath}", f"--data={fncPath}"]
) )
assert novelwriter.logger.getEffectiveLevel() == logging.INFO assert novelwriter.logger.getEffectiveLevel() == logging.INFO
assert nwGUI.closeMain() == "closeMain" assert nwGUI.closeMain() == "closeMain"
nwGUI = novelwriter.main( nwGUI = novelwriter.main(
["--testmode", "--debug", f"--config={tmpPath}", f"--data={tmpPath}"] ["--testmode", "--debug", f"--config={fncPath}", f"--data={fncPath}"]
) )
assert novelwriter.logger.getEffectiveLevel() == logging.DEBUG assert novelwriter.logger.getEffectiveLevel() == logging.DEBUG
assert nwGUI.closeMain() == "closeMain" assert nwGUI.closeMain() == "closeMain"
@@ -114,14 +114,14 @@ def testBaseInit_Options(monkeypatch, tmpPath):
# Help and Version # Help and Version
with pytest.raises(SystemExit) as ex: with pytest.raises(SystemExit) as ex:
nwGUI = novelwriter.main( nwGUI = novelwriter.main(
["--testmode", "--help", f"--config={tmpPath}", f"--data={tmpPath}"] ["--testmode", "--help", f"--config={fncPath}", f"--data={fncPath}"]
) )
assert nwGUI.closeMain() == "closeMain" assert nwGUI.closeMain() == "closeMain"
assert ex.value.code == 0 assert ex.value.code == 0
with pytest.raises(SystemExit) as ex: with pytest.raises(SystemExit) as ex:
nwGUI = novelwriter.main( nwGUI = novelwriter.main(
["--testmode", "--version", f"--config={tmpPath}", f"--data={tmpPath}"] ["--testmode", "--version", f"--config={fncPath}", f"--data={fncPath}"]
) )
assert nwGUI.closeMain() == "closeMain" assert nwGUI.closeMain() == "closeMain"
assert ex.value.code == 0 assert ex.value.code == 0
@@ -129,14 +129,14 @@ def testBaseInit_Options(monkeypatch, tmpPath):
# Invalid options # Invalid options
with pytest.raises(SystemExit) as ex: with pytest.raises(SystemExit) as ex:
nwGUI = novelwriter.main( nwGUI = novelwriter.main(
["--testmode", "--invalid", f"--config={tmpPath}", f"--data={tmpPath}"] ["--testmode", "--invalid", f"--config={fncPath}", f"--data={fncPath}"]
) )
assert nwGUI.closeMain() == "closeMain" assert nwGUI.closeMain() == "closeMain"
assert ex.value.code == 2 assert ex.value.code == 2
# Project Path # Project Path
nwGUI = novelwriter.main( nwGUI = novelwriter.main(
["--testmode", f"--config={tmpPath}", f"--data={tmpPath}", "sample/"] ["--testmode", f"--config={fncPath}", f"--data={fncPath}", "sample/"]
) )
assert nwGUI.closeMain() == "closeMain" assert nwGUI.closeMain() == "closeMain"
@@ -144,7 +144,7 @@ def testBaseInit_Options(monkeypatch, tmpPath):
@pytest.mark.base @pytest.mark.base
def testBaseInit_Imports(caplog, monkeypatch, tmpPath): def testBaseInit_Imports(caplog, monkeypatch, fncPath):
"""Check import error handling. """Check import error handling.
""" """
monkeypatch.setattr("novelwriter.guimain.GuiMain", MockGuiMain) monkeypatch.setattr("novelwriter.guimain.GuiMain", MockGuiMain)
@@ -160,7 +160,7 @@ def testBaseInit_Imports(caplog, monkeypatch, tmpPath):
with pytest.raises(SystemExit) as ex: with pytest.raises(SystemExit) as ex:
_ = novelwriter.main( _ = novelwriter.main(
["--testmode", f"--config={tmpPath}", f"--data={tmpPath}"] ["--testmode", f"--config={fncPath}", f"--data={fncPath}"]
) )
assert ex.value.code & 4 == 4 # Python version not satisfied assert ex.value.code & 4 == 4 # Python version not satisfied
+5 -4
View File
@@ -28,6 +28,7 @@ from zipfile import ZipFile
from mock import causeOSError from mock import causeOSError
from tools import C, buildTestProject, cmpFiles, XML_IGNORE from tools import C, buildTestProject, cmpFiles, XML_IGNORE
from novelwriter import CONFIG
from novelwriter.constants import nwItemClass from novelwriter.constants import nwItemClass
from novelwriter.core.project import NWProject from novelwriter.core.project import NWProject
from novelwriter.core.coretools import DocMerger, DocSplitter, ProjectBuilder from novelwriter.core.coretools import DocMerger, DocSplitter, ProjectBuilder
@@ -371,7 +372,7 @@ def testCoreTools_NewCustomB(monkeypatch, fncPath, tstPaths, mockGUI, mockRnd):
@pytest.mark.core @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 """Check that we can create a new project can be created from the
provided sample project via a zip file. 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 assert projBuild.buildProject({"popSample": True}) is False
# Force the lookup path for assets to our temp folder # Force the lookup path for assets to our temp folder
srcSample = tmpConf._appRoot / "sample" srcSample = CONFIG._appRoot / "sample"
dstSample = tmpPath / "sample.zip" dstSample = tstPaths.tmpDir / "sample.zip"
monkeypatch.setattr( 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 # Cannot extract when the zip does not exist
+7 -12
View File
@@ -704,7 +704,7 @@ def testCoreProject_OrphanedFiles(mockGUI, prjLipsum):
@pytest.mark.core @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 """Test the automated backup feature of the project class. The test
creates a backup of the Minimal test project, and then unzips the creates a backup of the Minimal test project, and then unzips the
backupd file and checks that the project XML file is identical to backupd file and checks that the project XML file is identical to
@@ -720,23 +720,18 @@ def testCoreProject_Backup(monkeypatch, mockGUI, fncPath, tmpPath):
# Invalid Settings # Invalid Settings
# ================ # ================
# No project
mockGUI.hasProject = False
assert theProject.backupProject(doNotify=False) is False
mockGUI.hasProject = True
# Invalid path # Invalid path
theProject.mainConf._backupPath = None theProject.mainConf._backupPath = None
assert theProject.backupProject(doNotify=False) is False assert theProject.backupProject(doNotify=False) is False
# Missing project name # Missing project name
theProject.mainConf._backupPath = tmpPath theProject.mainConf._backupPath = tstPaths.tmpDir
theProject.data.setName("") theProject.data.setName("")
assert theProject.backupProject(doNotify=False) is False assert theProject.backupProject(doNotify=False) is False
# Valid Settings # Valid Settings
# ============== # ==============
theProject.mainConf._backupPath = tmpPath theProject.mainConf._backupPath = tstPaths.tmpDir
theProject.data.setName("Test Minimal") theProject.data.setName("Test Minimal")
# Can't make folder # Can't make folder
@@ -752,7 +747,7 @@ def testCoreProject_Backup(monkeypatch, mockGUI, fncPath, tmpPath):
# Test correct settings # Test correct settings
assert theProject.backupProject(doNotify=True) is True assert theProject.backupProject(doNotify=True) is True
theFiles = list((tmpPath / "Test Minimal").iterdir()) theFiles = list((tstPaths.tmpDir / "Test Minimal").iterdir())
assert len(theFiles) == 1 assert len(theFiles) == 1
theZip = theFiles[0].name theZip = theFiles[0].name
@@ -760,13 +755,13 @@ def testCoreProject_Backup(monkeypatch, mockGUI, fncPath, tmpPath):
assert theZip[-4:] == ".zip" assert theZip[-4:] == ".zip"
# Extract the archive # Extract the archive
with ZipFile(tmpPath / "Test Minimal" / theZip, mode="r") as inZip: with ZipFile(tstPaths.tmpDir / "Test Minimal" / theZip, mode="r") as inZip:
inZip.extractall(tmpPath / "extract") inZip.extractall(tstPaths.tmpDir / "extract")
# Check that the main project file was restored # Check that the main project file was restored
assert cmpFiles( assert cmpFiles(
fncPath / "nwProject.nwx", fncPath / "nwProject.nwx",
tmpPath / "extract" / "nwProject.nwx" tstPaths.tmpDir / "extract" / "nwProject.nwx"
) )
# END Test testCoreProject_Backup # END Test testCoreProject_Backup
+2 -2
View File
@@ -299,10 +299,10 @@ def testCoreStorage_PrepareStorage(monkeypatch, fncPath):
@pytest.mark.core @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. """Test making a zip archive of a project.
""" """
zipFile = tmpPath / "project.zip" zipFile = tstPaths.tmpDir / "project.zip"
theProject = NWProject(mockGUI) theProject = NWProject(mockGUI)
storage = theProject.storage storage = theProject.storage
+5 -5
View File
@@ -437,7 +437,7 @@ def testCoreTree_Reorder(caplog, mockGUI, mockItems):
@pytest.mark.core @pytest.mark.core
def testCoreTree_ToCFile(monkeypatch, mockGUI, mockItems, tmpPath): def testCoreTree_ToCFile(monkeypatch, tstPaths, mockGUI, mockItems):
"""Test writing the ToC.txt file. """Test writing the ToC.txt file.
""" """
theProject = NWProject(mockGUI) theProject = NWProject(mockGUI)
@@ -463,20 +463,20 @@ def testCoreTree_ToCFile(monkeypatch, mockGUI, mockItems, tmpPath):
theProject._storage._runtimePath = None theProject._storage._runtimePath = None
assert theTree.writeToCFile() is False assert theTree.writeToCFile() is False
theProject._storage._runtimePath = tmpPath theProject._storage._runtimePath = tstPaths.tmpDir
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError) mp.setattr("builtins.open", causeOSError)
assert theTree.writeToCFile() is False assert theTree.writeToCFile() is False
theProject._storage._runtimePath = tmpPath theProject._storage._runtimePath = tstPaths.tmpDir
(tmpPath / "content").mkdir() (tstPaths.tmpDir / "content").mkdir()
assert theTree.writeToCFile() is True assert theTree.writeToCFile() is True
pathA = str(Path("content") / "c000000000001.nwd") pathA = str(Path("content") / "c000000000001.nwd")
pathB = str(Path("content") / "c000000000002.nwd") pathB = str(Path("content") / "c000000000002.nwd")
pathC = str(Path("content") / "b000000000002.nwd") pathC = str(Path("content") / "b000000000002.nwd")
assert readFile(tmpPath / nwFiles.TOC_TXT) == ( assert readFile(tstPaths.tmpDir / nwFiles.TOC_TXT) == (
"\n" "\n"
"Table of Contents\n" "Table of Contents\n"
"=================\n" "=================\n"
+2 -6
View File
@@ -37,12 +37,9 @@ KEY_DELAY = 1
@pytest.mark.gui @pytest.mark.gui
def testDlgPreferences_Main(qtbot, monkeypatch, nwGUI, fncPath, tstPaths): def testDlgPreferences_Main(qtbot, monkeypatch, nwGUI, tstPaths):
"""Test the load project wizard. """Test the load project wizard.
""" """
theConf = nwGUI.mainConf
assert theConf._confPath == fncPath
monkeypatch.setattr(GuiPreferences, "exec_", lambda *a: None) monkeypatch.setattr(GuiPreferences, "exec_", lambda *a: None)
monkeypatch.setattr(GuiPreferences, "result", lambda *a: QDialog.Accepted) monkeypatch.setattr(GuiPreferences, "result", lambda *a: QDialog.Accepted)
monkeypatch.setattr(nwGUI.docEditor.spEnchant, "listDictionaries", lambda: [("en", "none")]) monkeypatch.setattr(nwGUI.docEditor.spEnchant, "listDictionaries", lambda: [("en", "none")])
@@ -58,7 +55,6 @@ def testDlgPreferences_Main(qtbot, monkeypatch, nwGUI, fncPath, tstPaths):
nwPrefs = getGuiItem("GuiPreferences") nwPrefs = getGuiItem("GuiPreferences")
assert isinstance(nwPrefs, GuiPreferences) assert isinstance(nwPrefs, GuiPreferences)
nwPrefs.show() nwPrefs.show()
assert nwPrefs.mainConf._confPath == fncPath
assert nwPrefs.updateTheme is False assert nwPrefs.updateTheme is False
assert nwPrefs.updateSyntax is False assert nwPrefs.updateSyntax is False
@@ -216,7 +212,7 @@ def testDlgPreferences_Main(qtbot, monkeypatch, nwGUI, fncPath, tstPaths):
nwPrefs._doClose() nwPrefs._doClose()
assert nwGUI.mainConf.saveConfig() assert nwGUI.mainConf.saveConfig()
projFile = fncPath / "novelwriter.conf" projFile = tstPaths.cnfDir / "novelwriter.conf"
testFile = tstPaths.outDir / "guiPreferences_novelwriter.conf" testFile = tstPaths.outDir / "guiPreferences_novelwriter.conf"
compFile = tstPaths.refDir / "guiPreferences_novelwriter.conf" compFile = tstPaths.refDir / "guiPreferences_novelwriter.conf"
copyfile(projFile, testFile) copyfile(projFile, testFile)
+3 -3
View File
@@ -91,7 +91,7 @@ def testDlgProjSettings_Main(qtbot, monkeypatch, nwGUI, fncPath, projPath, mockR
# Create new project # Create new project
buildTestProject(nwGUI, projPath) buildTestProject(nwGUI, projPath)
mockRnd.reset() mockRnd.reset()
nwGUI.mainConf.backupPath = fncPath nwGUI.mainConf.setBackupPath(fncPath)
# Set some values # Set some values
theProject = nwGUI.theProject theProject = nwGUI.theProject
@@ -156,7 +156,7 @@ def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, fncPath, projPat
# Create new project # Create new project
mockRnd.reset() mockRnd.reset()
buildTestProject(nwGUI, projPath) buildTestProject(nwGUI, projPath)
nwGUI.mainConf.backupPath = fncPath nwGUI.mainConf.setBackupPath(fncPath)
# Set some values # Set some values
theProject = nwGUI.theProject theProject = nwGUI.theProject
@@ -357,7 +357,7 @@ def testDlgProjSettings_Replace(qtbot, monkeypatch, nwGUI, fncPath, projPath, mo
# Create new project # Create new project
mockRnd.reset() mockRnd.reset()
buildTestProject(nwGUI, projPath) buildTestProject(nwGUI, projPath)
nwGUI.mainConf.backupPath = fncPath nwGUI.mainConf.setBackupPath(fncPath)
# Set some values # Set some values
theProject = nwGUI.theProject theProject = nwGUI.theProject
+7 -12
View File
@@ -20,20 +20,20 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
""" """
import sys import sys
import novelwriter
import pytest import pytest
from PyQt5.QtWidgets import qApp, QMessageBox 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.gui
@pytest.mark.skipif(not sys.platform.startswith("linux"), reason="Linux Only") @pytest.mark.skipif(not sys.platform.startswith("linux"), reason="Linux Only")
@pytest.mark.skipif(not LANG_DATA, reason="No i18n Data") @pytest.mark.skipif(not LANG_DATA, reason="No i18n Data")
@pytest.mark.parametrize("language", [a for a, b in LANG_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. """test loading the gui with a specific language.
""" """
monkeypatch.setattr(QMessageBox, "warning", lambda *a: QMessageBox.Ok) 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) monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
# Set the test langauge # Set the test langauge
monkeypatch.setattr("novelwriter.CONFIG", fncConf) CONFIG.guiLocale = language
fncConf.guiLocale = language CONFIG.initLocalisation(qApp)
fncConf.initLocalisation(qApp)
nwGUI = novelwriter.main(["--testmode", f"--config={fncPath}", f"--data={fncPath}"]) nwGUI = main(["--testmode", f"--config={fncPath}", f"--data={fncPath}"])
qtbot.addWidget(nwGUI) qtbot.addWidget(nwGUI)
nwGUI.show() nwGUI.show()
qtbot.wait(20) qtbot.wait(20)
nwGUI.closeMain() nwGUI.closeMain()
# Reset the app language
fncConf.guiLocale = "en_GB"
fncConf.initLocalisation(qApp)
# END Test testI18n_Localisation # END Test testI18n_Localisation
+26 -36
View File
@@ -19,7 +19,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
""" """
import shutil
import pytest import pytest
from pathlib import Path from pathlib import Path
@@ -31,18 +30,17 @@ from tools import writeFile
from PyQt5.QtGui import QIcon, QPalette, QPixmap from PyQt5.QtGui import QIcon, QPalette, QPixmap
from PyQt5.QtWidgets import QApplication from PyQt5.QtWidgets import QApplication
from novelwriter import CONFIG
from novelwriter.enum import nwItemClass, nwItemLayout, nwItemType from novelwriter.enum import nwItemClass, nwItemLayout, nwItemType
from novelwriter.config import Config
from novelwriter.constants import nwLabels from novelwriter.constants import nwLabels
from novelwriter.gui.theme import GuiIcons, GuiTheme from novelwriter.gui.theme import GuiIcons, GuiTheme
@pytest.mark.gui @pytest.mark.gui
def testGuiTheme_Main(qtbot, nwGUI, fncPath): def testGuiTheme_Main(qtbot, nwGUI, tstPaths):
"""Test the theme class init. """Test the theme class init.
""" """
mainTheme: GuiTheme = nwGUI.mainTheme mainTheme: GuiTheme = nwGUI.mainTheme
mainConf: Config = nwGUI.mainConf
# Methods # Methods
# ======= # =======
@@ -55,35 +53,35 @@ def testGuiTheme_Main(qtbot, nwGUI, fncPath):
# ========== # ==========
# The defaults should be set # The defaults should be set
defaultFont = mainConf.guiFont defaultFont = CONFIG.guiFont
defaultSize = mainConf.guiFontSize defaultSize = CONFIG.guiFontSize
# CHange them to nonsense values # CHange them to nonsense values
mainConf.guiFont = "notafont" CONFIG.guiFont = "notafont"
mainConf.guiFontSize = 99 CONFIG.guiFontSize = 99
# Let the theme class set them back to default # Let the theme class set them back to default
mainTheme._setGuiFont() mainTheme._setGuiFont()
assert mainConf.guiFont == defaultFont assert CONFIG.guiFont == defaultFont
assert mainConf.guiFontSize == defaultSize assert CONFIG.guiFontSize == defaultSize
# A second call should just restore the defaults again # A second call should just restore the defaults again
mainTheme._setGuiFont() mainTheme._setGuiFont()
assert mainConf.guiFont == defaultFont assert CONFIG.guiFont == defaultFont
assert mainConf.guiFontSize == defaultSize assert CONFIG.guiFontSize == defaultSize
# Scan for Themes # Scan for Themes
# =============== # ===============
assert mainTheme._listConf({}, Path("not_a_path")) is False assert mainTheme._listConf({}, Path("not_a_path")) is False
themeOne = fncPath / "themes" / "themeone.conf" themeOne = tstPaths.cnfDir / "themes" / "themeone.conf"
themeTwo = fncPath / "themes" / "themetwo.conf" themeTwo = tstPaths.cnfDir / "themes" / "themetwo.conf"
writeFile(themeOne, "# Stuff") writeFile(themeOne, "# Stuff")
writeFile(themeTwo, "# Stuff") writeFile(themeTwo, "# Stuff")
result = {} result = {}
assert mainTheme._listConf(result, fncPath / "themes") is True assert mainTheme._listConf(result, tstPaths.cnfDir / "themes") is True
assert result["themeone"] == themeOne assert result["themeone"] == themeOne
assert result["themetwo"] == themeTwo assert result["themetwo"] == themeTwo
@@ -123,18 +121,14 @@ def testGuiTheme_Main(qtbot, nwGUI, fncPath):
@pytest.mark.gui @pytest.mark.gui
def testGuiTheme_Theme(qtbot, monkeypatch, nwGUI, fncPath): def testGuiTheme_Theme(qtbot, monkeypatch, nwGUI):
"""Test the theme part of the class. """Test the theme part of the class.
""" """
mainTheme: GuiTheme = nwGUI.mainTheme mainTheme: GuiTheme = nwGUI.mainTheme
mainConf: Config = nwGUI.mainConf
# List Themes # 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 # Block the reading of the files
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError) mp.setattr("builtins.open", causeOSError)
@@ -149,14 +143,14 @@ def testGuiTheme_Theme(qtbot, monkeypatch, nwGUI, fncPath):
assert mainTheme.listThemes() == mainTheme._themeList assert mainTheme.listThemes() == mainTheme._themeList
# Check handling of broken theme settings # Check handling of broken theme settings
mainConf.guiTheme = "not_a_theme" CONFIG.guiTheme = "not_a_theme"
availThemes = mainTheme._availThemes availThemes = mainTheme._availThemes
mainTheme._availThemes = {} mainTheme._availThemes = {}
assert mainTheme.loadTheme() is False assert mainTheme.loadTheme() is False
mainTheme._availThemes = availThemes mainTheme._availThemes = availThemes
# Check handling of unreadable file # Check handling of unreadable file
mainConf.guiTheme = "default" CONFIG.guiTheme = "default"
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError) mp.setattr("builtins.open", causeOSError)
assert mainTheme.loadTheme() is False 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) mainTheme._guiPalette.color(QPalette.Window).setRgb(0, 0, 0, 0)
# Load the default theme # Load the default theme
mainConf.guiTheme = "default" CONFIG.guiTheme = "default"
assert mainTheme.loadTheme() is True assert mainTheme.loadTheme() is True
# This should load a standard palette # This should load a standard palette
@@ -178,7 +172,7 @@ def testGuiTheme_Theme(qtbot, monkeypatch, nwGUI, fncPath):
# Load Default Dark Theme # Load Default Dark Theme
# ======================= # =======================
mainConf.guiTheme = "default_dark" CONFIG.guiTheme = "default_dark"
assert mainTheme.loadTheme() is True assert mainTheme.loadTheme() is True
# Check a few values # Check a few values
@@ -193,18 +187,14 @@ def testGuiTheme_Theme(qtbot, monkeypatch, nwGUI, fncPath):
@pytest.mark.gui @pytest.mark.gui
def testGuiTheme_Syntax(qtbot, monkeypatch, nwGUI, fncPath): def testGuiTheme_Syntax(qtbot, monkeypatch, nwGUI):
"""Test the syntax part of the class. """Test the syntax part of the class.
""" """
mainTheme: GuiTheme = nwGUI.mainTheme mainTheme: GuiTheme = nwGUI.mainTheme
mainConf: Config = nwGUI.mainConf
# List Themes # 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 # Block the reading of the files
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError) mp.setattr("builtins.open", causeOSError)
@@ -221,12 +211,12 @@ def testGuiTheme_Syntax(qtbot, monkeypatch, nwGUI, fncPath):
# Check handling of broken theme settings # Check handling of broken theme settings
availSyntax = mainTheme._availSyntax availSyntax = mainTheme._availSyntax
mainTheme._availSyntax = {} mainTheme._availSyntax = {}
mainConf.guiSyntax = "not_a_syntax" CONFIG.guiSyntax = "not_a_syntax"
assert mainTheme.loadSyntax() is False assert mainTheme.loadSyntax() is False
mainTheme._availSyntax = availSyntax mainTheme._availSyntax = availSyntax
# Check handling of unreadable file # Check handling of unreadable file
mainConf.guiSyntax = "default_light" CONFIG.guiSyntax = "default_light"
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError) mp.setattr("builtins.open", causeOSError)
assert mainTheme.loadSyntax() is False assert mainTheme.loadSyntax() is False
@@ -235,7 +225,7 @@ def testGuiTheme_Syntax(qtbot, monkeypatch, nwGUI, fncPath):
# ========================= # =========================
# Load the default syntax # Load the default syntax
mainConf.guiSyntax = "default_light" CONFIG.guiSyntax = "default_light"
assert mainTheme.loadSyntax() is True assert mainTheme.loadSyntax() is True
# Check some values # Check some values
@@ -248,7 +238,7 @@ def testGuiTheme_Syntax(qtbot, monkeypatch, nwGUI, fncPath):
# ======================= # =======================
# Load the default syntax # Load the default syntax
mainConf.guiSyntax = "default_dark" CONFIG.guiSyntax = "default_dark"
assert mainTheme.loadSyntax() is True assert mainTheme.loadSyntax() is True
# Check some values # Check some values
@@ -263,7 +253,7 @@ def testGuiTheme_Syntax(qtbot, monkeypatch, nwGUI, fncPath):
@pytest.mark.gui @pytest.mark.gui
def testGuiTheme_Icons(qtbot, caplog, monkeypatch, nwGUI, fncPath): def testGuiTheme_Icons(qtbot, caplog, monkeypatch, nwGUI, tstPaths):
"""Test the icon cache class. """Test the icon cache class.
""" """
iconCache: GuiIcons = nwGUI.mainTheme.iconCache iconCache: GuiIcons = nwGUI.mainTheme.iconCache
@@ -280,7 +270,7 @@ def testGuiTheme_Icons(qtbot, caplog, monkeypatch, nwGUI, fncPath):
assert iconCache.loadTheme("typicons_dark") is False assert iconCache.loadTheme("typicons_dark") is False
# Load a broken theme file # Load a broken theme file
iconsDir = fncPath / "icons" iconsDir = tstPaths.cnfDir / "icons"
testIcons = iconsDir / "testicons" testIcons = iconsDir / "testicons"
testIcons.mkdir() testIcons.mkdir()
writeFile(testIcons / "icons.conf", ( writeFile(testIcons / "icons.conf", (
@@ -293,7 +283,7 @@ def testGuiTheme_Icons(qtbot, caplog, monkeypatch, nwGUI, fncPath):
)) ))
iconPath = iconCache._iconPath iconPath = iconCache._iconPath
iconCache._iconPath = fncPath / "icons" iconCache._iconPath = tstPaths.cnfDir / "icons"
caplog.clear() caplog.clear()
assert iconCache.loadTheme("testicons") is True assert iconCache.loadTheme("testicons") is True
+7 -10
View File
@@ -33,7 +33,7 @@ from novelwriter.tools.writingstats import GuiWritingStats
@pytest.mark.gui @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. """Test the full writing stats tool.
""" """
# Create a project to work on # 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.listBox.topLevelItem(7).text(sessLog.C_COUNT) == "{:n}".format(200)
assert sessLog._saveData(sessLog.FMT_CSV) assert sessLog._saveData(sessLog.FMT_CSV)
qtbot.wait(100)
assert sessLog._saveData(sessLog.FMT_JSON) assert sessLog._saveData(sessLog.FMT_JSON)
qtbot.wait(100)
# Check the exported files # Check the exported files
jsonStats = fncPath / "sessionStats.json" jsonStats = tstPaths.tmpDir / "sessionStats.json"
with open(jsonStats, mode="r", encoding="utf-8") as inFile: with open(jsonStats, mode="r", encoding="utf-8") as inFile:
jsonData = json.load(inFile) jsonData = json.load(inFile)
@@ -171,7 +168,7 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncPath, projPath):
qtbot.mouseClick(sessLog.incNovel, Qt.LeftButton) qtbot.mouseClick(sessLog.incNovel, Qt.LeftButton)
assert sessLog._saveData(sessLog.FMT_JSON) assert sessLog._saveData(sessLog.FMT_JSON)
jsonStats = fncPath / "sessionStats.json" jsonStats = tstPaths.tmpDir / "sessionStats.json"
with open(jsonStats, mode="r", encoding="utf-8") as inFile: with open(jsonStats, mode="r", encoding="utf-8") as inFile:
jsonData = json.loads(inFile.read()) jsonData = json.loads(inFile.read())
@@ -217,7 +214,7 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncPath, projPath):
qtbot.mouseClick(sessLog.incNotes, Qt.LeftButton) qtbot.mouseClick(sessLog.incNotes, Qt.LeftButton)
assert sessLog._saveData(sessLog.FMT_JSON) assert sessLog._saveData(sessLog.FMT_JSON)
jsonStats = fncPath / "sessionStats.json" jsonStats = tstPaths.tmpDir / "sessionStats.json"
with open(jsonStats, mode="r", encoding="utf-8") as inFile: with open(jsonStats, mode="r", encoding="utf-8") as inFile:
jsonData = json.load(inFile) jsonData = json.load(inFile)
@@ -265,7 +262,7 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncPath, projPath):
# qtbot.stop() # qtbot.stop()
jsonStats = fncPath / "sessionStats.json" jsonStats = tstPaths.tmpDir / "sessionStats.json"
with open(jsonStats, mode="r", encoding="utf-8") as inFile: with open(jsonStats, mode="r", encoding="utf-8") as inFile:
jsonData = json.load(inFile) jsonData = json.load(inFile)
@@ -295,7 +292,7 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncPath, projPath):
qtbot.mouseClick(sessLog.hideZeros, Qt.LeftButton) qtbot.mouseClick(sessLog.hideZeros, Qt.LeftButton)
assert sessLog._saveData(sessLog.FMT_JSON) assert sessLog._saveData(sessLog.FMT_JSON)
jsonStats = fncPath / "sessionStats.json" jsonStats = tstPaths.tmpDir / "sessionStats.json"
with open(jsonStats, mode="r", encoding="utf-8") as inFile: with open(jsonStats, mode="r", encoding="utf-8") as inFile:
jsonData = json.load(inFile) jsonData = json.load(inFile)
@@ -348,7 +345,7 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncPath, projPath):
qtbot.mouseClick(sessLog.groupByDay, Qt.LeftButton) qtbot.mouseClick(sessLog.groupByDay, Qt.LeftButton)
assert sessLog._saveData(sessLog.FMT_JSON) assert sessLog._saveData(sessLog.FMT_JSON)
jsonStats = fncPath / "sessionStats.json" jsonStats = tstPaths.tmpDir / "sessionStats.json"
with open(jsonStats, mode="r", encoding="utf-8") as inFile: with open(jsonStats, mode="r", encoding="utf-8") as inFile:
jsonData = json.load(inFile) jsonData = json.load(inFile)