90 lines
4.7 KiB
Python
90 lines
4.7 KiB
Python
"""Version extraction uses the addon asset, not the manifest schema or game version."""
|
|
import importlib.util
|
|
from pathlib import Path
|
|
import unittest
|
|
import json
|
|
import io
|
|
from unittest.mock import patch
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
spec = importlib.util.spec_from_file_location('workshop_changelog', ROOT / 'tools/workshop_changelog.py')
|
|
tool = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(tool)
|
|
PROJECT = 'GameProject { GUID "2528466DE220D91C" }'
|
|
TEXT = '# Changelog\n\n## Update\n\n- Gameplay fix.\n'
|
|
|
|
|
|
class WorkshopTests(unittest.TestCase):
|
|
def test_asset_version(self):
|
|
manifest = {'version': 1, 'asset': {'id': '2528466DE220D91C', 'version': '0.0.109', 'gameVersion': '1.8.0.13'}}
|
|
self.assertEqual(tool.bundled_version(manifest, PROJECT), '0.0.109')
|
|
|
|
def test_reject_wrong_addon_and_invalid_manifest(self):
|
|
for manifest in (None, [], {}, {'asset': None}, {'asset': {'id': None}},
|
|
{'asset': {'id': 'OTHER', 'version': '0.0.109'}},
|
|
{'asset': {'id': '2528466DE220D91C', 'version': '99999.0.0'}},
|
|
{'version': '0.0.109', 'asset': {'id': '2528466DE220D91C'}}):
|
|
with self.subTest(manifest=manifest), self.assertRaises(ValueError):
|
|
tool.bundled_version(manifest, PROJECT)
|
|
|
|
def test_update_preserves_notes_and_is_idempotent(self):
|
|
updated = tool.update_changelog(TEXT, '0.0.109')
|
|
self.assertIn('Latest published Workshop version: **0.0.109**', updated)
|
|
self.assertTrue(updated.endswith('## Update\n\n- Gameplay fix.\n'))
|
|
self.assertEqual(updated, tool.update_changelog(updated, '0.0.109'))
|
|
next_release = tool.update_changelog(updated, '0.0.110')
|
|
self.assertNotIn('0.0.109', next_release)
|
|
self.assertEqual(next_release.count('Latest published Workshop version:'), 1)
|
|
|
|
def test_bad_layout_refused(self):
|
|
for text in ('Notes only', TEXT + 'Latest published Workshop version: **0.0.1**\n',
|
|
'# Changelog\nLatest published Workshop version: **0.0.1**\nLatest published Workshop version: **0.0.2**\n'):
|
|
with self.subTest(text=text), self.assertRaises(ValueError):
|
|
tool.update_changelog(text, '0.0.109')
|
|
|
|
|
|
class PublishedLookupTests(unittest.TestCase):
|
|
def page(self, **overrides):
|
|
asset = dict(id='2528466DE220D91C', currentVersionNumber='0.0.147',
|
|
gameVersion='1.9.0.37', versions=[dict(version='0.0.147',
|
|
assetId='2528466DE220D91C', published=True, approved=True)])
|
|
asset.update(overrides)
|
|
return '<script id="__NEXT_DATA__" type="application/json">' + json.dumps(
|
|
{'props': {'pageProps': {'asset': asset}}}) + '</script>'
|
|
|
|
def test_public_version_is_not_game_or_bundle_version(self):
|
|
self.assertEqual(tool.online_version(self.page(), '2528466DE220D91C'), '0.0.147')
|
|
|
|
def test_wrong_asset_unpublished_and_ambiguous_pages_are_rejected(self):
|
|
cases = [self.page(id='1111111111111111'), self.page(versions=[]),
|
|
self.page(private=True), self.page(blocked=True),
|
|
self.page(currentVersionNumber='1.9.0.37'),
|
|
self.page(versions=[dict(version='0.0.147', assetId='2528466DE220D91C', published=False, approved=True)]),
|
|
self.page(versions=[dict(version='0.0.147', assetId='2528466DE220D91C', published=True, approved=False)]),
|
|
self.page() + self.page(), '<html>unavailable</html>']
|
|
for page in cases:
|
|
with self.subTest(page=page), self.assertRaises(ValueError):
|
|
tool.online_version(page, '2528466DE220D91C')
|
|
|
|
def test_stale_response_is_not_a_downgrade(self):
|
|
text = tool.update_changelog(TEXT, '0.0.146')
|
|
with self.assertRaises(ValueError):
|
|
tool.prevent_downgrade(text, '0.0.142')
|
|
tool.prevent_downgrade(text, '0.0.146')
|
|
tool.prevent_downgrade(text, '0.0.147')
|
|
tool.prevent_downgrade(tool.update_changelog(TEXT, '0.0.9'), '0.0.10')
|
|
|
|
def test_live_sync_validates_response_and_fails_closed(self):
|
|
with patch.object(tool.urllib.request, 'urlopen', return_value=io.BytesIO(self.page().encode())):
|
|
self.assertEqual(tool.sync_version(PROJECT, TEXT), '0.0.147')
|
|
with patch.object(tool.urllib.request, 'urlopen', side_effect=OSError('offline')):
|
|
with self.assertRaises(OSError):
|
|
tool.sync_version(PROJECT, TEXT)
|
|
with patch.object(tool.urllib.request, 'urlopen', return_value=io.BytesIO(self.page().encode())):
|
|
with self.assertRaises(ValueError):
|
|
tool.sync_version(PROJECT, tool.update_changelog(TEXT, '0.0.148'))
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|