1
+ @TestOn ('vm' )
2
+
3
+ // ignore_for_file: invalid_use_of_internal_member
4
+
5
+ import 'dart:async' ;
6
+
7
+ import 'package:flutter/cupertino.dart' ;
1
8
import 'package:flutter/material.dart' ;
2
9
import 'package:flutter_test/flutter_test.dart' ;
3
10
import 'package:sentry_flutter/sentry_flutter.dart' ;
11
+ import 'package:sentry/src/sentry_tracer.dart' ;
4
12
5
13
import '../mocks.dart' ;
6
14
import '../mocks.mocks.dart' ;
@@ -17,48 +25,179 @@ void main() {
17
25
await tester.runAsync (() async {
18
26
final sut = fixture.getSut ();
19
27
20
- await tapMe (tester, sut, 'Button 1 ' );
28
+ await tapMe (tester, sut, 'btn_1 ' );
21
29
30
+ Breadcrumb ? crumb;
22
31
fixture.hub.configureScope ((scope) {
23
- final crumb = scope.breadcrumbs.last;
24
- expect (crumb.category, 'ui.click' );
25
- expect (crumb.data? ['view.id' ], 'btn_1' );
26
- expect (crumb.data? ['view.class' ], 'MaterialButton' );
32
+ crumb = scope.breadcrumbs.last;
27
33
});
34
+ expect (crumb? .category, 'ui.click' );
35
+ expect (crumb? .data? ['view.id' ], 'btn_1' );
36
+ expect (crumb? .data? ['view.class' ], 'MaterialButton' );
28
37
});
29
38
});
30
39
31
40
testWidgets ('Add crumb for MaterialButton with label' , (tester) async {
32
41
await tester.runAsync (() async {
33
42
final sut = fixture.getSut (sendDefaultPii: true );
34
43
35
- await tapMe (tester, sut, 'Button 1' );
44
+ await tapMe (tester, sut, 'btn_1' );
45
+
46
+ Breadcrumb ? crumb;
47
+ fixture.hub.configureScope ((scope) {
48
+ crumb = scope.breadcrumbs.last;
49
+ });
50
+ expect (crumb? .data? ['label' ], 'Button 1' );
51
+ });
52
+ });
53
+
54
+ testWidgets ('Add crumb for Icon with label' , (tester) async {
55
+ await tester.runAsync (() async {
56
+ final sut = fixture.getSut (sendDefaultPii: true );
57
+
58
+ await tapMe (tester, sut, 'btn_3' );
59
+
60
+ Breadcrumb ? crumb;
61
+ fixture.hub.configureScope ((scope) {
62
+ crumb = scope.breadcrumbs.last;
63
+ });
64
+ expect (crumb? .data? ['label' ], 'My Icon' );
65
+ });
66
+ });
67
+
68
+ testWidgets ('Add crumb for CupertinoButton with label' , (tester) async {
69
+ await tester.runAsync (() async {
70
+ final sut = fixture.getSut (sendDefaultPii: true );
71
+
72
+ await tapMe (tester, sut, 'btn_2' );
36
73
74
+ Breadcrumb ? crumb;
37
75
fixture.hub.configureScope ((scope) {
38
- final crumb = scope.breadcrumbs.last;
39
- expect (crumb.data? ['label' ], 'Button 1' );
76
+ crumb = scope.breadcrumbs.last;
40
77
});
78
+ expect (crumb? .data? ['label' ], 'Button 2' );
41
79
});
42
80
});
43
81
44
- testWidgets ('Do not add crumb' , (tester) async {
82
+ testWidgets ('Do not add crumb if disabled ' , (tester) async {
45
83
await tester.runAsync (() async {
46
84
final sut = fixture.getSut (enableUserInteractionBreadcrumbs: false );
47
85
48
- await tapMe (tester, sut, 'Button 1 ' );
86
+ await tapMe (tester, sut, 'btn_1 ' );
49
87
88
+ List <Breadcrumb >? crumbs;
50
89
fixture.hub.configureScope ((scope) {
51
- expect ( scope.breadcrumbs.isEmpty, true ) ;
90
+ crumbs = scope.breadcrumbs;
52
91
});
92
+ expect (crumbs? .isEmpty, true );
93
+ });
94
+ });
95
+ });
96
+
97
+ group ('$SentryUserInteractionWidget performance' , () {
98
+ late Fixture fixture;
99
+ setUp (() async {
100
+ fixture = Fixture ();
101
+ TestWidgetsFlutterBinding .ensureInitialized ();
102
+ });
103
+
104
+ testWidgets ('Start transaction and set in the scope' , (tester) async {
105
+ await tester.runAsync (() async {
106
+ final sut = fixture.getSut (
107
+ enableUserInteractionTracing: true ,
108
+ enableUserInteractionBreadcrumbs: false );
109
+
110
+ await tapMe (tester, sut, 'btn_1' );
111
+
112
+ SentryTracer ? tracer;
113
+ fixture.hub.configureScope ((scope) {
114
+ tracer = (scope.span as SentryTracer );
115
+ });
116
+ expect (tracer? .name, 'btn_1' );
117
+ expect (tracer? .context.operation, 'ui.action.click' );
118
+ expect (tracer? .transactionNameSource,
119
+ SentryTransactionNameSource .component);
120
+ expect (tracer? .autoFinishAfterTimer, isNotNull);
121
+ });
122
+ });
123
+
124
+ testWidgets ('Start transaction and do not set in the scope if any' ,
125
+ (tester) async {
126
+ await tester.runAsync (() async {
127
+ final sut = fixture.getSut (
128
+ enableUserInteractionTracing: true ,
129
+ enableUserInteractionBreadcrumbs: false );
130
+
131
+ fixture.hub.configureScope ((scope) {
132
+ scope.span = NoOpSentrySpan ();
133
+ });
134
+
135
+ await tapMe (tester, sut, 'btn_1' );
136
+
137
+ ISentrySpan ? span;
138
+ fixture.hub.configureScope ((scope) {
139
+ span = scope.span;
140
+ });
141
+ expect (span, NoOpSentrySpan ());
142
+ });
143
+ });
144
+
145
+ testWidgets ('Extend timer if transaction already started for same widget' ,
146
+ (tester) async {
147
+ await tester.runAsync (() async {
148
+ final sut = fixture.getSut (
149
+ enableUserInteractionTracing: true ,
150
+ enableUserInteractionBreadcrumbs: false );
151
+
152
+ await tapMe (tester, sut, 'btn_1' );
153
+ Timer ? currentTimer;
154
+
155
+ fixture.hub.configureScope ((scope) {
156
+ final tracer = (scope.span as SentryTracer );
157
+ currentTimer = tracer.autoFinishAfterTimer;
158
+ });
159
+
160
+ await tapMe (tester, sut, 'btn_1' );
161
+
162
+ Timer ? autoFinishAfterTimer;
163
+ fixture.hub.configureScope ((scope) {
164
+ final tracer = (scope.span as SentryTracer );
165
+ autoFinishAfterTimer = tracer.autoFinishAfterTimer;
166
+ });
167
+ expect (currentTimer, isNot (equals (autoFinishAfterTimer)));
168
+ });
169
+ });
170
+
171
+ testWidgets ('Finish transaction and start new one if new tap' ,
172
+ (tester) async {
173
+ await tester.runAsync (() async {
174
+ final sut = fixture.getSut (
175
+ enableUserInteractionTracing: true ,
176
+ enableUserInteractionBreadcrumbs: false );
177
+
178
+ await tapMe (tester, sut, 'btn_1' );
179
+ SentryTracer ? currentTracer;
180
+
181
+ fixture.hub.configureScope ((scope) {
182
+ currentTracer = (scope.span as SentryTracer );
183
+ });
184
+
185
+ await tapMe (tester, sut, 'btn_2' );
186
+
187
+ SentryTracer ? tracer;
188
+ fixture.hub.configureScope ((scope) {
189
+ tracer = (scope.span as SentryTracer );
190
+ });
191
+ expect (currentTracer, isNot (equals (tracer)));
53
192
});
54
193
});
55
194
});
56
195
}
57
196
58
- Future <void > tapMe (WidgetTester tester, Widget widget, String text ) async {
197
+ Future <void > tapMe (WidgetTester tester, Widget widget, String key ) async {
59
198
await tester.pumpWidget (widget);
60
199
61
- await tester.tap (find.text (text ));
200
+ await tester.tap (find.byKey ( Key (key) ));
62
201
}
63
202
64
203
class Fixture {
@@ -109,13 +248,23 @@ class MyApp extends StatelessWidget {
109
248
},
110
249
child: const Text ('Button 1' ),
111
250
),
112
- MaterialButton (
251
+ CupertinoButton (
113
252
key: Key ('btn_2' ),
114
253
onPressed: () {
115
254
// print('button pressed 2');
116
255
},
117
256
child: const Text ('Button 2' ),
118
257
),
258
+ IconButton (
259
+ key: Key ('btn_3' ),
260
+ onPressed: () {
261
+ // print('button pressed 3');
262
+ },
263
+ icon: Icon (
264
+ Icons .dark_mode,
265
+ semanticLabel: 'My Icon' ,
266
+ ),
267
+ ),
119
268
],
120
269
),
121
270
),
0 commit comments