add # 新增农场详述指令

This commit is contained in:
2026-10-20 18:47:36 +08:00
parent 024541bea2
commit 07a2f0f53e
10 changed files with 411 additions and 9 deletions
+62
View File
@@ -0,0 +1,62 @@
from dataclasses import replace
from io import BytesIO
from pathlib import Path
import sys
import unittest
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, Identity
from farm_core.domain import Account, Plot, Snapshot, boosted
from farm_render import FarmRenderer
from farm_render.details import detail_rows, render_details
class DetailTests(unittest.TestCase):
def setUp(self):
self.renderer = FarmRenderer(choose_font())
self.plant = Catalogue.bundled().get('草莓')
self.who = Identity('test', 'local', 'qq', 'details')
def snapshot(self, plots):
return Snapshot(Account('详述演示', 500, 0, 0), (), tuple(plots))
def test_frozen_maturity_loss_survives_clearing_and_integer_rounding(self):
plot = Plot(1, self.plant, 100, yield_bonus=10,
pest_count=0, pest_spawned=3, maturity_pests=3)
rows, pages = detail_rows(self.renderer, self.who,
self.snapshot([plot]), 200, 1)
self.assertEqual(pages, 1)
self.assertEqual(rows[0].amount,
boosted(self.plant.harvest, 10)*85//100)
self.assertEqual(rows[0].state, '已成熟')
self.assertIn('15%', rows[0].pest_note)
self.assertIn('成熟时', rows[0].pest_note)
def test_current_pests_and_season_boundary_empty_withered_pagination(self):
plot = Plot(1, self.plant, 1000, pest_count=2, pest_spawned=2)
rows, _ = detail_rows(self.renderer, self.who,
self.snapshot([plot]), 200, 1)
self.assertEqual(rows[0].amount, self.plant.harvest*90//100)
self.assertIn('预计', rows[0].pest_note)
data = self.snapshot([Plot(i) for i in range(1, 12)] + [
replace(plot, slot=12, harvest_count=self.plant.crop),
])
rows, pages = detail_rows(self.renderer, self.who, data, 200, 2)
self.assertEqual(pages, 2)
self.assertEqual([r.slot for r in rows], [11, 12])
self.assertIsNone(rows[0].amount)
self.assertEqual(rows[1].state, '已枯萎')
self.assertIsNone(rows[1].amount)
with self.assertRaises(ValueError):
detail_rows(self.renderer, self.who, data, 200, 3)
def test_render_full_farm_and_table(self):
data = self.snapshot([Plot(1, self.plant, 100)])
result = render_details(self.renderer, self.who, data, 200, 1,
'autumn', 'PNG')
with Image.open(BytesIO(result)) as image:
self.assertEqual(image.width, 1024)
self.assertGreater(image.height, 624)
+12 -1
View File
@@ -46,4 +46,15 @@ class ShopRenderTests(unittest.TestCase):
self.assertIn('按名称:购买种子 胡萝卜 5', labels)
with Image.open(BytesIO(result)) as image:
self.assertEqual(image.size, (1024, 1536))
self.assertEqual(image.format, 'PNG')
self.assertEqual(image.format, 'JPEG')
def test_explicit_png_and_default_jpeg_keep_dimensions(self):
renderer = FarmRenderer(choose_font())
rows, pages = shop_page(Catalogue.bundled(), 1)
jpeg = render_shop(renderer, rows, None, 1, pages)
png = render_shop(renderer, rows, None, 1, pages, 'PNG')
for content, codec in ((jpeg, 'JPEG'), (png, 'PNG')):
with Image.open(BytesIO(content)) as image:
self.assertEqual(image.size, (1024, 1536))
self.assertEqual(image.format, codec)
self.assertLess(len(jpeg), len(png) // 2)
+36
View File
@@ -161,6 +161,42 @@ class ZhenxunRuntimeTests(unittest.IsolatedAsyncioTestCase):
self.module.operation_id("b", "p", "u", "2", "buy"),
)
async def test_farm_details_image_pagination_text_and_single_snapshot(self):
from io import BytesIO
from PIL import Image
from unittest.mock import AsyncMock
self.assertEqual(self.module.COMMANDS['农场详述'], 'details')
self.assertEqual(self.module.COMMANDS['我的种子'], 'inventory')
await self.call('register')
await self.call('buy', '白萝卜 1', 'buy-details')
await self.call('sow', '白萝卜 1', 'sow-details')
before = await self.runtime.service.snapshot(self.runtime_identity())
with patch.object(self.runtime.service, 'snapshot',
new=AsyncMock(return_value=before)) as query:
image = await self.call('details')
query.assert_awaited_once()
with Image.open(BytesIO(image)) as decoded:
self.assertEqual(decoded.width, 1024)
self.assertIsInstance(await self.call('inventory'), str)
self.assertIn('页码无效', await self.call('details', '999'))
self.assertIsInstance(await self.call('farm', 'detail'), bytes)
rendering = self.runtime.rendering
self.runtime.rendering = None
try:
text = await self.call('details')
self.assertIn('白萝卜', text)
self.assertIn('1/1季', text)
self.assertNotIn('被偷', text)
finally:
self.runtime.rendering = rendering
def runtime_identity(self):
identity = importlib.import_module(
self.package + '._vendor.farm_core',
).Identity
return identity(self.runtime.deployment, self.context['bot_id'],
self.context['platform'], self.context['user_id'])
async def test_invalid_arguments_and_missing_font_are_explicit(self):
await self.call("register")
for action, arguments in (("buy", "白萝卜 nope"),