Reorganise remainin GUI tests, but no improved coverage
This commit is contained in:
+14
-1
@@ -52,7 +52,9 @@ pytest-3 -v -m core
|
||||
|
||||
Available markers are:
|
||||
|
||||
* '`core`' for unit tests covering the classes in the `nw/core` folder
|
||||
* `base` for unit tests covering the non-gui classes of the `bw` folder..
|
||||
* `core` for unit tests covering the classes in the `nw/core` folder.
|
||||
* `gui` for unit and integrations tests covering the classes in the `nw/gui` folder.
|
||||
|
||||
## Tests
|
||||
|
||||
@@ -78,6 +80,17 @@ The commands for the respective test categories are listed below.
|
||||
| Unit | Tokenizer class | nw/core/tokenizer.py | `-m core` | `-k testCoreToken` |
|
||||
| Integration | About Dialogs | nw/gui/about.py | `-m gui` | `-k testGuiAbout` |
|
||||
| Integration | Build Novel Project Tool | nw/gui/build.py | `-m gui` | `-k testGuiBuild` |
|
||||
| Integration | Document Editor Widget | nw/gui/doceditor.py | `-m gui` | `-k testGuiEditor` |
|
||||
| Integration | Document Viewer Widget | nw/gui/docviewer.py | `-m gui` | `-k testGuiViewer` |
|
||||
| Integration | Item Editor Dialog | nw/gui/itemeditor.py | `-m gui` | `-k testGuiItemEditor` |
|
||||
| Integration | Menu Widgets | nw/gui/mainmenu.py | `-m gui` | `-k testGuiMenu` |
|
||||
| Integration | Merge Tool | nw/gui/docmerge.py | `-m gui` | `-k testGuiMergeSplit` |
|
||||
| Integration | Outline Widget | nw/gui/outline.py | `-m gui` | `-k testGuiOutline` |
|
||||
| Integration | Preferences Dialog | nw/gui/preferences.py | `-m gui` | `-k testGuiPreferences` |
|
||||
| Integration | Project Load Dialog | nw/gui/projload.py | `-m gui` | `-k testGuiProjLoad` |
|
||||
| Integration | Project Settings Dialog | nw/gui/projsettings.py | `-m gui` | `-k testGuiProjSettings` |
|
||||
| Integration | Project Tree Widget | nw/gui/projtree.py | `-m gui` | `-k testGuiProjTree` |
|
||||
| Integration | Theme/Icon Classes | nw/gui/theme.py | `-m gui` | `-k testGuiTheme` |
|
||||
| Integration | Split Tool | nw/gui/docsplit.py | `-m gui` | `-k testGuiMergeSplit` |
|
||||
| Integration | Writing Stats Dialog | nw/gui/writingstats.py | `-m gui` | `-k testGuiWritingStats` |
|
||||
| Integration | Various Dialogs | N/A | `-m gui` | `-k testGuiDialogs` |
|
||||
|
||||
@@ -9,8 +9,6 @@ import os
|
||||
|
||||
from dummy import DummyMain
|
||||
|
||||
from PyQt5.QtWidgets import QMessageBox
|
||||
|
||||
sys.path.insert(1, os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir)))
|
||||
|
||||
import nw # noqa: E402
|
||||
@@ -184,42 +182,3 @@ def nwOldProj(tmpDir):
|
||||
if os.path.isdir(oldProjDir):
|
||||
shutil.rmtree(oldProjDir)
|
||||
return
|
||||
|
||||
##
|
||||
# Monkey Patch Dialogs
|
||||
##
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def yesToAll(monkeypatch):
|
||||
"""Make the message boxes/questions always say yes.
|
||||
"""
|
||||
monkeypatch.setattr(
|
||||
QMessageBox, "question", lambda *args, **kwargs: QMessageBox.Yes
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
QMessageBox, "information", lambda *args, **kwargs: QMessageBox.Yes
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
QMessageBox, "warning", lambda *args, **kwargs: QMessageBox.Yes
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
QMessageBox, "critical", lambda *args, **kwargs: QMessageBox.Yes
|
||||
)
|
||||
yield
|
||||
monkeypatch.undo()
|
||||
return
|
||||
|
||||
# =============================================================================================== #
|
||||
|
||||
##
|
||||
# Temporary Test Folders
|
||||
##
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def nwTempGUI(tmpDir):
|
||||
"""A temporary folder for GUI tests.
|
||||
"""
|
||||
guiDir = os.path.join(tmpDir, "gui")
|
||||
if not os.path.isdir(guiDir):
|
||||
os.mkdir(guiDir)
|
||||
return guiDir
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ backuponclose = True
|
||||
askbeforebackup = True
|
||||
|
||||
[State]
|
||||
showrefpanel = False
|
||||
showrefpanel = True
|
||||
viewcomments = True
|
||||
viewsynopsis = True
|
||||
searchcase = False
|
||||
+14
-506
@@ -2,511 +2,23 @@
|
||||
"""novelWriter Dialog Class Tester
|
||||
"""
|
||||
|
||||
import nw
|
||||
import pytest
|
||||
import os
|
||||
import sys
|
||||
|
||||
from shutil import copyfile
|
||||
from tools import cmpFiles, getGuiItem
|
||||
from PyQt5.QtCore import QItemSelectionModel
|
||||
from PyQt5.QtWidgets import QListWidgetItem, QDialog, QFileDialog, QMessageBox
|
||||
|
||||
from PyQt5.QtCore import Qt, QItemSelectionModel
|
||||
from PyQt5.QtWidgets import (
|
||||
QDialogButtonBox, QTreeWidgetItem, QListWidgetItem, QDialog, QAction,
|
||||
QFileDialog, QFontDialog
|
||||
)
|
||||
|
||||
from nw.gui import GuiProjectWizard, GuiProjectLoad, GuiPreferences
|
||||
from nw.gui.custom import QuotesDialog
|
||||
from nw.constants import nwItemClass
|
||||
|
||||
keyDelay = 2
|
||||
typeDelay = 1
|
||||
stepDelay = 20
|
||||
|
||||
@pytest.mark.gui
|
||||
def testNewProjectWizard(qtbot, monkeypatch, yesToAll, nwMinimal, tmpDir):
|
||||
|
||||
if sys.platform.startswith("darwin"):
|
||||
# Disable for macOS because the test segfaults on QWizard.show()
|
||||
return
|
||||
|
||||
from PyQt5.QtWidgets import QWizard
|
||||
from nw.gui.projwizard import (
|
||||
ProjWizardIntroPage, ProjWizardFolderPage, ProjWizardPopulatePage,
|
||||
ProjWizardCustomPage, ProjWizardFinalPage
|
||||
)
|
||||
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % tmpDir, "--data=%s" % tmpDir])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
##
|
||||
# Test New Project Function
|
||||
##
|
||||
|
||||
# New with a project open should cause an error
|
||||
assert nwGUI.openProject(nwMinimal)
|
||||
assert not nwGUI.newProject()
|
||||
|
||||
# Close project, but call with invalid path
|
||||
assert nwGUI.closeProject()
|
||||
monkeypatch.setattr(nwGUI, "showNewProjectDialog", lambda *args: None)
|
||||
assert not nwGUI.newProject()
|
||||
|
||||
# Now, with an empty dictionary
|
||||
monkeypatch.setattr(nwGUI, "showNewProjectDialog", lambda *args: {})
|
||||
assert not nwGUI.newProject()
|
||||
|
||||
# Now, with a non-empty folder
|
||||
monkeypatch.setattr(nwGUI, "showNewProjectDialog", lambda *args: {"projPath": nwMinimal})
|
||||
assert not nwGUI.newProject()
|
||||
|
||||
monkeypatch.undo()
|
||||
|
||||
##
|
||||
# Test the Wizard
|
||||
##
|
||||
|
||||
monkeypatch.setattr(GuiProjectWizard, "exec_", lambda *args: None)
|
||||
nwGUI.mainConf.lastPath = " "
|
||||
|
||||
nwGUI.closeProject()
|
||||
nwGUI.showNewProjectDialog()
|
||||
qtbot.waitUntil(lambda: getGuiItem("GuiProjectWizard") is not None, timeout=1000)
|
||||
|
||||
nwWiz = getGuiItem("GuiProjectWizard")
|
||||
assert isinstance(nwWiz, GuiProjectWizard)
|
||||
nwWiz.show()
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
for wStep in range(4):
|
||||
# This does not actually create the project, it just generates the
|
||||
# dictionary that defines it.
|
||||
|
||||
# Intro Page
|
||||
introPage = nwWiz.currentPage()
|
||||
assert isinstance(introPage, ProjWizardIntroPage)
|
||||
assert not nwWiz.button(QWizard.NextButton).isEnabled()
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
for c in ("Test Minimal %d" % wStep):
|
||||
qtbot.keyClick(introPage.projName, c, delay=typeDelay)
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
for c in "Minimal Novel":
|
||||
qtbot.keyClick(introPage.projTitle, c, delay=typeDelay)
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
for c in "Jane Doe":
|
||||
qtbot.keyClick(introPage.projAuthors, c, delay=typeDelay)
|
||||
|
||||
# Setting projName should activate the button
|
||||
assert nwWiz.button(QWizard.NextButton).isEnabled()
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwWiz.button(QWizard.NextButton), Qt.LeftButton)
|
||||
|
||||
# Folder Page
|
||||
storagePage = nwWiz.currentPage()
|
||||
assert isinstance(storagePage, ProjWizardFolderPage)
|
||||
assert not nwWiz.button(QWizard.NextButton).isEnabled()
|
||||
|
||||
if wStep == 0:
|
||||
# Check invalid path first, the first time we reach here
|
||||
monkeypatch.setattr(QFileDialog, "getExistingDirectory", lambda *a, **kw: "")
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(storagePage.browseButton, Qt.LeftButton, delay=100)
|
||||
assert storagePage.projPath.text() == ""
|
||||
|
||||
# Then, we always return nwMinimal as path
|
||||
monkeypatch.setattr(QFileDialog, "getExistingDirectory", lambda *a, **kw: nwMinimal)
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(storagePage.browseButton, Qt.LeftButton, delay=100)
|
||||
projPath = os.path.join(nwMinimal, "Test Minimal %d" % wStep)
|
||||
assert storagePage.projPath.text() == projPath
|
||||
|
||||
# Setting projPath should activate the button
|
||||
assert nwWiz.button(QWizard.NextButton).isEnabled()
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwWiz.button(QWizard.NextButton), Qt.LeftButton)
|
||||
|
||||
# Populate Page
|
||||
popPage = nwWiz.currentPage()
|
||||
assert isinstance(popPage, ProjWizardPopulatePage)
|
||||
assert nwWiz.button(QWizard.NextButton).isEnabled()
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
if wStep == 0:
|
||||
popPage.popMinimal.setChecked(True)
|
||||
elif wStep == 1:
|
||||
popPage.popCustom.setChecked(True)
|
||||
elif wStep == 2:
|
||||
popPage.popCustom.setChecked(True)
|
||||
elif wStep == 3:
|
||||
popPage.popSample.setChecked(True)
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwWiz.button(QWizard.NextButton), Qt.LeftButton)
|
||||
|
||||
# Custom Page
|
||||
if wStep == 1 or wStep == 2:
|
||||
customPage = nwWiz.currentPage()
|
||||
assert isinstance(customPage, ProjWizardCustomPage)
|
||||
assert nwWiz.button(QWizard.NextButton).isEnabled()
|
||||
|
||||
customPage.addPlot.setChecked(True)
|
||||
customPage.addChar.setChecked(True)
|
||||
customPage.addWorld.setChecked(True)
|
||||
customPage.addTime.setChecked(True)
|
||||
customPage.addObject.setChecked(True)
|
||||
customPage.addEntity.setChecked(True)
|
||||
|
||||
if wStep == 2:
|
||||
customPage.numChapters.setValue(0)
|
||||
customPage.numScenes.setValue(10)
|
||||
customPage.chFolders.setChecked(False)
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwWiz.button(QWizard.NextButton), Qt.LeftButton)
|
||||
|
||||
# Final Page
|
||||
finalPage = nwWiz.currentPage()
|
||||
assert isinstance(finalPage, ProjWizardFinalPage)
|
||||
assert nwWiz.button(QWizard.FinishButton).isEnabled() # But we don't click it
|
||||
|
||||
# Check Data
|
||||
projData = nwGUI._assembleProjectWizardData(nwWiz)
|
||||
assert projData["projName"] == "Test Minimal %d" % wStep
|
||||
assert projData["projTitle"] == "Minimal Novel"
|
||||
assert projData["projAuthors"] == "Jane Doe"
|
||||
assert projData["projPath"] == projPath
|
||||
assert projData["popMinimal"] == (wStep == 0)
|
||||
assert projData["popCustom"] == (wStep == 1 or wStep == 2)
|
||||
assert projData["popSample"] == (wStep == 3)
|
||||
if wStep == 1 or wStep == 2:
|
||||
assert projData["addRoots"] == [
|
||||
nwItemClass.PLOT,
|
||||
nwItemClass.CHARACTER,
|
||||
nwItemClass.WORLD,
|
||||
nwItemClass.TIMELINE,
|
||||
nwItemClass.OBJECT,
|
||||
nwItemClass.ENTITY,
|
||||
]
|
||||
if wStep == 1:
|
||||
assert projData["numChapters"] == 5
|
||||
assert projData["numScenes"] == 5
|
||||
assert projData["chFolders"]
|
||||
else:
|
||||
assert projData["numChapters"] == 0
|
||||
assert projData["numScenes"] == 10
|
||||
assert not projData["chFolders"]
|
||||
else:
|
||||
assert projData["addRoots"] == []
|
||||
assert projData["numChapters"] == 0
|
||||
assert projData["numScenes"] == 0
|
||||
assert not projData["chFolders"]
|
||||
|
||||
# Restart the wizard for next iteration
|
||||
nwWiz.restart()
|
||||
|
||||
nwWiz.reject()
|
||||
nwWiz.close()
|
||||
|
||||
# qtbot.stopForInteraction()
|
||||
nwGUI.closeMain()
|
||||
nwGUI.close()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testLoadProject(qtbot, monkeypatch, yesToAll, nwMinimal, tmpDir):
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwMinimal, "--data=%s" % tmpDir])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
assert nwGUI.openProject(nwMinimal)
|
||||
assert nwGUI.closeProject()
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
monkeypatch.setattr(GuiProjectLoad, "exec_", lambda *args: None)
|
||||
monkeypatch.setattr(GuiProjectLoad, "result", lambda *args: QDialog.Accepted)
|
||||
nwGUI.mainMenu.aOpenProject.activate(QAction.Trigger)
|
||||
qtbot.waitUntil(lambda: getGuiItem("GuiProjectLoad") is not None, timeout=1000)
|
||||
|
||||
nwLoad = getGuiItem("GuiProjectLoad")
|
||||
assert isinstance(nwLoad, GuiProjectLoad)
|
||||
nwLoad.show()
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
recentCount = nwLoad.listBox.topLevelItemCount()
|
||||
assert recentCount > 0
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
selItem = nwLoad.listBox.topLevelItem(0)
|
||||
selPath = selItem.data(nwLoad.C_NAME, Qt.UserRole)
|
||||
assert isinstance(selItem, QTreeWidgetItem)
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
nwLoad.selPath.setText("")
|
||||
nwLoad.listBox.setCurrentItem(selItem)
|
||||
nwLoad._doSelectRecent()
|
||||
assert nwLoad.selPath.text() == selPath
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwLoad.buttonBox.button(QDialogButtonBox.Open), Qt.LeftButton)
|
||||
assert nwLoad.openPath == selPath
|
||||
assert nwLoad.openState == nwLoad.OPEN_STATE
|
||||
|
||||
# Just create a new project load from scratch for the rest of the test
|
||||
del nwLoad
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
nwGUI.mainMenu.aOpenProject.activate(QAction.Trigger)
|
||||
qtbot.waitUntil(lambda: getGuiItem("GuiProjectLoad") is not None, timeout=1000)
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
nwLoad = getGuiItem("GuiProjectLoad")
|
||||
assert isinstance(nwLoad, GuiProjectLoad)
|
||||
nwLoad.show()
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwLoad.buttonBox.button(QDialogButtonBox.Cancel), Qt.LeftButton)
|
||||
assert nwLoad.openPath is None
|
||||
assert nwLoad.openState == nwLoad.NONE_STATE
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
nwLoad.show()
|
||||
qtbot.mouseClick(nwLoad.newButton, Qt.LeftButton)
|
||||
assert nwLoad.openPath is None
|
||||
assert nwLoad.openState == nwLoad.NEW_STATE
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
nwLoad.show()
|
||||
nwLoad._keyPressDelete()
|
||||
assert nwLoad.listBox.topLevelItemCount() == recentCount - 1
|
||||
|
||||
getFile = os.path.join(nwMinimal, "nwProject.nwx")
|
||||
monkeypatch.setattr(QFileDialog, "getOpenFileName", lambda *args, **kwargs: (getFile, None))
|
||||
qtbot.mouseClick(nwLoad.browseButton, Qt.LeftButton)
|
||||
assert nwLoad.openPath == nwMinimal
|
||||
assert nwLoad.openState == nwLoad.OPEN_STATE
|
||||
# qtbot.stopForInteraction()
|
||||
|
||||
nwLoad.close()
|
||||
nwGUI.closeMain()
|
||||
nwGUI.close()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testPreferences(qtbot, monkeypatch, yesToAll, nwMinimal, tmpDir, refDir, tmpConf):
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwMinimal, "--data=%s" % tmpDir])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
assert nwGUI.openProject(nwMinimal)
|
||||
|
||||
monkeypatch.setattr(GuiPreferences, "exec_", lambda *args: None)
|
||||
monkeypatch.setattr(GuiPreferences, "result", lambda *args: QDialog.Accepted)
|
||||
nwGUI.mainMenu.aPreferences.activate(QAction.Trigger)
|
||||
qtbot.waitUntil(lambda: getGuiItem("GuiPreferences") is not None, timeout=1000)
|
||||
|
||||
nwPrefs = getGuiItem("GuiPreferences")
|
||||
assert isinstance(nwPrefs, GuiPreferences)
|
||||
nwPrefs.show()
|
||||
|
||||
# Override Config
|
||||
tmpConf.confPath = nwMinimal
|
||||
tmpConf.showGUI = False
|
||||
nwGUI.mainConf = tmpConf
|
||||
nwPrefs.mainConf = tmpConf
|
||||
nwPrefs.tabGeneral.mainConf = tmpConf
|
||||
nwPrefs.tabProjects.mainConf = tmpConf
|
||||
nwPrefs.tabLayout.mainConf = tmpConf
|
||||
nwPrefs.tabEditing.mainConf = tmpConf
|
||||
nwPrefs.tabAutoRep.mainConf = tmpConf
|
||||
|
||||
# General Settings
|
||||
qtbot.wait(keyDelay)
|
||||
tabGeneral = nwPrefs.tabGeneral
|
||||
nwPrefs._tabBox.setCurrentWidget(tabGeneral)
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert not tabGeneral.preferDarkIcons.isChecked()
|
||||
qtbot.mouseClick(tabGeneral.preferDarkIcons, Qt.LeftButton)
|
||||
assert tabGeneral.preferDarkIcons.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert tabGeneral.showFullPath.isChecked()
|
||||
qtbot.mouseClick(tabGeneral.showFullPath, Qt.LeftButton)
|
||||
assert not tabGeneral.showFullPath.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert not tabGeneral.hideVScroll.isChecked()
|
||||
qtbot.mouseClick(tabGeneral.hideVScroll, Qt.LeftButton)
|
||||
assert tabGeneral.hideVScroll.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert not tabGeneral.hideHScroll.isChecked()
|
||||
qtbot.mouseClick(tabGeneral.hideHScroll, Qt.LeftButton)
|
||||
assert tabGeneral.hideHScroll.isChecked()
|
||||
|
||||
# Check font button
|
||||
monkeypatch.setattr(QFontDialog, "getFont", lambda font, obj: (font, True))
|
||||
qtbot.mouseClick(tabGeneral.fontButton, Qt.LeftButton)
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
tabGeneral.guiFontSize.setValue(12)
|
||||
|
||||
# Projects Settings
|
||||
qtbot.wait(keyDelay)
|
||||
tabProjects = nwPrefs.tabProjects
|
||||
nwPrefs._tabBox.setCurrentWidget(tabProjects)
|
||||
tabProjects.backupPath = "no/where"
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert not tabProjects.backupOnClose.isChecked()
|
||||
qtbot.mouseClick(tabProjects.backupOnClose, Qt.LeftButton)
|
||||
assert tabProjects.backupOnClose.isChecked()
|
||||
|
||||
# Check Browse button
|
||||
monkeypatch.setattr(QFileDialog, "getExistingDirectory", lambda *args, **kwargs: "")
|
||||
assert not tabProjects._backupFolder()
|
||||
monkeypatch.setattr(QFileDialog, "getExistingDirectory", lambda *args, **kwargs: "some/dir")
|
||||
qtbot.mouseClick(tabProjects.backupGetPath, Qt.LeftButton)
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
tabProjects.autoSaveDoc.setValue(20)
|
||||
tabProjects.autoSaveProj.setValue(40)
|
||||
|
||||
# Text Layout Settings
|
||||
qtbot.wait(keyDelay)
|
||||
tabLayout = nwPrefs.tabLayout
|
||||
nwPrefs._tabBox.setCurrentWidget(tabLayout)
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
qtbot.mouseClick(tabLayout.fontButton, Qt.LeftButton)
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
tabLayout.textStyleSize.setValue(13)
|
||||
tabLayout.textFlowMax.setValue(700)
|
||||
tabLayout.focusDocWidth.setValue(900)
|
||||
tabLayout.textMargin.setValue(45)
|
||||
tabLayout.tabWidth.setValue(45)
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert not tabLayout.textFlowFixed.isChecked()
|
||||
qtbot.mouseClick(tabLayout.textFlowFixed, Qt.LeftButton)
|
||||
assert tabLayout.textFlowFixed.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert not tabLayout.hideFocusFooter.isChecked()
|
||||
qtbot.mouseClick(tabLayout.hideFocusFooter, Qt.LeftButton)
|
||||
assert tabLayout.hideFocusFooter.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert tabLayout.textJustify.isChecked()
|
||||
qtbot.mouseClick(tabLayout.textJustify, Qt.LeftButton)
|
||||
assert not tabLayout.textJustify.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert tabLayout.scrollPastEnd.isChecked()
|
||||
qtbot.mouseClick(tabLayout.scrollPastEnd, Qt.LeftButton)
|
||||
assert not tabLayout.scrollPastEnd.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert not tabLayout.autoScroll.isChecked()
|
||||
qtbot.mouseClick(tabLayout.autoScroll, Qt.LeftButton)
|
||||
assert tabLayout.autoScroll.isChecked()
|
||||
|
||||
# Editor Settings
|
||||
qtbot.wait(keyDelay)
|
||||
tabEditing = nwPrefs.tabEditing
|
||||
nwPrefs._tabBox.setCurrentWidget(tabEditing)
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert tabEditing.highlightQuotes.isChecked()
|
||||
qtbot.mouseClick(tabEditing.highlightQuotes, Qt.LeftButton)
|
||||
assert not tabEditing.highlightQuotes.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert tabEditing.highlightEmph.isChecked()
|
||||
qtbot.mouseClick(tabEditing.highlightEmph, Qt.LeftButton)
|
||||
assert not tabEditing.highlightEmph.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert not tabEditing.showTabsNSpaces.isChecked()
|
||||
qtbot.mouseClick(tabEditing.showTabsNSpaces, Qt.LeftButton)
|
||||
assert tabEditing.showTabsNSpaces.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert not tabEditing.showLineEndings.isChecked()
|
||||
qtbot.mouseClick(tabEditing.showLineEndings, Qt.LeftButton)
|
||||
assert tabEditing.showLineEndings.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
tabEditing.bigDocLimit.setValue(500)
|
||||
|
||||
# Auto-Replace Settings
|
||||
qtbot.wait(keyDelay)
|
||||
tabAutoRep = nwPrefs.tabAutoRep
|
||||
nwPrefs._tabBox.setCurrentWidget(tabAutoRep)
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert tabAutoRep.autoSelect.isChecked()
|
||||
qtbot.mouseClick(tabAutoRep.autoSelect, Qt.LeftButton)
|
||||
assert not tabAutoRep.autoSelect.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert tabAutoRep.autoReplaceMain.isChecked()
|
||||
qtbot.mouseClick(tabAutoRep.autoReplaceMain, Qt.LeftButton)
|
||||
assert not tabAutoRep.autoReplaceMain.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert not tabAutoRep.autoReplaceSQ.isEnabled()
|
||||
assert not tabAutoRep.autoReplaceDQ.isEnabled()
|
||||
assert not tabAutoRep.autoReplaceDash.isEnabled()
|
||||
assert not tabAutoRep.autoReplaceDots.isEnabled()
|
||||
|
||||
monkeypatch.setattr(QuotesDialog, "selectedQuote", "'")
|
||||
monkeypatch.setattr(QuotesDialog, "exec_", lambda *args: QDialog.Accepted)
|
||||
qtbot.mouseClick(tabAutoRep.btnDoubleStyleC, Qt.LeftButton)
|
||||
|
||||
# Save and Check Config
|
||||
qtbot.mouseClick(nwPrefs.buttonBox.button(QDialogButtonBox.Ok), Qt.LeftButton)
|
||||
|
||||
assert tmpConf.confChanged
|
||||
tmpConf.lastPath = ""
|
||||
|
||||
assert nwGUI.mainConf.saveConfig()
|
||||
|
||||
# qtbot.stopForInteraction()
|
||||
nwGUI.closeMain()
|
||||
|
||||
refConf = os.path.join(refDir, "novelwriter_prefs.conf")
|
||||
projConf = os.path.join(nwGUI.mainConf.confPath, "novelwriter.conf")
|
||||
testConf = os.path.join(tmpDir, "novelwriter_prefs.conf")
|
||||
copyfile(projConf, testConf)
|
||||
ignoreLines = [
|
||||
2, # Timestamp
|
||||
9, # Release Notes
|
||||
12, 13, 14, 15, 16, 17, 18, # Window sizes
|
||||
7, 28, # Fonts (depends on system default)
|
||||
]
|
||||
assert cmpFiles(testConf, refConf, ignoreLines)
|
||||
|
||||
@pytest.mark.gui
|
||||
def testQuotesDialog(qtbot, yesToAll, nwMinimal, tmpDir):
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwMinimal, "--data=%s" % tmpDir, nwMinimal])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
qtbot.wait(stepDelay)
|
||||
def testGuiDialogs_Quotes(qtbot, monkeypatch, nwGUI, nwMinimal):
|
||||
"""Test the quote symbols dialog.
|
||||
"""
|
||||
# Block message box
|
||||
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
|
||||
|
||||
nwQuot = QuotesDialog(nwGUI)
|
||||
nwQuot.show()
|
||||
@@ -527,20 +39,16 @@ def testQuotesDialog(qtbot, yesToAll, nwMinimal, tmpDir):
|
||||
# qtbot.stopForInteraction()
|
||||
nwQuot._doReject()
|
||||
nwQuot.close()
|
||||
nwGUI.closeMain()
|
||||
nwGUI.close()
|
||||
|
||||
# END Test testDialogs_Quotes
|
||||
|
||||
@pytest.mark.gui
|
||||
def testDialogsOpenClose(qtbot, monkeypatch, yesToAll, nwMinimal, tmpDir):
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwMinimal, "--data=%s" % tmpDir, nwMinimal])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
def testGuiDialogs_Other(qtbot, monkeypatch, nwGUI, nwMinimal, tmpDir):
|
||||
"""Various other dialog tests.
|
||||
"""
|
||||
monkeypatch.setattr(QFileDialog, "getExistingDirectory", lambda *args, **kwargs: tmpDir)
|
||||
assert nwGUI.selectProjectPath() == tmpDir
|
||||
|
||||
# qtbot.stopForInteraction()
|
||||
nwGUI.closeMain()
|
||||
nwGUI.close()
|
||||
|
||||
# END Test testGuiDialogs_Other
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""novelWriter Dialog Class Tester
|
||||
"""
|
||||
|
||||
import nw
|
||||
import pytest
|
||||
import os
|
||||
|
||||
from shutil import copyfile
|
||||
from tools import cmpFiles, getGuiItem
|
||||
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import (
|
||||
QDialogButtonBox, QDialog, QAction, QFileDialog, QFontDialog, QMessageBox
|
||||
)
|
||||
|
||||
from nw.gui import GuiPreferences
|
||||
from nw.config import Config
|
||||
from nw.gui.custom import QuotesDialog
|
||||
|
||||
keyDelay = 2
|
||||
typeDelay = 1
|
||||
stepDelay = 20
|
||||
|
||||
@pytest.mark.gui
|
||||
def testGuiPreferences_Main(qtbot, monkeypatch, fncDir, outDir, refDir):
|
||||
"""Test the load project wizard.
|
||||
"""
|
||||
# Block message box
|
||||
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
|
||||
monkeypatch.setattr(QMessageBox, "information", lambda *args: QMessageBox.Yes)
|
||||
|
||||
# Must create a clean config and GUI object as the test-wide
|
||||
# nw.CONFIG object is created on import an can be tainted by other tests
|
||||
confFile = os.path.join(fncDir, "novelwriter.conf")
|
||||
if os.path.isfile(confFile):
|
||||
os.unlink(confFile)
|
||||
theConf = Config()
|
||||
theConf.initConfig(fncDir, fncDir)
|
||||
theConf.setLastPath("")
|
||||
origConf = nw.CONFIG
|
||||
nw.CONFIG = theConf
|
||||
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % fncDir, "--data=%s" % fncDir])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
qtbot.wait(20)
|
||||
|
||||
theConf = nwGUI.mainConf
|
||||
assert theConf.confPath == fncDir
|
||||
|
||||
monkeypatch.setattr(GuiPreferences, "exec_", lambda *args: None)
|
||||
monkeypatch.setattr(GuiPreferences, "result", lambda *args: QDialog.Accepted)
|
||||
nwGUI.mainMenu.aPreferences.activate(QAction.Trigger)
|
||||
qtbot.waitUntil(lambda: getGuiItem("GuiPreferences") is not None, timeout=1000)
|
||||
|
||||
nwPrefs = getGuiItem("GuiPreferences")
|
||||
assert isinstance(nwPrefs, GuiPreferences)
|
||||
nwPrefs.show()
|
||||
assert nwPrefs.mainConf.confPath == fncDir
|
||||
|
||||
# qtbot.stopForInteraction()
|
||||
# General Settings
|
||||
qtbot.wait(keyDelay)
|
||||
tabGeneral = nwPrefs.tabGeneral
|
||||
nwPrefs._tabBox.setCurrentWidget(tabGeneral)
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert not tabGeneral.preferDarkIcons.isChecked()
|
||||
qtbot.mouseClick(tabGeneral.preferDarkIcons, Qt.LeftButton)
|
||||
assert tabGeneral.preferDarkIcons.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert tabGeneral.showFullPath.isChecked()
|
||||
qtbot.mouseClick(tabGeneral.showFullPath, Qt.LeftButton)
|
||||
assert not tabGeneral.showFullPath.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert not tabGeneral.hideVScroll.isChecked()
|
||||
qtbot.mouseClick(tabGeneral.hideVScroll, Qt.LeftButton)
|
||||
assert tabGeneral.hideVScroll.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert not tabGeneral.hideHScroll.isChecked()
|
||||
qtbot.mouseClick(tabGeneral.hideHScroll, Qt.LeftButton)
|
||||
assert tabGeneral.hideHScroll.isChecked()
|
||||
|
||||
# Check font button
|
||||
monkeypatch.setattr(QFontDialog, "getFont", lambda font, obj: (font, True))
|
||||
qtbot.mouseClick(tabGeneral.fontButton, Qt.LeftButton)
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
tabGeneral.guiFontSize.setValue(12)
|
||||
|
||||
# Projects Settings
|
||||
qtbot.wait(keyDelay)
|
||||
tabProjects = nwPrefs.tabProjects
|
||||
nwPrefs._tabBox.setCurrentWidget(tabProjects)
|
||||
tabProjects.backupPath = "no/where"
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert not tabProjects.backupOnClose.isChecked()
|
||||
qtbot.mouseClick(tabProjects.backupOnClose, Qt.LeftButton)
|
||||
assert tabProjects.backupOnClose.isChecked()
|
||||
|
||||
# Check Browse button
|
||||
monkeypatch.setattr(QFileDialog, "getExistingDirectory", lambda *args, **kwargs: "")
|
||||
assert not tabProjects._backupFolder()
|
||||
monkeypatch.setattr(QFileDialog, "getExistingDirectory", lambda *args, **kwargs: "some/dir")
|
||||
qtbot.mouseClick(tabProjects.backupGetPath, Qt.LeftButton)
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
tabProjects.autoSaveDoc.setValue(20)
|
||||
tabProjects.autoSaveProj.setValue(40)
|
||||
|
||||
# Text Layout Settings
|
||||
qtbot.wait(keyDelay)
|
||||
tabLayout = nwPrefs.tabLayout
|
||||
nwPrefs._tabBox.setCurrentWidget(tabLayout)
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
qtbot.mouseClick(tabLayout.fontButton, Qt.LeftButton)
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
tabLayout.textStyleSize.setValue(13)
|
||||
tabLayout.textFlowMax.setValue(700)
|
||||
tabLayout.focusDocWidth.setValue(900)
|
||||
tabLayout.textMargin.setValue(45)
|
||||
tabLayout.tabWidth.setValue(45)
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert not tabLayout.textFlowFixed.isChecked()
|
||||
qtbot.mouseClick(tabLayout.textFlowFixed, Qt.LeftButton)
|
||||
assert tabLayout.textFlowFixed.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert not tabLayout.hideFocusFooter.isChecked()
|
||||
qtbot.mouseClick(tabLayout.hideFocusFooter, Qt.LeftButton)
|
||||
assert tabLayout.hideFocusFooter.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert tabLayout.textJustify.isChecked()
|
||||
qtbot.mouseClick(tabLayout.textJustify, Qt.LeftButton)
|
||||
assert not tabLayout.textJustify.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert tabLayout.scrollPastEnd.isChecked()
|
||||
qtbot.mouseClick(tabLayout.scrollPastEnd, Qt.LeftButton)
|
||||
assert not tabLayout.scrollPastEnd.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert not tabLayout.autoScroll.isChecked()
|
||||
qtbot.mouseClick(tabLayout.autoScroll, Qt.LeftButton)
|
||||
assert tabLayout.autoScroll.isChecked()
|
||||
|
||||
# Editor Settings
|
||||
qtbot.wait(keyDelay)
|
||||
tabEditing = nwPrefs.tabEditing
|
||||
nwPrefs._tabBox.setCurrentWidget(tabEditing)
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert tabEditing.highlightQuotes.isChecked()
|
||||
qtbot.mouseClick(tabEditing.highlightQuotes, Qt.LeftButton)
|
||||
assert not tabEditing.highlightQuotes.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert tabEditing.highlightEmph.isChecked()
|
||||
qtbot.mouseClick(tabEditing.highlightEmph, Qt.LeftButton)
|
||||
assert not tabEditing.highlightEmph.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert not tabEditing.showTabsNSpaces.isChecked()
|
||||
qtbot.mouseClick(tabEditing.showTabsNSpaces, Qt.LeftButton)
|
||||
assert tabEditing.showTabsNSpaces.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert not tabEditing.showLineEndings.isChecked()
|
||||
qtbot.mouseClick(tabEditing.showLineEndings, Qt.LeftButton)
|
||||
assert tabEditing.showLineEndings.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
tabEditing.bigDocLimit.setValue(500)
|
||||
|
||||
# Auto-Replace Settings
|
||||
qtbot.wait(keyDelay)
|
||||
tabAutoRep = nwPrefs.tabAutoRep
|
||||
nwPrefs._tabBox.setCurrentWidget(tabAutoRep)
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert tabAutoRep.autoSelect.isChecked()
|
||||
qtbot.mouseClick(tabAutoRep.autoSelect, Qt.LeftButton)
|
||||
assert not tabAutoRep.autoSelect.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert tabAutoRep.autoReplaceMain.isChecked()
|
||||
qtbot.mouseClick(tabAutoRep.autoReplaceMain, Qt.LeftButton)
|
||||
assert not tabAutoRep.autoReplaceMain.isChecked()
|
||||
|
||||
qtbot.wait(keyDelay)
|
||||
assert not tabAutoRep.autoReplaceSQ.isEnabled()
|
||||
assert not tabAutoRep.autoReplaceDQ.isEnabled()
|
||||
assert not tabAutoRep.autoReplaceDash.isEnabled()
|
||||
assert not tabAutoRep.autoReplaceDots.isEnabled()
|
||||
|
||||
monkeypatch.setattr(QuotesDialog, "selectedQuote", "'")
|
||||
monkeypatch.setattr(QuotesDialog, "exec_", lambda *args: QDialog.Accepted)
|
||||
qtbot.mouseClick(tabAutoRep.btnDoubleStyleC, Qt.LeftButton)
|
||||
|
||||
# Save and Check Config
|
||||
qtbot.mouseClick(nwPrefs.buttonBox.button(QDialogButtonBox.Ok), Qt.LeftButton)
|
||||
|
||||
assert theConf.confChanged
|
||||
theConf.lastPath = ""
|
||||
|
||||
assert nwGUI.mainConf.saveConfig()
|
||||
projFile = os.path.join(fncDir, "novelwriter.conf")
|
||||
testFile = os.path.join(outDir, "guiPreferences_novelwriter.conf")
|
||||
compFile = os.path.join(refDir, "guiPreferences_novelwriter.conf")
|
||||
copyfile(projFile, testFile)
|
||||
ignoreLines = [
|
||||
2, # Timestamp
|
||||
9, # Release Notes
|
||||
12, 13, 14, 15, 16, 17, 18, # Window sizes
|
||||
7, 28, # Fonts (depends on system default)
|
||||
]
|
||||
assert cmpFiles(testFile, compFile, ignoreLines)
|
||||
|
||||
# Clean up
|
||||
nw.CONFIG = origConf
|
||||
nwGUI.closeMain()
|
||||
|
||||
# qtbot.stopForInteraction()
|
||||
|
||||
# END Test testGuiPreferences_Main
|
||||
@@ -0,0 +1,99 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""novelWriter Dialog Class Tester
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import os
|
||||
|
||||
from tools import getGuiItem
|
||||
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import (
|
||||
QDialogButtonBox, QTreeWidgetItem, QDialog, QAction, QFileDialog,
|
||||
QMessageBox
|
||||
)
|
||||
|
||||
from nw.gui import GuiProjectLoad
|
||||
|
||||
keyDelay = 2
|
||||
typeDelay = 1
|
||||
stepDelay = 20
|
||||
|
||||
@pytest.mark.gui
|
||||
def testGuiLoadProject_Main(qtbot, monkeypatch, nwGUI, nwMinimal):
|
||||
"""Test the load project wizard.
|
||||
"""
|
||||
# Block message box
|
||||
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
|
||||
|
||||
assert nwGUI.openProject(nwMinimal)
|
||||
assert nwGUI.closeProject()
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
monkeypatch.setattr(GuiProjectLoad, "exec_", lambda *args: None)
|
||||
monkeypatch.setattr(GuiProjectLoad, "result", lambda *args: QDialog.Accepted)
|
||||
nwGUI.mainMenu.aOpenProject.activate(QAction.Trigger)
|
||||
qtbot.waitUntil(lambda: getGuiItem("GuiProjectLoad") is not None, timeout=1000)
|
||||
|
||||
nwLoad = getGuiItem("GuiProjectLoad")
|
||||
assert isinstance(nwLoad, GuiProjectLoad)
|
||||
nwLoad.show()
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
recentCount = nwLoad.listBox.topLevelItemCount()
|
||||
assert recentCount > 0
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
selItem = nwLoad.listBox.topLevelItem(0)
|
||||
selPath = selItem.data(nwLoad.C_NAME, Qt.UserRole)
|
||||
assert isinstance(selItem, QTreeWidgetItem)
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
nwLoad.selPath.setText("")
|
||||
nwLoad.listBox.setCurrentItem(selItem)
|
||||
nwLoad._doSelectRecent()
|
||||
assert nwLoad.selPath.text() == selPath
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwLoad.buttonBox.button(QDialogButtonBox.Open), Qt.LeftButton)
|
||||
assert nwLoad.openPath == selPath
|
||||
assert nwLoad.openState == nwLoad.OPEN_STATE
|
||||
|
||||
# Just create a new project load from scratch for the rest of the test
|
||||
del nwLoad
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
nwGUI.mainMenu.aOpenProject.activate(QAction.Trigger)
|
||||
qtbot.waitUntil(lambda: getGuiItem("GuiProjectLoad") is not None, timeout=1000)
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
nwLoad = getGuiItem("GuiProjectLoad")
|
||||
assert isinstance(nwLoad, GuiProjectLoad)
|
||||
nwLoad.show()
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwLoad.buttonBox.button(QDialogButtonBox.Cancel), Qt.LeftButton)
|
||||
assert nwLoad.openPath is None
|
||||
assert nwLoad.openState == nwLoad.NONE_STATE
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
nwLoad.show()
|
||||
qtbot.mouseClick(nwLoad.newButton, Qt.LeftButton)
|
||||
assert nwLoad.openPath is None
|
||||
assert nwLoad.openState == nwLoad.NEW_STATE
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
nwLoad.show()
|
||||
nwLoad._keyPressDelete()
|
||||
assert nwLoad.listBox.topLevelItemCount() == recentCount - 1
|
||||
|
||||
getFile = os.path.join(nwMinimal, "nwProject.nwx")
|
||||
monkeypatch.setattr(QFileDialog, "getOpenFileName", lambda *args, **kwargs: (getFile, None))
|
||||
qtbot.mouseClick(nwLoad.browseButton, Qt.LeftButton)
|
||||
assert nwLoad.openPath == nwMinimal
|
||||
assert nwLoad.openState == nwLoad.OPEN_STATE
|
||||
|
||||
nwLoad.close()
|
||||
# qtbot.stopForInteraction()
|
||||
|
||||
# END Test testGuiLoadProject_Main
|
||||
@@ -0,0 +1,212 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""novelWriter Project Wizard Class Tester
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import os
|
||||
import sys
|
||||
|
||||
from tools import getGuiItem
|
||||
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import QFileDialog, QWizard, QMessageBox
|
||||
|
||||
from nw.gui import GuiProjectWizard
|
||||
from nw.constants import nwItemClass
|
||||
from nw.gui.projwizard import (
|
||||
ProjWizardIntroPage, ProjWizardFolderPage, ProjWizardPopulatePage,
|
||||
ProjWizardCustomPage, ProjWizardFinalPage
|
||||
)
|
||||
|
||||
keyDelay = 2
|
||||
typeDelay = 1
|
||||
stepDelay = 20
|
||||
|
||||
@pytest.mark.gui
|
||||
def testGuiProjectWizard_Main(qtbot, monkeypatch, nwGUI, nwMinimal):
|
||||
"""Test the new project wizard.
|
||||
"""
|
||||
# Block message box
|
||||
monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes)
|
||||
|
||||
if sys.platform.startswith("darwin"):
|
||||
# Disable for macOS because the test segfaults on QWizard.show()
|
||||
return
|
||||
|
||||
##
|
||||
# Test New Project Function
|
||||
##
|
||||
|
||||
# New with a project open should cause an error
|
||||
assert nwGUI.openProject(nwMinimal)
|
||||
assert not nwGUI.newProject()
|
||||
|
||||
# Close project, but call with invalid path
|
||||
assert nwGUI.closeProject()
|
||||
monkeypatch.setattr(nwGUI, "showNewProjectDialog", lambda *args: None)
|
||||
assert not nwGUI.newProject()
|
||||
|
||||
# Now, with an empty dictionary
|
||||
monkeypatch.setattr(nwGUI, "showNewProjectDialog", lambda *args: {})
|
||||
assert not nwGUI.newProject()
|
||||
|
||||
# Now, with a non-empty folder
|
||||
monkeypatch.setattr(nwGUI, "showNewProjectDialog", lambda *args: {"projPath": nwMinimal})
|
||||
assert not nwGUI.newProject()
|
||||
|
||||
monkeypatch.undo()
|
||||
|
||||
##
|
||||
# Test the Wizard
|
||||
##
|
||||
|
||||
monkeypatch.setattr(GuiProjectWizard, "exec_", lambda *args: None)
|
||||
nwGUI.mainConf.lastPath = " "
|
||||
|
||||
nwGUI.closeProject()
|
||||
nwGUI.showNewProjectDialog()
|
||||
qtbot.waitUntil(lambda: getGuiItem("GuiProjectWizard") is not None, timeout=1000)
|
||||
|
||||
nwWiz = getGuiItem("GuiProjectWizard")
|
||||
assert isinstance(nwWiz, GuiProjectWizard)
|
||||
nwWiz.show()
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
for wStep in range(4):
|
||||
# This does not actually create the project, it just generates the
|
||||
# dictionary that defines it.
|
||||
|
||||
# Intro Page
|
||||
introPage = nwWiz.currentPage()
|
||||
assert isinstance(introPage, ProjWizardIntroPage)
|
||||
assert not nwWiz.button(QWizard.NextButton).isEnabled()
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
for c in ("Test Minimal %d" % wStep):
|
||||
qtbot.keyClick(introPage.projName, c, delay=typeDelay)
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
for c in "Minimal Novel":
|
||||
qtbot.keyClick(introPage.projTitle, c, delay=typeDelay)
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
for c in "Jane Doe":
|
||||
qtbot.keyClick(introPage.projAuthors, c, delay=typeDelay)
|
||||
|
||||
# Setting projName should activate the button
|
||||
assert nwWiz.button(QWizard.NextButton).isEnabled()
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwWiz.button(QWizard.NextButton), Qt.LeftButton)
|
||||
|
||||
# Folder Page
|
||||
storagePage = nwWiz.currentPage()
|
||||
assert isinstance(storagePage, ProjWizardFolderPage)
|
||||
assert not nwWiz.button(QWizard.NextButton).isEnabled()
|
||||
|
||||
if wStep == 0:
|
||||
# Check invalid path first, the first time we reach here
|
||||
monkeypatch.setattr(QFileDialog, "getExistingDirectory", lambda *a, **kw: "")
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(storagePage.browseButton, Qt.LeftButton, delay=100)
|
||||
assert storagePage.projPath.text() == ""
|
||||
|
||||
# Then, we always return nwMinimal as path
|
||||
monkeypatch.setattr(QFileDialog, "getExistingDirectory", lambda *a, **kw: nwMinimal)
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(storagePage.browseButton, Qt.LeftButton, delay=100)
|
||||
projPath = os.path.join(nwMinimal, "Test Minimal %d" % wStep)
|
||||
assert storagePage.projPath.text() == projPath
|
||||
|
||||
# Setting projPath should activate the button
|
||||
assert nwWiz.button(QWizard.NextButton).isEnabled()
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwWiz.button(QWizard.NextButton), Qt.LeftButton)
|
||||
|
||||
# Populate Page
|
||||
popPage = nwWiz.currentPage()
|
||||
assert isinstance(popPage, ProjWizardPopulatePage)
|
||||
assert nwWiz.button(QWizard.NextButton).isEnabled()
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
if wStep == 0:
|
||||
popPage.popMinimal.setChecked(True)
|
||||
elif wStep == 1:
|
||||
popPage.popCustom.setChecked(True)
|
||||
elif wStep == 2:
|
||||
popPage.popCustom.setChecked(True)
|
||||
elif wStep == 3:
|
||||
popPage.popSample.setChecked(True)
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwWiz.button(QWizard.NextButton), Qt.LeftButton)
|
||||
|
||||
# Custom Page
|
||||
if wStep == 1 or wStep == 2:
|
||||
customPage = nwWiz.currentPage()
|
||||
assert isinstance(customPage, ProjWizardCustomPage)
|
||||
assert nwWiz.button(QWizard.NextButton).isEnabled()
|
||||
|
||||
customPage.addPlot.setChecked(True)
|
||||
customPage.addChar.setChecked(True)
|
||||
customPage.addWorld.setChecked(True)
|
||||
customPage.addTime.setChecked(True)
|
||||
customPage.addObject.setChecked(True)
|
||||
customPage.addEntity.setChecked(True)
|
||||
|
||||
if wStep == 2:
|
||||
customPage.numChapters.setValue(0)
|
||||
customPage.numScenes.setValue(10)
|
||||
customPage.chFolders.setChecked(False)
|
||||
|
||||
qtbot.wait(stepDelay)
|
||||
qtbot.mouseClick(nwWiz.button(QWizard.NextButton), Qt.LeftButton)
|
||||
|
||||
# Final Page
|
||||
finalPage = nwWiz.currentPage()
|
||||
assert isinstance(finalPage, ProjWizardFinalPage)
|
||||
assert nwWiz.button(QWizard.FinishButton).isEnabled() # But we don't click it
|
||||
|
||||
# Check Data
|
||||
projData = nwGUI._assembleProjectWizardData(nwWiz)
|
||||
assert projData["projName"] == "Test Minimal %d" % wStep
|
||||
assert projData["projTitle"] == "Minimal Novel"
|
||||
assert projData["projAuthors"] == "Jane Doe"
|
||||
assert projData["projPath"] == projPath
|
||||
assert projData["popMinimal"] == (wStep == 0)
|
||||
assert projData["popCustom"] == (wStep == 1 or wStep == 2)
|
||||
assert projData["popSample"] == (wStep == 3)
|
||||
if wStep == 1 or wStep == 2:
|
||||
assert projData["addRoots"] == [
|
||||
nwItemClass.PLOT,
|
||||
nwItemClass.CHARACTER,
|
||||
nwItemClass.WORLD,
|
||||
nwItemClass.TIMELINE,
|
||||
nwItemClass.OBJECT,
|
||||
nwItemClass.ENTITY,
|
||||
]
|
||||
if wStep == 1:
|
||||
assert projData["numChapters"] == 5
|
||||
assert projData["numScenes"] == 5
|
||||
assert projData["chFolders"]
|
||||
else:
|
||||
assert projData["numChapters"] == 0
|
||||
assert projData["numScenes"] == 10
|
||||
assert not projData["chFolders"]
|
||||
else:
|
||||
assert projData["addRoots"] == []
|
||||
assert projData["numChapters"] == 0
|
||||
assert projData["numScenes"] == 0
|
||||
assert not projData["chFolders"]
|
||||
|
||||
# Restart the wizard for next iteration
|
||||
nwWiz.restart()
|
||||
|
||||
nwWiz.reject()
|
||||
nwWiz.close()
|
||||
|
||||
# qtbot.stopForInteraction()
|
||||
|
||||
# END Test testGuiProjectWizard_Main
|
||||
Reference in New Issue
Block a user