diff --git a/android/build.gradle b/android/build.gradle index 102714f6a..92b3a865e 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -52,7 +52,7 @@ android { } dependencies { - api 'com.instabug.library:instabug:15.0.2.7140934-SNAPSHOT' + api 'com.instabug.library:instabug:15.0.2.7160278-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/android/src/main/java/com/instabug/flutter/modules/ApmApi.java b/android/src/main/java/com/instabug/flutter/modules/ApmApi.java index ab1f0dd86..fb58834e6 100644 --- a/android/src/main/java/com/instabug/flutter/modules/ApmApi.java +++ b/android/src/main/java/com/instabug/flutter/modules/ApmApi.java @@ -374,6 +374,20 @@ public void isEndScreenLoadingEnabled(@NonNull ApmPigeon.Result result) isScreenLoadingEnabled(result); } + @Override + public void isAutoUiTraceEnabled(@NonNull ApmPigeon.Result result) { + try { + InternalAPM._isFeatureEnabledCP(APMFeature.UI_TRACE, "InstabugCaptureScreenLoading", new FeatureAvailabilityCallback() { + @Override + public void invoke(boolean isFeatureAvailable) { + result.success(isFeatureAvailable); + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + } + @Override public void isEnabled(@NonNull ApmPigeon.Result result) { try { diff --git a/android/src/test/java/com/instabug/flutter/ApmApiTest.java b/android/src/test/java/com/instabug/flutter/ApmApiTest.java index d7bacc450..81b9d2584 100644 --- a/android/src/test/java/com/instabug/flutter/ApmApiTest.java +++ b/android/src/test/java/com/instabug/flutter/ApmApiTest.java @@ -328,6 +328,28 @@ public void testSetScreenLoadingMonitoringEnabled() { mAPM.verify(() -> APM.setScreenLoadingEnabled(isEnabled)); } + @Test + public void testIsAutoUiTraceEnabled() { + + 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); + } + @Test public void testIsScreenRenderEnabled() { diff --git a/example/ios/InstabugTests/ApmApiTests.m b/example/ios/InstabugTests/ApmApiTests.m index e18643bf7..75572d958 100644 --- a/example/ios/InstabugTests/ApmApiTests.m +++ b/example/ios/InstabugTests/ApmApiTests.m @@ -199,6 +199,7 @@ - (void)testEndScreenLoading { OCMVerify([self.mAPM endScreenLoadingCPWithEndTimestampMUS:endScreenLoadingCPWithEndTimestampMUS]); } + - (void)testIsScreenRenderEnabled { XCTestExpectation *expectation = [self expectationWithDescription:@"Call completion handler"]; diff --git a/example/ios/Podfile b/example/ios/Podfile index ed931ce33..1768d6c13 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -30,7 +30,7 @@ target 'Runner' do use_frameworks! use_modular_headers! - pod 'Instabug', :podspec => 'https://ios-releases.instabug.com/custom/faeture-screen_rendering-release/15.1.29/Instabug.podspec' + pod 'Instabug', :podspec => 'https://ios-releases.instabug.com/custom/faeture-screen_rendering-release/15.1.31/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 0db0443b3..648043285 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,14 +1,14 @@ PODS: - Flutter (1.0.0) - - Instabug (15.1.29) + - Instabug (15.1.31) - instabug_flutter (14.3.0): - Flutter - - Instabug (= 15.1.29) + - Instabug (= 15.1.31) - OCMock (3.6) DEPENDENCIES: - Flutter (from `Flutter`) - - Instabug (from `https://ios-releases.instabug.com/custom/faeture-screen_rendering-release/15.1.29/Instabug.podspec`) + - Instabug (from `https://ios-releases.instabug.com/custom/faeture-screen_rendering-release/15.1.31/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/faeture-screen_rendering-release/15.1.29/Instabug.podspec + :podspec: https://ios-releases.instabug.com/custom/faeture-screen_rendering-release/15.1.31/Instabug.podspec instabug_flutter: :path: ".symlinks/plugins/instabug_flutter/ios" SPEC CHECKSUMS: Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 - Instabug: c2ddabc44a1f425615fedba6331a7d1e8805e413 - instabug_flutter: 30227104e2ba5857bcd7794dc21e353bdb691f3e + Instabug: 447d3f5a9f1c83120235437e08c9a51aaa8f8605 + instabug_flutter: 65aa2dee3036a3c7c8feff8e898c9547239a891d OCMock: 5ea90566be239f179ba766fd9fbae5885040b992 -PODFILE CHECKSUM: 8194fdeb7c217898e3faaeed21926a5fc586751d +PODFILE CHECKSUM: c5b98f57c27da87950775c360d20aaedd3216b8d COCOAPODS: 1.15.2 diff --git a/example/lib/main.dart b/example/lib/main.dart index 9552c647e..6979ec702 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -37,18 +37,17 @@ part 'src/screens/screen_render_page.dart'; void main() { runZonedGuarded( - () { + () async { WidgetsFlutterBinding.ensureInitialized(); - Instabug.init( + await Instabug.init( token: 'ed6f659591566da19b67857e1b9d40ab', invocationEvents: [InvocationEvent.floatingButton], debugLogsLevel: LogLevel.verbose, appVariant: 'variant 1', - ).then((_) { - APM.setScreenRenderingEnabled(true); - }); - + ); + APM.setScreenRenderingEnabled(true); + APM.setAutoUITraceEnabled(false); FlutterError.onError = (FlutterErrorDetails details) { Zone.current.handleUncaughtError(details.exception, details.stack!); }; diff --git a/example/pubspec.lock b/example/pubspec.lock index 1221be412..ed56bbe53 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: a38bed979f549ffe85efa46c46ca743cbfab95a51295b60f143f249b71655231 - url: "https://pub.dev" + url: "https://pub.dartlang.org" source: hosted version: "2.6.0" - 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/ios/Classes/Modules/ApmApi.m b/ios/Classes/Modules/ApmApi.m index b4d6bd161..ac16b84da 100644 --- a/ios/Classes/Modules/ApmApi.m +++ b/ios/Classes/Modules/ApmApi.m @@ -218,6 +218,13 @@ - (void)getDeviceRefreshRateAndToleranceWithCompletion:(nonnull void (^)(NSArray } } +- (void)isAutoUiTraceEnabledWithCompletion:(nonnull void (^)(NSNumber * _Nullable, FlutterError * _Nullable))completion { + BOOL isAutoUiTraceIsEnabled = IBGAPM.autoUITraceEnabled && IBGAPM.enabled; + NSNumber *isEnabledNumber = @(isAutoUiTraceIsEnabled); + completion(isEnabledNumber, nil); +} + + diff --git a/ios/Classes/Modules/InstabugApi.m b/ios/Classes/Modules/InstabugApi.m index 84f574b58..813173c9d 100644 --- a/ios/Classes/Modules/InstabugApi.m +++ b/ios/Classes/Modules/InstabugApi.m @@ -106,7 +106,7 @@ - (void)setWelcomeMessageModeMode:(NSString *)mode error:(FlutterError *_Nullabl } - (void)setPrimaryColorColor:(NSNumber *)color error:(FlutterError *_Nullable *_Nonnull)error { - Instabug.tintColor = UIColorFromRGB([color longValue]); +// Instabug.tintColor = UIColorFromRGB([color longValue]); } - (void)setSessionProfilerEnabledEnabled:(NSNumber *)enabled error:(FlutterError *_Nullable *_Nonnull)error { diff --git a/ios/instabug_flutter.podspec b/ios/instabug_flutter.podspec index 608a5b261..f216fdaf0 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.1.29' + s.dependency 'Instabug', '15.1.31' end diff --git a/lib/src/modules/apm.dart b/lib/src/modules/apm.dart index 58bc0541e..1ce12d413 100644 --- a/lib/src/modules/apm.dart +++ b/lib/src/modules/apm.dart @@ -1,8 +1,9 @@ // ignore_for_file: avoid_classes_with_only_static_members import 'dart:async'; +import 'dart:developer'; -import 'package:flutter/widgets.dart' show WidgetBuilder, WidgetsBinding; +import 'package:flutter/widgets.dart' show WidgetBuilder; import 'package:instabug_flutter/src/generated/apm.api.g.dart'; import 'package:instabug_flutter/src/models/instabug_screen_render_data.dart'; import 'package:instabug_flutter/src/models/network_data.dart'; @@ -140,6 +141,11 @@ class APM { static Future startUITrace(String name) async { final isScreenRenderingEnabled = await FlagsConfig.screenRendering.isEnabled(); + log("startUITrace: isScreenRenderEnabled: $isScreenRenderingEnabled"); + await InstabugScreenRenderManager.I + .checkForScreenRenderInitialization(isScreenRenderingEnabled); + + // Ends the active custom ui trace before starting new one. if (isScreenRenderingEnabled) { InstabugScreenRenderManager.I .endScreenRenderCollector(UiTraceType.custom); @@ -162,8 +168,15 @@ class APM { static Future endUITrace() async { // End screen render collector for custom ui trace if enabled. if (InstabugScreenRenderManager.I.screenRenderEnabled) { - return InstabugScreenRenderManager.I + InstabugScreenRenderManager.I .endScreenRenderCollector(UiTraceType.custom); + + final isAutoUiTraceEnabled = await FlagsConfig.uiTrace.isEnabled(); + + // dispose the InstabugScreenRenderManager if AutoUiTrace is disabled. + if (!isAutoUiTraceEnabled) InstabugScreenRenderManager.I.dispose(); + + return; } return _host.endUITrace(); @@ -316,6 +329,16 @@ class APM { return ScreenLoadingManager.wrapRoutes(routes, exclude: exclude); } + /// Returns a Future indicating whether the auto + /// ui trace is enabled. + /// + /// Returns: + /// A Future is being returned. + @internal + static Future isAutoUiTraceEnabled() async { + return _host.isAutoUiTraceEnabled(); + } + /// Returns a Future indicating whether the screen /// render is enabled. /// @@ -349,13 +372,7 @@ class APM { /// Returns: /// A Future is being returned. static Future setScreenRenderingEnabled(bool isEnabled) async { - return _host.setScreenRenderEnabled(isEnabled).then((_) async { - if (isEnabled) { - await InstabugScreenRenderManager.I.init(WidgetsBinding.instance); - } else { - InstabugScreenRenderManager.I.dispose(); - } - }); + return _host.setScreenRenderEnabled(isEnabled); } /// Ends screen rendering for diff --git a/lib/src/utils/instabug_navigator_observer.dart b/lib/src/utils/instabug_navigator_observer.dart index 8272c66ab..d10c59e6c 100644 --- a/lib/src/utils/instabug_navigator_observer.dart +++ b/lib/src/utils/instabug_navigator_observer.dart @@ -67,23 +67,14 @@ class InstabugNavigatorObserver extends NavigatorObserver { } FutureOr _startScreenRenderCollector(int? uiTraceId) async { + if (uiTraceId == null) return; final isScreenRenderEnabled = await FlagsConfig.screenRendering.isEnabled(); - await _checkForScreenRenderInitialization(isScreenRenderEnabled); - if (uiTraceId != null && isScreenRenderEnabled) { + + await InstabugScreenRenderManager.I + .checkForScreenRenderInitialization(isScreenRenderEnabled); + if (isScreenRenderEnabled) { InstabugScreenRenderManager.I .startScreenRenderCollectorForTraceId(uiTraceId); } } - - Future _checkForScreenRenderInitialization(bool isScreenRender) async { - if (isScreenRender) { - if (!InstabugScreenRenderManager.I.screenRenderEnabled) { - await InstabugScreenRenderManager.I.init(WidgetsBinding.instance); - } - } else { - if (InstabugScreenRenderManager.I.screenRenderEnabled) { - InstabugScreenRenderManager.I.dispose(); - } - } - } } diff --git a/lib/src/utils/screen_loading/screen_loading_manager.dart b/lib/src/utils/screen_loading/screen_loading_manager.dart index ca42af359..9a2747622 100644 --- a/lib/src/utils/screen_loading/screen_loading_manager.dart +++ b/lib/src/utils/screen_loading/screen_loading_manager.dart @@ -149,14 +149,13 @@ class ScreenLoadingManager { resetDidStartScreenLoading(); final isSDKBuilt = - await _checkInstabugSDKBuilt("APM.InstabugCaptureScreenLoading"); + await _checkInstabugSDKBuilt("APM.InstabugCaptureScreenLoading"); + 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. - // This is a temporary fix until we implement the isEnabled check correctly. - // We need to fix this in the future. - final isApmEnabled = await FlagsConfig.apm.isEnabled(); - if (!isApmEnabled && IBGBuildInfo.I.isIOS) { + + final isAutoUiTraceEnabled = await FlagsConfig.uiTrace.isEnabled(); + + if (!isAutoUiTraceEnabled) { InstabugLogger.I.e( 'APM is disabled, skipping starting the UI trace for screen: $screenName.\n' 'Please refer to the documentation for how to enable APM on your app: ' 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 718c9b473..4beb720af 100644 --- a/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart +++ b/lib/src/utils/screen_rendering/instabug_screen_render_manager.dart @@ -122,7 +122,7 @@ class InstabugScreenRenderManager { UiTraceType type = UiTraceType.auto, ]) { // Return if frameTimingListener not attached - if (frameCollectorIsNotActive) return; + if (_frameCollectorIsNotActive) return; if (type == UiTraceType.custom) { _screenRenderForCustomUiTrace.traceId = traceId; @@ -138,7 +138,7 @@ class InstabugScreenRenderManager { UiTraceType type = UiTraceType.auto, ]) { // Return if frameTimingListener not attached - if (frameCollectorIsNotActive) return; + if (_frameCollectorIsNotActive) return; //Save the memory cached data to be sent to native side if (_delayedFrames.isNotEmpty) { @@ -163,7 +163,7 @@ class InstabugScreenRenderManager { @internal void stopScreenRenderCollector() { // Return if frameTimingListener not attached - if (frameCollectorIsNotActive) return; + if (_frameCollectorIsNotActive) return; if (_delayedFrames.isNotEmpty) { _saveCollectedData(); @@ -183,10 +183,23 @@ class InstabugScreenRenderManager { } } - bool get frameCollectorIsNotActive => - !screenRenderEnabled || !_isTimingsListenerAttached; + @internal + Future checkForScreenRenderInitialization( + bool isScreenRenderEnabledFromBackend, + ) async { + if (isScreenRenderEnabledFromBackend) { + if (!screenRenderEnabled) { + await init(WidgetsBinding.instance); + } + } else { + if (screenRenderEnabled) { + dispose(); + } + } + } /// Dispose InstabugScreenRenderManager by removing timings callback and cashed data. + @internal void dispose() { try { _resetCachedFrameData(); @@ -194,6 +207,7 @@ class InstabugScreenRenderManager { _removeWidgetBindingObserver(); _widgetsBinding = null; screenRenderEnabled = false; + _epochOffset = null; } catch (error, stackTrace) { _logExceptionErrorAndStackTrace(error, stackTrace); } @@ -211,6 +225,9 @@ class InstabugScreenRenderManager { bool get _isTotalTimeLarge => _totalTimeMs >= _frozenFrameThresholdMs; + bool get _frameCollectorIsNotActive => + !screenRenderEnabled || !_isTimingsListenerAttached; + /// 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; 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 3c18b1642..d454309c1 100644 --- a/lib/src/utils/screen_rendering/instabug_widget_binding_observer.dart +++ b/lib/src/utils/screen_rendering/instabug_widget_binding_observer.dart @@ -36,7 +36,10 @@ class InstabugWidgetsBindingObserver extends WidgetsBindingObserver { .then((uiTraceId) { if (uiTraceId != null && InstabugScreenRenderManager.I.screenRenderEnabled) { + //End any active ScreenRenderCollector before starting a new one (Safe garde condition). InstabugScreenRenderManager.I.endScreenRenderCollector(); + + //Start new ScreenRenderCollector. InstabugScreenRenderManager.I .startScreenRenderCollectorForTraceId(uiTraceId); } @@ -49,11 +52,10 @@ class InstabugWidgetsBindingObserver extends WidgetsBindingObserver { } } - void _handleDetachedState() { + Future _handleDetachedState() async { if (InstabugScreenRenderManager.I.screenRenderEnabled) { - InstabugScreenRenderManager.I.stopScreenRenderCollector(); + dispose(); } - dispose(); } void _handleDefaultState() { diff --git a/lib/src/utils/ui_trace/flags_config.dart b/lib/src/utils/ui_trace/flags_config.dart index 92a899b15..bc447b70b 100644 --- a/lib/src/utils/ui_trace/flags_config.dart +++ b/lib/src/utils/ui_trace/flags_config.dart @@ -13,6 +13,8 @@ extension FeatureExtensions on FlagsConfig { switch (this) { case FlagsConfig.apm: return APM.isEnabled(); + case FlagsConfig.uiTrace: + return APM.isAutoUiTraceEnabled(); case FlagsConfig.screenLoading: return APM.isScreenLoadingEnabled(); case FlagsConfig.endScreenLoading: diff --git a/pigeons/apm.api.dart b/pigeons/apm.api.dart index eb7201792..5d7bc1ea7 100644 --- a/pigeons/apm.api.dart +++ b/pigeons/apm.api.dart @@ -32,6 +32,9 @@ abstract class ApmHostApi { @async bool isEndScreenLoadingEnabled(); + @async + bool isAutoUiTraceEnabled(); + @async bool isScreenRenderEnabled(); diff --git a/test/apm_test.dart b/test/apm_test.dart index 4b16f4501..36a40ba27 100644 --- a/test/apm_test.dart +++ b/test/apm_test.dart @@ -89,6 +89,12 @@ void main() { ).called(1); }); + test("[isAutoUiTraceEnabled] should call host method", () async { + when(mHost.isAutoUiTraceEnabled()).thenAnswer((_) async => true); + await APM.isAutoUiTraceEnabled(); + verify(mHost.isAutoUiTraceEnabled()); + }); + test('[startFlow] should call host method', () async { const flowName = "flow-name"; await APM.startFlow(flowName); @@ -226,6 +232,7 @@ void main() { }); tearDown(() { reset(mScreenRenderManager); + reset(mHost); }); test("[isScreenRenderEnabled] should call host method", () async { when(mHost.isScreenRenderEnabled()).thenAnswer((_) async => true); @@ -242,30 +249,13 @@ void main() { verify(mHost.getDeviceRefreshRateAndTolerance()).called(1); }); - test("[setScreenRenderEnabled] should call host method", () async { + test("[setScreenRenderingEnabled] should call host method", () async { const isEnabled = false; + when(mScreenRenderManager.screenRenderEnabled).thenReturn(false); await APM.setScreenRenderingEnabled(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.setScreenRenderingEnabled(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.setScreenRenderingEnabled(isEnabled); - verify(mScreenRenderManager.dispose()).called(1); - verifyNoMoreInteractions(mScreenRenderManager); - }); - test( "[startUITrace] should start screen render collector with right params, if screen render feature is enabled", () async { @@ -306,6 +296,7 @@ void main() { "[endUITrace] should stop screen render collector with, if screen render feature is enabled", () async { when(mHost.isScreenRenderEnabled()).thenAnswer((_) async => true); + when(mHost.isAutoUiTraceEnabled()).thenAnswer((_) async => true); when(mScreenRenderManager.screenRenderEnabled).thenReturn(true); await APM.endUITrace(); diff --git a/test/utils/screen_loading/screen_loading_manager_test.dart b/test/utils/screen_loading/screen_loading_manager_test.dart index 6b5c954f3..1d8598948 100644 --- a/test/utils/screen_loading/screen_loading_manager_test.dart +++ b/test/utils/screen_loading/screen_loading_manager_test.dart @@ -171,8 +171,7 @@ void main() { test('[startUiTrace] with APM disabled on iOS Platform should Log error', () async { mScreenLoadingManager.currentUiTrace = uiTrace; - when(FlagsConfig.apm.isEnabled()).thenAnswer((_) async => false); - when(IBGBuildInfo.I.isIOS).thenReturn(true); + when(FlagsConfig.uiTrace.isEnabled()).thenAnswer((_) async => false); await ScreenLoadingManager.I.startUiTrace(screenName); @@ -192,8 +191,7 @@ void main() { test( '[startUiTrace] with APM enabled on android Platform should call `APM.startCpUiTrace and set UiTrace', () async { - when(FlagsConfig.apm.isEnabled()).thenAnswer((_) async => true); - when(IBGBuildInfo.I.isIOS).thenReturn(false); + when(FlagsConfig.uiTrace.isEnabled()).thenAnswer((_) async => true); await ScreenLoadingManager.I.startUiTrace(screenName); @@ -217,8 +215,7 @@ void main() { test( '[startUiTrace] with APM enabled should create a UI trace with the matching screen name', () async { - when(FlagsConfig.apm.isEnabled()).thenAnswer((_) async => true); - when(IBGBuildInfo.I.isIOS).thenReturn(false); + when(FlagsConfig.uiTrace.isEnabled()).thenAnswer((_) async => true); when( RouteMatcher.I.match( routePath: anyNamed('routePath'), diff --git a/test/utils/screen_render/instabug_screen_render_manager_test_mocks.dart b/test/utils/screen_render/instabug_screen_render_manager_test_mocks.dart index fbb7545dd..3928266e0 100644 --- a/test/utils/screen_render/instabug_screen_render_manager_test_mocks.dart +++ b/test/utils/screen_render/instabug_screen_render_manager_test_mocks.dart @@ -2,20 +2,20 @@ // 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 _i8; -import 'dart:developer' as _i12; +import 'dart:async' as _i9; +import 'dart:developer' as _i13; import 'dart:ui' as _i4; -import 'package:flutter/foundation.dart' as _i11; +import 'package:flutter/foundation.dart' as _i3; import 'package:flutter/gestures.dart' as _i6; -import 'package:flutter/rendering.dart' as _i3; -import 'package:flutter/scheduler.dart' as _i9; +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 _i7; +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 _i10; +import 'package:flutter/src/widgets/framework.dart' as _i12; import 'package:instabug_flutter/instabug_flutter.dart' as _i16; -import 'package:instabug_flutter/src/generated/apm.api.g.dart' as _i13; +import 'package:instabug_flutter/src/generated/apm.api.g.dart' as _i8; import 'package:instabug_flutter/src/generated/crash_reporting.api.g.dart' as _i14; import 'package:instabug_flutter/src/utils/instabug_logger.dart' as _i15; @@ -65,11 +65,11 @@ class _FakeGestureArenaManager_10 extends _i1.Fake class _FakePointerSignalResolver_11 extends _i1.Fake implements _i6.PointerSignalResolver {} -class _FakeMouseTracker_12 extends _i1.Fake implements _i3.MouseTracker {} +class _FakeMouseTracker_12 extends _i1.Fake implements _i7.MouseTracker {} -class _FakePipelineOwner_13 extends _i1.Fake implements _i3.PipelineOwner {} +class _FakePipelineOwner_13 extends _i1.Fake implements _i7.PipelineOwner {} -class _FakeRenderView_14 extends _i1.Fake implements _i3.RenderView { +class _FakeRenderView_14 extends _i1.Fake implements _i7.RenderView { @override String toString({_i3.DiagnosticLevel? minLevel = _i3.DiagnosticLevel.info}) => super.toString(); @@ -79,15 +79,153 @@ class _FakeAccessibilityFeatures_15 extends _i1.Fake implements _i4.AccessibilityFeatures {} class _FakeViewConfiguration_16 extends _i1.Fake - implements _i3.ViewConfiguration {} + implements _i7.ViewConfiguration {} class _FakeSemanticsUpdateBuilder_17 extends _i1.Fake implements _i4.SemanticsUpdateBuilder {} +/// 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 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 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 isAutoUiTraceEnabled() => + (super.noSuchMethod(Invocation.method(#isAutoUiTraceEnabled, []), + 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> getDeviceRefreshRateAndTolerance() => + (super.noSuchMethod( + Invocation.method(#getDeviceRefreshRateAndTolerance, []), + returnValue: Future>.value([])) + 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); + @override + _i9.Future endScreenRenderForAutoUiTrace( + Map? arg_data) => + (super.noSuchMethod( + Invocation.method(#endScreenRenderForAutoUiTrace, [arg_data]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i9.Future); + @override + _i9.Future endScreenRenderForCustomUiTrace( + Map? arg_data) => + (super.noSuchMethod( + Invocation.method(#endScreenRenderForCustomUiTrace, [arg_data]), + 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 _i7.WidgetsBinding { +class MockWidgetsBinding extends _i1.Mock implements _i10.WidgetsBinding { MockWidgetsBinding() { _i1.throwOnMissingStub(this); } @@ -111,9 +249,9 @@ class MockWidgetsBinding extends _i1.Mock implements _i7.WidgetsBinding { (super.noSuchMethod(Invocation.getter(#firstFrameRasterized), returnValue: false) as bool); @override - _i8.Future get waitUntilFirstFrameRasterized => + _i9.Future get waitUntilFirstFrameRasterized => (super.noSuchMethod(Invocation.getter(#waitUntilFirstFrameRasterized), - returnValue: Future.value()) as _i8.Future); + returnValue: Future.value()) as _i9.Future); @override bool get debugDidSendFirstFrameEvent => (super.noSuchMethod(Invocation.getter(#debugDidSendFirstFrameEvent), @@ -160,12 +298,12 @@ class MockWidgetsBinding extends _i1.Mock implements _i7.WidgetsBinding { (super.noSuchMethod(Invocation.getter(#restorationManager), returnValue: _FakeRestorationManager_7()) as _i5.RestorationManager); @override - _i9.SchedulingStrategy get schedulingStrategy => + _i11.SchedulingStrategy get schedulingStrategy => (super.noSuchMethod(Invocation.getter(#schedulingStrategy), - returnValue: ({int? priority, _i9.SchedulerBinding? scheduler}) => - false) as _i9.SchedulingStrategy); + returnValue: ({int? priority, _i11.SchedulerBinding? scheduler}) => + false) as _i11.SchedulingStrategy); @override - set schedulingStrategy(_i9.SchedulingStrategy? _schedulingStrategy) => super + set schedulingStrategy(_i11.SchedulingStrategy? _schedulingStrategy) => super .noSuchMethod(Invocation.setter(#schedulingStrategy, _schedulingStrategy), returnValueForMissingStub: null); @override @@ -173,17 +311,17 @@ class MockWidgetsBinding extends _i1.Mock implements _i7.WidgetsBinding { (super.noSuchMethod(Invocation.getter(#transientCallbackCount), returnValue: 0) as int); @override - _i8.Future get endOfFrame => + _i9.Future get endOfFrame => (super.noSuchMethod(Invocation.getter(#endOfFrame), - returnValue: Future.value()) as _i8.Future); + returnValue: Future.value()) as _i9.Future); @override bool get hasScheduledFrame => (super.noSuchMethod(Invocation.getter(#hasScheduledFrame), returnValue: false) as bool); @override - _i9.SchedulerPhase get schedulerPhase => + _i11.SchedulerPhase get schedulerPhase => (super.noSuchMethod(Invocation.getter(#schedulerPhase), - returnValue: _i9.SchedulerPhase.idle) as _i9.SchedulerPhase); + returnValue: _i11.SchedulerPhase.idle) as _i11.SchedulerPhase); @override Duration get currentFrameTimeStamp => (super.noSuchMethod(Invocation.getter(#currentFrameTimeStamp), @@ -222,19 +360,19 @@ class MockWidgetsBinding extends _i1.Mock implements _i7.WidgetsBinding { super.noSuchMethod(Invocation.setter(#samplingOffset, _samplingOffset), returnValueForMissingStub: null); @override - _i3.MouseTracker get mouseTracker => + _i7.MouseTracker get mouseTracker => (super.noSuchMethod(Invocation.getter(#mouseTracker), - returnValue: _FakeMouseTracker_12()) as _i3.MouseTracker); + returnValue: _FakeMouseTracker_12()) as _i7.MouseTracker); @override - _i3.PipelineOwner get pipelineOwner => + _i7.PipelineOwner get pipelineOwner => (super.noSuchMethod(Invocation.getter(#pipelineOwner), - returnValue: _FakePipelineOwner_13()) as _i3.PipelineOwner); + returnValue: _FakePipelineOwner_13()) as _i7.PipelineOwner); @override - _i3.RenderView get renderView => + _i7.RenderView get renderView => (super.noSuchMethod(Invocation.getter(#renderView), - returnValue: _FakeRenderView_14()) as _i3.RenderView); + returnValue: _FakeRenderView_14()) as _i7.RenderView); @override - set renderView(_i3.RenderView? value) => + set renderView(_i7.RenderView? value) => super.noSuchMethod(Invocation.setter(#renderView, value), returnValueForMissingStub: null); @override @@ -259,11 +397,11 @@ class MockWidgetsBinding extends _i1.Mock implements _i7.WidgetsBinding { super.noSuchMethod(Invocation.method(#initServiceExtensions, []), returnValueForMissingStub: null); @override - void addObserver(_i7.WidgetsBindingObserver? observer) => + void addObserver(_i10.WidgetsBindingObserver? observer) => super.noSuchMethod(Invocation.method(#addObserver, [observer]), returnValueForMissingStub: null); @override - bool removeObserver(_i7.WidgetsBindingObserver? observer) => + bool removeObserver(_i10.WidgetsBindingObserver? observer) => (super.noSuchMethod(Invocation.method(#removeObserver, [observer]), returnValue: false) as bool); @override @@ -295,15 +433,15 @@ class MockWidgetsBinding extends _i1.Mock implements _i7.WidgetsBinding { Invocation.method(#dispatchAccessibilityFeaturesChanged, []), returnValueForMissingStub: null); @override - _i8.Future handlePopRoute() => + _i9.Future handlePopRoute() => (super.noSuchMethod(Invocation.method(#handlePopRoute, []), returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i8.Future); + returnValueForMissingStub: Future.value()) as _i9.Future); @override - _i8.Future handlePushRoute(String? route) => + _i9.Future handlePushRoute(String? route) => (super.noSuchMethod(Invocation.method(#handlePushRoute, [route]), returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i8.Future); + returnValueForMissingStub: Future.value()) as _i9.Future); @override void handleAppLifecycleStateChanged(_i4.AppLifecycleState? state) => super .noSuchMethod(Invocation.method(#handleAppLifecycleStateChanged, [state]), @@ -316,39 +454,39 @@ class MockWidgetsBinding extends _i1.Mock implements _i7.WidgetsBinding { void drawFrame() => super.noSuchMethod(Invocation.method(#drawFrame, []), returnValueForMissingStub: null); @override - void scheduleAttachRootWidget(_i10.Widget? rootWidget) => super.noSuchMethod( + void scheduleAttachRootWidget(_i12.Widget? rootWidget) => super.noSuchMethod( Invocation.method(#scheduleAttachRootWidget, [rootWidget]), returnValueForMissingStub: null); @override - void attachRootWidget(_i10.Widget? rootWidget) => + void attachRootWidget(_i12.Widget? rootWidget) => super.noSuchMethod(Invocation.method(#attachRootWidget, [rootWidget]), returnValueForMissingStub: null); @override - _i8.Future performReassemble() => + _i9.Future performReassemble() => (super.noSuchMethod(Invocation.method(#performReassemble, []), returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i8.Future); + returnValueForMissingStub: Future.value()) as _i9.Future); @override _i4.Locale? computePlatformResolvedLocale( List<_i4.Locale>? supportedLocales) => (super.noSuchMethod(Invocation.method( #computePlatformResolvedLocale, [supportedLocales])) as _i4.Locale?); @override - _i8.Future lockEvents(_i8.Future Function()? callback) => + _i9.Future lockEvents(_i9.Future Function()? callback) => (super.noSuchMethod(Invocation.method(#lockEvents, [callback]), returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i8.Future); + returnValueForMissingStub: Future.value()) as _i9.Future); @override void unlocked() => super.noSuchMethod(Invocation.method(#unlocked, []), returnValueForMissingStub: null); @override - _i8.Future reassembleApplication() => + _i9.Future reassembleApplication() => (super.noSuchMethod(Invocation.method(#reassembleApplication, []), returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i8.Future); + returnValueForMissingStub: Future.value()) as _i9.Future); @override void registerSignalServiceExtension( - {String? name, _i11.AsyncCallback? callback}) => + {String? name, _i3.AsyncCallback? callback}) => super.noSuchMethod( Invocation.method(#registerSignalServiceExtension, [], {#name: name, #callback: callback}), @@ -356,8 +494,8 @@ class MockWidgetsBinding extends _i1.Mock implements _i7.WidgetsBinding { @override void registerBoolServiceExtension( {String? name, - _i11.AsyncValueGetter? getter, - _i11.AsyncValueSetter? setter}) => + _i3.AsyncValueGetter? getter, + _i3.AsyncValueSetter? setter}) => super.noSuchMethod( Invocation.method(#registerBoolServiceExtension, [], {#name: name, #getter: getter, #setter: setter}), @@ -365,8 +503,8 @@ class MockWidgetsBinding extends _i1.Mock implements _i7.WidgetsBinding { @override void registerNumericServiceExtension( {String? name, - _i11.AsyncValueGetter? getter, - _i11.AsyncValueSetter? setter}) => + _i3.AsyncValueGetter? getter, + _i3.AsyncValueSetter? setter}) => super.noSuchMethod( Invocation.method(#registerNumericServiceExtension, [], {#name: name, #getter: getter, #setter: setter}), @@ -378,15 +516,15 @@ class MockWidgetsBinding extends _i1.Mock implements _i7.WidgetsBinding { @override void registerStringServiceExtension( {String? name, - _i11.AsyncValueGetter? getter, - _i11.AsyncValueSetter? setter}) => + _i3.AsyncValueGetter? getter, + _i3.AsyncValueSetter? setter}) => super.noSuchMethod( Invocation.method(#registerStringServiceExtension, [], {#name: name, #getter: getter, #setter: setter}), returnValueForMissingStub: null); @override void registerServiceExtension( - {String? name, _i11.ServiceExtensionCallback? callback}) => + {String? name, _i3.ServiceExtensionCallback? callback}) => super.noSuchMethod( Invocation.method(#registerServiceExtension, [], {#name: name, #callback: callback}), @@ -396,10 +534,10 @@ class MockWidgetsBinding extends _i1.Mock implements _i7.WidgetsBinding { (super.noSuchMethod(Invocation.method(#createBinaryMessenger, []), returnValue: _FakeBinaryMessenger_5()) as _i5.BinaryMessenger); @override - _i8.Future handleSystemMessage(Object? systemMessage) => (super + _i9.Future handleSystemMessage(Object? systemMessage) => (super .noSuchMethod(Invocation.method(#handleSystemMessage, [systemMessage]), returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i8.Future); + returnValueForMissingStub: Future.value()) as _i9.Future); @override void initLicenses() => super.noSuchMethod(Invocation.method(#initLicenses, []), @@ -429,19 +567,19 @@ class MockWidgetsBinding extends _i1.Mock implements _i7.WidgetsBinding { super.noSuchMethod(Invocation.method(#removeTimingsCallback, [callback]), returnValueForMissingStub: null); @override - _i8.Future scheduleTask( - _i9.TaskCallback? task, _i9.Priority? priority, - {String? debugLabel, _i12.Flow? flow}) => + _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 _i8.Future); + returnValue: Future.value(null)) as _i9.Future); @override bool handleEventLoopCallback() => (super.noSuchMethod(Invocation.method(#handleEventLoopCallback, []), returnValue: false) as bool); @override - int scheduleFrameCallback(_i9.FrameCallback? callback, + int scheduleFrameCallback(_i11.FrameCallback? callback, {bool? rescheduling = false}) => (super.noSuchMethod( Invocation.method(#scheduleFrameCallback, [callback], @@ -456,11 +594,11 @@ class MockWidgetsBinding extends _i1.Mock implements _i7.WidgetsBinding { Invocation.method(#debugAssertNoTransientCallbacks, [reason]), returnValue: false) as bool); @override - void addPersistentFrameCallback(_i9.FrameCallback? callback) => super + void addPersistentFrameCallback(_i11.FrameCallback? callback) => super .noSuchMethod(Invocation.method(#addPersistentFrameCallback, [callback]), returnValueForMissingStub: null); @override - void addPostFrameCallback(_i9.FrameCallback? callback) => + void addPostFrameCallback(_i11.FrameCallback? callback) => super.noSuchMethod(Invocation.method(#addPostFrameCallback, [callback]), returnValueForMissingStub: null); @override @@ -499,21 +637,21 @@ class MockWidgetsBinding extends _i1.Mock implements _i7.WidgetsBinding { super.noSuchMethod(Invocation.method(#cancelPointer, [pointer]), returnValueForMissingStub: null); @override - void handlePointerEvent(_i3.PointerEvent? event) => + void handlePointerEvent(_i6.PointerEvent? event) => super.noSuchMethod(Invocation.method(#handlePointerEvent, [event]), returnValueForMissingStub: null); @override - void hitTest(_i3.HitTestResult? result, _i4.Offset? position) => + void hitTest(_i6.HitTestResult? result, _i4.Offset? position) => super.noSuchMethod(Invocation.method(#hitTest, [result, position]), returnValueForMissingStub: null); @override void dispatchEvent( - _i3.PointerEvent? event, _i3.HitTestResult? hitTestResult) => + _i6.PointerEvent? event, _i6.HitTestResult? hitTestResult) => super.noSuchMethod( Invocation.method(#dispatchEvent, [event, hitTestResult]), returnValueForMissingStub: null); @override - void handleEvent(_i3.PointerEvent? event, _i3.HitTestEntry? entry) => + void handleEvent(_i6.PointerEvent? event, _i6.HitTestEntry? entry) => super.noSuchMethod(Invocation.method(#handleEvent, [event, entry]), returnValueForMissingStub: null); @override @@ -525,11 +663,11 @@ class MockWidgetsBinding extends _i1.Mock implements _i7.WidgetsBinding { super.noSuchMethod(Invocation.method(#initRenderView, []), returnValueForMissingStub: null); @override - _i3.ViewConfiguration createViewConfiguration() => + _i7.ViewConfiguration createViewConfiguration() => (super.noSuchMethod(Invocation.method(#createViewConfiguration, []), - returnValue: _FakeViewConfiguration_16()) as _i3.ViewConfiguration); + returnValue: _FakeViewConfiguration_16()) as _i7.ViewConfiguration); @override - void initMouseTracker([_i3.MouseTracker? tracker]) => + void initMouseTracker([_i7.MouseTracker? tracker]) => super.noSuchMethod(Invocation.method(#initMouseTracker, [tracker]), returnValueForMissingStub: null); @override @@ -612,140 +750,6 @@ class MockFrameTiming extends _i1.Mock implements _i4.FrameTiming { 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 _i13.ApmHostApi { - MockApmHostApi() { - _i1.throwOnMissingStub(this); - } - - @override - _i8.Future setEnabled(bool? arg_isEnabled) => - (super.noSuchMethod(Invocation.method(#setEnabled, [arg_isEnabled]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i8.Future); - @override - _i8.Future isEnabled() => - (super.noSuchMethod(Invocation.method(#isEnabled, []), - returnValue: Future.value(false)) as _i8.Future); - @override - _i8.Future setScreenLoadingEnabled(bool? arg_isEnabled) => - (super.noSuchMethod( - Invocation.method(#setScreenLoadingEnabled, [arg_isEnabled]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i8.Future); - @override - _i8.Future isScreenLoadingEnabled() => - (super.noSuchMethod(Invocation.method(#isScreenLoadingEnabled, []), - returnValue: Future.value(false)) as _i8.Future); - @override - _i8.Future setColdAppLaunchEnabled(bool? arg_isEnabled) => - (super.noSuchMethod( - Invocation.method(#setColdAppLaunchEnabled, [arg_isEnabled]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i8.Future); - @override - _i8.Future setAutoUITraceEnabled(bool? arg_isEnabled) => (super - .noSuchMethod(Invocation.method(#setAutoUITraceEnabled, [arg_isEnabled]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i8.Future); - @override - _i8.Future startFlow(String? arg_name) => - (super.noSuchMethod(Invocation.method(#startFlow, [arg_name]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i8.Future); - @override - _i8.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 _i8.Future); - @override - _i8.Future endFlow(String? arg_name) => - (super.noSuchMethod(Invocation.method(#endFlow, [arg_name]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i8.Future); - @override - _i8.Future startUITrace(String? arg_name) => - (super.noSuchMethod(Invocation.method(#startUITrace, [arg_name]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i8.Future); - @override - _i8.Future endUITrace() => - (super.noSuchMethod(Invocation.method(#endUITrace, []), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i8.Future); - @override - _i8.Future endAppLaunch() => - (super.noSuchMethod(Invocation.method(#endAppLaunch, []), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i8.Future); - @override - _i8.Future networkLogAndroid(Map? arg_data) => - (super.noSuchMethod(Invocation.method(#networkLogAndroid, [arg_data]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i8.Future); - @override - _i8.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 _i8.Future); - @override - _i8.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 _i8.Future); - @override - _i8.Future endScreenLoadingCP( - int? arg_timeStampMicro, int? arg_uiTraceId) => - (super.noSuchMethod( - Invocation.method( - #endScreenLoadingCP, [arg_timeStampMicro, arg_uiTraceId]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i8.Future); - @override - _i8.Future isEndScreenLoadingEnabled() => - (super.noSuchMethod(Invocation.method(#isEndScreenLoadingEnabled, []), - returnValue: Future.value(false)) as _i8.Future); - @override - _i8.Future isScreenRenderEnabled() => - (super.noSuchMethod(Invocation.method(#isScreenRenderEnabled, []), - returnValue: Future.value(false)) as _i8.Future); - @override - _i8.Future> getDeviceRefreshRateAndTolerance() => - (super.noSuchMethod( - Invocation.method(#getDeviceRefreshRateAndTolerance, []), - returnValue: Future>.value([])) - as _i8.Future>); - @override - _i8.Future setScreenRenderEnabled(bool? arg_isEnabled) => (super - .noSuchMethod(Invocation.method(#setScreenRenderEnabled, [arg_isEnabled]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i8.Future); - @override - _i8.Future endScreenRenderForAutoUiTrace( - Map? arg_data) => - (super.noSuchMethod( - Invocation.method(#endScreenRenderForAutoUiTrace, [arg_data]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i8.Future); - @override - _i8.Future endScreenRenderForCustomUiTrace( - Map? arg_data) => - (super.noSuchMethod( - Invocation.method(#endScreenRenderForCustomUiTrace, [arg_data]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i8.Future); -} - /// A class which mocks [CrashReportingHostApi]. /// /// See the documentation for Mockito's code generation for more information. @@ -756,17 +760,17 @@ class MockCrashReportingHostApi extends _i1.Mock } @override - _i8.Future setEnabled(bool? arg_isEnabled) => + _i9.Future setEnabled(bool? arg_isEnabled) => (super.noSuchMethod(Invocation.method(#setEnabled, [arg_isEnabled]), returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i8.Future); + returnValueForMissingStub: Future.value()) as _i9.Future); @override - _i8.Future send(String? arg_jsonCrash, bool? arg_isHandled) => (super + _i9.Future send(String? arg_jsonCrash, bool? arg_isHandled) => (super .noSuchMethod(Invocation.method(#send, [arg_jsonCrash, arg_isHandled]), returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i8.Future); + returnValueForMissingStub: Future.value()) as _i9.Future); @override - _i8.Future sendNonFatalError( + _i9.Future sendNonFatalError( String? arg_jsonCrash, Map? arg_userAttributes, String? arg_fingerprint, @@ -779,7 +783,7 @@ class MockCrashReportingHostApi extends _i1.Mock arg_nonFatalExceptionLevel ]), returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i8.Future); + returnValueForMissingStub: Future.value()) as _i9.Future); } /// A class which mocks [InstabugLogger]. 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 b97d312a0..d3117c7ca 100644 --- a/test/utils/screen_render/instabug_widget_binding_observer_test.dart +++ b/test/utils/screen_render/instabug_widget_binding_observer_test.dart @@ -73,15 +73,6 @@ void main() { verify(mockRenderManager.stopScreenRenderCollector()).called(1); }); - test('handles AppLifecycleState.detached and stops render collector', () { - when(mockRenderManager.screenRenderEnabled).thenReturn(true); - - InstabugWidgetsBindingObserver.I - .didChangeAppLifecycleState(AppLifecycleState.detached); - - verify(mockRenderManager.stopScreenRenderCollector()).called(1); - }); - test('handles AppLifecycleState.inactive with no action', () { // Just ensure it doesn't crash expect(