Fixing tests for Promises (new ones need to be written)

This commit is contained in:
Ad5001 2024-10-15 18:06:24 +02:00
parent 37ac400f23
commit ccddb068a6
Signed by: Ad5001
GPG key ID: EF45F9C6AFE20160
4 changed files with 57 additions and 58 deletions

BIN
runtime-pyside6/.coverage Normal file

Binary file not shown.

View file

@ -17,7 +17,7 @@
""" """
from typing import Callable from typing import Callable
from PySide6.QtCore import QRunnable, Signal, QObject, Slot, QThreadPool from PySide6.QtCore import QRunnable, Signal, Property, QObject, Slot, QThreadPool
from PySide6.QtQml import QJSValue from PySide6.QtQml import QJSValue
from LogarithmPlotter.util.js import PyJSValue from LogarithmPlotter.util.js import PyJSValue
@ -51,10 +51,10 @@ class PyPromiseRunner(QRunnable):
data = data.qjs_value data = data.qjs_value
else: else:
raise InvalidReturnValue("Must return either a primitive, a valid QObject, JS Value, or None.") raise InvalidReturnValue("Must return either a primitive, a valid QObject, JS Value, or None.")
self.promise.finished.emit(data) self.promise.fulfilled.emit(data)
except Exception as e: except Exception as e:
try: try:
self.promise.errored.emit(repr(e)) self.promise.rejected.emit(repr(e))
except RuntimeError as e2: except RuntimeError as e2:
# Happens when the PyPromise has already been garbage collected. # Happens when the PyPromise has already been garbage collected.
# In other words, nothing to report to nowhere. # In other words, nothing to report to nowhere.
@ -66,18 +66,22 @@ class PyPromise(QObject):
Asynchronous Promise-like object meant to interface between Python and Javascript easily. Asynchronous Promise-like object meant to interface between Python and Javascript easily.
Runs to_run in another thread, and calls fulfilled (populated by then) with its return value. Runs to_run in another thread, and calls fulfilled (populated by then) with its return value.
""" """
finished = Signal((QJSValue,), (QObject,)) fulfilled = Signal((QJSValue,), (QObject,))
errored = Signal(Exception) rejected = Signal(Exception)
def __init__(self, to_run: Callable, args): def __init__(self, to_run: Callable, args=[]):
QObject.__init__(self) QObject.__init__(self)
self._fulfills = [] self._fulfills = []
self._rejects = [] self._rejects = []
self.finished.connect(self._fulfill) self._state = "pending"
self.errored.connect(self._reject) self.fulfilled.connect(self._fulfill)
self.rejected.connect(self._reject)
self._runner = PyPromiseRunner(to_run, self, args) self._runner = PyPromiseRunner(to_run, self, args)
QThreadPool.globalInstance().start(self._runner) QThreadPool.globalInstance().start(self._runner)
@Property(str)
def state(self):
return self._state
@Slot(QJSValue, result=QObject) @Slot(QJSValue, result=QObject)
@Slot(QJSValue, QJSValue, result=QObject) @Slot(QJSValue, QJSValue, result=QObject)
@ -98,6 +102,7 @@ class PyPromise(QObject):
@Slot(QJSValue) @Slot(QJSValue)
@Slot(QObject) @Slot(QObject)
def _fulfill(self, data): def _fulfill(self, data):
self._state = "fulfilled"
no_return = [None, QJSValue.SpecialValue.UndefinedValue] no_return = [None, QJSValue.SpecialValue.UndefinedValue]
for on_fulfill in self._fulfills: for on_fulfill in self._fulfills:
try: try:
@ -110,6 +115,7 @@ class PyPromise(QObject):
@Slot(QJSValue) @Slot(QJSValue)
@Slot(str) @Slot(str)
def _reject(self, error): def _reject(self, error):
self._state = "rejected"
no_return = [None, QJSValue.SpecialValue.UndefinedValue] no_return = [None, QJSValue.SpecialValue.UndefinedValue]
for on_reject in self._rejects: for on_reject in self._rejects:
result = on_reject(error) result = on_reject(error)

View file

