import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:appsok/src/services/jenkins_client.dart'; import 'package:appsok/src/services/token_store.dart'; void main() { setUp(() { FlutterSecureStorage.setMockInitialValues({}); }); group('TokenStore.readSession', () { test('readSession returns null when config is incomplete', () async { final store = TokenStore(); expect(await store.readSession(), isNull); }); test('readSession returns null when only credentials are stored', () async { FlutterSecureStorage.setMockInitialValues({ 'jenkins.username': 'ada', 'jenkins.apiToken': 'tok', }); final store = TokenStore(); expect(await store.readSession(), isNull); }); test('readSession returns null when base url is invalid', () async { FlutterSecureStorage.setMockInitialValues({ 'jenkins.baseUrl': ':::not-a-url:::', 'jenkins.username': 'ada', 'jenkins.apiToken': 'tok', }); final store = TokenStore(); expect(await store.readSession(), isNull); }); test('saveSession and readSession round trip base url and credentials', () async { final store = TokenStore(); final session = JenkinsSessionConfig( baseUrl: Uri.parse('https://jenkins.example/'), credentials: const JenkinsCredentials( username: 'ada', apiToken: 'secret', ), ); await store.saveSession(session); final result = await store.readSession(); expect(result, isNotNull); expect(result!.baseUrl, Uri.parse('https://jenkins.example/')); expect(result.credentials.username, 'ada'); expect(result.credentials.apiToken, 'secret'); }); test('clearSession removes base url and credentials', () async { final store = TokenStore(); final session = JenkinsSessionConfig( baseUrl: Uri.parse('https://jenkins.example/'), credentials: const JenkinsCredentials( username: 'ada', apiToken: 'secret', ), ); await store.saveSession(session); await store.clearSession(); expect(await store.readSession(), isNull); }); }); group('TokenStore.saveSession atomicity', () { test('saveSession overwrites all three keys atomically', () async { final store = TokenStore(); // Save first session await store.saveSession( JenkinsSessionConfig( baseUrl: Uri.parse('https://jenkins.first/'), credentials: const JenkinsCredentials( username: 'first', apiToken: 'token-first', ), ), ); // Overwrite with second session await store.saveSession( JenkinsSessionConfig( baseUrl: Uri.parse('https://jenkins.second/'), credentials: const JenkinsCredentials( username: 'second', apiToken: 'token-second', ), ), ); final result = await store.readSession(); expect(result, isNotNull); expect(result!.baseUrl, Uri.parse('https://jenkins.second/')); expect(result.credentials.username, 'second'); expect(result.credentials.apiToken, 'token-second'); }); test('clearSession after saveSession returns null for readSession', () async { final store = TokenStore(); await store.saveSession( JenkinsSessionConfig( baseUrl: Uri.parse('https://jenkins.example/'), credentials: const JenkinsCredentials( username: 'user', apiToken: 'tok', ), ), ); await store.clearSession(); expect(await store.readSession(), isNull); }); }); group('TokenStore.readCredentials backward compatibility', () { test('readCredentials remains backward compatible', () async { final store = TokenStore(); await store.saveCredentials( const JenkinsCredentials(username: 'grace', apiToken: 'tok2'), ); final result = await store.readCredentials(); expect(result, isNotNull); expect(result!.username, 'grace'); expect(result.apiToken, 'tok2'); }); test('readCredentials returns null when nothing is stored', () async { final store = TokenStore(); expect(await store.readCredentials(), isNull); }); test('clearCredentials removes username and token', () async { final store = TokenStore(); await store.saveCredentials( const JenkinsCredentials(username: 'grace', apiToken: 'tok2'), ); await store.clearCredentials(); expect(await store.readCredentials(), isNull); }); }); }