- Update jenkins-credential.md milestone progress - Implement ReAuthUi and related fixes - Archive completed subtasks (02+01, 03) - Add new 04+03_reauth_ui subtask with PLAN and CODE_REVIEW - Update app, settings, and session related files - Add auth bridge and app auth tests
146 lines
4.6 KiB
Dart
146 lines
4.6 KiB
Dart
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);
|
|
});
|
|
});
|
|
}
|