Skip to content

Commit dd15eaa

Browse files
committed
update tests
1 parent d913348 commit dd15eaa

File tree

2 files changed

+216
-60
lines changed

2 files changed

+216
-60
lines changed

flutter/lib/src/user_interaction/sentry_user_interaction_widget.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ class _SentryUserInteractionWidgetState
382382
return false;
383383
}
384384

385-
final widgetName = element.widget.toStringShort();
385+
final widgetName = element.widget.runtimeType.toString();
386386
if (!widgetName.startsWith('_')) {
387387
final info = {
388388
'name': WidgetUtils.toStringValue(element.widget.key),

flutter/test/user_interaction/sentry_user_interaction_widget_test.dart

+215-59
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,24 @@ void main() {
109109

110110
await tapMe(tester, sut, 'btn_1');
111111

112-
Breadcrumb? crumb;
113-
fixture.hub.configureScope((scope) {
114-
crumb = scope.breadcrumbs.last;
115-
});
116-
expect(crumb?.category, 'ui.click');
117-
expect(crumb?.data?['view.id'], 'btn_1');
118-
expect(crumb?.data?['view.class'], 'MaterialButton');
112+
expect(
113+
fixture.getBreadcrumb().data?.replaceHashCodes(),
114+
equals({
115+
'path': [
116+
{'name': 'btn_1', 'element': 'MaterialButton'},
117+
{'element': 'Column'},
118+
{'element': 'Center'},
119+
{'name': '[GlobalKey#00000]', 'element': 'KeyedSubtree'},
120+
{'element': 'MediaQuery'},
121+
{'name': '_ScaffoldSlot.body', 'element': 'LayoutId'},
122+
{'element': 'CustomMultiChildLayout'},
123+
{'element': 'Actions'},
124+
{'element': 'AnimatedBuilder'},
125+
{'element': 'DefaultTextStyle'}
126+
],
127+
'view.id': 'btn_1',
128+
'view.class': 'MaterialButton',
129+
}));
119130
});
120131
});
121132

@@ -125,11 +136,25 @@ void main() {
125136

126137
await tapMe(tester, sut, 'btn_1');
127138

128-
Breadcrumb? crumb;
129-
fixture.hub.configureScope((scope) {
130-
crumb = scope.breadcrumbs.last;
131-
});
132-
expect(crumb?.data?['label'], 'Button 1');
139+
expect(
140+
fixture.getBreadcrumb().data?.replaceHashCodes(),
141+
equals({
142+
'path': [
143+
{'name': 'btn_1', 'element': 'MaterialButton'},
144+
{'element': 'Column'},
145+
{'element': 'Center'},
146+
{'name': '[GlobalKey#00000]', 'element': 'KeyedSubtree'},
147+
{'element': 'MediaQuery'},
148+
{'name': '_ScaffoldSlot.body', 'element': 'LayoutId'},
149+
{'element': 'CustomMultiChildLayout'},
150+
{'element': 'Actions'},
151+
{'element': 'AnimatedBuilder'},
152+
{'element': 'DefaultTextStyle'}
153+
],
154+
'label': 'Button 1',
155+
'view.id': 'btn_1',
156+
'view.class': 'MaterialButton'
157+
}));
133158
});
134159
});
135160

@@ -139,11 +164,25 @@ void main() {
139164

140165
await tapMe(tester, sut, 'btn_3');
141166

142-
Breadcrumb? crumb;
143-
fixture.hub.configureScope((scope) {
144-
crumb = scope.breadcrumbs.last;
145-
});
146-
expect(crumb?.data?['label'], 'My Icon');
167+
expect(
168+
fixture.getBreadcrumb().data?.replaceHashCodes(),
169+
equals({
170+
'path': [
171+
{'name': 'btn_3', 'element': 'IconButton'},
172+
{'element': 'Column'},
173+
{'element': 'Center'},
174+
{'name': '[GlobalKey#00000]', 'element': 'KeyedSubtree'},
175+
{'element': 'MediaQuery'},
176+
{'name': '_ScaffoldSlot.body', 'element': 'LayoutId'},
177+
{'element': 'CustomMultiChildLayout'},
178+
{'element': 'Actions'},
179+
{'element': 'AnimatedBuilder'},
180+
{'element': 'DefaultTextStyle'}
181+
],
182+
'label': 'My Icon',
183+
'view.id': 'btn_3',
184+
'view.class': 'IconButton'
185+
}));
147186
});
148187
});
149188

