1+ import 'package:flutter/foundation.dart' ;
2+ import 'package:flutter_test/flutter_test.dart' ;
3+ import 'package:patrol/patrol.dart' ;
4+
5+ import 'utils/utils.dart' ;
6+
7+ Future <void > assertOptionsPromptIsDisplayed (PatrolIntegrationTester $) async {
8+ final floatingButton = await $.native2.getNativeViews (NativeSelector (
9+ ios: IOSSelector (
10+ identifier: 'IBGReportBugPromptOptionAccessibilityIdentifier' ),
11+ android: AndroidSelector (
12+ resourceName:
13+ 'com.instabug.flutter.example:id/instabug_main_prompt_container' )));
14+
15+ expect (
16+ isAndroid
17+ ? floatingButton.androidViews.length
18+ : floatingButton.iosViews.length,
19+ greaterThanOrEqualTo (1 ));
20+ }
21+
22+ void main () {
23+ group ('Bug reporting end-to-end test' , () {
24+ patrolTest (
25+ 'Report a bug' ,
26+ ($) async {
27+ await init ($);
28+
29+ await $.native2.tap (NativeSelector (
30+ ios: IOSSelector (
31+ identifier: 'IBGFloatingButtonAccessibilityIdentifier' ),
32+ android: AndroidSelector (
33+ resourceName:
34+ 'com.instabug.flutter.example:id/instabug_floating_button' )));
35+
36+ await $.native2.tap (NativeSelector (
37+ ios: IOSSelector (labelContains: 'Report a bug' ),
38+ android: AndroidSelector (textContains: 'Report a bug' )));
39+
40+ await $.native2.enterText (
41+ NativeSelector (
42+ ios: IOSSelector (
43+ identifier:
44+ 'IBGBugInputViewEmailFieldAccessibilityIdentifier' ),
45+ android: AndroidSelector (
46+ resourceName:
47+ 'com.instabug.flutter.example:id/instabug_edit_text_email' )),
48+ 49+ );
50+
51+ await $.native2.tap (NativeSelector (
52+ ios: IOSSelector (
53+ identifier: 'IBGBugVCNextButtonAccessibilityIdentifier' ),
54+ android: AndroidSelector (
55+ resourceName:
56+ 'com.instabug.flutter.example:id/instabug_bugreporting_send' )));
57+
58+ bool isAndroid = defaultTargetPlatform == TargetPlatform .android;
59+ if (isAndroid == false ) {
60+ await Future .delayed (const Duration (milliseconds: 500 ));
61+ }
62+ final thankyou =
63+ await $.native .getNativeViews (Selector (textContains: "Thank you" ));
64+
65+ expect (thankyou.length, greaterThanOrEqualTo (1 ));
66+ },
67+ framePolicy: LiveTestWidgetsFlutterBindingFramePolicy .fullyLive,
68+ );
69+
70+ patrolTest (
71+ 'Floating Button Invocation Event' ,
72+ ($) async {
73+ await init ($);
74+
75+ await $.native2.tap (NativeSelector (
76+ ios: IOSSelector (
77+ identifier: 'IBGFloatingButtonAccessibilityIdentifier' ),
78+ android: AndroidSelector (
79+ resourceName:
80+ 'com.instabug.flutter.example:id/instabug_floating_button' )));
81+
82+ assertOptionsPromptIsDisplayed ($);
83+ },
84+ framePolicy: LiveTestWidgetsFlutterBindingFramePolicy .fullyLive,
85+ );
86+
87+ patrolTest (
88+ 'TwoFingers Swipe Left Invocation Event' ,
89+ ($) async {
90+ await init ($);
91+
92+ await $("Two Fingers Swipe Left" ).scrollTo ().tap ();
93+ await wait (second: 1 );
94+ final gesture1 = await $.tester.startGesture (const Offset (300 , 400 )); // finger 1
95+ final gesture2 = await $.tester.startGesture (const Offset (300 , 600 )); // finger 2
96+
97+ // Swipe both fingers to the left (same direction)
98+ await gesture1.moveBy (const Offset (- 150 , 0 ));
99+ await gesture2.moveBy (const Offset (- 150 , 0 ));
100+
101+ // End gestures
102+ await gesture1.up ();
103+ await gesture2.up ();
104+
105+ await wait (second: 1 );
106+ assertOptionsPromptIsDisplayed ($);
107+ },
108+ framePolicy: LiveTestWidgetsFlutterBindingFramePolicy .fullyLive,
109+ );
110+ patrolTest ('None Invocation Event hides floating button' , ($) async {
111+ await init ($);
112+
113+ await $('None' ).scrollTo ().tap ();
114+
115+ await wait (second: 1 );
116+ final floatingButton = await $.native2.getNativeViews (NativeSelector (
117+ ios: IOSSelector (identifier: 'IBGFloatingButtonAccessibilityIdentifier' ),
118+ android: AndroidSelector (
119+ resourceName:
120+ 'com.instabug.flutter.example:id/instabug_floating_button' ),
121+ ));
122+
123+ expect (
124+ isAndroid
125+ ? floatingButton.androidViews.length
126+ : floatingButton.iosViews.length,
127+ equals (0 ));
128+ });
129+
130+ patrolTest ('Manual Invocation shows prompt options' , ($) async {
131+ await init ($);
132+
133+ await $('Invoke' ).scrollTo ().tap ();
134+
135+ await assertOptionsPromptIsDisplayed ($);
136+ });
137+
138+ patrolTest ('Multiple Screenshots in Repro Steps' , ($) async {
139+ await init ($);
140+
141+ await $(#screen_name_input).scrollTo ().enterText ('My Screen' );
142+
143+ await wait (miliSeconds: 500 );
144+
145+ await $('Report Screen Change' ).scrollTo ().tap ();
146+ await wait (miliSeconds: 500 );
147+ await $('Send Bug Report' ).scrollTo ().tap ();
148+
149+ await $.native2.tap (NativeSelector (
150+ ios: IOSSelector (
151+ identifier: 'IBGBugVCReproStepsDisclaimerAccessibilityIdentifier' ),
152+ android: AndroidSelector (
153+ resourceName:
154+ 'com.instabug.flutter.example:id/instabug_text_view_repro_steps_disclaimer' ),
155+ ));
156+
157+ await wait (miliSeconds: 1000 );
158+
159+ final screenshots = await $.native2.getNativeViews (NativeSelector (
160+ ios: IOSSelector (
161+ identifier: 'IBGReproStepsTableCellViewAccessibilityIdentifier' ),
162+ android: AndroidSelector (
163+ resourceName:
164+ 'com.instabug.flutter.example:id/ib_bug_repro_step_screenshot' ),
165+ ));
166+
167+ final count = isAndroid
168+ ? screenshots.androidViews.length
169+ : screenshots.iosViews.length;
170+
171+ expect (count, 2 );
172+ });
173+
174+ patrolTest ('Floating Button moves to left edge' , ($) async {
175+ await init ($);
176+
177+ await $('Move Floating Button to Left' ).scrollTo ().tap ();
178+
179+
180+ await wait (second: 5 );
181+
182+ final floatingButton = await $.native2.getNativeViews (NativeSelector (
183+ ios: IOSSelector (
184+ identifier: 'IBGFloatingButtonAccessibilityIdentifier' ),
185+ android: AndroidSelector (
186+ resourceName:
187+ 'com.instabug.flutter.example:id/instabug_floating_button' ),
188+ ));
189+
190+
191+ await wait (second: 2 );
192+
193+ final size = $.tester.view.physicalSize / $.tester.view.devicePixelRatio;
194+ final width = size.width;
195+ $.log (floatingButton.androidViews.length.toString ());
196+
197+ $.log (floatingButton.androidViews.first.visibleBounds.minX.toString ());
198+ $.log (floatingButton.androidViews.first.visibleBounds.maxX.toString ());
199+ $.log ((width / 2 ).toString ());
200+
201+
202+ bool isLeft = false ;
203+ if (isAndroid &&
204+ floatingButton.androidViews.isNotEmpty) {
205+
206+
207+ $.log (floatingButton.androidViews.first.visibleBounds.minX.toString ());
208+ $.log (floatingButton.androidViews.first.visibleBounds.maxX.toString ());
209+ $.log ((width / 2 ).toString ());
210+
211+ isLeft = floatingButton.androidViews.first.visibleBounds.minX <
212+ (width / 2 );
213+ } else if ((! isAndroid) &&
214+ floatingButton.iosViews.isNotEmpty) {
215+ isLeft = floatingButton.iosViews.first.frame.minX <
216+ (width / 2 );
217+ }
218+
219+ expect (isLeft, true );
220+ });
221+
222+ patrolTest (
223+ 'onDismiss callback triggers when prompt is cancelled' , ($) async {
224+ await init ($);
225+
226+ await $('Set On Dismiss Callback' ).scrollTo ().tap ();
227+ await wait (second: 4 );
228+ await $('Invoke' ).scrollTo ().tap ();
229+
230+ await wait (second: 4 );
231+
232+ await $.native2.tap (NativeSelector (
233+ android: AndroidSelector (text: 'Cancel' ),
234+ ios: IOSSelector (label: 'Cancel' ),
235+ ));
236+
237+ await wait (second: 4 );
238+
239+ final callbackWidget = $('onDismiss callback called with DismissType.cancel and ReportType.other' );
240+ expect (callbackWidget, findsOneWidget);
241+ });
242+
243+ });
244+
245+ }
0 commit comments