diff --git a/lib/core/user_provider/user_provider.dart b/lib/core/user_provider/user_provider.dart index 00e11a757cb95d447a99f2b4f624a7fd4d3a59c5..fb85104174bf17b5ba3fdf7f898726529974f869 100644 --- a/lib/core/user_provider/user_provider.dart +++ b/lib/core/user_provider/user_provider.dart @@ -32,6 +32,10 @@ class ConnectionProvider extends ChangeNotifier { static Future<String> get mergeRequestWebUrl async => await LocalStorage.get(LocalStorageKeys.currentMergeRequestWebUrlKey, ''); + Connection? get jiHuConnection { + return _connections.jiHuConnection; + } + Future<Map<String, dynamic>> addUserByToken(Token token, String baseUrl) async { try { User user = await _fetchUserByToken(baseUrl, token); @@ -155,6 +159,13 @@ class ConnectionProvider extends ChangeNotifier { notifyListeners(); } + @visibleForTesting + void injectConnectionForTest(Connection connection) { + _connections.add(connection); + changeAccount(connection); + notifyListeners(); + } + @visibleForTesting fullReset() { clearActive(notify: false); diff --git a/lib/core/user_provider/users.dart b/lib/core/user_provider/users.dart index 18d23dde7c97b01ae506930e8bb42d69aa4f8a1c..693b89599484a1c18ecb707714adcdb608abcbbf 100644 --- a/lib/core/user_provider/users.dart +++ b/lib/core/user_provider/users.dart @@ -13,6 +13,11 @@ class Connections { List<Connection> get get => _connections; + Connection? get jiHuConnection { + var matches = _connections.where((o) => o.baseUrl.isJiHu() && o.personalAccessToken == null); + return matches.isEmpty ? null : matches.first; + } + void add(Connection connection) { if (_connections.any((o) => o.personalAccessToken != null) && connection.personalAccessToken != null) throw LoginTypeSameException(); if (connection.baseUrl.isJiHu() && connection.personalAccessToken == null && _connections.any((o) => o.baseUrl.isJiHu() && o.personalAccessToken == null)) throw LoginTypeSameException(); diff --git a/lib/core/widgets/account/account_page.dart b/lib/core/widgets/account/account_page.dart index 8519731c52ba100dca68d0f0cd32478f515347df..69e2bfed285ba949e8aeb219dad41e32b0bb020e 100644 --- a/lib/core/widgets/account/account_page.dart +++ b/lib/core/widgets/account/account_page.dart @@ -192,7 +192,8 @@ class _AccountPageState extends State<AccountPage> { textTheme.titleSmall, ConnectionProvider().isUsed(item) ? const Color(0xFF87878C) : Colors.black, )), - if (ConnectionProvider().isUsed(item)) const Text('Already used', style: TextStyle(color: Color(0xFF66696D), fontSize: 10, fontWeight: FontWeight.w400)) + if (ConnectionProvider().isUsed(item)) + Text(JiHuLocalizations.dictionary().already_used, style: const TextStyle(color: Color(0xFF66696D), fontSize: 10, fontWeight: FontWeight.w400)) ], ), if (_selectedItem.displayTitle == item) diff --git a/test/core/user_provider_test.dart b/test/core/user_provider_test.dart index e5e04f04c9b9d332e47d67a69931eed01ec5d462..3979e56c079a82f7eb7b75f6fec376b822e642e4 100644 --- a/test/core/user_provider_test.dart +++ b/test/core/user_provider_test.dart @@ -34,9 +34,20 @@ void main() { await ConnectionProvider().clearActive(); }); + test('Should not get jihulab.com connection from connections when there has no jihu connection', () async { + ConnectionProvider connectionProvider = ConnectionProvider(); + expect(connectionProvider.jiHuConnection, null); + }); + + test('Should not get jihulab.com connection from connections', () async { + ConnectionProvider().reset(Tester.user()); + ConnectionProvider connectionProvider = ConnectionProvider(); + expect(connectionProvider.jiHuConnection!.userInfo.id, 9527); + }); + test('Should create User Provider object with singleton instance', () { - ConnectionProvider userProvider = ConnectionProvider(); - expect(userProvider, ConnectionProvider()); + ConnectionProvider connectionProvider = ConnectionProvider(); + expect(connectionProvider, ConnectionProvider()); }); test('Should User Provider fetch user info be succeed when response correct user info', () async { diff --git a/test/integration_tests/account_page/account_page_test.dart b/test/integration_tests/account_page/account_page_test.dart new file mode 100644 index 0000000000000000000000000000000000000000..b7f013792e428350dbe2fddd5d2490b2f725af27 --- /dev/null +++ b/test/integration_tests/account_page/account_page_test.dart @@ -0,0 +1,179 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:jihu_gitlab_app/core/local_storage.dart'; +import 'package:jihu_gitlab_app/core/net/response.dart'; +import 'package:jihu_gitlab_app/core/user_provider/user_provider.dart'; +import 'package:jihu_gitlab_app/core/widgets/account/account_page.dart'; +import 'package:jihu_gitlab_app/l10n/jihu_localizations.dart'; +import 'package:jihu_gitlab_app/modules/auth/auth.dart'; +import 'package:mockito/mockito.dart'; +import 'package:provider/provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import '../../core/net/http_request_test.mocks.dart'; +import '../../mocker/tester.dart'; +import '../../test_data/user.dart'; + +void main() { + var client = MockHttpClient(); + setUp(() async { + JiHuLocalizations.init(); + SharedPreferences.setMockInitialValues(<String, Object>{}); + await LocalStorage.init(); + LocalStorage.save('privacy-policy-agreed', true); + ConnectionProvider().fullReset(); + when(client.getWithHeader<Map<String, dynamic>>("https://jihulab.com/api/v4/user", any)).thenAnswer((_) => Future(() => Response.of<Map<String, dynamic>>(userInfo))); + when(client.getWithHeader<Map<String, dynamic>>("https://example.com/api/v4/user", any)).thenAnswer((_) => Future(() => Response.of<Map<String, dynamic>>(userInfo))); + }); + + testWidgets('Should display account page as expect', (WidgetTester tester) async { + await tester.pumpWidget(MultiProvider( + providers: [ChangeNotifierProvider(create: (context) => ConnectionProvider())], + child: const MaterialApp( + home: Scaffold(body: AccountPage()), + ), + )); + await tester.pumpAndSettle(); + expect(find.text('Add account with'), findsOneWidget); + expect(find.text('Self-Managed'), findsOneWidget); + await tester.tap(find.byIcon(Icons.arrow_drop_down)); + await tester.pumpAndSettle(); + expect(find.text('Self-Managed'), findsNWidgets(2)); + expect(find.text('jihulab.com'), findsOneWidget); + expect(find.text('gitlab.com'), findsOneWidget); + await tester.tap(find.text('jihulab.com')); + await tester.pumpAndSettle(); + expect(find.text('jihulab.com'), findsOneWidget); + await tester.tap(find.byIcon(Icons.arrow_drop_down)); + await tester.pumpAndSettle(); + expect(find.text('jihulab.com'), findsNWidgets(2)); + await tester.tap(find.text('gitlab.com')); + await tester.pumpAndSettle(); + expect(find.text('gitlab.com'), findsOneWidget); + await tester.tap(find.byIcon(Icons.arrow_drop_down)); + await tester.pumpAndSettle(); + expect(find.text('gitlab.com'), findsNWidgets(2)); + }); + + testWidgets('Should display account page when connected jihulab.com', (WidgetTester tester) async { + ConnectionProvider().reset(Tester.user()); + await tester.pumpWidget(MultiProvider( + providers: [ChangeNotifierProvider(create: (context) => ConnectionProvider())], + child: const MaterialApp( + home: Scaffold(body: AccountPage()), + ), + )); + await tester.pumpAndSettle(); + expect(find.text('tester @tester'), findsOneWidget); + await tester.tap(find.byIcon(Icons.arrow_drop_down)); + await tester.pumpAndSettle(); + expect(find.text('Self-Managed'), findsNWidgets(2)); + expect(find.text('jihulab.com'), findsNWidgets(2)); + expect(find.text('Already used'), findsOneWidget); + expect(find.text('gitlab.com'), findsOneWidget); + await tester.tap(find.text('Already used')); + await tester.pumpAndSettle(const Duration(seconds: 2)); + expect(find.text('Self-Managed'), findsOneWidget); + }); + + testWidgets('Should display account page when connected self-managed', (WidgetTester tester) async { + ConnectionProvider().reset(Tester.selfManagedUser()); + await tester.pumpWidget(MultiProvider( + providers: [ChangeNotifierProvider(create: (context) => ConnectionProvider())], + child: const MaterialApp( + home: Scaffold(body: AccountPage()), + ), + )); + await tester.pumpAndSettle(); + expect(find.text('tester @tester'), findsOneWidget); + await tester.tap(find.byIcon(Icons.arrow_drop_down)); + await tester.pumpAndSettle(); + expect(find.text('Self-Managed'), findsNWidgets(3)); + expect(find.text('jihulab.com'), findsOneWidget); + expect(find.text('Already used'), findsOneWidget); + expect(find.text('gitlab.com'), findsOneWidget); + await tester.tap(find.text('Already used')); + await tester.pumpAndSettle(const Duration(seconds: 2)); + expect(find.text('Self-Managed'), findsNWidgets(2)); + }); + + testWidgets('Should not connect account when connected self-managed', (WidgetTester tester) async { + ConnectionProvider().reset(Tester.selfManagedUser()); + await tester.pumpWidget(MultiProvider( + providers: [ChangeNotifierProvider(create: (context) => ConnectionProvider())], + child: const MaterialApp( + home: Scaffold(body: AccountPage()), + ), + )); + await tester.pumpAndSettle(); + expect(find.text('tester @tester'), findsOneWidget); + await tester.tap(find.text('Add account with')); + await tester.pumpAndSettle(const Duration(seconds: 2)); + expect(find.text('tester @tester'), findsOneWidget); + expect(find.text('Add account with'), findsOneWidget); + }); + + testWidgets('Should disconnect account', (WidgetTester tester) async { + ConnectionProvider().reset(Tester.gitLabUser()); + ConnectionProvider().injectConnectionForTest(Tester.user()); + await tester.pumpWidget(MultiProvider( + providers: [ChangeNotifierProvider(create: (context) => ConnectionProvider())], + child: const MaterialApp( + home: Scaffold(body: AccountPage()), + ), + )); + await tester.pumpAndSettle(); + await tester.drag(find.text('jihulab.com'), const Offset(-300, 0)); + await tester.pump(); + expect(find.byIcon(Icons.exit_to_app), findsOneWidget); + await tester.tap(find.byIcon(Icons.exit_to_app)); + await tester.pumpAndSettle(); + expect(find.text('jihulab.com'), findsNothing); + await tester.drag(find.text('gitlab.com'), const Offset(-300, 0)); + await tester.pump(); + expect(find.byIcon(Icons.exit_to_app), findsOneWidget); + await tester.tap(find.byIcon(Icons.exit_to_app)); + await tester.pumpAndSettle(); + expect(find.text('gitlab.com'), findsNothing); + }); + + testWidgets('Should tap to checkout account', (WidgetTester tester) async { + ConnectionProvider().reset(Tester.gitLabUser()); + ConnectionProvider().injectConnectionForTest(Tester.user()); + await tester.pumpWidget(MultiProvider( + providers: [ChangeNotifierProvider(create: (context) => ConnectionProvider())], + child: const MaterialApp( + home: Scaffold(body: AccountPage()), + ), + )); + await tester.pumpAndSettle(); + expect(find.text('tester @tester'), findsNWidgets(2)); + await tester.tap(find.text('gitlab.com')); + await tester.pumpAndSettle(); + expect(ConnectionProvider.currentBaseUrl.get, 'https://gitlab.com'); + await tester.tap(find.text('jihulab.com')); + await tester.pumpAndSettle(); + expect(ConnectionProvider.currentBaseUrl.get, 'https://jihulab.com'); + }); + + testWidgets('Should tap add account with to goto another page', (WidgetTester tester) async { + ConnectionProvider().reset(Tester.gitLabUser()); + await tester.pumpWidget(MultiProvider( + providers: [ChangeNotifierProvider(create: (context) => ConnectionProvider())], + child: MaterialApp( + routes: {SelfManagedLoginPage.routeName: (context) => const SelfManagedLoginPage()}, + home: const Scaffold(body: AccountPage()), + ), + )); + await tester.pumpAndSettle(); + await tester.tap(find.text('Add account with')); + await tester.pumpAndSettle(); + expect(find.byType(SelfManagedLoginPage), findsOneWidget); + }); + + tearDown(() { + ConnectionProvider().fullReset(); + ConnectionProvider().clearActive(); + ConnectionProvider().loggedOut(true); + }); +} diff --git a/test/mocker/tester.dart b/test/mocker/tester.dart index 4628638d889c0693e6e10b599fb71b60f5c70e0a..7bc5d0c3451c8e45e2fbcf921da7c9a40aa0afc7 100644 --- a/test/mocker/tester.dart +++ b/test/mocker/tester.dart @@ -20,4 +20,35 @@ class Tester { user.token = token(); return user; } + + static Connection gitLabUser() { + var userInfo = User.fromJson({ + "id": 9527, + "username": "tester", + "name": "tester", + "state": "active", + "two_factor_enabled": true, + "external": false, + "private_profile": true, + }); + var user = Connection(userInfo, true, BaseUrl('https://gitlab.com')); + user.token = token(); + return user; + } + + static Connection selfManagedUser() { + var userInfo = User.fromJson({ + "id": 9527, + "username": "tester", + "name": "tester", + "state": "active", + "two_factor_enabled": true, + "external": false, + "private_profile": true, + }); + var user = Connection(userInfo, true, BaseUrl('https://gitlab.com')); + user.personalAccessToken = 'access_token'; + user.isSelfManaged = true; + return user; + } }