@ -17,7 +17,7 @@
""" """
import pytest import pytest
from os import getcwd, remove from os import getcwd, remove, path
from os.path import join from os.path import join
from tempfile import TemporaryDirectory from tempfile import TemporaryDirectory
from json import loads from json import loads
@ -25,11 +25,12 @@ from shutil import copy2
from PySide6.QtCore import QObject, Signal, QThreadPool from PySide6.QtCore import QObject, Signal, QThreadPool
from PySide6.QtGui import QImage from PySide6.QtGui import QImage
from PySide6.QtQml import QJSValue
from PySide6.QtWidgets import QApplication from PySide6.QtWidgets import QApplication
from LogarithmPlotter import __VERSION__ as version from LogarithmPlotter import __VERSION__ as version
from LogarithmPlotter.util import config, helper from LogarithmPlotter.util import config, helper
from LogarithmPlotter.util.helper import ChangelogFetcher, Helper, InvalidFileException from LogarithmPlotter.util.helper import Helper, InvalidFileException
pwd = getcwd() pwd = getcwd()
helper.SHOW_GUI_MESSAGES = False helper.SHOW_GUI_MESSAGES = False
@ -43,41 +44,45 @@ def temporary():
directory.cleanup() directory.cleanup()
class MockHelperSignals(QObject): def create_changelog_callback_asserter(promise, expect_404=False):
changelogFetched = Signal(str) def cb(changelog, expect_404=expect_404):
# print("Got changelog", changelog)
assert isinstance(changelog, QJSValue)
assert changelog.isString()
changlogValue = changelog.toVariant()
assert ('404' in changlogValue) == expect_404
def error(e):
raise eval(e)
promise.then(cb, error)
def __init__(self, expect_404): CHANGELOG_BASE_PATH = path.realpath(path.join(path.dirname(path.realpath(__file__)), "..", "CHANGELOG.md"))
QObject.__init__(self)
self.expect_404 = expect_404
self.changelogFetched.connect(self.changelog_fetched)
self.changelog = None
def changelog_fetched(self, changelog):
self.changelog = changelog
class TestChangelog:
def test_exists(self, qtbot):
helper.CHANGELOG_VERSION = '0.5.0'
mock_helper = MockHelperSignals(False)
fetcher = ChangelogFetcher(mock_helper)
fetcher.run() # Does not raise an exception
qtbot.waitSignal(mock_helper.changelogFetched, timeout=10000)
assert type(mock_helper.changelog) == str
assert '404' not in mock_helper.changelog
def tests_no_exist(self, qtbot):
mock_helper = MockHelperSignals(True)
helper.CHANGELOG_VERSION = '1.0.0'
fetcher = ChangelogFetcher(mock_helper)
fetcher.run()
qtbot.waitSignal(mock_helper.changelogFetched, timeout=10000)
assert type(mock_helper.changelog) == str
assert '404' in mock_helper.changelog
class TestHelper: class TestHelper:
def test_changelog(self, temporary, qtbot):
helper.CHANGELOG_VERSION = '0.5.0'
tmpfile, directory = temporary
obj = Helper(pwd, tmpfile)
promise = obj.fetchChangelog()
create_changelog_callback_asserter(promise, expect_404=False)
qtbot.waitSignal(promise.fulfilled, timeout=10000)
# No exist
helper.CHANGELOG_VERSION = '2.0.0'
tmpfile, directory = temporary
obj = Helper(pwd, tmpfile)
promise = obj.fetchChangelog()
create_changelog_callback_asserter(promise, expect_404=True)
qtbot.waitSignal(promise.fulfilled, timeout=10000)
# Local
tmpfile, directory = temporary
obj = Helper(pwd, tmpfile)
assert path.exists(CHANGELOG_BASE_PATH)
copy2(CHANGELOG_BASE_PATH, helper.CHANGELOG_CACHE_PATH)
assert path.exists(helper.CHANGELOG_CACHE_PATH)
promise = obj.fetchChangelog()
create_changelog_callback_asserter(promise, expect_404=False)
qtbot.waitSignal(promise.fulfilled, timeout=10000) # Local
def test_read(self, temporary): def test_read(self, temporary):
# Test file reading and information loading. # Test file reading and information loading.
tmpfile, directory = temporary tmpfile, directory = temporary
@ -168,15 +173,3 @@ class TestHelper:
obj.setSetting("last_install_greet", obj.getSetting("last_install_greet")) obj.setSetting("last_install_greet", obj.getSetting("last_install_greet"))
obj.setSetting("check_for_updates", obj.getSetting("check_for_updates")) obj.setSetting("check_for_updates", obj.getSetting("check_for_updates"))
obj.setSetting("default_graph.xzoom", obj.getSetting("default_graph.xzoom")) obj.setSetting("default_graph.xzoom", obj.getSetting("default_graph.xzoom"))
def test_fetch_changelog(self, temporary, qtbot):
tmpfile, directory = temporary
obj = Helper(pwd, tmpfile)
copy2("../../CHANGELOG.md", "../../LogarithmPlotter/util/CHANGELOG.md")
obj.fetchChangelog()
assert QThreadPool.globalInstance().activeThreadCount() == 0
qtbot.waitSignal(obj.changelogFetched, timeout=10000)
remove("../../LogarithmPlotter/util/CHANGELOG.md")
obj.fetchChangelog()
assert QThreadPool.globalInstance().activeThreadCount() > 0
qtbot.waitSignal(obj.changelogFetched, timeout=10000)

