import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:http/http.dart';
import 'package:http/testing.dart';
import 'package:machweis/core/auth/auth_client.dart';
import 'package:machweis/core/auth/auth_store.dart';
import 'package:machweis/features/auth/presentation/welcome_screen.dart';
import 'package:machweis/features/profile/presentation/profile_screen.dart';
class _MemoryAuthTokenStorage implements AuthTokenStorage {
String? accessToken;
String? refreshToken;
@override
Future<void> deleteTokens() async {
accessToken = null;
refreshToken = null;
}
@override
Future<String?> readRefreshToken() async => refreshToken;
@override
Future<void> writeTokens({
required String accessToken,
required String refreshToken,
}) async {
this.accessToken = accessToken;
this.refreshToken = refreshToken;
}
}
Response _sessionResponse() => Response(
jsonEncode({
'data': {
'accessToken': 'access',
'refreshToken': 'refresh',
'user': {'id': 'user', 'email': 'test@example.com'},
'tenantId': 'tenant',
'role': 'owner',
},
}),
200,
);
void main() {
test(
'Logout entfernt Access- und Refresh-Token sowie lokale Sitzung',
() async {
final storage = _MemoryAuthTokenStorage();
var serverLogoutCalled = false;
final store = AuthStore(
client: AuthClient(
client: MockClient((request) async {
if (request.url.path == '/api/v1/auth/logout') {
serverLogoutCalled = true;
return Response('', 204);
}
return _sessionResponse();
}),
baseUrl: 'https://api.example.test',
),
storage: storage,
);
await store.login('test@example.com', 'password');
expect(storage.accessToken, 'access');
expect(storage.refreshToken, 'refresh');
await store.logout();
expect(serverLogoutCalled, isTrue);
expect(storage.accessToken, isNull);
expect(storage.refreshToken, isNull);
expect(store.session, isNull);
expect(store.status, AuthStatus.signedOut);
},
);
test('App-Neustart nach Logout stellt keine Sitzung wieder her', () async {
final storage = _MemoryAuthTokenStorage();
var refreshCalls = 0;
final client = AuthClient(
client: MockClient((request) async {
if (request.url.path == '/api/v1/auth/refresh') refreshCalls++;
if (request.url.path == '/api/v1/auth/logout') return Response('', 204);
return _sessionResponse();
}),
baseUrl: 'https://api.example.test',
);
final firstRun = AuthStore(client: client, storage: storage);
await firstRun.login('test@example.com', 'password');
await firstRun.logout();
final restarted = AuthStore(client: client, storage: storage);
await restarted.initialize();
expect(refreshCalls, 0);
expect(restarted.session, isNull);
expect(restarted.status, AuthStatus.signedOut);
});
testWidgets('Abmelden in der Firmenverwaltung führt zur Willkommensseite', (
tester,
) async {
final storage = _MemoryAuthTokenStorage();
final store = AuthStore(
client: AuthClient(
client: MockClient((request) async {
if (request.url.path == '/api/v1/auth/logout') {
return Response('', 204);
}
return _sessionResponse();
}),
baseUrl: 'https://api.example.test',
),
storage: storage,
);
await store.login('test@example.com', 'password');
await tester.pumpWidget(
MaterialApp(
home: ListenableBuilder(
listenable: store,
builder: (context, _) => store.isSignedIn
? ProfileScreen(authStore: store)
: WelcomeScreen(authStore: store),
),
),
);
await tester.scrollUntilVisible(find.text('Abmelden'), 300);
await tester.tap(find.text('Abmelden'));
await tester.pumpAndSettle();
await tester.tap(find.text('Abmelden').last);
await tester.pumpAndSettle();
expect(find.text('Demo starten'), findsOneWidget);
expect(store.status, AuthStatus.signedOut);
});
}
