Improve test coverage of Outline

This commit is contained in:
Veronica Berglyd Olsen
2022-06-05 22:31:10 +02:00
parent 85f63721e0
commit 4d9b94cfe6
3 changed files with 181 additions and 21 deletions
+1 -1
View File
@@ -461,7 +461,7 @@ class GuiOutlineView(QTreeWidget):
document editor.
"""
tHandle, tLine = self.getSelectedHandle()
self.theParent.openDocument(tHandle, tLine=tLine-1, doScroll=True)
self.theParent.openDocument(tHandle, tLine=tLine - 1, doScroll=True)
return
@pyqtSlot()
+1 -1
View File
@@ -1453,7 +1453,7 @@ class GuiMain(QMainWindow):
return
##
# Slots
# Private Slots
##
@pyqtSlot(str, Enum)
+179 -19
View File
@@ -19,17 +19,144 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
import os
import time
import pytest
from PyQt5.QtWidgets import QTreeWidgetItem, QMessageBox
from tools import buildTestProject, writeFile
keyDelay = 2
typeDelay = 1
stepDelay = 20
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QMessageBox, QAction
from novelwriter.enum import nwItemClass, nwOutline, nwView
@pytest.mark.gui
def testGuiOutline_Main(qtbot, monkeypatch, nwGUI, nwLipsum):
def testGuiOutline_Main(qtbot, monkeypatch, nwGUI, fncDir):
"""Test the outline view.
"""
# Block message box
monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes)
# Create a project
prjDir = os.path.join(fncDir, "project")
buildTestProject(nwGUI, prjDir)
nwGUI.rebuildIndex()
nwGUI._changeView(nwView.OUTLINE)
outlineMain = nwGUI.projView
outlineView = outlineMain.outlineView
outlineData = outlineMain.outlineData
outlineMenu = outlineMain.outlineBar.mColumns
# Toggle scrollbars
nwGUI.mainConf.hideVScroll = True
nwGUI.mainConf.hideHScroll = True
nwGUI.projView.initOutline()
assert outlineView.verticalScrollBarPolicy() == Qt.ScrollBarAlwaysOff
assert outlineView.horizontalScrollBarPolicy() == Qt.ScrollBarAlwaysOff
assert outlineData.verticalScrollBarPolicy() == Qt.ScrollBarAlwaysOff
assert outlineData.horizontalScrollBarPolicy() == Qt.ScrollBarAlwaysOff
nwGUI.mainConf.hideVScroll = False
nwGUI.mainConf.hideHScroll = False
nwGUI.projView.initOutline()
assert outlineView.verticalScrollBarPolicy() == Qt.ScrollBarAsNeeded
assert outlineView.horizontalScrollBarPolicy() == Qt.ScrollBarAsNeeded
assert outlineData.verticalScrollBarPolicy() == Qt.ScrollBarAsNeeded
assert outlineData.horizontalScrollBarPolicy() == Qt.ScrollBarAsNeeded
# Check focus
with monkeypatch.context() as mp:
mp.setattr(QWidget, "hasFocus", lambda *a: True)
assert outlineMain.treeFocus() is True
outlineMain.setTreeFocus() # Can't check. just ensures that it doesn't error
# Option State
# ============
pOptions = nwGUI.theProject.options
colNames = [h.name for h in nwOutline]
colItems = [h for h in nwOutline]
colWidth = {h: outlineView.DEF_WIDTH[h] for h in nwOutline}
colHidden = {h: outlineView.DEF_HIDDEN[h] for h in nwOutline}
assert outlineView.topLevelItemCount() > 0
# Save header state not allowed
outlineView._lastBuild = 0
outlineView._saveHeaderState()
assert pOptions.getValue("GuiOutline", "headerOrder", []) == []
# Allow saving header state
outlineView._lastBuild = time.time()
outlineView._saveHeaderState()
assert pOptions.getValue("GuiOutline", "headerOrder", []) == colNames
assert outlineView._treeOrder == colItems
assert outlineView._colWidth == colWidth
assert outlineView._colHidden == colHidden
# Get default values
optItems = pOptions.getValue("GuiOutline", "headerOrder", [])
optWidth = pOptions.getValue("GuiOutline", "columnWidth", {})
optHidden = pOptions.getValue("GuiOutline", "columnHidden", {})
# Add invalid column name
pOptions.setValue("GuiOutline", "headerOrder", optItems + ["blabla"])
outlineView._loadHeaderState()
assert outlineView._treeOrder == colItems
assert outlineView._colHidden == colHidden
# Add duplicate column name
pOptions.setValue("GuiOutline", "headerOrder", optItems + [optItems[-1]])
outlineView._loadHeaderState()
assert outlineView._treeOrder == colItems
assert outlineView._colHidden == colHidden
# Invalid column width data
pOptions.setValue("GuiOutline", "headerOrder", optItems)
pOptions.setValue("GuiOutline", "columnWidth", {"blabla": None})
outlineView._loadHeaderState()
assert outlineView._treeOrder == colItems
assert outlineView._colHidden == colHidden
# Invalid column width data
pOptions.setValue("GuiOutline", "headerOrder", optItems)
pOptions.setValue("GuiOutline", "columnWidth", optWidth)
pOptions.setValue("GuiOutline", "columnHidden", {"bloabla": None})
outlineView._loadHeaderState()
assert outlineView._treeOrder == colItems
assert outlineView._colHidden == colHidden
# Valid settings
pOptions.setValue("GuiOutline", "headerOrder", optItems)
pOptions.setValue("GuiOutline", "columnWidth", optWidth)
pOptions.setValue("GuiOutline", "columnHidden", optHidden)
outlineView._loadHeaderState()
assert outlineView._treeOrder == colItems
assert outlineView._colHidden == colHidden
# Header Menu
# ===========
# Trigger the menu entry for all hidden columns
for hItem in nwOutline:
if outlineView.DEF_HIDDEN[hItem]:
outlineMenu.actionMap[hItem].activate(QAction.Trigger)
# Now no columns should be hidden
outlineView._saveHeaderState()
assert not any(pOptions.getValue("GuiOutline", "columnHidden", None).values())
# qtbot.stop()
# END Test testGuiOutline_Main
@pytest.mark.gui
def testGuiOutline_Content(qtbot, monkeypatch, nwGUI, nwLipsum):
"""Test the outline view.
"""
# Block message box
@@ -40,26 +167,59 @@ def testGuiOutline_Main(qtbot, monkeypatch, nwGUI, nwLipsum):
nwGUI.mainConf.lastPath = nwLipsum
nwGUI.rebuildIndex()
nwGUI.mainStack.setCurrentIndex(nwGUI.idxOutlineView)
nwGUI._changeView(nwView.OUTLINE)
outlineView = nwGUI.projView.outlineView
outlineData = nwGUI.projView.outlineData
outlineMain = nwGUI.projView
outlineBar = outlineMain.outlineBar
outlineView = outlineMain.outlineView
outlineData = outlineMain.outlineData
assert outlineView.topLevelItemCount() > 0
lipHandle = "b3643d0f92e32"
# Context Menu
# outlineView._headerRightClick(QPoint(1, 1))
# outlineView.headerMenu.actionMap[nwOutline.CCOUNT].activate(QAction.Trigger)
# outlineView.headerMenu.close()
# qtbot.mouseClick(outlineView, Qt.LeftButton)
# Check defaults in dropdown list
assert outlineBar.novelValue.itemData(0) == lipHandle
assert outlineBar.novelValue.itemData(1) is None # Separator
assert outlineBar.novelValue.itemData(2) == "" # All novels
# outlineView._loadHeaderState()
# assert not outlineView._colHidden[nwOutline.CCOUNT]
# Add a second novel folder
newHandle = nwGUI.theProject.newRoot(nwItemClass.NOVEL)
nwGUI.treeView.revealNewTreeItem(newHandle)
# Check new values in dropdown list
assert outlineBar.novelValue.itemData(0) == lipHandle
assert outlineBar.novelValue.itemData(1) == newHandle
assert outlineBar.novelValue.itemData(2) is None # Separator
assert outlineBar.novelValue.itemData(3) == "" # All novels
# Add a bunch of files in a header order that hits all tree combos
docList = [
("Section 1", 4), ("Scene 1", 3), ("Chapter 1", 2), ("Part 1", 1),
("Section 2", 4), ("Scene 2", 3), ("Chapter 2", 2),
("Section 3", 4), ("Scene 3", 3),
("Section 4", 4),
]
for dTitle, hLevel in docList:
aHandle = nwGUI.theProject.newFile(dTitle, newHandle)
hHash = "#"*hLevel
writeFile(os.path.join(nwLipsum, "content", f"{aHandle}.nwd"), f"{hHash} {dTitle}\n\n")
nwGUI.treeView.revealNewTreeItem(aHandle)
nwGUI.rebuildIndex()
# Build the second novel
outlineBar.novelValue.setCurrentIndex(1)
outlineBar._refreshRequested()
# Go back to Lipsum
outlineBar.novelValue.setCurrentIndex(0)
outlineBar._refreshRequested()
# Check Details
# =============
# First Item
outlineView.refreshTree()
selItem = outlineView.topLevelItem(0)
assert isinstance(selItem, QTreeWidgetItem)
outlineView.setCurrentItem(selItem)
assert outlineData.titleLabel.text() == "<b>Title</b>"
@@ -110,6 +270,6 @@ def testGuiOutline_Main(qtbot, monkeypatch, nwGUI, nwLipsum):
outlineView._treeDoubleClick(selItem, 0)
assert nwGUI.docEditor.docHandle() == "88243afbe5ed8"
# qtbot.stopForInteraction()
# qtbot.stop()
# END Test testGuiOutline_Main
# END Test testGuiOutline_Content