Add tests for the theme and icons files

This commit is contained in:
Veronica Berglyd Olsen
2025-06-04 15:05:22 +02:00
parent cd38e6a6ae
commit 92f68dfd58
3 changed files with 228 additions and 0 deletions
+114
View File
@@ -0,0 +1,114 @@
[
"alert_error",
"alert_info",
"alert_question",
"alert_warn",
"cls_archive",
"cls_character",
"cls_custom",
"cls_entity",
"cls_none",
"cls_novel",
"cls_object",
"cls_plot",
"cls_template",
"cls_timeline",
"cls_trash",
"cls_world",
"prj_folder",
"prj_document",
"prj_title",
"prj_chapter",
"prj_scene",
"prj_note",
"fmt_bold",
"fmt_italic",
"fmt_mark",
"fmt_strike",
"fmt_subscript",
"fmt_superscript",
"fmt_underline",
"fmt_toolbar",
"search",
"search_cancel",
"search_case",
"search_loop",
"search_preserve",
"search_project",
"search_regex",
"search_replace",
"search_word",
"bullet-off",
"bullet-on",
"unfold-hide",
"unfold-show",
"sb_build",
"sb_details",
"sb_novel",
"sb_outline",
"sb_project",
"sb_search",
"sb_stats",
"theme_light",
"theme_dark",
"theme_auto",
"add",
"bookmarks",
"browse",
"build_settings",
"cancel",
"checked",
"chevron_down",
"chevron_left",
"chevron_right",
"chevron_up",
"close",
"copy",
"document_add",
"document",
"edit",
"exclude",
"export",
"filter",
"fit_height",
"fit_width",
"folder",
"font",
"import",
"language",
"lines",
"list",
"margin_bottom",
"margin_left",
"margin_right",
"margin_top",
"maximise",
"minimise",
"more_arrow",
"more_vertical",
"noncheckable",
"open",
"panel",
"pin",
"project_copy",
"quote",
"refresh",
"remove",
"revert",
"settings",
"star",
"stats",
"text",
"timer_off",
"timer",
"unchecked",
"view"
]
+113
View File
@@ -20,6 +20,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
""" """
from __future__ import annotations from __future__ import annotations
import json
from configparser import ConfigParser from configparser import ConfigParser
from pathlib import Path from pathlib import Path
from unittest.mock import MagicMock, Mock from unittest.mock import MagicMock, Mock
@@ -563,3 +565,114 @@ def testGuiTheme_LoadDecorations(monkeypatch):
assert iconCache.getHeaderDecorationNarrow(4) == iconCache._headerDecNarrow[4] assert iconCache.getHeaderDecorationNarrow(4) == iconCache._headerDecNarrow[4]
assert iconCache.getHeaderDecorationNarrow(5) == iconCache._headerDecNarrow[5] assert iconCache.getHeaderDecorationNarrow(5) == iconCache._headerDecNarrow[5]
assert iconCache.getHeaderDecorationNarrow(6) == iconCache._headerDecNarrow[5] assert iconCache.getHeaderDecorationNarrow(6) == iconCache._headerDecNarrow[5]
THEMES = []
_listContent(THEMES, CONFIG.assetPath("themes"), ".conf")
@pytest.mark.gui
@pytest.mark.parametrize("theme", [a.stem for a in THEMES])
def testGuiTheme_CheckTheme(theme):
"""Test loading all themes."""
themes = GuiTheme()
themes.iconCache = MagicMock()
themes._scanThemes(THEMES)
assert theme in themes.colourThemes
current = themes.colourThemes[theme]
if current.dark:
CONFIG.darkTheme = theme
CONFIG.themeMode = nwTheme.DARK
else:
CONFIG.lightTheme = theme
CONFIG.themeMode = nwTheme.LIGHT
# Check loading
themes.loadTheme()
assert themes._meta.name == current.name
assert themes.isDarkTheme == current.dark
# Check completeness
parser = ConfigParser()
parser.read(current.path, encoding="utf-8")
sections = ["Main", "Base", "Project", "Palette", "GUI", "Syntax"]
assert sorted(parser.sections()) == sorted(sections)
structure = {
"Main": [
"name", "mode", # The rest are not required
],
"Base": [
"default", "faded", "red", "orange", "yellow", "green", "cyan",
"blue", "purple",
],
"Project": [
"root", "folder", "file", "title", "chapter", "scene", "note",
],
"Palette": [
"window", "windowtext", "base", "alternatebase", "text",
"tooltipbase", "tooltiptext", "button", "buttontext", "brighttext",
"highlight", "highlightedtext", "link", "linkvisited",
],
"GUI": [
"helptext", "fadedtext", "errortext",
],
"Syntax": [
"background", "text", "link", "headertext", "headertag",
"emphasis", "dialog", "altdialog", "hidden", "note", "shortcode",
"keyword", "tag", "value", "optional", "spellcheckline",
"errorline", "replacetag", "modifier", "texthighlight",
],
}
optional = ["description", "author", "credit", "url", "license", "licenseurl"]
missing = []
for section, options in structure.items():
missing.extend(opt for opt in options if opt not in parser[section])
assert missing == [], "Missing options in theme file"
# Check deprecated
deprecated = []
for section in sections:
deprecated.extend(
opt for opt in parser[section]
if opt not in structure[section] and opt not in optional
)
assert deprecated == [], "Deprecated options in theme file"
ICONS = []
_listContent(ICONS, CONFIG.assetPath("icons"), ".icons")
@pytest.mark.gui
@pytest.mark.parametrize("icons", [a.stem for a in ICONS])
def testGuiTheme_CheckIcons(icons, tstPaths):
"""Test loading all icons."""
keysFile: Path = tstPaths.filesDir / "all_icons.json"
iconKeys = json.loads(keysFile.read_text(encoding="utf-8"))
assert isinstance(iconKeys, list)
CONFIG.lightTheme = DEF_GUI_LIGHT
CONFIG.themeMode = nwTheme.LIGHT
themes = GuiTheme()
themes.initThemes()
iconCache = themes.iconCache
assert icons in iconCache.iconThemes
current = iconCache.iconThemes[icons]
CONFIG.iconTheme = icons
# Check loading
iconCache.loadTheme(icons)
assert iconCache._meta.name == current.name
# Check completeness
missing = [key for key in iconKeys if key not in iconCache._svgData]
assert missing == [], "Missing keys in icons file"
# Check deprecated
deprecated = [key for key in iconCache._svgData if key not in iconKeys]
assert deprecated == [], "Deprecated keys in icons file"
+1
View File
@@ -33,6 +33,7 @@ from utils.common import ROOT_DIR
UTILS = Path(__file__).parent UTILS = Path(__file__).parent
ET.register_namespace("", "http://www.w3.org/2000/svg") ET.register_namespace("", "http://www.w3.org/2000/svg")
ICONS = [ ICONS = [
# Remember to also update tests/files/all_icons.json for test coverage
"alert_error", "alert_error",
"alert_info", "alert_info",
"alert_question", "alert_question",