Fixing tests for Promises (new ones need to be written)
This commit is contained in:
parent
37ac400f23
commit
ccddb068a6
4 changed files with 57 additions and 58 deletions
BIN
runtime-pyside6/.coverage
Normal file
BIN
runtime-pyside6/.coverage
Normal file
Binary file not shown.
|
@ -17,7 +17,7 @@
|
|||
"""
|
||||
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 LogarithmPlotter.util.js import PyJSValue
|
||||
|
@ -51,10 +51,10 @@ class PyPromiseRunner(QRunnable):
|
|||
data = data.qjs_value
|
||||
else:
|
||||
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:
|
||||
try:
|
||||
self.promise.errored.emit(repr(e))
|
||||
self.promise.rejected.emit(repr(e))
|
||||
except RuntimeError as e2:
|
||||
# Happens when the PyPromise has already been garbage collected.
|
||||
# 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.
|
||||
Runs to_run in another thread, and calls fulfilled (populated by then) with its return value.
|
||||
"""
|
||||
finished = Signal((QJSValue,), (QObject,))
|
||||
errored = Signal(Exception)
|
||||
fulfilled = Signal((QJSValue,), (QObject,))
|
||||
rejected = Signal(Exception)
|
||||
|
||||
def __init__(self, to_run: Callable, args):
|
||||
def __init__(self, to_run: Callable, args=[]):
|
||||
QObject.__init__(self)
|
||||
self._fulfills = []
|
||||
self._rejects = []
|
||||
self.finished.connect(self._fulfill)
|
||||
self.errored.connect(self._reject)
|
||||
self._state = "pending"
|
||||
self.fulfilled.connect(self._fulfill)
|
||||
self.rejected.connect(self._reject)
|
||||
self._runner = PyPromiseRunner(to_run, self, args)
|
||||
QThreadPool.globalInstance().start(self._runner)
|
||||
|
||||
@Property(str)
|
||||
def state(self):
|
||||
return self._state
|
||||
|
||||
@Slot(QJSValue, result=QObject)
|
||||
@Slot(QJSValue, QJSValue, result=QObject)
|
||||
|
@ -98,6 +102,7 @@ class PyPromise(QObject):
|
|||
@Slot(QJSValue)
|
||||
@Slot(QObject)
|
||||
def _fulfill(self, data):
|
||||
self._state = "fulfilled"
|
||||
no_return = [None, QJSValue.SpecialValue.UndefinedValue]
|
||||
for on_fulfill in self._fulfills:
|
||||
try:
|
||||
|
@ -110,6 +115,7 @@ class PyPromise(QObject):
|
|||
@Slot(QJSValue)
|
||||
@Slot(str)
|
||||
def _reject(self, error):
|
||||
self._state = "rejected"
|
||||
no_return = [None, QJSValue.SpecialValue.UndefinedValue]
|
||||
for on_reject in self._rejects:
|
||||
result = on_reject(error)
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
"""
|
||||
|
||||
import pytest
|
||||
from os import getcwd, remove
|
||||
from os import getcwd, remove, path
|
||||
from os.path import join
|
||||
from tempfile import TemporaryDirectory
|
||||
from json import loads
|
||||
|
@ -25,11 +25,12 @@ from shutil import copy2
|
|||
|
||||
from PySide6.QtCore import QObject, Signal, QThreadPool
|
||||
from PySide6.QtGui import QImage
|
||||
from PySide6.QtQml import QJSValue
|
||||
from PySide6.QtWidgets import QApplication
|
||||
|
||||
from LogarithmPlotter import __VERSION__ as version
|
||||
from LogarithmPlotter.util import config, helper
|
||||
from LogarithmPlotter.util.helper import ChangelogFetcher, Helper, InvalidFileException
|
||||
from LogarithmPlotter.util.helper import Helper, InvalidFileException
|
||||
|
||||
pwd = getcwd()
|
||||
helper.SHOW_GUI_MESSAGES = False
|
||||
|
@ -43,41 +44,45 @@ def temporary():
|
|||
directory.cleanup()
|
||||
|
||||
|
||||
class MockHelperSignals(QObject):
|
||||
changelogFetched = Signal(str)
|
||||
def create_changelog_callback_asserter(promise, expect_404=False):
|
||||
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):
|
||||
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
|
||||
CHANGELOG_BASE_PATH = path.realpath(path.join(path.dirname(path.realpath(__file__)), "..", "CHANGELOG.md"))
|
||||
|
||||
|
||||
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):
|
||||
# Test file reading and information loading.
|
||||
tmpfile, directory = temporary
|
||||
|
@ -168,15 +173,3 @@ class TestHelper:
|
|||
obj.setSetting("last_install_greet", obj.getSetting("last_install_greet"))
|
||||
obj.setSetting("check_for_updates", obj.getSetting("check_for_updates"))
|
||||
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)
|
|
@ -54,8 +54,8 @@ class TestLatex:
|
|||
# Reset
|
||||
[latex.DVIPNG_PATH, latex.LATEX_PATH] = bkp
|
||||
|
||||
def test_render(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))
|
||||
def test_render_sync(self, latex_obj: latex.Latex) -> None:
|
||||
result = latex_obj.renderSync(r"\frac{d\sqrt{\mathrm{f}(x \times 2.3)}}{dx}", 14, QColor(0, 0, 0, 255))
|
||||
# Ensure result format
|
||||
assert type(result) == str
|
||||
[path, width, height] = result.split(",")
|
||||
|
@ -64,17 +64,17 @@ class TestLatex:
|
|||
assert match(r"\d+", height)
|
||||
# Ensure it returns errors on invalid latex.
|
||||
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
|
||||
bkp = latex.LATEX_PATH
|
||||
latex.LATEX_PATH = which("false")
|
||||
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
|
||||
|
||||
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)]
|
||||
latex_obj.render(*args)
|
||||
latex_obj.renderSync(*args)
|
||||
prerendered = latex_obj.findPrerendered(*args)
|
||||
assert type(prerendered) == str
|
||||
[path, width, height] = prerendered.split(",")
|
||||
|
|
Loading…
Reference in a new issue