@@ -153,11 +192,25 @@ void main() {
153192

154193
await tapMe(tester, sut, 'btn_2');
155194

156-
Breadcrumb? crumb;
157-
fixture.hub.configureScope((scope) {
158-
crumb = scope.breadcrumbs.last;
159-
});
160-
expect(crumb?.data?['label'], 'Button 2');
195+
expect(
196+
fixture.getBreadcrumb().data?.replaceHashCodes(),
197+
equals({
198+
'path': [
199+
{'name': 'btn_2', 'element': 'CupertinoButton'},
200+
{'element': 'Column'},
201+
{'element': 'Center'},
202+
{'name': '[GlobalKey#00000]', 'element': 'KeyedSubtree'},
203+
{'element': 'MediaQuery'},
204+
{'name': '_ScaffoldSlot.body', 'element': 'LayoutId'},
205+
{'element': 'CustomMultiChildLayout'},
206+
{'element': 'Actions'},
207+
{'element': 'AnimatedBuilder'},
208+
{'element': 'DefaultTextStyle'}
209+
],
210+
'label': 'Button 2',
211+
'view.id': 'btn_2',
212+
'view.class': 'CupertinoButton'
213+
}));
161214
});
162215
});
163216

@@ -183,11 +236,25 @@ void main() {
183236

184237
await tapMe(tester, sut, 'btn_5');
185238

186-
Breadcrumb? crumb;
187-
fixture.hub.configureScope((scope) {
188-
crumb = scope.breadcrumbs.last;
189-
});
190-
expect(crumb?.data?['label'], 'Button 5');
239+
expect(
240+
fixture.getBreadcrumb().data?.replaceHashCodes(),
241+
equals({
242+
'path': [
243+
{'name': 'btn_5', 'element': 'ButtonStyleButton'},
244+
{'element': 'Stack'},
245+
{'element': 'Listener'},
246+
{'element': 'RawGestureDetector'},
247+
{'name': 'btn_4', 'element': 'GestureDetector'},
248+
{'element': 'Semantics'},
249+
{'element': 'DefaultTextStyle'},
250+
{'element': 'AnimatedDefaultTextStyle'},
251+
{'element': 'NotificationListener<LayoutChangedNotification>'},
252+
{'element': 'CustomPaint'}
253+
],
254+
'label': 'Button 5',
255+
'view.id': 'btn_5',
256+
'view.class': 'ButtonStyleButton'
257+
}));
191258
});
192259
});
193260

@@ -197,13 +264,24 @@ void main() {
197264

198265
await tapMe(tester, sut, 'popup_menu_button');
199266

200-
Breadcrumb? crumb;
201-
fixture.hub.configureScope((scope) {
202-
crumb = scope.breadcrumbs.last;
203-
});
204-
expect(crumb?.category, 'ui.click');
205-
expect(crumb?.data?['view.id'], 'popup_menu_button');
206-
expect(crumb?.data?['view.class'], 'PopupMenuButton');
267+
expect(
268+
fixture.getBreadcrumb().data?.replaceHashCodes(),
269+
equals({
270+
'path': [
271+
{'name': 'popup_menu_button', 'element': 'PopupMenuButton'},
272+
{'element': 'Column'},
273+
{'element': 'Center'},
274+
{'name': '[GlobalKey#00000]', 'element': 'KeyedSubtree'},
275+
{'element': 'MediaQuery'},
276+
{'name': '_ScaffoldSlot.body', 'element': 'LayoutId'},
277+
{'element': 'CustomMultiChildLayout'},
278+
{'element': 'Actions'},
279+
{'element': 'AnimatedBuilder'},
280+
{'element': 'DefaultTextStyle'}
281+
],
282+
'view.id': 'popup_menu_button',
283+
'view.class': 'PopupMenuButton'
284+
}));
207285
});
208286
});
209287

@@ -217,13 +295,56 @@ void main() {
217295

218296
await tapMe(tester, sut, 'popup_menu_item_1');
219297

220-
Breadcrumb? crumb;
221-
fixture.hub.configureScope((scope) {
222-
crumb = scope.breadcrumbs.last;
223-
});
224-
expect(crumb?.category, 'ui.click');
225-
expect(crumb?.data?['view.id'], 'popup_menu_item_1');
226-
expect(crumb?.data?['view.class'], 'PopupMenuItem');
298+
expect(
299+
fixture.getBreadcrumb().data?.replaceHashCodes(),
300+
equals({
301+
'path': [
302+
{'name': 'popup_menu_item_1', 'element': 'PopupMenuItem'},
303+
{'name': '[GlobalKey#00000]', 'element': 'FadeTransition'},
304+
{'element': 'ListBody'},
305+
{'element': 'Padding'},
306+
{'name': '[GlobalKey#00000]', 'element': 'IgnorePointer'},
307+
{'element': 'Semantics'},
308+
{'element': 'Listener'},
309+
{
310+
'name': '[LabeledGlobalKey<RawGestureDetectorState>#00000]',
311+
'element': 'RawGestureDetector'
312+
},
313+
{'element': 'Listener'},
314+
{'element': 'NotificationListener<ScrollMetricsNotification>'}
315+
],
316+
'view.id': 'popup_menu_item_1',
317+
'view.class': 'PopupMenuItem'
318+
}));
319+
});
320+
});
321+
322+
testWidgets('Add crumb for button with tooltip', (tester) async {
323+
await tester.runAsync(() async {
324+
final sut = fixture.getSut(sendDefaultPii: true);
325+
326+
// open the popup menu and wait for the animation to complete
327+
await tapMe(tester, sut, 'tooltip_button');
328+
329+
expect(
330+
fixture.getBreadcrumb().data?.replaceHashCodes(),
331+
equals({
332+
'path': [
333+
{'name': 'tooltip_button', 'element': 'ButtonStyleButton'},
334+
{'element': 'Semantics'},
335+
{'element': 'Listener'},
336+
{'element': 'OverlayPortal'},
337+
{'element': 'Tooltip', 'label': 'Tooltip message.'},
338+
{'element': 'Column'},
339+
{'element': 'Center'},
340+
{'name': '[GlobalKey#00000]', 'element': 'KeyedSubtree'},
341+
{'element': 'MediaQuery'},
342+
{'name': '_ScaffoldSlot.body', 'element': 'LayoutId'}
343+
],
344+
'label': 'Button text',
345+
'view.id': 'tooltip_button',
346+
'view.class': 'ButtonStyleButton'
347+
}));
227348
});
228349
});
229350
});
@@ -394,6 +515,14 @@ class Fixture {
394515
child: MyApp(),
395516
);
396517
}
518+
519+
Breadcrumb getBreadcrumb() {
520+
late final Breadcrumb crumb;
521+
hub.configureScope((scope) {
522+
crumb = scope.breadcrumbs.last;
523+
});
524+
return crumb;
525+
}
397526
}
398527

