import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'package:flutter_secure_storage_platform_interface/flutter_secure_storage_platform_interface.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:fuel_tax_tracker/services/cloud/webdav_provider.dart'; const _multistatusBody = ''' / HTTP/1.1 200 OK '''; /// Confirms sign-in survives a cold app restart: [WebDavProvider] persists /// verified credentials to secure storage on [signInWithCredentials], and a /// *fresh* instance (an in-memory field reset, standing in for a relaunched /// app) can restore the session from them via [attemptSilentSignIn] — the /// gap flagged in README's "Known limitations" and fixed here. void main() { late HttpServer server; late String serverUrl; const username = 'alice'; const password = 'hunter2'; setUp(() async { FlutterSecureStoragePlatform.instance = _FakeSecureStoragePlatform(); server = await HttpServer.bind(InternetAddress.loopbackIPv4, 0); serverUrl = 'http://127.0.0.1:${server.port}/'; unawaited(server.forEach((request) async { final auth = request.headers.value('authorization'); final expected = 'Basic ${base64Encode(utf8.encode('$username:$password'))}'; if (request.method == 'PROPFIND' && auth == expected) { request.response.statusCode = 207; request.response.headers.contentType = ContentType('application', 'xml'); request.response.write(_multistatusBody); } else if (request.method == 'PROPFIND') { request.response.statusCode = 401; } else { request.response.statusCode = 404; } await request.response.close(); })); }); tearDown(() async { await server.close(force: true); }); test('signInWithCredentials persists credentials that a fresh instance can restore', () async { final first = WebDavProvider(); await first.signInWithCredentials(serverUrl: serverUrl, username: username, password: password); expect(first.isSignedIn, isTrue); // A brand new instance has no in-memory session — simulates the app // process having been killed and relaunched. final afterRestart = WebDavProvider(); expect(afterRestart.isSignedIn, isFalse); final restored = await afterRestart.attemptSilentSignIn(); expect(restored, isTrue); expect(afterRestart.isSignedIn, isTrue); expect(afterRestart.accountLabel, first.accountLabel); }); test('attemptSilentSignIn returns false, not throws, when nothing was ever stored', () async { final provider = WebDavProvider(); expect(await provider.attemptSilentSignIn(), isFalse); expect(provider.isSignedIn, isFalse); }); test('signOut clears stored credentials so a later restart no longer restores', () async { final first = WebDavProvider(); await first.signInWithCredentials(serverUrl: serverUrl, username: username, password: password); await first.signOut(); final afterRestart = WebDavProvider(); expect(await afterRestart.attemptSilentSignIn(), isFalse); }); } class _FakeSecureStoragePlatform extends FlutterSecureStoragePlatform { final Map _store = {}; @override Future write({required String key, required String value, required Map options}) async { _store[key] = value; } @override Future read({required String key, required Map options}) async => _store[key]; @override Future containsKey({required String key, required Map options}) async => _store.containsKey(key); @override Future delete({required String key, required Map options}) async { _store.remove(key); } @override Future> readAll({required Map options}) async => Map.of(_store); @override Future deleteAll({required Map options}) async => _store.clear(); }