import 'package:flame_lua_runtime/runtime/events/runtime_event_gate.dart'; import 'package:flame_lua_runtime/runtime/lifecycle/runtime_session.dart'; import 'package:flame_lua_runtime/runtime/models/runtime_event.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { group('RuntimeEventGate', () { test('attaches session id without exposing lifecycle fields to Lua', () { final session = RuntimeSession(gameId: 'game')..activate(); final gate = RuntimeEventGate( session: session, isScopeAlive: (_) => true, ); final event = gate.attachSession(const RuntimeEvent(type: 'tap')); expect(event.sessionId, session.id); expect(event.toMap(), {'type': 'tap'}); }); test('accepts only active matching sessions', () { final session = RuntimeSession(gameId: 'game')..activate(); final gate = RuntimeEventGate( session: session, isScopeAlive: (_) => true, ); expect( gate.accepts(RuntimeEvent(type: 'tap', sessionId: session.id)), isTrue, ); expect( gate.accepts(RuntimeEvent(type: 'tap', sessionId: session.id + 1)), isFalse, ); session.beginDisposing(); expect( gate.accepts(RuntimeEvent(type: 'tap', sessionId: session.id)), isFalse, ); }); test('drops dead scopes and stale epochs', () { final session = RuntimeSession(gameId: 'game')..activate(); final gate = RuntimeEventGate( session: session, isScopeAlive: (scope) => scope == 'alive', isNodeEpochAlive: (id, epoch) => epoch == 2, ); expect( gate.accepts( RuntimeEvent( type: 'tap', sessionId: session.id, scope: 'alive', scopeEpoch: 2, target: 'button', targetEpoch: 2, ), ), isTrue, ); expect( gate.accepts( RuntimeEvent(type: 'tap', sessionId: session.id, scope: 'dead'), ), isFalse, ); expect( gate.accepts( RuntimeEvent( type: 'tap', sessionId: session.id, target: 'button', targetEpoch: 1, ), ), isFalse, ); }); }); }