399528
class MyApp extends StatelessWidget {
@@ -420,23 +549,17 @@ class Page1 extends StatelessWidget {
420549
children: [
421550
MaterialButton(
422551
key: Key('btn_1'),
423-
onPressed: () {
424-
// print('button pressed');
425-
},
552+
onPressed: () {},
426553
child: const Text('Button 1'),
427554
),
428555
CupertinoButton(
429556
key: Key('btn_2'),
430-
onPressed: () {
431-
// print('button pressed 2');
432-
},
557+
onPressed: () {},
433558
child: const Text('Button 2'),
434559
),
435560
IconButton(
436561
key: Key('btn_3'),
437-
onPressed: () {
438-
// print('button pressed 3');
439-
},
562+
onPressed: () {},
440563
icon: Icon(
441564
Icons.dark_mode,
442565
semanticLabel: 'My Icon',
@@ -445,17 +568,13 @@ class Page1 extends StatelessWidget {
445568
Card(
446569
child: GestureDetector(
447570
key: Key('btn_4'),
448-
onTap: () => {
449-
// print('button pressed 4'),
450-
},
571+
onTap: () => {},
451572
child: Stack(
452573
children: [
453574
//fancy card layout
454575
ElevatedButton(
455576
key: Key('btn_5'),
456-
onPressed: () => {
457-
// print('button pressed 5'),
458-
},
577+
onPressed: () => {},
459578
child: const Text('Button 5'),
460579
),
461580
],
@@ -478,6 +597,14 @@ class Page1 extends StatelessWidget {
478597
),
479598
],
480599
),
600+
Tooltip(
601+
message: 'Tooltip message.',
602+
child: ElevatedButton(
603+
key: ValueKey('tooltip_button'),
604+
onPressed: () {},
605+
child: Text('Button text'),
606+
),
607+
)
481608
],
482609
),
483610
),
@@ -496,9 +623,7 @@ class Page2 extends StatelessWidget {
496623
children: [
497624
MaterialButton(
498625
key: Key('btn_page_2'),
499-
onPressed: () {
500-
// print('button page 2 pressed');
501-
},
626+
onPressed: () {},
502627
child: const Text('Button Page 2'),
503628
),
504629
],
@@ -507,3 +632,34 @@ class Page2 extends StatelessWidget {
507632
);
508633
}
509634
}
635+
636+
extension on String {
637+
String replaceHashCodes() => replaceAll(RegExp(r'#[\da-fA-F]{5}'), '#00000');
638+
}
639+
640+
extension on Map<dynamic, dynamic> {
641+
Map<dynamic, dynamic> replaceHashCodes() => map((key, value) {
642+
if (value is String) {
643+
value = value.replaceHashCodes();
644+
} else if (value is Map) {
645+
value = value.replaceHashCodes();
646+
} else if (value is List) {
647+
value = value.replaceHashCodes();
648+
}
649+
return MapEntry(key, value);
650+
});
651+
}
652+
653+
extension on List<dynamic> {
654+
Iterable<dynamic> replaceHashCodes() => map((value) {
655+
if (value is String) {
656+
return value.replaceHashCodes();
657+
} else if (value is Map) {
658+
return value.replaceHashCodes();
659+
} else if (value is List) {
660+
return value.replaceHashCodes();
661+
} else {
662+
return value;
663+
}
664+
});
665+
}

0 commit comments

Comments
 (0)