fix: jenkins client and test updates

This commit is contained in:
toki 2026-06-16 09:37:21 +09:00
parent 2e0e971656
commit 9f4048a889
3 changed files with 127 additions and 29 deletions

View file

@ -201,7 +201,21 @@ class JenkinsClient {
_throwIfFailed(response);
final json = jsonDecode(response.body) as Map<String, Object?>;
if (json['anonymous'] == true) {
throw const JenkinsClientException(
statusCode: 401,
message: 'Jenkins whoAmI returned anonymous user',
);
}
final id = (json['id'] as String?)?.trim() ?? '';
if (id.isEmpty) {
throw const JenkinsClientException(
statusCode: 401,
message: 'Jenkins whoAmI returned empty user id',
);
}
final displayName = _firstNonBlank([
json['fullName'] as String?,
json['name'] as String?,

View file

@ -220,33 +220,35 @@ void main() {
expect(result.isRestored, isFalse);
});
test('restoreDetailed returns restored after current user validation',
() async {
FlutterSecureStorage.setMockInitialValues({
'jenkins.baseUrl': baseUrl,
'jenkins.username': credentials.username,
'jenkins.apiToken': credentials.apiToken,
});
test(
'restoreDetailed returns restored after current user validation',
() async {
FlutterSecureStorage.setMockInitialValues({
'jenkins.baseUrl': baseUrl,
'jenkins.username': credentials.username,
'jenkins.apiToken': credentials.apiToken,
});
final session = JenkinsArtifactSession(
store: TokenStore(),
client: JenkinsClient(
client: MockClient((request) async {
if (request.url.path.endsWith('whoAmI/api/json')) {
return http.Response(jsonEncode({'id': 'user'}), 200);
}
return http.Response('unexpected', 400);
}),
),
stager: ArtifactStagingService(),
);
final session = JenkinsArtifactSession(
store: TokenStore(),
client: JenkinsClient(
client: MockClient((request) async {
if (request.url.path.endsWith('whoAmI/api/json')) {
return http.Response(jsonEncode({'id': 'user'}), 200);
}
return http.Response('unexpected', 400);
}),
),
stager: ArtifactStagingService(),
);
final result = await session.restoreDetailed();
final result = await session.restoreDetailed();
expect(result.kind, JenkinsSessionRestoreKind.restored);
expect(result.isRestored, isTrue);
expect(session.isRestored, isTrue);
});
expect(result.kind, JenkinsSessionRestoreKind.restored);
expect(result.isRestored, isTrue);
expect(session.isRestored, isTrue);
},
);
test(
'restoreDetailed returns reauthRequired and clears session on 401',
@ -261,9 +263,7 @@ void main() {
final session = JenkinsArtifactSession(
store: store,
client: JenkinsClient(
client: MockClient(
(_) async => http.Response('Unauthorized', 401),
),
client: MockClient((_) async => http.Response('Unauthorized', 401)),
),
stager: ArtifactStagingService(),
);
@ -286,12 +286,46 @@ void main() {
'jenkins.apiToken': credentials.apiToken,
});
final store = TokenStore();
final session = JenkinsArtifactSession(
store: store,
client: JenkinsClient(
client: MockClient((_) async => http.Response('Forbidden', 403)),
),
stager: ArtifactStagingService(),
);
final result = await session.restoreDetailed();
expect(result.kind, JenkinsSessionRestoreKind.reauthRequired);
expect(result.isRestored, isFalse);
expect(session.isRestored, isFalse);
expect(await store.readSession(), isNull);
},
);
test(
'restoreDetailed returns reauthRequired and clears session on anonymous whoAmI',
() async {
FlutterSecureStorage.setMockInitialValues({
'jenkins.baseUrl': baseUrl,
'jenkins.username': credentials.username,
'jenkins.apiToken': credentials.apiToken,
});
final store = TokenStore();
final session = JenkinsArtifactSession(
store: store,
client: JenkinsClient(
client: MockClient(
(_) async => http.Response('Forbidden', 403),
(_) async => http.Response(
jsonEncode({
'anonymous': true,
'id': 'anonymous',
'fullName': 'anonymous',
}),
200,
),
),
),
stager: ArtifactStagingService(),
@ -319,7 +353,9 @@ void main() {
final session = JenkinsArtifactSession(
store: store,
client: JenkinsClient(
client: MockClient((_) async => throw const SocketException('offline')),
client: MockClient(
(_) async => throw const SocketException('offline'),
),
),
stager: ArtifactStagingService(),
);

View file

@ -468,6 +468,54 @@ void main() {
);
},
);
test('fetchCurrentUser rejects anonymous whoAmI response', () async {
final client = JenkinsClient(
client: MockClient(
(_) async => http.Response(
jsonEncode({
'anonymous': true,
'id': 'anonymous',
'fullName': 'anonymous',
}),
200,
),
),
);
expect(
() =>
client.fetchCurrentUser(baseUrl: baseUrl, credentials: credentials),
throwsA(
isA<JenkinsClientException>().having(
(e) => e.statusCode,
'statusCode',
401,
),
),
);
});
test('fetchCurrentUser rejects blank whoAmI id', () async {
final client = JenkinsClient(
client: MockClient(
(_) async =>
http.Response(jsonEncode({'anonymous': false, 'id': ' '}), 200),
),
);
expect(
() =>
client.fetchCurrentUser(baseUrl: baseUrl, credentials: credentials),
throwsA(
isA<JenkinsClientException>().having(
(e) => e.statusCode,
'statusCode',
401,
),
),
);
});
});
group('JenkinsClient.fetchRecentBuilds', () {