From c5111cfd9c09c1803cee0f9baab8171d4e914222 Mon Sep 17 00:00:00 2001 From: Andrew Amin Date: Fri, 6 Jun 2025 23:04:44 +0300 Subject: [PATCH 01/15] feat: add instabug_screen_render_manager which control screen render , add instabug_widget_binding_observer which manage app life cycle, refactor ui trace related apis --- .../gradle/wrapper/gradle-wrapper.properties | 1 - .../com/instabug/flutter/modules/ApmApi.java | 17 +- example/ios/Podfile.lock | 2 +- example/ios/Runner/AppDelegate.swift | 2 +- example/lib/main.dart | 6 + example/lib/src/components/animated_box.dart | 80 +++++ example/lib/src/components/screen_render.dart | 31 ++ example/lib/src/screens/apm_page.dart | 1 + .../lib/src/screens/screen_render_page.dart | 44 +++ example/pubspec.lock | 34 +- ios/Classes/Modules/ApmApi.m | 10 + lib/instabug_flutter.dart | 2 +- lib/src/models/InstabugFrameData.dart | 9 + lib/src/models/InstabugScreenRenderData.dart | 32 ++ lib/src/modules/apm.dart | 19 ++ lib/src/modules/instabug.dart | 5 + .../utils/instabug_navigator_observer.dart | 11 +- .../screen_loading_manager.dart | 12 +- .../instabug_frame_tracking.dart | 43 +++ .../instabug_screen_render_manager.dart | 313 ++++++++++++++++++ .../instabug_widget_binding_observer.dart | 55 +++ .../flags_config.dart | 3 + .../route_matcher.dart | 0 .../ui_trace.dart | 2 +- pigeons/apm.api.dart | 6 + test/route_matcher_test.dart | 2 +- .../screen_loading_manager_test.dart | 5 +- test/utils/screen_loading/ui_trace_test.dart | 2 +- 28 files changed, 716 insertions(+), 33 deletions(-) create mode 100644 example/lib/src/components/animated_box.dart create mode 100644 example/lib/src/components/screen_render.dart create mode 100644 example/lib/src/screens/screen_render_page.dart create mode 100644 lib/src/models/InstabugFrameData.dart create mode 100644 lib/src/models/InstabugScreenRenderData.dart create mode 100644 lib/src/utils/screen_rendering/instabug_frame_tracking.dart create mode 100644 lib/src/utils/screen_rendering/instabug_screen_render_manager.dart create mode 100644 lib/src/utils/screen_rendering/instabug_widget_binding_observer.dart rename lib/src/utils/{screen_loading => ui_trace}/flags_config.dart (83%) rename lib/src/utils/{screen_loading => ui_trace}/route_matcher.dart (100%) rename lib/src/utils/{screen_loading => ui_trace}/ui_trace.dart (94%) diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index ca8c529fc..5ca64aa4c 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,3 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-bin.zip diff --git a/android/src/main/java/com/instabug/flutter/modules/ApmApi.java b/android/src/main/java/com/instabug/flutter/modules/ApmApi.java index 496b90eaf..c32a243bb 100644 --- a/android/src/main/java/com/instabug/flutter/modules/ApmApi.java +++ b/android/src/main/java/com/instabug/flutter/modules/ApmApi.java @@ -345,7 +345,6 @@ public void isEndScreenLoadingEnabled(@NonNull ApmPigeon.Result result) isScreenLoadingEnabled(result); } - @Override public void isEnabled(@NonNull ApmPigeon.Result result) { try { @@ -385,4 +384,20 @@ public void setScreenLoadingEnabled(@NonNull Boolean isEnabled) { e.printStackTrace(); } } + + + @Override + public void isScreenRenderEnabled(@NonNull ApmPigeon.Result result) { + try { + result.success(true); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void deviceRefreshRate(@NonNull ApmPigeon.Result result) { + result.success(60.0); + } + } diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 484d0ae99..aee5aad67 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -30,4 +30,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 8f7552fd115ace1988c3db54a69e4a123c448f84 -COCOAPODS: 1.16.2 +COCOAPODS: 1.15.2 diff --git a/example/ios/Runner/AppDelegate.swift b/example/ios/Runner/AppDelegate.swift index 11f416a26..b8991863b 100644 --- a/example/ios/Runner/AppDelegate.swift +++ b/example/ios/Runner/AppDelegate.swift @@ -1,7 +1,7 @@ import UIKit import Flutter -@UIApplicationMain +@main @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, diff --git a/example/lib/main.dart b/example/lib/main.dart index 91b0a67e7..40fc4f4e1 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -30,6 +30,8 @@ part 'src/screens/screen_loading_page.dart'; part 'src/screens/my_home_page.dart'; +part 'src/screens/screen_render_page.dart'; + part 'src/components/fatal_crashes_content.dart'; part 'src/components/non_fatal_crashes_content.dart'; @@ -42,6 +44,10 @@ part 'src/components/traces_content.dart'; part 'src/components/flows_content.dart'; +part 'src/components/screen_render.dart'; + +part 'src/components/animated_box.dart'; + void main() { runZonedGuarded( () { diff --git a/example/lib/src/components/animated_box.dart b/example/lib/src/components/animated_box.dart new file mode 100644 index 000000000..4eec36bcd --- /dev/null +++ b/example/lib/src/components/animated_box.dart @@ -0,0 +1,80 @@ +part of '../../main.dart'; + +class AnimatedBox extends StatefulWidget { + const AnimatedBox({Key? key}) : super(key: key); + + @override + _AnimatedBoxState createState() => _AnimatedBoxState(); +} + +class _AnimatedBoxState extends State + with SingleTickerProviderStateMixin { + late AnimationController _controller; + late Animation _animation; + + @override + void initState() { + super.initState(); + _controller = AnimationController( + duration: const Duration(minutes: 1 , seconds: 40), + vsync: this, + ); + _animation = Tween(begin: 0, end: 100).animate(_controller) + ..addListener(() { + setState(() { + // The state that has changed here is the animation value + }); + }); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + void _startAnimation() { + _controller.forward(); + } + + void _stopAnimation() { + _controller.stop(); + } + + void _resetAnimation() { + _controller.reset(); + } + + @override + Widget build(BuildContext context) { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + RotationTransition( + turns: _animation, + child: const FlutterLogo(size: 100), + ), + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + onPressed: () => _startAnimation(), + child: const Text('Start'), + ), + const SizedBox(width: 20), + ElevatedButton( + onPressed: () => _stopAnimation(), + child: const Text('Stop'), + ), + const SizedBox(width: 20), + ElevatedButton( + onPressed: () => _resetAnimation(), + child: const Text('reset'), + ), + ], + ), + ], + ); + } +} diff --git a/example/lib/src/components/screen_render.dart b/example/lib/src/components/screen_render.dart new file mode 100644 index 000000000..2ab70282f --- /dev/null +++ b/example/lib/src/components/screen_render.dart @@ -0,0 +1,31 @@ +part of '../../main.dart'; + +class ScreenRender extends StatelessWidget { + const ScreenRender({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + const SectionTitle('Screen Render'), + InstabugButton( + text: 'Screen Render', + onPressed: () => _navigateToScreenRender(context), + ), + ], + ); + } + + _navigateToScreenRender(BuildContext context) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const InstabugCaptureScreenLoading( + screenName: ScreenRenderPage.screenName, + child: ScreenRenderPage(), + ), + settings: const RouteSettings(name: ScreenRenderPage.screenName), + ), + ); + } +} diff --git a/example/lib/src/screens/apm_page.dart b/example/lib/src/screens/apm_page.dart index 798e906fa..153b23b5c 100644 --- a/example/lib/src/screens/apm_page.dart +++ b/example/lib/src/screens/apm_page.dart @@ -51,6 +51,7 @@ class _ApmPageState extends State { SizedBox.fromSize( size: const Size.fromHeight(12), ), + ScreenRender(), ], ); } diff --git a/example/lib/src/screens/screen_render_page.dart b/example/lib/src/screens/screen_render_page.dart new file mode 100644 index 000000000..924eefab2 --- /dev/null +++ b/example/lib/src/screens/screen_render_page.dart @@ -0,0 +1,44 @@ +part of '../../main.dart'; + +class ScreenRenderPage extends StatelessWidget { + const ScreenRenderPage({Key? key}) : super(key: key); + static const String screenName = "/screenRenderPageRoute"; + + @override + Widget build(BuildContext context) { + return Page(title: 'Screen Render', children: [ + + const AnimatedBox(), + SizedBox.fromSize(size: const Size.fromHeight(50),), + InstabugButton( + text: 'Perform Frozen Frame', + onPressed: () => _simulateHeavyComputation(), + ), + InstabugButton( + text: 'Monitored Complex Page', + onPressed: () => _navigateToComplexPage(context), + ), + ]); + } + + void _navigateToComplexPage(BuildContext context) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const ComplexPage.monitored(), + settings: const RouteSettings( + name: ComplexPage.screenName, + ), + ), + ); + } + + // Simulates a computationally expensive task + void _simulateHeavyComputation() { + final startTime = DateTime.now(); + // Block the UI thread for ~500ms + while (DateTime.now().difference(startTime).inMilliseconds <= 1000) { + // Busy waiting (not recommended in real apps) + } + } +} diff --git a/example/pubspec.lock b/example/pubspec.lock index 93971dc8b..ba4cc0a6d 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -37,10 +37,10 @@ packages: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.19.0" fake_async: dependency: transitive description: @@ -120,18 +120,18 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" + sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" url: "https://pub.dev" source: hosted - version: "10.0.5" + version: "10.0.7" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" + sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.8" leak_tracker_testing: dependency: transitive description: @@ -200,7 +200,7 @@ packages: dependency: transitive description: flutter source: sdk - version: "0.0.99" + version: "0.0.0" source_span: dependency: transitive description: @@ -213,10 +213,10 @@ packages: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.12.0" stream_channel: dependency: transitive description: @@ -229,10 +229,10 @@ packages: dependency: transitive description: name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.3.0" sync_http: dependency: transitive description: @@ -253,10 +253,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" + sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" url: "https://pub.dev" source: hosted - version: "0.7.2" + version: "0.7.3" typed_data: dependency: transitive description: @@ -277,18 +277,18 @@ packages: dependency: transitive description: name: vm_service - sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" + sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b url: "https://pub.dev" source: hosted - version: "14.2.5" + version: "14.3.0" webdriver: dependency: transitive description: name: webdriver - sha256: "003d7da9519e1e5f329422b36c4dcdf18d7d2978d1ba099ea4e45ba490ed845e" + sha256: "3d773670966f02a646319410766d3b5e1037efb7f07cc68f844d5e06cd4d61c8" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.4" sdks: dart: ">=3.5.0 <4.0.0" flutter: ">=3.18.0-18.0.pre.54" diff --git a/ios/Classes/Modules/ApmApi.m b/ios/Classes/Modules/ApmApi.m index 782765ad7..c27f953b2 100644 --- a/ios/Classes/Modules/ApmApi.m +++ b/ios/Classes/Modules/ApmApi.m @@ -197,5 +197,15 @@ - (void)isEndScreenLoadingEnabledWithCompletion:(nonnull void (^)(NSNumber * _Nu completion(isEnabledNumber, nil); } +- (void)isScreenRenderEnabledWithCompletion:(void (^)(NSNumber * _Nullable, FlutterError * _Nullable))completion{ + BOOL isScreenRenderEnabled = YES; + NSNumber *isEnabledNumber = @(isScreenRenderEnabled); + completion(isEnabledNumber, nil); +} + +- (void)deviceRefreshRateWithCompletion:(void (^)(NSNumber * _Nullable, FlutterError * _Nullable))completion{ + completion(@60 , nil); +} + @end diff --git a/lib/instabug_flutter.dart b/lib/instabug_flutter.dart index e38545897..edf703ba3 100644 --- a/lib/instabug_flutter.dart +++ b/lib/instabug_flutter.dart @@ -20,5 +20,5 @@ export 'src/modules/surveys.dart'; // Utils export 'src/utils/instabug_navigator_observer.dart'; export 'src/utils/screen_loading/instabug_capture_screen_loading.dart'; -export 'src/utils/screen_loading/route_matcher.dart'; +export 'src/utils/ui_trace/route_matcher.dart'; export 'src/utils/screen_name_masker.dart' show ScreenNameMaskingCallback; diff --git a/lib/src/models/InstabugFrameData.dart b/lib/src/models/InstabugFrameData.dart new file mode 100644 index 000000000..d7db5a01d --- /dev/null +++ b/lib/src/models/InstabugFrameData.dart @@ -0,0 +1,9 @@ +class InstabugFrameData{ + int startTimeTimestamp; + int duration; + + InstabugFrameData(this.startTimeTimestamp, this.duration); + + @override + String toString() => "startTime: $startTimeTimestamp, duration: $duration"; +} \ No newline at end of file diff --git a/lib/src/models/InstabugScreenRenderData.dart b/lib/src/models/InstabugScreenRenderData.dart new file mode 100644 index 000000000..b55f464f1 --- /dev/null +++ b/lib/src/models/InstabugScreenRenderData.dart @@ -0,0 +1,32 @@ +import 'package:instabug_flutter/src/models/InstabugFrameData.dart'; + +class InstabugScreenRenderData { + int traceId; + int totalSlowFramesDurations; + int totalFrozenFramesDurations; + List frameData; + + InstabugScreenRenderData({ + this.totalSlowFramesDurations = 0, + this.totalFrozenFramesDurations = 0, + required this.frameData , + this.traceId = -1, + }); + + bool get isEmpty => traceId == -1; + + bool get isNotEmpty => !isEmpty; + + void clear() { + traceId = -1; + totalFrozenFramesDurations = 0; + totalSlowFramesDurations = 0; + frameData.clear(); + } + + @override + String toString() => '\nTraceId $traceId\n' + 'TotalSlowFramesDurations: $totalSlowFramesDurations\n' + 'TotalFrozenFramesDurations $totalFrozenFramesDurations\n' + 'FrameData[\n${frameData.map((element) => '\t\n$element')}\n]'; +} diff --git a/lib/src/modules/apm.dart b/lib/src/modules/apm.dart index a9f6e0a7c..a37d8c118 100644 --- a/lib/src/modules/apm.dart +++ b/lib/src/modules/apm.dart @@ -346,4 +346,23 @@ class APM { }) { return ScreenLoadingManager.wrapRoutes(routes, exclude: exclude); } + + /// Returns a Future indicating whether the screen + /// render is enabled. + /// + /// Returns: + /// A Future is being returned. + @internal + static Future isScreenRenderEnabled() async{ + return _host.isScreenRenderEnabled(); + } + + /// Retrieve the device refresh rate from native side . + /// + /// Returns: + /// A Future that represent the refresh rate. + @internal + static Future getDeviceRefreshRate(){ + return _host.deviceRefreshRate(); + } } diff --git a/lib/src/modules/instabug.dart b/lib/src/modules/instabug.dart index 6bba8ed1f..96b40876d 100644 --- a/lib/src/modules/instabug.dart +++ b/lib/src/modules/instabug.dart @@ -21,6 +21,8 @@ import 'package:instabug_flutter/src/utils/feature_flags_manager.dart'; import 'package:instabug_flutter/src/utils/ibg_build_info.dart'; import 'package:instabug_flutter/src/utils/instabug_logger.dart'; import 'package:instabug_flutter/src/utils/screen_name_masker.dart'; +import 'package:instabug_flutter/src/utils/screen_rendering/instabug_screen_render_manager.dart'; +import 'package:instabug_flutter/src/utils/screen_rendering/instabug_widget_binding_observer.dart'; import 'package:meta/meta.dart'; enum InvocationEvent { @@ -191,6 +193,9 @@ class Instabug { invocationEvents.mapToString(), debugLogsLevel.toString(), ); + + await InstabugScreenRenderManager.I.init(); + return FeatureFlagsManager().registerW3CFlagsListener(); } diff --git a/lib/src/utils/instabug_navigator_observer.dart b/lib/src/utils/instabug_navigator_observer.dart index d9d6b02db..e185347ad 100644 --- a/lib/src/utils/instabug_navigator_observer.dart +++ b/lib/src/utils/instabug_navigator_observer.dart @@ -6,6 +6,7 @@ import 'package:instabug_flutter/src/utils/instabug_logger.dart'; import 'package:instabug_flutter/src/utils/repro_steps_constants.dart'; import 'package:instabug_flutter/src/utils/screen_loading/screen_loading_manager.dart'; import 'package:instabug_flutter/src/utils/screen_name_masker.dart'; +import 'package:instabug_flutter/src/utils/screen_rendering/instabug_screen_render_manager.dart'; class InstabugNavigatorObserver extends NavigatorObserver { final List _steps = []; @@ -24,7 +25,15 @@ class InstabugNavigatorObserver extends NavigatorObserver { ); // Starts a the new UI trace which is exclusive to screen loading - ScreenLoadingManager.I.startUiTrace(maskedScreenName, screenName); + ScreenLoadingManager.I + .startUiTrace(maskedScreenName, screenName) + .then((uiTraceId) { + if (uiTraceId != null) { + InstabugScreenRenderManager.I + .startScreenRenderCollectorForTraceId(uiTraceId); + } + }); + // If there is a step that hasn't been pushed yet if (_steps.isNotEmpty) { // Report the last step and remove it from the list diff --git a/lib/src/utils/screen_loading/screen_loading_manager.dart b/lib/src/utils/screen_loading/screen_loading_manager.dart index b01b77627..ce73a3e30 100644 --- a/lib/src/utils/screen_loading/screen_loading_manager.dart +++ b/lib/src/utils/screen_loading/screen_loading_manager.dart @@ -4,9 +4,9 @@ import 'package:instabug_flutter/src/utils/ibg_build_info.dart'; import 'package:instabug_flutter/src/utils/ibg_date_time.dart'; import 'package:instabug_flutter/src/utils/instabug_logger.dart'; import 'package:instabug_flutter/src/utils/instabug_montonic_clock.dart'; -import 'package:instabug_flutter/src/utils/screen_loading/flags_config.dart'; +import 'package:instabug_flutter/src/utils/ui_trace/flags_config.dart'; import 'package:instabug_flutter/src/utils/screen_loading/screen_loading_trace.dart'; -import 'package:instabug_flutter/src/utils/screen_loading/ui_trace.dart'; +import 'package:instabug_flutter/src/utils/ui_trace/ui_trace.dart'; import 'package:meta/meta.dart'; /// Manages screen loading traces and UI traces for performance monitoring. @@ -139,7 +139,7 @@ class ScreenLoadingManager { /// [matchingScreenName] as the screen name used for matching the UI trace /// with a Screen Loading trace. @internal - Future startUiTrace( + Future startUiTrace( String screenName, [ String? matchingScreenName, ]) async { @@ -150,7 +150,7 @@ class ScreenLoadingManager { final isSDKBuilt = await _checkInstabugSDKBuilt("APM.InstabugCaptureScreenLoading"); - if (!isSDKBuilt) return; + if (!isSDKBuilt) return null; // TODO: On Android, FlagsConfig.apm.isEnabled isn't implemented correctly // so we skip the isApmEnabled check on Android and only check on iOS. @@ -164,7 +164,7 @@ class ScreenLoadingManager { 'https://docs.instabug.com/docs/react-native-apm-disabling-enabling', tag: APM.tag, ); - return; + return null; } final sanitizedScreenName = sanitizeScreenName(screenName); @@ -181,8 +181,10 @@ class ScreenLoadingManager { matchingScreenName: sanitizedMatchingScreenName, traceId: uiTraceId, ); + return uiTraceId; } catch (error, stackTrace) { _logExceptionErrorAndStackTrace(error, stackTrace); + return null; } } diff --git a/lib/src/utils/screen_rendering/instabug_frame_tracking.dart b/lib/src/utils/screen_rendering/instabug_frame_tracking.dart new file mode 100644 index 000000000..486abdb51 --- /dev/null +++ b/lib/src/utils/screen_rendering/instabug_frame_tracking.dart @@ -0,0 +1,43 @@ +// import 'dart:async'; +// import 'dart:developer'; +// import 'dart:ui'; +// import 'package:flutter/foundation.dart'; +// import 'package:flutter/widgets.dart'; +// import 'package:instabug_flutter/src/modules/apm.dart'; +// import 'package:meta/meta.dart'; +// +// @internal +// class InstabugFrameTracker { +// late Duration buildTime; +// late Duration rasterTime; +// late Duration totalTime; +// +// int _JANKFrames = 0; +// double _deviceRefreshRate = 60; +// double _threshold = 16; +// +// // final stackChain = Chain.current(); +// +// InstabugFrameTracker() { +// log("Andrew InstabugFrameTracker has been attached"); +// _checkForWidgetBinding(); +// +// WidgetsBinding.instance.addTimingsCallback((timings) { +// for (final frameTiming in timings) { +// _analyzeFrameTiming(frameTiming); +// } +// }); +// } +// +// // Simulates a computationally expensive task +// void simulateHeavyComputation() { +// final startTime = DateTime.now(); +// // Block the UI thread for ~500ms +// while (DateTime.now().difference(startTime).inMilliseconds <= 1000) { +// // Busy waiting (not recommended in real apps) +// } +// } +// +// +// +// } diff --git a/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart b/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart new file mode 100644 index 000000000..092c62169 --- /dev/null +++ b/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart @@ -0,0 +1,313 @@ +import 'dart:developer'; +import 'dart:ui'; + +import 'package:flutter/widgets.dart'; +import 'package:instabug_flutter/src/models/InstabugFrameData.dart'; +import 'package:instabug_flutter/src/models/InstabugScreenRenderData.dart'; +import 'package:instabug_flutter/src/modules/apm.dart'; +import 'package:instabug_flutter/src/modules/instabug.dart'; +import 'package:instabug_flutter/src/utils/instabug_logger.dart'; +import 'package:instabug_flutter/src/utils/screen_rendering/instabug_widget_binding_observer.dart'; +import 'package:instabug_flutter/src/utils/ui_trace/flags_config.dart'; +import 'package:meta/meta.dart'; + +@internal +enum UiTraceType { + auto, + custom, +} + +@internal +class InstabugScreenRenderManager { + late int _buildTime; + late int _rasterTime; + late int _totalTime; + late TimingsCallback _timingsCallback; + late InstabugScreenRenderData _screenRenderForAutoUiTrace; + late InstabugScreenRenderData _screenRenderForCustomUiTrace; + + final List _delayedFrames = []; + + double _deviceRefreshRate = 60; + double _slowFrameThresholdMs = 16.67; + final _frozenFrameThresholdMs = 700; + int _slowFramesTotalDuration = 0; + int _frozenFramesTotalDuration = 0; + + bool _isTimingsListenerAttached = false; + + InstabugScreenRenderManager._(); + + static final InstabugScreenRenderManager _instance = + InstabugScreenRenderManager._(); + + /// Returns the singleton instance of [InstabugScreenRenderManager]. + static InstabugScreenRenderManager get instance => _instance; + + /// Shorthand for [instance] + static InstabugScreenRenderManager get I => instance; + + /// Logging tag for debugging purposes. + static const tag = "ScreenRenderManager"; + + /// A named constructor used for testing purposes + + @visibleForTesting + InstabugScreenRenderManager.init(); + + /// setup function for [InstabugScreenRenderManager] + Future init() async { + if (await FlagsConfig.screenRendering.isEnabled() && + (!_isTimingsListenerAttached)) { + log("Andrew InstabugScreenRenderManager has been attached"); + _checkForWidgetBinding(); + WidgetsBinding.instance.addObserver(InstabugWidgetsBindingObserver()); + _initStaticValues(); + _initFrameTimings(); + } + } + + /// analyze frame data in order to detect slow/frozen frame. + void _analyzeFrameTiming(FrameTiming frameTiming) { + _buildTime = frameTiming.buildDuration.inMilliseconds; + _rasterTime = frameTiming.rasterDuration.inMilliseconds; + _totalTime = frameTiming.totalSpan.inMilliseconds; + + _displayFrameTimingDetails(frameTiming); + if (_isUiSlow) { + _slowFramesTotalDuration += + _buildTime.inMicro; //convert from milliseconds to microseconds + } else if (_isRasterSlow) { + _slowFramesTotalDuration += + _rasterTime.inMicro; //convert from milliseconds to microseconds + } + + if (_isUiFrozen) { + _frozenFramesTotalDuration += _buildTime.inMicro; + } else if (_isRasterFrozen) { + _frozenFramesTotalDuration += _rasterTime.inMicro; + } else if (_isFrozen) { + _frozenFramesTotalDuration += _totalTime.inMicro; + } + + if (_isUiDelayed) { + _onDelayedFrameDetected( + frameTiming.timestampInMicroseconds(FramePhase.buildStart), + frameTiming.buildDuration.inMicroseconds, + ); + } else if (_isRasterDelayed) { + _onDelayedFrameDetected( + frameTiming.timestampInMicroseconds(FramePhase.rasterStart), + frameTiming.rasterDuration.inMicroseconds, + ); + } else if (_isTotalTimeLarge) { + // todo what to do? + _onDelayedFrameDetected( + frameTiming.timestampInMicroseconds(FramePhase.vsyncStart), + frameTiming.totalSpan.inMicroseconds, + ); + } + } + + bool get _isSlow => _isUiSlow || _isRasterSlow; + + bool get _isUiDelayed => _isUiSlow || _isUiFrozen; + + bool get _isRasterDelayed => _isRasterSlow || _isRasterFrozen; + + bool get _isUiSlow => + _buildTime > _slowFrameThresholdMs && + _buildTime < _frozenFrameThresholdMs; + + bool get _isRasterSlow => + _rasterTime > _slowFrameThresholdMs && + _buildTime < _frozenFrameThresholdMs; + + bool get _isFrozen => _isUiFrozen || _isRasterFrozen || _isTotalTimeLarge; + + bool get _isTotalTimeLarge => _totalTime >= _frozenFrameThresholdMs; + + bool get _isUiFrozen => _buildTime >= _frozenFrameThresholdMs; + + bool get _isRasterFrozen => _rasterTime >= _frozenFrameThresholdMs; + + double _targetMsPerFrame(double displayRefreshRate) => + 1 / displayRefreshRate * 1000; + + /// Safe garde check for [WidgetsBinding.instance] initialization + void _checkForWidgetBinding() { + try { + WidgetsBinding.instance; + } catch (_) { + WidgetsFlutterBinding.ensureInitialized(); + } + } + + /// Checks if the Instabug SDK is built before calling API methods. + Future _checkInstabugSDKBuilt(String apiName) async { + final isInstabugSDKBuilt = await Instabug.isBuilt(); + if (!isInstabugSDKBuilt) { + InstabugLogger.I.e( + 'Instabug API {$apiName} was called before the SDK is built. To build it, first by following the instructions at this link:\n' + 'https://docs.instabug.com/reference#showing-and-manipulating-the-invocation', + tag: APM.tag, + ); + } + return isInstabugSDKBuilt; + } + + /// check if getting from native would return different value. + /// Platforms may limit what information is available to the application with regard to secondary displays and/or displays that do not have an active application window. + /// Presently, on Android and Web this collection will only contain the display that the current window is on. + /// On iOS, it will only contains the main display on the phone or tablet. + /// On Desktop, it will contain only a main display with a valid refresh rate but invalid size and device pixel ratio values. + double get _getDeviceRefreshRate => + WidgetsBinding.instance.platformDispatcher.displays.last.refreshRate; + + /// get device refresh rate from native side. + Future get _getDeviceRefreshRateFromNative => + APM.getDeviceRefreshRate(); + + /// initialize the static variables + void _initStaticValues() { + _timingsCallback = (timings) { + for (final frameTiming in timings) { + _analyzeFrameTiming(frameTiming); + } + }; + _deviceRefreshRate = _getDeviceRefreshRate; + _slowFrameThresholdMs = _targetMsPerFrame(_getDeviceRefreshRate); + _screenRenderForAutoUiTrace = InstabugScreenRenderData(frameData: []); + _screenRenderForCustomUiTrace = InstabugScreenRenderData(frameData: []); + } + + /// add a frame observer by calling [WidgetsBinding.instance.addTimingsCallback] + void _initFrameTimings() { + WidgetsBinding.instance.addTimingsCallback(_timingsCallback); + _isTimingsListenerAttached = true; + } + + /// remove the running frame observer by calling [WidgetsBinding.instance.removeTimingsCallback] + void _removeFrameTimings() { + WidgetsBinding.instance.removeTimingsCallback(_timingsCallback); + _isTimingsListenerAttached = false; + } + + void startScreenRenderCollectorForTraceId( + int traceId, [ + UiTraceType type = UiTraceType.auto, + ]) { + if (!_isTimingsListenerAttached) { + _initFrameTimings(); + } + + if (_delayedFrames.isNotEmpty) { + _saveCollectedData(); + _resetCachedFrameData(); + } + if (type == UiTraceType.custom) { + if (_screenRenderForCustomUiTrace.isNotEmpty) { + _reportScreenRenderForCustomUiTrace(_screenRenderForCustomUiTrace); + _screenRenderForCustomUiTrace.clear(); + } + _screenRenderForCustomUiTrace.traceId = traceId; + } + if (type == UiTraceType.auto) { + if (_screenRenderForAutoUiTrace.isNotEmpty) { + _reportScreenRenderForAutoUiTrace(_screenRenderForAutoUiTrace); + _screenRenderForAutoUiTrace.clear(); + } + _screenRenderForAutoUiTrace.traceId = traceId; + } + } + + void stopScreenRenderCollector([UiTraceType? type]) { + _saveCollectedData(); + if (_screenRenderForCustomUiTrace.isNotEmpty) { + _reportScreenRenderForCustomUiTrace(_screenRenderForCustomUiTrace); + } + if (_screenRenderForAutoUiTrace.isNotEmpty) { + _reportScreenRenderForAutoUiTrace(_screenRenderForAutoUiTrace); + } + + _removeFrameTimings(); + _resetCachedFrameData(); + } + + void _resetCachedFrameData() { + _slowFramesTotalDuration = 0; + _frozenFramesTotalDuration = 0; + _delayedFrames.clear(); + } + + /// Save Slow/Frozen Frames data + void _onDelayedFrameDetected(int startTime, int duration) { + _delayedFrames.add(InstabugFrameData(startTime, duration)); + } + + //todo: to be removed + void _displayFrameTimingDetails(FrameTiming frameTiming) { + if (_isSlow) { + debugPrint( + '========================= Slow frame detected ⚠️ =========================', + ); + } + if (_isFrozen) { + debugPrint( + '========================= Frozen frame detected 🚨 =========================', + ); + } + + if (_isFrozen || _isSlow) { + debugPrint("{\n\t$frameTiming\n\t" + "Timestamps(${frameTiming.timestampInMicroseconds( + FramePhase.buildStart, + )}, ${frameTiming.timestampInMicroseconds( + FramePhase.buildFinish, + )}, ${frameTiming.timestampInMicroseconds( + FramePhase.rasterStart, + )}, ${frameTiming.timestampInMicroseconds( + FramePhase.rasterFinish, + )}, ${frameTiming.timestampInMicroseconds( + FramePhase.vsyncStart, + )}, ${frameTiming.timestampInMicroseconds( + FramePhase.rasterFinishWallTime, + )}" + ")\n}\n"); + debugPrint("Device refresh rate: $_deviceRefreshRate FPS"); + debugPrint("Threshold: $_slowFrameThresholdMs ms\n" + "==============================================================================="); + } + } + + Future _reportScreenRenderForCustomUiTrace( + InstabugScreenRenderData screenRenderData) async { + log("ReportedData: $screenRenderData", name: tag); + } + + Future _reportScreenRenderForAutoUiTrace( + InstabugScreenRenderData screenRenderData) async { + log("ReportedData: $screenRenderData", name: tag); + } + + void _saveCollectedData() { + if (_screenRenderForAutoUiTrace.isNotEmpty) { + _screenRenderForAutoUiTrace.totalSlowFramesDurations += + _slowFramesTotalDuration; + _screenRenderForAutoUiTrace.totalFrozenFramesDurations += + _frozenFramesTotalDuration; + _screenRenderForAutoUiTrace.frameData.addAll(_delayedFrames); + } + if (_screenRenderForCustomUiTrace.isNotEmpty) { + _screenRenderForCustomUiTrace.totalSlowFramesDurations += + _slowFramesTotalDuration; + _screenRenderForCustomUiTrace.totalFrozenFramesDurations += + _frozenFramesTotalDuration; + _screenRenderForCustomUiTrace.frameData.addAll(_delayedFrames); + } + } +} + +extension on int { + int get inMicro => this * 1000; +} diff --git a/lib/src/utils/screen_rendering/instabug_widget_binding_observer.dart b/lib/src/utils/screen_rendering/instabug_widget_binding_observer.dart new file mode 100644 index 000000000..89119f088 --- /dev/null +++ b/lib/src/utils/screen_rendering/instabug_widget_binding_observer.dart @@ -0,0 +1,55 @@ +import 'dart:async'; +import 'dart:developer'; +import 'dart:ui'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/widgets.dart'; +import 'package:instabug_flutter/src/models/InstabugScreenRenderData.dart'; +import 'package:instabug_flutter/src/utils/screen_loading/screen_loading_manager.dart'; +import 'package:instabug_flutter/src/utils/screen_name_masker.dart'; +import 'package:instabug_flutter/src/utils/screen_rendering/instabug_screen_render_manager.dart'; + +class InstabugWidgetsBindingObserver extends WidgetsBindingObserver { + void _handleResumedState() { + log('Performing resume actions...'); + final lastUiTrace = ScreenLoadingManager.I.currentUiTrace; + if (lastUiTrace != null) { + final maskedScreenName = ScreenNameMasker.I.mask(lastUiTrace.screenName); + ScreenLoadingManager.I + .startUiTrace(maskedScreenName, lastUiTrace.screenName); + } + // ... complex logic for resumed state + } + + void _handlePausedState() { + // ... complex logic for paused state + log('Performing pause actions...'); + InstabugScreenRenderManager.I.stopScreenRenderCollector(); + } + + void _handleDetachedState() { + log('Performing detached actions...'); + InstabugScreenRenderManager.I.stopScreenRenderCollector(); + // ... complex logic for paused state + } + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + switch (state) { + case AppLifecycleState.resumed: + _handleResumedState(); + break; + case AppLifecycleState.paused: + _handlePausedState(); + break; + case AppLifecycleState.detached: + _handleDetachedState(); + break; + case AppLifecycleState.inactive: + // TODO: Handle this case. + break; + case AppLifecycleState.hidden: + // TODO: Handle this case. + break; + } + } +} diff --git a/lib/src/utils/screen_loading/flags_config.dart b/lib/src/utils/ui_trace/flags_config.dart similarity index 83% rename from lib/src/utils/screen_loading/flags_config.dart rename to lib/src/utils/ui_trace/flags_config.dart index f18eb1ccb..92a899b15 100644 --- a/lib/src/utils/screen_loading/flags_config.dart +++ b/lib/src/utils/ui_trace/flags_config.dart @@ -5,6 +5,7 @@ enum FlagsConfig { uiTrace, screenLoading, endScreenLoading, + screenRendering, } extension FeatureExtensions on FlagsConfig { @@ -16,6 +17,8 @@ extension FeatureExtensions on FlagsConfig { return APM.isScreenLoadingEnabled(); case FlagsConfig.endScreenLoading: return APM.isEndScreenLoadingEnabled(); + case FlagsConfig.screenRendering: + return APM.isScreenRenderEnabled(); default: return false; } diff --git a/lib/src/utils/screen_loading/route_matcher.dart b/lib/src/utils/ui_trace/route_matcher.dart similarity index 100% rename from lib/src/utils/screen_loading/route_matcher.dart rename to lib/src/utils/ui_trace/route_matcher.dart diff --git a/lib/src/utils/screen_loading/ui_trace.dart b/lib/src/utils/ui_trace/ui_trace.dart similarity index 94% rename from lib/src/utils/screen_loading/ui_trace.dart rename to lib/src/utils/ui_trace/ui_trace.dart index 17ef41046..34c88cbc0 100644 --- a/lib/src/utils/screen_loading/ui_trace.dart +++ b/lib/src/utils/ui_trace/ui_trace.dart @@ -1,4 +1,4 @@ -import 'package:instabug_flutter/src/utils/screen_loading/route_matcher.dart'; +import 'package:instabug_flutter/src/utils/ui_trace/route_matcher.dart'; class UiTrace { final String screenName; diff --git a/pigeons/apm.api.dart b/pigeons/apm.api.dart index 84fe9eb8e..d4a159631 100644 --- a/pigeons/apm.api.dart +++ b/pigeons/apm.api.dart @@ -40,4 +40,10 @@ abstract class ApmHostApi { @async bool isEndScreenLoadingEnabled(); + + @async + bool isScreenRenderEnabled(); + + @async + double deviceRefreshRate(); } diff --git a/test/route_matcher_test.dart b/test/route_matcher_test.dart index 977c61d88..5d8b234c4 100644 --- a/test/route_matcher_test.dart +++ b/test/route_matcher_test.dart @@ -1,6 +1,6 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:instabug_flutter/src/utils/screen_loading/route_matcher.dart'; +import 'package:instabug_flutter/src/utils/ui_trace/route_matcher.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); diff --git a/test/utils/screen_loading/screen_loading_manager_test.dart b/test/utils/screen_loading/screen_loading_manager_test.dart index c008b8bcc..f452c4cda 100644 --- a/test/utils/screen_loading/screen_loading_manager_test.dart +++ b/test/utils/screen_loading/screen_loading_manager_test.dart @@ -7,12 +7,13 @@ import 'package:instabug_flutter/src/utils/ibg_build_info.dart'; import 'package:instabug_flutter/src/utils/ibg_date_time.dart'; import 'package:instabug_flutter/src/utils/instabug_logger.dart'; import 'package:instabug_flutter/src/utils/instabug_montonic_clock.dart'; -import 'package:instabug_flutter/src/utils/screen_loading/flags_config.dart'; import 'package:instabug_flutter/src/utils/screen_loading/screen_loading_manager.dart'; import 'package:instabug_flutter/src/utils/screen_loading/screen_loading_trace.dart'; -import 'package:instabug_flutter/src/utils/screen_loading/ui_trace.dart'; +import 'package:instabug_flutter/src/utils/ui_trace/ui_trace.dart'; +import 'package:instabug_flutter/src/utils/ui_trace/flags_config.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; + import 'screen_loading_manager_test.mocks.dart'; class ScreenLoadingManagerNoResets extends ScreenLoadingManager { diff --git a/test/utils/screen_loading/ui_trace_test.dart b/test/utils/screen_loading/ui_trace_test.dart index 11ed57c66..68a0f06cf 100644 --- a/test/utils/screen_loading/ui_trace_test.dart +++ b/test/utils/screen_loading/ui_trace_test.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:instabug_flutter/instabug_flutter.dart'; -import 'package:instabug_flutter/src/utils/screen_loading/ui_trace.dart'; +import 'package:instabug_flutter/src/utils/ui_trace/ui_trace.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; From 7064e0e6c878b5250357918379fd3236366f9490 Mon Sep 17 00:00:00 2001 From: Andrew Amin Date: Wed, 18 Jun 2025 12:14:07 +0300 Subject: [PATCH 02/15] chore: attach screen render collector to the app lifecycle and ui traces , add unit tests. --- example/lib/main.dart | 2 + .../lib/src/components/ui_traces_content.dart | 75 ++++ example/lib/src/screens/apm_page.dart | 2 + lib/src/models/InstabugFrameData.dart | 13 +- lib/src/models/InstabugScreenRenderData.dart | 34 +- lib/src/modules/apm.dart | 19 +- lib/src/modules/instabug.dart | 7 +- .../instabug_frame_tracking.dart | 43 --- .../instabug_screen_render_manager.dart | 170 +++++--- .../instabug_widget_binding_observer.dart | 39 +- .../instabug_screen_render_manager_test.dart | 364 ++++++++++++++++++ 11 files changed, 638 insertions(+), 130 deletions(-) create mode 100644 example/lib/src/components/ui_traces_content.dart delete mode 100644 lib/src/utils/screen_rendering/instabug_frame_tracking.dart create mode 100644 test/utils/screen_render/instabug_screen_render_manager_test.dart diff --git a/example/lib/main.dart b/example/lib/main.dart index 40fc4f4e1..8895bd084 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -48,6 +48,8 @@ part 'src/components/screen_render.dart'; part 'src/components/animated_box.dart'; +part 'src/components/ui_traces_content.dart'; + void main() { runZonedGuarded( () { diff --git a/example/lib/src/components/ui_traces_content.dart b/example/lib/src/components/ui_traces_content.dart new file mode 100644 index 000000000..19e9ec0dd --- /dev/null +++ b/example/lib/src/components/ui_traces_content.dart @@ -0,0 +1,75 @@ +part of '../../main.dart'; + +class UITracesContent extends StatefulWidget { + const UITracesContent({Key? key}) : super(key: key); + + @override + State createState() => _UITracesContentState(); +} + +class _UITracesContentState extends State { + final traceNameController = TextEditingController(); + + @override + Widget build(BuildContext context) { + final textTheme = Theme.of(context).textTheme; + return Column( + children: [ + InstabugTextField( + label: 'UI Trace name', + labelStyle: textTheme.labelMedium, + controller: traceNameController, + ), + SizedBox.fromSize( + size: const Size.fromHeight(10.0), + ), + Row( + children: [ + Flexible( + flex: 5, + child: InstabugButton.smallFontSize( + text: 'Start UI Trace', + onPressed: () => _startTrace(traceNameController.text), + margin: const EdgeInsetsDirectional.only( + start: 20.0, + end: 10.0, + ), + ), + ), + Flexible( + flex: 5, + child: InstabugButton.smallFontSize( + text: 'End UI Trace', + onPressed: () => _endTrace(), + margin: const EdgeInsetsDirectional.only( + start: 10.0, + end: 20.0, + ), + ), + ), + ], + ), + + ], + ); + } + + void _startTrace( + String traceName, { + int delayInMilliseconds = 0, + }) { + if (traceName.trim().isNotEmpty) { + log('_startTrace — traceName: $traceName, delay in Milliseconds: $delayInMilliseconds'); + log('traceName: $traceName'); + Future.delayed(Duration(milliseconds: delayInMilliseconds), + () => APM.startUITrace(traceName)); + } else { + log('startUITrace - Please enter a trace name'); + } + } + + void _endTrace() { + log('endUITrace - '); + APM.endUITrace(); + } +} diff --git a/example/lib/src/screens/apm_page.dart b/example/lib/src/screens/apm_page.dart index 153b23b5c..0dcf90a2c 100644 --- a/example/lib/src/screens/apm_page.dart +++ b/example/lib/src/screens/apm_page.dart @@ -40,6 +40,8 @@ class _ApmPageState extends State { const TracesContent(), const SectionTitle('Flows'), const FlowsContent(), + const SectionTitle('Custom UI Traces'), + const UITracesContent(), const SectionTitle('Screen Loading'), SizedBox.fromSize( size: const Size.fromHeight(12), diff --git a/lib/src/models/InstabugFrameData.dart b/lib/src/models/InstabugFrameData.dart index d7db5a01d..d62368c3a 100644 --- a/lib/src/models/InstabugFrameData.dart +++ b/lib/src/models/InstabugFrameData.dart @@ -1,9 +1,16 @@ -class InstabugFrameData{ +class InstabugFrameData { int startTimeTimestamp; int duration; InstabugFrameData(this.startTimeTimestamp, this.duration); @override - String toString() => "startTime: $startTimeTimestamp, duration: $duration"; -} \ No newline at end of file + String toString() => "start time: $startTimeTimestamp, duration: $duration"; + + @override + bool operator == (covariant InstabugFrameData other) { + if (identical(this, other)) return true; + return startTimeTimestamp == other.startTimeTimestamp && + duration == other.duration; + } +} diff --git a/lib/src/models/InstabugScreenRenderData.dart b/lib/src/models/InstabugScreenRenderData.dart index b55f464f1..ed5f4a2f3 100644 --- a/lib/src/models/InstabugScreenRenderData.dart +++ b/lib/src/models/InstabugScreenRenderData.dart @@ -1,15 +1,16 @@ +import 'package:flutter/foundation.dart'; import 'package:instabug_flutter/src/models/InstabugFrameData.dart'; class InstabugScreenRenderData { int traceId; - int totalSlowFramesDurations; - int totalFrozenFramesDurations; + int slowFramesTotalDuration; + int frozenFramesTotalDuration; List frameData; InstabugScreenRenderData({ - this.totalSlowFramesDurations = 0, - this.totalFrozenFramesDurations = 0, - required this.frameData , + this.slowFramesTotalDuration = 0, + this.frozenFramesTotalDuration = 0, + required this.frameData, this.traceId = -1, }); @@ -19,14 +20,25 @@ class InstabugScreenRenderData { void clear() { traceId = -1; - totalFrozenFramesDurations = 0; - totalSlowFramesDurations = 0; + frozenFramesTotalDuration = 0; + slowFramesTotalDuration = 0; frameData.clear(); } @override - String toString() => '\nTraceId $traceId\n' - 'TotalSlowFramesDurations: $totalSlowFramesDurations\n' - 'TotalFrozenFramesDurations $totalFrozenFramesDurations\n' - 'FrameData[\n${frameData.map((element) => '\t\n$element')}\n]'; + String toString() => '\nTrace Id $traceId\n' + 'Slow Frames Total Duration: $slowFramesTotalDuration\n' + 'Frozen Frames Total Duration $frozenFramesTotalDuration\n' + 'Frame Data[\n${frameData.map((element) => '\t\n$element')}\n]'; + + @override + bool operator ==(covariant InstabugScreenRenderData other) { + if (identical(this, other)) return true; + return traceId == other.traceId && + slowFramesTotalDuration == other.slowFramesTotalDuration && + frozenFramesTotalDuration == other.frozenFramesTotalDuration && + listEquals(frameData, other.frameData); + } + + } diff --git a/lib/src/modules/apm.dart b/lib/src/modules/apm.dart index a37d8c118..43af7b7d7 100644 --- a/lib/src/modules/apm.dart +++ b/lib/src/modules/apm.dart @@ -10,6 +10,8 @@ import 'package:instabug_flutter/src/utils/ibg_build_info.dart'; import 'package:instabug_flutter/src/utils/ibg_date_time.dart'; import 'package:instabug_flutter/src/utils/instabug_logger.dart'; import 'package:instabug_flutter/src/utils/screen_loading/screen_loading_manager.dart'; +import 'package:instabug_flutter/src/utils/screen_rendering/instabug_screen_render_manager.dart'; +import 'package:instabug_flutter/src/utils/ui_trace/flags_config.dart'; import 'package:meta/meta.dart'; class APM { @@ -189,7 +191,14 @@ class APM { /// Returns: /// The method is returning a `Future`. static Future startUITrace(String name) async { - return _host.startUITrace(name); + return _host.startUITrace(name).then( + (_) async { + // Start screen render collector for custom ui trace if enabled. + if (await FlagsConfig.screenRendering.isEnabled()) { + InstabugScreenRenderManager.I.startScreenRenderCollectorForTraceId(0 ,UiTraceType.custom); + } + }, + ); } /// The [endUITrace] function ends a UI trace. @@ -197,6 +206,12 @@ class APM { /// Returns: /// The method is returning a `Future`. static Future endUITrace() async { + // End screen render collector for custom ui trace if enabled. + if (await FlagsConfig.screenRendering.isEnabled()) { + return InstabugScreenRenderManager.I + .endScreenRenderCollectorForCustomUiTrace(); + } + return _host.endUITrace(); } @@ -353,7 +368,7 @@ class APM { /// Returns: /// A Future is being returned. @internal - static Future isScreenRenderEnabled() async{ + static Future isScreenRenderEnabled() async { return _host.isScreenRenderEnabled(); } diff --git a/lib/src/modules/instabug.dart b/lib/src/modules/instabug.dart index 96b40876d..0a832526b 100644 --- a/lib/src/modules/instabug.dart +++ b/lib/src/modules/instabug.dart @@ -11,6 +11,7 @@ import 'dart:typed_data'; import 'dart:ui'; import 'package:flutter/material.dart'; + // to maintain supported versions prior to Flutter 3.3 // ignore: unused_import import 'package:flutter/services.dart'; @@ -23,6 +24,7 @@ import 'package:instabug_flutter/src/utils/instabug_logger.dart'; import 'package:instabug_flutter/src/utils/screen_name_masker.dart'; import 'package:instabug_flutter/src/utils/screen_rendering/instabug_screen_render_manager.dart'; import 'package:instabug_flutter/src/utils/screen_rendering/instabug_widget_binding_observer.dart'; +import 'package:instabug_flutter/src/utils/ui_trace/flags_config.dart'; import 'package:meta/meta.dart'; enum InvocationEvent { @@ -194,7 +196,10 @@ class Instabug { debugLogsLevel.toString(), ); - await InstabugScreenRenderManager.I.init(); + if (await FlagsConfig.screenRendering.isEnabled()) { + checkForWidgetBinding(); + await InstabugScreenRenderManager.I.init(WidgetsBinding.instance); + } return FeatureFlagsManager().registerW3CFlagsListener(); } diff --git a/lib/src/utils/screen_rendering/instabug_frame_tracking.dart b/lib/src/utils/screen_rendering/instabug_frame_tracking.dart deleted file mode 100644 index 486abdb51..000000000 --- a/lib/src/utils/screen_rendering/instabug_frame_tracking.dart +++ /dev/null @@ -1,43 +0,0 @@ -// import 'dart:async'; -// import 'dart:developer'; -// import 'dart:ui'; -// import 'package:flutter/foundation.dart'; -// import 'package:flutter/widgets.dart'; -// import 'package:instabug_flutter/src/modules/apm.dart'; -// import 'package:meta/meta.dart'; -// -// @internal -// class InstabugFrameTracker { -// late Duration buildTime; -// late Duration rasterTime; -// late Duration totalTime; -// -// int _JANKFrames = 0; -// double _deviceRefreshRate = 60; -// double _threshold = 16; -// -// // final stackChain = Chain.current(); -// -// InstabugFrameTracker() { -// log("Andrew InstabugFrameTracker has been attached"); -// _checkForWidgetBinding(); -// -// WidgetsBinding.instance.addTimingsCallback((timings) { -// for (final frameTiming in timings) { -// _analyzeFrameTiming(frameTiming); -// } -// }); -// } -// -// // Simulates a computationally expensive task -// void simulateHeavyComputation() { -// final startTime = DateTime.now(); -// // Block the UI thread for ~500ms -// while (DateTime.now().difference(startTime).inMilliseconds <= 1000) { -// // Busy waiting (not recommended in real apps) -// } -// } -// -// -// -// } diff --git a/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart b/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart index 092c62169..55baed043 100644 --- a/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart +++ b/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart @@ -5,12 +5,13 @@ import 'package:flutter/widgets.dart'; import 'package:instabug_flutter/src/models/InstabugFrameData.dart'; import 'package:instabug_flutter/src/models/InstabugScreenRenderData.dart'; import 'package:instabug_flutter/src/modules/apm.dart'; -import 'package:instabug_flutter/src/modules/instabug.dart'; -import 'package:instabug_flutter/src/utils/instabug_logger.dart'; import 'package:instabug_flutter/src/utils/screen_rendering/instabug_widget_binding_observer.dart'; -import 'package:instabug_flutter/src/utils/ui_trace/flags_config.dart'; import 'package:meta/meta.dart'; +extension on int { + int get inMicro => this * 1000; +} + @internal enum UiTraceType { auto, @@ -19,6 +20,7 @@ enum UiTraceType { @internal class InstabugScreenRenderManager { + late final WidgetsBinding _widgetsBinding; late int _buildTime; late int _rasterTime; late int _totalTime; @@ -56,19 +58,24 @@ class InstabugScreenRenderManager { InstabugScreenRenderManager.init(); /// setup function for [InstabugScreenRenderManager] - Future init() async { - if (await FlagsConfig.screenRendering.isEnabled() && - (!_isTimingsListenerAttached)) { - log("Andrew InstabugScreenRenderManager has been attached"); - _checkForWidgetBinding(); - WidgetsBinding.instance.addObserver(InstabugWidgetsBindingObserver()); - _initStaticValues(); + @internal + Future init(WidgetsBinding widgetBinding) async { + if (!_isTimingsListenerAttached) { + _widgetsBinding = widgetBinding; + _addWidgetBindingObserver(); + await _initStaticValues(); _initFrameTimings(); } } + /// nodoc + + void _addWidgetBindingObserver() => + _widgetsBinding.addObserver(InstabugWidgetsBindingObserver.instance); + /// analyze frame data in order to detect slow/frozen frame. - void _analyzeFrameTiming(FrameTiming frameTiming) { + @visibleForTesting + void analyzeFrameTiming(FrameTiming frameTiming) { _buildTime = frameTiming.buildDuration.inMilliseconds; _rasterTime = frameTiming.rasterDuration.inMilliseconds; _totalTime = frameTiming.totalSpan.inMilliseconds; @@ -121,7 +128,7 @@ class InstabugScreenRenderManager { bool get _isRasterSlow => _rasterTime > _slowFrameThresholdMs && - _buildTime < _frozenFrameThresholdMs; + _rasterTime < _frozenFrameThresholdMs; bool get _isFrozen => _isUiFrozen || _isRasterFrozen || _isTotalTimeLarge; @@ -131,109 +138,121 @@ class InstabugScreenRenderManager { bool get _isRasterFrozen => _rasterTime >= _frozenFrameThresholdMs; + /// Calculate the target time for the frame to be drawn in milliseconds based on the device refresh rate. double _targetMsPerFrame(double displayRefreshRate) => 1 / displayRefreshRate * 1000; - /// Safe garde check for [WidgetsBinding.instance] initialization - void _checkForWidgetBinding() { - try { - WidgetsBinding.instance; - } catch (_) { - WidgetsFlutterBinding.ensureInitialized(); - } - } - - /// Checks if the Instabug SDK is built before calling API methods. - Future _checkInstabugSDKBuilt(String apiName) async { - final isInstabugSDKBuilt = await Instabug.isBuilt(); - if (!isInstabugSDKBuilt) { - InstabugLogger.I.e( - 'Instabug API {$apiName} was called before the SDK is built. To build it, first by following the instructions at this link:\n' - 'https://docs.instabug.com/reference#showing-and-manipulating-the-invocation', - tag: APM.tag, - ); - } - return isInstabugSDKBuilt; - } - - /// check if getting from native would return different value. + /// Check if getting from native would return different value. /// Platforms may limit what information is available to the application with regard to secondary displays and/or displays that do not have an active application window. /// Presently, on Android and Web this collection will only contain the display that the current window is on. /// On iOS, it will only contains the main display on the phone or tablet. /// On Desktop, it will contain only a main display with a valid refresh rate but invalid size and device pixel ratio values. + //todo: will be removed after getting the actual value from native side. double get _getDeviceRefreshRate => - WidgetsBinding.instance.platformDispatcher.displays.last.refreshRate; + _widgetsBinding.platformDispatcher.displays.last.refreshRate; - /// get device refresh rate from native side. + /// Get device refresh rate from native side. Future get _getDeviceRefreshRateFromNative => APM.getDeviceRefreshRate(); - /// initialize the static variables - void _initStaticValues() { + /// Initialize the static variables + Future _initStaticValues() async { _timingsCallback = (timings) { for (final frameTiming in timings) { - _analyzeFrameTiming(frameTiming); + analyzeFrameTiming(frameTiming); } }; - _deviceRefreshRate = _getDeviceRefreshRate; - _slowFrameThresholdMs = _targetMsPerFrame(_getDeviceRefreshRate); + _deviceRefreshRate = await _getDeviceRefreshRateFromNative; + _slowFrameThresholdMs = _targetMsPerFrame(_deviceRefreshRate); _screenRenderForAutoUiTrace = InstabugScreenRenderData(frameData: []); _screenRenderForCustomUiTrace = InstabugScreenRenderData(frameData: []); } - /// add a frame observer by calling [WidgetsBinding.instance.addTimingsCallback] + /// Add a frame observer by calling [WidgetsBinding.instance.addTimingsCallback] + void _initFrameTimings() { - WidgetsBinding.instance.addTimingsCallback(_timingsCallback); + _widgetsBinding.addTimingsCallback(_timingsCallback); _isTimingsListenerAttached = true; } - /// remove the running frame observer by calling [WidgetsBinding.instance.removeTimingsCallback] + /// Remove the running frame observer by calling [_widgetsBinding.removeTimingsCallback] void _removeFrameTimings() { - WidgetsBinding.instance.removeTimingsCallback(_timingsCallback); + _widgetsBinding.removeTimingsCallback(_timingsCallback); _isTimingsListenerAttached = false; } + /// Start collecting screen render data for the running [UITrace]. + /// It ends the running collector when starting a new one of the same type [UiTraceType]. + @internal void startScreenRenderCollectorForTraceId( int traceId, [ UiTraceType type = UiTraceType.auto, ]) { + // Attach frameTimingListener if not attached if (!_isTimingsListenerAttached) { _initFrameTimings(); } + //Save the memory cached data to be sent to native side if (_delayedFrames.isNotEmpty) { _saveCollectedData(); _resetCachedFrameData(); } + + //Sync the captured screen render data of the Custom UI trace when starting new one if (type == UiTraceType.custom) { if (_screenRenderForCustomUiTrace.isNotEmpty) { - _reportScreenRenderForCustomUiTrace(_screenRenderForCustomUiTrace); + reportScreenRending(_screenRenderForCustomUiTrace, UiTraceType.custom); _screenRenderForCustomUiTrace.clear(); } _screenRenderForCustomUiTrace.traceId = traceId; } + + //Sync the captured screen render data of the Auto UI trace when starting new one if (type == UiTraceType.auto) { if (_screenRenderForAutoUiTrace.isNotEmpty) { - _reportScreenRenderForAutoUiTrace(_screenRenderForAutoUiTrace); + reportScreenRending(_screenRenderForAutoUiTrace); _screenRenderForAutoUiTrace.clear(); } _screenRenderForAutoUiTrace.traceId = traceId; } } - void stopScreenRenderCollector([UiTraceType? type]) { + /// Stop screen render collector and sync the captured data. + @internal + void stopScreenRenderCollector() { _saveCollectedData(); + if (_screenRenderForCustomUiTrace.isNotEmpty) { - _reportScreenRenderForCustomUiTrace(_screenRenderForCustomUiTrace); + reportScreenRending(_screenRenderForCustomUiTrace, UiTraceType.custom); } if (_screenRenderForAutoUiTrace.isNotEmpty) { - _reportScreenRenderForAutoUiTrace(_screenRenderForAutoUiTrace); + reportScreenRending(_screenRenderForAutoUiTrace); } _removeFrameTimings(); + _resetCachedFrameData(); } + /// Sync the capture screen render data of the custom UI trace without stopping the collector. + @internal + void endScreenRenderCollectorForCustomUiTrace() { + if (_screenRenderForCustomUiTrace.isNotEmpty) { + // Save the captured screen rendering data to be synced + _screenRenderForCustomUiTrace.slowFramesTotalDuration += + _slowFramesTotalDuration; + _screenRenderForCustomUiTrace.frozenFramesTotalDuration += + _frozenFramesTotalDuration; + _screenRenderForCustomUiTrace.frameData.addAll(_delayedFrames); + + // Sync the saved screen rendering data + reportScreenRending(_screenRenderForCustomUiTrace, UiTraceType.custom); + _screenRenderForCustomUiTrace.clear(); + } + } + + /// Reset the memory cashed data void _resetCachedFrameData() { _slowFramesTotalDuration = 0; _frozenFramesTotalDuration = 0; @@ -280,34 +299,61 @@ class InstabugScreenRenderManager { } } + @visibleForTesting + Future reportScreenRending(InstabugScreenRenderData screenRenderData, + [UiTraceType type = UiTraceType.auto]) async { + if (type == UiTraceType.auto) { + _reportScreenRenderForAutoUiTrace(screenRenderData); + } else { + _reportScreenRenderForCustomUiTrace(screenRenderData); + } + log("Reported Data (${type == UiTraceType.auto ? 'auto' : 'custom'}): $screenRenderData", + name: tag); + } + Future _reportScreenRenderForCustomUiTrace( - InstabugScreenRenderData screenRenderData) async { - log("ReportedData: $screenRenderData", name: tag); + InstabugScreenRenderData screenRenderData, + ) async { + //todo: Will be implemented in next sprint } Future _reportScreenRenderForAutoUiTrace( - InstabugScreenRenderData screenRenderData) async { - log("ReportedData: $screenRenderData", name: tag); + InstabugScreenRenderData screenRenderData, + ) async { + //todo: Will be implemented in next sprint } + /// Add the memory cashed data to the objects that will be synced asynchronously to the native side. void _saveCollectedData() { if (_screenRenderForAutoUiTrace.isNotEmpty) { - _screenRenderForAutoUiTrace.totalSlowFramesDurations += + _screenRenderForAutoUiTrace.slowFramesTotalDuration += _slowFramesTotalDuration; - _screenRenderForAutoUiTrace.totalFrozenFramesDurations += + _screenRenderForAutoUiTrace.frozenFramesTotalDuration += _frozenFramesTotalDuration; _screenRenderForAutoUiTrace.frameData.addAll(_delayedFrames); } if (_screenRenderForCustomUiTrace.isNotEmpty) { - _screenRenderForCustomUiTrace.totalSlowFramesDurations += + _screenRenderForCustomUiTrace.slowFramesTotalDuration += _slowFramesTotalDuration; - _screenRenderForCustomUiTrace.totalFrozenFramesDurations += + _screenRenderForCustomUiTrace.frozenFramesTotalDuration += _frozenFramesTotalDuration; _screenRenderForCustomUiTrace.frameData.addAll(_delayedFrames); } } -} -extension on int { - int get inMicro => this * 1000; + /// --------------------------- testing helper functions --------------------- + @visibleForTesting + InstabugScreenRenderData get screenRenderForAutoUiTrace => + _screenRenderForAutoUiTrace; + + @visibleForTesting + InstabugScreenRenderData get screenRenderForCustomUiTrace => + _screenRenderForCustomUiTrace; + + @visibleForTesting + void setFrameData(InstabugScreenRenderData data) { + _delayedFrames.addAll(data.frameData); + _frozenFramesTotalDuration = data.frozenFramesTotalDuration; + _slowFramesTotalDuration = data.slowFramesTotalDuration; + } } diff --git a/lib/src/utils/screen_rendering/instabug_widget_binding_observer.dart b/lib/src/utils/screen_rendering/instabug_widget_binding_observer.dart index 89119f088..053beaed8 100644 --- a/lib/src/utils/screen_rendering/instabug_widget_binding_observer.dart +++ b/lib/src/utils/screen_rendering/instabug_widget_binding_observer.dart @@ -1,27 +1,42 @@ -import 'dart:async'; import 'dart:developer'; -import 'dart:ui'; -import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; -import 'package:instabug_flutter/src/models/InstabugScreenRenderData.dart'; import 'package:instabug_flutter/src/utils/screen_loading/screen_loading_manager.dart'; import 'package:instabug_flutter/src/utils/screen_name_masker.dart'; import 'package:instabug_flutter/src/utils/screen_rendering/instabug_screen_render_manager.dart'; +import 'package:meta/meta.dart'; class InstabugWidgetsBindingObserver extends WidgetsBindingObserver { + InstabugWidgetsBindingObserver._(); + + static final InstabugWidgetsBindingObserver _instance = + InstabugWidgetsBindingObserver._(); + + /// Returns the singleton instance of [InstabugWidgetsBindingObserver]. + static InstabugWidgetsBindingObserver get instance => _instance; + + /// Shorthand for [instance] + static InstabugWidgetsBindingObserver get I => instance; + + /// Logging tag for debugging purposes. + static const tag = "InstabugWidgetsBindingObserver"; + void _handleResumedState() { log('Performing resume actions...'); final lastUiTrace = ScreenLoadingManager.I.currentUiTrace; if (lastUiTrace != null) { final maskedScreenName = ScreenNameMasker.I.mask(lastUiTrace.screenName); ScreenLoadingManager.I - .startUiTrace(maskedScreenName, lastUiTrace.screenName); + .startUiTrace(maskedScreenName, lastUiTrace.screenName) + .then((uiTraceId) { + if (uiTraceId != null) { + InstabugScreenRenderManager.I + .startScreenRenderCollectorForTraceId(uiTraceId); + } + }); } - // ... complex logic for resumed state } void _handlePausedState() { - // ... complex logic for paused state log('Performing pause actions...'); InstabugScreenRenderManager.I.stopScreenRenderCollector(); } @@ -29,7 +44,6 @@ class InstabugWidgetsBindingObserver extends WidgetsBindingObserver { void _handleDetachedState() { log('Performing detached actions...'); InstabugScreenRenderManager.I.stopScreenRenderCollector(); - // ... complex logic for paused state } @override @@ -53,3 +67,12 @@ class InstabugWidgetsBindingObserver extends WidgetsBindingObserver { } } } + +@internal +void checkForWidgetBinding() { + try { + WidgetsBinding.instance; + } catch (_) { + WidgetsFlutterBinding.ensureInitialized(); + } +} diff --git a/test/utils/screen_render/instabug_screen_render_manager_test.dart b/test/utils/screen_render/instabug_screen_render_manager_test.dart new file mode 100644 index 000000000..1f0f404b0 --- /dev/null +++ b/test/utils/screen_render/instabug_screen_render_manager_test.dart @@ -0,0 +1,364 @@ +import 'dart:ui'; + +import 'package:flutter/widgets.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:instabug_flutter/instabug_flutter.dart'; +import 'package:instabug_flutter/src/generated/apm.api.g.dart'; +import 'package:instabug_flutter/src/models/InstabugFrameData.dart'; +import 'package:instabug_flutter/src/models/InstabugScreenRenderData.dart'; +import 'package:instabug_flutter/src/utils/screen_rendering/instabug_screen_render_manager.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; + +import 'instabug_screen_render_manager_test.mocks.dart'; + +@GenerateMocks([FrameTiming, ApmHostApi, WidgetsBinding]) +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + late InstabugScreenRenderManager manager; + late MockApmHostApi mApmHost; + late MockWidgetsBinding mWidgetBinding; + + setUp(() async { + mApmHost = MockApmHostApi(); + mWidgetBinding = MockWidgetsBinding(); + manager = InstabugScreenRenderManager.init(); // test-only constructor + APM.$setHostApi(mApmHost); + + when(mApmHost.deviceRefreshRate()).thenAnswer((_) async => 60); + await manager.init(mWidgetBinding); + await untilCalled(mApmHost.deviceRefreshRate()); + }); + + tearDown(() { + // Clean up state after each test + }); + + group('InstabugScreenRenderManager.init()', () { + test('should initialize timings callback and add observer', () async { + expect(manager, isA()); + + verify(mWidgetBinding.addObserver(any)).called(1); + + verify(mWidgetBinding.addTimingsCallback(any)).called(1); + }); + + test('calling init more that one time should do nothing', () async { + await manager.init(mWidgetBinding); + await manager.init(mWidgetBinding); // second call should be ignored + + + verify(mWidgetBinding.addObserver(any)).called(1); + + verify(mWidgetBinding.addTimingsCallback(any)).called(1); + + expect(true, isTrue); // no crash + }); + }); + + group('startScreenRenderCollectorForTraceId()', () { + test('should not attach timing listener if it is attached', () async { + manager.startScreenRenderCollectorForTraceId(1); + manager.startScreenRenderCollectorForTraceId(2); + manager.startScreenRenderCollectorForTraceId(3); + + verify(mWidgetBinding.addTimingsCallback(any)).called( + 1, + ); // the one form init() + }); + + test( + 'should report data to native when starting new trace from the same type', + () async { + ///todo: will be implemented in next sprint + }); + + test('should attach timing listener if it is not attached', () async { + manager.stopScreenRenderCollector(); // this should detach listener safely + + manager.startScreenRenderCollectorForTraceId(1); + + verify(mWidgetBinding.addTimingsCallback(any)).called( + 2, + ); // one form init() and one form startScreenRenderCollectorForTraceId() + }); + + test('should update the data for same trace type', () { + const firstTraceId = 123; + const secondTraceId = 456; + + expect(manager.screenRenderForAutoUiTrace.isNotEmpty, false); + + manager.startScreenRenderCollectorForTraceId( + firstTraceId, UiTraceType.auto); + expect(manager.screenRenderForAutoUiTrace.isNotEmpty, true); + expect(manager.screenRenderForAutoUiTrace.traceId, firstTraceId); + + manager.startScreenRenderCollectorForTraceId( + secondTraceId, UiTraceType.auto); + expect(manager.screenRenderForAutoUiTrace.isNotEmpty, true); + expect(manager.screenRenderForAutoUiTrace.traceId, secondTraceId); + }); + + test('should not update the data for same trace type', () { + const firstTraceId = 123; + const secondTraceId = 456; + + expect(manager.screenRenderForAutoUiTrace.isNotEmpty, false); + expect(manager.screenRenderForCustomUiTrace.isNotEmpty, false); + + manager.startScreenRenderCollectorForTraceId( + firstTraceId, UiTraceType.auto); + expect(manager.screenRenderForAutoUiTrace.isNotEmpty, true); + expect(manager.screenRenderForAutoUiTrace.traceId, firstTraceId); + + manager.startScreenRenderCollectorForTraceId( + secondTraceId, UiTraceType.custom); + expect(manager.screenRenderForAutoUiTrace.traceId, firstTraceId); + expect(manager.screenRenderForCustomUiTrace.traceId, secondTraceId); + }); + }); + + group('stopScreenRenderCollector()', () { + test('should not save data if no UI trace is started', () { + final frameTestdata = InstabugScreenRenderData( + traceId: 123, + frameData: [ + InstabugFrameData(10000, 200), + InstabugFrameData(20000, 1000), + ], + frozenFramesTotalDuration: 1000, + slowFramesTotalDuration: 200, + ); + + manager.setFrameData(frameTestdata); + + manager.stopScreenRenderCollector(); + + expect(manager.screenRenderForAutoUiTrace.isEmpty, true); + expect(manager.screenRenderForAutoUiTrace == frameTestdata, false); + + expect(manager.screenRenderForCustomUiTrace.isEmpty, true); + expect(manager.screenRenderForCustomUiTrace == frameTestdata, false); + }); + + test( + 'should save and data to screenRenderForAutoUiTrace when for autoUITrace', + () { + final frameTestdata = InstabugScreenRenderData( + traceId: 123, + frameData: [ + InstabugFrameData(10000, 200), + InstabugFrameData(20000, 1000), + ], + frozenFramesTotalDuration: 1000, + slowFramesTotalDuration: 200, + ); + + manager.startScreenRenderCollectorForTraceId( + frameTestdata.traceId, + UiTraceType.auto, + ); + + manager.setFrameData(frameTestdata); + + manager.stopScreenRenderCollector(); + + expect(manager.screenRenderForAutoUiTrace.isNotEmpty, true); + + expect(manager.screenRenderForAutoUiTrace == frameTestdata, true); + + expect(manager.screenRenderForCustomUiTrace.isEmpty, true); + }); + + test( + 'should save and data to screenRenderForCustomUiTrace when for customUITrace', + () { + final frameTestdata = InstabugScreenRenderData( + traceId: 123, + frameData: [ + InstabugFrameData(10000, 200), + InstabugFrameData(20000, 1000), + ], + frozenFramesTotalDuration: 1000, + slowFramesTotalDuration: 200, + ); + + manager.startScreenRenderCollectorForTraceId( + frameTestdata.traceId, + UiTraceType.custom, + ); + + manager.setFrameData(frameTestdata); + + manager.stopScreenRenderCollector(); + + expect(manager.screenRenderForCustomUiTrace.isNotEmpty, true); + + expect(manager.screenRenderForCustomUiTrace == frameTestdata, true); + + expect(manager.screenRenderForAutoUiTrace.isEmpty, true); + }); + + test('should remove timing callback listener', () { + manager.stopScreenRenderCollector(); + + verify(mWidgetBinding.removeTimingsCallback(any)).called(1); + }); + + test( + 'should report data to native when starting new trace from the same type', + () async { + ///todo: will be implemented in next sprint + }); + }); + + group('endScreenRenderCollectorForCustomUiTrace()', () { + setUp(() { + manager.screenRenderForAutoUiTrace.clear(); + manager.screenRenderForCustomUiTrace.clear(); + }); + + test('should not save data if no custom UI trace is started', () { + final frameTestdata = InstabugScreenRenderData( + traceId: 123, + frameData: [ + InstabugFrameData(10000, 200), + InstabugFrameData(20000, 1000), + ], + frozenFramesTotalDuration: 1000, + slowFramesTotalDuration: 200, + ); + + manager.setFrameData(frameTestdata); + + manager.endScreenRenderCollectorForCustomUiTrace(); + + expect(manager.screenRenderForCustomUiTrace.isEmpty, true); + expect(manager.screenRenderForCustomUiTrace == frameTestdata, false); + }); + + test( + 'should save data to screenRenderForCustomUiTrace if custom UI trace is started', + () { + final frameTestdata = InstabugScreenRenderData( + traceId: 123, + frameData: [ + InstabugFrameData(10000, 200), + InstabugFrameData(20000, 1000), + ], + frozenFramesTotalDuration: 1000, + slowFramesTotalDuration: 200, + ); + + manager.startScreenRenderCollectorForTraceId( + frameTestdata.traceId, + UiTraceType.custom, + ); + + manager.setFrameData(frameTestdata); + + manager.endScreenRenderCollectorForCustomUiTrace(); + }); + + test('should not remove timing callback listener', () { + manager.endScreenRenderCollectorForCustomUiTrace(); + + verifyNever(mWidgetBinding.removeTimingsCallback(any)); + }); + + test( + 'should report data to native when starting new trace from the same type', + () async { + ///todo: will be implemented in next sprint + }); + }); + + group('analyzeFrameTiming()', () { + late MockFrameTiming mockFrameTiming; + + setUp(() { + mockFrameTiming = MockFrameTiming(); + when(mockFrameTiming.buildDuration) + .thenReturn(const Duration(milliseconds: 1)); + when(mockFrameTiming.rasterDuration) + .thenReturn(const Duration(milliseconds: 1)); + when(mockFrameTiming.totalSpan) + .thenReturn(const Duration(milliseconds: 2)); + when(mockFrameTiming.timestampInMicroseconds(any)).thenReturn(1000); + }); + + test('should detect slow frame on ui thread and record duration', () { + const buildDuration = 20; + when(mockFrameTiming.buildDuration) + .thenReturn(const Duration(milliseconds: buildDuration)); + + manager.startScreenRenderCollectorForTraceId(1); // start new collector + manager.analyzeFrameTiming(mockFrameTiming); // mock frame timing + manager.stopScreenRenderCollector(); // should save data + + expect(manager.screenRenderForAutoUiTrace.frameData.length, 1); + expect(manager.screenRenderForAutoUiTrace.slowFramesTotalDuration, buildDuration *1000); // * 1000 to convert from milli to micro + expect(manager.screenRenderForAutoUiTrace.frozenFramesTotalDuration, 0); + + }); + + test('should detect slow frame on raster thread and record duration', () { + const rasterDuration = 20; + when(mockFrameTiming.rasterDuration) + .thenReturn(const Duration(milliseconds: rasterDuration)); + + manager.startScreenRenderCollectorForTraceId(1); // start new collector + manager.analyzeFrameTiming(mockFrameTiming); // mock frame timing + manager.stopScreenRenderCollector(); // should save data + + expect(manager.screenRenderForAutoUiTrace.frameData.length, 1); + expect(manager.screenRenderForAutoUiTrace.slowFramesTotalDuration, rasterDuration *1000); // * 1000 to convert from milli to micro + expect(manager.screenRenderForAutoUiTrace.frozenFramesTotalDuration, 0); + + }); + + test('should detect frozen frame on build thread when durations are greater than or equal 700 ms', () { + const buildDuration = 700; + when(mockFrameTiming.buildDuration) + .thenReturn(const Duration(milliseconds: buildDuration)); + manager.startScreenRenderCollectorForTraceId(1); // start new collector + manager.analyzeFrameTiming(mockFrameTiming); // mock frame timing + manager.stopScreenRenderCollector(); // should save data + + expect(manager.screenRenderForAutoUiTrace.frameData.length, 1); + expect(manager.screenRenderForAutoUiTrace.frozenFramesTotalDuration, buildDuration *1000); // * 1000 to convert from milli to micro + expect(manager.screenRenderForAutoUiTrace.slowFramesTotalDuration, 0); + + }); + + test('should detect frozen frame on raster thread when durations are greater than or equal 700 ms', () { + const rasterBuild = 700; + when(mockFrameTiming.buildDuration) + .thenReturn(const Duration(milliseconds: rasterBuild)); + manager.startScreenRenderCollectorForTraceId(1); // start new collector + manager.analyzeFrameTiming(mockFrameTiming); // mock frame timing + manager.stopScreenRenderCollector(); // should save data + + expect(manager.screenRenderForAutoUiTrace.frameData.length, 1); + expect(manager.screenRenderForAutoUiTrace.frozenFramesTotalDuration, rasterBuild *1000); // * 1000 to convert from milli to micro + expect(manager.screenRenderForAutoUiTrace.slowFramesTotalDuration, 0); + + }); + + test('should detect no slow or frozen frame under thresholds', () { + when(mockFrameTiming.buildDuration) + .thenReturn(const Duration(milliseconds: 5)); + when(mockFrameTiming.rasterDuration) + .thenReturn(const Duration(milliseconds: 5)); + when(mockFrameTiming.totalSpan) + .thenReturn(const Duration(milliseconds: 10)); + manager.analyzeFrameTiming(mockFrameTiming); + expect(manager.screenRenderForAutoUiTrace.frameData.isEmpty, true); + expect(manager.screenRenderForAutoUiTrace.frozenFramesTotalDuration, 0); // * 1000 to convert from milli to micro + expect(manager.screenRenderForAutoUiTrace.slowFramesTotalDuration, 0); + + }); + }); +} From 2faf643042e20554f05c6e12b77207af5b9cd1b8 Mon Sep 17 00:00:00 2001 From: Andrew Amin Date: Wed, 18 Jun 2025 13:54:50 +0300 Subject: [PATCH 03/15] chore: add unit tests for app lifecycle --- .../instabug_screen_render_manager.dart | 10 +- ...instabug_widget_binding_observer_test.dart | 103 ++++++++++++++++++ 2 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 test/utils/screen_render/instabug_widget_binding_observer_test.dart diff --git a/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart b/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart index 55baed043..e5f1cd775 100644 --- a/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart +++ b/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart @@ -40,7 +40,7 @@ class InstabugScreenRenderManager { InstabugScreenRenderManager._(); - static final InstabugScreenRenderManager _instance = + static InstabugScreenRenderManager _instance = InstabugScreenRenderManager._(); /// Returns the singleton instance of [InstabugScreenRenderManager]. @@ -53,10 +53,16 @@ class InstabugScreenRenderManager { static const tag = "ScreenRenderManager"; /// A named constructor used for testing purposes - + @internal @visibleForTesting InstabugScreenRenderManager.init(); + /// Allows setting a custom instance for testing. + @visibleForTesting + // ignore: use_setters_to_change_properties + static void setInstance(InstabugScreenRenderManager instance) { + _instance = instance; + } /// setup function for [InstabugScreenRenderManager] @internal Future init(WidgetsBinding widgetBinding) async { diff --git a/test/utils/screen_render/instabug_widget_binding_observer_test.dart b/test/utils/screen_render/instabug_widget_binding_observer_test.dart new file mode 100644 index 000000000..8c5d952c5 --- /dev/null +++ b/test/utils/screen_render/instabug_widget_binding_observer_test.dart @@ -0,0 +1,103 @@ +import 'package:flutter/widgets.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:instabug_flutter/src/utils/screen_loading/screen_loading_manager.dart'; +import 'package:instabug_flutter/src/utils/screen_name_masker.dart'; +import 'package:instabug_flutter/src/utils/screen_rendering/instabug_screen_render_manager.dart'; +import 'package:instabug_flutter/src/utils/screen_rendering/instabug_widget_binding_observer.dart'; +import 'package:instabug_flutter/src/utils/ui_trace/ui_trace.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; + +import 'instabug_widget_binding_observer_test.mocks.dart'; + +@GenerateMocks([ + InstabugScreenRenderManager, + ScreenLoadingManager, + ScreenNameMasker, + UiTrace, +]) +void main() { + late MockInstabugScreenRenderManager mockRenderManager; + late MockScreenLoadingManager mockLoadingManager; + late MockScreenNameMasker mockNameMasker; + late MockUiTrace mockUiTrace; + + setUp(() { + mockRenderManager = MockInstabugScreenRenderManager(); + mockLoadingManager = MockScreenLoadingManager(); + mockNameMasker = MockScreenNameMasker(); + mockUiTrace = MockUiTrace(); + + // Inject singleton mocks + InstabugScreenRenderManager.setInstance(mockRenderManager); + ScreenLoadingManager.setInstance(mockLoadingManager); + ScreenNameMasker.setInstance(mockNameMasker); + }); + + group('InstabugWidgetsBindingObserver', () { + test('returns the singleton instance', () { + final instance = InstabugWidgetsBindingObserver.instance; + final shorthand = InstabugWidgetsBindingObserver.I; + expect(instance, isA()); + expect(shorthand, same(instance)); + }); + + test('handles AppLifecycleState.resumed and starts UiTrace', () async { + when(mockLoadingManager.currentUiTrace).thenReturn(mockUiTrace); + when(mockUiTrace.screenName).thenReturn("HomeScreen"); + when(mockNameMasker.mask("HomeScreen")).thenReturn("MaskedHome"); + when(mockLoadingManager.startUiTrace("MaskedHome", "HomeScreen")) + .thenAnswer((_) async => 123); + + InstabugWidgetsBindingObserver.I + .didChangeAppLifecycleState(AppLifecycleState.resumed); + + // wait for async call to complete + await untilCalled( + mockRenderManager.startScreenRenderCollectorForTraceId(123)); + + verify(mockRenderManager.startScreenRenderCollectorForTraceId(123)) + .called(1); + }); + + test('handles AppLifecycleState.paused and stops render collector', () { + InstabugWidgetsBindingObserver.I + .didChangeAppLifecycleState(AppLifecycleState.paused); + verify(mockRenderManager.stopScreenRenderCollector()).called(1); + }); + + test('handles AppLifecycleState.detached and stops render collector', () { + InstabugWidgetsBindingObserver.I + .didChangeAppLifecycleState(AppLifecycleState.detached); + verify(mockRenderManager.stopScreenRenderCollector()).called(1); + }); + + test('handles AppLifecycleState.inactive with no action', () { + // Just ensure it doesn't crash + expect(() { + InstabugWidgetsBindingObserver.I + .didChangeAppLifecycleState(AppLifecycleState.inactive); + }, returnsNormally); + }); + + test('handles AppLifecycleState.hidden with no action', () { + expect(() { + InstabugWidgetsBindingObserver.I + .didChangeAppLifecycleState(AppLifecycleState.hidden); + }, returnsNormally); + }); + + test('_handleResumedState does nothing if no currentUiTrace', () { + when(mockLoadingManager.currentUiTrace).thenReturn(null); + + InstabugWidgetsBindingObserver.I + .didChangeAppLifecycleState(AppLifecycleState.resumed); + + verifyNever(mockRenderManager.startScreenRenderCollectorForTraceId(any)); + }); + + test('checkForWidgetBinding ensures initialization', () { + expect(() => checkForWidgetBinding(), returnsNormally); + }); + }); +} From 21cc57baa8d9eb6a57fc20d51293744cf50934ca Mon Sep 17 00:00:00 2001 From: Andrew Amin Date: Thu, 19 Jun 2025 21:42:07 +0300 Subject: [PATCH 04/15] chore: fix related uint testing files , fix implementation logic. --- .../lib/src/screens/screen_render_page.dart | 31 +++++-- lib/src/modules/instabug.dart | 2 +- .../utils/instabug_navigator_observer.dart | 3 +- .../instabug_screen_render_manager.dart | 55 +++++++------ .../instabug_widget_binding_observer.dart | 6 +- test/apm_test.dart | 6 +- test/instabug_test.dart | 8 ++ .../instabug_navigator_observer_test.dart | 9 +-- .../instabug_screen_render_manager_test.dart | 81 ++++++++++++------- ...instabug_widget_binding_observer_test.dart | 26 +++--- 10 files changed, 144 insertions(+), 83 deletions(-) diff --git a/example/lib/src/screens/screen_render_page.dart b/example/lib/src/screens/screen_render_page.dart index 924eefab2..a6c97cb23 100644 --- a/example/lib/src/screens/screen_render_page.dart +++ b/example/lib/src/screens/screen_render_page.dart @@ -1,17 +1,32 @@ part of '../../main.dart'; -class ScreenRenderPage extends StatelessWidget { +class ScreenRenderPage extends StatefulWidget { const ScreenRenderPage({Key? key}) : super(key: key); static const String screenName = "/screenRenderPageRoute"; + @override + State createState() => _ScreenRenderPageState(); +} + +class _ScreenRenderPageState extends State { + final durationController = TextEditingController(); + @override Widget build(BuildContext context) { return Page(title: 'Screen Render', children: [ - + SizedBox.fromSize(size: const Size.fromHeight(16.0)), const AnimatedBox(), - SizedBox.fromSize(size: const Size.fromHeight(50),), + SizedBox.fromSize( + size: const Size.fromHeight(50), + ), + InstabugTextField( + label: 'Frame duration in milliseconds', + labelStyle: Theme.of(context).textTheme.labelMedium, + controller: durationController, + ), + SizedBox.fromSize(size: const Size.fromHeight(16.0)), InstabugButton( - text: 'Perform Frozen Frame', + text: 'Perform Heavy Computation', onPressed: () => _simulateHeavyComputation(), ), InstabugButton( @@ -36,9 +51,13 @@ class ScreenRenderPage extends StatelessWidget { // Simulates a computationally expensive task void _simulateHeavyComputation() { final startTime = DateTime.now(); + final pauseTime = double.tryParse(durationController.text.trim()); // Block the UI thread for ~500ms - while (DateTime.now().difference(startTime).inMilliseconds <= 1000) { - // Busy waiting (not recommended in real apps) + if (pauseTime == null) { + return log("enter a valid number"); + } + while (DateTime.now().difference(startTime).inMilliseconds <= pauseTime) { + // Busy waiting } } } diff --git a/lib/src/modules/instabug.dart b/lib/src/modules/instabug.dart index 0a832526b..4b079ab99 100644 --- a/lib/src/modules/instabug.dart +++ b/lib/src/modules/instabug.dart @@ -198,7 +198,7 @@ class Instabug { if (await FlagsConfig.screenRendering.isEnabled()) { checkForWidgetBinding(); - await InstabugScreenRenderManager.I.init(WidgetsBinding.instance); + InstabugScreenRenderManager.I.init(WidgetsBinding.instance); } return FeatureFlagsManager().registerW3CFlagsListener(); diff --git a/lib/src/utils/instabug_navigator_observer.dart b/lib/src/utils/instabug_navigator_observer.dart index e185347ad..775236f2b 100644 --- a/lib/src/utils/instabug_navigator_observer.dart +++ b/lib/src/utils/instabug_navigator_observer.dart @@ -28,7 +28,8 @@ class InstabugNavigatorObserver extends NavigatorObserver { ScreenLoadingManager.I .startUiTrace(maskedScreenName, screenName) .then((uiTraceId) { - if (uiTraceId != null) { + if (uiTraceId != null && + InstabugScreenRenderManager.I.screenRenderEnabled) { InstabugScreenRenderManager.I .startScreenRenderCollectorForTraceId(uiTraceId); } diff --git a/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart b/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart index e5f1cd775..bc5c7fc71 100644 --- a/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart +++ b/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart @@ -8,6 +8,7 @@ import 'package:instabug_flutter/src/modules/apm.dart'; import 'package:instabug_flutter/src/utils/screen_rendering/instabug_widget_binding_observer.dart'; import 'package:meta/meta.dart'; +//todo: remove logs extension on int { int get inMicro => this * 1000; } @@ -37,10 +38,10 @@ class InstabugScreenRenderManager { int _frozenFramesTotalDuration = 0; bool _isTimingsListenerAttached = false; - + bool screenRenderEnabled = false; InstabugScreenRenderManager._(); - static InstabugScreenRenderManager _instance = + static InstabugScreenRenderManager _instance = InstabugScreenRenderManager._(); /// Returns the singleton instance of [InstabugScreenRenderManager]. @@ -52,25 +53,15 @@ class InstabugScreenRenderManager { /// Logging tag for debugging purposes. static const tag = "ScreenRenderManager"; - /// A named constructor used for testing purposes - @internal - @visibleForTesting - InstabugScreenRenderManager.init(); - - /// Allows setting a custom instance for testing. - @visibleForTesting - // ignore: use_setters_to_change_properties - static void setInstance(InstabugScreenRenderManager instance) { - _instance = instance; - } /// setup function for [InstabugScreenRenderManager] @internal - Future init(WidgetsBinding widgetBinding) async { + void init(WidgetsBinding widgetBinding, [double? refreshRate]) { if (!_isTimingsListenerAttached) { _widgetsBinding = widgetBinding; _addWidgetBindingObserver(); - await _initStaticValues(); + _initStaticValues(refreshRate); _initFrameTimings(); + screenRenderEnabled = true; } } @@ -153,22 +144,24 @@ class InstabugScreenRenderManager { /// Presently, on Android and Web this collection will only contain the display that the current window is on. /// On iOS, it will only contains the main display on the phone or tablet. /// On Desktop, it will contain only a main display with a valid refresh rate but invalid size and device pixel ratio values. - //todo: will be removed after getting the actual value from native side. + //todo: will be compared with value from native side after it's implemented. double get _getDeviceRefreshRate => - _widgetsBinding.platformDispatcher.displays.last.refreshRate; + _widgetsBinding.platformDispatcher.displays.first.refreshRate; /// Get device refresh rate from native side. + //todo: will be compared with value from native side after it's implemented. + // ignore: unused_element Future get _getDeviceRefreshRateFromNative => APM.getDeviceRefreshRate(); /// Initialize the static variables - Future _initStaticValues() async { + void _initStaticValues(double? refreshRate) { _timingsCallback = (timings) { for (final frameTiming in timings) { analyzeFrameTiming(frameTiming); } }; - _deviceRefreshRate = await _getDeviceRefreshRateFromNative; + _deviceRefreshRate = refreshRate ?? _getDeviceRefreshRate; _slowFrameThresholdMs = _targetMsPerFrame(_deviceRefreshRate); _screenRenderForAutoUiTrace = InstabugScreenRenderData(frameData: []); _screenRenderForCustomUiTrace = InstabugScreenRenderData(frameData: []); @@ -270,7 +263,7 @@ class InstabugScreenRenderManager { _delayedFrames.add(InstabugFrameData(startTime, duration)); } - //todo: to be removed + //todo: will be removed void _displayFrameTimingDetails(FrameTiming frameTiming) { if (_isSlow) { debugPrint( @@ -306,15 +299,19 @@ class InstabugScreenRenderManager { } @visibleForTesting - Future reportScreenRending(InstabugScreenRenderData screenRenderData, - [UiTraceType type = UiTraceType.auto]) async { + Future reportScreenRending( + InstabugScreenRenderData screenRenderData, [ + UiTraceType type = UiTraceType.auto, + ]) async { if (type == UiTraceType.auto) { _reportScreenRenderForAutoUiTrace(screenRenderData); } else { _reportScreenRenderForCustomUiTrace(screenRenderData); } - log("Reported Data (${type == UiTraceType.auto ? 'auto' : 'custom'}): $screenRenderData", - name: tag); + log( + "Reported Data (${type == UiTraceType.auto ? 'auto' : 'custom'}): $screenRenderData", + name: tag, + ); } Future _reportScreenRenderForCustomUiTrace( @@ -348,6 +345,16 @@ class InstabugScreenRenderManager { } /// --------------------------- testing helper functions --------------------- + + @visibleForTesting + InstabugScreenRenderManager.init(); + + @visibleForTesting + // ignore: use_setters_to_change_properties + static void setInstance(InstabugScreenRenderManager instance) { + _instance = instance; + } + @visibleForTesting InstabugScreenRenderData get screenRenderForAutoUiTrace => _screenRenderForAutoUiTrace; diff --git a/lib/src/utils/screen_rendering/instabug_widget_binding_observer.dart b/lib/src/utils/screen_rendering/instabug_widget_binding_observer.dart index 053beaed8..caf768be3 100644 --- a/lib/src/utils/screen_rendering/instabug_widget_binding_observer.dart +++ b/lib/src/utils/screen_rendering/instabug_widget_binding_observer.dart @@ -5,11 +5,12 @@ import 'package:instabug_flutter/src/utils/screen_name_masker.dart'; import 'package:instabug_flutter/src/utils/screen_rendering/instabug_screen_render_manager.dart'; import 'package:meta/meta.dart'; +//todo: remove logs class InstabugWidgetsBindingObserver extends WidgetsBindingObserver { InstabugWidgetsBindingObserver._(); static final InstabugWidgetsBindingObserver _instance = - InstabugWidgetsBindingObserver._(); + InstabugWidgetsBindingObserver._(); /// Returns the singleton instance of [InstabugWidgetsBindingObserver]. static InstabugWidgetsBindingObserver get instance => _instance; @@ -28,7 +29,8 @@ class InstabugWidgetsBindingObserver extends WidgetsBindingObserver { ScreenLoadingManager.I .startUiTrace(maskedScreenName, lastUiTrace.screenName) .then((uiTraceId) { - if (uiTraceId != null) { + if (uiTraceId != null && + InstabugScreenRenderManager.I.screenRenderEnabled) { InstabugScreenRenderManager.I .startScreenRenderCollectorForTraceId(uiTraceId); } diff --git a/test/apm_test.dart b/test/apm_test.dart index c801926f3..4e8ec87a6 100644 --- a/test/apm_test.dart +++ b/test/apm_test.dart @@ -165,6 +165,9 @@ void main() { test('[startUITrace] should call host method', () async { const name = 'UI-trace'; + //disable the feature flag for screen render feature in order to skip its checking. + when(mHost.isScreenRenderEnabled()).thenAnswer((_) async => false); + await APM.startUITrace(name); verify( @@ -214,7 +217,6 @@ void main() { verify( mHost.startCpUiTrace(screenName, microTimeStamp, traceId), ).called(1); - verifyNoMoreInteractions(mHost); }); test('[reportScreenLoading] should call host method', () async { @@ -235,7 +237,6 @@ void main() { uiTraceId, ), ).called(1); - verifyNoMoreInteractions(mHost); }); test('[endScreenLoading] should call host method', () async { @@ -247,7 +248,6 @@ void main() { verify( mHost.endScreenLoadingCP(timeStampMicro, uiTraceId), ).called(1); - verifyNoMoreInteractions(mHost); }); test('[isSEndScreenLoadingEnabled] should call host method', () async { diff --git a/test/instabug_test.dart b/test/instabug_test.dart index e2fd7d298..3afb6648c 100644 --- a/test/instabug_test.dart +++ b/test/instabug_test.dart @@ -3,6 +3,7 @@ import 'dart:typed_data'; import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:instabug_flutter/instabug_flutter.dart'; +import 'package:instabug_flutter/src/generated/apm.api.g.dart'; import 'package:instabug_flutter/src/generated/instabug.api.g.dart'; import 'package:instabug_flutter/src/utils/enum_converter.dart'; import 'package:instabug_flutter/src/utils/feature_flags_manager.dart'; @@ -17,6 +18,7 @@ import 'instabug_test.mocks.dart'; InstabugHostApi, IBGBuildInfo, ScreenNameMasker, + ApmHostApi, ]) void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -25,12 +27,14 @@ void main() { final mHost = MockInstabugHostApi(); final mBuildInfo = MockIBGBuildInfo(); final mScreenNameMasker = MockScreenNameMasker(); + final mApmHost = MockApmHostApi(); setUpAll(() { Instabug.$setHostApi(mHost); FeatureFlagsManager().$setHostApi(mHost); IBGBuildInfo.setInstance(mBuildInfo); ScreenNameMasker.setInstance(mScreenNameMasker); + APM.$setHostApi(mApmHost); }); test('[setEnabled] should call host method', () async { @@ -78,6 +82,10 @@ void main() { "isW3cCaughtHeaderEnabled": true, }), ); + + //disable the feature flag for screen render feature in order to skip its checking. + when(mApmHost.isScreenRenderEnabled()).thenAnswer((_) async => false); + await Instabug.init( token: token, invocationEvents: events, diff --git a/test/utils/instabug_navigator_observer_test.dart b/test/utils/instabug_navigator_observer_test.dart index ebf541137..81a9f174e 100644 --- a/test/utils/instabug_navigator_observer_test.dart +++ b/test/utils/instabug_navigator_observer_test.dart @@ -10,13 +10,10 @@ import 'package:mockito/mockito.dart'; import 'instabug_navigator_observer_test.mocks.dart'; -@GenerateMocks([ - InstabugHostApi, - ScreenLoadingManager, -]) +@GenerateMocks([InstabugHostApi]) +@GenerateNiceMocks([MockSpec()]) void main() { TestWidgetsFlutterBinding.ensureInitialized(); - WidgetsFlutterBinding.ensureInitialized(); final mHost = MockInstabugHostApi(); final mScreenLoadingManager = MockScreenLoadingManager(); @@ -41,7 +38,7 @@ void main() { }); test('should report screen change when a route is pushed', () { - fakeAsync((async) { + fakeAsync((async) async { observer.didPush(route, previousRoute); async.elapse(const Duration(milliseconds: 1000)); diff --git a/test/utils/screen_render/instabug_screen_render_manager_test.dart b/test/utils/screen_render/instabug_screen_render_manager_test.dart index 1f0f404b0..37879753a 100644 --- a/test/utils/screen_render/instabug_screen_render_manager_test.dart +++ b/test/utils/screen_render/instabug_screen_render_manager_test.dart @@ -19,6 +19,7 @@ void main() { late InstabugScreenRenderManager manager; late MockApmHostApi mApmHost; late MockWidgetsBinding mWidgetBinding; + const mRefreshRate = 60.0; setUp(() async { mApmHost = MockApmHostApi(); @@ -26,9 +27,7 @@ void main() { manager = InstabugScreenRenderManager.init(); // test-only constructor APM.$setHostApi(mApmHost); - when(mApmHost.deviceRefreshRate()).thenAnswer((_) async => 60); - await manager.init(mWidgetBinding); - await untilCalled(mApmHost.deviceRefreshRate()); + manager.init(mWidgetBinding, mRefreshRate); }); tearDown(() { @@ -45,9 +44,11 @@ void main() { }); test('calling init more that one time should do nothing', () async { - await manager.init(mWidgetBinding); - await manager.init(mWidgetBinding); // second call should be ignored - + manager.init(mWidgetBinding, mRefreshRate); + manager.init( + mWidgetBinding, + mRefreshRate, + ); // second call should be ignored verify(mWidgetBinding.addObserver(any)).called(1); @@ -65,7 +66,7 @@ void main() { verify(mWidgetBinding.addTimingsCallback(any)).called( 1, - ); // the one form init() + ); // the one form initForTesting() }); test( @@ -81,7 +82,7 @@ void main() { verify(mWidgetBinding.addTimingsCallback(any)).called( 2, - ); // one form init() and one form startScreenRenderCollectorForTraceId() + ); // one form initForTesting() and one form startScreenRenderCollectorForTraceId() }); test('should update the data for same trace type', () { @@ -91,12 +92,14 @@ void main() { expect(manager.screenRenderForAutoUiTrace.isNotEmpty, false); manager.startScreenRenderCollectorForTraceId( - firstTraceId, UiTraceType.auto); + firstTraceId, + ); expect(manager.screenRenderForAutoUiTrace.isNotEmpty, true); expect(manager.screenRenderForAutoUiTrace.traceId, firstTraceId); manager.startScreenRenderCollectorForTraceId( - secondTraceId, UiTraceType.auto); + secondTraceId, + ); expect(manager.screenRenderForAutoUiTrace.isNotEmpty, true); expect(manager.screenRenderForAutoUiTrace.traceId, secondTraceId); }); @@ -109,12 +112,15 @@ void main() { expect(manager.screenRenderForCustomUiTrace.isNotEmpty, false); manager.startScreenRenderCollectorForTraceId( - firstTraceId, UiTraceType.auto); + firstTraceId, + ); expect(manager.screenRenderForAutoUiTrace.isNotEmpty, true); expect(manager.screenRenderForAutoUiTrace.traceId, firstTraceId); manager.startScreenRenderCollectorForTraceId( - secondTraceId, UiTraceType.custom); + secondTraceId, + UiTraceType.custom, + ); expect(manager.screenRenderForAutoUiTrace.traceId, firstTraceId); expect(manager.screenRenderForCustomUiTrace.traceId, secondTraceId); }); @@ -158,7 +164,6 @@ void main() { manager.startScreenRenderCollectorForTraceId( frameTestdata.traceId, - UiTraceType.auto, ); manager.setFrameData(frameTestdata); @@ -209,9 +214,9 @@ void main() { test( 'should report data to native when starting new trace from the same type', - () async { - ///todo: will be implemented in next sprint - }); + () async { + ///todo: will be implemented in next sprint + }); }); group('endScreenRenderCollectorForCustomUiTrace()', () { @@ -270,9 +275,9 @@ void main() { test( 'should report data to native when starting new trace from the same type', - () async { - ///todo: will be implemented in next sprint - }); + () async { + ///todo: will be implemented in next sprint + }); }); group('analyzeFrameTiming()', () { @@ -299,9 +304,11 @@ void main() { manager.stopScreenRenderCollector(); // should save data expect(manager.screenRenderForAutoUiTrace.frameData.length, 1); - expect(manager.screenRenderForAutoUiTrace.slowFramesTotalDuration, buildDuration *1000); // * 1000 to convert from milli to micro + expect( + manager.screenRenderForAutoUiTrace.slowFramesTotalDuration, + buildDuration * 1000, + ); // * 1000 to convert from milli to micro expect(manager.screenRenderForAutoUiTrace.frozenFramesTotalDuration, 0); - }); test('should detect slow frame on raster thread and record duration', () { @@ -314,12 +321,16 @@ void main() { manager.stopScreenRenderCollector(); // should save data expect(manager.screenRenderForAutoUiTrace.frameData.length, 1); - expect(manager.screenRenderForAutoUiTrace.slowFramesTotalDuration, rasterDuration *1000); // * 1000 to convert from milli to micro + expect( + manager.screenRenderForAutoUiTrace.slowFramesTotalDuration, + rasterDuration * 1000, + ); // * 1000 to convert from milli to micro expect(manager.screenRenderForAutoUiTrace.frozenFramesTotalDuration, 0); - }); - test('should detect frozen frame on build thread when durations are greater than or equal 700 ms', () { + test( + 'should detect frozen frame on build thread when durations are greater than or equal 700 ms', + () { const buildDuration = 700; when(mockFrameTiming.buildDuration) .thenReturn(const Duration(milliseconds: buildDuration)); @@ -328,12 +339,16 @@ void main() { manager.stopScreenRenderCollector(); // should save data expect(manager.screenRenderForAutoUiTrace.frameData.length, 1); - expect(manager.screenRenderForAutoUiTrace.frozenFramesTotalDuration, buildDuration *1000); // * 1000 to convert from milli to micro + expect( + manager.screenRenderForAutoUiTrace.frozenFramesTotalDuration, + buildDuration * 1000, + ); // * 1000 to convert from milli to micro expect(manager.screenRenderForAutoUiTrace.slowFramesTotalDuration, 0); - }); - test('should detect frozen frame on raster thread when durations are greater than or equal 700 ms', () { + test( + 'should detect frozen frame on raster thread when durations are greater than or equal 700 ms', + () { const rasterBuild = 700; when(mockFrameTiming.buildDuration) .thenReturn(const Duration(milliseconds: rasterBuild)); @@ -342,9 +357,11 @@ void main() { manager.stopScreenRenderCollector(); // should save data expect(manager.screenRenderForAutoUiTrace.frameData.length, 1); - expect(manager.screenRenderForAutoUiTrace.frozenFramesTotalDuration, rasterBuild *1000); // * 1000 to convert from milli to micro + expect( + manager.screenRenderForAutoUiTrace.frozenFramesTotalDuration, + rasterBuild * 1000, + ); // * 1000 to convert from milli to micro expect(manager.screenRenderForAutoUiTrace.slowFramesTotalDuration, 0); - }); test('should detect no slow or frozen frame under thresholds', () { @@ -356,9 +373,11 @@ void main() { .thenReturn(const Duration(milliseconds: 10)); manager.analyzeFrameTiming(mockFrameTiming); expect(manager.screenRenderForAutoUiTrace.frameData.isEmpty, true); - expect(manager.screenRenderForAutoUiTrace.frozenFramesTotalDuration, 0); // * 1000 to convert from milli to micro + expect( + manager.screenRenderForAutoUiTrace.frozenFramesTotalDuration, + 0, + ); // * 1000 to convert from milli to micro expect(manager.screenRenderForAutoUiTrace.slowFramesTotalDuration, 0); - }); }); } diff --git a/test/utils/screen_render/instabug_widget_binding_observer_test.dart b/test/utils/screen_render/instabug_widget_binding_observer_test.dart index 8c5d952c5..58bbe92d8 100644 --- a/test/utils/screen_render/instabug_widget_binding_observer_test.dart +++ b/test/utils/screen_render/instabug_widget_binding_observer_test.dart @@ -48,13 +48,15 @@ void main() { when(mockNameMasker.mask("HomeScreen")).thenReturn("MaskedHome"); when(mockLoadingManager.startUiTrace("MaskedHome", "HomeScreen")) .thenAnswer((_) async => 123); + when(mockRenderManager.screenRenderEnabled).thenReturn(true); InstabugWidgetsBindingObserver.I .didChangeAppLifecycleState(AppLifecycleState.resumed); // wait for async call to complete await untilCalled( - mockRenderManager.startScreenRenderCollectorForTraceId(123)); + mockRenderManager.startScreenRenderCollectorForTraceId(123), + ); verify(mockRenderManager.startScreenRenderCollectorForTraceId(123)) .called(1); @@ -74,17 +76,23 @@ void main() { test('handles AppLifecycleState.inactive with no action', () { // Just ensure it doesn't crash - expect(() { - InstabugWidgetsBindingObserver.I - .didChangeAppLifecycleState(AppLifecycleState.inactive); - }, returnsNormally); + expect( + () { + InstabugWidgetsBindingObserver.I + .didChangeAppLifecycleState(AppLifecycleState.inactive); + }, + returnsNormally, + ); }); test('handles AppLifecycleState.hidden with no action', () { - expect(() { - InstabugWidgetsBindingObserver.I - .didChangeAppLifecycleState(AppLifecycleState.hidden); - }, returnsNormally); + expect( + () { + InstabugWidgetsBindingObserver.I + .didChangeAppLifecycleState(AppLifecycleState.hidden); + }, + returnsNormally, + ); }); test('_handleResumedState does nothing if no currentUiTrace', () { From 35a0c5aabbb187a8224b43e16e216ece08864f95 Mon Sep 17 00:00:00 2001 From: Andrew Amin Date: Sat, 21 Jun 2025 18:42:06 +0300 Subject: [PATCH 05/15] chore: fix ci failed jobs --- example/lib/src/components/animated_box.dart | 2 +- example/lib/src/components/ui_traces_content.dart | 1 - lib/src/models/InstabugFrameData.dart | 2 +- lib/src/models/InstabugScreenRenderData.dart | 2 -- lib/src/modules/apm.dart | 5 +++-- .../instabug_screen_render_manager.dart | 12 ++++++------ .../instabug_widget_binding_observer.dart | 13 +++++++------ .../instabug_screen_render_manager_test.dart | 8 +++----- 8 files changed, 21 insertions(+), 24 deletions(-) diff --git a/example/lib/src/components/animated_box.dart b/example/lib/src/components/animated_box.dart index 4eec36bcd..fc0a8e362 100644 --- a/example/lib/src/components/animated_box.dart +++ b/example/lib/src/components/animated_box.dart @@ -16,7 +16,7 @@ class _AnimatedBoxState extends State void initState() { super.initState(); _controller = AnimationController( - duration: const Duration(minutes: 1 , seconds: 40), + duration: const Duration(minutes: 1, seconds: 40), vsync: this, ); _animation = Tween(begin: 0, end: 100).animate(_controller) diff --git a/example/lib/src/components/ui_traces_content.dart b/example/lib/src/components/ui_traces_content.dart index 19e9ec0dd..b05144408 100644 --- a/example/lib/src/components/ui_traces_content.dart +++ b/example/lib/src/components/ui_traces_content.dart @@ -49,7 +49,6 @@ class _UITracesContentState extends State { ), ], ), - ], ); } diff --git a/lib/src/models/InstabugFrameData.dart b/lib/src/models/InstabugFrameData.dart index d62368c3a..6c9c1ae8a 100644 --- a/lib/src/models/InstabugFrameData.dart +++ b/lib/src/models/InstabugFrameData.dart @@ -8,7 +8,7 @@ class InstabugFrameData { String toString() => "start time: $startTimeTimestamp, duration: $duration"; @override - bool operator == (covariant InstabugFrameData other) { + bool operator ==(covariant InstabugFrameData other) { if (identical(this, other)) return true; return startTimeTimestamp == other.startTimeTimestamp && duration == other.duration; diff --git a/lib/src/models/InstabugScreenRenderData.dart b/lib/src/models/InstabugScreenRenderData.dart index ed5f4a2f3..1e093de98 100644 --- a/lib/src/models/InstabugScreenRenderData.dart +++ b/lib/src/models/InstabugScreenRenderData.dart @@ -39,6 +39,4 @@ class InstabugScreenRenderData { frozenFramesTotalDuration == other.frozenFramesTotalDuration && listEquals(frameData, other.frameData); } - - } diff --git a/lib/src/modules/apm.dart b/lib/src/modules/apm.dart index 43af7b7d7..efd9dc609 100644 --- a/lib/src/modules/apm.dart +++ b/lib/src/modules/apm.dart @@ -195,7 +195,8 @@ class APM { (_) async { // Start screen render collector for custom ui trace if enabled. if (await FlagsConfig.screenRendering.isEnabled()) { - InstabugScreenRenderManager.I.startScreenRenderCollectorForTraceId(0 ,UiTraceType.custom); + InstabugScreenRenderManager.I + .startScreenRenderCollectorForTraceId(0, UiTraceType.custom); } }, ); @@ -377,7 +378,7 @@ class APM { /// Returns: /// A Future that represent the refresh rate. @internal - static Future getDeviceRefreshRate(){ + static Future getDeviceRefreshRate() { return _host.deviceRefreshRate(); } } diff --git a/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart b/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart index bc5c7fc71..34f17f60c 100644 --- a/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart +++ b/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart @@ -55,11 +55,11 @@ class InstabugScreenRenderManager { /// setup function for [InstabugScreenRenderManager] @internal - void init(WidgetsBinding widgetBinding, [double? refreshRate]) { + Future init(WidgetsBinding widgetBinding) async { if (!_isTimingsListenerAttached) { _widgetsBinding = widgetBinding; _addWidgetBindingObserver(); - _initStaticValues(refreshRate); + await _initStaticValues(); _initFrameTimings(); screenRenderEnabled = true; } @@ -145,8 +145,8 @@ class InstabugScreenRenderManager { /// On iOS, it will only contains the main display on the phone or tablet. /// On Desktop, it will contain only a main display with a valid refresh rate but invalid size and device pixel ratio values. //todo: will be compared with value from native side after it's implemented. - double get _getDeviceRefreshRate => - _widgetsBinding.platformDispatcher.displays.first.refreshRate; + // double get _getDeviceRefreshRate => + // _widgetsBinding.platformDispatcher.displays.first.refreshRate; /// Get device refresh rate from native side. //todo: will be compared with value from native side after it's implemented. @@ -155,13 +155,13 @@ class InstabugScreenRenderManager { APM.getDeviceRefreshRate(); /// Initialize the static variables - void _initStaticValues(double? refreshRate) { + Future _initStaticValues() async { _timingsCallback = (timings) { for (final frameTiming in timings) { analyzeFrameTiming(frameTiming); } }; - _deviceRefreshRate = refreshRate ?? _getDeviceRefreshRate; + _deviceRefreshRate = await _getDeviceRefreshRateFromNative; _slowFrameThresholdMs = _targetMsPerFrame(_deviceRefreshRate); _screenRenderForAutoUiTrace = InstabugScreenRenderData(frameData: []); _screenRenderForCustomUiTrace = InstabugScreenRenderData(frameData: []); diff --git a/lib/src/utils/screen_rendering/instabug_widget_binding_observer.dart b/lib/src/utils/screen_rendering/instabug_widget_binding_observer.dart index caf768be3..89ba6886a 100644 --- a/lib/src/utils/screen_rendering/instabug_widget_binding_observer.dart +++ b/lib/src/utils/screen_rendering/instabug_widget_binding_observer.dart @@ -60,14 +60,15 @@ class InstabugWidgetsBindingObserver extends WidgetsBindingObserver { case AppLifecycleState.detached: _handleDetachedState(); break; - case AppLifecycleState.inactive: - // TODO: Handle this case. - break; - case AppLifecycleState.hidden: - // TODO: Handle this case. - break; + default: + _handleDefaultState(); } } + + void _handleDefaultState() { + //todo: will be removed + debugPrint("default"); + } } @internal diff --git a/test/utils/screen_render/instabug_screen_render_manager_test.dart b/test/utils/screen_render/instabug_screen_render_manager_test.dart index 37879753a..563703018 100644 --- a/test/utils/screen_render/instabug_screen_render_manager_test.dart +++ b/test/utils/screen_render/instabug_screen_render_manager_test.dart @@ -19,15 +19,14 @@ void main() { late InstabugScreenRenderManager manager; late MockApmHostApi mApmHost; late MockWidgetsBinding mWidgetBinding; - const mRefreshRate = 60.0; setUp(() async { mApmHost = MockApmHostApi(); mWidgetBinding = MockWidgetsBinding(); manager = InstabugScreenRenderManager.init(); // test-only constructor APM.$setHostApi(mApmHost); - - manager.init(mWidgetBinding, mRefreshRate); + when(mApmHost.deviceRefreshRate()).thenAnswer((_) async => 60); + manager.init(mWidgetBinding); }); tearDown(() { @@ -44,10 +43,9 @@ void main() { }); test('calling init more that one time should do nothing', () async { - manager.init(mWidgetBinding, mRefreshRate); + manager.init(mWidgetBinding); manager.init( mWidgetBinding, - mRefreshRate, ); // second call should be ignored verify(mWidgetBinding.addObserver(any)).called(1); From 953cb536e727a0f468dd348a1387c50e01101e8a Mon Sep 17 00:00:00 2001 From: Andrew Amin Date: Sun, 22 Jun 2025 11:18:21 +0300 Subject: [PATCH 06/15] chore: fix ci failed jobs --- lib/instabug_flutter.dart | 3 +-- ...rameData.dart => instabug_frame_data.dart} | 1 + ....dart => instabug_screen_render_data.dart} | 3 ++- lib/src/modules/instabug.dart | 1 + .../screen_loading_manager.dart | 2 +- .../instabug_screen_render_manager.dart | 22 ++++++------------- .../instabug_widget_binding_observer.dart | 2 +- test/instabug_test.dart | 1 + .../screen_loading_manager_test.dart | 2 +- .../instabug_screen_render_manager_test.dart | 5 +++-- ...instabug_widget_binding_observer_test.dart | 10 --------- 11 files changed, 19 insertions(+), 33 deletions(-) rename lib/src/models/{InstabugFrameData.dart => instabug_frame_data.dart} (93%) rename lib/src/models/{InstabugScreenRenderData.dart => instabug_screen_render_data.dart} (92%) diff --git a/lib/instabug_flutter.dart b/lib/instabug_flutter.dart index edf703ba3..d2df80429 100644 --- a/lib/instabug_flutter.dart +++ b/lib/instabug_flutter.dart @@ -5,7 +5,6 @@ export 'src/models/feature_flag.dart'; export 'src/models/network_data.dart'; export 'src/models/trace.dart'; export 'src/models/w3c_header.dart'; - // Modules export 'src/modules/apm.dart'; export 'src/modules/bug_reporting.dart'; @@ -20,5 +19,5 @@ export 'src/modules/surveys.dart'; // Utils export 'src/utils/instabug_navigator_observer.dart'; export 'src/utils/screen_loading/instabug_capture_screen_loading.dart'; -export 'src/utils/ui_trace/route_matcher.dart'; export 'src/utils/screen_name_masker.dart' show ScreenNameMaskingCallback; +export 'src/utils/ui_trace/route_matcher.dart'; diff --git a/lib/src/models/InstabugFrameData.dart b/lib/src/models/instabug_frame_data.dart similarity index 93% rename from lib/src/models/InstabugFrameData.dart rename to lib/src/models/instabug_frame_data.dart index 6c9c1ae8a..60bda2550 100644 --- a/lib/src/models/InstabugFrameData.dart +++ b/lib/src/models/instabug_frame_data.dart @@ -8,6 +8,7 @@ class InstabugFrameData { String toString() => "start time: $startTimeTimestamp, duration: $duration"; @override + // ignore: hash_and_equals bool operator ==(covariant InstabugFrameData other) { if (identical(this, other)) return true; return startTimeTimestamp == other.startTimeTimestamp && diff --git a/lib/src/models/InstabugScreenRenderData.dart b/lib/src/models/instabug_screen_render_data.dart similarity index 92% rename from lib/src/models/InstabugScreenRenderData.dart rename to lib/src/models/instabug_screen_render_data.dart index 1e093de98..11a002345 100644 --- a/lib/src/models/InstabugScreenRenderData.dart +++ b/lib/src/models/instabug_screen_render_data.dart @@ -1,5 +1,5 @@ import 'package:flutter/foundation.dart'; -import 'package:instabug_flutter/src/models/InstabugFrameData.dart'; +import 'package:instabug_flutter/src/models/instabug_frame_data.dart'; class InstabugScreenRenderData { int traceId; @@ -32,6 +32,7 @@ class InstabugScreenRenderData { 'Frame Data[\n${frameData.map((element) => '\t\n$element')}\n]'; @override + // ignore: hash_and_equals bool operator ==(covariant InstabugScreenRenderData other) { if (identical(this, other)) return true; return traceId == other.traceId && diff --git a/lib/src/modules/instabug.dart b/lib/src/modules/instabug.dart index 4b079ab99..9ef4930b0 100644 --- a/lib/src/modules/instabug.dart +++ b/lib/src/modules/instabug.dart @@ -1,4 +1,5 @@ // ignore_for_file: avoid_classes_with_only_static_members +// ignore_for_file: deprecated_member_use import 'dart:async'; diff --git a/lib/src/utils/screen_loading/screen_loading_manager.dart b/lib/src/utils/screen_loading/screen_loading_manager.dart index ce73a3e30..9b48d6441 100644 --- a/lib/src/utils/screen_loading/screen_loading_manager.dart +++ b/lib/src/utils/screen_loading/screen_loading_manager.dart @@ -4,8 +4,8 @@ import 'package:instabug_flutter/src/utils/ibg_build_info.dart'; import 'package:instabug_flutter/src/utils/ibg_date_time.dart'; import 'package:instabug_flutter/src/utils/instabug_logger.dart'; import 'package:instabug_flutter/src/utils/instabug_montonic_clock.dart'; -import 'package:instabug_flutter/src/utils/ui_trace/flags_config.dart'; import 'package:instabug_flutter/src/utils/screen_loading/screen_loading_trace.dart'; +import 'package:instabug_flutter/src/utils/ui_trace/flags_config.dart'; import 'package:instabug_flutter/src/utils/ui_trace/ui_trace.dart'; import 'package:meta/meta.dart'; diff --git a/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart b/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart index 34f17f60c..143032215 100644 --- a/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart +++ b/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart @@ -2,8 +2,8 @@ import 'dart:developer'; import 'dart:ui'; import 'package:flutter/widgets.dart'; -import 'package:instabug_flutter/src/models/InstabugFrameData.dart'; -import 'package:instabug_flutter/src/models/InstabugScreenRenderData.dart'; +import 'package:instabug_flutter/src/models/instabug_frame_data.dart'; +import 'package:instabug_flutter/src/models/instabug_screen_render_data.dart'; import 'package:instabug_flutter/src/modules/apm.dart'; import 'package:instabug_flutter/src/utils/screen_rendering/instabug_widget_binding_observer.dart'; import 'package:meta/meta.dart'; @@ -39,6 +39,7 @@ class InstabugScreenRenderManager { bool _isTimingsListenerAttached = false; bool screenRenderEnabled = false; + InstabugScreenRenderManager._(); static InstabugScreenRenderManager _instance = @@ -55,8 +56,9 @@ class InstabugScreenRenderManager { /// setup function for [InstabugScreenRenderManager] @internal - Future init(WidgetsBinding widgetBinding) async { - if (!_isTimingsListenerAttached) { + Future init(WidgetsBinding? widgetBinding) async { + // passing WidgetsBinding? (nullable) for flutter versions prior than 3.x + if (!_isTimingsListenerAttached && widgetBinding != null) { _widgetsBinding = widgetBinding; _addWidgetBindingObserver(); await _initStaticValues(); @@ -139,18 +141,8 @@ class InstabugScreenRenderManager { double _targetMsPerFrame(double displayRefreshRate) => 1 / displayRefreshRate * 1000; - /// Check if getting from native would return different value. - /// Platforms may limit what information is available to the application with regard to secondary displays and/or displays that do not have an active application window. - /// Presently, on Android and Web this collection will only contain the display that the current window is on. - /// On iOS, it will only contains the main display on the phone or tablet. - /// On Desktop, it will contain only a main display with a valid refresh rate but invalid size and device pixel ratio values. - //todo: will be compared with value from native side after it's implemented. - // double get _getDeviceRefreshRate => - // _widgetsBinding.platformDispatcher.displays.first.refreshRate; - /// Get device refresh rate from native side. //todo: will be compared with value from native side after it's implemented. - // ignore: unused_element Future get _getDeviceRefreshRateFromNative => APM.getDeviceRefreshRate(); @@ -263,7 +255,7 @@ class InstabugScreenRenderManager { _delayedFrames.add(InstabugFrameData(startTime, duration)); } - //todo: will be removed + //todo: will be removed (is used for debugging) void _displayFrameTimingDetails(FrameTiming frameTiming) { if (_isSlow) { debugPrint( diff --git a/lib/src/utils/screen_rendering/instabug_widget_binding_observer.dart b/lib/src/utils/screen_rendering/instabug_widget_binding_observer.dart index 89ba6886a..6a92b51ce 100644 --- a/lib/src/utils/screen_rendering/instabug_widget_binding_observer.dart +++ b/lib/src/utils/screen_rendering/instabug_widget_binding_observer.dart @@ -66,7 +66,7 @@ class InstabugWidgetsBindingObserver extends WidgetsBindingObserver { } void _handleDefaultState() { - //todo: will be removed + //todo: will be implemented in next story debugPrint("default"); } } diff --git a/test/instabug_test.dart b/test/instabug_test.dart index 3afb6648c..06f3a3ef2 100644 --- a/test/instabug_test.dart +++ b/test/instabug_test.dart @@ -1,3 +1,4 @@ +// ignore_for_file: deprecated_member_use import 'dart:typed_data'; import 'package:flutter/widgets.dart'; diff --git a/test/utils/screen_loading/screen_loading_manager_test.dart b/test/utils/screen_loading/screen_loading_manager_test.dart index f452c4cda..341bc7368 100644 --- a/test/utils/screen_loading/screen_loading_manager_test.dart +++ b/test/utils/screen_loading/screen_loading_manager_test.dart @@ -9,8 +9,8 @@ import 'package:instabug_flutter/src/utils/instabug_logger.dart'; import 'package:instabug_flutter/src/utils/instabug_montonic_clock.dart'; import 'package:instabug_flutter/src/utils/screen_loading/screen_loading_manager.dart'; import 'package:instabug_flutter/src/utils/screen_loading/screen_loading_trace.dart'; -import 'package:instabug_flutter/src/utils/ui_trace/ui_trace.dart'; import 'package:instabug_flutter/src/utils/ui_trace/flags_config.dart'; +import 'package:instabug_flutter/src/utils/ui_trace/ui_trace.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; diff --git a/test/utils/screen_render/instabug_screen_render_manager_test.dart b/test/utils/screen_render/instabug_screen_render_manager_test.dart index 563703018..f84a9fad4 100644 --- a/test/utils/screen_render/instabug_screen_render_manager_test.dart +++ b/test/utils/screen_render/instabug_screen_render_manager_test.dart @@ -4,8 +4,9 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:instabug_flutter/instabug_flutter.dart'; import 'package:instabug_flutter/src/generated/apm.api.g.dart'; -import 'package:instabug_flutter/src/models/InstabugFrameData.dart'; -import 'package:instabug_flutter/src/models/InstabugScreenRenderData.dart'; +import 'package:instabug_flutter/src/models/instabug_frame_data.dart'; +import 'package:instabug_flutter/src/models/instabug_screen_render_data.dart'; + import 'package:instabug_flutter/src/utils/screen_rendering/instabug_screen_render_manager.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; diff --git a/test/utils/screen_render/instabug_widget_binding_observer_test.dart b/test/utils/screen_render/instabug_widget_binding_observer_test.dart index 58bbe92d8..54415fdb7 100644 --- a/test/utils/screen_render/instabug_widget_binding_observer_test.dart +++ b/test/utils/screen_render/instabug_widget_binding_observer_test.dart @@ -85,16 +85,6 @@ void main() { ); }); - test('handles AppLifecycleState.hidden with no action', () { - expect( - () { - InstabugWidgetsBindingObserver.I - .didChangeAppLifecycleState(AppLifecycleState.hidden); - }, - returnsNormally, - ); - }); - test('_handleResumedState does nothing if no currentUiTrace', () { when(mockLoadingManager.currentUiTrace).thenReturn(null); From e576a89d3283aa78351f46644d4cb0d1781b0a3a Mon Sep 17 00:00:00 2001 From: Andrew Amin Date: Sun, 22 Jun 2025 15:36:08 +0300 Subject: [PATCH 07/15] chore: add unit test cases for instabug_navigator_observer --- .../utils/instabug_navigator_observer.dart | 11 +-- .../instabug_screen_render_manager.dart | 38 +++++----- .../instabug_navigator_observer_test.dart | 75 ++++++++++++++++++- 3 files changed, 95 insertions(+), 29 deletions(-) diff --git a/lib/src/utils/instabug_navigator_observer.dart b/lib/src/utils/instabug_navigator_observer.dart index 775236f2b..4f3e814ff 100644 --- a/lib/src/utils/instabug_navigator_observer.dart +++ b/lib/src/utils/instabug_navigator_observer.dart @@ -6,7 +6,6 @@ import 'package:instabug_flutter/src/utils/instabug_logger.dart'; import 'package:instabug_flutter/src/utils/repro_steps_constants.dart'; import 'package:instabug_flutter/src/utils/screen_loading/screen_loading_manager.dart'; import 'package:instabug_flutter/src/utils/screen_name_masker.dart'; -import 'package:instabug_flutter/src/utils/screen_rendering/instabug_screen_render_manager.dart'; class InstabugNavigatorObserver extends NavigatorObserver { final List _steps = []; @@ -25,15 +24,7 @@ class InstabugNavigatorObserver extends NavigatorObserver { ); // Starts a the new UI trace which is exclusive to screen loading - ScreenLoadingManager.I - .startUiTrace(maskedScreenName, screenName) - .then((uiTraceId) { - if (uiTraceId != null && - InstabugScreenRenderManager.I.screenRenderEnabled) { - InstabugScreenRenderManager.I - .startScreenRenderCollectorForTraceId(uiTraceId); - } - }); + ScreenLoadingManager.I.startUiTrace(maskedScreenName, screenName); // If there is a step that hasn't been pushed yet if (_steps.isNotEmpty) { diff --git a/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart b/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart index 143032215..bde2008c3 100644 --- a/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart +++ b/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart @@ -269,24 +269,28 @@ class InstabugScreenRenderManager { } if (_isFrozen || _isSlow) { - debugPrint("{\n\t$frameTiming\n\t" - "Timestamps(${frameTiming.timestampInMicroseconds( - FramePhase.buildStart, - )}, ${frameTiming.timestampInMicroseconds( - FramePhase.buildFinish, - )}, ${frameTiming.timestampInMicroseconds( - FramePhase.rasterStart, - )}, ${frameTiming.timestampInMicroseconds( - FramePhase.rasterFinish, - )}, ${frameTiming.timestampInMicroseconds( - FramePhase.vsyncStart, - )}, ${frameTiming.timestampInMicroseconds( - FramePhase.rasterFinishWallTime, - )}" - ")\n}\n"); + debugPrint( + "{\n\t$frameTiming\n\t" + "Timestamps(${frameTiming.timestampInMicroseconds( + FramePhase.buildStart, + )}, ${frameTiming.timestampInMicroseconds( + FramePhase.buildFinish, + )}, ${frameTiming.timestampInMicroseconds( + FramePhase.rasterStart, + )}, ${frameTiming.timestampInMicroseconds( + FramePhase.rasterFinish, + )}, ${frameTiming.timestampInMicroseconds( + FramePhase.vsyncStart, + )}, ${frameTiming.timestampInMicroseconds( + FramePhase.rasterFinishWallTime, + )}" + ")\n}\n", + ); debugPrint("Device refresh rate: $_deviceRefreshRate FPS"); - debugPrint("Threshold: $_slowFrameThresholdMs ms\n" - "==============================================================================="); + debugPrint( + "Threshold: $_slowFrameThresholdMs ms\n" + "===============================================================================", + ); } } diff --git a/test/utils/instabug_navigator_observer_test.dart b/test/utils/instabug_navigator_observer_test.dart index 81a9f174e..76ae1840e 100644 --- a/test/utils/instabug_navigator_observer_test.dart +++ b/test/utils/instabug_navigator_observer_test.dart @@ -5,18 +5,23 @@ import 'package:instabug_flutter/instabug_flutter.dart'; import 'package:instabug_flutter/src/generated/instabug.api.g.dart'; import 'package:instabug_flutter/src/utils/screen_loading/screen_loading_manager.dart'; import 'package:instabug_flutter/src/utils/screen_name_masker.dart'; +import 'package:instabug_flutter/src/utils/screen_rendering/instabug_screen_render_manager.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; import 'instabug_navigator_observer_test.mocks.dart'; -@GenerateMocks([InstabugHostApi]) -@GenerateNiceMocks([MockSpec()]) +@GenerateMocks([ + InstabugHostApi, + ScreenLoadingManager, + InstabugScreenRenderManager, +]) void main() { TestWidgetsFlutterBinding.ensureInitialized(); final mHost = MockInstabugHostApi(); final mScreenLoadingManager = MockScreenLoadingManager(); + final mScreenRenderManager = MockInstabugScreenRenderManager(); late InstabugNavigatorObserver observer; const screen = '/screen'; @@ -35,6 +40,7 @@ void main() { previousRoute = createRoute(previousScreen); ScreenNameMasker.I.setMaskingCallback(null); + when(mScreenRenderManager.screenRenderEnabled).thenReturn(false); }); test('should report screen change when a route is pushed', () { @@ -57,6 +63,9 @@ void main() { 'should report screen change when a route is popped and previous is known', () { fakeAsync((async) { + when(mScreenLoadingManager.startUiTrace(previousScreen, previousScreen)) + .thenAnswer((realInvocation) async => null); + observer.didPop(route, previousRoute); async.elapse(const Duration(milliseconds: 1000)); @@ -94,6 +103,9 @@ void main() { final route = createRoute(''); const fallback = 'N/A'; + when(mScreenLoadingManager.startUiTrace(fallback, fallback)) + .thenAnswer((realInvocation) async => null); + observer.didPush(route, previousRoute); async.elapse(const Duration(milliseconds: 1000)); @@ -111,6 +123,9 @@ void main() { test('should mask screen name when masking callback is set', () { const maskedScreen = 'maskedScreen'; + when(mScreenLoadingManager.startUiTrace(maskedScreen, screen)) + .thenAnswer((realInvocation) async => null); + ScreenNameMasker.I.setMaskingCallback((_) => maskedScreen); fakeAsync((async) { @@ -127,6 +142,62 @@ void main() { ).called(1); }); }); + + test('should start new screen render collector when a route is pushed', () { + fakeAsync((async) async { + const traceID = 123; + + when(mScreenLoadingManager.startUiTrace(screen, screen)) + .thenAnswer((_) async => traceID); + when(mScreenRenderManager.screenRenderEnabled).thenReturn(true); + + observer.didPush(route, previousRoute); + + async.elapse(const Duration(milliseconds: 1000)); + + verify( + mScreenRenderManager.startScreenRenderCollectorForTraceId(traceID), + ).called(1); + }); + }); + + test( + 'should not start new screen render collector when a route is pushed and [traceID] is null', + () { + fakeAsync((async) async { + when(mScreenLoadingManager.startUiTrace(screen, screen)) + .thenAnswer((_) async => null); + + when(mScreenRenderManager.screenRenderEnabled).thenReturn(true); + + observer.didPush(route, previousRoute); + + async.elapse(const Duration(milliseconds: 1000)); + + verifyNever( + mScreenRenderManager.startScreenRenderCollectorForTraceId(any), + ); + }); + }); + + test( + 'should not start new screen render collector when a route is pushed and [mScreenRenderManager.screenRenderEnabled] is false', + () { + fakeAsync((async) async { + when(mScreenLoadingManager.startUiTrace(screen, screen)) + .thenAnswer((_) async => 123); + + when(mScreenRenderManager.screenRenderEnabled).thenReturn(false); + + observer.didPush(route, previousRoute); + + async.elapse(const Duration(milliseconds: 1000)); + + verifyNever( + mScreenRenderManager.startScreenRenderCollectorForTraceId(any), + ); + }); + }); } Route createRoute(String? name) { From ec2b04bb913d5b8d9fbcb5e5b4831e88d198d11a Mon Sep 17 00:00:00 2001 From: Andrew Amin Date: Sun, 22 Jun 2025 17:18:03 +0300 Subject: [PATCH 08/15] chore: add instabug_screen_render_manager_test_manual_mocks.dart --- .../instabug_screen_render_manager_test.dart | 7 +- ...reen_render_manager_test_manual_mocks.dart | 879 ++++++++++++++++++ 2 files changed, 880 insertions(+), 6 deletions(-) create mode 100644 test/utils/screen_render/instabug_screen_render_manager_test_manual_mocks.dart diff --git a/test/utils/screen_render/instabug_screen_render_manager_test.dart b/test/utils/screen_render/instabug_screen_render_manager_test.dart index f84a9fad4..54b16301d 100644 --- a/test/utils/screen_render/instabug_screen_render_manager_test.dart +++ b/test/utils/screen_render/instabug_screen_render_manager_test.dart @@ -1,19 +1,14 @@ -import 'dart:ui'; -import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:instabug_flutter/instabug_flutter.dart'; -import 'package:instabug_flutter/src/generated/apm.api.g.dart'; import 'package:instabug_flutter/src/models/instabug_frame_data.dart'; import 'package:instabug_flutter/src/models/instabug_screen_render_data.dart'; import 'package:instabug_flutter/src/utils/screen_rendering/instabug_screen_render_manager.dart'; -import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; -import 'instabug_screen_render_manager_test.mocks.dart'; +import 'instabug_screen_render_manager_test_manual_mocks.dart'; -@GenerateMocks([FrameTiming, ApmHostApi, WidgetsBinding]) void main() { TestWidgetsFlutterBinding.ensureInitialized(); diff --git a/test/utils/screen_render/instabug_screen_render_manager_test_manual_mocks.dart b/test/utils/screen_render/instabug_screen_render_manager_test_manual_mocks.dart new file mode 100644 index 000000000..0560e4bcc --- /dev/null +++ b/test/utils/screen_render/instabug_screen_render_manager_test_manual_mocks.dart @@ -0,0 +1,879 @@ +// Mocks generated by Mockito 5.2.0 from annotations +// in instabug_flutter/example/ios/.symlinks/plugins/instabug_flutter/test/utils/screen_render/instabug_screen_render_manager_test.dart. +// Do not manually edit this file. + +import 'dart:async' as _i9; +import 'dart:developer' as _i13; +import 'dart:ui' as _i4; + +import 'package:flutter/foundation.dart' as _i3; +import 'package:flutter/gestures.dart' as _i6; +import 'package:flutter/rendering.dart' as _i7; +import 'package:flutter/scheduler.dart' as _i11; +import 'package:flutter/services.dart' as _i5; +import 'package:flutter/src/widgets/binding.dart' as _i10; +import 'package:flutter/src/widgets/focus_manager.dart' as _i2; +import 'package:flutter/src/widgets/framework.dart' as _i12; +import 'package:instabug_flutter/src/generated/apm.api.g.dart' as _i8; +import 'package:mockito/mockito.dart' as _i1; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types + +// This file has been manually changed due to a mockito inconsistency with flutter v 2.10.5 + +class _FakeDuration_0 extends _i1.Fake implements Duration {} + +class _FakeFocusManager_1 extends _i1.Fake implements _i2.FocusManager { + @override + String toString({_i3.DiagnosticLevel? minLevel = _i3.DiagnosticLevel.info}) => + super.toString(); +} + +class _FakeSingletonFlutterWindow_2 extends _i1.Fake + implements _i4.SingletonFlutterWindow {} + +class _FakePlatformDispatcher_3 extends _i1.Fake + implements _i4.PlatformDispatcher {} + +class _FakeHardwareKeyboard_4 extends _i1.Fake implements _i5.HardwareKeyboard { +} + +class _FakeKeyEventManager_5 extends _i1.Fake implements _i5.KeyEventManager {} + +class _FakeBinaryMessenger_6 extends _i1.Fake implements _i5.BinaryMessenger {} + +class _FakeChannelBuffers_7 extends _i1.Fake implements _i4.ChannelBuffers {} + +class _FakeRestorationManager_8 extends _i1.Fake + implements _i5.RestorationManager {} + +class _FakePointerRouter_9 extends _i1.Fake implements _i6.PointerRouter {} + +class _FakeGestureArenaManager_10 extends _i1.Fake + implements _i6.GestureArenaManager {} + +class _FakePointerSignalResolver_11 extends _i1.Fake + implements _i6.PointerSignalResolver {} + +class _FakeMouseTracker_12 extends _i1.Fake implements _i7.MouseTracker {} + +class _FakePipelineOwner_13 extends _i1.Fake implements _i7.PipelineOwner {} + +class _FakeRenderView_14 extends _i1.Fake implements _i7.RenderView { + @override + String toString({_i3.DiagnosticLevel? minLevel = _i3.DiagnosticLevel.info}) => + super.toString(); +} + +class _FakeAccessibilityFeatures_15 extends _i1.Fake + implements _i4.AccessibilityFeatures {} + +class _FakeViewConfiguration_16 extends _i1.Fake + implements _i7.ViewConfiguration {} + +class _FakeSemanticsUpdateBuilder_17 extends _i1.Fake + implements _i4.SemanticsUpdateBuilder {} + +/// A class which mocks [FrameTiming]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockFrameTiming extends _i1.Mock implements _i4.FrameTiming { + MockFrameTiming() { + _i1.throwOnMissingStub(this); + } + + @override + Duration get buildDuration => + (super.noSuchMethod(Invocation.getter(#buildDuration), + returnValue: _FakeDuration_0()) as Duration); + + @override + Duration get rasterDuration => + (super.noSuchMethod(Invocation.getter(#rasterDuration), + returnValue: _FakeDuration_0()) as Duration); + + @override + Duration get vsyncOverhead => + (super.noSuchMethod(Invocation.getter(#vsyncOverhead), + returnValue: _FakeDuration_0()) as Duration); + + @override + Duration get totalSpan => (super.noSuchMethod(Invocation.getter(#totalSpan), + returnValue: _FakeDuration_0()) as Duration); + + @override + int get layerCacheCount => + (super.noSuchMethod(Invocation.getter(#layerCacheCount), returnValue: 0) + as int); + + @override + int get layerCacheBytes => + (super.noSuchMethod(Invocation.getter(#layerCacheBytes), returnValue: 0) + as int); + + @override + double get layerCacheMegabytes => + (super.noSuchMethod(Invocation.getter(#layerCacheMegabytes), + returnValue: 0.0) as double); + + @override + int get pictureCacheCount => + (super.noSuchMethod(Invocation.getter(#pictureCacheCount), returnValue: 0) + as int); + + @override + int get pictureCacheBytes => + (super.noSuchMethod(Invocation.getter(#pictureCacheBytes), returnValue: 0) + as int); + + @override + double get pictureCacheMegabytes => + (super.noSuchMethod(Invocation.getter(#pictureCacheMegabytes), + returnValue: 0.0) as double); + + @override + int get frameNumber => + (super.noSuchMethod(Invocation.getter(#frameNumber), returnValue: 0) + as int); + + @override + int timestampInMicroseconds(_i4.FramePhase? phase) => + (super.noSuchMethod(Invocation.method(#timestampInMicroseconds, [phase]), + returnValue: 0) as int); +} + +/// A class which mocks [ApmHostApi]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockApmHostApi extends _i1.Mock implements _i8.ApmHostApi { + MockApmHostApi() { + _i1.throwOnMissingStub(this); + } + + @override + _i9.Future setEnabled(bool? arg_isEnabled) => + (super.noSuchMethod(Invocation.method(#setEnabled, [arg_isEnabled]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); + + @override + _i9.Future isEnabled() => + (super.noSuchMethod(Invocation.method(#isEnabled, []), + returnValue: Future.value(false)) as _i9.Future); + + @override + _i9.Future setScreenLoadingEnabled(bool? arg_isEnabled) => + (super.noSuchMethod( + Invocation.method(#setScreenLoadingEnabled, [arg_isEnabled]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); + + @override + _i9.Future isScreenLoadingEnabled() => + (super.noSuchMethod(Invocation.method(#isScreenLoadingEnabled, []), + returnValue: Future.value(false)) as _i9.Future); + + @override + _i9.Future setColdAppLaunchEnabled(bool? arg_isEnabled) => + (super.noSuchMethod( + Invocation.method(#setColdAppLaunchEnabled, [arg_isEnabled]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); + + @override + _i9.Future setAutoUITraceEnabled(bool? arg_isEnabled) => (super + .noSuchMethod(Invocation.method(#setAutoUITraceEnabled, [arg_isEnabled]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); + + @override + _i9.Future startExecutionTrace(String? arg_id, String? arg_name) => + (super.noSuchMethod( + Invocation.method(#startExecutionTrace, [arg_id, arg_name]), + returnValue: Future.value()) as _i9.Future); + + @override + _i9.Future startFlow(String? arg_name) => + (super.noSuchMethod(Invocation.method(#startFlow, [arg_name]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); + + @override + _i9.Future setFlowAttribute( + String? arg_name, String? arg_key, String? arg_value) => + (super.noSuchMethod( + Invocation.method(#setFlowAttribute, [arg_name, arg_key, arg_value]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); + + @override + _i9.Future endFlow(String? arg_name) => + (super.noSuchMethod(Invocation.method(#endFlow, [arg_name]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); + + @override + _i9.Future setExecutionTraceAttribute( + String? arg_id, String? arg_key, String? arg_value) => + (super.noSuchMethod( + Invocation.method( + #setExecutionTraceAttribute, [arg_id, arg_key, arg_value]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); + + @override + _i9.Future endExecutionTrace(String? arg_id) => + (super.noSuchMethod(Invocation.method(#endExecutionTrace, [arg_id]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); + + @override + _i9.Future startUITrace(String? arg_name) => + (super.noSuchMethod(Invocation.method(#startUITrace, [arg_name]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); + + @override + _i9.Future endUITrace() => + (super.noSuchMethod(Invocation.method(#endUITrace, []), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); + + @override + _i9.Future endAppLaunch() => + (super.noSuchMethod(Invocation.method(#endAppLaunch, []), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); + + @override + _i9.Future networkLogAndroid(Map? arg_data) => + (super.noSuchMethod(Invocation.method(#networkLogAndroid, [arg_data]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); + + @override + _i9.Future startCpUiTrace( + String? arg_screenName, int? arg_microTimeStamp, int? arg_traceId) => + (super.noSuchMethod( + Invocation.method(#startCpUiTrace, + [arg_screenName, arg_microTimeStamp, arg_traceId]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); + + @override + _i9.Future reportScreenLoadingCP(int? arg_startTimeStampMicro, + int? arg_durationMicro, int? arg_uiTraceId) => + (super.noSuchMethod( + Invocation.method(#reportScreenLoadingCP, + [arg_startTimeStampMicro, arg_durationMicro, arg_uiTraceId]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); + + @override + _i9.Future endScreenLoadingCP( + int? arg_timeStampMicro, int? arg_uiTraceId) => + (super.noSuchMethod( + Invocation.method( + #endScreenLoadingCP, [arg_timeStampMicro, arg_uiTraceId]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); + + @override + _i9.Future isEndScreenLoadingEnabled() => + (super.noSuchMethod(Invocation.method(#isEndScreenLoadingEnabled, []), + returnValue: Future.value(false)) as _i9.Future); + + @override + _i9.Future isScreenRenderEnabled() => + (super.noSuchMethod(Invocation.method(#isScreenRenderEnabled, []), + returnValue: Future.value(false)) as _i9.Future); + + @override + _i9.Future deviceRefreshRate() => + (super.noSuchMethod(Invocation.method(#deviceRefreshRate, []), + returnValue: Future.value(0.0)) as _i9.Future); +} + +/// A class which mocks [WidgetsBinding]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockWidgetsBinding extends _i1.Mock implements _i10.WidgetsBinding { + MockWidgetsBinding() { + _i1.throwOnMissingStub(this); + } + + @override + bool get debugBuildingDirtyElements => + (super.noSuchMethod(Invocation.getter(#debugBuildingDirtyElements), + returnValue: false) as bool); + + @override + set debugBuildingDirtyElements(bool? _debugBuildingDirtyElements) => + super.noSuchMethod( + Invocation.setter( + #debugBuildingDirtyElements, _debugBuildingDirtyElements), + returnValueForMissingStub: null); + + @override + _i2.FocusManager get focusManager => + (super.noSuchMethod(Invocation.getter(#focusManager), + returnValue: _FakeFocusManager_1()) as _i2.FocusManager); + + @override + bool get firstFrameRasterized => + (super.noSuchMethod(Invocation.getter(#firstFrameRasterized), + returnValue: false) as bool); + + @override + _i9.Future get waitUntilFirstFrameRasterized => + (super.noSuchMethod(Invocation.getter(#waitUntilFirstFrameRasterized), + returnValue: Future.value()) as _i9.Future); + + @override + bool get debugDidSendFirstFrameEvent => + (super.noSuchMethod(Invocation.getter(#debugDidSendFirstFrameEvent), + returnValue: false) as bool); + + @override + bool get framesEnabled => + (super.noSuchMethod(Invocation.getter(#framesEnabled), returnValue: false) + as bool); + + @override + bool get isRootWidgetAttached => + (super.noSuchMethod(Invocation.getter(#isRootWidgetAttached), + returnValue: false) as bool); + + @override + _i4.SingletonFlutterWindow get window => + (super.noSuchMethod(Invocation.getter(#window), + returnValue: _FakeSingletonFlutterWindow_2()) + as _i4.SingletonFlutterWindow); + + @override + _i4.PlatformDispatcher get platformDispatcher => + (super.noSuchMethod(Invocation.getter(#platformDispatcher), + returnValue: _FakePlatformDispatcher_3()) as _i4.PlatformDispatcher); + + @override + bool get locked => + (super.noSuchMethod(Invocation.getter(#locked), returnValue: false) + as bool); + + @override + _i5.HardwareKeyboard get keyboard => + (super.noSuchMethod(Invocation.getter(#keyboard), + returnValue: _FakeHardwareKeyboard_4()) as _i5.HardwareKeyboard); + + @override + _i5.KeyEventManager get keyEventManager => + (super.noSuchMethod(Invocation.getter(#keyEventManager), + returnValue: _FakeKeyEventManager_5()) as _i5.KeyEventManager); + + @override + _i5.BinaryMessenger get defaultBinaryMessenger => + (super.noSuchMethod(Invocation.getter(#defaultBinaryMessenger), + returnValue: _FakeBinaryMessenger_6()) as _i5.BinaryMessenger); + + @override + _i4.ChannelBuffers get channelBuffers => + (super.noSuchMethod(Invocation.getter(#channelBuffers), + returnValue: _FakeChannelBuffers_7()) as _i4.ChannelBuffers); + + @override + _i5.RestorationManager get restorationManager => + (super.noSuchMethod(Invocation.getter(#restorationManager), + returnValue: _FakeRestorationManager_8()) as _i5.RestorationManager); + + // Parameters {int? priority, _i11.SchedulerBinding? scheduler} have been changed from {int priority, _i11.SchedulerBinding scheduler}. + @override + _i11.SchedulingStrategy get schedulingStrategy => + (super.noSuchMethod(Invocation.getter(#schedulingStrategy), + returnValue: ({int? priority, _i11.SchedulerBinding? scheduler}) => + false) as _i11.SchedulingStrategy); + + @override + set schedulingStrategy(_i11.SchedulingStrategy? _schedulingStrategy) => super + .noSuchMethod(Invocation.setter(#schedulingStrategy, _schedulingStrategy), + returnValueForMissingStub: null); + + @override + int get transientCallbackCount => + (super.noSuchMethod(Invocation.getter(#transientCallbackCount), + returnValue: 0) as int); + + @override + _i9.Future get endOfFrame => + (super.noSuchMethod(Invocation.getter(#endOfFrame), + returnValue: Future.value()) as _i9.Future); + + @override + bool get hasScheduledFrame => + (super.noSuchMethod(Invocation.getter(#hasScheduledFrame), + returnValue: false) as bool); + + @override + _i11.SchedulerPhase get schedulerPhase => + (super.noSuchMethod(Invocation.getter(#schedulerPhase), + returnValue: _i11.SchedulerPhase.idle) as _i11.SchedulerPhase); + + @override + Duration get currentFrameTimeStamp => + (super.noSuchMethod(Invocation.getter(#currentFrameTimeStamp), + returnValue: _FakeDuration_0()) as Duration); + + @override + Duration get currentSystemFrameTimeStamp => + (super.noSuchMethod(Invocation.getter(#currentSystemFrameTimeStamp), + returnValue: _FakeDuration_0()) as Duration); + + @override + _i6.PointerRouter get pointerRouter => + (super.noSuchMethod(Invocation.getter(#pointerRouter), + returnValue: _FakePointerRouter_9()) as _i6.PointerRouter); + + @override + _i6.GestureArenaManager get gestureArena => (super.noSuchMethod( + Invocation.getter(#gestureArena), + returnValue: _FakeGestureArenaManager_10()) as _i6.GestureArenaManager); + + @override + _i6.PointerSignalResolver get pointerSignalResolver => + (super.noSuchMethod(Invocation.getter(#pointerSignalResolver), + returnValue: _FakePointerSignalResolver_11()) + as _i6.PointerSignalResolver); + + @override + bool get resamplingEnabled => + (super.noSuchMethod(Invocation.getter(#resamplingEnabled), + returnValue: false) as bool); + + @override + set resamplingEnabled(bool? _resamplingEnabled) => super.noSuchMethod( + Invocation.setter(#resamplingEnabled, _resamplingEnabled), + returnValueForMissingStub: null); + + @override + Duration get samplingOffset => + (super.noSuchMethod(Invocation.getter(#samplingOffset), + returnValue: _FakeDuration_0()) as Duration); + + @override + set samplingOffset(Duration? _samplingOffset) => + super.noSuchMethod(Invocation.setter(#samplingOffset, _samplingOffset), + returnValueForMissingStub: null); + + @override + _i7.MouseTracker get mouseTracker => + (super.noSuchMethod(Invocation.getter(#mouseTracker), + returnValue: _FakeMouseTracker_12()) as _i7.MouseTracker); + + @override + _i7.PipelineOwner get pipelineOwner => + (super.noSuchMethod(Invocation.getter(#pipelineOwner), + returnValue: _FakePipelineOwner_13()) as _i7.PipelineOwner); + + @override + _i7.RenderView get renderView => + (super.noSuchMethod(Invocation.getter(#renderView), + returnValue: _FakeRenderView_14()) as _i7.RenderView); + + @override + set renderView(_i7.RenderView? value) => + super.noSuchMethod(Invocation.setter(#renderView, value), + returnValueForMissingStub: null); + + @override + bool get sendFramesToEngine => + (super.noSuchMethod(Invocation.getter(#sendFramesToEngine), + returnValue: false) as bool); + + @override + _i4.AccessibilityFeatures get accessibilityFeatures => + (super.noSuchMethod(Invocation.getter(#accessibilityFeatures), + returnValue: _FakeAccessibilityFeatures_15()) + as _i4.AccessibilityFeatures); + + @override + bool get disableAnimations => + (super.noSuchMethod(Invocation.getter(#disableAnimations), + returnValue: false) as bool); + + @override + void initInstances() => + super.noSuchMethod(Invocation.method(#initInstances, []), + returnValueForMissingStub: null); + + @override + void initServiceExtensions() => + super.noSuchMethod(Invocation.method(#initServiceExtensions, []), + returnValueForMissingStub: null); + + @override + void addObserver(_i10.WidgetsBindingObserver? observer) => + super.noSuchMethod(Invocation.method(#addObserver, [observer]), + returnValueForMissingStub: null); + + @override + bool removeObserver(_i10.WidgetsBindingObserver? observer) => + (super.noSuchMethod(Invocation.method(#removeObserver, [observer]), + returnValue: false) as bool); + + @override + void handleMetricsChanged() => + super.noSuchMethod(Invocation.method(#handleMetricsChanged, []), + returnValueForMissingStub: null); + + @override + void handleTextScaleFactorChanged() => + super.noSuchMethod(Invocation.method(#handleTextScaleFactorChanged, []), + returnValueForMissingStub: null); + + @override + void handlePlatformBrightnessChanged() => super.noSuchMethod( + Invocation.method(#handlePlatformBrightnessChanged, []), + returnValueForMissingStub: null); + + @override + void handleAccessibilityFeaturesChanged() => super.noSuchMethod( + Invocation.method(#handleAccessibilityFeaturesChanged, []), + returnValueForMissingStub: null); + + @override + void handleLocaleChanged() => + super.noSuchMethod(Invocation.method(#handleLocaleChanged, []), + returnValueForMissingStub: null); + + @override + void dispatchLocalesChanged(List<_i4.Locale>? locales) => + super.noSuchMethod(Invocation.method(#dispatchLocalesChanged, [locales]), + returnValueForMissingStub: null); + + @override + void dispatchAccessibilityFeaturesChanged() => super.noSuchMethod( + Invocation.method(#dispatchAccessibilityFeaturesChanged, []), + returnValueForMissingStub: null); + + @override + _i9.Future handlePopRoute() => + (super.noSuchMethod(Invocation.method(#handlePopRoute, []), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); + + @override + _i9.Future handlePushRoute(String? route) => + (super.noSuchMethod(Invocation.method(#handlePushRoute, [route]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); + + @override + void handleAppLifecycleStateChanged(_i4.AppLifecycleState? state) => super + .noSuchMethod(Invocation.method(#handleAppLifecycleStateChanged, [state]), + returnValueForMissingStub: null); + + @override + void handleMemoryPressure() => + super.noSuchMethod(Invocation.method(#handleMemoryPressure, []), + returnValueForMissingStub: null); + + @override + void drawFrame() => super.noSuchMethod(Invocation.method(#drawFrame, []), + returnValueForMissingStub: null); + + @override + void scheduleAttachRootWidget(_i12.Widget? rootWidget) => super.noSuchMethod( + Invocation.method(#scheduleAttachRootWidget, [rootWidget]), + returnValueForMissingStub: null); + + @override + void attachRootWidget(_i12.Widget? rootWidget) => + super.noSuchMethod(Invocation.method(#attachRootWidget, [rootWidget]), + returnValueForMissingStub: null); + + @override + _i9.Future performReassemble() => + (super.noSuchMethod(Invocation.method(#performReassemble, []), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); + + @override + _i4.Locale? computePlatformResolvedLocale( + List<_i4.Locale>? supportedLocales) => + (super.noSuchMethod(Invocation.method( + #computePlatformResolvedLocale, [supportedLocales])) as _i4.Locale?); + + @override + _i9.Future lockEvents(_i9.Future Function()? callback) => + (super.noSuchMethod(Invocation.method(#lockEvents, [callback]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); + + @override + void unlocked() => super.noSuchMethod(Invocation.method(#unlocked, []), + returnValueForMissingStub: null); + + @override + _i9.Future reassembleApplication() => + (super.noSuchMethod(Invocation.method(#reassembleApplication, []), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); + + @override + void registerSignalServiceExtension( + {String? name, _i3.AsyncCallback? callback}) => + super.noSuchMethod( + Invocation.method(#registerSignalServiceExtension, [], + {#name: name, #callback: callback}), + returnValueForMissingStub: null); + + @override + void registerBoolServiceExtension( + {String? name, + _i3.AsyncValueGetter? getter, + _i3.AsyncValueSetter? setter}) => + super.noSuchMethod( + Invocation.method(#registerBoolServiceExtension, [], + {#name: name, #getter: getter, #setter: setter}), + returnValueForMissingStub: null); + + @override + void registerNumericServiceExtension( + {String? name, + _i3.AsyncValueGetter? getter, + _i3.AsyncValueSetter? setter}) => + super.noSuchMethod( + Invocation.method(#registerNumericServiceExtension, [], + {#name: name, #getter: getter, #setter: setter}), + returnValueForMissingStub: null); + + @override + void postEvent(String? eventKind, Map? eventData) => + super.noSuchMethod(Invocation.method(#postEvent, [eventKind, eventData]), + returnValueForMissingStub: null); + + @override + void registerStringServiceExtension( + {String? name, + _i3.AsyncValueGetter? getter, + _i3.AsyncValueSetter? setter}) => + super.noSuchMethod( + Invocation.method(#registerStringServiceExtension, [], + {#name: name, #getter: getter, #setter: setter}), + returnValueForMissingStub: null); + + @override + void registerServiceExtension( + {String? name, _i3.ServiceExtensionCallback? callback}) => + super.noSuchMethod( + Invocation.method(#registerServiceExtension, [], + {#name: name, #callback: callback}), + returnValueForMissingStub: null); + + @override + _i5.BinaryMessenger createBinaryMessenger() => + (super.noSuchMethod(Invocation.method(#createBinaryMessenger, []), + returnValue: _FakeBinaryMessenger_6()) as _i5.BinaryMessenger); + + @override + _i9.Future handleSystemMessage(Object? systemMessage) => (super + .noSuchMethod(Invocation.method(#handleSystemMessage, [systemMessage]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); + + @override + void initLicenses() => + super.noSuchMethod(Invocation.method(#initLicenses, []), + returnValueForMissingStub: null); + + @override + void evict(String? asset) => + super.noSuchMethod(Invocation.method(#evict, [asset]), + returnValueForMissingStub: null); + + @override + void readInitialLifecycleStateFromNativeWindow() => super.noSuchMethod( + Invocation.method(#readInitialLifecycleStateFromNativeWindow, []), + returnValueForMissingStub: null); + + @override + _i5.RestorationManager createRestorationManager() => + (super.noSuchMethod(Invocation.method(#createRestorationManager, []), + returnValue: _FakeRestorationManager_8()) as _i5.RestorationManager); + + @override + void setSystemUiChangeCallback(_i5.SystemUiChangeCallback? callback) => super + .noSuchMethod(Invocation.method(#setSystemUiChangeCallback, [callback]), + returnValueForMissingStub: null); + + @override + void addTimingsCallback(_i4.TimingsCallback? callback) => + super.noSuchMethod(Invocation.method(#addTimingsCallback, [callback]), + returnValueForMissingStub: null); + + @override + void removeTimingsCallback(_i4.TimingsCallback? callback) => + super.noSuchMethod(Invocation.method(#removeTimingsCallback, [callback]), + returnValueForMissingStub: null); + + @override + _i9.Future scheduleTask( + _i11.TaskCallback? task, _i11.Priority? priority, + {String? debugLabel, _i13.Flow? flow}) => + (super.noSuchMethod( + Invocation.method(#scheduleTask, [task, priority], + {#debugLabel: debugLabel, #flow: flow}), + returnValue: Future.value(null)) as _i9.Future); + + @override + bool handleEventLoopCallback() => + (super.noSuchMethod(Invocation.method(#handleEventLoopCallback, []), + returnValue: false) as bool); + + @override + int scheduleFrameCallback(_i11.FrameCallback? callback, + {bool? rescheduling = false}) => + (super.noSuchMethod( + Invocation.method(#scheduleFrameCallback, [callback], + {#rescheduling: rescheduling}), + returnValue: 0) as int); + + @override + void cancelFrameCallbackWithId(int? id) => + super.noSuchMethod(Invocation.method(#cancelFrameCallbackWithId, [id]), + returnValueForMissingStub: null); + + @override + bool debugAssertNoTransientCallbacks(String? reason) => (super.noSuchMethod( + Invocation.method(#debugAssertNoTransientCallbacks, [reason]), + returnValue: false) as bool); + + @override + void addPersistentFrameCallback(_i11.FrameCallback? callback) => super + .noSuchMethod(Invocation.method(#addPersistentFrameCallback, [callback]), + returnValueForMissingStub: null); + + @override + void addPostFrameCallback(_i11.FrameCallback? callback) => + super.noSuchMethod(Invocation.method(#addPostFrameCallback, [callback]), + returnValueForMissingStub: null); + + @override + void ensureFrameCallbacksRegistered() => + super.noSuchMethod(Invocation.method(#ensureFrameCallbacksRegistered, []), + returnValueForMissingStub: null); + + @override + void ensureVisualUpdate() => + super.noSuchMethod(Invocation.method(#ensureVisualUpdate, []), + returnValueForMissingStub: null); + + @override + void scheduleFrame() => + super.noSuchMethod(Invocation.method(#scheduleFrame, []), + returnValueForMissingStub: null); + + @override + void scheduleForcedFrame() => + super.noSuchMethod(Invocation.method(#scheduleForcedFrame, []), + returnValueForMissingStub: null); + + @override + void scheduleWarmUpFrame() => + super.noSuchMethod(Invocation.method(#scheduleWarmUpFrame, []), + returnValueForMissingStub: null); + + @override + void resetEpoch() => super.noSuchMethod(Invocation.method(#resetEpoch, []), + returnValueForMissingStub: null); + + @override + void handleBeginFrame(Duration? rawTimeStamp) => + super.noSuchMethod(Invocation.method(#handleBeginFrame, [rawTimeStamp]), + returnValueForMissingStub: null); + + @override + void handleDrawFrame() => + super.noSuchMethod(Invocation.method(#handleDrawFrame, []), + returnValueForMissingStub: null); + + @override + void cancelPointer(int? pointer) => + super.noSuchMethod(Invocation.method(#cancelPointer, [pointer]), + returnValueForMissingStub: null); + + @override + void handlePointerEvent(_i7.PointerEvent? event) => + super.noSuchMethod(Invocation.method(#handlePointerEvent, [event]), + returnValueForMissingStub: null); + + @override + void hitTest(_i7.HitTestResult? result, _i4.Offset? position) => + super.noSuchMethod(Invocation.method(#hitTest, [result, position]), + returnValueForMissingStub: null); + + @override + void dispatchEvent( + _i7.PointerEvent? event, _i7.HitTestResult? hitTestResult) => + super.noSuchMethod( + Invocation.method(#dispatchEvent, [event, hitTestResult]), + returnValueForMissingStub: null); + + @override + void handleEvent(_i7.PointerEvent? event, _i7.HitTestEntry? entry) => + super.noSuchMethod(Invocation.method(#handleEvent, [event, entry]), + returnValueForMissingStub: null); + + @override + void resetGestureBinding() => + super.noSuchMethod(Invocation.method(#resetGestureBinding, []), + returnValueForMissingStub: null); + + @override + void initRenderView() => + super.noSuchMethod(Invocation.method(#initRenderView, []), + returnValueForMissingStub: null); + + @override + _i7.ViewConfiguration createViewConfiguration() => + (super.noSuchMethod(Invocation.method(#createViewConfiguration, []), + returnValue: _FakeViewConfiguration_16()) as _i7.ViewConfiguration); + + @override + void initMouseTracker([_i7.MouseTracker? tracker]) => + super.noSuchMethod(Invocation.method(#initMouseTracker, [tracker]), + returnValueForMissingStub: null); + + @override + void setSemanticsEnabled(bool? enabled) => + super.noSuchMethod(Invocation.method(#setSemanticsEnabled, [enabled]), + returnValueForMissingStub: null); + + @override + void deferFirstFrame() => + super.noSuchMethod(Invocation.method(#deferFirstFrame, []), + returnValueForMissingStub: null); + + @override + void allowFirstFrame() => + super.noSuchMethod(Invocation.method(#allowFirstFrame, []), + returnValueForMissingStub: null); + + @override + void resetFirstFrameSent() => + super.noSuchMethod(Invocation.method(#resetFirstFrameSent, []), + returnValueForMissingStub: null); + + @override + _i4.SemanticsUpdateBuilder createSemanticsUpdateBuilder() => + (super.noSuchMethod(Invocation.method(#createSemanticsUpdateBuilder, []), + returnValue: _FakeSemanticsUpdateBuilder_17()) + as _i4.SemanticsUpdateBuilder); +} From 608f5e50b2b495e8b3e53641421d1d53fc76628a Mon Sep 17 00:00:00 2001 From: Andrew Amin Date: Sun, 22 Jun 2025 17:49:01 +0300 Subject: [PATCH 09/15] chore: run dart format . --- .../utils/screen_render/instabug_screen_render_manager_test.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/test/utils/screen_render/instabug_screen_render_manager_test.dart b/test/utils/screen_render/instabug_screen_render_manager_test.dart index 54b16301d..f77d8b234 100644 --- a/test/utils/screen_render/instabug_screen_render_manager_test.dart +++ b/test/utils/screen_render/instabug_screen_render_manager_test.dart @@ -1,4 +1,3 @@ - import 'package:flutter_test/flutter_test.dart'; import 'package:instabug_flutter/instabug_flutter.dart'; import 'package:instabug_flutter/src/models/instabug_frame_data.dart'; From dce7286e16d06be84a3efdb912cf35e4019067bf Mon Sep 17 00:00:00 2001 From: Andrew Amin Date: Sun, 22 Jun 2025 18:05:18 +0300 Subject: [PATCH 10/15] chore: run dart format . --- .../instabug_screen_render_manager_test_manual_mocks.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/utils/screen_render/instabug_screen_render_manager_test_manual_mocks.dart b/test/utils/screen_render/instabug_screen_render_manager_test_manual_mocks.dart index 0560e4bcc..b35602da3 100644 --- a/test/utils/screen_render/instabug_screen_render_manager_test_manual_mocks.dart +++ b/test/utils/screen_render/instabug_screen_render_manager_test_manual_mocks.dart @@ -393,7 +393,8 @@ class MockWidgetsBinding extends _i1.Mock implements _i10.WidgetsBinding { (super.noSuchMethod(Invocation.getter(#restorationManager), returnValue: _FakeRestorationManager_8()) as _i5.RestorationManager); - // Parameters {int? priority, _i11.SchedulerBinding? scheduler} have been changed from {int priority, _i11.SchedulerBinding scheduler}. + // Parameters {int? priority, _i11.SchedulerBinding? scheduler} have been + // changed from {int priority, _i11.SchedulerBinding scheduler}. @override _i11.SchedulingStrategy get schedulingStrategy => (super.noSuchMethod(Invocation.getter(#schedulingStrategy), From 83cbbbac105e01fe8989d78f2daf417560693055 Mon Sep 17 00:00:00 2001 From: Andrew Amin Date: Sat, 28 Jun 2025 23:52:39 +0300 Subject: [PATCH 11/15] chore: add native feature apis --- android/build.gradle | 11 +- .../flutter/InstabugFlutterPlugin.java | 27 +- .../com/instabug/flutter/modules/ApmApi.java | 32 +- .../java/com/instabug/flutter/ApmApiTest.java | 42 +- example/ios/Podfile | 3 +- example/ios/Podfile.lock | 16 +- example/ios/Runner.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/xcschemes/Runner.xcscheme | 5 +- example/lib/main.dart | 46 +- example/pubspec.lock | 189 ++-- ios/Classes/Modules/ApmApi.m | 57 +- ios/Classes/Util/IBGAPM+PrivateAPIs.h | 2 + ios/instabug_flutter.podspec | 2 +- lib/src/modules/apm.dart | 13 + lib/src/modules/instabug.dart | 2 +- .../utils/instabug_navigator_observer.dart | 19 +- .../instabug_screen_render_manager.dart | 38 +- pigeons/apm.api.dart | 2 + scripts/pigeon.sh | 0 .../instabug_screen_render_manager_test.dart | 31 +- ...reen_render_manager_test_manual_mocks.dart | 880 ------------------ 21 files changed, 345 insertions(+), 1074 deletions(-) mode change 100644 => 100755 scripts/pigeon.sh delete mode 100644 test/utils/screen_render/instabug_screen_render_manager_test_manual_mocks.dart diff --git a/android/build.gradle b/android/build.gradle index a6c41ffd0..0a1bab7ea 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,3 +1,5 @@ +package android + group 'com.instabug.flutter' version '14.3.0' @@ -16,9 +18,17 @@ rootProject.allprojects { repositories { google() mavenCentral() + maven { + url "https://mvn.instabug.com/nexus/repository/instabug-internal/" + credentials { + username "instabug" + password System.getenv("INSTABUG_REPOSITORY_PASSWORD") + } + } } } + apply plugin: 'com.android.library' android { @@ -48,7 +58,6 @@ dependencies { testImplementation 'junit:junit:4.13.2' testImplementation "org.mockito:mockito-inline:3.12.1" testImplementation "io.mockk:mockk:1.13.13" - } // add upload_symbols task diff --git a/android/src/main/java/com/instabug/flutter/InstabugFlutterPlugin.java b/android/src/main/java/com/instabug/flutter/InstabugFlutterPlugin.java index bb3b043fa..3a51a4051 100644 --- a/android/src/main/java/com/instabug/flutter/InstabugFlutterPlugin.java +++ b/android/src/main/java/com/instabug/flutter/InstabugFlutterPlugin.java @@ -4,7 +4,9 @@ import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; +import android.os.Build; import android.util.Log; +import android.view.Display; import android.view.View; import androidx.annotation.NonNull; @@ -73,7 +75,14 @@ public Bitmap call() { } }; - ApmApi.init(messenger); + Callable refreshRateProvider = new Callable() { + @Override + public Float call(){ + return getRefreshRate(); + } + }; + + ApmApi.init(messenger, refreshRateProvider); BugReportingApi.init(messenger); CrashReportingApi.init(messenger); FeatureRequestsApi.init(messenger); @@ -99,4 +108,20 @@ private static Bitmap takeScreenshot(FlutterRenderer renderer) { return null; } } + + private static float getRefreshRate() { + float refreshRate = 60f; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + final Display display = activity.getDisplay(); + if (display != null) { + refreshRate = display.getRefreshRate(); + } + } else { + refreshRate = activity.getWindowManager().getDefaultDisplay().getRefreshRate(); + } + + return refreshRate; + } + } diff --git a/android/src/main/java/com/instabug/flutter/modules/ApmApi.java b/android/src/main/java/com/instabug/flutter/modules/ApmApi.java index ee93d7614..3b16e93fb 100644 --- a/android/src/main/java/com/instabug/flutter/modules/ApmApi.java +++ b/android/src/main/java/com/instabug/flutter/modules/ApmApi.java @@ -23,13 +23,20 @@ import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.Callable; public class ApmApi implements ApmPigeon.ApmHostApi { private final String TAG = ApmApi.class.getName(); private final HashMap traces = new HashMap<>(); + private final Callable refreshRate; - public static void init(BinaryMessenger messenger) { - final ApmApi api = new ApmApi(); + public ApmApi(Callable refreshRate) { + this.refreshRate = refreshRate; + } + + public static void init(BinaryMessenger messenger, Callable refreshRateProvider) { + + final ApmApi api = new ApmApi(refreshRateProvider); ApmPigeon.ApmHostApi.setup(messenger, api); } @@ -475,11 +482,24 @@ public void setScreenLoadingEnabled(@NonNull Boolean isEnabled) { } } + @Override + public void setScreenRenderEnabled(@NonNull Boolean isEnabled) { + try { + APM.setScreenRenderingEnabled(isEnabled); + } catch (Exception e) { + e.printStackTrace(); + } + } @Override public void isScreenRenderEnabled(@NonNull ApmPigeon.Result result) { try { - result.success(true); + InternalAPM._isFeatureEnabledCP(APMFeature.SCREEN_RENDERING, "InstabugCaptureScreenRender", new FeatureAvailabilityCallback() { + @Override + public void invoke(boolean isEnabled) { + result.success(isEnabled); + } + }); } catch (Exception e) { e.printStackTrace(); } @@ -487,7 +507,11 @@ public void isScreenRenderEnabled(@NonNull ApmPigeon.Result result) { @Override public void deviceRefreshRate(@NonNull ApmPigeon.Result result) { - result.success(60.0); + try { + result.success(refreshRate.call().doubleValue()); + } catch (Exception e) { + e.printStackTrace(); + } } } diff --git a/android/src/test/java/com/instabug/flutter/ApmApiTest.java b/android/src/test/java/com/instabug/flutter/ApmApiTest.java index 725d3bd98..4ef118cec 100644 --- a/android/src/test/java/com/instabug/flutter/ApmApiTest.java +++ b/android/src/test/java/com/instabug/flutter/ApmApiTest.java @@ -8,10 +8,9 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.mockConstruction; import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; import com.instabug.apm.APM; import com.instabug.apm.InternalAPM; @@ -24,8 +23,6 @@ import com.instabug.flutter.util.GlobalMocks; import com.instabug.flutter.util.MockReflected; -import io.flutter.plugin.common.BinaryMessenger; - import org.json.JSONObject; import org.junit.After; import org.junit.Assert; @@ -36,18 +33,21 @@ import java.util.HashMap; import java.util.Map; +import java.util.concurrent.Callable; import static com.instabug.flutter.util.GlobalMocks.reflected; import static com.instabug.flutter.util.MockResult.makeResult; import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; +import io.flutter.plugin.common.BinaryMessenger; public class ApmApiTest { private final BinaryMessenger mMessenger = mock(BinaryMessenger.class); - private final ApmApi api = new ApmApi(); + private final Callable refreshRateProvider = () -> mock(Float.class); + private final ApmApi api = new ApmApi(refreshRateProvider); private MockedStatic mAPM; private MockedStatic mInternalApmStatic; private MockedStatic mHostApi; @@ -83,7 +83,7 @@ private ExecutionTrace mockTrace(String id) { public void testInit() { BinaryMessenger messenger = mock(BinaryMessenger.class); - ApmApi.init(messenger); + ApmApi.init(messenger, refreshRateProvider); mHostApi.verify(() -> ApmPigeon.ApmHostApi.setup(eq(messenger), any(ApmApi.class))); } @@ -386,4 +386,34 @@ public void testSetScreenLoadingMonitoringEnabled() { mAPM.verify(() -> APM.setScreenLoadingEnabled(isEnabled)); } + + @Test + public void testIsScreenRenderEnabled() { + + boolean expected = true; + ApmPigeon.Result result = spy(makeResult((actual) -> assertEquals(expected, actual))); + + mInternalApmStatic.when(() -> InternalAPM._isFeatureEnabledCP(any(), any(), any())).thenAnswer( + invocation -> { + FeatureAvailabilityCallback callback = (FeatureAvailabilityCallback) invocation.getArguments()[2]; + callback.invoke(expected); + return null; + }); + + + api.isScreenRenderEnabled(result); + + mInternalApmStatic.verify(() -> InternalAPM._isFeatureEnabledCP(any(), any(), any())); + mInternalApmStatic.verifyNoMoreInteractions(); + + verify(result).success(expected); + } + + public void testSetScreenRenderEnabled() { + boolean isEnabled = false; + + api.setScreenRenderEnabled(isEnabled); + + mAPM.verify(() -> APM.setScreenRenderingEnabled(isEnabled)); + } } diff --git a/example/ios/Podfile b/example/ios/Podfile index 6020d7a4b..f72ca45fe 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -30,7 +30,8 @@ target 'Runner' do use_frameworks! use_modular_headers! - pod 'Instabug', :podspec => 'https://ios-releases.instabug.com/custom/fix-main-thread-warning/15.0.0/Instabug.podspec' +# pod 'Instabug', :podspec => 'https://ios-releases.instabug.com/custom/fix-main-thread-warning/15.0.0/Instabug.podspec' + pod 'Instabug', :podspec => 'https://ios-releases.instabug.com/custom/faeture-screen_rendering-release/15.1.0/Instabug.podspec' flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) end diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index fdf33bc82..7fcc59514 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,14 +1,14 @@ PODS: - Flutter (1.0.0) - - Instabug (15.0.0) + - Instabug (15.1.0) - instabug_flutter (14.3.0): - Flutter - - Instabug (= 15.0.0) + - Instabug (= 15.1.0) - OCMock (3.6) DEPENDENCIES: - Flutter (from `Flutter`) - - Instabug (from `https://ios-releases.instabug.com/custom/fix-main-thread-warning/15.0.0/Instabug.podspec`) + - Instabug (from `https://ios-releases.instabug.com/custom/faeture-screen_rendering-release/15.1.0/Instabug.podspec`) - instabug_flutter (from `.symlinks/plugins/instabug_flutter/ios`) - OCMock (= 3.6) @@ -20,16 +20,16 @@ EXTERNAL SOURCES: Flutter: :path: Flutter Instabug: - :podspec: https://ios-releases.instabug.com/custom/fix-main-thread-warning/15.0.0/Instabug.podspec + :podspec: https://ios-releases.instabug.com/custom/faeture-screen_rendering-release/15.1.0/Instabug.podspec instabug_flutter: :path: ".symlinks/plugins/instabug_flutter/ios" SPEC CHECKSUMS: - Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 - Instabug: 3b1db5a683e85ec5a02946aa2b3314036f9022be - instabug_flutter: e59da7a0cae82ce00b2773625ee544c275442000 + Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a + Instabug: a2b8c384cd4af7a01ab43b2ce2957a880f8862d7 + instabug_flutter: 6ee721f30066123a769da64b687eded6eb4ff125 OCMock: 5ea90566be239f179ba766fd9fbae5885040b992 -PODFILE CHECKSUM: c16418947581b888c337ed7ff120a59b4b5f3f3f +PODFILE CHECKSUM: e6e180d6b55e3a12f55f266c3f4d8654480877ef COCOAPODS: 1.15.2 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index d32f983fc..2d4497cb9 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -271,7 +271,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1510; + LastUpgradeCheck = 1300; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 0b15932d1..b7206827b 100644 --- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ diff --git a/example/lib/main.dart b/example/lib/main.dart index 8895bd084..020c05b59 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,54 +1,38 @@ import 'dart:async'; +import 'dart:convert'; import 'dart:developer'; import 'dart:io'; -import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:instabug_flutter/instabug_flutter.dart'; -import 'package:instabug_flutter_example/src/components/apm_switch.dart'; -import 'package:instabug_http_client/instabug_http_client.dart'; +import 'package:instabug_flutter/src/utils/screen_loading/screen_loading_manager.dart'; import 'package:instabug_flutter_example/src/app_routes.dart'; +import 'package:instabug_flutter_example/src/components/apm_switch.dart'; import 'package:instabug_flutter_example/src/widget/nested_view.dart'; +import 'package:instabug_http_client/instabug_http_client.dart'; import 'src/native/instabug_flutter_example_method_channel.dart'; import 'src/widget/instabug_button.dart'; import 'src/widget/instabug_clipboard_input.dart'; import 'src/widget/instabug_text_field.dart'; -import 'package:instabug_flutter/src/utils/screen_loading/screen_loading_manager.dart'; - import 'src/widget/section_title.dart'; -part 'src/screens/crashes_page.dart'; - -part 'src/screens/complex_page.dart'; - -part 'src/screens/apm_page.dart'; - -part 'src/screens/screen_capture_premature_extension_page.dart'; - -part 'src/screens/screen_loading_page.dart'; - -part 'src/screens/my_home_page.dart'; - -part 'src/screens/screen_render_page.dart'; - +part 'src/components/animated_box.dart'; part 'src/components/fatal_crashes_content.dart'; - -part 'src/components/non_fatal_crashes_content.dart'; - +part 'src/components/flows_content.dart'; part 'src/components/network_content.dart'; - +part 'src/components/non_fatal_crashes_content.dart'; part 'src/components/page.dart'; - -part 'src/components/traces_content.dart'; - -part 'src/components/flows_content.dart'; - part 'src/components/screen_render.dart'; - -part 'src/components/animated_box.dart'; - +part 'src/components/traces_content.dart'; part 'src/components/ui_traces_content.dart'; +part 'src/screens/apm_page.dart'; +part 'src/screens/complex_page.dart'; +part 'src/screens/crashes_page.dart'; +part 'src/screens/my_home_page.dart'; +part 'src/screens/screen_capture_premature_extension_page.dart'; +part 'src/screens/screen_loading_page.dart'; +part 'src/screens/screen_render_page.dart'; void main() { runZonedGuarded( diff --git a/example/pubspec.lock b/example/pubspec.lock index ba4cc0a6d..db618bb81 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -1,62 +1,76 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + archive: + dependency: transitive + description: + name: archive + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.6" async: dependency: transitive description: name: async - sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.11.0" + version: "2.8.2" boolean_selector: dependency: transitive description: name: boolean_selector - sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.0" characters: dependency: transitive description: name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.2.0" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.1" clock: dependency: transitive description: name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.1.1" + version: "1.1.0" collection: dependency: transitive description: name: collection - sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.19.0" + version: "1.15.0" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" fake_async: dependency: transitive description: name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.3.1" + version: "1.2.0" file: dependency: transitive description: name: file - sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "7.0.0" + version: "6.1.2" flutter: dependency: "direct main" description: flutter @@ -71,8 +85,7 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: b543301ad291598523947dc534aaddc5aaad597b709d2426d3a0e0d44c5cb493 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.4" flutter_test: @@ -89,16 +102,14 @@ packages: dependency: "direct main" description: name: http - sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "0.13.6" + version: "0.13.5" http_parser: dependency: transitive description: name: http_parser - sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "4.0.2" instabug_flutter: @@ -112,183 +123,139 @@ packages: dependency: "direct main" description: name: instabug_http_client - sha256: "7d52803c0dd639f6dddbe07333418eb251ae02f3f9f4d30402517533ca692784" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.4.0" - leak_tracker: - dependency: transitive - description: - name: leak_tracker - sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" - url: "https://pub.dev" - source: hosted - version: "10.0.7" - leak_tracker_flutter_testing: - dependency: transitive - description: - name: leak_tracker_flutter_testing - sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" - url: "https://pub.dev" - source: hosted - version: "3.0.8" - leak_tracker_testing: - dependency: transitive - description: - name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" - url: "https://pub.dev" - source: hosted - version: "3.0.1" + version: "2.5.1" lints: dependency: transitive description: name: lints - sha256: a2c3d198cb5ea2e179926622d433331d8b58374ab8f29cdda6e863bd62fd369c - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.1" matcher: dependency: transitive description: name: matcher - sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "0.12.16+1" + version: "0.12.11" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "0.11.1" + version: "0.1.3" meta: dependency: transitive description: name: meta - sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.15.0" + version: "1.7.0" path: dependency: transitive description: name: path - sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.9.0" + version: "1.8.0" platform: dependency: transitive description: name: platform - sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "3.1.5" + version: "3.1.0" process: dependency: transitive description: name: process - sha256: "21e54fd2faf1b5bdd5102afd25012184a6793927648ea81eea80552ac9405b32" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "5.0.2" + version: "4.2.4" sky_engine: dependency: transitive description: flutter source: sdk - version: "0.0.0" + version: "0.0.99" source_span: dependency: transitive description: name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.10.0" + version: "1.8.1" stack_trace: dependency: transitive description: name: stack_trace - sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.12.0" + version: "1.10.0" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.1.2" + version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner - sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.1.0" sync_http: dependency: transitive description: name: sync_http - sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "0.3.1" + version: "0.3.0" term_glyph: dependency: transitive description: name: term_glyph - sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.2.1" + version: "1.2.0" test_api: dependency: transitive description: name: test_api - sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "0.7.3" + version: "0.4.8" typed_data: dependency: transitive description: name: typed_data - sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.4.0" + version: "1.3.0" vector_math: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.1.4" + version: "2.1.1" vm_service: dependency: transitive description: name: vm_service - sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "14.3.0" + version: "7.5.0" webdriver: dependency: transitive description: name: webdriver - sha256: "3d773670966f02a646319410766d3b5e1037efb7f07cc68f844d5e06cd4d61c8" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "3.0.4" + version: "3.0.0" sdks: - dart: ">=3.5.0 <4.0.0" - flutter: ">=3.18.0-18.0.pre.54" + dart: ">=2.14.0 <3.0.0" diff --git a/ios/Classes/Modules/ApmApi.m b/ios/Classes/Modules/ApmApi.m index 01d4952b3..385936702 100644 --- a/ios/Classes/Modules/ApmApi.m +++ b/ios/Classes/Modules/ApmApi.m @@ -91,7 +91,7 @@ - (void)startExecutionTraceId:(NSString *)id name:(NSString *)name completion:(v // Deprecated - see [startFlowName, setFlowAttributeName & endFlowName]. - (void)setExecutionTraceAttributeId:(NSString *)id key:(NSString *)key value:(NSString *)value error:(FlutterError *_Nullable *_Nonnull)error { IBGExecutionTrace *trace = [traces objectForKey:id]; - + if (trace != nil) { [trace setAttributeWithKey:key value:value]; } @@ -103,7 +103,7 @@ - (void)setExecutionTraceAttributeId:(NSString *)id key:(NSString *)key value:(N // Deprecated - see [startFlowName, setFlowAttributeName & endFlowName]. - (void)endExecutionTraceId:(NSString *)id error:(FlutterError *_Nullable *_Nonnull)error { IBGExecutionTrace *trace = [traces objectForKey:id]; - + if (trace != nil) { [trace end]; } @@ -130,13 +130,13 @@ - (void)endFlowName:(nonnull NSString *)name error:(FlutterError * _Nullable __a [IBGAPM endFlowWithName:name]; } -// This method is responsible for starting a UI trace with the given `name`. +// This method is responsible for starting a UI trace with the given `name`. // Which initiates the tracking of user interface interactions for monitoring the performance of the application. - (void)startUITraceName:(NSString *)name error:(FlutterError *_Nullable *_Nonnull)error { [IBGAPM startUITraceWithName:name]; } -// The method is responsible for ending the currently active UI trace. +// The method is responsible for ending the currently active UI trace. // Which signifies the completion of tracking user interface interactions. - (void)endUITraceWithError:(FlutterError *_Nullable *_Nonnull)error { [IBGAPM endUITrace]; @@ -198,13 +198,58 @@ - (void)isEndScreenLoadingEnabledWithCompletion:(nonnull void (^)(NSNumber * _Nu } - (void)isScreenRenderEnabledWithCompletion:(void (^)(NSNumber * _Nullable, FlutterError * _Nullable))completion{ - BOOL isScreenRenderEnabled = YES; + BOOL isScreenRenderEnabled = IBGAPM.isScreenRenderingOperational; NSNumber *isEnabledNumber = @(isScreenRenderEnabled); completion(isEnabledNumber, nil); } +- (void)setScreenRenderEnabledIsEnabled:(nonnull NSNumber *)isEnabled error:(FlutterError * _Nullable __autoreleasing * _Nonnull)error { + [IBGAPM setScreenRenderingEnabled:[isEnabled boolValue]]; + +} + - (void)deviceRefreshRateWithCompletion:(void (^)(NSNumber * _Nullable, FlutterError * _Nullable))completion{ - completion(@60 , nil); + // First, try using CADisplayLink to get the preferred frame rate. + // This is a more modern approach, especially for ProMotion displays. + CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(onDisplayLink:)]; + displayLink.paused = YES; + [displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; + + NSInteger preferredFPS = displayLink.preferredFramesPerSecond; + + [displayLink invalidate]; + + if (preferredFPS != 0) { + completion(@(preferredFPS) , nil); + return; + } + + // If CADisplayLink fails, fall back to other methods. + // For iOS 13+, use the windowScene for better accuracy in multi-window environments. + if (@available(iOS 13.0, *)) { + UIWindowScene *windowScene = nil; + // Find the first active window scene + for (UIScene *scene in [UIApplication sharedApplication].connectedScenes) { + if (scene.activationState == UISceneActivationStateForegroundActive && [scene isKindOfClass:[UIWindowScene class]]) { + windowScene = (UIWindowScene *)scene; + break; + } + } + + if (windowScene) { + completion(@(windowScene.screen.maximumFramesPerSecond) , nil); + return; + } + } + + // As a final fallback (and for iOS versions < 13), use the main screen. + if (@available(iOS 10.3, *)) { + double refreshRate = [UIScreen mainScreen].maximumFramesPerSecond; + completion(@(refreshRate) ,nil); + } else { + // Fallback for very old iOS versions. + completion(@(60.0) , nil); + } } diff --git a/ios/Classes/Util/IBGAPM+PrivateAPIs.h b/ios/Classes/Util/IBGAPM+PrivateAPIs.h index 22207d45b..dba847b13 100644 --- a/ios/Classes/Util/IBGAPM+PrivateAPIs.h +++ b/ios/Classes/Util/IBGAPM+PrivateAPIs.h @@ -22,4 +22,6 @@ + (void)endScreenLoadingCPWithEndTimestampMUS:(IBGMicroSecondsTimeInterval)endTimestampMUS; ++ (BOOL)isScreenRenderingOperational; + @end diff --git a/ios/instabug_flutter.podspec b/ios/instabug_flutter.podspec index 22c684ec7..cf6703fda 100644 --- a/ios/instabug_flutter.podspec +++ b/ios/instabug_flutter.podspec @@ -17,6 +17,6 @@ Pod::Spec.new do |s| s.pod_target_xcconfig = { 'OTHER_LDFLAGS' => '-framework "Flutter" -framework "InstabugSDK"'} s.dependency 'Flutter' - s.dependency 'Instabug', '15.0.0' + s.dependency 'Instabug', '15.1.0' end diff --git a/lib/src/modules/apm.dart b/lib/src/modules/apm.dart index efd9dc609..4077d65f2 100644 --- a/lib/src/modules/apm.dart +++ b/lib/src/modules/apm.dart @@ -381,4 +381,17 @@ class APM { static Future getDeviceRefreshRate() { return _host.deviceRefreshRate(); } + + /// Sets the screen Render state based on the provided boolean value. + /// + /// Args: + /// isEnabled (bool): The [isEnabled] parameter is a boolean value that determines whether screen + /// Render is enabled or disabled. If [isEnabled] is `true`, screen render will be enabled; if + /// [isEnabled] is `false`, screen render will be disabled. + /// + /// Returns: + /// A Future is being returned. + static Future setScreenRenderEnabled(bool isEnabled) { + return _host.setScreenRenderEnabled(isEnabled); + } } diff --git a/lib/src/modules/instabug.dart b/lib/src/modules/instabug.dart index 9ef4930b0..3d7b52f1b 100644 --- a/lib/src/modules/instabug.dart +++ b/lib/src/modules/instabug.dart @@ -191,6 +191,7 @@ class Instabug { }) async { $setup(); InstabugLogger.I.logLevel = debugLogsLevel; + checkForWidgetBinding(); await _host.init( token, invocationEvents.mapToString(), @@ -198,7 +199,6 @@ class Instabug { ); if (await FlagsConfig.screenRendering.isEnabled()) { - checkForWidgetBinding(); InstabugScreenRenderManager.I.init(WidgetsBinding.instance); } diff --git a/lib/src/utils/instabug_navigator_observer.dart b/lib/src/utils/instabug_navigator_observer.dart index 4f3e814ff..80b4cb13d 100644 --- a/lib/src/utils/instabug_navigator_observer.dart +++ b/lib/src/utils/instabug_navigator_observer.dart @@ -1,3 +1,6 @@ +import 'dart:async'; +import 'dart:developer'; + import 'package:flutter/material.dart'; import 'package:instabug_flutter/instabug_flutter.dart'; import 'package:instabug_flutter/src/models/instabug_route.dart'; @@ -6,6 +9,8 @@ import 'package:instabug_flutter/src/utils/instabug_logger.dart'; import 'package:instabug_flutter/src/utils/repro_steps_constants.dart'; import 'package:instabug_flutter/src/utils/screen_loading/screen_loading_manager.dart'; import 'package:instabug_flutter/src/utils/screen_name_masker.dart'; +import 'package:instabug_flutter/src/utils/screen_rendering/instabug_screen_render_manager.dart'; +import 'package:instabug_flutter/src/utils/ui_trace/flags_config.dart'; class InstabugNavigatorObserver extends NavigatorObserver { final List _steps = []; @@ -23,8 +28,9 @@ class InstabugNavigatorObserver extends NavigatorObserver { name: maskedScreenName, ); - // Starts a the new UI trace which is exclusive to screen loading - ScreenLoadingManager.I.startUiTrace(maskedScreenName, screenName); + ScreenLoadingManager.I + .startUiTrace(maskedScreenName, screenName) + .then(_startScreenRenderCollector); // If there is a step that hasn't been pushed yet if (_steps.isNotEmpty) { @@ -48,6 +54,15 @@ class InstabugNavigatorObserver extends NavigatorObserver { } } + FutureOr _startScreenRenderCollector(int? uiTraceId) async { + final isScreenRender = await FlagsConfig.screenRendering.isEnabled(); + log("isScreenRender: $isScreenRender", name: 'Andrew'); + if (uiTraceId != null && isScreenRender) { + InstabugScreenRenderManager.I + .startScreenRenderCollectorForTraceId(uiTraceId); + } + } + @override void didPop(Route route, Route? previousRoute) { if (previousRoute != null) { diff --git a/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart b/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart index bde2008c3..50e16fbc5 100644 --- a/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart +++ b/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart @@ -142,9 +142,11 @@ class InstabugScreenRenderManager { 1 / displayRefreshRate * 1000; /// Get device refresh rate from native side. - //todo: will be compared with value from native side after it's implemented. - Future get _getDeviceRefreshRateFromNative => - APM.getDeviceRefreshRate(); + Future get _getDeviceRefreshRateFromNative { + final rr = APM.getDeviceRefreshRate(); + log("refreshRateFromNative: $rr", name: "Andrew"); + return rr; + } /// Initialize the static variables Future _initStaticValues() async { @@ -162,12 +164,16 @@ class InstabugScreenRenderManager { /// Add a frame observer by calling [WidgetsBinding.instance.addTimingsCallback] void _initFrameTimings() { + if (_isTimingsListenerAttached) { + return; // A timings callback is already attached + } _widgetsBinding.addTimingsCallback(_timingsCallback); _isTimingsListenerAttached = true; } /// Remove the running frame observer by calling [_widgetsBinding.removeTimingsCallback] void _removeFrameTimings() { + if (!_isTimingsListenerAttached) return; // No timings callback attached. _widgetsBinding.removeTimingsCallback(_timingsCallback); _isTimingsListenerAttached = false; } @@ -212,6 +218,8 @@ class InstabugScreenRenderManager { /// Stop screen render collector and sync the captured data. @internal void stopScreenRenderCollector() { + if (_delayedFrames.isEmpty) return; // No delayed framed to be synced. + _saveCollectedData(); if (_screenRenderForCustomUiTrace.isNotEmpty) { @@ -229,18 +237,18 @@ class InstabugScreenRenderManager { /// Sync the capture screen render data of the custom UI trace without stopping the collector. @internal void endScreenRenderCollectorForCustomUiTrace() { - if (_screenRenderForCustomUiTrace.isNotEmpty) { - // Save the captured screen rendering data to be synced - _screenRenderForCustomUiTrace.slowFramesTotalDuration += - _slowFramesTotalDuration; - _screenRenderForCustomUiTrace.frozenFramesTotalDuration += - _frozenFramesTotalDuration; - _screenRenderForCustomUiTrace.frameData.addAll(_delayedFrames); - - // Sync the saved screen rendering data - reportScreenRending(_screenRenderForCustomUiTrace, UiTraceType.custom); - _screenRenderForCustomUiTrace.clear(); - } + if (_screenRenderForCustomUiTrace.isEmpty) return; + + // Save the captured screen rendering data to be synced + _screenRenderForCustomUiTrace.slowFramesTotalDuration += + _slowFramesTotalDuration; + _screenRenderForCustomUiTrace.frozenFramesTotalDuration += + _frozenFramesTotalDuration; + _screenRenderForCustomUiTrace.frameData.addAll(_delayedFrames); + + // Sync the saved screen rendering data + reportScreenRending(_screenRenderForCustomUiTrace, UiTraceType.custom); + _screenRenderForCustomUiTrace.clear(); } /// Reset the memory cashed data diff --git a/pigeons/apm.api.dart b/pigeons/apm.api.dart index d4a159631..255e35de4 100644 --- a/pigeons/apm.api.dart +++ b/pigeons/apm.api.dart @@ -46,4 +46,6 @@ abstract class ApmHostApi { @async double deviceRefreshRate(); + + void setScreenRenderEnabled(bool isEnabled); } diff --git a/scripts/pigeon.sh b/scripts/pigeon.sh old mode 100644 new mode 100755 diff --git a/test/utils/screen_render/instabug_screen_render_manager_test.dart b/test/utils/screen_render/instabug_screen_render_manager_test.dart index f77d8b234..73fea5561 100644 --- a/test/utils/screen_render/instabug_screen_render_manager_test.dart +++ b/test/utils/screen_render/instabug_screen_render_manager_test.dart @@ -1,13 +1,19 @@ +import 'dart:ui'; + +import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:instabug_flutter/instabug_flutter.dart'; +import 'package:instabug_flutter/src/generated/apm.api.g.dart'; import 'package:instabug_flutter/src/models/instabug_frame_data.dart'; import 'package:instabug_flutter/src/models/instabug_screen_render_data.dart'; import 'package:instabug_flutter/src/utils/screen_rendering/instabug_screen_render_manager.dart'; +import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; +import 'instabug_screen_render_manager_test.mocks.dart'; +// import 'instabug_screen_render_manager_test_manual_mocks.dart'; -import 'instabug_screen_render_manager_test_manual_mocks.dart'; - +@GenerateMocks([FrameTiming, ApmHostApi, WidgetsBinding]) void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -74,8 +80,8 @@ void main() { manager.startScreenRenderCollectorForTraceId(1); verify(mWidgetBinding.addTimingsCallback(any)).called( - 2, - ); // one form initForTesting() and one form startScreenRenderCollectorForTraceId() + 1, + ); }); test('should update the data for same trace type', () { @@ -199,7 +205,24 @@ void main() { expect(manager.screenRenderForAutoUiTrace.isEmpty, true); }); + test('should do nothing if there is no cached data', () { + manager.stopScreenRenderCollector(); + + verifyNever(mWidgetBinding.removeTimingsCallback(any)); + }); + test('should remove timing callback listener', () { + final frameTestdata = InstabugScreenRenderData( + traceId: 123, + frameData: [ + InstabugFrameData(10000, 200), + InstabugFrameData(20000, 1000), + ], + frozenFramesTotalDuration: 1000, + slowFramesTotalDuration: 200, + ); + + manager.setFrameData(frameTestdata); manager.stopScreenRenderCollector(); verify(mWidgetBinding.removeTimingsCallback(any)).called(1); diff --git a/test/utils/screen_render/instabug_screen_render_manager_test_manual_mocks.dart b/test/utils/screen_render/instabug_screen_render_manager_test_manual_mocks.dart deleted file mode 100644 index b35602da3..000000000 --- a/test/utils/screen_render/instabug_screen_render_manager_test_manual_mocks.dart +++ /dev/null @@ -1,880 +0,0 @@ -// Mocks generated by Mockito 5.2.0 from annotations -// in instabug_flutter/example/ios/.symlinks/plugins/instabug_flutter/test/utils/screen_render/instabug_screen_render_manager_test.dart. -// Do not manually edit this file. - -import 'dart:async' as _i9; -import 'dart:developer' as _i13; -import 'dart:ui' as _i4; - -import 'package:flutter/foundation.dart' as _i3; -import 'package:flutter/gestures.dart' as _i6; -import 'package:flutter/rendering.dart' as _i7; -import 'package:flutter/scheduler.dart' as _i11; -import 'package:flutter/services.dart' as _i5; -import 'package:flutter/src/widgets/binding.dart' as _i10; -import 'package:flutter/src/widgets/focus_manager.dart' as _i2; -import 'package:flutter/src/widgets/framework.dart' as _i12; -import 'package:instabug_flutter/src/generated/apm.api.g.dart' as _i8; -import 'package:mockito/mockito.dart' as _i1; - -// ignore_for_file: type=lint -// ignore_for_file: avoid_redundant_argument_values -// ignore_for_file: avoid_setters_without_getters -// ignore_for_file: comment_references -// ignore_for_file: implementation_imports -// ignore_for_file: invalid_use_of_visible_for_testing_member -// ignore_for_file: prefer_const_constructors -// ignore_for_file: unnecessary_parenthesis -// ignore_for_file: camel_case_types - -// This file has been manually changed due to a mockito inconsistency with flutter v 2.10.5 - -class _FakeDuration_0 extends _i1.Fake implements Duration {} - -class _FakeFocusManager_1 extends _i1.Fake implements _i2.FocusManager { - @override - String toString({_i3.DiagnosticLevel? minLevel = _i3.DiagnosticLevel.info}) => - super.toString(); -} - -class _FakeSingletonFlutterWindow_2 extends _i1.Fake - implements _i4.SingletonFlutterWindow {} - -class _FakePlatformDispatcher_3 extends _i1.Fake - implements _i4.PlatformDispatcher {} - -class _FakeHardwareKeyboard_4 extends _i1.Fake implements _i5.HardwareKeyboard { -} - -class _FakeKeyEventManager_5 extends _i1.Fake implements _i5.KeyEventManager {} - -class _FakeBinaryMessenger_6 extends _i1.Fake implements _i5.BinaryMessenger {} - -class _FakeChannelBuffers_7 extends _i1.Fake implements _i4.ChannelBuffers {} - -class _FakeRestorationManager_8 extends _i1.Fake - implements _i5.RestorationManager {} - -class _FakePointerRouter_9 extends _i1.Fake implements _i6.PointerRouter {} - -class _FakeGestureArenaManager_10 extends _i1.Fake - implements _i6.GestureArenaManager {} - -class _FakePointerSignalResolver_11 extends _i1.Fake - implements _i6.PointerSignalResolver {} - -class _FakeMouseTracker_12 extends _i1.Fake implements _i7.MouseTracker {} - -class _FakePipelineOwner_13 extends _i1.Fake implements _i7.PipelineOwner {} - -class _FakeRenderView_14 extends _i1.Fake implements _i7.RenderView { - @override - String toString({_i3.DiagnosticLevel? minLevel = _i3.DiagnosticLevel.info}) => - super.toString(); -} - -class _FakeAccessibilityFeatures_15 extends _i1.Fake - implements _i4.AccessibilityFeatures {} - -class _FakeViewConfiguration_16 extends _i1.Fake - implements _i7.ViewConfiguration {} - -class _FakeSemanticsUpdateBuilder_17 extends _i1.Fake - implements _i4.SemanticsUpdateBuilder {} - -/// A class which mocks [FrameTiming]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockFrameTiming extends _i1.Mock implements _i4.FrameTiming { - MockFrameTiming() { - _i1.throwOnMissingStub(this); - } - - @override - Duration get buildDuration => - (super.noSuchMethod(Invocation.getter(#buildDuration), - returnValue: _FakeDuration_0()) as Duration); - - @override - Duration get rasterDuration => - (super.noSuchMethod(Invocation.getter(#rasterDuration), - returnValue: _FakeDuration_0()) as Duration); - - @override - Duration get vsyncOverhead => - (super.noSuchMethod(Invocation.getter(#vsyncOverhead), - returnValue: _FakeDuration_0()) as Duration); - - @override - Duration get totalSpan => (super.noSuchMethod(Invocation.getter(#totalSpan), - returnValue: _FakeDuration_0()) as Duration); - - @override - int get layerCacheCount => - (super.noSuchMethod(Invocation.getter(#layerCacheCount), returnValue: 0) - as int); - - @override - int get layerCacheBytes => - (super.noSuchMethod(Invocation.getter(#layerCacheBytes), returnValue: 0) - as int); - - @override - double get layerCacheMegabytes => - (super.noSuchMethod(Invocation.getter(#layerCacheMegabytes), - returnValue: 0.0) as double); - - @override - int get pictureCacheCount => - (super.noSuchMethod(Invocation.getter(#pictureCacheCount), returnValue: 0) - as int); - - @override - int get pictureCacheBytes => - (super.noSuchMethod(Invocation.getter(#pictureCacheBytes), returnValue: 0) - as int); - - @override - double get pictureCacheMegabytes => - (super.noSuchMethod(Invocation.getter(#pictureCacheMegabytes), - returnValue: 0.0) as double); - - @override - int get frameNumber => - (super.noSuchMethod(Invocation.getter(#frameNumber), returnValue: 0) - as int); - - @override - int timestampInMicroseconds(_i4.FramePhase? phase) => - (super.noSuchMethod(Invocation.method(#timestampInMicroseconds, [phase]), - returnValue: 0) as int); -} - -/// A class which mocks [ApmHostApi]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockApmHostApi extends _i1.Mock implements _i8.ApmHostApi { - MockApmHostApi() { - _i1.throwOnMissingStub(this); - } - - @override - _i9.Future setEnabled(bool? arg_isEnabled) => - (super.noSuchMethod(Invocation.method(#setEnabled, [arg_isEnabled]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - - @override - _i9.Future isEnabled() => - (super.noSuchMethod(Invocation.method(#isEnabled, []), - returnValue: Future.value(false)) as _i9.Future); - - @override - _i9.Future setScreenLoadingEnabled(bool? arg_isEnabled) => - (super.noSuchMethod( - Invocation.method(#setScreenLoadingEnabled, [arg_isEnabled]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - - @override - _i9.Future isScreenLoadingEnabled() => - (super.noSuchMethod(Invocation.method(#isScreenLoadingEnabled, []), - returnValue: Future.value(false)) as _i9.Future); - - @override - _i9.Future setColdAppLaunchEnabled(bool? arg_isEnabled) => - (super.noSuchMethod( - Invocation.method(#setColdAppLaunchEnabled, [arg_isEnabled]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - - @override - _i9.Future setAutoUITraceEnabled(bool? arg_isEnabled) => (super - .noSuchMethod(Invocation.method(#setAutoUITraceEnabled, [arg_isEnabled]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - - @override - _i9.Future startExecutionTrace(String? arg_id, String? arg_name) => - (super.noSuchMethod( - Invocation.method(#startExecutionTrace, [arg_id, arg_name]), - returnValue: Future.value()) as _i9.Future); - - @override - _i9.Future startFlow(String? arg_name) => - (super.noSuchMethod(Invocation.method(#startFlow, [arg_name]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - - @override - _i9.Future setFlowAttribute( - String? arg_name, String? arg_key, String? arg_value) => - (super.noSuchMethod( - Invocation.method(#setFlowAttribute, [arg_name, arg_key, arg_value]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - - @override - _i9.Future endFlow(String? arg_name) => - (super.noSuchMethod(Invocation.method(#endFlow, [arg_name]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - - @override - _i9.Future setExecutionTraceAttribute( - String? arg_id, String? arg_key, String? arg_value) => - (super.noSuchMethod( - Invocation.method( - #setExecutionTraceAttribute, [arg_id, arg_key, arg_value]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - - @override - _i9.Future endExecutionTrace(String? arg_id) => - (super.noSuchMethod(Invocation.method(#endExecutionTrace, [arg_id]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - - @override - _i9.Future startUITrace(String? arg_name) => - (super.noSuchMethod(Invocation.method(#startUITrace, [arg_name]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - - @override - _i9.Future endUITrace() => - (super.noSuchMethod(Invocation.method(#endUITrace, []), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - - @override - _i9.Future endAppLaunch() => - (super.noSuchMethod(Invocation.method(#endAppLaunch, []), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - - @override - _i9.Future networkLogAndroid(Map? arg_data) => - (super.noSuchMethod(Invocation.method(#networkLogAndroid, [arg_data]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - - @override - _i9.Future startCpUiTrace( - String? arg_screenName, int? arg_microTimeStamp, int? arg_traceId) => - (super.noSuchMethod( - Invocation.method(#startCpUiTrace, - [arg_screenName, arg_microTimeStamp, arg_traceId]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - - @override - _i9.Future reportScreenLoadingCP(int? arg_startTimeStampMicro, - int? arg_durationMicro, int? arg_uiTraceId) => - (super.noSuchMethod( - Invocation.method(#reportScreenLoadingCP, - [arg_startTimeStampMicro, arg_durationMicro, arg_uiTraceId]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - - @override - _i9.Future endScreenLoadingCP( - int? arg_timeStampMicro, int? arg_uiTraceId) => - (super.noSuchMethod( - Invocation.method( - #endScreenLoadingCP, [arg_timeStampMicro, arg_uiTraceId]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - - @override - _i9.Future isEndScreenLoadingEnabled() => - (super.noSuchMethod(Invocation.method(#isEndScreenLoadingEnabled, []), - returnValue: Future.value(false)) as _i9.Future); - - @override - _i9.Future isScreenRenderEnabled() => - (super.noSuchMethod(Invocation.method(#isScreenRenderEnabled, []), - returnValue: Future.value(false)) as _i9.Future); - - @override - _i9.Future deviceRefreshRate() => - (super.noSuchMethod(Invocation.method(#deviceRefreshRate, []), - returnValue: Future.value(0.0)) as _i9.Future); -} - -/// A class which mocks [WidgetsBinding]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockWidgetsBinding extends _i1.Mock implements _i10.WidgetsBinding { - MockWidgetsBinding() { - _i1.throwOnMissingStub(this); - } - - @override - bool get debugBuildingDirtyElements => - (super.noSuchMethod(Invocation.getter(#debugBuildingDirtyElements), - returnValue: false) as bool); - - @override - set debugBuildingDirtyElements(bool? _debugBuildingDirtyElements) => - super.noSuchMethod( - Invocation.setter( - #debugBuildingDirtyElements, _debugBuildingDirtyElements), - returnValueForMissingStub: null); - - @override - _i2.FocusManager get focusManager => - (super.noSuchMethod(Invocation.getter(#focusManager), - returnValue: _FakeFocusManager_1()) as _i2.FocusManager); - - @override - bool get firstFrameRasterized => - (super.noSuchMethod(Invocation.getter(#firstFrameRasterized), - returnValue: false) as bool); - - @override - _i9.Future get waitUntilFirstFrameRasterized => - (super.noSuchMethod(Invocation.getter(#waitUntilFirstFrameRasterized), - returnValue: Future.value()) as _i9.Future); - - @override - bool get debugDidSendFirstFrameEvent => - (super.noSuchMethod(Invocation.getter(#debugDidSendFirstFrameEvent), - returnValue: false) as bool); - - @override - bool get framesEnabled => - (super.noSuchMethod(Invocation.getter(#framesEnabled), returnValue: false) - as bool); - - @override - bool get isRootWidgetAttached => - (super.noSuchMethod(Invocation.getter(#isRootWidgetAttached), - returnValue: false) as bool); - - @override - _i4.SingletonFlutterWindow get window => - (super.noSuchMethod(Invocation.getter(#window), - returnValue: _FakeSingletonFlutterWindow_2()) - as _i4.SingletonFlutterWindow); - - @override - _i4.PlatformDispatcher get platformDispatcher => - (super.noSuchMethod(Invocation.getter(#platformDispatcher), - returnValue: _FakePlatformDispatcher_3()) as _i4.PlatformDispatcher); - - @override - bool get locked => - (super.noSuchMethod(Invocation.getter(#locked), returnValue: false) - as bool); - - @override - _i5.HardwareKeyboard get keyboard => - (super.noSuchMethod(Invocation.getter(#keyboard), - returnValue: _FakeHardwareKeyboard_4()) as _i5.HardwareKeyboard); - - @override - _i5.KeyEventManager get keyEventManager => - (super.noSuchMethod(Invocation.getter(#keyEventManager), - returnValue: _FakeKeyEventManager_5()) as _i5.KeyEventManager); - - @override - _i5.BinaryMessenger get defaultBinaryMessenger => - (super.noSuchMethod(Invocation.getter(#defaultBinaryMessenger), - returnValue: _FakeBinaryMessenger_6()) as _i5.BinaryMessenger); - - @override - _i4.ChannelBuffers get channelBuffers => - (super.noSuchMethod(Invocation.getter(#channelBuffers), - returnValue: _FakeChannelBuffers_7()) as _i4.ChannelBuffers); - - @override - _i5.RestorationManager get restorationManager => - (super.noSuchMethod(Invocation.getter(#restorationManager), - returnValue: _FakeRestorationManager_8()) as _i5.RestorationManager); - - // Parameters {int? priority, _i11.SchedulerBinding? scheduler} have been - // changed from {int priority, _i11.SchedulerBinding scheduler}. - @override - _i11.SchedulingStrategy get schedulingStrategy => - (super.noSuchMethod(Invocation.getter(#schedulingStrategy), - returnValue: ({int? priority, _i11.SchedulerBinding? scheduler}) => - false) as _i11.SchedulingStrategy); - - @override - set schedulingStrategy(_i11.SchedulingStrategy? _schedulingStrategy) => super - .noSuchMethod(Invocation.setter(#schedulingStrategy, _schedulingStrategy), - returnValueForMissingStub: null); - - @override - int get transientCallbackCount => - (super.noSuchMethod(Invocation.getter(#transientCallbackCount), - returnValue: 0) as int); - - @override - _i9.Future get endOfFrame => - (super.noSuchMethod(Invocation.getter(#endOfFrame), - returnValue: Future.value()) as _i9.Future); - - @override - bool get hasScheduledFrame => - (super.noSuchMethod(Invocation.getter(#hasScheduledFrame), - returnValue: false) as bool); - - @override - _i11.SchedulerPhase get schedulerPhase => - (super.noSuchMethod(Invocation.getter(#schedulerPhase), - returnValue: _i11.SchedulerPhase.idle) as _i11.SchedulerPhase); - - @override - Duration get currentFrameTimeStamp => - (super.noSuchMethod(Invocation.getter(#currentFrameTimeStamp), - returnValue: _FakeDuration_0()) as Duration); - - @override - Duration get currentSystemFrameTimeStamp => - (super.noSuchMethod(Invocation.getter(#currentSystemFrameTimeStamp), - returnValue: _FakeDuration_0()) as Duration); - - @override - _i6.PointerRouter get pointerRouter => - (super.noSuchMethod(Invocation.getter(#pointerRouter), - returnValue: _FakePointerRouter_9()) as _i6.PointerRouter); - - @override - _i6.GestureArenaManager get gestureArena => (super.noSuchMethod( - Invocation.getter(#gestureArena), - returnValue: _FakeGestureArenaManager_10()) as _i6.GestureArenaManager); - - @override - _i6.PointerSignalResolver get pointerSignalResolver => - (super.noSuchMethod(Invocation.getter(#pointerSignalResolver), - returnValue: _FakePointerSignalResolver_11()) - as _i6.PointerSignalResolver); - - @override - bool get resamplingEnabled => - (super.noSuchMethod(Invocation.getter(#resamplingEnabled), - returnValue: false) as bool); - - @override - set resamplingEnabled(bool? _resamplingEnabled) => super.noSuchMethod( - Invocation.setter(#resamplingEnabled, _resamplingEnabled), - returnValueForMissingStub: null); - - @override - Duration get samplingOffset => - (super.noSuchMethod(Invocation.getter(#samplingOffset), - returnValue: _FakeDuration_0()) as Duration); - - @override - set samplingOffset(Duration? _samplingOffset) => - super.noSuchMethod(Invocation.setter(#samplingOffset, _samplingOffset), - returnValueForMissingStub: null); - - @override - _i7.MouseTracker get mouseTracker => - (super.noSuchMethod(Invocation.getter(#mouseTracker), - returnValue: _FakeMouseTracker_12()) as _i7.MouseTracker); - - @override - _i7.PipelineOwner get pipelineOwner => - (super.noSuchMethod(Invocation.getter(#pipelineOwner), - returnValue: _FakePipelineOwner_13()) as _i7.PipelineOwner); - - @override - _i7.RenderView get renderView => - (super.noSuchMethod(Invocation.getter(#renderView), - returnValue: _FakeRenderView_14()) as _i7.RenderView); - - @override - set renderView(_i7.RenderView? value) => - super.noSuchMethod(Invocation.setter(#renderView, value), - returnValueForMissingStub: null); - - @override - bool get sendFramesToEngine => - (super.noSuchMethod(Invocation.getter(#sendFramesToEngine), - returnValue: false) as bool); - - @override - _i4.AccessibilityFeatures get accessibilityFeatures => - (super.noSuchMethod(Invocation.getter(#accessibilityFeatures), - returnValue: _FakeAccessibilityFeatures_15()) - as _i4.AccessibilityFeatures); - - @override - bool get disableAnimations => - (super.noSuchMethod(Invocation.getter(#disableAnimations), - returnValue: false) as bool); - - @override - void initInstances() => - super.noSuchMethod(Invocation.method(#initInstances, []), - returnValueForMissingStub: null); - - @override - void initServiceExtensions() => - super.noSuchMethod(Invocation.method(#initServiceExtensions, []), - returnValueForMissingStub: null); - - @override - void addObserver(_i10.WidgetsBindingObserver? observer) => - super.noSuchMethod(Invocation.method(#addObserver, [observer]), - returnValueForMissingStub: null); - - @override - bool removeObserver(_i10.WidgetsBindingObserver? observer) => - (super.noSuchMethod(Invocation.method(#removeObserver, [observer]), - returnValue: false) as bool); - - @override - void handleMetricsChanged() => - super.noSuchMethod(Invocation.method(#handleMetricsChanged, []), - returnValueForMissingStub: null); - - @override - void handleTextScaleFactorChanged() => - super.noSuchMethod(Invocation.method(#handleTextScaleFactorChanged, []), - returnValueForMissingStub: null); - - @override - void handlePlatformBrightnessChanged() => super.noSuchMethod( - Invocation.method(#handlePlatformBrightnessChanged, []), - returnValueForMissingStub: null); - - @override - void handleAccessibilityFeaturesChanged() => super.noSuchMethod( - Invocation.method(#handleAccessibilityFeaturesChanged, []), - returnValueForMissingStub: null); - - @override - void handleLocaleChanged() => - super.noSuchMethod(Invocation.method(#handleLocaleChanged, []), - returnValueForMissingStub: null); - - @override - void dispatchLocalesChanged(List<_i4.Locale>? locales) => - super.noSuchMethod(Invocation.method(#dispatchLocalesChanged, [locales]), - returnValueForMissingStub: null); - - @override - void dispatchAccessibilityFeaturesChanged() => super.noSuchMethod( - Invocation.method(#dispatchAccessibilityFeaturesChanged, []), - returnValueForMissingStub: null); - - @override - _i9.Future handlePopRoute() => - (super.noSuchMethod(Invocation.method(#handlePopRoute, []), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - - @override - _i9.Future handlePushRoute(String? route) => - (super.noSuchMethod(Invocation.method(#handlePushRoute, [route]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - - @override - void handleAppLifecycleStateChanged(_i4.AppLifecycleState? state) => super - .noSuchMethod(Invocation.method(#handleAppLifecycleStateChanged, [state]), - returnValueForMissingStub: null); - - @override - void handleMemoryPressure() => - super.noSuchMethod(Invocation.method(#handleMemoryPressure, []), - returnValueForMissingStub: null); - - @override - void drawFrame() => super.noSuchMethod(Invocation.method(#drawFrame, []), - returnValueForMissingStub: null); - - @override - void scheduleAttachRootWidget(_i12.Widget? rootWidget) => super.noSuchMethod( - Invocation.method(#scheduleAttachRootWidget, [rootWidget]), - returnValueForMissingStub: null); - - @override - void attachRootWidget(_i12.Widget? rootWidget) => - super.noSuchMethod(Invocation.method(#attachRootWidget, [rootWidget]), - returnValueForMissingStub: null); - - @override - _i9.Future performReassemble() => - (super.noSuchMethod(Invocation.method(#performReassemble, []), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - - @override - _i4.Locale? computePlatformResolvedLocale( - List<_i4.Locale>? supportedLocales) => - (super.noSuchMethod(Invocation.method( - #computePlatformResolvedLocale, [supportedLocales])) as _i4.Locale?); - - @override - _i9.Future lockEvents(_i9.Future Function()? callback) => - (super.noSuchMethod(Invocation.method(#lockEvents, [callback]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - - @override - void unlocked() => super.noSuchMethod(Invocation.method(#unlocked, []), - returnValueForMissingStub: null); - - @override - _i9.Future reassembleApplication() => - (super.noSuchMethod(Invocation.method(#reassembleApplication, []), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - - @override - void registerSignalServiceExtension( - {String? name, _i3.AsyncCallback? callback}) => - super.noSuchMethod( - Invocation.method(#registerSignalServiceExtension, [], - {#name: name, #callback: callback}), - returnValueForMissingStub: null); - - @override - void registerBoolServiceExtension( - {String? name, - _i3.AsyncValueGetter? getter, - _i3.AsyncValueSetter? setter}) => - super.noSuchMethod( - Invocation.method(#registerBoolServiceExtension, [], - {#name: name, #getter: getter, #setter: setter}), - returnValueForMissingStub: null); - - @override - void registerNumericServiceExtension( - {String? name, - _i3.AsyncValueGetter? getter, - _i3.AsyncValueSetter? setter}) => - super.noSuchMethod( - Invocation.method(#registerNumericServiceExtension, [], - {#name: name, #getter: getter, #setter: setter}), - returnValueForMissingStub: null); - - @override - void postEvent(String? eventKind, Map? eventData) => - super.noSuchMethod(Invocation.method(#postEvent, [eventKind, eventData]), - returnValueForMissingStub: null); - - @override - void registerStringServiceExtension( - {String? name, - _i3.AsyncValueGetter? getter, - _i3.AsyncValueSetter? setter}) => - super.noSuchMethod( - Invocation.method(#registerStringServiceExtension, [], - {#name: name, #getter: getter, #setter: setter}), - returnValueForMissingStub: null); - - @override - void registerServiceExtension( - {String? name, _i3.ServiceExtensionCallback? callback}) => - super.noSuchMethod( - Invocation.method(#registerServiceExtension, [], - {#name: name, #callback: callback}), - returnValueForMissingStub: null); - - @override - _i5.BinaryMessenger createBinaryMessenger() => - (super.noSuchMethod(Invocation.method(#createBinaryMessenger, []), - returnValue: _FakeBinaryMessenger_6()) as _i5.BinaryMessenger); - - @override - _i9.Future handleSystemMessage(Object? systemMessage) => (super - .noSuchMethod(Invocation.method(#handleSystemMessage, [systemMessage]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i9.Future); - - @override - void initLicenses() => - super.noSuchMethod(Invocation.method(#initLicenses, []), - returnValueForMissingStub: null); - - @override - void evict(String? asset) => - super.noSuchMethod(Invocation.method(#evict, [asset]), - returnValueForMissingStub: null); - - @override - void readInitialLifecycleStateFromNativeWindow() => super.noSuchMethod( - Invocation.method(#readInitialLifecycleStateFromNativeWindow, []), - returnValueForMissingStub: null); - - @override - _i5.RestorationManager createRestorationManager() => - (super.noSuchMethod(Invocation.method(#createRestorationManager, []), - returnValue: _FakeRestorationManager_8()) as _i5.RestorationManager); - - @override - void setSystemUiChangeCallback(_i5.SystemUiChangeCallback? callback) => super - .noSuchMethod(Invocation.method(#setSystemUiChangeCallback, [callback]), - returnValueForMissingStub: null); - - @override - void addTimingsCallback(_i4.TimingsCallback? callback) => - super.noSuchMethod(Invocation.method(#addTimingsCallback, [callback]), - returnValueForMissingStub: null); - - @override - void removeTimingsCallback(_i4.TimingsCallback? callback) => - super.noSuchMethod(Invocation.method(#removeTimingsCallback, [callback]), - returnValueForMissingStub: null); - - @override - _i9.Future scheduleTask( - _i11.TaskCallback? task, _i11.Priority? priority, - {String? debugLabel, _i13.Flow? flow}) => - (super.noSuchMethod( - Invocation.method(#scheduleTask, [task, priority], - {#debugLabel: debugLabel, #flow: flow}), - returnValue: Future.value(null)) as _i9.Future); - - @override - bool handleEventLoopCallback() => - (super.noSuchMethod(Invocation.method(#handleEventLoopCallback, []), - returnValue: false) as bool); - - @override - int scheduleFrameCallback(_i11.FrameCallback? callback, - {bool? rescheduling = false}) => - (super.noSuchMethod( - Invocation.method(#scheduleFrameCallback, [callback], - {#rescheduling: rescheduling}), - returnValue: 0) as int); - - @override - void cancelFrameCallbackWithId(int? id) => - super.noSuchMethod(Invocation.method(#cancelFrameCallbackWithId, [id]), - returnValueForMissingStub: null); - - @override - bool debugAssertNoTransientCallbacks(String? reason) => (super.noSuchMethod( - Invocation.method(#debugAssertNoTransientCallbacks, [reason]), - returnValue: false) as bool); - - @override - void addPersistentFrameCallback(_i11.FrameCallback? callback) => super - .noSuchMethod(Invocation.method(#addPersistentFrameCallback, [callback]), - returnValueForMissingStub: null); - - @override - void addPostFrameCallback(_i11.FrameCallback? callback) => - super.noSuchMethod(Invocation.method(#addPostFrameCallback, [callback]), - returnValueForMissingStub: null); - - @override - void ensureFrameCallbacksRegistered() => - super.noSuchMethod(Invocation.method(#ensureFrameCallbacksRegistered, []), - returnValueForMissingStub: null); - - @override - void ensureVisualUpdate() => - super.noSuchMethod(Invocation.method(#ensureVisualUpdate, []), - returnValueForMissingStub: null); - - @override - void scheduleFrame() => - super.noSuchMethod(Invocation.method(#scheduleFrame, []), - returnValueForMissingStub: null); - - @override - void scheduleForcedFrame() => - super.noSuchMethod(Invocation.method(#scheduleForcedFrame, []), - returnValueForMissingStub: null); - - @override - void scheduleWarmUpFrame() => - super.noSuchMethod(Invocation.method(#scheduleWarmUpFrame, []), - returnValueForMissingStub: null); - - @override - void resetEpoch() => super.noSuchMethod(Invocation.method(#resetEpoch, []), - returnValueForMissingStub: null); - - @override - void handleBeginFrame(Duration? rawTimeStamp) => - super.noSuchMethod(Invocation.method(#handleBeginFrame, [rawTimeStamp]), - returnValueForMissingStub: null); - - @override - void handleDrawFrame() => - super.noSuchMethod(Invocation.method(#handleDrawFrame, []), - returnValueForMissingStub: null); - - @override - void cancelPointer(int? pointer) => - super.noSuchMethod(Invocation.method(#cancelPointer, [pointer]), - returnValueForMissingStub: null); - - @override - void handlePointerEvent(_i7.PointerEvent? event) => - super.noSuchMethod(Invocation.method(#handlePointerEvent, [event]), - returnValueForMissingStub: null); - - @override - void hitTest(_i7.HitTestResult? result, _i4.Offset? position) => - super.noSuchMethod(Invocation.method(#hitTest, [result, position]), - returnValueForMissingStub: null); - - @override - void dispatchEvent( - _i7.PointerEvent? event, _i7.HitTestResult? hitTestResult) => - super.noSuchMethod( - Invocation.method(#dispatchEvent, [event, hitTestResult]), - returnValueForMissingStub: null); - - @override - void handleEvent(_i7.PointerEvent? event, _i7.HitTestEntry? entry) => - super.noSuchMethod(Invocation.method(#handleEvent, [event, entry]), - returnValueForMissingStub: null); - - @override - void resetGestureBinding() => - super.noSuchMethod(Invocation.method(#resetGestureBinding, []), - returnValueForMissingStub: null); - - @override - void initRenderView() => - super.noSuchMethod(Invocation.method(#initRenderView, []), - returnValueForMissingStub: null); - - @override - _i7.ViewConfiguration createViewConfiguration() => - (super.noSuchMethod(Invocation.method(#createViewConfiguration, []), - returnValue: _FakeViewConfiguration_16()) as _i7.ViewConfiguration); - - @override - void initMouseTracker([_i7.MouseTracker? tracker]) => - super.noSuchMethod(Invocation.method(#initMouseTracker, [tracker]), - returnValueForMissingStub: null); - - @override - void setSemanticsEnabled(bool? enabled) => - super.noSuchMethod(Invocation.method(#setSemanticsEnabled, [enabled]), - returnValueForMissingStub: null); - - @override - void deferFirstFrame() => - super.noSuchMethod(Invocation.method(#deferFirstFrame, []), - returnValueForMissingStub: null); - - @override - void allowFirstFrame() => - super.noSuchMethod(Invocation.method(#allowFirstFrame, []), - returnValueForMissingStub: null); - - @override - void resetFirstFrameSent() => - super.noSuchMethod(Invocation.method(#resetFirstFrameSent, []), - returnValueForMissingStub: null); - - @override - _i4.SemanticsUpdateBuilder createSemanticsUpdateBuilder() => - (super.noSuchMethod(Invocation.method(#createSemanticsUpdateBuilder, []), - returnValue: _FakeSemanticsUpdateBuilder_17()) - as _i4.SemanticsUpdateBuilder); -} From 7a2ca1112031571e51737f5de194856810b56de0 Mon Sep 17 00:00:00 2001 From: Andrew Amin Date: Mon, 30 Jun 2025 18:02:31 +0300 Subject: [PATCH 12/15] chore: fix some capture logic, add unit test cases. --- android/build.gradle | 4 +- example/ios/Podfile.lock | 2 +- example/ios/Runner.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- example/lib/main.dart | 4 +- example/lib/src/components/apm_switch.dart | 26 +- .../src/components/screen_render_switch.dart | 35 +++ example/lib/src/screens/apm_page.dart | 2 +- .../lib/src/screens/screen_render_page.dart | 7 + example/pubspec.lock | 189 +++++++------ ios/Classes/Modules/ApmApi.m | 5 +- lib/src/modules/apm.dart | 10 +- .../utils/instabug_navigator_observer.dart | 3 + .../instabug_screen_render_manager.dart | 263 ++++++++++-------- .../instabug_widget_binding_observer.dart | 39 +-- test/apm_test.dart | 115 ++++++++ 16 files changed, 478 insertions(+), 230 deletions(-) create mode 100644 example/lib/src/components/screen_render_switch.dart diff --git a/android/build.gradle b/android/build.gradle index 0a1bab7ea..8767af259 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,5 +1,3 @@ -package android - group 'com.instabug.flutter' version '14.3.0' @@ -54,7 +52,7 @@ android { } dependencies { - api 'com.instabug.library:instabug:14.3.0' + api 'com.instabug.library:instabug:15.0.0.6897042-SNAPSHOT' testImplementation 'junit:junit:4.13.2' testImplementation "org.mockito:mockito-inline:3.12.1" testImplementation "io.mockk:mockk:1.13.13" diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 7fcc59514..8dad08077 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -25,7 +25,7 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/instabug_flutter/ios" SPEC CHECKSUMS: - Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 Instabug: a2b8c384cd4af7a01ab43b2ce2957a880f8862d7 instabug_flutter: 6ee721f30066123a769da64b687eded6eb4ff125 OCMock: 5ea90566be239f179ba766fd9fbae5885040b992 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 2d4497cb9..d32f983fc 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -271,7 +271,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index b7206827b..3264af370 100644 --- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ { @override Widget build(BuildContext context) { - return Column( - children: [ - SwitchListTile.adaptive( - title: const Text('APM Enabled'), - value: isEnabled, - onChanged: (value) => onAPMChanged(context, value), - ), - ], - ); + return FutureBuilder( + future: APM.isEnabled(), + builder: (context, snapshot) { + if (snapshot.hasData) { + isEnabled = snapshot.data ?? false; + return SwitchListTile.adaptive( + title: const Text('APM Enabled'), + value: isEnabled, + onChanged: (value) => onAPMChanged(context, value), + ); + } + return const SizedBox.shrink(); + }); } void onAPMChanged(BuildContext context, bool value) { diff --git a/example/lib/src/components/screen_render_switch.dart b/example/lib/src/components/screen_render_switch.dart new file mode 100644 index 000000000..d5c6d9e18 --- /dev/null +++ b/example/lib/src/components/screen_render_switch.dart @@ -0,0 +1,35 @@ +part of '../../main.dart'; + +class ScreenRenderSwitch extends StatefulWidget { + const ScreenRenderSwitch({Key? key}) : super(key: key); + + @override + State createState() => _ScreenRenderSwitchState(); +} + +class _ScreenRenderSwitchState extends State { + bool isEnabled = false; + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: APM.isScreenRenderEnabled(), + builder: (context, snapshot) { + if (snapshot.hasData) { + isEnabled = snapshot.data ?? false; + return SwitchListTile.adaptive( + title: const Text('Screen Render Enabled'), + value: isEnabled, + onChanged: (value) => onScreenRenderChanged(context, value), + ); + } + return const SizedBox.shrink(); + }); + } + + void onScreenRenderChanged(BuildContext context, bool value) { + APM.setScreenRenderEnabled(value); + showSnackBar(context, "Screen Render is ${value ? "enabled" : "disabled"}"); + setState(() => isEnabled = value); + } +} diff --git a/example/lib/src/screens/apm_page.dart b/example/lib/src/screens/apm_page.dart index 0dcf90a2c..b5de7a228 100644 --- a/example/lib/src/screens/apm_page.dart +++ b/example/lib/src/screens/apm_page.dart @@ -53,7 +53,7 @@ class _ApmPageState extends State { SizedBox.fromSize( size: const Size.fromHeight(12), ), - ScreenRender(), + const ScreenRender(), ], ); } diff --git a/example/lib/src/screens/screen_render_page.dart b/example/lib/src/screens/screen_render_page.dart index a6c97cb23..872435f99 100644 --- a/example/lib/src/screens/screen_render_page.dart +++ b/example/lib/src/screens/screen_render_page.dart @@ -11,9 +11,16 @@ class ScreenRenderPage extends StatefulWidget { class _ScreenRenderPageState extends State { final durationController = TextEditingController(); + @override + void dispose() { + durationController.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { return Page(title: 'Screen Render', children: [ + const ScreenRenderSwitch(), SizedBox.fromSize(size: const Size.fromHeight(16.0)), const AnimatedBox(), SizedBox.fromSize( diff --git a/example/pubspec.lock b/example/pubspec.lock index db618bb81..74b4b6b46 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -1,76 +1,62 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: - archive: - dependency: transitive - description: - name: archive - url: "https://pub.dartlang.org" - source: hosted - version: "3.1.6" async: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" + url: "https://pub.dev" source: hosted - version: "2.8.2" + version: "2.13.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.2" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.4.0" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.2" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" + url: "https://pub.dev" source: hosted - version: "1.15.0" - crypto: - dependency: transitive - description: - name: crypto - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.1" + version: "1.19.1" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dartlang.org" + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" + url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.3.3" file: dependency: transitive description: name: file - url: "https://pub.dartlang.org" + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://pub.dev" source: hosted - version: "6.1.2" + version: "7.0.1" flutter: dependency: "direct main" description: flutter @@ -85,7 +71,8 @@ packages: dependency: "direct dev" description: name: flutter_lints - url: "https://pub.dartlang.org" + sha256: b543301ad291598523947dc534aaddc5aaad597b709d2426d3a0e0d44c5cb493 + url: "https://pub.dev" source: hosted version: "1.0.4" flutter_test: @@ -102,16 +89,18 @@ packages: dependency: "direct main" description: name: http - url: "https://pub.dartlang.org" + sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" + url: "https://pub.dev" source: hosted - version: "0.13.5" + version: "0.13.6" http_parser: dependency: transitive description: name: http_parser - url: "https://pub.dartlang.org" + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + url: "https://pub.dev" source: hosted - version: "4.0.2" + version: "4.1.2" instabug_flutter: dependency: "direct main" description: @@ -123,139 +112,183 @@ packages: dependency: "direct main" description: name: instabug_http_client - url: "https://pub.dartlang.org" + sha256: "97a6ab88491eff87e42437564b528d6986a65eb3f3262f73373009f949cb4560" + url: "https://pub.dev" source: hosted version: "2.5.1" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" + url: "https://pub.dev" + source: hosted + version: "10.0.9" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + url: "https://pub.dev" + source: hosted + version: "3.0.9" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" lints: dependency: transitive description: name: lints - url: "https://pub.dartlang.org" + sha256: a2c3d198cb5ea2e179926622d433331d8b58374ab8f29cdda6e863bd62fd369c + url: "https://pub.dev" source: hosted version: "1.0.1" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + url: "https://pub.dev" source: hosted - version: "0.12.11" + version: "0.12.17" material_color_utilities: dependency: transitive description: name: material_color_utilities - url: "https://pub.dartlang.org" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + url: "https://pub.dev" source: hosted - version: "0.1.3" + version: "0.11.1" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c + url: "https://pub.dev" source: hosted - version: "1.7.0" + version: "1.16.0" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" + url: "https://pub.dev" source: hosted - version: "1.8.0" + version: "1.9.1" platform: dependency: transitive description: name: platform - url: "https://pub.dartlang.org" + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" + url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.6" process: dependency: transitive description: name: process - url: "https://pub.dartlang.org" + sha256: "107d8be718f120bbba9dcd1e95e3bd325b1b4a4f07db64154635ba03f2567a0d" + url: "https://pub.dev" source: hosted - version: "4.2.4" + version: "5.0.3" sky_engine: dependency: transitive description: flutter source: sdk - version: "0.0.99" + version: "0.0.0" source_span: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" + url: "https://pub.dev" source: hosted - version: "1.8.1" + version: "1.10.1" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" + url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.12.1" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.4" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.4.1" sync_http: dependency: transitive description: name: sync_http - url: "https://pub.dartlang.org" + sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961" + url: "https://pub.dev" source: hosted - version: "0.3.0" + version: "0.3.1" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" + url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.2.2" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd + url: "https://pub.dev" source: hosted - version: "0.4.8" + version: "0.7.4" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dartlang.org" + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.0" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.4" vm_service: dependency: transitive description: name: vm_service - url: "https://pub.dartlang.org" + sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02 + url: "https://pub.dev" source: hosted - version: "7.5.0" + version: "15.0.0" webdriver: dependency: transitive description: name: webdriver - url: "https://pub.dartlang.org" + sha256: "2f3a14ca026957870cfd9c635b83507e0e51d8091568e90129fbf805aba7cade" + url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "3.1.0" sdks: - dart: ">=2.14.0 <3.0.0" + dart: ">=3.7.0-0 <4.0.0" + flutter: ">=3.18.0-18.0.pre.54" diff --git a/ios/Classes/Modules/ApmApi.m b/ios/Classes/Modules/ApmApi.m index 385936702..f82219770 100644 --- a/ios/Classes/Modules/ApmApi.m +++ b/ios/Classes/Modules/ApmApi.m @@ -215,7 +215,7 @@ - (void)deviceRefreshRateWithCompletion:(void (^)(NSNumber * _Nullable, FlutterE displayLink.paused = YES; [displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; - NSInteger preferredFPS = displayLink.preferredFramesPerSecond; + double preferredFPS = displayLink.preferredFramesPerSecond; [displayLink invalidate]; @@ -237,7 +237,8 @@ - (void)deviceRefreshRateWithCompletion:(void (^)(NSNumber * _Nullable, FlutterE } if (windowScene) { - completion(@(windowScene.screen.maximumFramesPerSecond) , nil); + double preferredFPS = windowScene.screen.maximumFramesPerSecond; + completion(@(preferredFPS) , nil); return; } } diff --git a/lib/src/modules/apm.dart b/lib/src/modules/apm.dart index 4077d65f2..7d4ef9804 100644 --- a/lib/src/modules/apm.dart +++ b/lib/src/modules/apm.dart @@ -2,7 +2,7 @@ import 'dart:async'; -import 'package:flutter/widgets.dart' show WidgetBuilder; +import 'package:flutter/widgets.dart' show WidgetBuilder, WidgetsBinding; import 'package:instabug_flutter/src/generated/apm.api.g.dart'; import 'package:instabug_flutter/src/models/network_data.dart'; import 'package:instabug_flutter/src/models/trace.dart'; @@ -392,6 +392,12 @@ class APM { /// Returns: /// A Future is being returned. static Future setScreenRenderEnabled(bool isEnabled) { - return _host.setScreenRenderEnabled(isEnabled); + return _host.setScreenRenderEnabled(isEnabled).then((_) { + if (isEnabled) { + InstabugScreenRenderManager.I.init(WidgetsBinding.instance); + } else { + InstabugScreenRenderManager.I.remove(); + } + }); } } diff --git a/lib/src/utils/instabug_navigator_observer.dart b/lib/src/utils/instabug_navigator_observer.dart index 80b4cb13d..63dc31dad 100644 --- a/lib/src/utils/instabug_navigator_observer.dart +++ b/lib/src/utils/instabug_navigator_observer.dart @@ -61,6 +61,9 @@ class InstabugNavigatorObserver extends NavigatorObserver { InstabugScreenRenderManager.I .startScreenRenderCollectorForTraceId(uiTraceId); } + // if(isScreenRender && InstabugScreenRenderManager.I.screenRenderEnabled){ + // InstabugScreenRenderManager.I.remove(); + // } } @override diff --git a/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart b/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart index 50e16fbc5..526c2ddc3 100644 --- a/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart +++ b/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:developer'; import 'dart:ui'; @@ -5,6 +6,7 @@ import 'package:flutter/widgets.dart'; import 'package:instabug_flutter/src/models/instabug_frame_data.dart'; import 'package:instabug_flutter/src/models/instabug_screen_render_data.dart'; import 'package:instabug_flutter/src/modules/apm.dart'; +import 'package:instabug_flutter/src/utils/instabug_logger.dart'; import 'package:instabug_flutter/src/utils/screen_rendering/instabug_widget_binding_observer.dart'; import 'package:meta/meta.dart'; @@ -57,21 +59,21 @@ class InstabugScreenRenderManager { /// setup function for [InstabugScreenRenderManager] @internal Future init(WidgetsBinding? widgetBinding) async { - // passing WidgetsBinding? (nullable) for flutter versions prior than 3.x - if (!_isTimingsListenerAttached && widgetBinding != null) { - _widgetsBinding = widgetBinding; - _addWidgetBindingObserver(); - await _initStaticValues(); - _initFrameTimings(); - screenRenderEnabled = true; + try { + // passing WidgetsBinding? (nullable) for flutter versions prior than 3.x + if (!_isTimingsListenerAttached && widgetBinding != null) { + _widgetsBinding = widgetBinding; + _addWidgetBindingObserver(); + await _initStaticValues(); + _initFrameTimings(); + screenRenderEnabled = true; + } + log("$tag: init", name: 'andrew'); + } catch (error, stackTrace) { + _logExceptionErrorAndStackTrace(error, stackTrace); } } - /// nodoc - - void _addWidgetBindingObserver() => - _widgetsBinding.addObserver(InstabugWidgetsBindingObserver.instance); - /// analyze frame data in order to detect slow/frozen frame. @visibleForTesting void analyzeFrameTiming(FrameTiming frameTiming) { @@ -115,6 +117,128 @@ class InstabugScreenRenderManager { } } + /// Start collecting screen render data for the running [UITrace]. + /// It ends the running collector when starting a new one of the same type [UiTraceType]. + @internal + void startScreenRenderCollectorForTraceId( + int traceId, [ + UiTraceType type = UiTraceType.auto, + ]) { + try { + // Return if frameTimingListener not attached + if (!screenRenderEnabled || !_isTimingsListenerAttached) { + log("$tag: start returned", name: 'andrew'); + + return; + } + + //Save the memory cached data to be sent to native side + if (_delayedFrames.isNotEmpty) { + _saveCollectedData(); + _resetCachedFrameData(); + } + + //Sync the captured screen render data of the Custom UI trace when starting new one + if (type == UiTraceType.custom) { + if (_screenRenderForCustomUiTrace.isNotEmpty) { + reportScreenRending( + _screenRenderForCustomUiTrace, + UiTraceType.custom, + ); + _screenRenderForCustomUiTrace.clear(); + } + _screenRenderForCustomUiTrace.traceId = traceId; + } + + //Sync the captured screen render data of the Auto UI trace when starting new one + if (type == UiTraceType.auto) { + if (_screenRenderForAutoUiTrace.isNotEmpty) { + reportScreenRending(_screenRenderForAutoUiTrace); + _screenRenderForAutoUiTrace.clear(); + } + _screenRenderForAutoUiTrace.traceId = traceId; + } + log("$tag: start normally", name: 'andrew'); + } catch (error, stackTrace) { + _logExceptionErrorAndStackTrace(error, stackTrace); + } + } + + /// Stop screen render collector and sync the captured data. + @internal + void stopScreenRenderCollector() { + try { + if (_delayedFrames.isEmpty) { + return; + } // No delayed framed to be synced. + + _saveCollectedData(); + + if (_screenRenderForCustomUiTrace.isNotEmpty) { + reportScreenRending(_screenRenderForCustomUiTrace, UiTraceType.custom); + } + if (_screenRenderForAutoUiTrace.isNotEmpty) { + reportScreenRending(_screenRenderForAutoUiTrace); + } + + _removeFrameTimings(); + + _resetCachedFrameData(); + log("$tag: stop", name: 'andrew'); + } catch (error, stackTrace) { + _logExceptionErrorAndStackTrace(error, stackTrace); + } + } + + /// Sync the capture screen render data of the custom UI trace without stopping the collector. + @internal + void endScreenRenderCollectorForCustomUiTrace() { + try { + if (_screenRenderForCustomUiTrace.isEmpty) { + return; + } + + // Save the captured screen rendering data to be synced + _screenRenderForCustomUiTrace.slowFramesTotalDuration += + _slowFramesTotalDuration; + _screenRenderForCustomUiTrace.frozenFramesTotalDuration += + _frozenFramesTotalDuration; + _screenRenderForCustomUiTrace.frameData.addAll(_delayedFrames); + + // Sync the saved screen rendering data + reportScreenRending(_screenRenderForCustomUiTrace, UiTraceType.custom); + _screenRenderForCustomUiTrace.clear(); + log("$tag: endCustom", name: 'andrew'); + } catch (error, stackTrace) { + _logExceptionErrorAndStackTrace(error, stackTrace); + } + } + + @visibleForTesting + Future reportScreenRending( + InstabugScreenRenderData screenRenderData, [ + UiTraceType type = UiTraceType.auto, + ]) async { + if (type == UiTraceType.auto) { + _reportScreenRenderForAutoUiTrace(screenRenderData); + } else { + _reportScreenRenderForCustomUiTrace(screenRenderData); + } + log( + "$tag: Report ${type == UiTraceType.auto ? 'auto' : 'custom'} Data: $screenRenderData", + name: 'andrew', + ); + } + + void remove() { + _resetCachedFrameData(); + _removeFrameTimings(); + screenRenderEnabled = false; + log("$tag: remove", name: 'andrew'); + } + + /// --------------------------- private methods --------------------- + bool get _isSlow => _isUiSlow || _isRasterSlow; bool get _isUiDelayed => _isUiSlow || _isUiFrozen; @@ -142,11 +266,12 @@ class InstabugScreenRenderManager { 1 / displayRefreshRate * 1000; /// Get device refresh rate from native side. - Future get _getDeviceRefreshRateFromNative { - final rr = APM.getDeviceRefreshRate(); - log("refreshRateFromNative: $rr", name: "Andrew"); - return rr; - } + Future get _getDeviceRefreshRateFromNative => + APM.getDeviceRefreshRate(); + + /// add new [WidgetsBindingObserver] to track app lifecycle. + void _addWidgetBindingObserver() => + _widgetsBinding.addObserver(InstabugWidgetsBindingObserver.instance); /// Initialize the static variables Future _initStaticValues() async { @@ -178,79 +303,6 @@ class InstabugScreenRenderManager { _isTimingsListenerAttached = false; } - /// Start collecting screen render data for the running [UITrace]. - /// It ends the running collector when starting a new one of the same type [UiTraceType]. - @internal - void startScreenRenderCollectorForTraceId( - int traceId, [ - UiTraceType type = UiTraceType.auto, - ]) { - // Attach frameTimingListener if not attached - if (!_isTimingsListenerAttached) { - _initFrameTimings(); - } - - //Save the memory cached data to be sent to native side - if (_delayedFrames.isNotEmpty) { - _saveCollectedData(); - _resetCachedFrameData(); - } - - //Sync the captured screen render data of the Custom UI trace when starting new one - if (type == UiTraceType.custom) { - if (_screenRenderForCustomUiTrace.isNotEmpty) { - reportScreenRending(_screenRenderForCustomUiTrace, UiTraceType.custom); - _screenRenderForCustomUiTrace.clear(); - } - _screenRenderForCustomUiTrace.traceId = traceId; - } - - //Sync the captured screen render data of the Auto UI trace when starting new one - if (type == UiTraceType.auto) { - if (_screenRenderForAutoUiTrace.isNotEmpty) { - reportScreenRending(_screenRenderForAutoUiTrace); - _screenRenderForAutoUiTrace.clear(); - } - _screenRenderForAutoUiTrace.traceId = traceId; - } - } - - /// Stop screen render collector and sync the captured data. - @internal - void stopScreenRenderCollector() { - if (_delayedFrames.isEmpty) return; // No delayed framed to be synced. - - _saveCollectedData(); - - if (_screenRenderForCustomUiTrace.isNotEmpty) { - reportScreenRending(_screenRenderForCustomUiTrace, UiTraceType.custom); - } - if (_screenRenderForAutoUiTrace.isNotEmpty) { - reportScreenRending(_screenRenderForAutoUiTrace); - } - - _removeFrameTimings(); - - _resetCachedFrameData(); - } - - /// Sync the capture screen render data of the custom UI trace without stopping the collector. - @internal - void endScreenRenderCollectorForCustomUiTrace() { - if (_screenRenderForCustomUiTrace.isEmpty) return; - - // Save the captured screen rendering data to be synced - _screenRenderForCustomUiTrace.slowFramesTotalDuration += - _slowFramesTotalDuration; - _screenRenderForCustomUiTrace.frozenFramesTotalDuration += - _frozenFramesTotalDuration; - _screenRenderForCustomUiTrace.frameData.addAll(_delayedFrames); - - // Sync the saved screen rendering data - reportScreenRending(_screenRenderForCustomUiTrace, UiTraceType.custom); - _screenRenderForCustomUiTrace.clear(); - } - /// Reset the memory cashed data void _resetCachedFrameData() { _slowFramesTotalDuration = 0; @@ -302,32 +354,16 @@ class InstabugScreenRenderManager { } } - @visibleForTesting - Future reportScreenRending( - InstabugScreenRenderData screenRenderData, [ - UiTraceType type = UiTraceType.auto, - ]) async { - if (type == UiTraceType.auto) { - _reportScreenRenderForAutoUiTrace(screenRenderData); - } else { - _reportScreenRenderForCustomUiTrace(screenRenderData); - } - log( - "Reported Data (${type == UiTraceType.auto ? 'auto' : 'custom'}): $screenRenderData", - name: tag, - ); - } - Future _reportScreenRenderForCustomUiTrace( InstabugScreenRenderData screenRenderData, ) async { - //todo: Will be implemented in next sprint + //todo: Will be implemented in the next PR } Future _reportScreenRenderForAutoUiTrace( InstabugScreenRenderData screenRenderData, ) async { - //todo: Will be implemented in next sprint + //todo: Will be implemented in the next PR } /// Add the memory cashed data to the objects that will be synced asynchronously to the native side. @@ -348,7 +384,16 @@ class InstabugScreenRenderManager { } } - /// --------------------------- testing helper functions --------------------- + /// @nodoc + void _logExceptionErrorAndStackTrace(Object error, StackTrace stackTrace) { + InstabugLogger.I.e( + '[Error]:$error \n' + '[StackTrace]: $stackTrace', + tag: tag, + ); + } + + /// --------------------------- testing helper methods --------------------- @visibleForTesting InstabugScreenRenderManager.init(); diff --git a/lib/src/utils/screen_rendering/instabug_widget_binding_observer.dart b/lib/src/utils/screen_rendering/instabug_widget_binding_observer.dart index 6a92b51ce..f7e16f054 100644 --- a/lib/src/utils/screen_rendering/instabug_widget_binding_observer.dart +++ b/lib/src/utils/screen_rendering/instabug_widget_binding_observer.dart @@ -1,4 +1,5 @@ import 'dart:developer'; + import 'package:flutter/widgets.dart'; import 'package:instabug_flutter/src/utils/screen_loading/screen_loading_manager.dart'; import 'package:instabug_flutter/src/utils/screen_name_masker.dart'; @@ -22,32 +23,37 @@ class InstabugWidgetsBindingObserver extends WidgetsBindingObserver { static const tag = "InstabugWidgetsBindingObserver"; void _handleResumedState() { - log('Performing resume actions...'); + log('Performing resume actions...', name: 'andrew'); final lastUiTrace = ScreenLoadingManager.I.currentUiTrace; - if (lastUiTrace != null) { - final maskedScreenName = ScreenNameMasker.I.mask(lastUiTrace.screenName); - ScreenLoadingManager.I - .startUiTrace(maskedScreenName, lastUiTrace.screenName) - .then((uiTraceId) { - if (uiTraceId != null && - InstabugScreenRenderManager.I.screenRenderEnabled) { - InstabugScreenRenderManager.I - .startScreenRenderCollectorForTraceId(uiTraceId); - } - }); + if (lastUiTrace == null) { + return; } + final maskedScreenName = ScreenNameMasker.I.mask(lastUiTrace.screenName); + ScreenLoadingManager.I + .startUiTrace(maskedScreenName, lastUiTrace.screenName) + .then((uiTraceId) { + if (uiTraceId != null && + InstabugScreenRenderManager.I.screenRenderEnabled) { + InstabugScreenRenderManager.I + .startScreenRenderCollectorForTraceId(uiTraceId); + } + }); } void _handlePausedState() { - log('Performing pause actions...'); + log('Performing pause actions...', name: 'andrew'); InstabugScreenRenderManager.I.stopScreenRenderCollector(); } void _handleDetachedState() { - log('Performing detached actions...'); + log('Performing detached actions...', name: 'andrew'); InstabugScreenRenderManager.I.stopScreenRenderCollector(); } + void _handleDefaultState() { + log("handle default state", name: 'andrew'); + } + @override void didChangeAppLifecycleState(AppLifecycleState state) { switch (state) { @@ -64,11 +70,6 @@ class InstabugWidgetsBindingObserver extends WidgetsBindingObserver { _handleDefaultState(); } } - - void _handleDefaultState() { - //todo: will be implemented in next story - debugPrint("default"); - } } @internal diff --git a/test/apm_test.dart b/test/apm_test.dart index 4e8ec87a6..9f095f15d 100644 --- a/test/apm_test.dart +++ b/test/apm_test.dart @@ -4,6 +4,7 @@ import 'package:instabug_flutter/instabug_flutter.dart'; import 'package:instabug_flutter/src/generated/apm.api.g.dart'; import 'package:instabug_flutter/src/utils/ibg_build_info.dart'; import 'package:instabug_flutter/src/utils/ibg_date_time.dart'; +import 'package:instabug_flutter/src/utils/screen_rendering/instabug_screen_render_manager.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; @@ -13,6 +14,7 @@ import 'apm_test.mocks.dart'; ApmHostApi, IBGDateTime, IBGBuildInfo, + InstabugScreenRenderManager, ]) void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -21,6 +23,7 @@ void main() { final mHost = MockApmHostApi(); final mDateTime = MockIBGDateTime(); final mBuildInfo = MockIBGBuildInfo(); + final mScreenRenderManager = MockInstabugScreenRenderManager(); setUpAll(() { APM.$setHostApi(mHost); @@ -258,4 +261,116 @@ void main() { mHost.isEndScreenLoadingEnabled(), ).called(1); }); + + group("ScreenRender", () { + setUp(() { + InstabugScreenRenderManager.setInstance(mScreenRenderManager); + }); + tearDown((){ + reset(mScreenRenderManager); + }); + test("[isScreenRenderEnabled] should call host method", () async { + when(mHost.isScreenRenderEnabled()).thenAnswer((_) async => true); + await APM.isScreenRenderEnabled(); + verify(mHost.isScreenRenderEnabled()); + }); + + test("[getDeviceRefreshRate] should call host method", () async { + when(mHost.deviceRefreshRate()).thenAnswer((_) async => 60.0); + await APM.getDeviceRefreshRate(); + verify(mHost.deviceRefreshRate()).called(1); + }); + + test("[setScreenRenderEnabled] should call host method", () async { + const isEnabled = false; + await APM.setScreenRenderEnabled(isEnabled); + verify(mHost.setScreenRenderEnabled(isEnabled)).called(1); + }); + + test("[setScreenRenderEnabled] should call [init()] screen render collector, is the feature is enabled", () async { + const isEnabled = true; + await APM.setScreenRenderEnabled(isEnabled); + verify(mScreenRenderManager.init(any)).called(1); + verifyNoMoreInteractions(mScreenRenderManager); + }); + + test("[setScreenRenderEnabled] should call [remove()] screen render collector, is the feature is enabled", () async { + const isEnabled = false; + await APM.setScreenRenderEnabled(isEnabled); + verify(mScreenRenderManager.remove()).called(1); + verifyNoMoreInteractions(mScreenRenderManager); + }); + + + + test( + "[startUITrace] should start screen render collector with right params, if screen render feature is enabled", + () async { + when(mHost.isScreenRenderEnabled()).thenAnswer((_) async => true); + + const traceName = "traceNameTest"; + await APM.startUITrace(traceName); + + verify(mHost.startUITrace(traceName)).called(1); + verify(mHost.isScreenRenderEnabled()).called(1); + verify( + mScreenRenderManager.startScreenRenderCollectorForTraceId( + 0, + UiTraceType.custom, + ), + ).called(1); + }); + + test( + "[startUITrace] should not start screen render collector, if screen render feature is disabled", + () async { + when(mHost.isScreenRenderEnabled()).thenAnswer((_) async => false); + + const traceName = "traceNameTest"; + await APM.startUITrace(traceName); + + verify(mHost.startUITrace(traceName)).called(1); + verify(mHost.isScreenRenderEnabled()).called(1); + verifyNever( + mScreenRenderManager.startScreenRenderCollectorForTraceId( + any, + any, + ), + ); + }); + + test( + "[endUITrace] should stop screen render collector with, if screen render feature is enabled", + () async { + when(mHost.isScreenRenderEnabled()).thenAnswer((_) async => true); + + const traceName = "traceNameTest"; + await APM.startUITrace(traceName); + await APM.endUITrace(); + + verify(mHost.startUITrace(traceName)).called(1); + verify( + mScreenRenderManager.endScreenRenderCollectorForCustomUiTrace(), + ).called(1); + verifyNever(mHost.endUITrace()); + }); + + test( + "[endUITrace] should acts as normal and do nothing related to screen render, if screen render feature is disabled", + () async { + when(mHost.isScreenRenderEnabled()).thenAnswer((_) async => false); + + const traceName = "traceNameTest"; + await APM.startUITrace(traceName); + await APM.endUITrace(); + + verify(mHost.startUITrace(traceName)).called(1); + verify( + mHost.endUITrace(), + ).called(1); + verifyNever( + mScreenRenderManager.endScreenRenderCollectorForCustomUiTrace(), + ); + }); + }); } From b804d45df3a222824762a02ef136b53623f08451 Mon Sep 17 00:00:00 2001 From: Andrew Amin Date: Mon, 30 Jun 2025 23:33:03 +0300 Subject: [PATCH 13/15] chore: merge screen_render_native_apis branch --- test/apm_test.dart | 12 +- .../instabug_screen_render_manager_test.dart | 9 +- ...reen_render_manager_test_manual_mocks.dart | 2140 +++++++++++++++++ 3 files changed, 2148 insertions(+), 13 deletions(-) create mode 100644 test/utils/screen_render/instabug_screen_render_manager_test_manual_mocks.dart diff --git a/test/apm_test.dart b/test/apm_test.dart index 9f095f15d..0e02cd48e 100644 --- a/test/apm_test.dart +++ b/test/apm_test.dart @@ -266,7 +266,7 @@ void main() { setUp(() { InstabugScreenRenderManager.setInstance(mScreenRenderManager); }); - tearDown((){ + tearDown(() { reset(mScreenRenderManager); }); test("[isScreenRenderEnabled] should call host method", () async { @@ -287,22 +287,24 @@ void main() { verify(mHost.setScreenRenderEnabled(isEnabled)).called(1); }); - test("[setScreenRenderEnabled] should call [init()] screen render collector, is the feature is enabled", () async { + test( + "[setScreenRenderEnabled] should call [init()] screen render collector, is the feature is enabled", + () async { const isEnabled = true; await APM.setScreenRenderEnabled(isEnabled); verify(mScreenRenderManager.init(any)).called(1); verifyNoMoreInteractions(mScreenRenderManager); }); - test("[setScreenRenderEnabled] should call [remove()] screen render collector, is the feature is enabled", () async { + test( + "[setScreenRenderEnabled] should call [remove()] screen render collector, is the feature is enabled", + () async { const isEnabled = false; await APM.setScreenRenderEnabled(isEnabled); verify(mScreenRenderManager.remove()).called(1); verifyNoMoreInteractions(mScreenRenderManager); }); - - test( "[startUITrace] should start screen render collector with right params, if screen render feature is enabled", () async { diff --git a/test/utils/screen_render/instabug_screen_render_manager_test.dart b/test/utils/screen_render/instabug_screen_render_manager_test.dart index 73fea5561..deb227462 100644 --- a/test/utils/screen_render/instabug_screen_render_manager_test.dart +++ b/test/utils/screen_render/instabug_screen_render_manager_test.dart @@ -1,19 +1,12 @@ -import 'dart:ui'; - -import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:instabug_flutter/instabug_flutter.dart'; -import 'package:instabug_flutter/src/generated/apm.api.g.dart'; import 'package:instabug_flutter/src/models/instabug_frame_data.dart'; import 'package:instabug_flutter/src/models/instabug_screen_render_data.dart'; import 'package:instabug_flutter/src/utils/screen_rendering/instabug_screen_render_manager.dart'; -import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; -import 'instabug_screen_render_manager_test.mocks.dart'; -// import 'instabug_screen_render_manager_test_manual_mocks.dart'; +import 'instabug_screen_render_manager_test_manual_mocks.dart'; -@GenerateMocks([FrameTiming, ApmHostApi, WidgetsBinding]) void main() { TestWidgetsFlutterBinding.ensureInitialized(); diff --git a/test/utils/screen_render/instabug_screen_render_manager_test_manual_mocks.dart b/test/utils/screen_render/instabug_screen_render_manager_test_manual_mocks.dart new file mode 100644 index 000000000..f34570489 --- /dev/null +++ b/test/utils/screen_render/instabug_screen_render_manager_test_manual_mocks.dart @@ -0,0 +1,2140 @@ +// Mocks generated by Mockito 5.4.4 from annotations +// in instabug_flutter/test/utils/screen_render/instabug_screen_render_manager_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i10; +import 'dart:developer' as _i15; +import 'dart:ui' as _i5; + +import 'package:flutter/foundation.dart' as _i3; +import 'package:flutter/gestures.dart' as _i7; +import 'package:flutter/rendering.dart' as _i8; +import 'package:flutter/scheduler.dart' as _i13; +import 'package:flutter/services.dart' as _i6; +import 'package:flutter/src/widgets/binding.dart' as _i12; +import 'package:flutter/src/widgets/focus_manager.dart' as _i4; +import 'package:flutter/src/widgets/framework.dart' as _i9; +import 'package:flutter/src/widgets/platform_menu_bar.dart' as _i2; +import 'package:instabug_flutter/src/generated/apm.api.g.dart' as _i11; +import 'package:mockito/mockito.dart' as _i1; +import 'package:mockito/src/dummies.dart' as _i14; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class + +class _FakeDuration_0 extends _i1.SmartFake implements Duration { + _FakeDuration_0( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakePlatformMenuDelegate_1 extends _i1.SmartFake + implements _i2.PlatformMenuDelegate { + _FakePlatformMenuDelegate_1( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeValueNotifier_2 extends _i1.SmartFake + implements _i3.ValueNotifier { + _FakeValueNotifier_2( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeFocusManager_3 extends _i1.SmartFake implements _i4.FocusManager { + _FakeFocusManager_3( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); + + @override + String toString({_i3.DiagnosticLevel? minLevel = _i3.DiagnosticLevel.info}) => + super.toString(); +} + +class _FakeSingletonFlutterWindow_4 extends _i1.SmartFake + implements _i5.SingletonFlutterWindow { + _FakeSingletonFlutterWindow_4( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakePlatformDispatcher_5 extends _i1.SmartFake + implements _i5.PlatformDispatcher { + _FakePlatformDispatcher_5( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeHardwareKeyboard_6 extends _i1.SmartFake + implements _i6.HardwareKeyboard { + _FakeHardwareKeyboard_6( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeKeyEventManager_7 extends _i1.SmartFake + implements _i6.KeyEventManager { + _FakeKeyEventManager_7( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeBinaryMessenger_8 extends _i1.SmartFake + implements _i6.BinaryMessenger { + _FakeBinaryMessenger_8( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeChannelBuffers_9 extends _i1.SmartFake + implements _i5.ChannelBuffers { + _FakeChannelBuffers_9( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeRestorationManager_10 extends _i1.SmartFake + implements _i6.RestorationManager { + _FakeRestorationManager_10( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakePointerRouter_11 extends _i1.SmartFake implements _i7.PointerRouter { + _FakePointerRouter_11( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeGestureArenaManager_12 extends _i1.SmartFake + implements _i7.GestureArenaManager { + _FakeGestureArenaManager_12( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakePointerSignalResolver_13 extends _i1.SmartFake + implements _i7.PointerSignalResolver { + _FakePointerSignalResolver_13( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeSamplingClock_14 extends _i1.SmartFake implements _i7.SamplingClock { + _FakeSamplingClock_14( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeRenderView_15 extends _i1.SmartFake implements _i8.RenderView { + _FakeRenderView_15( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); + + @override + String toString({_i3.DiagnosticLevel? minLevel = _i3.DiagnosticLevel.info}) => + super.toString(); +} + +class _FakeMouseTracker_16 extends _i1.SmartFake implements _i8.MouseTracker { + _FakeMouseTracker_16( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeAccessibilityFeatures_17 extends _i1.SmartFake + implements _i5.AccessibilityFeatures { + _FakeAccessibilityFeatures_17( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeWidget_18 extends _i1.SmartFake implements _i9.Widget { + _FakeWidget_18( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); + + @override + String toString({_i3.DiagnosticLevel? minLevel = _i3.DiagnosticLevel.info}) => + super.toString(); +} + +class _FakeFuture_19 extends _i1.SmartFake implements _i10.Future { + _FakeFuture_19( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeViewConfiguration_20 extends _i1.SmartFake + implements _i8.ViewConfiguration { + _FakeViewConfiguration_20( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeSceneBuilder_21 extends _i1.SmartFake implements _i5.SceneBuilder { + _FakeSceneBuilder_21( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakePictureRecorder_22 extends _i1.SmartFake + implements _i5.PictureRecorder { + _FakePictureRecorder_22( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeCanvas_23 extends _i1.SmartFake implements _i5.Canvas { + _FakeCanvas_23( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeSemanticsHandle_24 extends _i1.SmartFake + implements _i8.SemanticsHandle { + _FakeSemanticsHandle_24( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeSemanticsUpdateBuilder_25 extends _i1.SmartFake + implements _i5.SemanticsUpdateBuilder { + _FakeSemanticsUpdateBuilder_25( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +/// A class which mocks [FrameTiming]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockFrameTiming extends _i1.Mock implements _i5.FrameTiming { + MockFrameTiming() { + _i1.throwOnMissingStub(this); + } + + @override + Duration get buildDuration => (super.noSuchMethod( + Invocation.getter(#buildDuration), + returnValue: _FakeDuration_0( + this, + Invocation.getter(#buildDuration), + ), + ) as Duration); + + @override + Duration get rasterDuration => (super.noSuchMethod( + Invocation.getter(#rasterDuration), + returnValue: _FakeDuration_0( + this, + Invocation.getter(#rasterDuration), + ), + ) as Duration); + + @override + Duration get vsyncOverhead => (super.noSuchMethod( + Invocation.getter(#vsyncOverhead), + returnValue: _FakeDuration_0( + this, + Invocation.getter(#vsyncOverhead), + ), + ) as Duration); + + @override + Duration get totalSpan => (super.noSuchMethod( + Invocation.getter(#totalSpan), + returnValue: _FakeDuration_0( + this, + Invocation.getter(#totalSpan), + ), + ) as Duration); + + @override + int get layerCacheCount => (super.noSuchMethod( + Invocation.getter(#layerCacheCount), + returnValue: 0, + ) as int); + + @override + int get layerCacheBytes => (super.noSuchMethod( + Invocation.getter(#layerCacheBytes), + returnValue: 0, + ) as int); + + @override + double get layerCacheMegabytes => (super.noSuchMethod( + Invocation.getter(#layerCacheMegabytes), + returnValue: 0.0, + ) as double); + + @override + int get pictureCacheCount => (super.noSuchMethod( + Invocation.getter(#pictureCacheCount), + returnValue: 0, + ) as int); + + @override + int get pictureCacheBytes => (super.noSuchMethod( + Invocation.getter(#pictureCacheBytes), + returnValue: 0, + ) as int); + + @override + double get pictureCacheMegabytes => (super.noSuchMethod( + Invocation.getter(#pictureCacheMegabytes), + returnValue: 0.0, + ) as double); + + @override + int get frameNumber => (super.noSuchMethod( + Invocation.getter(#frameNumber), + returnValue: 0, + ) as int); + + @override + int timestampInMicroseconds(_i5.FramePhase? phase) => (super.noSuchMethod( + Invocation.method( + #timestampInMicroseconds, + [phase], + ), + returnValue: 0, + ) as int); +} + +/// A class which mocks [ApmHostApi]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockApmHostApi extends _i1.Mock implements _i11.ApmHostApi { + MockApmHostApi() { + _i1.throwOnMissingStub(this); + } + + @override + _i10.Future setEnabled(bool? arg_isEnabled) => (super.noSuchMethod( + Invocation.method( + #setEnabled, + [arg_isEnabled], + ), + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); + + @override + _i10.Future isEnabled() => (super.noSuchMethod( + Invocation.method( + #isEnabled, + [], + ), + returnValue: _i10.Future.value(false), + ) as _i10.Future); + + @override + _i10.Future setScreenLoadingEnabled(bool? arg_isEnabled) => + (super.noSuchMethod( + Invocation.method( + #setScreenLoadingEnabled, + [arg_isEnabled], + ), + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); + + @override + _i10.Future isScreenLoadingEnabled() => (super.noSuchMethod( + Invocation.method( + #isScreenLoadingEnabled, + [], + ), + returnValue: _i10.Future.value(false), + ) as _i10.Future); + + @override + _i10.Future setColdAppLaunchEnabled(bool? arg_isEnabled) => + (super.noSuchMethod( + Invocation.method( + #setColdAppLaunchEnabled, + [arg_isEnabled], + ), + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); + + @override + _i10.Future setAutoUITraceEnabled(bool? arg_isEnabled) => + (super.noSuchMethod( + Invocation.method( + #setAutoUITraceEnabled, + [arg_isEnabled], + ), + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); + + @override + _i10.Future startExecutionTrace( + String? arg_id, + String? arg_name, + ) => + (super.noSuchMethod( + Invocation.method( + #startExecutionTrace, + [ + arg_id, + arg_name, + ], + ), + returnValue: _i10.Future.value(), + ) as _i10.Future); + + @override + _i10.Future startFlow(String? arg_name) => (super.noSuchMethod( + Invocation.method( + #startFlow, + [arg_name], + ), + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); + + @override + _i10.Future setFlowAttribute( + String? arg_name, + String? arg_key, + String? arg_value, + ) => + (super.noSuchMethod( + Invocation.method( + #setFlowAttribute, + [ + arg_name, + arg_key, + arg_value, + ], + ), + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); + + @override + _i10.Future endFlow(String? arg_name) => (super.noSuchMethod( + Invocation.method( + #endFlow, + [arg_name], + ), + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); + + @override + _i10.Future setExecutionTraceAttribute( + String? arg_id, + String? arg_key, + String? arg_value, + ) => + (super.noSuchMethod( + Invocation.method( + #setExecutionTraceAttribute, + [ + arg_id, + arg_key, + arg_value, + ], + ), + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); + + @override + _i10.Future endExecutionTrace(String? arg_id) => (super.noSuchMethod( + Invocation.method( + #endExecutionTrace, + [arg_id], + ), + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); + + @override + _i10.Future startUITrace(String? arg_name) => (super.noSuchMethod( + Invocation.method( + #startUITrace, + [arg_name], + ), + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); + + @override + _i10.Future endUITrace() => (super.noSuchMethod( + Invocation.method( + #endUITrace, + [], + ), + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); + + @override + _i10.Future endAppLaunch() => (super.noSuchMethod( + Invocation.method( + #endAppLaunch, + [], + ), + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); + + @override + _i10.Future networkLogAndroid(Map? arg_data) => + (super.noSuchMethod( + Invocation.method( + #networkLogAndroid, + [arg_data], + ), + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); + + @override + _i10.Future startCpUiTrace( + String? arg_screenName, + int? arg_microTimeStamp, + int? arg_traceId, + ) => + (super.noSuchMethod( + Invocation.method( + #startCpUiTrace, + [ + arg_screenName, + arg_microTimeStamp, + arg_traceId, + ], + ), + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); + + @override + _i10.Future reportScreenLoadingCP( + int? arg_startTimeStampMicro, + int? arg_durationMicro, + int? arg_uiTraceId, + ) => + (super.noSuchMethod( + Invocation.method( + #reportScreenLoadingCP, + [ + arg_startTimeStampMicro, + arg_durationMicro, + arg_uiTraceId, + ], + ), + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); + + @override + _i10.Future endScreenLoadingCP( + int? arg_timeStampMicro, + int? arg_uiTraceId, + ) => + (super.noSuchMethod( + Invocation.method( + #endScreenLoadingCP, + [ + arg_timeStampMicro, + arg_uiTraceId, + ], + ), + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); + + @override + _i10.Future isEndScreenLoadingEnabled() => (super.noSuchMethod( + Invocation.method( + #isEndScreenLoadingEnabled, + [], + ), + returnValue: _i10.Future.value(false), + ) as _i10.Future); + + @override + _i10.Future isScreenRenderEnabled() => (super.noSuchMethod( + Invocation.method( + #isScreenRenderEnabled, + [], + ), + returnValue: _i10.Future.value(false), + ) as _i10.Future); + + @override + _i10.Future deviceRefreshRate() => (super.noSuchMethod( + Invocation.method( + #deviceRefreshRate, + [], + ), + returnValue: _i10.Future.value(0.0), + ) as _i10.Future); + + @override + _i10.Future setScreenRenderEnabled(bool? arg_isEnabled) => + (super.noSuchMethod( + Invocation.method( + #setScreenRenderEnabled, + [arg_isEnabled], + ), + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); +} + +/// A class which mocks [WidgetsBinding]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockWidgetsBinding extends _i1.Mock implements _i12.WidgetsBinding { + MockWidgetsBinding() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.PlatformMenuDelegate get platformMenuDelegate => (super.noSuchMethod( + Invocation.getter(#platformMenuDelegate), + returnValue: _FakePlatformMenuDelegate_1( + this, + Invocation.getter(#platformMenuDelegate), + ), + ) as _i2.PlatformMenuDelegate); + + @override + set platformMenuDelegate(_i2.PlatformMenuDelegate? _platformMenuDelegate) => + super.noSuchMethod( + Invocation.setter( + #platformMenuDelegate, + _platformMenuDelegate, + ), + returnValueForMissingStub: null, + ); + + @override + bool get debugBuildingDirtyElements => (super.noSuchMethod( + Invocation.getter(#debugBuildingDirtyElements), + returnValue: false, + ) as bool); + + @override + set debugBuildingDirtyElements(bool? _debugBuildingDirtyElements) => + super.noSuchMethod( + Invocation.setter( + #debugBuildingDirtyElements, + _debugBuildingDirtyElements, + ), + returnValueForMissingStub: null, + ); + + @override + bool get debugShowWidgetInspectorOverride => (super.noSuchMethod( + Invocation.getter(#debugShowWidgetInspectorOverride), + returnValue: false, + ) as bool); + + @override + set debugShowWidgetInspectorOverride(bool? value) => super.noSuchMethod( + Invocation.setter( + #debugShowWidgetInspectorOverride, + value, + ), + returnValueForMissingStub: null, + ); + + @override + _i3.ValueNotifier get debugShowWidgetInspectorOverrideNotifier => + (super.noSuchMethod( + Invocation.getter(#debugShowWidgetInspectorOverrideNotifier), + returnValue: _FakeValueNotifier_2( + this, + Invocation.getter(#debugShowWidgetInspectorOverrideNotifier), + ), + ) as _i3.ValueNotifier); + + @override + _i3.ValueNotifier get debugWidgetInspectorSelectionOnTapEnabled => + (super.noSuchMethod( + Invocation.getter(#debugWidgetInspectorSelectionOnTapEnabled), + returnValue: _FakeValueNotifier_2( + this, + Invocation.getter(#debugWidgetInspectorSelectionOnTapEnabled), + ), + ) as _i3.ValueNotifier); + + @override + _i4.FocusManager get focusManager => (super.noSuchMethod( + Invocation.getter(#focusManager), + returnValue: _FakeFocusManager_3( + this, + Invocation.getter(#focusManager), + ), + ) as _i4.FocusManager); + + @override + bool get firstFrameRasterized => (super.noSuchMethod( + Invocation.getter(#firstFrameRasterized), + returnValue: false, + ) as bool); + + @override + _i10.Future get waitUntilFirstFrameRasterized => (super.noSuchMethod( + Invocation.getter(#waitUntilFirstFrameRasterized), + returnValue: _i10.Future.value(), + ) as _i10.Future); + + @override + bool get debugDidSendFirstFrameEvent => (super.noSuchMethod( + Invocation.getter(#debugDidSendFirstFrameEvent), + returnValue: false, + ) as bool); + + @override + bool get framesEnabled => (super.noSuchMethod( + Invocation.getter(#framesEnabled), + returnValue: false, + ) as bool); + + @override + bool get isRootWidgetAttached => (super.noSuchMethod( + Invocation.getter(#isRootWidgetAttached), + returnValue: false, + ) as bool); + + @override + _i5.SingletonFlutterWindow get window => (super.noSuchMethod( + Invocation.getter(#window), + returnValue: _FakeSingletonFlutterWindow_4( + this, + Invocation.getter(#window), + ), + ) as _i5.SingletonFlutterWindow); + + @override + _i5.PlatformDispatcher get platformDispatcher => (super.noSuchMethod( + Invocation.getter(#platformDispatcher), + returnValue: _FakePlatformDispatcher_5( + this, + Invocation.getter(#platformDispatcher), + ), + ) as _i5.PlatformDispatcher); + + @override + bool get locked => (super.noSuchMethod( + Invocation.getter(#locked), + returnValue: false, + ) as bool); + + @override + _i3.ValueNotifier get accessibilityFocus => (super.noSuchMethod( + Invocation.getter(#accessibilityFocus), + returnValue: _FakeValueNotifier_2( + this, + Invocation.getter(#accessibilityFocus), + ), + ) as _i3.ValueNotifier); + + @override + _i6.HardwareKeyboard get keyboard => (super.noSuchMethod( + Invocation.getter(#keyboard), + returnValue: _FakeHardwareKeyboard_6( + this, + Invocation.getter(#keyboard), + ), + ) as _i6.HardwareKeyboard); + + @override + _i6.KeyEventManager get keyEventManager => (super.noSuchMethod( + Invocation.getter(#keyEventManager), + returnValue: _FakeKeyEventManager_7( + this, + Invocation.getter(#keyEventManager), + ), + ) as _i6.KeyEventManager); + + @override + _i6.BinaryMessenger get defaultBinaryMessenger => (super.noSuchMethod( + Invocation.getter(#defaultBinaryMessenger), + returnValue: _FakeBinaryMessenger_8( + this, + Invocation.getter(#defaultBinaryMessenger), + ), + ) as _i6.BinaryMessenger); + + @override + _i5.ChannelBuffers get channelBuffers => (super.noSuchMethod( + Invocation.getter(#channelBuffers), + returnValue: _FakeChannelBuffers_9( + this, + Invocation.getter(#channelBuffers), + ), + ) as _i5.ChannelBuffers); + + @override + _i6.RestorationManager get restorationManager => (super.noSuchMethod( + Invocation.getter(#restorationManager), + returnValue: _FakeRestorationManager_10( + this, + Invocation.getter(#restorationManager), + ), + ) as _i6.RestorationManager); + + @override + _i13.SchedulingStrategy get schedulingStrategy => (super.noSuchMethod( + Invocation.getter(#schedulingStrategy), + returnValue: ({ + required int priority, + required _i13.SchedulerBinding scheduler, + }) => + false, + ) as _i13.SchedulingStrategy); + + @override + set schedulingStrategy(_i13.SchedulingStrategy? _schedulingStrategy) => + super.noSuchMethod( + Invocation.setter( + #schedulingStrategy, + _schedulingStrategy, + ), + returnValueForMissingStub: null, + ); + + @override + int get transientCallbackCount => (super.noSuchMethod( + Invocation.getter(#transientCallbackCount), + returnValue: 0, + ) as int); + + @override + _i10.Future get endOfFrame => (super.noSuchMethod( + Invocation.getter(#endOfFrame), + returnValue: _i10.Future.value(), + ) as _i10.Future); + + @override + bool get hasScheduledFrame => (super.noSuchMethod( + Invocation.getter(#hasScheduledFrame), + returnValue: false, + ) as bool); + + @override + _i13.SchedulerPhase get schedulerPhase => (super.noSuchMethod( + Invocation.getter(#schedulerPhase), + returnValue: _i13.SchedulerPhase.idle, + ) as _i13.SchedulerPhase); + + @override + Duration get currentFrameTimeStamp => (super.noSuchMethod( + Invocation.getter(#currentFrameTimeStamp), + returnValue: _FakeDuration_0( + this, + Invocation.getter(#currentFrameTimeStamp), + ), + ) as Duration); + + @override + Duration get currentSystemFrameTimeStamp => (super.noSuchMethod( + Invocation.getter(#currentSystemFrameTimeStamp), + returnValue: _FakeDuration_0( + this, + Invocation.getter(#currentSystemFrameTimeStamp), + ), + ) as Duration); + + @override + _i7.PointerRouter get pointerRouter => (super.noSuchMethod( + Invocation.getter(#pointerRouter), + returnValue: _FakePointerRouter_11( + this, + Invocation.getter(#pointerRouter), + ), + ) as _i7.PointerRouter); + + @override + _i7.GestureArenaManager get gestureArena => (super.noSuchMethod( + Invocation.getter(#gestureArena), + returnValue: _FakeGestureArenaManager_12( + this, + Invocation.getter(#gestureArena), + ), + ) as _i7.GestureArenaManager); + + @override + _i7.PointerSignalResolver get pointerSignalResolver => (super.noSuchMethod( + Invocation.getter(#pointerSignalResolver), + returnValue: _FakePointerSignalResolver_13( + this, + Invocation.getter(#pointerSignalResolver), + ), + ) as _i7.PointerSignalResolver); + + @override + bool get resamplingEnabled => (super.noSuchMethod( + Invocation.getter(#resamplingEnabled), + returnValue: false, + ) as bool); + + @override + set resamplingEnabled(bool? _resamplingEnabled) => super.noSuchMethod( + Invocation.setter( + #resamplingEnabled, + _resamplingEnabled, + ), + returnValueForMissingStub: null, + ); + + @override + Duration get samplingOffset => (super.noSuchMethod( + Invocation.getter(#samplingOffset), + returnValue: _FakeDuration_0( + this, + Invocation.getter(#samplingOffset), + ), + ) as Duration); + + @override + set samplingOffset(Duration? _samplingOffset) => super.noSuchMethod( + Invocation.setter( + #samplingOffset, + _samplingOffset, + ), + returnValueForMissingStub: null, + ); + + @override + _i7.SamplingClock get samplingClock => (super.noSuchMethod( + Invocation.getter(#samplingClock), + returnValue: _FakeSamplingClock_14( + this, + Invocation.getter(#samplingClock), + ), + ) as _i7.SamplingClock); + + @override + _i8.PipelineOwner get pipelineOwner => (super.noSuchMethod( + Invocation.getter(#pipelineOwner), + returnValue: _i14.dummyValue<_i8.PipelineOwner>( + this, + Invocation.getter(#pipelineOwner), + ), + ) as _i8.PipelineOwner); + + @override + _i8.RenderView get renderView => (super.noSuchMethod( + Invocation.getter(#renderView), + returnValue: _FakeRenderView_15( + this, + Invocation.getter(#renderView), + ), + ) as _i8.RenderView); + + @override + _i8.MouseTracker get mouseTracker => (super.noSuchMethod( + Invocation.getter(#mouseTracker), + returnValue: _FakeMouseTracker_16( + this, + Invocation.getter(#mouseTracker), + ), + ) as _i8.MouseTracker); + + @override + _i8.PipelineOwner get rootPipelineOwner => (super.noSuchMethod( + Invocation.getter(#rootPipelineOwner), + returnValue: _i14.dummyValue<_i8.PipelineOwner>( + this, + Invocation.getter(#rootPipelineOwner), + ), + ) as _i8.PipelineOwner); + + @override + Iterable<_i8.RenderView> get renderViews => (super.noSuchMethod( + Invocation.getter(#renderViews), + returnValue: <_i8.RenderView>[], + ) as Iterable<_i8.RenderView>); + + @override + bool get sendFramesToEngine => (super.noSuchMethod( + Invocation.getter(#sendFramesToEngine), + returnValue: false, + ) as bool); + + @override + bool get semanticsEnabled => (super.noSuchMethod( + Invocation.getter(#semanticsEnabled), + returnValue: false, + ) as bool); + + @override + int get debugOutstandingSemanticsHandles => (super.noSuchMethod( + Invocation.getter(#debugOutstandingSemanticsHandles), + returnValue: 0, + ) as int); + + @override + _i5.AccessibilityFeatures get accessibilityFeatures => (super.noSuchMethod( + Invocation.getter(#accessibilityFeatures), + returnValue: _FakeAccessibilityFeatures_17( + this, + Invocation.getter(#accessibilityFeatures), + ), + ) as _i5.AccessibilityFeatures); + + @override + bool get disableAnimations => (super.noSuchMethod( + Invocation.getter(#disableAnimations), + returnValue: false, + ) as bool); + + @override + void initInstances() => super.noSuchMethod( + Invocation.method( + #initInstances, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void resetInternalState() => super.noSuchMethod( + Invocation.method( + #resetInternalState, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void initServiceExtensions() => super.noSuchMethod( + Invocation.method( + #initServiceExtensions, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void addObserver(_i12.WidgetsBindingObserver? observer) => super.noSuchMethod( + Invocation.method( + #addObserver, + [observer], + ), + returnValueForMissingStub: null, + ); + + @override + bool removeObserver(_i12.WidgetsBindingObserver? observer) => + (super.noSuchMethod( + Invocation.method( + #removeObserver, + [observer], + ), + returnValue: false, + ) as bool); + + @override + _i10.Future<_i5.AppExitResponse> handleRequestAppExit() => + (super.noSuchMethod( + Invocation.method( + #handleRequestAppExit, + [], + ), + returnValue: + _i10.Future<_i5.AppExitResponse>.value(_i5.AppExitResponse.exit), + ) as _i10.Future<_i5.AppExitResponse>); + + @override + void handleMetricsChanged() => super.noSuchMethod( + Invocation.method( + #handleMetricsChanged, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void handleTextScaleFactorChanged() => super.noSuchMethod( + Invocation.method( + #handleTextScaleFactorChanged, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void handlePlatformBrightnessChanged() => super.noSuchMethod( + Invocation.method( + #handlePlatformBrightnessChanged, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void handleAccessibilityFeaturesChanged() => super.noSuchMethod( + Invocation.method( + #handleAccessibilityFeaturesChanged, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void handleLocaleChanged() => super.noSuchMethod( + Invocation.method( + #handleLocaleChanged, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void dispatchLocalesChanged(List<_i5.Locale>? locales) => super.noSuchMethod( + Invocation.method( + #dispatchLocalesChanged, + [locales], + ), + returnValueForMissingStub: null, + ); + + @override + void dispatchAccessibilityFeaturesChanged() => super.noSuchMethod( + Invocation.method( + #dispatchAccessibilityFeaturesChanged, + [], + ), + returnValueForMissingStub: null, + ); + + @override + _i10.Future handlePopRoute() => (super.noSuchMethod( + Invocation.method( + #handlePopRoute, + [], + ), + returnValue: _i10.Future.value(false), + ) as _i10.Future); + + @override + _i10.Future handlePushRoute(String? route) => (super.noSuchMethod( + Invocation.method( + #handlePushRoute, + [route], + ), + returnValue: _i10.Future.value(false), + ) as _i10.Future); + + @override + void handleAppLifecycleStateChanged(_i5.AppLifecycleState? state) => + super.noSuchMethod( + Invocation.method( + #handleAppLifecycleStateChanged, + [state], + ), + returnValueForMissingStub: null, + ); + + @override + void handleViewFocusChanged(_i5.ViewFocusEvent? event) => super.noSuchMethod( + Invocation.method( + #handleViewFocusChanged, + [event], + ), + returnValueForMissingStub: null, + ); + + @override + void handleMemoryPressure() => super.noSuchMethod( + Invocation.method( + #handleMemoryPressure, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void drawFrame() => super.noSuchMethod( + Invocation.method( + #drawFrame, + [], + ), + returnValueForMissingStub: null, + ); + + @override + _i9.Widget wrapWithDefaultView(_i9.Widget? rootWidget) => (super.noSuchMethod( + Invocation.method( + #wrapWithDefaultView, + [rootWidget], + ), + returnValue: _FakeWidget_18( + this, + Invocation.method( + #wrapWithDefaultView, + [rootWidget], + ), + ), + ) as _i9.Widget); + + @override + void scheduleAttachRootWidget(_i9.Widget? rootWidget) => super.noSuchMethod( + Invocation.method( + #scheduleAttachRootWidget, + [rootWidget], + ), + returnValueForMissingStub: null, + ); + + @override + void attachRootWidget(_i9.Widget? rootWidget) => super.noSuchMethod( + Invocation.method( + #attachRootWidget, + [rootWidget], + ), + returnValueForMissingStub: null, + ); + + @override + void attachToBuildOwner(_i12.RootWidget? widget) => super.noSuchMethod( + Invocation.method( + #attachToBuildOwner, + [widget], + ), + returnValueForMissingStub: null, + ); + + @override + _i10.Future performReassemble() => (super.noSuchMethod( + Invocation.method( + #performReassemble, + [], + ), + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); + + @override + _i5.Locale? computePlatformResolvedLocale( + List<_i5.Locale>? supportedLocales) => + (super.noSuchMethod(Invocation.method( + #computePlatformResolvedLocale, + [supportedLocales], + )) as _i5.Locale?); + + @override + bool debugCheckZone(String? entryPoint) => (super.noSuchMethod( + Invocation.method( + #debugCheckZone, + [entryPoint], + ), + returnValue: false, + ) as bool); + + @override + _i10.Future lockEvents(_i10.Future Function()? callback) => + (super.noSuchMethod( + Invocation.method( + #lockEvents, + [callback], + ), + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); + + @override + void unlocked() => super.noSuchMethod( + Invocation.method( + #unlocked, + [], + ), + returnValueForMissingStub: null, + ); + + @override + _i10.Future reassembleApplication() => (super.noSuchMethod( + Invocation.method( + #reassembleApplication, + [], + ), + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); + + @override + void registerSignalServiceExtension({ + required String? name, + required _i3.AsyncCallback? callback, + }) => + super.noSuchMethod( + Invocation.method( + #registerSignalServiceExtension, + [], + { + #name: name, + #callback: callback, + }, + ), + returnValueForMissingStub: null, + ); + + @override + void registerBoolServiceExtension({ + required String? name, + required _i3.AsyncValueGetter? getter, + required _i3.AsyncValueSetter? setter, + }) => + super.noSuchMethod( + Invocation.method( + #registerBoolServiceExtension, + [], + { + #name: name, + #getter: getter, + #setter: setter, + }, + ), + returnValueForMissingStub: null, + ); + + @override + void registerNumericServiceExtension({ + required String? name, + required _i3.AsyncValueGetter? getter, + required _i3.AsyncValueSetter? setter, + }) => + super.noSuchMethod( + Invocation.method( + #registerNumericServiceExtension, + [], + { + #name: name, + #getter: getter, + #setter: setter, + }, + ), + returnValueForMissingStub: null, + ); + + @override + void postEvent( + String? eventKind, + Map? eventData, + ) => + super.noSuchMethod( + Invocation.method( + #postEvent, + [ + eventKind, + eventData, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void registerStringServiceExtension({ + required String? name, + required _i3.AsyncValueGetter? getter, + required _i3.AsyncValueSetter? setter, + }) => + super.noSuchMethod( + Invocation.method( + #registerStringServiceExtension, + [], + { + #name: name, + #getter: getter, + #setter: setter, + }, + ), + returnValueForMissingStub: null, + ); + + @override + void registerServiceExtension({ + required String? name, + required _i3.ServiceExtensionCallback? callback, + }) => + super.noSuchMethod( + Invocation.method( + #registerServiceExtension, + [], + { + #name: name, + #callback: callback, + }, + ), + returnValueForMissingStub: null, + ); + + @override + _i6.BinaryMessenger createBinaryMessenger() => (super.noSuchMethod( + Invocation.method( + #createBinaryMessenger, + [], + ), + returnValue: _FakeBinaryMessenger_8( + this, + Invocation.method( + #createBinaryMessenger, + [], + ), + ), + ) as _i6.BinaryMessenger); + + @override + _i10.Future handleSystemMessage(Object? systemMessage) => + (super.noSuchMethod( + Invocation.method( + #handleSystemMessage, + [systemMessage], + ), + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); + + @override + void initLicenses() => super.noSuchMethod( + Invocation.method( + #initLicenses, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void evict(String? asset) => super.noSuchMethod( + Invocation.method( + #evict, + [asset], + ), + returnValueForMissingStub: null, + ); + + @override + void readInitialLifecycleStateFromNativeWindow() => super.noSuchMethod( + Invocation.method( + #readInitialLifecycleStateFromNativeWindow, + [], + ), + returnValueForMissingStub: null, + ); + + @override + _i10.Future<_i5.AppExitResponse> exitApplication( + _i5.AppExitType? exitType, [ + int? exitCode = 0, + ]) => + (super.noSuchMethod( + Invocation.method( + #exitApplication, + [ + exitType, + exitCode, + ], + ), + returnValue: + _i10.Future<_i5.AppExitResponse>.value(_i5.AppExitResponse.exit), + ) as _i10.Future<_i5.AppExitResponse>); + + @override + _i6.RestorationManager createRestorationManager() => (super.noSuchMethod( + Invocation.method( + #createRestorationManager, + [], + ), + returnValue: _FakeRestorationManager_10( + this, + Invocation.method( + #createRestorationManager, + [], + ), + ), + ) as _i6.RestorationManager); + + @override + void setSystemUiChangeCallback(_i6.SystemUiChangeCallback? callback) => + super.noSuchMethod( + Invocation.method( + #setSystemUiChangeCallback, + [callback], + ), + returnValueForMissingStub: null, + ); + + @override + _i10.Future initializationComplete() => (super.noSuchMethod( + Invocation.method( + #initializationComplete, + [], + ), + returnValue: _i10.Future.value(), + returnValueForMissingStub: _i10.Future.value(), + ) as _i10.Future); + + @override + void addTimingsCallback(_i5.TimingsCallback? callback) => super.noSuchMethod( + Invocation.method( + #addTimingsCallback, + [callback], + ), + returnValueForMissingStub: null, + ); + + @override + void removeTimingsCallback(_i5.TimingsCallback? callback) => + super.noSuchMethod( + Invocation.method( + #removeTimingsCallback, + [callback], + ), + returnValueForMissingStub: null, + ); + + @override + _i10.Future scheduleTask( + _i13.TaskCallback? task, + _i13.Priority? priority, { + String? debugLabel, + _i15.Flow? flow, + }) => + (super.noSuchMethod( + Invocation.method( + #scheduleTask, + [ + task, + priority, + ], + { + #debugLabel: debugLabel, + #flow: flow, + }, + ), + returnValue: _i14.ifNotNull( + _i14.dummyValueOrNull( + this, + Invocation.method( + #scheduleTask, + [ + task, + priority, + ], + { + #debugLabel: debugLabel, + #flow: flow, + }, + ), + ), + (T v) => _i10.Future.value(v), + ) ?? + _FakeFuture_19( + this, + Invocation.method( + #scheduleTask, + [ + task, + priority, + ], + { + #debugLabel: debugLabel, + #flow: flow, + }, + ), + ), + ) as _i10.Future); + + @override + bool handleEventLoopCallback() => (super.noSuchMethod( + Invocation.method( + #handleEventLoopCallback, + [], + ), + returnValue: false, + ) as bool); + + @override + int scheduleFrameCallback( + _i13.FrameCallback? callback, { + bool? rescheduling = false, + bool? scheduleNewFrame = true, + }) => + (super.noSuchMethod( + Invocation.method( + #scheduleFrameCallback, + [callback], + { + #rescheduling: rescheduling, + #scheduleNewFrame: scheduleNewFrame, + }, + ), + returnValue: 0, + ) as int); + + @override + void cancelFrameCallbackWithId(int? id) => super.noSuchMethod( + Invocation.method( + #cancelFrameCallbackWithId, + [id], + ), + returnValueForMissingStub: null, + ); + + @override + bool debugAssertNoTransientCallbacks(String? reason) => (super.noSuchMethod( + Invocation.method( + #debugAssertNoTransientCallbacks, + [reason], + ), + returnValue: false, + ) as bool); + + @override + bool debugAssertNoPendingPerformanceModeRequests(String? reason) => + (super.noSuchMethod( + Invocation.method( + #debugAssertNoPendingPerformanceModeRequests, + [reason], + ), + returnValue: false, + ) as bool); + + @override + bool debugAssertNoTimeDilation(String? reason) => (super.noSuchMethod( + Invocation.method( + #debugAssertNoTimeDilation, + [reason], + ), + returnValue: false, + ) as bool); + + @override + void addPersistentFrameCallback(_i13.FrameCallback? callback) => + super.noSuchMethod( + Invocation.method( + #addPersistentFrameCallback, + [callback], + ), + returnValueForMissingStub: null, + ); + + @override + void addPostFrameCallback( + _i13.FrameCallback? callback, { + String? debugLabel = r'callback', + }) => + super.noSuchMethod( + Invocation.method( + #addPostFrameCallback, + [callback], + {#debugLabel: debugLabel}, + ), + returnValueForMissingStub: null, + ); + + @override + void ensureFrameCallbacksRegistered() => super.noSuchMethod( + Invocation.method( + #ensureFrameCallbacksRegistered, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void ensureVisualUpdate() => super.noSuchMethod( + Invocation.method( + #ensureVisualUpdate, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void scheduleFrame() => super.noSuchMethod( + Invocation.method( + #scheduleFrame, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void scheduleForcedFrame() => super.noSuchMethod( + Invocation.method( + #scheduleForcedFrame, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void scheduleWarmUpFrame() => super.noSuchMethod( + Invocation.method( + #scheduleWarmUpFrame, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void resetEpoch() => super.noSuchMethod( + Invocation.method( + #resetEpoch, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void handleBeginFrame(Duration? rawTimeStamp) => super.noSuchMethod( + Invocation.method( + #handleBeginFrame, + [rawTimeStamp], + ), + returnValueForMissingStub: null, + ); + + @override + _i13.PerformanceModeRequestHandle? requestPerformanceMode( + _i5.DartPerformanceMode? mode) => + (super.noSuchMethod(Invocation.method( + #requestPerformanceMode, + [mode], + )) as _i13.PerformanceModeRequestHandle?); + + @override + void handleDrawFrame() => super.noSuchMethod( + Invocation.method( + #handleDrawFrame, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void cancelPointer(int? pointer) => super.noSuchMethod( + Invocation.method( + #cancelPointer, + [pointer], + ), + returnValueForMissingStub: null, + ); + + @override + void handlePointerEvent(_i6.PointerEvent? event) => super.noSuchMethod( + Invocation.method( + #handlePointerEvent, + [event], + ), + returnValueForMissingStub: null, + ); + + @override + void hitTestInView( + _i7.HitTestResult? result, + _i5.Offset? position, + int? viewId, + ) => + super.noSuchMethod( + Invocation.method( + #hitTestInView, + [ + result, + position, + viewId, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void hitTest( + _i7.HitTestResult? result, + _i5.Offset? position, + ) => + super.noSuchMethod( + Invocation.method( + #hitTest, + [ + result, + position, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void dispatchEvent( + _i6.PointerEvent? event, + _i7.HitTestResult? hitTestResult, + ) => + super.noSuchMethod( + Invocation.method( + #dispatchEvent, + [ + event, + hitTestResult, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void handleEvent( + _i6.PointerEvent? event, + _i7.HitTestEntry<_i7.HitTestTarget>? entry, + ) => + super.noSuchMethod( + Invocation.method( + #handleEvent, + [ + event, + entry, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void resetGestureBinding() => super.noSuchMethod( + Invocation.method( + #resetGestureBinding, + [], + ), + returnValueForMissingStub: null, + ); + + @override + _i8.PipelineOwner createRootPipelineOwner() => (super.noSuchMethod( + Invocation.method( + #createRootPipelineOwner, + [], + ), + returnValue: _i14.dummyValue<_i8.PipelineOwner>( + this, + Invocation.method( + #createRootPipelineOwner, + [], + ), + ), + ) as _i8.PipelineOwner); + + @override + void addRenderView(_i8.RenderView? view) => super.noSuchMethod( + Invocation.method( + #addRenderView, + [view], + ), + returnValueForMissingStub: null, + ); + + @override + void removeRenderView(_i8.RenderView? view) => super.noSuchMethod( + Invocation.method( + #removeRenderView, + [view], + ), + returnValueForMissingStub: null, + ); + + @override + _i8.ViewConfiguration createViewConfigurationFor( + _i8.RenderView? renderView) => + (super.noSuchMethod( + Invocation.method( + #createViewConfigurationFor, + [renderView], + ), + returnValue: _FakeViewConfiguration_20( + this, + Invocation.method( + #createViewConfigurationFor, + [renderView], + ), + ), + ) as _i8.ViewConfiguration); + + @override + _i5.SceneBuilder createSceneBuilder() => (super.noSuchMethod( + Invocation.method( + #createSceneBuilder, + [], + ), + returnValue: _FakeSceneBuilder_21( + this, + Invocation.method( + #createSceneBuilder, + [], + ), + ), + ) as _i5.SceneBuilder); + + @override + _i5.PictureRecorder createPictureRecorder() => (super.noSuchMethod( + Invocation.method( + #createPictureRecorder, + [], + ), + returnValue: _FakePictureRecorder_22( + this, + Invocation.method( + #createPictureRecorder, + [], + ), + ), + ) as _i5.PictureRecorder); + + @override + _i5.Canvas createCanvas(_i5.PictureRecorder? recorder) => (super.noSuchMethod( + Invocation.method( + #createCanvas, + [recorder], + ), + returnValue: _FakeCanvas_23( + this, + Invocation.method( + #createCanvas, + [recorder], + ), + ), + ) as _i5.Canvas); + + @override + void initMouseTracker([_i8.MouseTracker? tracker]) => super.noSuchMethod( + Invocation.method( + #initMouseTracker, + [tracker], + ), + returnValueForMissingStub: null, + ); + + @override + void performSemanticsAction(_i5.SemanticsActionEvent? action) => + super.noSuchMethod( + Invocation.method( + #performSemanticsAction, + [action], + ), + returnValueForMissingStub: null, + ); + + @override + void deferFirstFrame() => super.noSuchMethod( + Invocation.method( + #deferFirstFrame, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void allowFirstFrame() => super.noSuchMethod( + Invocation.method( + #allowFirstFrame, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void resetFirstFrameSent() => super.noSuchMethod( + Invocation.method( + #resetFirstFrameSent, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void addSemanticsEnabledListener(_i5.VoidCallback? listener) => + super.noSuchMethod( + Invocation.method( + #addSemanticsEnabledListener, + [listener], + ), + returnValueForMissingStub: null, + ); + + @override + void removeSemanticsEnabledListener(_i5.VoidCallback? listener) => + super.noSuchMethod( + Invocation.method( + #removeSemanticsEnabledListener, + [listener], + ), + returnValueForMissingStub: null, + ); + + @override + void addSemanticsActionListener( + _i3.ValueSetter<_i5.SemanticsActionEvent>? listener) => + super.noSuchMethod( + Invocation.method( + #addSemanticsActionListener, + [listener], + ), + returnValueForMissingStub: null, + ); + + @override + void removeSemanticsActionListener( + _i3.ValueSetter<_i5.SemanticsActionEvent>? listener) => + super.noSuchMethod( + Invocation.method( + #removeSemanticsActionListener, + [listener], + ), + returnValueForMissingStub: null, + ); + + @override + _i8.SemanticsHandle ensureSemantics() => (super.noSuchMethod( + Invocation.method( + #ensureSemantics, + [], + ), + returnValue: _FakeSemanticsHandle_24( + this, + Invocation.method( + #ensureSemantics, + [], + ), + ), + ) as _i8.SemanticsHandle); + + @override + _i5.SemanticsUpdateBuilder createSemanticsUpdateBuilder() => + (super.noSuchMethod( + Invocation.method( + #createSemanticsUpdateBuilder, + [], + ), + returnValue: _FakeSemanticsUpdateBuilder_25( + this, + Invocation.method( + #createSemanticsUpdateBuilder, + [], + ), + ), + ) as _i5.SemanticsUpdateBuilder); +} From 39bdd7254a6e30689ad56472614afdb8054246a5 Mon Sep 17 00:00:00 2001 From: Andrew Amin Date: Tue, 1 Jul 2025 14:08:07 +0300 Subject: [PATCH 14/15] chore: apply flutter 2.10.5 --- example/pubspec.lock | 189 +- .../instabug_screen_render_manager_test.dart | 13 +- ...reen_render_manager_test_manual_mocks.dart | 2484 ++++------------- 3 files changed, 698 insertions(+), 1988 deletions(-) diff --git a/example/pubspec.lock b/example/pubspec.lock index 74b4b6b46..db618bb81 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -1,62 +1,76 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + archive: + dependency: transitive + description: + name: archive + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.6" async: dependency: transitive description: name: async - sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.13.0" + version: "2.8.2" boolean_selector: dependency: transitive description: name: boolean_selector - sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.1.2" + version: "2.1.0" characters: dependency: transitive description: name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 - url: "https://pub.dev" + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.dartlang.org" source: hosted - version: "1.4.0" + version: "1.3.1" clock: dependency: transitive description: name: clock - sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.1.2" + version: "1.1.0" collection: dependency: transitive description: name: collection - sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.19.1" + version: "1.15.0" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" fake_async: dependency: transitive description: name: fake_async - sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.3.3" + version: "1.2.0" file: dependency: transitive description: name: file - sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "7.0.1" + version: "6.1.2" flutter: dependency: "direct main" description: flutter @@ -71,8 +85,7 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: b543301ad291598523947dc534aaddc5aaad597b709d2426d3a0e0d44c5cb493 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.4" flutter_test: @@ -89,18 +102,16 @@ packages: dependency: "direct main" description: name: http - sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "0.13.6" + version: "0.13.5" http_parser: dependency: transitive description: name: http_parser - sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "4.1.2" + version: "4.0.2" instabug_flutter: dependency: "direct main" description: @@ -112,183 +123,139 @@ packages: dependency: "direct main" description: name: instabug_http_client - sha256: "97a6ab88491eff87e42437564b528d6986a65eb3f3262f73373009f949cb4560" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.5.1" - leak_tracker: - dependency: transitive - description: - name: leak_tracker - sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" - url: "https://pub.dev" - source: hosted - version: "10.0.9" - leak_tracker_flutter_testing: - dependency: transitive - description: - name: leak_tracker_flutter_testing - sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 - url: "https://pub.dev" - source: hosted - version: "3.0.9" - leak_tracker_testing: - dependency: transitive - description: - name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" - url: "https://pub.dev" - source: hosted - version: "3.0.1" lints: dependency: transitive description: name: lints - sha256: a2c3d198cb5ea2e179926622d433331d8b58374ab8f29cdda6e863bd62fd369c - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "1.0.1" matcher: dependency: transitive description: name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "0.12.17" + version: "0.12.11" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "0.11.1" + version: "0.1.3" meta: dependency: transitive description: name: meta - sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.16.0" + version: "1.7.0" path: dependency: transitive description: name: path - sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.9.1" + version: "1.8.0" platform: dependency: transitive description: name: platform - sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "3.1.6" + version: "3.1.0" process: dependency: transitive description: name: process - sha256: "107d8be718f120bbba9dcd1e95e3bd325b1b4a4f07db64154635ba03f2567a0d" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "5.0.3" + version: "4.2.4" sky_engine: dependency: transitive description: flutter source: sdk - version: "0.0.0" + version: "0.0.99" source_span: dependency: transitive description: name: source_span - sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.10.1" + version: "1.8.1" stack_trace: dependency: transitive description: name: stack_trace - sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.12.1" + version: "1.10.0" stream_channel: dependency: transitive description: name: stream_channel - sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.1.4" + version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner - sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.4.1" + version: "1.1.0" sync_http: dependency: transitive description: name: sync_http - sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "0.3.1" + version: "0.3.0" term_glyph: dependency: transitive description: name: term_glyph - sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.2.2" + version: "1.2.0" test_api: dependency: transitive description: name: test_api - sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "0.7.4" + version: "0.4.8" typed_data: dependency: transitive description: name: typed_data - sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "1.4.0" + version: "1.3.0" vector_math: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "2.1.4" + version: "2.1.1" vm_service: dependency: transitive description: name: vm_service - sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "15.0.0" + version: "7.5.0" webdriver: dependency: transitive description: name: webdriver - sha256: "2f3a14ca026957870cfd9c635b83507e0e51d8091568e90129fbf805aba7cade" - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted - version: "3.1.0" + version: "3.0.0" sdks: - dart: ">=3.7.0-0 <4.0.0" - flutter: ">=3.18.0-18.0.pre.54" + dart: ">=2.14.0 <3.0.0" diff --git a/test/utils/screen_render/instabug_screen_render_manager_test.dart b/test/utils/screen_render/instabug_screen_render_manager_test.dart index deb227462..c261fc879 100644 --- a/test/utils/screen_render/instabug_screen_render_manager_test.dart +++ b/test/utils/screen_render/instabug_screen_render_manager_test.dart @@ -1,12 +1,19 @@ +import 'dart:ui'; + +import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:instabug_flutter/instabug_flutter.dart'; +import 'package:instabug_flutter/src/generated/apm.api.g.dart'; import 'package:instabug_flutter/src/models/instabug_frame_data.dart'; import 'package:instabug_flutter/src/models/instabug_screen_render_data.dart'; import 'package:instabug_flutter/src/utils/screen_rendering/instabug_screen_render_manager.dart'; +import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; + import 'instabug_screen_render_manager_test_manual_mocks.dart'; +@GenerateMocks([ApmHostApi, WidgetsBinding, FrameTiming]) void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -23,10 +30,6 @@ void main() { manager.init(mWidgetBinding); }); - tearDown(() { - // Clean up state after each test - }); - group('InstabugScreenRenderManager.init()', () { test('should initialize timings callback and add observer', () async { expect(manager, isA()); @@ -45,8 +48,6 @@ void main() { verify(mWidgetBinding.addObserver(any)).called(1); verify(mWidgetBinding.addTimingsCallback(any)).called(1); - - expect(true, isTrue); // no crash }); }); diff --git a/test/utils/screen_render/instabug_screen_render_manager_test_manual_mocks.dart b/test/utils/screen_render/instabug_screen_render_manager_test_manual_mocks.dart index f34570489..dcc87eaab 100644 --- a/test/utils/screen_render/instabug_screen_render_manager_test_manual_mocks.dart +++ b/test/utils/screen_render/instabug_screen_render_manager_test_manual_mocks.dart @@ -1,2140 +1,882 @@ -// Mocks generated by Mockito 5.4.4 from annotations -// in instabug_flutter/test/utils/screen_render/instabug_screen_render_manager_test.dart. +// Mocks generated by Mockito 5.2.0 from annotations +// in instabug_flutter/example/ios/.symlinks/plugins/instabug_flutter/test/utils/screen_render/instabug_screen_render_manager_test.dart. // Do not manually edit this file. -// ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i10; -import 'dart:developer' as _i15; -import 'dart:ui' as _i5; +import 'dart:async' as _i9; +import 'dart:developer' as _i13; +import 'dart:ui' as _i4; import 'package:flutter/foundation.dart' as _i3; -import 'package:flutter/gestures.dart' as _i7; -import 'package:flutter/rendering.dart' as _i8; -import 'package:flutter/scheduler.dart' as _i13; -import 'package:flutter/services.dart' as _i6; -import 'package:flutter/src/widgets/binding.dart' as _i12; -import 'package:flutter/src/widgets/focus_manager.dart' as _i4; -import 'package:flutter/src/widgets/framework.dart' as _i9; -import 'package:flutter/src/widgets/platform_menu_bar.dart' as _i2; -import 'package:instabug_flutter/src/generated/apm.api.g.dart' as _i11; +import 'package:flutter/gestures.dart' as _i6; +import 'package:flutter/rendering.dart' as _i7; +import 'package:flutter/scheduler.dart' as _i11; +import 'package:flutter/services.dart' as _i5; +import 'package:flutter/src/widgets/binding.dart' as _i10; +import 'package:flutter/src/widgets/focus_manager.dart' as _i2; +import 'package:flutter/src/widgets/framework.dart' as _i12; +import 'package:instabug_flutter/src/generated/apm.api.g.dart' as _i8; import 'package:mockito/mockito.dart' as _i1; -import 'package:mockito/src/dummies.dart' as _i14; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values // ignore_for_file: avoid_setters_without_getters // ignore_for_file: comment_references -// ignore_for_file: deprecated_member_use -// ignore_for_file: deprecated_member_use_from_same_package // ignore_for_file: implementation_imports // ignore_for_file: invalid_use_of_visible_for_testing_member // ignore_for_file: prefer_const_constructors // ignore_for_file: unnecessary_parenthesis // ignore_for_file: camel_case_types -// ignore_for_file: subtype_of_sealed_class - -class _FakeDuration_0 extends _i1.SmartFake implements Duration { - _FakeDuration_0( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} - -class _FakePlatformMenuDelegate_1 extends _i1.SmartFake - implements _i2.PlatformMenuDelegate { - _FakePlatformMenuDelegate_1( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} - -class _FakeValueNotifier_2 extends _i1.SmartFake - implements _i3.ValueNotifier { - _FakeValueNotifier_2( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} - -class _FakeFocusManager_3 extends _i1.SmartFake implements _i4.FocusManager { - _FakeFocusManager_3( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); +class _FakeFocusManager_0 extends _i1.Fake implements _i2.FocusManager { @override String toString({_i3.DiagnosticLevel? minLevel = _i3.DiagnosticLevel.info}) => super.toString(); } -class _FakeSingletonFlutterWindow_4 extends _i1.SmartFake - implements _i5.SingletonFlutterWindow { - _FakeSingletonFlutterWindow_4( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} - -class _FakePlatformDispatcher_5 extends _i1.SmartFake - implements _i5.PlatformDispatcher { - _FakePlatformDispatcher_5( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} - -class _FakeHardwareKeyboard_6 extends _i1.SmartFake - implements _i6.HardwareKeyboard { - _FakeHardwareKeyboard_6( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} - -class _FakeKeyEventManager_7 extends _i1.SmartFake - implements _i6.KeyEventManager { - _FakeKeyEventManager_7( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} +class _FakeSingletonFlutterWindow_1 extends _i1.Fake + implements _i4.SingletonFlutterWindow {} -class _FakeBinaryMessenger_8 extends _i1.SmartFake - implements _i6.BinaryMessenger { - _FakeBinaryMessenger_8( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} +class _FakePlatformDispatcher_2 extends _i1.Fake + implements _i4.PlatformDispatcher {} -class _FakeChannelBuffers_9 extends _i1.SmartFake - implements _i5.ChannelBuffers { - _FakeChannelBuffers_9( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); +class _FakeHardwareKeyboard_3 extends _i1.Fake implements _i5.HardwareKeyboard { } -class _FakeRestorationManager_10 extends _i1.SmartFake - implements _i6.RestorationManager { - _FakeRestorationManager_10( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} +class _FakeKeyEventManager_4 extends _i1.Fake implements _i5.KeyEventManager {} -class _FakePointerRouter_11 extends _i1.SmartFake implements _i7.PointerRouter { - _FakePointerRouter_11( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} +class _FakeBinaryMessenger_5 extends _i1.Fake implements _i5.BinaryMessenger {} -class _FakeGestureArenaManager_12 extends _i1.SmartFake - implements _i7.GestureArenaManager { - _FakeGestureArenaManager_12( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} +class _FakeChannelBuffers_6 extends _i1.Fake implements _i4.ChannelBuffers {} -class _FakePointerSignalResolver_13 extends _i1.SmartFake - implements _i7.PointerSignalResolver { - _FakePointerSignalResolver_13( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} +class _FakeRestorationManager_7 extends _i1.Fake + implements _i5.RestorationManager {} -class _FakeSamplingClock_14 extends _i1.SmartFake implements _i7.SamplingClock { - _FakeSamplingClock_14( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} +class _FakeDuration_8 extends _i1.Fake implements Duration {} -class _FakeRenderView_15 extends _i1.SmartFake implements _i8.RenderView { - _FakeRenderView_15( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); +class _FakePointerRouter_9 extends _i1.Fake implements _i6.PointerRouter {} - @override - String toString({_i3.DiagnosticLevel? minLevel = _i3.DiagnosticLevel.info}) => - super.toString(); -} +class _FakeGestureArenaManager_10 extends _i1.Fake + implements _i6.GestureArenaManager {} -class _FakeMouseTracker_16 extends _i1.SmartFake implements _i8.MouseTracker { - _FakeMouseTracker_16( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} +class _FakePointerSignalResolver_11 extends _i1.Fake + implements _i6.PointerSignalResolver {} -class _FakeAccessibilityFeatures_17 extends _i1.SmartFake - implements _i5.AccessibilityFeatures { - _FakeAccessibilityFeatures_17( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} +class _FakeMouseTracker_12 extends _i1.Fake implements _i7.MouseTracker {} -class _FakeWidget_18 extends _i1.SmartFake implements _i9.Widget { - _FakeWidget_18( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); +class _FakePipelineOwner_13 extends _i1.Fake implements _i7.PipelineOwner {} +class _FakeRenderView_14 extends _i1.Fake implements _i7.RenderView { @override String toString({_i3.DiagnosticLevel? minLevel = _i3.DiagnosticLevel.info}) => super.toString(); } -class _FakeFuture_19 extends _i1.SmartFake implements _i10.Future { - _FakeFuture_19( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} +class _FakeAccessibilityFeatures_15 extends _i1.Fake + implements _i4.AccessibilityFeatures {} -class _FakeViewConfiguration_20 extends _i1.SmartFake - implements _i8.ViewConfiguration { - _FakeViewConfiguration_20( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} - -class _FakeSceneBuilder_21 extends _i1.SmartFake implements _i5.SceneBuilder { - _FakeSceneBuilder_21( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} +class _FakeViewConfiguration_16 extends _i1.Fake + implements _i7.ViewConfiguration {} -class _FakePictureRecorder_22 extends _i1.SmartFake - implements _i5.PictureRecorder { - _FakePictureRecorder_22( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} +class _FakeSemanticsUpdateBuilder_17 extends _i1.Fake + implements _i4.SemanticsUpdateBuilder {} -class _FakeCanvas_23 extends _i1.SmartFake implements _i5.Canvas { - _FakeCanvas_23( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} - -class _FakeSemanticsHandle_24 extends _i1.SmartFake - implements _i8.SemanticsHandle { - _FakeSemanticsHandle_24( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} - -class _FakeSemanticsUpdateBuilder_25 extends _i1.SmartFake - implements _i5.SemanticsUpdateBuilder { - _FakeSemanticsUpdateBuilder_25( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} - -/// A class which mocks [FrameTiming]. +/// A class which mocks [ApmHostApi]. /// /// See the documentation for Mockito's code generation for more information. -class MockFrameTiming extends _i1.Mock implements _i5.FrameTiming { - MockFrameTiming() { +class MockApmHostApi extends _i1.Mock implements _i8.ApmHostApi { + MockApmHostApi() { _i1.throwOnMissingStub(this); } @override - Duration get buildDuration => (super.noSuchMethod( - Invocation.getter(#buildDuration), - returnValue: _FakeDuration_0( - this, - Invocation.getter(#buildDuration), - ), - ) as Duration); + _i9.Future setEnabled(bool? arg_isEnabled) => + (super.noSuchMethod(Invocation.method(#setEnabled, [arg_isEnabled]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); @override - Duration get rasterDuration => (super.noSuchMethod( - Invocation.getter(#rasterDuration), - returnValue: _FakeDuration_0( - this, - Invocation.getter(#rasterDuration), - ), - ) as Duration); + _i9.Future isEnabled() => + (super.noSuchMethod(Invocation.method(#isEnabled, []), + returnValue: Future.value(false)) as _i9.Future); @override - Duration get vsyncOverhead => (super.noSuchMethod( - Invocation.getter(#vsyncOverhead), - returnValue: _FakeDuration_0( - this, - Invocation.getter(#vsyncOverhead), - ), - ) as Duration); + _i9.Future setScreenLoadingEnabled(bool? arg_isEnabled) => + (super.noSuchMethod( + Invocation.method(#setScreenLoadingEnabled, [arg_isEnabled]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); @override - Duration get totalSpan => (super.noSuchMethod( - Invocation.getter(#totalSpan), - returnValue: _FakeDuration_0( - this, - Invocation.getter(#totalSpan), - ), - ) as Duration); + _i9.Future isScreenLoadingEnabled() => + (super.noSuchMethod(Invocation.method(#isScreenLoadingEnabled, []), + returnValue: Future.value(false)) as _i9.Future); @override - int get layerCacheCount => (super.noSuchMethod( - Invocation.getter(#layerCacheCount), - returnValue: 0, - ) as int); + _i9.Future setColdAppLaunchEnabled(bool? arg_isEnabled) => + (super.noSuchMethod( + Invocation.method(#setColdAppLaunchEnabled, [arg_isEnabled]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); @override - int get layerCacheBytes => (super.noSuchMethod( - Invocation.getter(#layerCacheBytes), - returnValue: 0, - ) as int); + _i9.Future setAutoUITraceEnabled(bool? arg_isEnabled) => (super + .noSuchMethod(Invocation.method(#setAutoUITraceEnabled, [arg_isEnabled]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); @override - double get layerCacheMegabytes => (super.noSuchMethod( - Invocation.getter(#layerCacheMegabytes), - returnValue: 0.0, - ) as double); + _i9.Future startExecutionTrace(String? arg_id, String? arg_name) => + (super.noSuchMethod( + Invocation.method(#startExecutionTrace, [arg_id, arg_name]), + returnValue: Future.value()) as _i9.Future); @override - int get pictureCacheCount => (super.noSuchMethod( - Invocation.getter(#pictureCacheCount), - returnValue: 0, - ) as int); + _i9.Future startFlow(String? arg_name) => + (super.noSuchMethod(Invocation.method(#startFlow, [arg_name]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); @override - int get pictureCacheBytes => (super.noSuchMethod( - Invocation.getter(#pictureCacheBytes), - returnValue: 0, - ) as int); + _i9.Future setFlowAttribute( + String? arg_name, String? arg_key, String? arg_value) => + (super.noSuchMethod( + Invocation.method(#setFlowAttribute, [arg_name, arg_key, arg_value]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); @override - double get pictureCacheMegabytes => (super.noSuchMethod( - Invocation.getter(#pictureCacheMegabytes), - returnValue: 0.0, - ) as double); + _i9.Future endFlow(String? arg_name) => + (super.noSuchMethod(Invocation.method(#endFlow, [arg_name]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); @override - int get frameNumber => (super.noSuchMethod( - Invocation.getter(#frameNumber), - returnValue: 0, - ) as int); + _i9.Future setExecutionTraceAttribute( + String? arg_id, String? arg_key, String? arg_value) => + (super.noSuchMethod( + Invocation.method( + #setExecutionTraceAttribute, [arg_id, arg_key, arg_value]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); @override - int timestampInMicroseconds(_i5.FramePhase? phase) => (super.noSuchMethod( - Invocation.method( - #timestampInMicroseconds, - [phase], - ), - returnValue: 0, - ) as int); -} - -/// A class which mocks [ApmHostApi]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockApmHostApi extends _i1.Mock implements _i11.ApmHostApi { - MockApmHostApi() { - _i1.throwOnMissingStub(this); - } + _i9.Future endExecutionTrace(String? arg_id) => + (super.noSuchMethod(Invocation.method(#endExecutionTrace, [arg_id]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); @override - _i10.Future setEnabled(bool? arg_isEnabled) => (super.noSuchMethod( - Invocation.method( - #setEnabled, - [arg_isEnabled], - ), - returnValue: _i10.Future.value(), - returnValueForMissingStub: _i10.Future.value(), - ) as _i10.Future); + _i9.Future startUITrace(String? arg_name) => + (super.noSuchMethod(Invocation.method(#startUITrace, [arg_name]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); @override - _i10.Future isEnabled() => (super.noSuchMethod( - Invocation.method( - #isEnabled, - [], - ), - returnValue: _i10.Future.value(false), - ) as _i10.Future); + _i9.Future endUITrace() => + (super.noSuchMethod(Invocation.method(#endUITrace, []), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); @override - _i10.Future setScreenLoadingEnabled(bool? arg_isEnabled) => - (super.noSuchMethod( - Invocation.method( - #setScreenLoadingEnabled, - [arg_isEnabled], - ), - returnValue: _i10.Future.value(), - returnValueForMissingStub: _i10.Future.value(), - ) as _i10.Future); + _i9.Future endAppLaunch() => + (super.noSuchMethod(Invocation.method(#endAppLaunch, []), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); @override - _i10.Future isScreenLoadingEnabled() => (super.noSuchMethod( - Invocation.method( - #isScreenLoadingEnabled, - [], - ), - returnValue: _i10.Future.value(false), - ) as _i10.Future); + _i9.Future networkLogAndroid(Map? arg_data) => + (super.noSuchMethod(Invocation.method(#networkLogAndroid, [arg_data]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); @override - _i10.Future setColdAppLaunchEnabled(bool? arg_isEnabled) => + _i9.Future startCpUiTrace( + String? arg_screenName, int? arg_microTimeStamp, int? arg_traceId) => (super.noSuchMethod( - Invocation.method( - #setColdAppLaunchEnabled, - [arg_isEnabled], - ), - returnValue: _i10.Future.value(), - returnValueForMissingStub: _i10.Future.value(), - ) as _i10.Future); + Invocation.method(#startCpUiTrace, + [arg_screenName, arg_microTimeStamp, arg_traceId]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); @override - _i10.Future setAutoUITraceEnabled(bool? arg_isEnabled) => - (super.noSuchMethod( - Invocation.method( - #setAutoUITraceEnabled, - [arg_isEnabled], - ), - returnValue: _i10.Future.value(), - returnValueForMissingStub: _i10.Future.value(), - ) as _i10.Future); - - @override - _i10.Future startExecutionTrace( - String? arg_id, - String? arg_name, - ) => - (super.noSuchMethod( - Invocation.method( - #startExecutionTrace, - [ - arg_id, - arg_name, - ], - ), - returnValue: _i10.Future.value(), - ) as _i10.Future); - - @override - _i10.Future startFlow(String? arg_name) => (super.noSuchMethod( - Invocation.method( - #startFlow, - [arg_name], - ), - returnValue: _i10.Future.value(), - returnValueForMissingStub: _i10.Future.value(), - ) as _i10.Future); - - @override - _i10.Future setFlowAttribute( - String? arg_name, - String? arg_key, - String? arg_value, - ) => - (super.noSuchMethod( - Invocation.method( - #setFlowAttribute, - [ - arg_name, - arg_key, - arg_value, - ], - ), - returnValue: _i10.Future.value(), - returnValueForMissingStub: _i10.Future.value(), - ) as _i10.Future); - - @override - _i10.Future endFlow(String? arg_name) => (super.noSuchMethod( - Invocation.method( - #endFlow, - [arg_name], - ), - returnValue: _i10.Future.value(), - returnValueForMissingStub: _i10.Future.value(), - ) as _i10.Future); - - @override - _i10.Future setExecutionTraceAttribute( - String? arg_id, - String? arg_key, - String? arg_value, - ) => + _i9.Future reportScreenLoadingCP(int? arg_startTimeStampMicro, + int? arg_durationMicro, int? arg_uiTraceId) => (super.noSuchMethod( - Invocation.method( - #setExecutionTraceAttribute, - [ - arg_id, - arg_key, - arg_value, - ], - ), - returnValue: _i10.Future.value(), - returnValueForMissingStub: _i10.Future.value(), - ) as _i10.Future); - - @override - _i10.Future endExecutionTrace(String? arg_id) => (super.noSuchMethod( - Invocation.method( - #endExecutionTrace, - [arg_id], - ), - returnValue: _i10.Future.value(), - returnValueForMissingStub: _i10.Future.value(), - ) as _i10.Future); - - @override - _i10.Future startUITrace(String? arg_name) => (super.noSuchMethod( - Invocation.method( - #startUITrace, - [arg_name], - ), - returnValue: _i10.Future.value(), - returnValueForMissingStub: _i10.Future.value(), - ) as _i10.Future); - - @override - _i10.Future endUITrace() => (super.noSuchMethod( - Invocation.method( - #endUITrace, - [], - ), - returnValue: _i10.Future.value(), - returnValueForMissingStub: _i10.Future.value(), - ) as _i10.Future); - - @override - _i10.Future endAppLaunch() => (super.noSuchMethod( - Invocation.method( - #endAppLaunch, - [], - ), - returnValue: _i10.Future.value(), - returnValueForMissingStub: _i10.Future.value(), - ) as _i10.Future); - - @override - _i10.Future networkLogAndroid(Map? arg_data) => - (super.noSuchMethod( - Invocation.method( - #networkLogAndroid, - [arg_data], - ), - returnValue: _i10.Future.value(), - returnValueForMissingStub: _i10.Future.value(), - ) as _i10.Future); - - @override - _i10.Future startCpUiTrace( - String? arg_screenName, - int? arg_microTimeStamp, - int? arg_traceId, - ) => - (super.noSuchMethod( - Invocation.method( - #startCpUiTrace, - [ - arg_screenName, - arg_microTimeStamp, - arg_traceId, - ], - ), - returnValue: _i10.Future.value(), - returnValueForMissingStub: _i10.Future.value(), - ) as _i10.Future); - - @override - _i10.Future reportScreenLoadingCP( - int? arg_startTimeStampMicro, - int? arg_durationMicro, - int? arg_uiTraceId, - ) => - (super.noSuchMethod( - Invocation.method( - #reportScreenLoadingCP, - [ - arg_startTimeStampMicro, - arg_durationMicro, - arg_uiTraceId, - ], - ), - returnValue: _i10.Future.value(), - returnValueForMissingStub: _i10.Future.value(), - ) as _i10.Future); - - @override - _i10.Future endScreenLoadingCP( - int? arg_timeStampMicro, - int? arg_uiTraceId, - ) => - (super.noSuchMethod( - Invocation.method( - #endScreenLoadingCP, - [ - arg_timeStampMicro, - arg_uiTraceId, - ], - ), - returnValue: _i10.Future.value(), - returnValueForMissingStub: _i10.Future.value(), - ) as _i10.Future); - - @override - _i10.Future isEndScreenLoadingEnabled() => (super.noSuchMethod( - Invocation.method( - #isEndScreenLoadingEnabled, - [], - ), - returnValue: _i10.Future.value(false), - ) as _i10.Future); - - @override - _i10.Future isScreenRenderEnabled() => (super.noSuchMethod( - Invocation.method( - #isScreenRenderEnabled, - [], - ), - returnValue: _i10.Future.value(false), - ) as _i10.Future); - - @override - _i10.Future deviceRefreshRate() => (super.noSuchMethod( - Invocation.method( - #deviceRefreshRate, - [], - ), - returnValue: _i10.Future.value(0.0), - ) as _i10.Future); - - @override - _i10.Future setScreenRenderEnabled(bool? arg_isEnabled) => + Invocation.method(#reportScreenLoadingCP, + [arg_startTimeStampMicro, arg_durationMicro, arg_uiTraceId]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); + + @override + _i9.Future endScreenLoadingCP( + int? arg_timeStampMicro, int? arg_uiTraceId) => (super.noSuchMethod( - Invocation.method( - #setScreenRenderEnabled, - [arg_isEnabled], - ), - returnValue: _i10.Future.value(), - returnValueForMissingStub: _i10.Future.value(), - ) as _i10.Future); + Invocation.method( + #endScreenLoadingCP, [arg_timeStampMicro, arg_uiTraceId]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); + + @override + _i9.Future isEndScreenLoadingEnabled() => + (super.noSuchMethod(Invocation.method(#isEndScreenLoadingEnabled, []), + returnValue: Future.value(false)) as _i9.Future); + + @override + _i9.Future isScreenRenderEnabled() => + (super.noSuchMethod(Invocation.method(#isScreenRenderEnabled, []), + returnValue: Future.value(false)) as _i9.Future); + + @override + _i9.Future deviceRefreshRate() => + (super.noSuchMethod(Invocation.method(#deviceRefreshRate, []), + returnValue: Future.value(0.0)) as _i9.Future); + + @override + _i9.Future setScreenRenderEnabled(bool? arg_isEnabled) => (super + .noSuchMethod(Invocation.method(#setScreenRenderEnabled, [arg_isEnabled]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); } /// A class which mocks [WidgetsBinding]. /// /// See the documentation for Mockito's code generation for more information. -class MockWidgetsBinding extends _i1.Mock implements _i12.WidgetsBinding { +class MockWidgetsBinding extends _i1.Mock implements _i10.WidgetsBinding { MockWidgetsBinding() { _i1.throwOnMissingStub(this); } @override - _i2.PlatformMenuDelegate get platformMenuDelegate => (super.noSuchMethod( - Invocation.getter(#platformMenuDelegate), - returnValue: _FakePlatformMenuDelegate_1( - this, - Invocation.getter(#platformMenuDelegate), - ), - ) as _i2.PlatformMenuDelegate); + bool get debugBuildingDirtyElements => + (super.noSuchMethod(Invocation.getter(#debugBuildingDirtyElements), + returnValue: false) as bool); @override - set platformMenuDelegate(_i2.PlatformMenuDelegate? _platformMenuDelegate) => + set debugBuildingDirtyElements(bool? _debugBuildingDirtyElements) => super.noSuchMethod( - Invocation.setter( - #platformMenuDelegate, - _platformMenuDelegate, - ), - returnValueForMissingStub: null, - ); + Invocation.setter( + #debugBuildingDirtyElements, _debugBuildingDirtyElements), + returnValueForMissingStub: null); @override - bool get debugBuildingDirtyElements => (super.noSuchMethod( - Invocation.getter(#debugBuildingDirtyElements), - returnValue: false, - ) as bool); + _i2.FocusManager get focusManager => + (super.noSuchMethod(Invocation.getter(#focusManager), + returnValue: _FakeFocusManager_0()) as _i2.FocusManager); @override - set debugBuildingDirtyElements(bool? _debugBuildingDirtyElements) => - super.noSuchMethod( - Invocation.setter( - #debugBuildingDirtyElements, - _debugBuildingDirtyElements, - ), - returnValueForMissingStub: null, - ); + bool get firstFrameRasterized => + (super.noSuchMethod(Invocation.getter(#firstFrameRasterized), + returnValue: false) as bool); @override - bool get debugShowWidgetInspectorOverride => (super.noSuchMethod( - Invocation.getter(#debugShowWidgetInspectorOverride), - returnValue: false, - ) as bool); + _i9.Future get waitUntilFirstFrameRasterized => + (super.noSuchMethod(Invocation.getter(#waitUntilFirstFrameRasterized), + returnValue: Future.value()) as _i9.Future); @override - set debugShowWidgetInspectorOverride(bool? value) => super.noSuchMethod( - Invocation.setter( - #debugShowWidgetInspectorOverride, - value, - ), - returnValueForMissingStub: null, - ); + bool get debugDidSendFirstFrameEvent => + (super.noSuchMethod(Invocation.getter(#debugDidSendFirstFrameEvent), + returnValue: false) as bool); @override - _i3.ValueNotifier get debugShowWidgetInspectorOverrideNotifier => - (super.noSuchMethod( - Invocation.getter(#debugShowWidgetInspectorOverrideNotifier), - returnValue: _FakeValueNotifier_2( - this, - Invocation.getter(#debugShowWidgetInspectorOverrideNotifier), - ), - ) as _i3.ValueNotifier); + bool get framesEnabled => + (super.noSuchMethod(Invocation.getter(#framesEnabled), returnValue: false) + as bool); @override - _i3.ValueNotifier get debugWidgetInspectorSelectionOnTapEnabled => - (super.noSuchMethod( - Invocation.getter(#debugWidgetInspectorSelectionOnTapEnabled), - returnValue: _FakeValueNotifier_2( - this, - Invocation.getter(#debugWidgetInspectorSelectionOnTapEnabled), - ), - ) as _i3.ValueNotifier); + bool get isRootWidgetAttached => + (super.noSuchMethod(Invocation.getter(#isRootWidgetAttached), + returnValue: false) as bool); @override - _i4.FocusManager get focusManager => (super.noSuchMethod( - Invocation.getter(#focusManager), - returnValue: _FakeFocusManager_3( - this, - Invocation.getter(#focusManager), - ), - ) as _i4.FocusManager); + _i4.SingletonFlutterWindow get window => + (super.noSuchMethod(Invocation.getter(#window), + returnValue: _FakeSingletonFlutterWindow_1()) + as _i4.SingletonFlutterWindow); @override - bool get firstFrameRasterized => (super.noSuchMethod( - Invocation.getter(#firstFrameRasterized), - returnValue: false, - ) as bool); + _i4.PlatformDispatcher get platformDispatcher => + (super.noSuchMethod(Invocation.getter(#platformDispatcher), + returnValue: _FakePlatformDispatcher_2()) as _i4.PlatformDispatcher); @override - _i10.Future get waitUntilFirstFrameRasterized => (super.noSuchMethod( - Invocation.getter(#waitUntilFirstFrameRasterized), - returnValue: _i10.Future.value(), - ) as _i10.Future); + bool get locked => + (super.noSuchMethod(Invocation.getter(#locked), returnValue: false) + as bool); @override - bool get debugDidSendFirstFrameEvent => (super.noSuchMethod( - Invocation.getter(#debugDidSendFirstFrameEvent), - returnValue: false, - ) as bool); + _i5.HardwareKeyboard get keyboard => + (super.noSuchMethod(Invocation.getter(#keyboard), + returnValue: _FakeHardwareKeyboard_3()) as _i5.HardwareKeyboard); @override - bool get framesEnabled => (super.noSuchMethod( - Invocation.getter(#framesEnabled), - returnValue: false, - ) as bool); + _i5.KeyEventManager get keyEventManager => + (super.noSuchMethod(Invocation.getter(#keyEventManager), + returnValue: _FakeKeyEventManager_4()) as _i5.KeyEventManager); @override - bool get isRootWidgetAttached => (super.noSuchMethod( - Invocation.getter(#isRootWidgetAttached), - returnValue: false, - ) as bool); + _i5.BinaryMessenger get defaultBinaryMessenger => + (super.noSuchMethod(Invocation.getter(#defaultBinaryMessenger), + returnValue: _FakeBinaryMessenger_5()) as _i5.BinaryMessenger); @override - _i5.SingletonFlutterWindow get window => (super.noSuchMethod( - Invocation.getter(#window), - returnValue: _FakeSingletonFlutterWindow_4( - this, - Invocation.getter(#window), - ), - ) as _i5.SingletonFlutterWindow); + _i4.ChannelBuffers get channelBuffers => + (super.noSuchMethod(Invocation.getter(#channelBuffers), + returnValue: _FakeChannelBuffers_6()) as _i4.ChannelBuffers); @override - _i5.PlatformDispatcher get platformDispatcher => (super.noSuchMethod( - Invocation.getter(#platformDispatcher), - returnValue: _FakePlatformDispatcher_5( - this, - Invocation.getter(#platformDispatcher), - ), - ) as _i5.PlatformDispatcher); + _i5.RestorationManager get restorationManager => + (super.noSuchMethod(Invocation.getter(#restorationManager), + returnValue: _FakeRestorationManager_7()) as _i5.RestorationManager); @override - bool get locked => (super.noSuchMethod( - Invocation.getter(#locked), - returnValue: false, - ) as bool); + _i11.SchedulingStrategy get schedulingStrategy => + (super.noSuchMethod(Invocation.getter(#schedulingStrategy), + returnValue: ({int? priority, _i11.SchedulerBinding? scheduler}) => + false) as _i11.SchedulingStrategy); @override - _i3.ValueNotifier get accessibilityFocus => (super.noSuchMethod( - Invocation.getter(#accessibilityFocus), - returnValue: _FakeValueNotifier_2( - this, - Invocation.getter(#accessibilityFocus), - ), - ) as _i3.ValueNotifier); + set schedulingStrategy(_i11.SchedulingStrategy? _schedulingStrategy) => super + .noSuchMethod(Invocation.setter(#schedulingStrategy, _schedulingStrategy), + returnValueForMissingStub: null); @override - _i6.HardwareKeyboard get keyboard => (super.noSuchMethod( - Invocation.getter(#keyboard), - returnValue: _FakeHardwareKeyboard_6( - this, - Invocation.getter(#keyboard), - ), - ) as _i6.HardwareKeyboard); + int get transientCallbackCount => + (super.noSuchMethod(Invocation.getter(#transientCallbackCount), + returnValue: 0) as int); @override - _i6.KeyEventManager get keyEventManager => (super.noSuchMethod( - Invocation.getter(#keyEventManager), - returnValue: _FakeKeyEventManager_7( - this, - Invocation.getter(#keyEventManager), - ), - ) as _i6.KeyEventManager); + _i9.Future get endOfFrame => + (super.noSuchMethod(Invocation.getter(#endOfFrame), + returnValue: Future.value()) as _i9.Future); @override - _i6.BinaryMessenger get defaultBinaryMessenger => (super.noSuchMethod( - Invocation.getter(#defaultBinaryMessenger), - returnValue: _FakeBinaryMessenger_8( - this, - Invocation.getter(#defaultBinaryMessenger), - ), - ) as _i6.BinaryMessenger); + bool get hasScheduledFrame => + (super.noSuchMethod(Invocation.getter(#hasScheduledFrame), + returnValue: false) as bool); @override - _i5.ChannelBuffers get channelBuffers => (super.noSuchMethod( - Invocation.getter(#channelBuffers), - returnValue: _FakeChannelBuffers_9( - this, - Invocation.getter(#channelBuffers), - ), - ) as _i5.ChannelBuffers); + _i11.SchedulerPhase get schedulerPhase => + (super.noSuchMethod(Invocation.getter(#schedulerPhase), + returnValue: _i11.SchedulerPhase.idle) as _i11.SchedulerPhase); @override - _i6.RestorationManager get restorationManager => (super.noSuchMethod( - Invocation.getter(#restorationManager), - returnValue: _FakeRestorationManager_10( - this, - Invocation.getter(#restorationManager), - ), - ) as _i6.RestorationManager); + Duration get currentFrameTimeStamp => + (super.noSuchMethod(Invocation.getter(#currentFrameTimeStamp), + returnValue: _FakeDuration_8()) as Duration); @override - _i13.SchedulingStrategy get schedulingStrategy => (super.noSuchMethod( - Invocation.getter(#schedulingStrategy), - returnValue: ({ - required int priority, - required _i13.SchedulerBinding scheduler, - }) => - false, - ) as _i13.SchedulingStrategy); + Duration get currentSystemFrameTimeStamp => + (super.noSuchMethod(Invocation.getter(#currentSystemFrameTimeStamp), + returnValue: _FakeDuration_8()) as Duration); @override - set schedulingStrategy(_i13.SchedulingStrategy? _schedulingStrategy) => - super.noSuchMethod( - Invocation.setter( - #schedulingStrategy, - _schedulingStrategy, - ), - returnValueForMissingStub: null, - ); + _i6.PointerRouter get pointerRouter => + (super.noSuchMethod(Invocation.getter(#pointerRouter), + returnValue: _FakePointerRouter_9()) as _i6.PointerRouter); @override - int get transientCallbackCount => (super.noSuchMethod( - Invocation.getter(#transientCallbackCount), - returnValue: 0, - ) as int); + _i6.GestureArenaManager get gestureArena => (super.noSuchMethod( + Invocation.getter(#gestureArena), + returnValue: _FakeGestureArenaManager_10()) as _i6.GestureArenaManager); @override - _i10.Future get endOfFrame => (super.noSuchMethod( - Invocation.getter(#endOfFrame), - returnValue: _i10.Future.value(), - ) as _i10.Future); + _i6.PointerSignalResolver get pointerSignalResolver => + (super.noSuchMethod(Invocation.getter(#pointerSignalResolver), + returnValue: _FakePointerSignalResolver_11()) + as _i6.PointerSignalResolver); @override - bool get hasScheduledFrame => (super.noSuchMethod( - Invocation.getter(#hasScheduledFrame), - returnValue: false, - ) as bool); + bool get resamplingEnabled => + (super.noSuchMethod(Invocation.getter(#resamplingEnabled), + returnValue: false) as bool); @override - _i13.SchedulerPhase get schedulerPhase => (super.noSuchMethod( - Invocation.getter(#schedulerPhase), - returnValue: _i13.SchedulerPhase.idle, - ) as _i13.SchedulerPhase); + set resamplingEnabled(bool? _resamplingEnabled) => super.noSuchMethod( + Invocation.setter(#resamplingEnabled, _resamplingEnabled), + returnValueForMissingStub: null); @override - Duration get currentFrameTimeStamp => (super.noSuchMethod( - Invocation.getter(#currentFrameTimeStamp), - returnValue: _FakeDuration_0( - this, - Invocation.getter(#currentFrameTimeStamp), - ), - ) as Duration); + Duration get samplingOffset => + (super.noSuchMethod(Invocation.getter(#samplingOffset), + returnValue: _FakeDuration_8()) as Duration); @override - Duration get currentSystemFrameTimeStamp => (super.noSuchMethod( - Invocation.getter(#currentSystemFrameTimeStamp), - returnValue: _FakeDuration_0( - this, - Invocation.getter(#currentSystemFrameTimeStamp), - ), - ) as Duration); + set samplingOffset(Duration? _samplingOffset) => + super.noSuchMethod(Invocation.setter(#samplingOffset, _samplingOffset), + returnValueForMissingStub: null); @override - _i7.PointerRouter get pointerRouter => (super.noSuchMethod( - Invocation.getter(#pointerRouter), - returnValue: _FakePointerRouter_11( - this, - Invocation.getter(#pointerRouter), - ), - ) as _i7.PointerRouter); + _i7.MouseTracker get mouseTracker => + (super.noSuchMethod(Invocation.getter(#mouseTracker), + returnValue: _FakeMouseTracker_12()) as _i7.MouseTracker); @override - _i7.GestureArenaManager get gestureArena => (super.noSuchMethod( - Invocation.getter(#gestureArena), - returnValue: _FakeGestureArenaManager_12( - this, - Invocation.getter(#gestureArena), - ), - ) as _i7.GestureArenaManager); + _i7.PipelineOwner get pipelineOwner => + (super.noSuchMethod(Invocation.getter(#pipelineOwner), + returnValue: _FakePipelineOwner_13()) as _i7.PipelineOwner); @override - _i7.PointerSignalResolver get pointerSignalResolver => (super.noSuchMethod( - Invocation.getter(#pointerSignalResolver), - returnValue: _FakePointerSignalResolver_13( - this, - Invocation.getter(#pointerSignalResolver), - ), - ) as _i7.PointerSignalResolver); + _i7.RenderView get renderView => + (super.noSuchMethod(Invocation.getter(#renderView), + returnValue: _FakeRenderView_14()) as _i7.RenderView); @override - bool get resamplingEnabled => (super.noSuchMethod( - Invocation.getter(#resamplingEnabled), - returnValue: false, - ) as bool); + set renderView(_i7.RenderView? value) => + super.noSuchMethod(Invocation.setter(#renderView, value), + returnValueForMissingStub: null); @override - set resamplingEnabled(bool? _resamplingEnabled) => super.noSuchMethod( - Invocation.setter( - #resamplingEnabled, - _resamplingEnabled, - ), - returnValueForMissingStub: null, - ); - - @override - Duration get samplingOffset => (super.noSuchMethod( - Invocation.getter(#samplingOffset), - returnValue: _FakeDuration_0( - this, - Invocation.getter(#samplingOffset), - ), - ) as Duration); - - @override - set samplingOffset(Duration? _samplingOffset) => super.noSuchMethod( - Invocation.setter( - #samplingOffset, - _samplingOffset, - ), - returnValueForMissingStub: null, - ); - - @override - _i7.SamplingClock get samplingClock => (super.noSuchMethod( - Invocation.getter(#samplingClock), - returnValue: _FakeSamplingClock_14( - this, - Invocation.getter(#samplingClock), - ), - ) as _i7.SamplingClock); - - @override - _i8.PipelineOwner get pipelineOwner => (super.noSuchMethod( - Invocation.getter(#pipelineOwner), - returnValue: _i14.dummyValue<_i8.PipelineOwner>( - this, - Invocation.getter(#pipelineOwner), - ), - ) as _i8.PipelineOwner); - - @override - _i8.RenderView get renderView => (super.noSuchMethod( - Invocation.getter(#renderView), - returnValue: _FakeRenderView_15( - this, - Invocation.getter(#renderView), - ), - ) as _i8.RenderView); + bool get sendFramesToEngine => + (super.noSuchMethod(Invocation.getter(#sendFramesToEngine), + returnValue: false) as bool); @override - _i8.MouseTracker get mouseTracker => (super.noSuchMethod( - Invocation.getter(#mouseTracker), - returnValue: _FakeMouseTracker_16( - this, - Invocation.getter(#mouseTracker), - ), - ) as _i8.MouseTracker); + _i4.AccessibilityFeatures get accessibilityFeatures => + (super.noSuchMethod(Invocation.getter(#accessibilityFeatures), + returnValue: _FakeAccessibilityFeatures_15()) + as _i4.AccessibilityFeatures); @override - _i8.PipelineOwner get rootPipelineOwner => (super.noSuchMethod( - Invocation.getter(#rootPipelineOwner), - returnValue: _i14.dummyValue<_i8.PipelineOwner>( - this, - Invocation.getter(#rootPipelineOwner), - ), - ) as _i8.PipelineOwner); + bool get disableAnimations => + (super.noSuchMethod(Invocation.getter(#disableAnimations), + returnValue: false) as bool); @override - Iterable<_i8.RenderView> get renderViews => (super.noSuchMethod( - Invocation.getter(#renderViews), - returnValue: <_i8.RenderView>[], - ) as Iterable<_i8.RenderView>); + void initInstances() => + super.noSuchMethod(Invocation.method(#initInstances, []), + returnValueForMissingStub: null); @override - bool get sendFramesToEngine => (super.noSuchMethod( - Invocation.getter(#sendFramesToEngine), - returnValue: false, - ) as bool); + void initServiceExtensions() => + super.noSuchMethod(Invocation.method(#initServiceExtensions, []), + returnValueForMissingStub: null); @override - bool get semanticsEnabled => (super.noSuchMethod( - Invocation.getter(#semanticsEnabled), - returnValue: false, - ) as bool); + void addObserver(_i10.WidgetsBindingObserver? observer) => + super.noSuchMethod(Invocation.method(#addObserver, [observer]), + returnValueForMissingStub: null); @override - int get debugOutstandingSemanticsHandles => (super.noSuchMethod( - Invocation.getter(#debugOutstandingSemanticsHandles), - returnValue: 0, - ) as int); + bool removeObserver(_i10.WidgetsBindingObserver? observer) => + (super.noSuchMethod(Invocation.method(#removeObserver, [observer]), + returnValue: false) as bool); @override - _i5.AccessibilityFeatures get accessibilityFeatures => (super.noSuchMethod( - Invocation.getter(#accessibilityFeatures), - returnValue: _FakeAccessibilityFeatures_17( - this, - Invocation.getter(#accessibilityFeatures), - ), - ) as _i5.AccessibilityFeatures); + void handleMetricsChanged() => + super.noSuchMethod(Invocation.method(#handleMetricsChanged, []), + returnValueForMissingStub: null); @override - bool get disableAnimations => (super.noSuchMethod( - Invocation.getter(#disableAnimations), - returnValue: false, - ) as bool); + void handleTextScaleFactorChanged() => + super.noSuchMethod(Invocation.method(#handleTextScaleFactorChanged, []), + returnValueForMissingStub: null); @override - void initInstances() => super.noSuchMethod( - Invocation.method( - #initInstances, - [], - ), - returnValueForMissingStub: null, - ); + void handlePlatformBrightnessChanged() => super.noSuchMethod( + Invocation.method(#handlePlatformBrightnessChanged, []), + returnValueForMissingStub: null); @override - void resetInternalState() => super.noSuchMethod( - Invocation.method( - #resetInternalState, - [], - ), - returnValueForMissingStub: null, - ); + void handleAccessibilityFeaturesChanged() => super.noSuchMethod( + Invocation.method(#handleAccessibilityFeaturesChanged, []), + returnValueForMissingStub: null); @override - void initServiceExtensions() => super.noSuchMethod( - Invocation.method( - #initServiceExtensions, - [], - ), - returnValueForMissingStub: null, - ); + void handleLocaleChanged() => + super.noSuchMethod(Invocation.method(#handleLocaleChanged, []), + returnValueForMissingStub: null); @override - void addObserver(_i12.WidgetsBindingObserver? observer) => super.noSuchMethod( - Invocation.method( - #addObserver, - [observer], - ), - returnValueForMissingStub: null, - ); + void dispatchLocalesChanged(List<_i4.Locale>? locales) => + super.noSuchMethod(Invocation.method(#dispatchLocalesChanged, [locales]), + returnValueForMissingStub: null); @override - bool removeObserver(_i12.WidgetsBindingObserver? observer) => - (super.noSuchMethod( - Invocation.method( - #removeObserver, - [observer], - ), - returnValue: false, - ) as bool); + void dispatchAccessibilityFeaturesChanged() => super.noSuchMethod( + Invocation.method(#dispatchAccessibilityFeaturesChanged, []), + returnValueForMissingStub: null); @override - _i10.Future<_i5.AppExitResponse> handleRequestAppExit() => - (super.noSuchMethod( - Invocation.method( - #handleRequestAppExit, - [], - ), - returnValue: - _i10.Future<_i5.AppExitResponse>.value(_i5.AppExitResponse.exit), - ) as _i10.Future<_i5.AppExitResponse>); + _i9.Future handlePopRoute() => + (super.noSuchMethod(Invocation.method(#handlePopRoute, []), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); @override - void handleMetricsChanged() => super.noSuchMethod( - Invocation.method( - #handleMetricsChanged, - [], - ), - returnValueForMissingStub: null, - ); + _i9.Future handlePushRoute(String? route) => + (super.noSuchMethod(Invocation.method(#handlePushRoute, [route]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); @override - void handleTextScaleFactorChanged() => super.noSuchMethod( - Invocation.method( - #handleTextScaleFactorChanged, - [], - ), - returnValueForMissingStub: null, - ); + void handleAppLifecycleStateChanged(_i4.AppLifecycleState? state) => super + .noSuchMethod(Invocation.method(#handleAppLifecycleStateChanged, [state]), + returnValueForMissingStub: null); @override - void handlePlatformBrightnessChanged() => super.noSuchMethod( - Invocation.method( - #handlePlatformBrightnessChanged, - [], - ), - returnValueForMissingStub: null, - ); + void handleMemoryPressure() => + super.noSuchMethod(Invocation.method(#handleMemoryPressure, []), + returnValueForMissingStub: null); @override - void handleAccessibilityFeaturesChanged() => super.noSuchMethod( - Invocation.method( - #handleAccessibilityFeaturesChanged, - [], - ), - returnValueForMissingStub: null, - ); + void drawFrame() => super.noSuchMethod(Invocation.method(#drawFrame, []), + returnValueForMissingStub: null); @override - void handleLocaleChanged() => super.noSuchMethod( - Invocation.method( - #handleLocaleChanged, - [], - ), - returnValueForMissingStub: null, - ); + void scheduleAttachRootWidget(_i12.Widget? rootWidget) => super.noSuchMethod( + Invocation.method(#scheduleAttachRootWidget, [rootWidget]), + returnValueForMissingStub: null); @override - void dispatchLocalesChanged(List<_i5.Locale>? locales) => super.noSuchMethod( - Invocation.method( - #dispatchLocalesChanged, - [locales], - ), - returnValueForMissingStub: null, - ); + void attachRootWidget(_i12.Widget? rootWidget) => + super.noSuchMethod(Invocation.method(#attachRootWidget, [rootWidget]), + returnValueForMissingStub: null); @override - void dispatchAccessibilityFeaturesChanged() => super.noSuchMethod( - Invocation.method( - #dispatchAccessibilityFeaturesChanged, - [], - ), - returnValueForMissingStub: null, - ); + _i9.Future performReassemble() => + (super.noSuchMethod(Invocation.method(#performReassemble, []), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); @override - _i10.Future handlePopRoute() => (super.noSuchMethod( - Invocation.method( - #handlePopRoute, - [], - ), - returnValue: _i10.Future.value(false), - ) as _i10.Future); + _i4.Locale? computePlatformResolvedLocale( + List<_i4.Locale>? supportedLocales) => + (super.noSuchMethod(Invocation.method( + #computePlatformResolvedLocale, [supportedLocales])) as _i4.Locale?); @override - _i10.Future handlePushRoute(String? route) => (super.noSuchMethod( - Invocation.method( - #handlePushRoute, - [route], - ), - returnValue: _i10.Future.value(false), - ) as _i10.Future); + _i9.Future lockEvents(_i9.Future Function()? callback) => + (super.noSuchMethod(Invocation.method(#lockEvents, [callback]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); @override - void handleAppLifecycleStateChanged(_i5.AppLifecycleState? state) => - super.noSuchMethod( - Invocation.method( - #handleAppLifecycleStateChanged, - [state], - ), - returnValueForMissingStub: null, - ); - - @override - void handleViewFocusChanged(_i5.ViewFocusEvent? event) => super.noSuchMethod( - Invocation.method( - #handleViewFocusChanged, - [event], - ), - returnValueForMissingStub: null, - ); - - @override - void handleMemoryPressure() => super.noSuchMethod( - Invocation.method( - #handleMemoryPressure, - [], - ), - returnValueForMissingStub: null, - ); - - @override - void drawFrame() => super.noSuchMethod( - Invocation.method( - #drawFrame, - [], - ), - returnValueForMissingStub: null, - ); - - @override - _i9.Widget wrapWithDefaultView(_i9.Widget? rootWidget) => (super.noSuchMethod( - Invocation.method( - #wrapWithDefaultView, - [rootWidget], - ), - returnValue: _FakeWidget_18( - this, - Invocation.method( - #wrapWithDefaultView, - [rootWidget], - ), - ), - ) as _i9.Widget); - - @override - void scheduleAttachRootWidget(_i9.Widget? rootWidget) => super.noSuchMethod( - Invocation.method( - #scheduleAttachRootWidget, - [rootWidget], - ), - returnValueForMissingStub: null, - ); - - @override - void attachRootWidget(_i9.Widget? rootWidget) => super.noSuchMethod( - Invocation.method( - #attachRootWidget, - [rootWidget], - ), - returnValueForMissingStub: null, - ); - - @override - void attachToBuildOwner(_i12.RootWidget? widget) => super.noSuchMethod( - Invocation.method( - #attachToBuildOwner, - [widget], - ), - returnValueForMissingStub: null, - ); - - @override - _i10.Future performReassemble() => (super.noSuchMethod( - Invocation.method( - #performReassemble, - [], - ), - returnValue: _i10.Future.value(), - returnValueForMissingStub: _i10.Future.value(), - ) as _i10.Future); - - @override - _i5.Locale? computePlatformResolvedLocale( - List<_i5.Locale>? supportedLocales) => - (super.noSuchMethod(Invocation.method( - #computePlatformResolvedLocale, - [supportedLocales], - )) as _i5.Locale?); + void unlocked() => super.noSuchMethod(Invocation.method(#unlocked, []), + returnValueForMissingStub: null); @override - bool debugCheckZone(String? entryPoint) => (super.noSuchMethod( - Invocation.method( - #debugCheckZone, - [entryPoint], - ), - returnValue: false, - ) as bool); + _i9.Future reassembleApplication() => + (super.noSuchMethod(Invocation.method(#reassembleApplication, []), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); @override - _i10.Future lockEvents(_i10.Future Function()? callback) => - (super.noSuchMethod( - Invocation.method( - #lockEvents, - [callback], - ), - returnValue: _i10.Future.value(), - returnValueForMissingStub: _i10.Future.value(), - ) as _i10.Future); - - @override - void unlocked() => super.noSuchMethod( - Invocation.method( - #unlocked, - [], - ), - returnValueForMissingStub: null, - ); - - @override - _i10.Future reassembleApplication() => (super.noSuchMethod( - Invocation.method( - #reassembleApplication, - [], - ), - returnValue: _i10.Future.value(), - returnValueForMissingStub: _i10.Future.value(), - ) as _i10.Future); - - @override - void registerSignalServiceExtension({ - required String? name, - required _i3.AsyncCallback? callback, - }) => - super.noSuchMethod( - Invocation.method( - #registerSignalServiceExtension, - [], - { - #name: name, - #callback: callback, - }, - ), - returnValueForMissingStub: null, - ); - - @override - void registerBoolServiceExtension({ - required String? name, - required _i3.AsyncValueGetter? getter, - required _i3.AsyncValueSetter? setter, - }) => + void registerSignalServiceExtension( + {String? name, _i3.AsyncCallback? callback}) => super.noSuchMethod( - Invocation.method( - #registerBoolServiceExtension, - [], - { - #name: name, - #getter: getter, - #setter: setter, - }, - ), - returnValueForMissingStub: null, - ); - - @override - void registerNumericServiceExtension({ - required String? name, - required _i3.AsyncValueGetter? getter, - required _i3.AsyncValueSetter? setter, - }) => + Invocation.method(#registerSignalServiceExtension, [], + {#name: name, #callback: callback}), + returnValueForMissingStub: null); + + @override + void registerBoolServiceExtension( + {String? name, + _i3.AsyncValueGetter? getter, + _i3.AsyncValueSetter? setter}) => super.noSuchMethod( - Invocation.method( - #registerNumericServiceExtension, - [], - { - #name: name, - #getter: getter, - #setter: setter, - }, - ), - returnValueForMissingStub: null, - ); - - @override - void postEvent( - String? eventKind, - Map? eventData, - ) => + Invocation.method(#registerBoolServiceExtension, [], + {#name: name, #getter: getter, #setter: setter}), + returnValueForMissingStub: null); + + @override + void registerNumericServiceExtension( + {String? name, + _i3.AsyncValueGetter? getter, + _i3.AsyncValueSetter? setter}) => super.noSuchMethod( - Invocation.method( - #postEvent, - [ - eventKind, - eventData, - ], - ), - returnValueForMissingStub: null, - ); - - @override - void registerStringServiceExtension({ - required String? name, - required _i3.AsyncValueGetter? getter, - required _i3.AsyncValueSetter? setter, - }) => + Invocation.method(#registerNumericServiceExtension, [], + {#name: name, #getter: getter, #setter: setter}), + returnValueForMissingStub: null); + + @override + void postEvent(String? eventKind, Map? eventData) => + super.noSuchMethod(Invocation.method(#postEvent, [eventKind, eventData]), + returnValueForMissingStub: null); + + @override + void registerStringServiceExtension( + {String? name, + _i3.AsyncValueGetter? getter, + _i3.AsyncValueSetter? setter}) => super.noSuchMethod( - Invocation.method( - #registerStringServiceExtension, - [], - { - #name: name, - #getter: getter, - #setter: setter, - }, - ), - returnValueForMissingStub: null, - ); - - @override - void registerServiceExtension({ - required String? name, - required _i3.ServiceExtensionCallback? callback, - }) => + Invocation.method(#registerStringServiceExtension, [], + {#name: name, #getter: getter, #setter: setter}), + returnValueForMissingStub: null); + + @override + void registerServiceExtension( + {String? name, _i3.ServiceExtensionCallback? callback}) => super.noSuchMethod( - Invocation.method( - #registerServiceExtension, - [], - { - #name: name, - #callback: callback, - }, - ), - returnValueForMissingStub: null, - ); - - @override - _i6.BinaryMessenger createBinaryMessenger() => (super.noSuchMethod( - Invocation.method( - #createBinaryMessenger, - [], - ), - returnValue: _FakeBinaryMessenger_8( - this, - Invocation.method( - #createBinaryMessenger, - [], - ), - ), - ) as _i6.BinaryMessenger); + Invocation.method(#registerServiceExtension, [], + {#name: name, #callback: callback}), + returnValueForMissingStub: null); @override - _i10.Future handleSystemMessage(Object? systemMessage) => - (super.noSuchMethod( - Invocation.method( - #handleSystemMessage, - [systemMessage], - ), - returnValue: _i10.Future.value(), - returnValueForMissingStub: _i10.Future.value(), - ) as _i10.Future); + _i5.BinaryMessenger createBinaryMessenger() => + (super.noSuchMethod(Invocation.method(#createBinaryMessenger, []), + returnValue: _FakeBinaryMessenger_5()) as _i5.BinaryMessenger); @override - void initLicenses() => super.noSuchMethod( - Invocation.method( - #initLicenses, - [], - ), - returnValueForMissingStub: null, - ); + _i9.Future handleSystemMessage(Object? systemMessage) => (super + .noSuchMethod(Invocation.method(#handleSystemMessage, [systemMessage]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); @override - void evict(String? asset) => super.noSuchMethod( - Invocation.method( - #evict, - [asset], - ), - returnValueForMissingStub: null, - ); + void initLicenses() => + super.noSuchMethod(Invocation.method(#initLicenses, []), + returnValueForMissingStub: null); + + @override + void evict(String? asset) => + super.noSuchMethod(Invocation.method(#evict, [asset]), + returnValueForMissingStub: null); @override void readInitialLifecycleStateFromNativeWindow() => super.noSuchMethod( - Invocation.method( - #readInitialLifecycleStateFromNativeWindow, - [], - ), - returnValueForMissingStub: null, - ); - - @override - _i10.Future<_i5.AppExitResponse> exitApplication( - _i5.AppExitType? exitType, [ - int? exitCode = 0, - ]) => - (super.noSuchMethod( - Invocation.method( - #exitApplication, - [ - exitType, - exitCode, - ], - ), - returnValue: - _i10.Future<_i5.AppExitResponse>.value(_i5.AppExitResponse.exit), - ) as _i10.Future<_i5.AppExitResponse>); - - @override - _i6.RestorationManager createRestorationManager() => (super.noSuchMethod( - Invocation.method( - #createRestorationManager, - [], - ), - returnValue: _FakeRestorationManager_10( - this, - Invocation.method( - #createRestorationManager, - [], - ), - ), - ) as _i6.RestorationManager); + Invocation.method(#readInitialLifecycleStateFromNativeWindow, []), + returnValueForMissingStub: null); @override - void setSystemUiChangeCallback(_i6.SystemUiChangeCallback? callback) => - super.noSuchMethod( - Invocation.method( - #setSystemUiChangeCallback, - [callback], - ), - returnValueForMissingStub: null, - ); - - @override - _i10.Future initializationComplete() => (super.noSuchMethod( - Invocation.method( - #initializationComplete, - [], - ), - returnValue: _i10.Future.value(), - returnValueForMissingStub: _i10.Future.value(), - ) as _i10.Future); - - @override - void addTimingsCallback(_i5.TimingsCallback? callback) => super.noSuchMethod( - Invocation.method( - #addTimingsCallback, - [callback], - ), - returnValueForMissingStub: null, - ); - - @override - void removeTimingsCallback(_i5.TimingsCallback? callback) => - super.noSuchMethod( - Invocation.method( - #removeTimingsCallback, - [callback], - ), - returnValueForMissingStub: null, - ); - - @override - _i10.Future scheduleTask( - _i13.TaskCallback? task, - _i13.Priority? priority, { - String? debugLabel, - _i15.Flow? flow, - }) => + _i5.RestorationManager createRestorationManager() => + (super.noSuchMethod(Invocation.method(#createRestorationManager, []), + returnValue: _FakeRestorationManager_7()) as _i5.RestorationManager); + + @override + void setSystemUiChangeCallback(_i5.SystemUiChangeCallback? callback) => super + .noSuchMethod(Invocation.method(#setSystemUiChangeCallback, [callback]), + returnValueForMissingStub: null); + + @override + void addTimingsCallback(_i4.TimingsCallback? callback) => + super.noSuchMethod(Invocation.method(#addTimingsCallback, [callback]), + returnValueForMissingStub: null); + + @override + void removeTimingsCallback(_i4.TimingsCallback? callback) => + super.noSuchMethod(Invocation.method(#removeTimingsCallback, [callback]), + returnValueForMissingStub: null); + + @override + _i9.Future scheduleTask( + _i11.TaskCallback? task, _i11.Priority? priority, + {String? debugLabel, _i13.Flow? flow}) => (super.noSuchMethod( - Invocation.method( - #scheduleTask, - [ - task, - priority, - ], - { - #debugLabel: debugLabel, - #flow: flow, - }, - ), - returnValue: _i14.ifNotNull( - _i14.dummyValueOrNull( - this, - Invocation.method( - #scheduleTask, - [ - task, - priority, - ], - { - #debugLabel: debugLabel, - #flow: flow, - }, - ), - ), - (T v) => _i10.Future.value(v), - ) ?? - _FakeFuture_19( - this, - Invocation.method( - #scheduleTask, - [ - task, - priority, - ], - { - #debugLabel: debugLabel, - #flow: flow, - }, - ), - ), - ) as _i10.Future); - - @override - bool handleEventLoopCallback() => (super.noSuchMethod( - Invocation.method( - #handleEventLoopCallback, - [], - ), - returnValue: false, - ) as bool); - - @override - int scheduleFrameCallback( - _i13.FrameCallback? callback, { - bool? rescheduling = false, - bool? scheduleNewFrame = true, - }) => + Invocation.method(#scheduleTask, [task, priority], + {#debugLabel: debugLabel, #flow: flow}), + returnValue: Future.value(null)) as _i9.Future); + + @override + bool handleEventLoopCallback() => + (super.noSuchMethod(Invocation.method(#handleEventLoopCallback, []), + returnValue: false) as bool); + + @override + int scheduleFrameCallback(_i11.FrameCallback? callback, + {bool? rescheduling = false}) => (super.noSuchMethod( - Invocation.method( - #scheduleFrameCallback, - [callback], - { - #rescheduling: rescheduling, - #scheduleNewFrame: scheduleNewFrame, - }, - ), - returnValue: 0, - ) as int); - - @override - void cancelFrameCallbackWithId(int? id) => super.noSuchMethod( - Invocation.method( - #cancelFrameCallbackWithId, - [id], - ), - returnValueForMissingStub: null, - ); + Invocation.method(#scheduleFrameCallback, [callback], + {#rescheduling: rescheduling}), + returnValue: 0) as int); + + @override + void cancelFrameCallbackWithId(int? id) => + super.noSuchMethod(Invocation.method(#cancelFrameCallbackWithId, [id]), + returnValueForMissingStub: null); @override bool debugAssertNoTransientCallbacks(String? reason) => (super.noSuchMethod( - Invocation.method( - #debugAssertNoTransientCallbacks, - [reason], - ), - returnValue: false, - ) as bool); + Invocation.method(#debugAssertNoTransientCallbacks, [reason]), + returnValue: false) as bool); @override - bool debugAssertNoPendingPerformanceModeRequests(String? reason) => - (super.noSuchMethod( - Invocation.method( - #debugAssertNoPendingPerformanceModeRequests, - [reason], - ), - returnValue: false, - ) as bool); + void addPersistentFrameCallback(_i11.FrameCallback? callback) => super + .noSuchMethod(Invocation.method(#addPersistentFrameCallback, [callback]), + returnValueForMissingStub: null); @override - bool debugAssertNoTimeDilation(String? reason) => (super.noSuchMethod( - Invocation.method( - #debugAssertNoTimeDilation, - [reason], - ), - returnValue: false, - ) as bool); + void addPostFrameCallback(_i11.FrameCallback? callback) => + super.noSuchMethod(Invocation.method(#addPostFrameCallback, [callback]), + returnValueForMissingStub: null); @override - void addPersistentFrameCallback(_i13.FrameCallback? callback) => - super.noSuchMethod( - Invocation.method( - #addPersistentFrameCallback, - [callback], - ), - returnValueForMissingStub: null, - ); - - @override - void addPostFrameCallback( - _i13.FrameCallback? callback, { - String? debugLabel = r'callback', - }) => - super.noSuchMethod( - Invocation.method( - #addPostFrameCallback, - [callback], - {#debugLabel: debugLabel}, - ), - returnValueForMissingStub: null, - ); - - @override - void ensureFrameCallbacksRegistered() => super.noSuchMethod( - Invocation.method( - #ensureFrameCallbacksRegistered, - [], - ), - returnValueForMissingStub: null, - ); - - @override - void ensureVisualUpdate() => super.noSuchMethod( - Invocation.method( - #ensureVisualUpdate, - [], - ), - returnValueForMissingStub: null, - ); - - @override - void scheduleFrame() => super.noSuchMethod( - Invocation.method( - #scheduleFrame, - [], - ), - returnValueForMissingStub: null, - ); - - @override - void scheduleForcedFrame() => super.noSuchMethod( - Invocation.method( - #scheduleForcedFrame, - [], - ), - returnValueForMissingStub: null, - ); - - @override - void scheduleWarmUpFrame() => super.noSuchMethod( - Invocation.method( - #scheduleWarmUpFrame, - [], - ), - returnValueForMissingStub: null, - ); - - @override - void resetEpoch() => super.noSuchMethod( - Invocation.method( - #resetEpoch, - [], - ), - returnValueForMissingStub: null, - ); - - @override - void handleBeginFrame(Duration? rawTimeStamp) => super.noSuchMethod( - Invocation.method( - #handleBeginFrame, - [rawTimeStamp], - ), - returnValueForMissingStub: null, - ); - - @override - _i13.PerformanceModeRequestHandle? requestPerformanceMode( - _i5.DartPerformanceMode? mode) => - (super.noSuchMethod(Invocation.method( - #requestPerformanceMode, - [mode], - )) as _i13.PerformanceModeRequestHandle?); - - @override - void handleDrawFrame() => super.noSuchMethod( - Invocation.method( - #handleDrawFrame, - [], - ), - returnValueForMissingStub: null, - ); - - @override - void cancelPointer(int? pointer) => super.noSuchMethod( - Invocation.method( - #cancelPointer, - [pointer], - ), - returnValueForMissingStub: null, - ); - - @override - void handlePointerEvent(_i6.PointerEvent? event) => super.noSuchMethod( - Invocation.method( - #handlePointerEvent, - [event], - ), - returnValueForMissingStub: null, - ); - - @override - void hitTestInView( - _i7.HitTestResult? result, - _i5.Offset? position, - int? viewId, - ) => - super.noSuchMethod( - Invocation.method( - #hitTestInView, - [ - result, - position, - viewId, - ], - ), - returnValueForMissingStub: null, - ); - - @override - void hitTest( - _i7.HitTestResult? result, - _i5.Offset? position, - ) => - super.noSuchMethod( - Invocation.method( - #hitTest, - [ - result, - position, - ], - ), - returnValueForMissingStub: null, - ); + void ensureFrameCallbacksRegistered() => + super.noSuchMethod(Invocation.method(#ensureFrameCallbacksRegistered, []), + returnValueForMissingStub: null); + + @override + void ensureVisualUpdate() => + super.noSuchMethod(Invocation.method(#ensureVisualUpdate, []), + returnValueForMissingStub: null); + + @override + void scheduleFrame() => + super.noSuchMethod(Invocation.method(#scheduleFrame, []), + returnValueForMissingStub: null); + + @override + void scheduleForcedFrame() => + super.noSuchMethod(Invocation.method(#scheduleForcedFrame, []), + returnValueForMissingStub: null); + + @override + void scheduleWarmUpFrame() => + super.noSuchMethod(Invocation.method(#scheduleWarmUpFrame, []), + returnValueForMissingStub: null); + + @override + void resetEpoch() => super.noSuchMethod(Invocation.method(#resetEpoch, []), + returnValueForMissingStub: null); + + @override + void handleBeginFrame(Duration? rawTimeStamp) => + super.noSuchMethod(Invocation.method(#handleBeginFrame, [rawTimeStamp]), + returnValueForMissingStub: null); + + @override + void handleDrawFrame() => + super.noSuchMethod(Invocation.method(#handleDrawFrame, []), + returnValueForMissingStub: null); + + @override + void cancelPointer(int? pointer) => + super.noSuchMethod(Invocation.method(#cancelPointer, [pointer]), + returnValueForMissingStub: null); + + @override + void handlePointerEvent(_i6.PointerEvent? event) => + super.noSuchMethod(Invocation.method(#handlePointerEvent, [event]), + returnValueForMissingStub: null); + + @override + void hitTest(_i6.HitTestResult? result, _i4.Offset? position) => + super.noSuchMethod(Invocation.method(#hitTest, [result, position]), + returnValueForMissingStub: null); @override void dispatchEvent( - _i6.PointerEvent? event, - _i7.HitTestResult? hitTestResult, - ) => - super.noSuchMethod( - Invocation.method( - #dispatchEvent, - [ - event, - hitTestResult, - ], - ), - returnValueForMissingStub: null, - ); - - @override - void handleEvent( - _i6.PointerEvent? event, - _i7.HitTestEntry<_i7.HitTestTarget>? entry, - ) => + _i6.PointerEvent? event, _i6.HitTestResult? hitTestResult) => super.noSuchMethod( - Invocation.method( - #handleEvent, - [ - event, - entry, - ], - ), - returnValueForMissingStub: null, - ); - - @override - void resetGestureBinding() => super.noSuchMethod( - Invocation.method( - #resetGestureBinding, - [], - ), - returnValueForMissingStub: null, - ); - - @override - _i8.PipelineOwner createRootPipelineOwner() => (super.noSuchMethod( - Invocation.method( - #createRootPipelineOwner, - [], - ), - returnValue: _i14.dummyValue<_i8.PipelineOwner>( - this, - Invocation.method( - #createRootPipelineOwner, - [], - ), - ), - ) as _i8.PipelineOwner); + Invocation.method(#dispatchEvent, [event, hitTestResult]), + returnValueForMissingStub: null); @override - void addRenderView(_i8.RenderView? view) => super.noSuchMethod( - Invocation.method( - #addRenderView, - [view], - ), - returnValueForMissingStub: null, - ); + void handleEvent(_i6.PointerEvent? event, _i6.HitTestEntry? entry) => + super.noSuchMethod(Invocation.method(#handleEvent, [event, entry]), + returnValueForMissingStub: null); @override - void removeRenderView(_i8.RenderView? view) => super.noSuchMethod( - Invocation.method( - #removeRenderView, - [view], - ), - returnValueForMissingStub: null, - ); + void resetGestureBinding() => + super.noSuchMethod(Invocation.method(#resetGestureBinding, []), + returnValueForMissingStub: null); @override - _i8.ViewConfiguration createViewConfigurationFor( - _i8.RenderView? renderView) => - (super.noSuchMethod( - Invocation.method( - #createViewConfigurationFor, - [renderView], - ), - returnValue: _FakeViewConfiguration_20( - this, - Invocation.method( - #createViewConfigurationFor, - [renderView], - ), - ), - ) as _i8.ViewConfiguration); - - @override - _i5.SceneBuilder createSceneBuilder() => (super.noSuchMethod( - Invocation.method( - #createSceneBuilder, - [], - ), - returnValue: _FakeSceneBuilder_21( - this, - Invocation.method( - #createSceneBuilder, - [], - ), - ), - ) as _i5.SceneBuilder); - - @override - _i5.PictureRecorder createPictureRecorder() => (super.noSuchMethod( - Invocation.method( - #createPictureRecorder, - [], - ), - returnValue: _FakePictureRecorder_22( - this, - Invocation.method( - #createPictureRecorder, - [], - ), - ), - ) as _i5.PictureRecorder); - - @override - _i5.Canvas createCanvas(_i5.PictureRecorder? recorder) => (super.noSuchMethod( - Invocation.method( - #createCanvas, - [recorder], - ), - returnValue: _FakeCanvas_23( - this, - Invocation.method( - #createCanvas, - [recorder], - ), - ), - ) as _i5.Canvas); + void initRenderView() => + super.noSuchMethod(Invocation.method(#initRenderView, []), + returnValueForMissingStub: null); @override - void initMouseTracker([_i8.MouseTracker? tracker]) => super.noSuchMethod( - Invocation.method( - #initMouseTracker, - [tracker], - ), - returnValueForMissingStub: null, - ); + _i7.ViewConfiguration createViewConfiguration() => + (super.noSuchMethod(Invocation.method(#createViewConfiguration, []), + returnValue: _FakeViewConfiguration_16()) as _i7.ViewConfiguration); @override - void performSemanticsAction(_i5.SemanticsActionEvent? action) => - super.noSuchMethod( - Invocation.method( - #performSemanticsAction, - [action], - ), - returnValueForMissingStub: null, - ); - - @override - void deferFirstFrame() => super.noSuchMethod( - Invocation.method( - #deferFirstFrame, - [], - ), - returnValueForMissingStub: null, - ); - - @override - void allowFirstFrame() => super.noSuchMethod( - Invocation.method( - #allowFirstFrame, - [], - ), - returnValueForMissingStub: null, - ); - - @override - void resetFirstFrameSent() => super.noSuchMethod( - Invocation.method( - #resetFirstFrameSent, - [], - ), - returnValueForMissingStub: null, - ); - - @override - void addSemanticsEnabledListener(_i5.VoidCallback? listener) => - super.noSuchMethod( - Invocation.method( - #addSemanticsEnabledListener, - [listener], - ), - returnValueForMissingStub: null, - ); + void initMouseTracker([_i7.MouseTracker? tracker]) => + super.noSuchMethod(Invocation.method(#initMouseTracker, [tracker]), + returnValueForMissingStub: null); @override - void removeSemanticsEnabledListener(_i5.VoidCallback? listener) => - super.noSuchMethod( - Invocation.method( - #removeSemanticsEnabledListener, - [listener], - ), - returnValueForMissingStub: null, - ); + void setSemanticsEnabled(bool? enabled) => + super.noSuchMethod(Invocation.method(#setSemanticsEnabled, [enabled]), + returnValueForMissingStub: null); @override - void addSemanticsActionListener( - _i3.ValueSetter<_i5.SemanticsActionEvent>? listener) => - super.noSuchMethod( - Invocation.method( - #addSemanticsActionListener, - [listener], - ), - returnValueForMissingStub: null, - ); + void deferFirstFrame() => + super.noSuchMethod(Invocation.method(#deferFirstFrame, []), + returnValueForMissingStub: null); @override - void removeSemanticsActionListener( - _i3.ValueSetter<_i5.SemanticsActionEvent>? listener) => - super.noSuchMethod( - Invocation.method( - #removeSemanticsActionListener, - [listener], - ), - returnValueForMissingStub: null, - ); - - @override - _i8.SemanticsHandle ensureSemantics() => (super.noSuchMethod( - Invocation.method( - #ensureSemantics, - [], - ), - returnValue: _FakeSemanticsHandle_24( - this, - Invocation.method( - #ensureSemantics, - [], - ), - ), - ) as _i8.SemanticsHandle); + void allowFirstFrame() => + super.noSuchMethod(Invocation.method(#allowFirstFrame, []), + returnValueForMissingStub: null); @override - _i5.SemanticsUpdateBuilder createSemanticsUpdateBuilder() => - (super.noSuchMethod( - Invocation.method( - #createSemanticsUpdateBuilder, - [], - ), - returnValue: _FakeSemanticsUpdateBuilder_25( - this, - Invocation.method( - #createSemanticsUpdateBuilder, - [], - ), - ), - ) as _i5.SemanticsUpdateBuilder); + void resetFirstFrameSent() => + super.noSuchMethod(Invocation.method(#resetFirstFrameSent, []), + returnValueForMissingStub: null); + + @override + _i4.SemanticsUpdateBuilder createSemanticsUpdateBuilder() => + (super.noSuchMethod(Invocation.method(#createSemanticsUpdateBuilder, []), + returnValue: _FakeSemanticsUpdateBuilder_17()) + as _i4.SemanticsUpdateBuilder); +} + +/// A class which mocks [FrameTiming]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockFrameTiming extends _i1.Mock implements _i4.FrameTiming { + MockFrameTiming() { + _i1.throwOnMissingStub(this); + } + + @override + Duration get buildDuration => + (super.noSuchMethod(Invocation.getter(#buildDuration), + returnValue: _FakeDuration_8()) as Duration); + + @override + Duration get rasterDuration => + (super.noSuchMethod(Invocation.getter(#rasterDuration), + returnValue: _FakeDuration_8()) as Duration); + + @override + Duration get vsyncOverhead => + (super.noSuchMethod(Invocation.getter(#vsyncOverhead), + returnValue: _FakeDuration_8()) as Duration); + + @override + Duration get totalSpan => (super.noSuchMethod(Invocation.getter(#totalSpan), + returnValue: _FakeDuration_8()) as Duration); + + @override + int get layerCacheCount => + (super.noSuchMethod(Invocation.getter(#layerCacheCount), returnValue: 0) + as int); + + @override + int get layerCacheBytes => + (super.noSuchMethod(Invocation.getter(#layerCacheBytes), returnValue: 0) + as int); + + @override + double get layerCacheMegabytes => + (super.noSuchMethod(Invocation.getter(#layerCacheMegabytes), + returnValue: 0.0) as double); + + @override + int get pictureCacheCount => + (super.noSuchMethod(Invocation.getter(#pictureCacheCount), returnValue: 0) + as int); + + @override + int get pictureCacheBytes => + (super.noSuchMethod(Invocation.getter(#pictureCacheBytes), returnValue: 0) + as int); + + @override + double get pictureCacheMegabytes => + (super.noSuchMethod(Invocation.getter(#pictureCacheMegabytes), + returnValue: 0.0) as double); + + @override + int get frameNumber => + (super.noSuchMethod(Invocation.getter(#frameNumber), returnValue: 0) + as int); + + @override + int timestampInMicroseconds(_i4.FramePhase? phase) => + (super.noSuchMethod(Invocation.method(#timestampInMicroseconds, [phase]), + returnValue: 0) as int); } From 2ae2acccdaf2634cd27e487424b0100a7db870eb Mon Sep 17 00:00:00 2001 From: Ahmed alaa Date: Tue, 1 Jul 2025 14:18:22 +0300 Subject: [PATCH 15/15] fix: dart format --- .../instabug_screen_render_manager_test_manual_mocks.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/utils/screen_render/instabug_screen_render_manager_test_manual_mocks.dart b/test/utils/screen_render/instabug_screen_render_manager_test_manual_mocks.dart index dcc87eaab..35f21c850 100644 --- a/test/utils/screen_render/instabug_screen_render_manager_test_manual_mocks.dart +++ b/test/utils/screen_render/instabug_screen_render_manager_test_manual_mocks.dart @@ -39,8 +39,8 @@ class _FakeSingletonFlutterWindow_1 extends _i1.Fake class _FakePlatformDispatcher_2 extends _i1.Fake implements _i4.PlatformDispatcher {} -class _FakeHardwareKeyboard_3 extends _i1.Fake implements _i5.HardwareKeyboard { -} +class _FakeHardwareKeyboard_3 extends _i1.Fake + implements _i5.HardwareKeyboard {} class _FakeKeyEventManager_4 extends _i1.Fake implements _i5.KeyEventManager {}