Complete coverage of themes classes

This commit is contained in:
Veronica Berglyd Olsen
2022-10-28 23:26:25 +02:00
parent 42f5ea205f
commit f76fc95494
2 changed files with 266 additions and 9 deletions
+4 -4
View File
@@ -244,7 +244,7 @@ class GuiTheme:
self.statSaved = self._parseColour(confParser, cnfSec, "statussaved")
# Icons
self.iconCache.updateTheme(self.themeIcons)
self.iconCache.loadTheme(self.themeIcons)
# CSS File
cssData = readTextFile(themeFile[:-5]+".qss")
@@ -498,7 +498,7 @@ class GuiIcons:
# Actions
##
def updateTheme(self, iconTheme):
def loadTheme(self, iconTheme):
"""Update the theme map. This is more of an init, since many of
the GUI icons cannot really be replaced without writing specific
update functions for the classes where they're used.
@@ -585,7 +585,7 @@ class GuiIcons:
return QPixmap()
if not os.path.isfile(imgPath):
logger.error("Asset '%s' not found", self.IMAGE_MAP[decoKey])
logger.error("Asset not found: %s", imgPath)
return QPixmap()
theDeco = QPixmap(imgPath)
@@ -598,7 +598,7 @@ class GuiIcons:
return theDeco
def getIcon(self, iconKey, iconSize=None):
def getIcon(self, iconKey):
"""Return an icon from the icon buffer. If it doesn't exist,
return, load it, and if it still doesn't exist, return an empty
icon.
+262 -5
View File
@@ -26,13 +26,15 @@ import pytest
from configparser import ConfigParser
from mock import causeOSError
from novelwriter.constants import nwLabels
from novelwriter.enum import nwItemClass, nwItemLayout, nwItemType
from tools import writeFile
from PyQt5.QtGui import QPalette
from PyQt5.QtGui import QIcon, QPalette, QPixmap
from PyQt5.QtWidgets import QApplication
from novelwriter.config import Config
from novelwriter.gui.theme import GuiTheme
from novelwriter.gui.theme import GuiIcons, GuiTheme
@pytest.mark.gui
@@ -121,8 +123,8 @@ def testGuiTheme_Main(qtbot, nwGUI, fncDir):
@pytest.mark.gui
def testGuiTheme_Themes(qtbot, monkeypatch, nwGUI, fncDir):
"""Test the theme class init.
def testGuiTheme_Theme(qtbot, monkeypatch, nwGUI, fncDir):
"""Test the theme part of the class.
"""
mainTheme: GuiTheme = nwGUI.mainTheme
mainConf: Config = nwGUI.mainConf
@@ -140,6 +142,11 @@ def testGuiTheme_Themes(qtbot, monkeypatch, nwGUI, fncDir):
)
writeFile(os.path.join(fncDir, "themes", "default.qss"), "/* Stuff */")
# Block the reading of the files
with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError)
assert mainTheme.listThemes() == []
# Load the theme info
themesList = mainTheme.listThemes()
assert themesList[0] == ("default_dark", "Default Dark Theme")
@@ -186,4 +193,254 @@ def testGuiTheme_Themes(qtbot, monkeypatch, nwGUI, fncDir):
# qtbot.stop()
# END Test testGuiTheme_Themes
# END Test testGuiTheme_Theme
@pytest.mark.gui
def testGuiTheme_Syntax(qtbot, monkeypatch, nwGUI, fncDir):
"""Test the syntax part of the class.
"""
mainTheme: GuiTheme = nwGUI.mainTheme
mainConf: Config = nwGUI.mainConf
# List Themes
# ===========
shutil.copy(
os.path.join(mainConf.assetPath, "syntax", "default_dark.conf"),
os.path.join(fncDir, "syntax")
)
shutil.copy(
os.path.join(mainConf.assetPath, "syntax", "default_light.conf"),
os.path.join(fncDir, "syntax")
)
# Block the reading of the files
with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError)
assert mainTheme.listThemes() == []
# Load the syntax info
syntaxList = mainTheme.listSyntax()
assert syntaxList[0] == ("default_dark", "Default Dark")
assert syntaxList[1] == ("default_light", "Default Light")
# A second call should returned the cached list
assert mainTheme.listSyntax() == mainTheme._syntaxList
# Check handling of broken theme settings
mainConf.guiSyntax = "not_a_syntax"
assert mainTheme.loadSyntax() is False
# Check handling of unreadable file
mainConf.guiSyntax = "default_light"
with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError)
assert mainTheme.loadSyntax() is False
# Load Default Light Syntax
# =========================
# Load the default syntax
mainConf.guiSyntax = "default_light"
assert mainTheme.loadSyntax() is True
# Check some values
assert mainTheme.syntaxName == "Default Light"
assert mainTheme.colBack == [255, 255, 255]
assert mainTheme.colText == [0, 0, 0]
assert mainTheme.colLink == [0, 0, 200]
# Load Default Dark Theme
# =======================
# Load the default syntax
mainConf.guiSyntax = "default_dark"
assert mainTheme.loadSyntax() is True
# Check some values
assert mainTheme.syntaxName == "Default Dark"
assert mainTheme.colBack == [54, 54, 54]
assert mainTheme.colText == [199, 207, 208]
assert mainTheme.colLink == [184, 200, 0]
# qtbot.stop()
# END Test testGuiTheme_Syntax
@pytest.mark.gui
def testGuiTheme_Icons(qtbot, caplog, monkeypatch, nwGUI, fncDir):
"""Test the icon cache class.
"""
iconCache: GuiIcons = nwGUI.mainTheme.iconCache
mainConf: Config = nwGUI.mainConf
# Load Theme
# ==========
# Invalid theme name
assert iconCache.loadTheme("not_a_theme") is False
# Check handling of unreadable file
with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError)
assert iconCache.loadTheme("typicons_dark") is False
# Load a broken theme file
iconsDir = os.path.join(fncDir, "icons")
os.mkdir(iconsDir)
os.mkdir(os.path.join(iconsDir, "testicons"))
writeFile(os.path.join(iconsDir, "testicons", "icons.conf"), (
"[Main]\n"
"name = Test Icons\n"
"\n"
"[Map]\n"
"add = add.svg\n"
"stuff = stuff.svg\n"
))
assetPath = mainConf.assetPath
mainConf.assetPath = fncDir
caplog.clear()
assert iconCache.loadTheme("testicons") is True
assert "Unknown icon name 'stuff' in config file" in caplog.text
assert "Icon file 'add.svg' not in theme folder" in caplog.text
mainConf.assetPath = assetPath
# Load working theme file
assert iconCache.loadTheme("typicons_dark") is True
assert "add" in iconCache._themeMap
# Load Decorations
# ================
# Invalid name should return empty pixmap
qPix = iconCache.loadDecoration("stuff")
assert qPix.isNull() is True
# Load an image
qPix = iconCache.loadDecoration("wiz-back")
assert qPix.isNull() is False
# Fail finding the file
with monkeypatch.context() as mp:
mp.setattr("os.path.isfile", lambda *a: False)
qPix = iconCache.loadDecoration("wiz-back")
assert qPix.isNull() is True
# Test image sizes
qPix = iconCache.loadDecoration("wiz-back", pxW=100, pxH=None)
assert qPix.isNull() is False
assert qPix.width() == 100
assert qPix.height() > 100
qPix = iconCache.loadDecoration("wiz-back", pxW=None, pxH=100)
assert qPix.isNull() is False
assert qPix.width() < 100
assert qPix.height() == 100
qPix = iconCache.loadDecoration("wiz-back", pxW=100, pxH=100)
assert qPix.isNull() is False
assert qPix.width() == 100
assert qPix.height() == 100
# Load Icons
# ==========
# Load an unknown icon
qIcon = iconCache.getIcon("stuff")
assert isinstance(qIcon, QIcon)
assert qIcon.isNull() is True
# Load an icon, it is likelyu already cached
qIcon = iconCache.getIcon("add")
assert isinstance(qIcon, QIcon)
assert qIcon.isNull() is False
# Load it as a pixmap with a size
qPix = iconCache.getPixmap("add", (50, 50))
assert isinstance(qPix, QPixmap)
assert qPix.isNull() is False
assert qPix.width() == 50
assert qPix.height() == 50
# Load app icon
qIcon = iconCache.getIcon("novelwriter")
assert isinstance(qIcon, QIcon)
assert qIcon.isNull() is False
# Load mime icon
qIcon = iconCache.getIcon("proj_nwx")
assert isinstance(qIcon, QIcon)
assert qIcon.isNull() is False
# Load Item Icons
# ===============
# Root -> Not Null
assert iconCache.getItemIcon(
nwItemType.ROOT, nwItemClass.NOVEL, nwItemLayout.NO_LAYOUT, hLevel="H0"
) == iconCache.getIcon(nwLabels.CLASS_ICON[nwItemClass.NOVEL])
# Folder -> Not Null
assert iconCache.getItemIcon(
nwItemType.FOLDER, nwItemClass.NOVEL, nwItemLayout.NO_LAYOUT, hLevel="H0"
) == iconCache.getIcon("proj_folder")
# Document H0 -> Not Null
assert iconCache.getItemIcon(
nwItemType.FILE, nwItemClass.NOVEL, nwItemLayout.NO_LAYOUT, hLevel="H0"
) == iconCache.getIcon("proj_document")
# Document H1 -> Not Null
assert iconCache.getItemIcon(
nwItemType.FILE, nwItemClass.NOVEL, nwItemLayout.DOCUMENT, hLevel="H1"
) == iconCache.getIcon("proj_title")
# Document H2 -> Not Null
assert iconCache.getItemIcon(
nwItemType.FILE, nwItemClass.NOVEL, nwItemLayout.DOCUMENT, hLevel="H2"
) == iconCache.getIcon("proj_chapter")
# Document H3 -> Not Null
assert iconCache.getItemIcon(
nwItemType.FILE, nwItemClass.NOVEL, nwItemLayout.DOCUMENT, hLevel="H3"
) == iconCache.getIcon("proj_scene")
# Document H4 -> Not Null
assert iconCache.getItemIcon(
nwItemType.FILE, nwItemClass.NOVEL, nwItemLayout.DOCUMENT, hLevel="H4"
) == iconCache.getIcon("proj_section")
# Document H5 -> Not Null
assert iconCache.getItemIcon(
nwItemType.FILE, nwItemClass.NOVEL, nwItemLayout.NO_LAYOUT, hLevel="H4"
) == iconCache.getIcon("proj_document")
# Note -> Not Null
assert iconCache.getItemIcon(
nwItemType.FILE, nwItemClass.NOVEL, nwItemLayout.NOTE, hLevel="H5"
) == iconCache.getIcon("proj_note")
# No Type -> Null
assert iconCache.getItemIcon(
nwItemType.NO_TYPE, nwItemClass.NOVEL, nwItemLayout.DOCUMENT, hLevel="H0"
).isNull() is True
# Header Decorations
# ==================
assert iconCache.getHeaderDecoration(-1) == iconCache._headerDec[0]
assert iconCache.getHeaderDecoration(0) == iconCache._headerDec[0]
assert iconCache.getHeaderDecoration(1) == iconCache._headerDec[1]
assert iconCache.getHeaderDecoration(2) == iconCache._headerDec[2]
assert iconCache.getHeaderDecoration(3) == iconCache._headerDec[3]
assert iconCache.getHeaderDecoration(4) == iconCache._headerDec[4]
assert iconCache.getHeaderDecoration(5) == iconCache._headerDec[4]
# qtbot.stop()
# END Test testGuiTheme_Icons