Skip to content

Commit e886d5a

Browse files
committed
fix tests
1 parent 31efee2 commit e886d5a

File tree

2 files changed

+165
-23
lines changed

2 files changed

+165
-23
lines changed

flutter/lib/src/user_interaction/sentry_user_interaction_widget.dart

+2-9
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,6 @@ class _SentryUserInteractionWidgetState
8888
}
8989
final element = tappedWidget.element;
9090

91-
// String? currentRouteName;
92-
// if (element is StatefulElement) {
93-
// currentRouteName = ModalRoute.of(element.state.context)?.settings.name;
94-
// } else if (element is StatelessElement) {
95-
96-
// }
97-
9891
Map<String, dynamic>? data;
9992
// ignore: invalid_use_of_internal_member
10093
if ((_options?.sendDefaultPii ?? false) &&
@@ -109,7 +102,6 @@ class _SentryUserInteractionWidgetState
109102
final crumb = Breadcrumb.userInteraction(
110103
subCategory: category,
111104
viewId: keyValue,
112-
// viewClass: tappedWidget.element.widget.runtimeType.toString(),
113105
viewClass: tappedWidget.type, // to avoid minification
114106
data: data,
115107
);
@@ -122,7 +114,8 @@ class _SentryUserInteractionWidgetState
122114
return;
123115
}
124116

125-
// TODO: name should be screenName.widgetName, maybe get from router?
117+
// getting the name of the screen using ModalRoute.of(context).settings.name
118+
// is expensive, so we expect that the keys are unique across the app
126119
final transactionContext = SentryTransactionContext(
127120
keyValue,
128121
'ui.action.$category',

flutter/test/user_interaction/sentry_user_interaction_widget_test.dart

+163-14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
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';
18
import 'package:flutter/material.dart';
29
import 'package:flutter_test/flutter_test.dart';
310
import 'package:sentry_flutter/sentry_flutter.dart';
11+
import 'package:sentry/src/sentry_tracer.dart';
412

513
import '../mocks.dart';
614
import '../mocks.mocks.dart';
@@ -17,48 +25,179 @@ void main() {
1725
await tester.runAsync(() async {
1826
final sut = fixture.getSut();
1927

20-
await tapMe(tester, sut, 'Button 1');
28+
await tapMe(tester, sut, 'btn_1');
2129

30+
Breadcrumb? crumb;
2231
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;
2733
});
34+
expect(crumb?.category, 'ui.click');
35+
expect(crumb?.data?['view.id'], 'btn_1');
36+
expect(crumb?.data?['view.class'], 'MaterialButton');
2837
});
2938
});
3039

3140
testWidgets('Add crumb for MaterialButton with label', (tester) async {
3241
await tester.runAsync(() async {
3342
final sut = fixture.getSut(sendDefaultPii: true);
3443

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');
3673

74+
Breadcrumb? crumb;
3775
fixture.hub.configureScope((scope) {
38-
final crumb = scope.breadcrumbs.last;
39-
expect(crumb.data?['label'], 'Button 1');
76+
crumb = scope.breadcrumbs.last;
4077
});
78+
expect(crumb?.data?['label'], 'Button 2');
4179
});
4280
});
4381

44-
testWidgets('Do not add crumb', (tester) async {
82+
testWidgets('Do not add crumb if disabled', (tester) async {
4583
await tester.runAsync(() async {
4684
final sut = fixture.getSut(enableUserInteractionBreadcrumbs: false);
4785

48-
await tapMe(tester, sut, 'Button 1');
86+
await tapMe(tester, sut, 'btn_1');
4987

88+
List<Breadcrumb>? crumbs;
5089
fixture.hub.configureScope((scope) {
51-
expect(scope.breadcrumbs.isEmpty, true);
90+
crumbs = scope.breadcrumbs;
5291
});
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)));
53192
});
54193
});
55194
});
56195
}
57196

58-
Future<void> tapMe(WidgetTester tester, Widget widget, String text) async {
197+
Future<void> tapMe(WidgetTester tester, Widget widget, String key) async {
59198
await tester.pumpWidget(widget);
60199

61-
await tester.tap(find.text(text));
200+
await tester.tap(find.byKey(Key(key)));
62201
}
63202

64203
class Fixture {
@@ -109,13 +248,23 @@ class MyApp extends StatelessWidget {
109248
},
110249
child: const Text('Button 1'),
111250
),
112-
MaterialButton(
251+
CupertinoButton(
113252
key: Key('btn_2'),
114253
onPressed: () {
115254
// print('button pressed 2');
116255
},
117256
child: const Text('Button 2'),
118257
),
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+
),
119268
],
120269
),
121270
),

0 commit comments

Comments
 (0)