Adding main tests (note: full main app may not be completely tested though)

This commit is contained in:
Ad5001 2024-09-19 01:52:23 +02:00
parent 4a5756f24d
commit a9e47dbc17
Signed by: Ad5001
GPG key ID: EF45F9C6AFE20160
7 changed files with 194 additions and 37 deletions

View file

@ -48,16 +48,31 @@ from LogarithmPlotter.util.helper import Helper
from LogarithmPlotter.util.latex import Latex from LogarithmPlotter.util.latex import Latex
from LogarithmPlotter.util.js import PyJSValue from LogarithmPlotter.util.js import PyJSValue
LINUX_THEMES = { # See https://specifications.freedesktop.org/menu-spec/latest/onlyshowin-registry.html
"COSMIC": "Basic",
"GNOME": "Basic",
"GNOME-Classic": "Basic",
"GNOME-Flashback": "Basic",
"KDE": "Fusion",
"LXDE": "Basic",
"LXQt": "Fusion",
"MATE": "Fusion",
"TDE": "Fusion",
"Unity": "Basic",
"XFCE": "Basic",
"Cinnamon": "Fusion",
"Pantheon": "Basic",
"DDE": "Basic",
"EDE": "Fusion",
"Endless": "Basic",
"Old": "Fusion",
}
def get_linux_theme() -> str: def get_linux_theme() -> str:
des = {
"KDE": "Fusion",
"gnome": "Basic",
"lxqt": "Fusion",
"mate": "Fusion",
}
if "XDG_SESSION_DESKTOP" in environ: if "XDG_SESSION_DESKTOP" in environ:
if environ["XDG_SESSION_DESKTOP"] in des: if environ["XDG_SESSION_DESKTOP"] in LINUX_THEMES:
return des[environ["XDG_SESSION_DESKTOP"]] return LINUX_THEMES[environ["XDG_SESSION_DESKTOP"]]
return "Fusion" return "Fusion"
else: else:
# Android # Android
@ -77,18 +92,18 @@ def get_platform_qt_style(os) -> str:
def register_icon_directories() -> None: def register_icon_directories() -> None:
icon_fallbacks = QIcon.fallbackSearchPaths() icon_fallbacks = QIcon.fallbackSearchPaths()
base_icon_path = path.join(getcwd(), "qml", "eu", "ad5001", "LogarithmPlotter", "icons") base_icon_path = path.join(getcwd(), "qml", "eu", "ad5001", "LogarithmPlotter", "icons")
icon_fallbacks.append(path.realpath(path.join(base_icon_path, "common"))) paths = [["common"], ["objects"], ["history"], ["settings"], ["settings", "custom"]]
icon_fallbacks.append(path.realpath(path.join(base_icon_path, "objects"))) for p in paths:
icon_fallbacks.append(path.realpath(path.join(base_icon_path, "history"))) icon_fallbacks.append(path.realpath(path.join(base_icon_path, *p)))
icon_fallbacks.append(path.realpath(path.join(base_icon_path, "settings")))
icon_fallbacks.append(path.realpath(path.join(base_icon_path, "settings", "custom")))
QIcon.setFallbackSearchPaths(icon_fallbacks) QIcon.setFallbackSearchPaths(icon_fallbacks)
def create_qapp() -> QApplication: def create_qapp() -> QApplication:
app = QApplication(argv) app = QApplication(argv)
app.setApplicationName("LogarithmPlotter") app.setApplicationName("LogarithmPlotter")
app.setDesktopFileName("eu.ad5001.LogarithmPlotter.desktop") app.setApplicationDisplayName("LogarithmPlotter")
app.setApplicationVersion(f"v{__VERSION__}")
app.setDesktopFileName("eu.ad5001.LogarithmPlotter")
app.setOrganizationName("Ad5001") app.setOrganizationName("Ad5001")
app.styleHints().setShowShortcutsInContextMenus(True) app.styleHints().setShowShortcutsInContextMenus(True)
app.setWindowIcon(QIcon(path.realpath(path.join(getcwd(), "logarithmplotter.svg")))) app.setWindowIcon(QIcon(path.realpath(path.join(getcwd(), "logarithmplotter.svg"))))
@ -101,8 +116,10 @@ def install_translation(app: QApplication) -> QTranslator:
# Check if lang is forced. # Check if lang is forced.
forcedlang = [p for p in argv if p[:7] == "--lang="] forcedlang = [p for p in argv if p[:7] == "--lang="]
locale = QLocale(forcedlang[0][7:]) if len(forcedlang) > 0 else QLocale() locale = QLocale(forcedlang[0][7:]) if len(forcedlang) > 0 else QLocale()
if translator.load(locale, "lp", "_", path.realpath(path.join(getcwd(), "i18n"))): if not translator.load(locale, "lp", "_", path.realpath(path.join(getcwd(), "i18n"))):
app.installTranslator(translator) # Load default translation
translator.load(QLocale("en"), "lp", "_", path.realpath(path.join(getcwd(), "i18n")))
app.installTranslator(translator)
return translator return translator
@ -145,7 +162,7 @@ def run():
latex = Latex(tempdir) latex = Latex(tempdir)
engine, js_globals = create_engine(helper, latex, dep_time) engine, js_globals = create_engine(helper, latex, dep_time)
if len(engine.rootObjects()) == 0: # No root objects loaded if len(engine.rootObjects()) == 0: # No root objects loaded
print("No root object", path.realpath(path.join(getcwd(), "qml"))) print("No root object", path.realpath(path.join(getcwd(), "qml")))
exit(-1) exit(-1)

View file

