""" novelWriter – Version Info Widget Tester ======================================== This file is a part of novelWriter Copyright (C) 2024 Veronica Berglyd Olsen and novelWriter contributors 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 from urllib.error import HTTPError import pytest from PyQt5.QtCore import QUrl from novelwriter import SHARED from novelwriter.constants import nwConst from novelwriter.extensions.versioninfo import VersionInfoWidget, _Retriever, _RetrieverSignal from tests.tools import SimpleDialog class MockRetriever: signals = _RetrieverSignal() class MockDesktopServices: url = None @staticmethod def openUrl(url): MockDesktopServices.url = url return class MockData: def decode(self, *a): return '{"tag_name": "v1.0"}' class MockPayload: def __enter__(self): return self def __exit__(self, *args): return def read(self): data = MockData() return data class MockHTTPError: def __enter__(self): raise HTTPError("http://example.com", 403, "Rate limit", None, None) # type: ignore 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) # type: ignore 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() @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") # type: ignore # 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!"]