"""
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 PyQt6.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!"]