Skip to content

Commit 2faf643

Browse files
chore: add unit tests for app lifecycle
1 parent 7064e0e commit 2faf643

File tree

2 files changed

+111
-2
lines changed

2 files changed

+111
-2
lines changed

lib/src/utils/screen_rendering/instabug_screen_render_manager.dart

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class InstabugScreenRenderManager {
4040

4141
InstabugScreenRenderManager._();
4242

43-
static final InstabugScreenRenderManager _instance =
43+
static InstabugScreenRenderManager _instance =
4444
InstabugScreenRenderManager._();
4545

4646
/// Returns the singleton instance of [InstabugScreenRenderManager].
@@ -53,10 +53,16 @@ class InstabugScreenRenderManager {
5353
static const tag = "ScreenRenderManager";
5454

5555
/// A named constructor used for testing purposes
56-
56+
@internal
5757
@visibleForTesting
5858
InstabugScreenRenderManager.init();
5959

60+
/// Allows setting a custom instance for testing.
61+
@visibleForTesting
62+
// ignore: use_setters_to_change_properties
63+
static void setInstance(InstabugScreenRenderManager instance) {
64+
_instance = instance;
65+
}
6066
/// setup function for [InstabugScreenRenderManager]
6167
@internal
6268
Future<void> init(WidgetsBinding widgetBinding) async {
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import 'package:flutter/widgets.dart';
2+
import 'package:flutter_test/flutter_test.dart';
3+
import 'package:instabug_flutter/src/utils/screen_loading/screen_loading_manager.dart';
4+
import 'package:instabug_flutter/src/utils/screen_name_masker.dart';
5+
import 'package:instabug_flutter/src/utils/screen_rendering/instabug_screen_render_manager.dart';
6+
import 'package:instabug_flutter/src/utils/screen_rendering/instabug_widget_binding_observer.dart';
7+
import 'package:instabug_flutter/src/utils/ui_trace/ui_trace.dart';
8+
import 'package:mockito/annotations.dart';
9+
import 'package:mockito/mockito.dart';
10+
11+
import 'instabug_widget_binding_observer_test.mocks.dart';
12+
13+
@GenerateMocks([
14+
InstabugScreenRenderManager,
15+
ScreenLoadingManager,
16+
ScreenNameMasker,
17+
UiTrace,
18+
])
19+
void main() {
20+
late MockInstabugScreenRenderManager mockRenderManager;
21+
late MockScreenLoadingManager mockLoadingManager;
22+
late MockScreenNameMasker mockNameMasker;
23+
late MockUiTrace mockUiTrace;
24+
25+
setUp(() {
26+
mockRenderManager = MockInstabugScreenRenderManager();
27+
mockLoadingManager = MockScreenLoadingManager();
28+
mockNameMasker = MockScreenNameMasker();
29+
mockUiTrace = MockUiTrace();
30+
31+
// Inject singleton mocks
32+
InstabugScreenRenderManager.setInstance(mockRenderManager);
33+
ScreenLoadingManager.setInstance(mockLoadingManager);
34+
ScreenNameMasker.setInstance(mockNameMasker);
35+
});
36+
37+
group('InstabugWidgetsBindingObserver', () {
38+
test('returns the singleton instance', () {
39+
final instance = InstabugWidgetsBindingObserver.instance;
40+
final shorthand = InstabugWidgetsBindingObserver.I;
41+
expect(instance, isA<InstabugWidgetsBindingObserver>());
42+
expect(shorthand, same(instance));
43+
});
44+
45+
test('handles AppLifecycleState.resumed and starts UiTrace', () async {
46+
when(mockLoadingManager.currentUiTrace).thenReturn(mockUiTrace);
47+
when(mockUiTrace.screenName).thenReturn("HomeScreen");
48+
when(mockNameMasker.mask("HomeScreen")).thenReturn("MaskedHome");
49+
when(mockLoadingManager.startUiTrace("MaskedHome", "HomeScreen"))
50+
.thenAnswer((_) async => 123);
51+
52+
InstabugWidgetsBindingObserver.I
53+
.didChangeAppLifecycleState(AppLifecycleState.resumed);
54+
55+
// wait for async call to complete
56+
await untilCalled(
57+
mockRenderManager.startScreenRenderCollectorForTraceId(123));
58+
59+
verify(mockRenderManager.startScreenRenderCollectorForTraceId(123))
60+
.called(1);
61+
});
62+
63+
test('handles AppLifecycleState.paused and stops render collector', () {
64+
InstabugWidgetsBindingObserver.I
65+
.didChangeAppLifecycleState(AppLifecycleState.paused);
66+
verify(mockRenderManager.stopScreenRenderCollector()).called(1);
67+
});
68+
69+
test('handles AppLifecycleState.detached and stops render collector', () {
70+
InstabugWidgetsBindingObserver.I
71+
.didChangeAppLifecycleState(AppLifecycleState.detached);
72+
verify(mockRenderManager.stopScreenRenderCollector()).called(1);
73+
});
74+
75+
test('handles AppLifecycleState.inactive with no action', () {
76+
// Just ensure it doesn't crash
77+
expect(() {
78+
InstabugWidgetsBindingObserver.I
79+
.didChangeAppLifecycleState(AppLifecycleState.inactive);
80+
}, returnsNormally);
81+
});
82+
83+
test('handles AppLifecycleState.hidden with no action', () {
84+
expect(() {
85+
InstabugWidgetsBindingObserver.I
86+
.didChangeAppLifecycleState(AppLifecycleState.hidden);
87+
}, returnsNormally);
88+
});
89+
90+
test('_handleResumedState does nothing if no currentUiTrace', () {
91+
when(mockLoadingManager.currentUiTrace).thenReturn(null);
92+
93+
InstabugWidgetsBindingObserver.I
94+
.didChangeAppLifecycleState(AppLifecycleState.resumed);
95+
96+
verifyNever(mockRenderManager.startScreenRenderCollectorForTraceId(any));
97+
});
98+
99+
test('checkForWidgetBinding ensures initialization', () {
100+
expect(() => checkForWidgetBinding(), returnsNormally);
101+
});
102+
});
103+
}

0 commit comments

Comments
 (0)