From ed7dde2aaa3084e24a9d45dffe4060909944859c Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Wed, 14 Feb 2024 23:19:25 +0100 Subject: [PATCH] Add test coverage --- novelwriter/extensions/versioninfo.py | 1 - tests/test_ext/test_ext_modified.py | 4 +- tests/test_ext/test_ext_versioninfo.py | 155 +++++++++++++++++++++++++ 3 files changed, 157 insertions(+), 3 deletions(-) create mode 100644 tests/test_ext/test_ext_versioninfo.py diff --git a/novelwriter/extensions/versioninfo.py b/novelwriter/extensions/versioninfo.py index 02fb86e4..08cbc74e 100644 --- a/novelwriter/extensions/versioninfo.py +++ b/novelwriter/extensions/versioninfo.py @@ -118,7 +118,6 @@ class _Retriever(QRunnable): def __init__(self) -> None: super().__init__() - self._isRunning = False self.signals = _RetrieverSignal() return diff --git a/tests/test_ext/test_ext_modified.py b/tests/test_ext/test_ext_modified.py index c1d0e3c2..7ea40755 100644 --- a/tests/test_ext/test_ext_modified.py +++ b/tests/test_ext/test_ext_modified.py @@ -1,6 +1,6 @@ """ -novelWriter – Wheel Event Filter Tester -======================================= +novelWriter – Modified Widgets Tester +===================================== This file is a part of novelWriter Copyright 2018–2024, Veronica Berglyd Olsen diff --git a/tests/test_ext/test_ext_versioninfo.py b/tests/test_ext/test_ext_versioninfo.py new file mode 100644 index 00000000..b30fb19c --- /dev/null +++ b/tests/test_ext/test_ext_versioninfo.py @@ -0,0 +1,155 @@ +""" +novelWriter – Version Info Widget Tester +======================================== + +This file is a part of novelWriter +Copyright 2018–2024, Veronica Berglyd Olsen + +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 . +""" +from __future__ import annotations + +import pytest + +from urllib.error import HTTPError + +from tools import SimpleDialog + +from PyQt5.QtCore import QUrl + +from novelwriter import SHARED +from novelwriter.constants import nwConst +from novelwriter.extensions.versioninfo import VersionInfoWidget, _Retriever, _RetrieverSignal + + +class MockRetriever: + signals = _RetrieverSignal() + + +class MockDesktopServices: + + url = None + + @staticmethod + def openUrl(url): + MockDesktopServices.url = url + return + + +class MockData: + pass + + +class MockPayload: + + def __enter__(self): + return self + + def __exit__(self, *args): + return + + def read(self): + data = MockData() + data.decode = lambda *a: '{"tag_name": "v1.0"}' + return data + + +class MockHTTPError: + + def __enter__(self): + raise HTTPError("http://example.com", 403, "Rate limit", None, None) + + def __exit__(self, *args): + return + + +class MockException: + + def __enter__(self): + raise Exception("Oh noes!") + + def __exit__(self, *args): + return + + +@pytest.mark.gui +def testExtVersionInfo_Main(qtbot, monkeypatch): + """Test the VersionInfoWidget class.""" + version = VersionInfoWidget(None) + dialog = SimpleDialog(version) + dialog.show() + + with monkeypatch.context() as mp: + mp.setattr("novelwriter.extensions.versioninfo.QDesktopServices", MockDesktopServices) + version._processLink("#notes") + assert MockDesktopServices.url == QUrl(nwConst.URL_RELEASES) + + with monkeypatch.context() as mp: + mp.setattr("novelwriter.extensions.versioninfo.QDesktopServices", MockDesktopServices) + version._processLink("#website") + assert MockDesktopServices.url == QUrl(nwConst.URL_WEB) + + with monkeypatch.context() as mp: + mp.setattr("novelwriter.extensions.versioninfo._Retriever", MockRetriever) + mp.setattr(SHARED, "runInThreadPool", lambda *a: None) + version._processLink("#update") + assert version._lblRelease.text() == "Latest Version: Checking ..." + + version._updateReleaseInfo("v2.0", "") + assert version._lblRelease.text() == ( + "Latest Version: 2.0 – Download from novelwriter.io" + ) + + version._updateReleaseInfo("", "Error") + assert version._lblRelease.text() == "Latest Version: Error" + + version._updateReleaseInfo("", "") + assert version._lblRelease.text() == "Latest Version: Failed" + + dialog.close() + # qtbot.stop() + +# END Test testExtVersionInfo_Main + + +@pytest.mark.gui +def testExtVersionInfo_Retriever(qtbot, monkeypatch): + """Test the _Retriever class.""" + task = _Retriever() + + # Valid Data + with monkeypatch.context() as mp: + mp.setattr("novelwriter.extensions.versioninfo.urlopen", lambda *a, **k: MockPayload()) + with qtbot.waitSignal(task.signals.dataReady) as signal: + task.run() + assert signal.args == ["v1.0", ""] + + def httpErr(): + raise HTTPError("http://example.com", 403, "Rate limit") + + # HTTP Error + with monkeypatch.context() as mp: + mp.setattr("novelwriter.extensions.versioninfo.urlopen", lambda *a, **k: MockHTTPError()) + with qtbot.waitSignal(task.signals.dataReady) as signal: + task.run() + assert signal.args == ["", "Rate limit (HTTP 403)"] + + # Other Error + with monkeypatch.context() as mp: + mp.setattr("novelwriter.extensions.versioninfo.urlopen", lambda *a, **k: MockException()) + with qtbot.waitSignal(task.signals.dataReady) as signal: + task.run() + assert signal.args == ["", "Oh noes!"] + +# END Test testExtVersionInfo_Retriever