From 9e23bad9fbcf68ba7a138f5ca0dfd05970ced067 Mon Sep 17 00:00:00 2001 From: Owais Jamil Date: Tue, 5 May 2026 11:51:42 -0500 Subject: [PATCH] chore: rm integration tests --- .../auth_token_recovery_flow_test.dart | 252 ------------------ ...oauth_callback_https_integration_test.dart | 67 ----- ios/Podfile.lock | 6 - justfile | 10 - pubspec.lock | 39 --- pubspec.yaml | 2 - 6 files changed, 376 deletions(-) delete mode 100644 integration_test/auth_token_recovery_flow_test.dart delete mode 100644 integration_test/oauth_callback_https_integration_test.dart diff --git a/integration_test/auth_token_recovery_flow_test.dart b/integration_test/auth_token_recovery_flow_test.dart deleted file mode 100644 index d25a577..0000000 --- a/integration_test/auth_token_recovery_flow_test.dart +++ /dev/null @@ -1,252 +0,0 @@ -import 'dart:async'; - -import 'package:atproto_core/atproto_core.dart'; -import 'package:bloc_test/bloc_test.dart'; -import 'package:bluesky/app_bsky_actor_defs.dart'; -import 'package:bluesky/app_bsky_feed_defs.dart'; -import 'package:drift/native.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:integration_test/integration_test.dart'; -import 'package:lazurite/core/database/app_database.dart'; -import 'package:lazurite/core/theme/app_theme.dart'; -import 'package:lazurite/core/theme/feed_layout.dart'; -import 'package:lazurite/features/auth/bloc/auth_bloc.dart'; -import 'package:lazurite/features/auth/data/models/auth_models.dart'; -import 'package:lazurite/features/connectivity/cubit/connectivity_cubit.dart'; -import 'package:lazurite/features/feed/cubit/feed_preferences_cubit.dart'; -import 'package:lazurite/features/feed/cubit/post_action_cache.dart'; -import 'package:lazurite/features/feed/cubit/saved_posts_cubit.dart'; -import 'package:lazurite/features/feed/data/feed_repository.dart'; -import 'package:lazurite/features/feed/data/post_action_repository.dart'; -import 'package:lazurite/features/feed/presentation/home_feed_screen.dart'; -import 'package:lazurite/features/feed/presentation/widgets/post_card_with_actions.dart'; -import 'package:lazurite/features/settings/bloc/settings_cubit.dart'; -import 'package:lazurite/features/settings/bloc/settings_state.dart'; -import 'package:mocktail/mocktail.dart'; - -class MockSettingsCubit extends MockCubit implements SettingsCubit {} - -class MockFeedPreferencesCubit extends MockCubit implements FeedPreferencesCubit {} - -class MockConnectivityCubit extends MockCubit implements ConnectivityCubit {} - -class MockAuthBloc extends MockBloc implements AuthBloc {} - -class MockSavedPostsCubit extends MockCubit implements SavedPostsCubit {} - -class MockPostActionRepository extends Mock implements PostActionRepository {} - -class _FakeFeedData { - _FakeFeedData({required this.feed, this.cursor}); - - final List feed; - final String? cursor; -} - -class _FakeFeedResponse { - _FakeFeedResponse(this.data); - - final _FakeFeedData data; -} - -class _HandlerFeedApi { - _HandlerFeedApi({required this.getTimelineHandler}); - - final Future<_FakeFeedResponse> Function({String? cursor, int? limit, Map? headers}) - getTimelineHandler; - - Future<_FakeFeedResponse> getTimeline({String? cursor, int? limit, Map? $headers}) { - return getTimelineHandler(cursor: cursor, limit: limit, headers: $headers); - } -} - -class _FakeBluesky { - _FakeBluesky(this.feed); - - final dynamic feed; -} - -void main() { - IntegrationTestWidgetsFlutterBinding.ensureInitialized(); - - const homeFeedState = FeedPreferencesState.loaded( - feeds: [ - SavedFeed( - id: 'timeline', - type: SavedFeedType.knownValue(data: KnownSavedFeedType.timeline), - value: 'timeline', - pinned: true, - ), - ], - ); - - SettingsState settingsState(FeedLayout architecture) => SettingsState( - themePalette: AppThemePalette.oxocarbon, - themeVariant: AppThemeVariant.dark, - useSystemTheme: false, - feedLayout: architecture, - ); - - testWidgets('home feed recovers from expired token unauthorized response', (tester) async { - final database = AppDatabase(executor: NativeDatabase.memory()); - addTearDown(database.close); - - final feedPreferencesCubit = MockFeedPreferencesCubit(); - final connectivityCubit = MockConnectivityCubit(); - final settingsCubit = MockSettingsCubit(); - final authBloc = MockAuthBloc(); - final savedPostsCubit = MockSavedPostsCubit(); - final postActionRepository = MockPostActionRepository(); - - when(() => feedPreferencesCubit.state).thenReturn(homeFeedState); - whenListen(feedPreferencesCubit, const Stream.empty(), initialState: homeFeedState); - - when(() => connectivityCubit.state).thenReturn(const ConnectivityState.online()); - whenListen( - connectivityCubit, - const Stream.empty(), - initialState: const ConnectivityState.online(), - ); - - when(() => settingsCubit.state).thenReturn(settingsState(FeedLayout.card)); - whenListen(settingsCubit, const Stream.empty(), initialState: settingsState(FeedLayout.card)); - - const authState = AuthState.authenticated( - AuthTokens( - accessToken: 'access-token', - refreshToken: 'refresh-token', - did: 'did:plc:test', - handle: 'test.bsky.social', - ), - ); - when(() => authBloc.state).thenReturn(authState); - whenListen(authBloc, const Stream.empty(), initialState: authState); - - const savedPostsState = SavedPostsState(status: SavedPostsStatus.loaded); - when(() => savedPostsCubit.state).thenReturn(savedPostsState); - whenListen(savedPostsCubit, const Stream.empty(), initialState: savedPostsState); - - var primaryTimelineCalls = 0; - var fallbackTimelineCalls = 0; - var authRecoveryCalls = 0; - - final primaryFeedApi = _HandlerFeedApi( - getTimelineHandler: ({String? cursor, int? limit, Map? headers}) async { - primaryTimelineCalls += 1; - throw _unauthorizedException('app.bsky.feed.getTimeline'); - }, - ); - - final fallbackFeedApi = _HandlerFeedApi( - getTimelineHandler: ({String? cursor, int? limit, Map? headers}) async { - fallbackTimelineCalls += 1; - return _FakeFeedResponse(_FakeFeedData(feed: [_post(1)], cursor: null)); - }, - ); - - final repository = FeedRepository( - bluesky: _FakeBluesky(primaryFeedApi), - database: database, - accountDid: 'did:plc:test', - onUnauthorized: () async { - authRecoveryCalls += 1; - return _freshTokens(); - }, - blueskyClientFactory: (_) => _FakeBluesky(fallbackFeedApi), - ); - - await tester.pumpWidget( - MaterialApp( - home: MultiRepositoryProvider( - providers: [ - RepositoryProvider.value(value: repository), - RepositoryProvider.value(value: postActionRepository), - RepositoryProvider(create: (_) => PostActionCache()), - ], - child: MultiBlocProvider( - providers: [ - BlocProvider.value(value: authBloc), - BlocProvider.value(value: settingsCubit), - BlocProvider.value(value: feedPreferencesCubit), - BlocProvider.value(value: connectivityCubit), - BlocProvider.value(value: savedPostsCubit), - ], - child: const HomeFeedScreen(), - ), - ), - ), - ); - - await tester.pump(); - - await _pumpUntil( - tester, - condition: () => find.byType(PostCardWithActions).evaluate().isNotEmpty, - timeout: const Duration(seconds: 5), - ); - - expect(primaryTimelineCalls, 1); - expect(authRecoveryCalls, 1); - expect(fallbackTimelineCalls, 1); - expect(find.byType(PostCardWithActions), findsOneWidget); - expect(find.textContaining('Failed to load feed'), findsNothing); - }); -} - -Future _pumpUntil( - WidgetTester tester, { - required bool Function() condition, - Duration timeout = const Duration(seconds: 3), -}) async { - final deadline = DateTime.now().add(timeout); - while (!condition()) { - if (DateTime.now().isAfter(deadline)) { - fail('Timed out waiting for condition in integration test'); - } - await tester.pump(const Duration(milliseconds: 50)); - } -} - -FeedViewPost _post(int index) { - final timestamp = DateTime.utc(2026, 5, 4, 12).subtract(Duration(minutes: index)); - final did = 'did:plc:author$index'; - return FeedViewPost( - post: PostView( - uri: AtUri('at://$did/app.bsky.feed.post/$index'), - cid: 'cid-$index', - author: ProfileViewBasic(did: did, handle: 'author$index.bsky.social'), - record: { - r'$type': 'app.bsky.feed.post', - 'text': 'Recovered post $index', - 'createdAt': timestamp.toIso8601String(), - }, - indexedAt: timestamp, - ), - ); -} - -AuthTokens _freshTokens() { - final now = DateTime.now().toUtc(); - return AuthTokens( - accessToken: 'fresh-access-token', - refreshToken: 'fresh-refresh-token', - expiresAt: now.add(const Duration(hours: 1)), - did: 'did:plc:test', - handle: 'test.bsky.social', - service: 'bsky.social', - ); -} - -UnauthorizedException _unauthorizedException(String methodId) { - return UnauthorizedException( - XRPCResponse( - headers: const {}, - status: HttpStatus.unauthorized, - request: XRPCRequest(method: HttpMethod.get, url: Uri.https('bsky.social', '/xrpc/$methodId')), - rateLimit: RateLimit.unlimited(), - data: const XRPCError(error: 'Unauthorized', message: 'exp claim timestamp check failed'), - ), - ); -} diff --git a/integration_test/oauth_callback_https_integration_test.dart b/integration_test/oauth_callback_https_integration_test.dart deleted file mode 100644 index 8d85d13..0000000 --- a/integration_test/oauth_callback_https_integration_test.dart +++ /dev/null @@ -1,67 +0,0 @@ -import 'package:bloc_test/bloc_test.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:go_router/go_router.dart'; -import 'package:integration_test/integration_test.dart'; -import 'package:lazurite/features/auth/bloc/auth_bloc.dart'; -import 'package:lazurite/features/auth/presentation/oauth_callback_screen.dart'; -import 'package:mocktail/mocktail.dart'; - -class MockAuthBloc extends MockBloc implements AuthBloc {} - -void main() { - IntegrationTestWidgetsFlutterBinding.ensureInitialized(); - - setUpAll(() { - registerFallbackValue(Uri.parse('https://example.com/oauth/callback')); - }); - - testWidgets('forwards HTTPS callback URI query params and returns to login', (tester) async { - final authBloc = MockAuthBloc(); - when(() => authBloc.state).thenReturn(const AuthState.unauthenticated()); - whenListen(authBloc, const Stream.empty(), initialState: const AuthState.unauthenticated()); - - Uri? capturedUri; - when(() => authBloc.handleOAuthRedirectUri(any())).thenAnswer((invocation) async { - capturedUri = invocation.positionalArguments.first as Uri; - return true; - }); - - final router = GoRouter( - initialLocation: OAuthCallbackScreen.routePath, - routes: [ - GoRoute( - path: OAuthCallbackScreen.routePath, - builder: (context, state) => OAuthCallbackScreen( - callbackUri: Uri.parse( - 'https://lazurite.stormlightlabs.org/oauth/callback?code=abc&state=xyz&iss=https%3A%2F%2Fbsky.social', - ), - ), - ), - GoRoute( - path: '/login', - builder: (context, state) => const Scaffold(body: Text('login')), - ), - ], - ); - - await tester.pumpWidget( - BlocProvider.value( - value: authBloc, - child: MaterialApp.router(routerConfig: router), - ), - ); - await tester.pumpAndSettle(); - - verify(() => authBloc.handleOAuthRedirectUri(any())).called(1); - expect(capturedUri, isNotNull); - expect(capturedUri!.scheme, equals('https')); - expect(capturedUri!.host, equals('lazurite.stormlightlabs.org')); - expect(capturedUri!.path, equals('/oauth/callback')); - expect(capturedUri!.queryParameters['code'], equals('abc')); - expect(capturedUri!.queryParameters['state'], equals('xyz')); - expect(capturedUri!.queryParameters['iss'], equals('https://bsky.social')); - expect(find.text('login'), findsOneWidget); - }); -} diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 052c213..8e3c79c 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -96,8 +96,6 @@ PODS: - GoogleUtilities/Privacy - image_picker_ios (0.0.1): - Flutter - - integration_test (0.0.1): - - Flutter - nanopb (3.30910.0): - nanopb/decode (= 3.30910.0) - nanopb/encode (= 3.30910.0) @@ -185,7 +183,6 @@ DEPENDENCIES: - flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`) - gal (from `.symlinks/plugins/gal/darwin`) - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) - - integration_test (from `.symlinks/plugins/integration_test/ios`) - objectbox_flutter_libs (from `.symlinks/plugins/objectbox_flutter_libs/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) @@ -236,8 +233,6 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/gal/darwin" image_picker_ios: :path: ".symlinks/plugins/image_picker_ios/ios" - integration_test: - :path: ".symlinks/plugins/integration_test/ios" objectbox_flutter_libs: :path: ".symlinks/plugins/objectbox_flutter_libs/ios" package_info_plus: @@ -281,7 +276,6 @@ SPEC CHECKSUMS: GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7 GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1 image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326 - integration_test: 4a889634ef21a45d28d50d622cf412dc6d9f586e nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 ObjectBox: eccb95ea2054c39d81dfa2d4ccc5f1e31187228a objectbox_flutter_libs: ed1510f71602e4a0d3f2a721324e468d066fdbb9 diff --git a/justfile b/justfile index feadc4a..38e0283 100644 --- a/justfile +++ b/justfile @@ -29,16 +29,6 @@ test *paths='': just objectbox-check flutter test {{ paths }} --fail-fast --timeout=120s -# Run end-to-end style integration tests from integration_test/ -e2e: - just objectbox-check - flutter test integration_test --reporter=failures-only --fail-fast --timeout=180s - -# Run one specific end-to-end test file -e2e-file path: - just objectbox-check - flutter test {{ path }} --reporter=failures-only --fail-fast --timeout=180s - generate: flutter pub run build_runner build --delete-conflicting-outputs diff --git a/pubspec.lock b/pubspec.lock index b3e3335..f052e0f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -590,11 +590,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.4.1" - flutter_driver: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" flutter_lints: dependency: "direct dev" description: @@ -693,11 +688,6 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.0" - fuchsia_remote_debug_protocol: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" gal: dependency: "direct main" description: @@ -850,11 +840,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.2.2" - integration_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" intl: dependency: "direct main" description: @@ -1263,14 +1248,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.2" - process: - dependency: transitive - description: - name: process - sha256: c6248e4526673988586e8c00bb22a49210c258dc91df5227d5da9748ecf79744 - url: "https://pub.dev" - source: hosted - version: "5.0.5" provider: dependency: "direct main" description: @@ -1516,14 +1493,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.1" - sync_http: - dependency: transitive - description: - name: sync_http - sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961" - url: "https://pub.dev" - source: hosted - version: "0.3.1" synchronized: dependency: transitive description: @@ -1788,14 +1757,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.3" - webdriver: - dependency: transitive - description: - name: webdriver - sha256: "2f3a14ca026957870cfd9c635b83507e0e51d8091568e90129fbf805aba7cade" - url: "https://pub.dev" - source: hosted - version: "3.1.0" webkit_inspection_protocol: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index ade17f4..0971521 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -61,8 +61,6 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - integration_test: - sdk: flutter flutter_lints: ^6.0.0 drift_dev: ^2.24.0 build_runner: ^2.4.15 -- 2.51.2