208 lines
6.2 KiB
Dart
208 lines
6.2 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
import 'package:appsok/src/features/settings/settings_page.dart';
|
|
import 'package:appsok/src/theme/app_theme.dart';
|
|
|
|
Widget _wrap(Widget child) => MaterialApp(
|
|
theme: AppTheme.light(),
|
|
home: Scaffold(body: child),
|
|
);
|
|
|
|
void main() {
|
|
group('SettingsPage web login', () {
|
|
testWidgets('disables web login for invalid Jenkins URL', (tester) async {
|
|
await tester.pumpWidget(_wrap(const SettingsPage()));
|
|
|
|
final button = tester.widget<ElevatedButton>(
|
|
find.byKey(const ValueKey('jenkins-web-login-button')),
|
|
);
|
|
expect(button.onPressed, isNull);
|
|
|
|
// Empty URL — still disabled
|
|
await tester.enterText(find.byType(TextField).first, '');
|
|
await tester.pump();
|
|
final buttonAfterEmpty = tester.widget<ElevatedButton>(
|
|
find.byKey(const ValueKey('jenkins-web-login-button')),
|
|
);
|
|
expect(buttonAfterEmpty.onPressed, isNull);
|
|
|
|
// Non-URL text — still disabled
|
|
await tester.enterText(find.byType(TextField).first, 'not-a-url');
|
|
await tester.pump();
|
|
final buttonAfterInvalid = tester.widget<ElevatedButton>(
|
|
find.byKey(const ValueKey('jenkins-web-login-button')),
|
|
);
|
|
expect(buttonAfterInvalid.onPressed, isNull);
|
|
});
|
|
|
|
testWidgets('calls web login launcher with normalized base URL', (
|
|
tester,
|
|
) async {
|
|
String? capturedUrl;
|
|
await tester.pumpWidget(
|
|
_wrap(
|
|
SettingsPage(
|
|
webLoginLauncher: (url) async {
|
|
capturedUrl = url;
|
|
return null;
|
|
},
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.enterText(
|
|
find.byType(TextField).first,
|
|
'https://jenkins.example.com',
|
|
);
|
|
await tester.pump();
|
|
|
|
final button = tester.widget<ElevatedButton>(
|
|
find.byKey(const ValueKey('jenkins-web-login-button')),
|
|
);
|
|
expect(button.onPressed, isNotNull);
|
|
|
|
await tester.tap(find.byKey(const ValueKey('jenkins-web-login-button')));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(capturedUrl, 'https://jenkins.example.com');
|
|
});
|
|
|
|
testWidgets('shows completed login user without token text', (
|
|
tester,
|
|
) async {
|
|
await tester.pumpWidget(
|
|
_wrap(
|
|
SettingsPage(
|
|
webLoginLauncher: (_) async => const JenkinsWebLoginResult(
|
|
username: 'toki',
|
|
displayName: 'Toki Lab',
|
|
apiToken: 'issued-token',
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.enterText(
|
|
find.byType(TextField).first,
|
|
'https://jenkins.example.com',
|
|
);
|
|
await tester.pump();
|
|
|
|
await tester.tap(find.byKey(const ValueKey('jenkins-web-login-button')));
|
|
await tester.pumpAndSettle();
|
|
|
|
// Result label must show displayName
|
|
expect(find.byKey(const ValueKey('web-login-result')), findsOneWidget);
|
|
expect(find.textContaining('Toki Lab'), findsOneWidget);
|
|
// No token-like text should appear
|
|
expect(find.textContaining('token'), findsNothing);
|
|
expect(find.textContaining('apiToken'), findsNothing);
|
|
});
|
|
|
|
testWidgets('shows token issue error when web login returns no apiToken', (
|
|
tester,
|
|
) async {
|
|
await tester.pumpWidget(
|
|
_wrap(
|
|
SettingsPage(
|
|
webLoginLauncher: (_) async => const JenkinsWebLoginResult(
|
|
username: 'toki',
|
|
displayName: 'Toki Lab',
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.enterText(
|
|
find.byType(TextField).first,
|
|
'https://jenkins.example.com',
|
|
);
|
|
await tester.pump();
|
|
|
|
await tester.tap(find.byKey(const ValueKey('jenkins-web-login-button')));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.byKey(const ValueKey('web-login-result')), findsNothing);
|
|
expect(find.textContaining('API token 발급에 실패했습니다'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('clears stored credential through sessionClearer', (
|
|
tester,
|
|
) async {
|
|
var clearCalled = false;
|
|
|
|
await tester.pumpWidget(
|
|
_wrap(
|
|
SettingsPage(
|
|
sessionClearer: () async {
|
|
clearCalled = true;
|
|
},
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.tap(
|
|
find.byKey(const ValueKey('jenkins-clear-session-button')),
|
|
);
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(clearCalled, isTrue);
|
|
expect(
|
|
find.byKey(const ValueKey('session-cleared-label')),
|
|
findsOneWidget,
|
|
);
|
|
expect(find.byKey(const ValueKey('session-clear-error')), findsNothing);
|
|
});
|
|
});
|
|
|
|
group('SettingsPage base URL change clears transient state', () {
|
|
testWidgets(
|
|
'SettingsPage clears transient login/save/clear state when base url changes',
|
|
(tester) async {
|
|
await tester.pumpWidget(
|
|
_wrap(
|
|
SettingsPage(
|
|
webLoginLauncher: (url) async => const JenkinsWebLoginResult(
|
|
username: 'toki',
|
|
displayName: 'Toki Lab',
|
|
apiToken: 'issued-token',
|
|
),
|
|
tokenSaver: (baseUrl, username, apiToken) async => true,
|
|
onSessionSaved: () {},
|
|
),
|
|
),
|
|
);
|
|
|
|
// Enter a valid URL and trigger web login so token-saved-label appears.
|
|
await tester.enterText(
|
|
find.byType(TextField).first,
|
|
'https://jenkins.example.com',
|
|
);
|
|
await tester.pump();
|
|
|
|
await tester.tap(
|
|
find.byKey(const ValueKey('jenkins-web-login-button')),
|
|
);
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.byKey(const ValueKey('token-saved-label')), findsOneWidget);
|
|
|
|
// Change URL — all transient labels must be cleared.
|
|
await tester.enterText(
|
|
find.byType(TextField).first,
|
|
'https://jenkins2.example.com',
|
|
);
|
|
await tester.pump();
|
|
|
|
expect(find.byKey(const ValueKey('token-saved-label')), findsNothing);
|
|
expect(find.byKey(const ValueKey('web-login-result')), findsNothing);
|
|
expect(find.byKey(const ValueKey('token-save-error')), findsNothing);
|
|
expect(
|
|
find.byKey(const ValueKey('session-cleared-label')),
|
|
findsNothing,
|
|
);
|
|
},
|
|
);
|
|
});
|
|
}
|