import 'package:flutter_test/flutter_test.dart'; import 'package:matrix/matrix.dart'; import 'package:pyramid/features/spaces/space_admin_dialog.dart'; /// Fake-Client für `updatePowerLevelsSafely`: liefert einen vorgegebenen /// Server-Stand des power_levels-Events und zeichnet auf, was (wenn /// überhaupt) zurückgeschrieben wird. Alles andere → NoSuchMethodError. class _FakeClient implements Client { _FakeClient({required this.serverState, this.getError}); Map serverState; MatrixException? getError; Map? written; @override String? get userID => '@me:pyramid.example'; @override Future> getRoomStateWithKey( String roomId, String eventType, String stateKey, { Format? format, }) async { final err = getError; if (err != null) throw err; return serverState; } @override Future setRoomStateWithKey( String roomId, String eventType, String stateKey, Map body, ) async { written = body; return r'$neuesEvent'; } @override dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); } class _FakeRoom implements Room { _FakeRoom(this.client); @override final Client client; @override String get id => '!raum:pyramid.example'; @override dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); } void main() { test('Server-Stand bleibt erhalten: fremde Einträge werden nie überschrieben ' '(genau der Bug, der schon einmal Admins ausgesperrt hat)', () async { final client = _FakeClient(serverState: { 'users': {'@me:pyramid.example': 100, '@uta:pyramid.example': 50}, 'users_default': 0, 'state_default': 50, }); final room = _FakeRoom(client); await updatePowerLevelsSafely(room, (content) { (content['users'] as Map)['@neu:pyramid.example'] = 50; }); final users = client.written!['users'] as Map; expect(users['@uta:pyramid.example'], 50, reason: 'bestehender Server-Eintrag muss überleben'); expect(users['@me:pyramid.example'], 100); expect(users['@neu:pyramid.example'], 50); }); test('Selbst-Degradierung unter das nötige Level wird abgebrochen, ' 'nichts wird geschrieben', () async { final client = _FakeClient(serverState: { 'users': {'@me:pyramid.example': 100}, 'state_default': 50, }); final room = _FakeRoom(client); await expectLater( updatePowerLevelsSafely(room, (content) { (content['users'] as Map)['@me:pyramid.example'] = 0; }), throwsException, ); expect(client.written, isNull); }); test('eigener Eintrag entfernt → Fallback auf users_default greift und ' 'schützt ebenfalls', () async { final client = _FakeClient(serverState: { 'users': {'@me:pyramid.example': 100}, 'users_default': 0, }); final room = _FakeRoom(client); await expectLater( updatePowerLevelsSafely(room, (content) { (content['users'] as Map) .remove('@me:pyramid.example'); }), throwsException, ); expect(client.written, isNull); }); test('explizites events[m.room.power_levels]-Erfordernis wird respektiert', () async { final client = _FakeClient(serverState: { 'users': {'@me:pyramid.example': 60}, 'events': {'m.room.power_levels': 75}, 'state_default': 50, }); final room = _FakeRoom(client); // 60 < 75 → muss abbrechen, obwohl state_default (50) erfüllt wäre. await expectLater( updatePowerLevelsSafely(room, (_) {}), throwsException, ); expect(client.written, isNull); }); test('fehlendes power_levels-Event (M_NOT_FOUND): Start mit leerem Event, ' 'Schreiben nur wenn man sich selbst hoch genug setzt', () async { final client = _FakeClient( serverState: {}, getError: MatrixException.fromJson( {'errcode': 'M_NOT_FOUND', 'error': 'Event not found.'}), ); final room = _FakeRoom(client); // Ohne eigenen Eintrag: users_default 0 < state_default-Fallback 50 → Abbruch. await expectLater( updatePowerLevelsSafely(room, (_) {}), throwsException, ); expect(client.written, isNull); // Setzt man sich selbst auf 100, darf geschrieben werden. await updatePowerLevelsSafely(room, (content) { (content['users'] as Map)['@me:pyramid.example'] = 100; }); final users = client.written!['users'] as Map; expect(users['@me:pyramid.example'], 100); }); test('andere Serverfehler (z. B. M_FORBIDDEN) werden durchgereicht, ' 'nichts wird geschrieben', () async { final client = _FakeClient( serverState: {}, getError: MatrixException.fromJson( {'errcode': 'M_FORBIDDEN', 'error': 'Nope.'}), ); final room = _FakeRoom(client); await expectLater( updatePowerLevelsSafely(room, (_) {}), throwsA(isA()), ); expect(client.written, isNull); }); }