add # 新增种子商店界面

fixed # 修复数据库目录错误的BUG
This commit is contained in:
2026-10-20 13:15:01 +08:00
parent 92a3944e43
commit 38f4b84cf0
15 changed files with 395 additions and 15 deletions
+47
View File
@@ -0,0 +1,47 @@
import importlib.util
from pathlib import Path
from types import SimpleNamespace
import tempfile
import unittest
ROOT = Path(__file__).resolve().parents[1]
spec = importlib.util.spec_from_file_location(
"farm_config_migration",
ROOT / "integrations/zhenxun/config_migration.py",
)
migration = importlib.util.module_from_spec(spec)
spec.loader.exec_module(migration)
class ConfigMigrationTests(unittest.TestCase):
def test_cleanup_backups_and_repeat_are_scoped(self):
with tempfile.TemporaryDirectory() as temporary:
root = Path(temporary)
group = SimpleNamespace(configs={
"绘制农场清晰度": "low", "CUSTOM": "keep",
})
saves = []
manager = SimpleNamespace(
file=root / "plugins2config.yaml",
_simple_file=root / "config.yaml",
_simple_data={
"farm": {"绘制农场清晰度": "low", "CUSTOM": "keep"},
"other": {"服务地址": "keep"},
},
get=lambda module: group,
save=lambda **kwargs: saves.append(kwargs),
)
for path in (manager.file, manager._simple_file):
path.write_text("original", encoding="utf-8")
migration.migrate_config(manager, "farm")
self.assertEqual(group.configs, {"CUSTOM": "keep"})
self.assertEqual(manager._simple_data["farm"], {"CUSTOM": "keep"})
self.assertEqual(manager._simple_data["other"], {"服务地址": "keep"})
self.assertEqual(saves, [{"save_simple_data": True}])
for path in (manager.file, manager._simple_file):
self.assertEqual(path.with_name(
path.name + ".farm-v1.bak",
).read_text(encoding="utf-8"), "original")
migration.migrate_config(manager, "farm")
self.assertEqual(len(saves), 1)
+49
View File
@@ -0,0 +1,49 @@
from dataclasses import replace
from io import BytesIO
from pathlib import Path
import sys
import unittest
from unittest.mock import patch
from PIL import Image
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / 'scripts'))
from ci_font import choose_font
from farm_core import Catalogue
from farm_core.domain import Account
from farm_render import FarmRenderer
from farm_render.shop import shop_page, render_shop
from farm_render.canvas import Canvas
class ShopRenderTests(unittest.TestCase):
def test_pages_filter_unavailable_and_keep_stable_ids(self):
plant = Catalogue.bundled().get('胡萝卜')
plants = [replace(plant, plant_id=i) for i in range(1, 9)]
plants += [replace(plant, plant_id=99, purchasable=False)]
rows, total = shop_page(plants, 2)
self.assertEqual(total, 2)
self.assertEqual([p.plant_id for p in rows], [7, 8])
for page in (0, 3, True):
with self.assertRaises(ValueError):
shop_page(plants, page)
self.assertEqual(shop_page([], 1), ((), 1))
def test_shop_uses_actual_fields_and_missing_icon_fallback(self):
renderer = FarmRenderer(choose_font())
plant = Catalogue.bundled().get('胡萝卜')
rows = (plant, replace(plant, plant_id=99999,
name='不存在的素材', is_vip=True, vip_buy=35))
with patch.object(Canvas, 'text', autospec=True) as text:
result = render_shop(
renderer, rows, Account('商店', 12580, 36, 0), 1, 1,
)
labels = [call.args[2] for call in text.call_args_list]
self.assertIn(f'{plant.cost:,} 农场币 / 粒', labels)
self.assertIn('35 点券 / 粒', labels)
self.assertIn('暂无图', labels)
self.assertIn(f'按编号:购买种子 #{plant.plant_id} 5', labels)
self.assertIn('按名称:购买种子 胡萝卜 5', labels)
with Image.open(BytesIO(result)) as image:
self.assertEqual(image.size, (1024, 1536))
self.assertEqual(image.format, 'PNG')
+34 -2
View File
@@ -69,7 +69,12 @@ class ZhenxunRuntimeTests(unittest.IsolatedAsyncioTestCase):
replace(carrot, plant_id=9002, enabled=False, name="停用菜"),
replace(carrot, plant_id=9003, crop_type=11, name="特殊道具"),
])
shop = await self.call("shop")
rendering = self.runtime.rendering
self.runtime.rendering = None
try:
shop = await self.call("shop")
finally:
self.runtime.rendering = rendering
self.assertIn("胡萝卜(#1)", shop)
for name in ("禁售菜", "停用菜", "特殊道具"):
self.assertNotIn(name, shop)
@@ -78,6 +83,28 @@ class ZhenxunRuntimeTests(unittest.IsolatedAsyncioTestCase):
self.assertIn("不出售", await self.call("buy", "禁售菜 1", "blocked"))
self.assertIn("(#1)", await self.call("inventory"))
async def test_shop_image_page_and_buy_by_name_or_id(self):
from io import BytesIO
from PIL import Image
result = await self.call('shop')
with Image.open(BytesIO(result)) as image:
self.assertEqual(image.size, (1024, 1536))
await self.call('register')
self.assertIn('已完成', await self.call('buy', '白萝卜 1', 'name'))
plant = self.runtime.service.catalogue.get('白萝卜')
self.assertIn('已完成', await self.call(
'buy', f'#{plant.plant_id} 1', 'id',
))
from unittest.mock import AsyncMock
self.runtime.rendering.seed_shop = AsyncMock(return_value=b'shop')
self.assertEqual(await self.call('shop', '2'), b'shop')
args = self.runtime.rendering.seed_shop.call_args.args
self.assertEqual(len(args[0]), 6)
self.assertEqual(args[1].name, '离线玩家')
self.assertEqual(args[2], 2)
for page in ('0', '999999'):
self.assertIn('页码无效', await self.call('shop', page))
async def test_farm_uses_calendar_theme_and_bee_is_not_a_user_option(self):
rendering = self.runtime.rendering
from unittest.mock import AsyncMock
@@ -251,8 +278,13 @@ class ZhenxunRuntimeTests(unittest.IsolatedAsyncioTestCase):
))
platform = ModuleType("zhenxun.utils.platform")
platform.PlatformUtils = SimpleNamespace()
config = ModuleType("zhenxun.configs.config")
config.Config = SimpleNamespace(
get=lambda module: SimpleNamespace(configs={}),
_simple_data={},
)
modules = {m.__name__:m for m in (
nonebot, adapters, params, uninfo, paths, messages, platform,
nonebot, adapters, params, uninfo, paths, messages, platform, config,
)}
with patch.dict(sys.modules, modules):
imported = importlib.import_module(self.package + ".commands")