Skip to content

Commit a905fd1

Browse files
committed
Normalize setContexts & setExtra
1 parent 9709c72 commit a905fd1

File tree

4 files changed

+173
-107
lines changed

4 files changed

+173
-107
lines changed

flutter/lib/src/method_channel_helper.dart

+20-26
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,33 @@ import 'package:meta/meta.dart';
33
/// Makes sure no invalid data is sent over method channels.
44
@internal
55
class MethodChannelHelper {
6+
static dynamic normalize(dynamic data) {
7+
if (data == null) {
8+
return null;
9+
}
10+
if (_isPrimitive(data)) {
11+
return data;
12+
} else if (data is List<dynamic>) {
13+
return _normalizeList(data);
14+
} else if (data is Map<String, dynamic>) {
15+
return normalizeMap(data);
16+
} else {
17+
return data.toString();
18+
}
19+
}
20+
621
static Map<String, dynamic>? normalizeMap(Map<String, dynamic>? data) {
722
if (data == null) {
823
return null;
924
}
10-
final mapToReturn = <String, dynamic>{};
11-
data.forEach((key, value) {
12-
if (_isPrimitive(value)) {
13-
mapToReturn[key] = value;
14-
} else if (value is List<dynamic>) {
15-
mapToReturn[key] = _normalizeList(value);
16-
} else if (value is Map<String, dynamic>) {
17-
mapToReturn[key] = normalizeMap(value);
18-
} else {
19-
mapToReturn[key] = value.toString();
20-
}
21-
});
22-
return mapToReturn;
25+
return data.map((key, value) => MapEntry(key, normalize(value)));
2326
}
2427

25-
static List<dynamic> _normalizeList(List<dynamic> data) {
26-
final listToReturn = <dynamic>[];
27-
for (final element in data) {
28-
if (_isPrimitive(element)) {
29-
listToReturn.add(element);
30-
} else if (element is List<dynamic>) {
31-
listToReturn.add(_normalizeList(element));
32-
} else if (element is Map<String, dynamic>) {
33-
listToReturn.add(normalizeMap(element));
34-
} else {
35-
listToReturn.add(element.toString());
36-
}
28+
static List<dynamic>? _normalizeList(List<dynamic>? data) {
29+
if (data == null) {
30+
return null;
3731
}
38-
return listToReturn;
32+
return data.map((e) => normalize(e)).toList();
3933
}
4034

4135
static bool _isPrimitive(dynamic value) {

flutter/lib/src/sentry_native_channel.dart

+11-3
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,11 @@ class SentryNativeChannel {
8484

8585
Future<void> setContexts(String key, dynamic value) async {
8686
try {
87-
await _channel.invokeMethod('setContexts', {'key': key, 'value': value});
87+
final normalizedValue = MethodChannelHelper.normalize(value);
88+
await _channel.invokeMethod(
89+
'setContexts',
90+
{'key': key, 'value': normalizedValue},
91+
);
8892
} catch (error, stackTrace) {
8993
_logError('setContexts', error, stackTrace);
9094
}
@@ -100,7 +104,11 @@ class SentryNativeChannel {
100104

101105
Future<void> setExtra(String key, dynamic value) async {
102106
try {
103-
await _channel.invokeMethod('setExtra', {'key': key, 'value': value});
107+
final normalizedValue = MethodChannelHelper.normalize(value);
108+
await _channel.invokeMethod(
109+
'setExtra',
110+
{'key': key, 'value': normalizedValue},
111+
);
104112
} catch (error, stackTrace) {
105113
_logError('setExtra', error, stackTrace);
106114
}
@@ -114,7 +122,7 @@ class SentryNativeChannel {
114122
}
115123
}
116124

117-
Future<void> setTag(String key, dynamic value) async {
125+
Future<void> setTag(String key, String value) async {
118126
try {
119127
await _channel.invokeMethod('setTag', {'key': key, 'value': value});
120128
} catch (error, stackTrace) {

flutter/test/method_channel_helper_test.dart

+132-72
Original file line numberDiff line numberDiff line change
@@ -3,91 +3,151 @@ import 'package:sentry_flutter/src/method_channel_helper.dart';
33
import 'package:collection/collection.dart';
44

55
void main() {
6-
test('primitives', () {
7-
var expected = <String, dynamic>{
8-
'null': null,
9-
'int': 1,
10-
'float': 1.1,
11-
'bool': true,
12-
'string': 'Foo',
13-
};
14-
15-
var actual = MethodChannelHelper.normalizeMap(expected);
16-
expect(
17-
DeepCollectionEquality().equals(actual, expected),
18-
true,
19-
);
20-
});
6+
group('normalize', () {
7+
test('primitives', () {
8+
var expected = <String, dynamic>{
9+
'null': null,
10+
'int': 1,
11+
'float': 1.1,
12+
'bool': true,
13+
'string': 'Foo',
14+
};
15+
16+
var actual = MethodChannelHelper.normalizeMap(expected);
17+
expect(
18+
DeepCollectionEquality().equals(actual, expected),
19+
true,
20+
);
21+
22+
expect(MethodChannelHelper.normalize(null), null);
23+
expect(MethodChannelHelper.normalize(1), 1);
24+
expect(MethodChannelHelper.normalize(1.1), 1.1);
25+
expect(MethodChannelHelper.normalize(true), true);
26+
expect(MethodChannelHelper.normalize('Foo'), 'Foo');
27+
});
28+
29+
test('object', () {
30+
expect(MethodChannelHelper.normalize(_CustomObject()), 'CustomObject()');
31+
});
32+
33+
test('object in list', () {
34+
var input = <String, dynamic>{
35+
'object': [_CustomObject()]
36+
};
37+
var expected = <String, dynamic>{
38+
'object': ['CustomObject()']
39+
};
40+
41+
var actual = MethodChannelHelper.normalize(input);
42+
expect(
43+
DeepCollectionEquality().equals(actual, expected),
44+
true,
45+
);
46+
});
2147

22-
test('list with primitives', () {
23-
var expected = <String, dynamic>{
24-
'list': [null, 1, 1.1, true, 'Foo'],
25-
};
48+
test('object in map', () {
49+
var input = <String, dynamic>{
50+
'object': <String, dynamic>{'object': _CustomObject()}
51+
};
52+
var expected = <String, dynamic>{
53+
'object': <String, dynamic>{'object': 'CustomObject()'}
54+
};
2655

27-
var actual = MethodChannelHelper.normalizeMap(expected);
28-
expect(
29-
DeepCollectionEquality().equals(actual, expected),
30-
true,
31-
);
56+
var actual = MethodChannelHelper.normalize(input);
57+
expect(
58+
DeepCollectionEquality().equals(actual, expected),
59+
true,
60+
);
61+
});
3262
});
3363

34-
test('map with primitives', () {
35-
var expected = <String, dynamic>{
36-
'map': <String, dynamic>{
64+
group('normalizeMap', () {
65+
test('primitives', () {
66+
var expected = <String, dynamic>{
3767
'null': null,
3868
'int': 1,
3969
'float': 1.1,
4070
'bool': true,
4171
'string': 'Foo',
42-
},
43-
};
44-
45-
var actual = MethodChannelHelper.normalizeMap(expected);
46-
expect(
47-
DeepCollectionEquality().equals(actual, expected),
48-
true,
49-
);
50-
});
72+
};
5173

52-
test('object', () {
53-
var input = <String, dynamic>{'object': _CustomObject()};
54-
var expected = <String, dynamic>{'object': 'CustomObject()'};
74+
var actual = MethodChannelHelper.normalizeMap(expected);
75+
expect(
76+
DeepCollectionEquality().equals(actual, expected),
77+
true,
78+
);
79+
});
5580

56-
var actual = MethodChannelHelper.normalizeMap(input);
57-
expect(
58-
DeepCollectionEquality().equals(actual, expected),
59-
true,
60-
);
61-
});
81+
test('list with primitives', () {
82+
var expected = <String, dynamic>{
83+
'list': [null, 1, 1.1, true, 'Foo'],
84+
};
6285

63-
test('object in list', () {
64-
var input = <String, dynamic>{
65-
'object': [_CustomObject()]
66-
};
67-
var expected = <String, dynamic>{
68-
'object': ['CustomObject()']
69-
};
70-
71-
var actual = MethodChannelHelper.normalizeMap(input);
72-
expect(
73-
DeepCollectionEquality().equals(actual, expected),
74-
true,
75-
);
76-
});
86+
var actual = MethodChannelHelper.normalizeMap(expected);
87+
expect(
88+
DeepCollectionEquality().equals(actual, expected),
89+
true,
90+
);
91+
});
92+
93+
test('map with primitives', () {
94+
var expected = <String, dynamic>{
95+
'map': <String, dynamic>{
96+
'null': null,
97+
'int': 1,
98+
'float': 1.1,
99+
'bool': true,
100+
'string': 'Foo',
101+
},
102+
};
103+
104+
var actual = MethodChannelHelper.normalizeMap(expected);
105+
expect(
106+
DeepCollectionEquality().equals(actual, expected),
107+
true,
108+
);
109+
});
110+
111+
test('object', () {
112+
var input = <String, dynamic>{'object': _CustomObject()};
113+
var expected = <String, dynamic>{'object': 'CustomObject()'};
114+
115+
var actual = MethodChannelHelper.normalizeMap(input);
116+
expect(
117+
DeepCollectionEquality().equals(actual, expected),
118+
true,
119+
);
120+
});
121+
122+
test('object in list', () {
123+
var input = <String, dynamic>{
124+
'object': [_CustomObject()]
125+
};
126+
var expected = <String, dynamic>{
127+
'object': ['CustomObject()']
128+
};
129+
130+
var actual = MethodChannelHelper.normalizeMap(input);
131+
expect(
132+
DeepCollectionEquality().equals(actual, expected),
133+
true,
134+
);
135+
});
136+
137+
test('object in map', () {
138+
var input = <String, dynamic>{
139+
'object': <String, dynamic>{'object': _CustomObject()}
140+
};
141+
var expected = <String, dynamic>{
142+
'object': <String, dynamic>{'object': 'CustomObject()'}
143+
};
77144

78-
test('object in map', () {
79-
var input = <String, dynamic>{
80-
'object': <String, dynamic>{'object': _CustomObject()}
81-
};
82-
var expected = <String, dynamic>{
83-
'object': <String, dynamic>{'object': 'CustomObject()'}
84-
};
85-
86-
var actual = MethodChannelHelper.normalizeMap(input);
87-
expect(
88-
DeepCollectionEquality().equals(actual, expected),
89-
true,
90-
);
145+
var actual = MethodChannelHelper.normalizeMap(input);
146+
expect(
147+
DeepCollectionEquality().equals(actual, expected),
148+
true,
149+
);
150+
});
91151
});
92152
}
93153

flutter/test/sentry_native_channel_test.dart

+10-6
Original file line numberDiff line numberDiff line change
@@ -112,15 +112,17 @@ void main() {
112112
});
113113

114114
test('setContexts', () async {
115+
final value = {'object': Object()};
116+
final normalizedValue = MethodChannelHelper.normalize(value);
115117
when(fixture.methodChannel.invokeMethod(
116-
'setContexts', {'key': 'fixture-key', 'value': 'fixture-value'}))
118+
'setContexts', {'key': 'fixture-key', 'value': normalizedValue}))
117119
.thenAnswer((_) => Future.value());
118120

119121
final sut = fixture.getSut();
120-
await sut.setContexts('fixture-key', 'fixture-value');
122+
await sut.setContexts('fixture-key', value);
121123

122124
verify(fixture.methodChannel.invokeMethod(
123-
'setContexts', {'key': 'fixture-key', 'value': 'fixture-value'}));
125+
'setContexts', {'key': 'fixture-key', 'value': normalizedValue}));
124126
});
125127

126128
test('removeContexts', () async {
@@ -136,15 +138,17 @@ void main() {
136138
});
137139

138140
test('setExtra', () async {
141+
final value = {'object': Object()};
142+
final normalizedValue = MethodChannelHelper.normalize(value);
139143
when(fixture.methodChannel.invokeMethod(
140-
'setExtra', {'key': 'fixture-key', 'value': 'fixture-value'}))
144+
'setExtra', {'key': 'fixture-key', 'value': normalizedValue}))
141145
.thenAnswer((_) => Future.value());
142146

143147
final sut = fixture.getSut();
144-
await sut.setExtra('fixture-key', 'fixture-value');
148+
await sut.setExtra('fixture-key', value);
145149

146150
verify(fixture.methodChannel.invokeMethod(
147-
'setExtra', {'key': 'fixture-key', 'value': 'fixture-value'}));
151+
'setExtra', {'key': 'fixture-key', 'value': normalizedValue}));
148152
});
149153

150154
test('removeExtra', () async {

0 commit comments

Comments
 (0)