anki/qt/tests/test_addons.py
Damien Elmes ffd392de21
Change Anki's version scheme; bump to 23.09 (#2640)
* Accept iterables as inputs to backend methods

* Shift add-on check to backend; use new endpoint

The new endpoint will return info on a suitable branch if found,
instead of returning all branches. This simplifies the frontend code,
and means that you can now drop support for certain versions without
it also remotely disabling the add-on for people who are running one of
the excluded versions, like in

https://forums.ankiweb.net/t/prevent-add-ons-from-being-disabled-remote-stealthily-surreptitiously/33427

* Bump version to 23.09

This changes Anki's version numbering system to year.month.patch, as
previously mentioned on https://forums.ankiweb.net/t/use-a-different-versioning-system-semver-perhaps/20046/5

This is shaping up to be a big release, with the introduction of FSRS and
image occlusion, and it seems like a good time to be finally updating the
version scheme as well. AnkiWeb has been updated to understand the new
format, and add-on authors will now specify version compatibility using
the full version number, as can be seen here:

https://ankiweb.net/shared/info/3918629684

* Shift update check to backend, and tidy up update.py

* Use the shared client for sync connections too
2023-09-07 12:37:15 +10:00

78 lines
2.0 KiB
Python

# Copyright: Ankitects Pty Ltd and contributors
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import os.path
from tempfile import TemporaryDirectory
from zipfile import ZipFile
from mock import MagicMock
from aqt.addons import AddonManager, package_name_valid
def test_readMinimalManifest():
assertReadManifest(
'{"package": "yes", "name": "no"}', {"package": "yes", "name": "no"}
)
def test_readExtraKeys():
assertReadManifest(
'{"package": "a", "name": "b", "mod": 3, "conflicts": ["d", "e"]}',
{"package": "a", "name": "b", "mod": 3, "conflicts": ["d", "e"]},
)
def test_invalidManifest():
assertReadManifest('{"one": 1}', {})
def test_mustHaveName():
assertReadManifest('{"package": "something"}', {})
def test_mustHavePackage():
assertReadManifest('{"name": "something"}', {})
def test_invalidJson():
assertReadManifest("this is not a JSON dictionary", {})
def test_missingManifest():
assertReadManifest(
'{"package": "what", "name": "ever"}', {}, nameInZip="not-manifest.bin"
)
def test_ignoreExtraKeys():
assertReadManifest(
'{"package": "a", "name": "b", "game": "c"}', {"package": "a", "name": "b"}
)
def test_conflictsMustBeStrings():
assertReadManifest(
'{"package": "a", "name": "b", "conflicts": ["c", 4, {"d": "e"}]}', {}
)
def assertReadManifest(contents, expectedManifest, nameInZip="manifest.json"):
with TemporaryDirectory() as td:
zfn = os.path.join(td, "addon.zip")
with ZipFile(zfn, "w") as zfile:
zfile.writestr(nameInZip, contents)
adm = AddonManager(MagicMock())
with ZipFile(zfn, "r") as zfile:
assert adm.readManifestFile(zfile) == expectedManifest
def test_package_name_validation():
assert not package_name_valid("")
assert not package_name_valid("/")
assert not package_name_valid("a/b")
assert not package_name_valid("..")
assert package_name_valid("ab")