@ -48,11 +48,11 @@ class PyJSValue:
def __eq__(self, other): def __eq__(self, other):
if isinstance(other, PyJSValue): if isinstance(other, PyJSValue):
return self.qjs_value.equals(other.qjs_value) return self.qjs_value.strictlyEquals(other.qjs_value)
elif isinstance(other, QJSValue): elif isinstance(other, QJSValue):
return self.qjs_value.equals(other) return self.qjs_value.strictlyEquals(other)
elif type(other) in (int, float, str, bool): elif type(other) in (int, float, str, bool):
return self.qjs_value.equals(QJSValue(other)) return self.qjs_value.strictlyEquals(QJSValue(other))
else: else:
return False return False

View file

@ -15,6 +15,6 @@
* You should have received a copy of the GNU General Public License * 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/>.
""" """
if __name__ == "__main__": from LogarithmPlotter.logarithmplotter import create_qapp
from .logarithmplotter import run
run() app = create_qapp()

View file

@ -1,3 +1,21 @@
"""
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* 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 pytest import pytest
from os import getcwd from os import getcwd
from os.path import join from os.path import join

View file

@ -1,3 +1,21 @@
"""
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* 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 pytest import pytest
from tempfile import TemporaryDirectory from tempfile import TemporaryDirectory
from shutil import which from shutil import which

View file

@ -1,6 +1,33 @@
import pytest """
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
from LogarithmPlotter.logarithmplotter import get_linux_theme import pytest
from os import environ
from os.path import exists, join
from PySide6.QtGui import QIcon
from tempfile import TemporaryDirectory
from LogarithmPlotter.logarithmplotter import get_linux_theme, LINUX_THEMES, get_platform_qt_style, \
register_icon_directories, install_translation, create_engine
from LogarithmPlotter.util import config
from LogarithmPlotter.util.helper import Helper
from LogarithmPlotter.util.latex import Latex
from globals import app
THEMES = [ THEMES = [
"Basic", "Basic",
@ -11,6 +38,61 @@ THEMES = [
"macOS" "macOS"
] ]
OS_PLATFORMS = [
"linux",
"freebsd",
"win32",
"cygwin",
"darwin"
]
@pytest.fixture()
def temporary():
directory = TemporaryDirectory()
config.CONFIG_PATH = join(directory.name, "config.json")
tmpfile = join(directory.name, "graph.png")
yield tmpfile, directory
directory.cleanup()
class TestMain: class TestMain:
def test_themes(self): def test_linux_themes(self):
get_linux_theme() # Check without a desktop
if "XDG_SESSION_DESKTOP" in environ:
del environ["XDG_SESSION_DESKTOP"]
assert get_linux_theme() in THEMES
# Test various environments.
environ["XDG_SESSION_DESKTOP"] = "GNOME"
assert get_linux_theme() in THEMES
# Test various environments.
environ["XDG_SESSION_DESKTOP"] = "NON-EXISTENT"
assert get_linux_theme() in THEMES
# Check all linux themes are in list
for desktop, theme in LINUX_THEMES.items():
assert theme in THEMES
def test_os_themes(self):
for platform in OS_PLATFORMS:
assert get_platform_qt_style(platform) in THEMES
def test_icon_directories(self):
base_paths = QIcon.fallbackSearchPaths()
register_icon_directories()
# Check if registered
assert len(base_paths) < len(QIcon.fallbackSearchPaths())
# Check if all exists
for p in QIcon.fallbackSearchPaths():
assert exists(p)
def test_app(self, temporary):
assert not app.windowIcon().isNull()
# Translations
translator = install_translation(app)
assert not translator.isEmpty()
# Engine
tmpfile, tempdir = temporary
helper = Helper(".", tmpfile)
latex = Latex(tempdir)
engine, js_globals = create_engine(helper, latex, 0)
assert len(engine.rootObjects()) > 0 # QML File loaded.
assert type(engine.rootContext().contextProperty("TestBuild")) is bool
assert engine.rootContext().contextProperty("StartTime") == 0

View file

@ -1,30 +1,52 @@
"""
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
* Copyright (C) 2021-2024 Ad5001
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* 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 pytest import pytest
from PySide6.QtQml import QJSEngine, QJSValue from PySide6.QtQml import QJSEngine, QJSValue
from PySide6.QtWidgets import QApplication
from LogarithmPlotter.util.js import PyJSValue, InvalidAttributeValueException from LogarithmPlotter.util.js import PyJSValue, InvalidAttributeValueException
from globals import app
app = QApplication() @pytest.fixture()
engine = QJSEngine() def data():
obj = PyJSValue(engine.globalObject()) engine = QJSEngine()
obj = PyJSValue(engine.globalObject())
yield engine, obj
class TestPyJS: class TestPyJS:
def test_set(self): def test_set(self, data):
engine, obj = data
obj.num1 = 2 obj.num1 = 2
obj.num2 = QJSValue(2) obj.num2 = QJSValue(2)
obj.num3 = PyJSValue(QJSValue(2)) obj.num3 = PyJSValue(QJSValue(2))
with pytest.raises(InvalidAttributeValueException): with pytest.raises(InvalidAttributeValueException):
obj.num3 = object() obj.num3 = object()
def test_eq(self): def test_eq(self, data):
engine, obj = data
obj.num = QJSValue(2) obj.num = QJSValue(2)
assert obj.num == 2 assert obj.num == 2
assert obj.num == QJSValue(2) assert obj.num == QJSValue(2)
assert obj.num == PyJSValue(QJSValue(2)) assert obj.num == PyJSValue(QJSValue(2))
assert obj.num != object() assert obj.num != object()
def test_function(self): def test_function(self, data):
engine, obj = data
function = PyJSValue(engine.evaluate("(function(argument) {return argument*2})")) function = PyJSValue(engine.evaluate("(function(argument) {return argument*2})"))
assert function(3) == 6 assert function(3) == 6
assert function(10) == 20 assert function(10) == 20