68 lines
3.6 KiB
Python
68 lines
3.6 KiB
Python
"""Test the actual embedded UI timer methods with a deterministic clock (no rendering mocks)."""
|
|
import ast
|
|
from pathlib import Path
|
|
import types
|
|
import unittest
|
|
|
|
ROOT=Path(__file__).resolve().parents[2]
|
|
|
|
|
|
def window_class(filename,name,clock,messages):
|
|
text=(ROOT/'src/platform/ScriptLib'/filename).read_text().split('R"PY(',1)[1].rsplit(')PY";',1)[0]
|
|
tree=ast.parse(text)
|
|
tree.body=[n for n in tree.body if isinstance(n,(ast.ClassDef,ast.FunctionDef))]
|
|
ns=dict(ui=types.SimpleNamespace(Window=object),app=types.SimpleNamespace(GetTime=lambda:clock[0]),
|
|
chat=types.SimpleNamespace(CHAT_TYPE_INFO=1,AppendChat=lambda kind,text:messages.append(text)),
|
|
L=lambda text:text,NAMES={1:'moon',2:'sock'})
|
|
exec(compile(tree,filename,'exec'),ns)
|
|
return ns[name]
|
|
|
|
|
|
class TimerTests(unittest.TestCase):
|
|
def setUp(self):self.clock=[10.];self.messages=[]
|
|
|
|
def test_dungeon_reminder_only_confirmed_snapshot_and_extended_deadline(self):
|
|
cls=window_class('DungeonScript.inc','DungeonWindow',self.clock,self.messages)
|
|
w=cls.__new__(cls);w.reminder=(0,100);w.stale=True;w.values={'lair_end':100};w.serverTime=101;w.received=10.
|
|
w.CheckReminder();self.assertFalse(self.messages)
|
|
w.stale=False;w.values['lair_end']=200;w.CheckReminder()
|
|
self.assertEqual(w.reminder,(0,200));self.assertFalse(self.messages)
|
|
w.serverTime=200;w.CheckReminder();self.assertFalse(self.messages) # strict original deadline
|
|
w.serverTime=201;w.CheckReminder();w.CheckReminder()
|
|
self.assertEqual(len(self.messages),1);self.assertIsNone(w.reminder)
|
|
|
|
def test_dungeon_sleep_invalidates_display_and_requeries_before_notification(self):
|
|
cls=window_class('DungeonScript.inc','DungeonWindow',self.clock,self.messages)
|
|
w=cls.__new__(cls);w.lastTick=1.;w.stale=False;w.nextQuery=999;w.pending=False;w.values={};w.reminder=(0,5)
|
|
w.IsShow=lambda:False;calls=[];w.Query=lambda:calls.append('query')
|
|
w.Now=lambda:1000
|
|
w.OnUpdate()
|
|
self.assertTrue(w.stale);self.assertTrue(calls);self.assertFalse(self.messages)
|
|
|
|
def test_calendar_actual_scope_and_start_end_notifications_once(self):
|
|
cls=window_class('CalendarScript.inc','CalendarWindow',self.clock,self.messages)
|
|
w=cls.__new__(cls);w.offset=0;w.watch=dict(id=1,began=False,offset=0)
|
|
w.data=dict(time=100,rows=[[1,1,100,200,2,0,0]])
|
|
w.Notify();self.assertFalse(self.messages) # other channel cannot trigger start
|
|
w.data['rows'][0][-1]=1;w.Notify();w.Notify();self.assertEqual(len(self.messages),1)
|
|
w.data['time']=200;w.Notify();w.Notify();self.assertEqual(len(self.messages),2);self.assertIsNone(w.watch)
|
|
|
|
def test_short_screen_two_row_pages_do_not_skip_server_rows(self):
|
|
cls=window_class('CalendarScript.inc','CalendarWindow',self.clock,self.messages)
|
|
w=cls.__new__(cls);w.pending=False;w.offset=0;w.rowPage=0;w.pageSize=2;w.data=dict(total=10)
|
|
calls=[];w.Refresh=lambda:None;w.Query=lambda:calls.append(w.offset)
|
|
seen=[]
|
|
for i in range(5):
|
|
seen.append(w.offset+w.rowPage*w.pageSize)
|
|
w.Page(1)
|
|
if w.data is None:w.data=dict(total=10)
|
|
self.assertEqual(seen,[0,2,4,6,8]);self.assertEqual(calls,[8])
|
|
|
|
def test_calendar_removed_event_cancels_without_fake_end(self):
|
|
cls=window_class('CalendarScript.inc','CalendarWindow',self.clock,self.messages)
|
|
w=cls.__new__(cls);w.offset=0;w.watch=dict(id=1,began=True,offset=0);w.data=dict(time=500,rows=[])
|
|
w.Notify();self.assertIsNone(w.watch);self.assertFalse(self.messages)
|
|
|
|
|
|
if __name__=='__main__':unittest.main()
|