import 'package:flame_lua_runtime/runtime/diagnostics/runtime_diagnostics.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { group('RuntimeDiagnostics', () { test('keeps entries in insertion order', () { final diagnostics = RuntimeDiagnostics(); diagnostics ..record( type: RuntimeDiagnosticType.packageActivationError, message: 'activation failed', ) ..record( type: RuntimeDiagnosticType.luaEventError, message: 'event failed', error: StateError('boom'), context: {'eventType': 'tap'}, ); expect(diagnostics.entries, hasLength(2)); expect( diagnostics.entries.first.type, RuntimeDiagnosticType.packageActivationError, ); expect(diagnostics.entries.last.error, isA()); expect(diagnostics.entries.last.context, {'eventType': 'tap'}); }); test('exports debug json with sanitized context and errors', () { final diagnostics = RuntimeDiagnostics(maxEntries: 3) ..record( type: RuntimeDiagnosticType.resourceLoadError, message: 'audio failed', error: StateError('missing'), context: { 'asset': 'bgm', 'attempt': 2, 'nested': {'z': 1, 'a': DateTime.utc(2026)}, 'values': [StateError('bad'), true], }, ); final json = diagnostics.toDebugJson(); expect(json['maxEntries'], 3); expect(json['count'], 1); final entries = json['entries'] as List; final entry = entries.single as Map; expect(entry['type'], 'resourceLoadError'); expect(entry['message'], 'audio failed'); expect(entry['error'], contains('missing')); expect(entry['timestamp'], isA()); expect(entry['context'], { 'asset': 'bgm', 'attempt': 2, 'nested': {'a': '2026-01-01T00:00:00.000Z', 'z': 1}, 'values': ['Bad state: bad', true], }); }); test('dumps readable text for empty and populated diagnostics', () { final diagnostics = RuntimeDiagnostics(maxEntries: 2); expect(diagnostics.dumpText(), 'RuntimeDiagnostics: no entries'); diagnostics.record( type: RuntimeDiagnosticType.commandError, message: 'command failed', error: ArgumentError('bad command'), context: {'command': 'play_bgm'}, ); final dump = diagnostics.dumpText(); expect(dump, contains('RuntimeDiagnostics (1/2)')); expect(dump, contains('commandError: command failed')); expect(dump, contains('error: Invalid argument(s): bad command')); expect(dump, contains('context: {"command":"play_bgm"}')); }); test('entry debug helpers support direct use', () { final entry = RuntimeDiagnosticEntry( type: RuntimeDiagnosticType.luaEventError, message: 'lua failed', timestamp: DateTime.utc(2026, 6, 4, 12), error: 'boom', context: {'event': 'tap'}, ); expect(entry.toDebugJson(), { 'timestamp': '2026-06-04T12:00:00.000Z', 'type': 'luaEventError', 'message': 'lua failed', 'error': 'boom', 'context': {'event': 'tap'}, }); expect( entry.dumpText(), '[2026-06-04T12:00:00.000Z] luaEventError: lua failed\n' ' error: boom\n' ' context: {"event":"tap"}', ); }); test('evicts oldest entries when max size is reached', () { final diagnostics = RuntimeDiagnostics(maxEntries: 2); diagnostics ..record(type: RuntimeDiagnosticType.commandError, message: 'one') ..record(type: RuntimeDiagnosticType.commandError, message: 'two') ..record(type: RuntimeDiagnosticType.commandError, message: 'three'); expect(diagnostics.entries.map((entry) => entry.message), [ 'two', 'three', ]); }); }); }