add # 新增背景图的优化

This commit is contained in:
2026-10-20 10:39:49 +08:00
parent 54164aeb9c
commit 2761be6c3f
20 changed files with 1644 additions and 102 deletions
+74
View File
@@ -0,0 +1,74 @@
from datetime import datetime, timezone
from pathlib import Path
import sys
import unittest
from unittest.mock import patch
from farm_core import Identity
from farm_core.domain import Account, Plot, Snapshot
from farm_render import FarmRenderer, RenderOptions
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / "scripts"))
from ci_font import choose_font
class SeasonBackgroundTests(unittest.TestCase):
def test_calendar_uses_beijing_time_and_month_boundaries(self):
from farm_render.seasons import season_for
cases = (
("2026-02-28T15:59:59", "winter"),
("2026-02-28T16:00:00", "spring"),
("2026-05-31T15:59:59", "spring"),
("2026-05-31T16:00:00", "summer"),
("2026-08-31T16:00:00", "autumn"),
("2026-11-30T16:00:00", "winter"),
("2026-12-31T16:00:00", "winter"),
)
for value, expected in cases:
utc = datetime.fromisoformat(value).replace(tzinfo=timezone.utc)
self.assertEqual(season_for(int(utc.timestamp())), expected)
def test_every_theme_has_nine_decorations_and_known_fallbacks(self):
renderer = FarmRenderer(choose_font())
layouts = renderer.assets.metadata["decorations"]
for theme in ("default", "spring", "summer", "autumn", "winter", "bee"):
self.assertEqual(len(layouts[theme]), 9)
self.assertEqual(RenderOptions(theme=theme).theme, theme)
for item in layouts[theme]:
self.assertIn(item["sprite"], renderer.assets.metadata["images"])
spring_mail = layouts["spring"][6]
autumn_workshop = layouts["autumn"][7]
self.assertEqual(spring_mail["source_theme"], "default")
self.assertEqual(autumn_workshop["source_theme"], "default")
def test_shorter_house_keeps_ground_baseline_and_aspect_ratio(self):
renderer = FarmRenderer(choose_font())
layouts = renderer.assets.metadata["decorations"]
spring, winter = layouts["spring"][0], layouts["winter"][0]
self.assertAlmostEqual(
spring["position"][1] + spring["size"][1],
winter["position"][1] + winter["size"][1], places=5,
)
self.assertAlmostEqual(winter["size"][0] / winter["size"][1],
890 / 821, places=5)
def test_dock_is_drawn_after_crops_and_theme_cache_is_separate(self):
renderer = FarmRenderer(choose_font())
who = Identity("test", "local", "qq", "seasons")
data = Snapshot(Account("四季测试", 500, 0, 0), (), (Plot(1),))
for theme in ("spring", "summer", "autumn", "winter", "bee"):
first = renderer.render(who, data, 0, RenderOptions(theme=theme))
warm = renderer.render(who, data, 1, RenderOptions(theme=theme))
self.assertFalse(first.cache_hit)
self.assertTrue(warm.cache_hit)
scene = renderer.scene(who, data, 0)
order = []
with patch.object(renderer, "_plants", side_effect=lambda *a:
order.append("plants")), patch.object(
renderer, "_decorations", side_effect=lambda c, o, layer:
order.append(layer)
):
renderer.render(who, data, 0, RenderOptions(width=1536))
self.assertLess(order.index("plants"), order.index("foreground"))
+13
View File
@@ -93,6 +93,19 @@ class ZhenxunPackageTests(unittest.TestCase):
self.assertEqual(sentinel.read_text(), "preserved")
self.assertTrue((target / "__init__.py").is_file())
def test_readme_image_is_in_repository_archive_and_manifest(self):
expected = (ROOT / "images/farm-preview.png").read_bytes()
relative = "images/farm-preview.png"
self.assertEqual(
(self.output / "repository" / relative).read_bytes(), expected,
)
manifest = verify_package(self.bundle)
self.assertIn(relative, manifest["files"])
with ZipFile(self.bundle) as archive:
self.assertEqual(archive.read(
f"zhenxun_plugin_farm_preview/{relative}",
), expected)
def test_tampering_extra_path_and_traversal_rejected(self):
for name in ("../outside.txt", "C:/escape.txt", "extra.txt",
"..\\outside.txt"):
+17
View File
@@ -78,6 +78,23 @@ class ZhenxunRuntimeTests(unittest.IsolatedAsyncioTestCase):
self.assertIn("不出售", await self.call("buy", "禁售菜 1", "blocked"))
self.assertIn("(#1)", await self.call("inventory"))
async def test_farm_uses_calendar_theme_and_bee_is_not_a_user_option(self):
rendering = self.runtime.rendering
from unittest.mock import AsyncMock
rendering.my_farm = AsyncMock(return_value=SimpleNamespace(content=b"ok"))
for now, expected in (
(1767225600, "winter"), (1775001600, "spring"),
(1782864000, "summer"), (1790812800, "autumn"),
):
self.runtime.service.clock = lambda: now
self.assertEqual(await self.call("farm"), b"ok")
call = rendering.my_farm.call_args
self.assertEqual(call.kwargs["options"].theme, expected)
self.assertEqual(call.kwargs["now"], now)
self.assertEqual(await self.call("farm", "高清"), b"ok")
self.assertEqual(rendering.my_farm.call_args.kwargs["options"].width, 1536)
self.assertIn("参数有误", await self.call("farm", "蜂巢"))
async def test_pest_command_clears_pests_and_preserves_growth(self):
self.assertEqual(self.module.COMMANDS["农场除虫"], "clear_pests")
self.assertIn("每只虫", await self.call("help"))