import 'dart:io'; import 'package:flutter_test/flutter_test.dart'; import 'package:path_provider_platform_interface/path_provider_platform_interface.dart'; import 'package:pyramid/core/auth_log.dart'; /// Plattform kaputt/nicht verfügbar (z. B. sehr früher App-Start, exotischer /// Fehler): genau der Fall, in dem AuthLog.write NIEMALS werfen darf – der /// Soft-Logout-Guard ruft es in seinem catch-Pfad auf, und ein Throw dort /// würde im SDK zu logout()+clear() eskalieren (der Uta-Bug). class _BrokenPathProvider extends PathProviderPlatform { @override Future getApplicationSupportPath() async => throw StateError('Plattform nicht verfügbar'); } class _TempPathProvider extends PathProviderPlatform { _TempPathProvider(this.path); final String path; @override Future getApplicationSupportPath() async => path; } void main() { // WICHTIG: Reihenfolge der Tests ist Absicht. AuthLog cached sein File-Handle // statisch; der Kaputt-Plattform-Test muss laufen, BEVOR ein Test mit // funktionierender Plattform das Handle in den Cache legt. late Directory tempDir; setUpAll(() { tempDir = Directory.systemTemp.createTempSync('pyramid_auth_log_test'); }); tearDownAll(() { tempDir.deleteSync(recursive: true); }); test( 'write/read werfen NIE, auch wenn die Plattform fehlt ' '(CLAUDE.md: Fehlerpfade dürfen nie in einem stillen Logout enden)', () async { PathProviderPlatform.instance = _BrokenPathProvider(); // Darf normal zurückkehren, obwohl getApplicationSupportPath wirft. await AuthLog.write('darf nicht werfen'); expect(await AuthLog.read(), startsWith('Log konnte nicht gelesen werden')); }); test('read ohne bisherige Einträge liefert Platzhalter statt Fehler', () async { PathProviderPlatform.instance = _TempPathProvider(tempDir.path); expect(await AuthLog.read(), '(noch keine Einträge)'); }); test('write hängt Zeile mit ISO-Zeitstempel an, read liefert sie zurück', () async { PathProviderPlatform.instance = _TempPathProvider(tempDir.path); await AuthLog.write('Hallo Log'); final content = await AuthLog.read(); expect(content, contains('Hallo Log')); expect( RegExp(r'^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}').hasMatch(content), isTrue, reason: 'jede Zeile beginnt mit einem ISO-8601-Zeitstempel', ); }); test( 'Log wird auf 500 Zeilen gekappt (älteste fliegen raus), ' 'damit es nie unbegrenzt wächst', () async { PathProviderPlatform.instance = _TempPathProvider(tempDir.path); for (var i = 0; i < 520; i++) { await AuthLog.write('Zeile $i'); } final lines = (await AuthLog.read()).trimRight().split('\n'); expect(lines.length, 500); expect(lines.last, contains('Zeile 519'), reason: 'neueste Einträge müssen überleben'); expect((await AuthLog.read()).contains('Hallo Log'), isFalse, reason: 'ältester Eintrag (aus dem Test davor) muss weggekappt sein'); }); }