View file

@ -54,8 +54,8 @@ class TestLatex:
# Reset # Reset
[latex.DVIPNG_PATH, latex.LATEX_PATH] = bkp [latex.DVIPNG_PATH, latex.LATEX_PATH] = bkp
def test_render(self, latex_obj: latex.Latex) -> None: def test_render_sync(self, latex_obj: latex.Latex) -> None:
result = latex_obj.render(r"\frac{d\sqrt{\mathrm{f}(x \times 2.3)}}{dx}", 14, QColor(0, 0, 0, 255)) result = latex_obj.renderSync(r"\frac{d\sqrt{\mathrm{f}(x \times 2.3)}}{dx}", 14, QColor(0, 0, 0, 255))
# Ensure result format # Ensure result format
assert type(result) == str assert type(result) == str
[path, width, height] = result.split(",") [path, width, height] = result.split(",")
@ -64,17 +64,17 @@ class TestLatex:
assert match(r"\d+", height) assert match(r"\d+", height)
# Ensure it returns errors on invalid latex. # Ensure it returns errors on invalid latex.
with pytest.raises(latex.RenderError): with pytest.raises(latex.RenderError):
latex_obj.render(r"\nonexistant", 14, QColor(0, 0, 0, 255)) latex_obj.renderSync(r"\nonexistant", 14, QColor(0, 0, 0, 255))
# Replace latex bin with one that returns errors # Replace latex bin with one that returns errors
bkp = latex.LATEX_PATH bkp = latex.LATEX_PATH
latex.LATEX_PATH = which("false") latex.LATEX_PATH = which("false")
with pytest.raises(latex.RenderError): with pytest.raises(latex.RenderError):
latex_obj.render(r"\mathrm{f}(x)", 14, QColor(0, 0, 0, 255)) latex_obj.renderSync(r"\mathrm{f}(x)", 14, QColor(0, 0, 0, 255))
latex.LATEX_PATH = bkp latex.LATEX_PATH = bkp
def test_prerendered(self, latex_obj: latex.Latex) -> None: def test_prerendered(self, latex_obj: latex.Latex) -> None:
args = [r"\frac{d\sqrt{\mathrm{f}(x \times 2.3)}}{dx}", 14, QColor(0, 0, 0, 255)] args = [r"\frac{d\sqrt{\mathrm{f}(x \times 2.3)}}{dx}", 14, QColor(0, 0, 0, 255)]
latex_obj.render(*args) latex_obj.renderSync(*args)
prerendered = latex_obj.findPrerendered(*args) prerendered = latex_obj.findPrerendered(*args)
assert type(prerendered) == str assert type(prerendered) == str
[path, width, height] = prerendered.split(",") [path, width, height] = prerendered.split(",")