Skip to content

Commit bb8c974

Browse files
Merge 8080b00 into d31895e
2 parents d31895e + 8080b00 commit bb8c974

File tree

7 files changed

+209
-80
lines changed

7 files changed

+209
-80
lines changed

RNSentryCocoaTester/RNSentryCocoaTester.xcodeproj/project.pbxproj

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
/* Begin PBXBuildFile section */
1010
330F308C2C0F3840002A0D4E /* RNSentryBreadcrumbTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 330F308B2C0F3840002A0D4E /* RNSentryBreadcrumbTests.m */; };
11+
336084392C32E382008CC412 /* RNSentryCocoaUnitTesterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 336084382C32E382008CC412 /* RNSentryCocoaUnitTesterTests.swift */; };
1112
33958C692BFCF12600AD1FB6 /* RNSentryOnDrawReporterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 33958C682BFCF12600AD1FB6 /* RNSentryOnDrawReporterTests.m */; };
1213
33AFDFED2B8D14B300AAB120 /* RNSentryFramesTrackerListenerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 33AFDFEC2B8D14B300AAB120 /* RNSentryFramesTrackerListenerTests.m */; };
1314
33AFDFF12B8D15E500AAB120 /* RNSentryDependencyContainerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 33AFDFF02B8D15E500AAB120 /* RNSentryDependencyContainerTests.m */; };
@@ -19,6 +20,9 @@
1920
1482D5685A340AB93348A43D /* Pods-RNSentryCocoaTesterTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNSentryCocoaTesterTests.release.xcconfig"; path = "Target Support Files/Pods-RNSentryCocoaTesterTests/Pods-RNSentryCocoaTesterTests.release.xcconfig"; sourceTree = "<group>"; };
2021
330F308B2C0F3840002A0D4E /* RNSentryBreadcrumbTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNSentryBreadcrumbTests.m; sourceTree = "<group>"; };
2122
330F308D2C0F385A002A0D4E /* RNSentryBreadcrumb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSentryBreadcrumb.h; path = ../ios/RNSentryBreadcrumb.h; sourceTree = "<group>"; };
23+
336084372C32E382008CC412 /* RNSentryCocoaTesterTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RNSentryCocoaTesterTests-Bridging-Header.h"; sourceTree = "<group>"; };
24+
336084382C32E382008CC412 /* RNSentryCocoaUnitTesterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RNSentryCocoaUnitTesterTests.swift; sourceTree = "<group>"; };
25+
3360843A2C32E3A8008CC412 /* RNSentryReplayBreadcrumbConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSentryReplayBreadcrumbConverter.h; path = ../ios/RNSentryReplayBreadcrumbConverter.h; sourceTree = "<group>"; };
2226
3360898D29524164007C7730 /* RNSentryCocoaTesterTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RNSentryCocoaTesterTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
2327
338739072A7D7D2800950DDD /* RNSentryTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNSentryTests.h; sourceTree = "<group>"; };
2428
33958C672BFCEF5A00AD1FB6 /* RNSentryOnDrawReporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSentryOnDrawReporter.h; path = ../ios/RNSentryOnDrawReporter.h; sourceTree = "<group>"; };
@@ -76,6 +80,7 @@
7680
3360899029524164007C7730 /* RNSentryCocoaTesterTests */ = {
7781
isa = PBXGroup;
7882
children = (
83+
336084382C32E382008CC412 /* RNSentryCocoaUnitTesterTests.swift */,
7984
33F58ACF2977037D008F60EA /* RNSentryTests.mm */,
8085
338739072A7D7D2800950DDD /* RNSentryTests.h */,
8186
33AFDFEC2B8D14B300AAB120 /* RNSentryFramesTrackerListenerTests.m */,
@@ -84,13 +89,15 @@
8489
33AFDFF22B8D15F600AAB120 /* RNSentryDependencyContainerTests.h */,
8590
33958C682BFCF12600AD1FB6 /* RNSentryOnDrawReporterTests.m */,
8691
330F308B2C0F3840002A0D4E /* RNSentryBreadcrumbTests.m */,
92+
336084372C32E382008CC412 /* RNSentryCocoaTesterTests-Bridging-Header.h */,
8793
);
8894
path = RNSentryCocoaTesterTests;
8995
sourceTree = "<group>";
9096
};
9197
33AFE0122B8F319000AAB120 /* RNSentry */ = {
9298
isa = PBXGroup;
9399
children = (
100+
3360843A2C32E3A8008CC412 /* RNSentryReplayBreadcrumbConverter.h */,
94101
330F308D2C0F385A002A0D4E /* RNSentryBreadcrumb.h */,
95102
33958C672BFCEF5A00AD1FB6 /* RNSentryOnDrawReporter.h */,
96103
33AFE0132B8F31AF00AAB120 /* RNSentryDependencyContainer.h */,
@@ -134,10 +141,12 @@
134141
isa = PBXProject;
135142
attributes = {
136143
BuildIndependentTargetsInParallel = 1;
144+
LastSwiftUpdateCheck = 1540;
137145
LastUpgradeCheck = 1420;
138146
TargetAttributes = {
139147
3360898C29524164007C7730 = {
140148
CreatedOnToolsVersion = 14.2;
149+
LastSwiftMigration = 1540;
141150
};
142151
};
143152
};
@@ -207,6 +216,7 @@
207216
buildActionMask = 2147483647;
208217
files = (
209218
33AFDFF12B8D15E500AAB120 /* RNSentryDependencyContainerTests.m in Sources */,
219+
336084392C32E382008CC412 /* RNSentryCocoaUnitTesterTests.swift in Sources */,
210220
33F58AD02977037D008F60EA /* RNSentryTests.mm in Sources */,
211221
33958C692BFCF12600AD1FB6 /* RNSentryOnDrawReporterTests.m in Sources */,
212222
330F308C2C0F3840002A0D4E /* RNSentryBreadcrumbTests.m in Sources */,
@@ -333,6 +343,7 @@
333343
isa = XCBuildConfiguration;
334344
baseConfigurationReference = E2321E7CFA55AB617247098E /* Pods-RNSentryCocoaTesterTests.debug.xcconfig */;
335345
buildSettings = {
346+
CLANG_ENABLE_MODULES = YES;
336347
CODE_SIGN_STYLE = Automatic;
337348
CURRENT_PROJECT_VERSION = 1;
338349
GENERATE_INFOPLIST_FILE = YES;
@@ -387,6 +398,9 @@
387398
SUPPORTS_MACCATALYST = NO;
388399
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
389400
SWIFT_EMIT_LOC_STRINGS = NO;
401+
SWIFT_OBJC_BRIDGING_HEADER = "RNSentryCocoaTesterTests/RNSentryCocoaTesterTests-Bridging-Header.h";
402+
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
403+
SWIFT_VERSION = 5.0;
390404
TARGETED_DEVICE_FAMILY = 1;
391405
};
392406
name = Debug;
@@ -395,6 +409,7 @@
395409
isa = XCBuildConfiguration;
396410
baseConfigurationReference = 1482D5685A340AB93348A43D /* Pods-RNSentryCocoaTesterTests.release.xcconfig */;
397411
buildSettings = {
412+
CLANG_ENABLE_MODULES = YES;
398413
CODE_SIGN_STYLE = Automatic;
399414
CURRENT_PROJECT_VERSION = 1;
400415
GENERATE_INFOPLIST_FILE = YES;
@@ -449,6 +464,8 @@
449464
SUPPORTS_MACCATALYST = NO;
450465
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
451466
SWIFT_EMIT_LOC_STRINGS = NO;
467+
SWIFT_OBJC_BRIDGING_HEADER = "RNSentryCocoaTesterTests/RNSentryCocoaTesterTests-Bridging-Header.h";
468+
SWIFT_VERSION = 5.0;
452469
TARGETED_DEVICE_FAMILY = 1;
453470
};
454471
name = Release;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//
2+
// Use this file to import your target's public headers that you would like to expose to Swift.
3+
//
4+
5+
#import "RNSentryReplayBreadcrumbConverter.h"
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import XCTest
2+
3+
final class RNSentryCocoaUnitTesterTests: XCTestCase {
4+
5+
func testTouchMessageReturnsNilOnEmptyArray() throws {
6+
let converter = RNSentryReplayBreadcrumbConverter()
7+
let actual = converter.getTouchPathMessage(from: [])
8+
XCTAssertEqual(actual, nil);
9+
}
10+
11+
func testTouchMessageReturnsNilOnNilArray() throws {
12+
let converter = RNSentryReplayBreadcrumbConverter()
13+
let actual = converter.getTouchPathMessage(from: nil as [Any]?)
14+
XCTAssertEqual(actual, nil);
15+
}
16+
17+
func testTouchMessageReturnsNilOnMissingNameAndLavel() throws {
18+
let testPath: [Any?] = [["element": "element4", "file": "file4"]]
19+
let converter = RNSentryReplayBreadcrumbConverter()
20+
let actual = converter.getTouchPathMessage(from: testPath as [Any])
21+
XCTAssertEqual(actual, nil);
22+
}
23+
24+
func testTouchMessageReturnsMessageOnValidPathExample1() throws {
25+
let testPath: [Any?] = [
26+
["label": "label0"],
27+
["name": "name1"],
28+
["name": "item2", "label": "label2"],
29+
["name": "item3", "label": "label3", "element": "element3"],
30+
["name": "item4", "label": "label4", "file": "file4"],
31+
["name": "item5", "label": "label5", "element": "element5", "file": "file5"],
32+
]
33+
let converter = RNSentryReplayBreadcrumbConverter()
34+
let actual = converter.getTouchPathMessage(from: testPath as [Any])
35+
XCTAssertEqual(actual, "label3(element3) > label2 > name1 > label0");
36+
}
37+
38+
func testTouchMessageReturnsMessageOnValidPathExample2() throws {
39+
let testPath: [Any?] = [
40+
["name": "item2", "label": "label2"],
41+
["name": "item3", "label": "label3", "element": "element3"],
42+
["name": "item4", "label": "label4", "file": "file4"],
43+
["name": "item5", "label": "label5", "element": "element5", "file": "file5"],
44+
["label": "label6"],
45+
["name": "name7"],
46+
]
47+
let converter = RNSentryReplayBreadcrumbConverter()
48+
let actual = converter.getTouchPathMessage(from: testPath as [Any])
49+
XCTAssertEqual(actual, "label5(element5, file5) > label4(file4) > label3(element3) > label2");
50+
}
51+
52+
}

ios/RNSentryReplayBreadcrumbConverter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,7 @@
88

99
- (instancetype _Nonnull)init;
1010

11+
- (NSString* _Nullable) getTouchPathMessageFrom:(NSArray* _Nullable) path;
12+
1113
@end
1214
#endif

ios/RNSentryReplayBreadcrumbConverter.m

Lines changed: 67 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -30,39 +30,7 @@ - (instancetype _Nonnull)init {
3030
}
3131

3232
if ([breadcrumb.category isEqualToString:@"touch"]) {
33-
NSMutableString *message;
34-
if (breadcrumb.data) {
35-
NSMutableArray *path = [breadcrumb.data valueForKey:@"path"];
36-
if (path != nil) {
37-
message = [[NSMutableString alloc] init];
38-
for (NSInteger i = MIN(3, [path count] - 1); i >= 0; i--) {
39-
NSDictionary *item = [path objectAtIndex:i];
40-
[message appendString:[item objectForKey:@"name"]];
41-
if ([item objectForKey:@"element"] || [item objectForKey:@"file"]) {
42-
[message appendString:@"("];
43-
if ([item objectForKey:@"element"]) {
44-
[message appendString:[item objectForKey:@"element"]];
45-
if ([item objectForKey:@"file"]) {
46-
[message appendString:@", "];
47-
[message appendString:[item objectForKey:@"file"]];
48-
}
49-
} else if ([item objectForKey:@"file"]) {
50-
[message appendString:[item objectForKey:@"file"]];
51-
}
52-
[message appendString:@")"];
53-
}
54-
if (i > 0) {
55-
[message appendString:@" > "];
56-
}
57-
}
58-
}
59-
}
60-
return [SentrySessionReplayIntegration
61-
createBreadcrumbwithTimestamp:breadcrumb.timestamp
62-
category:@"ui.tap"
63-
message:message
64-
level:breadcrumb.level
65-
data:breadcrumb.data];
33+
return [self convertTouch:breadcrumb];
6634
}
6735

6836
if ([breadcrumb.category isEqualToString:@"navigation"]) {
@@ -93,6 +61,72 @@ - (instancetype _Nonnull)init {
9361
return nativeBreadcrumb;
9462
}
9563

64+
- (id<SentryRRWebEvent> _Nullable) convertTouch:(SentryBreadcrumb *_Nonnull)breadcrumb {
65+
if (breadcrumb.data == nil) {
66+
return nil;
67+
}
68+
69+
NSMutableArray *path = [breadcrumb.data valueForKey:@"path"];
70+
NSString* message = [self getTouchPathMessageFrom:path];
71+
72+
return [SentrySessionReplayIntegration
73+
createBreadcrumbwithTimestamp:breadcrumb.timestamp
74+
category:@"ui.tap"
75+
message:message
76+
level:breadcrumb.level
77+
data:breadcrumb.data];
78+
}
79+
80+
- (NSString* _Nullable) getTouchPathMessageFrom:(NSArray* _Nullable) path {
81+
if (path == nil) {
82+
return nil;
83+
}
84+
85+
NSInteger pathCount = [path count];
86+
if (pathCount <= 0) {
87+
return nil;
88+
}
89+
90+
NSMutableString *message = [[NSMutableString alloc] init];
91+
for (NSInteger i = MIN(3, pathCount - 1); i >= 0; i--) {
92+
NSDictionary *item = [path objectAtIndex:i];
93+
if (item == nil) {
94+
return nil; // There should be no nil (undefined) from JS, but to be safe we check it here
95+
}
96+
97+
id name = [item objectForKey:@"name"];
98+
id label = [item objectForKey:@"label"];
99+
BOOL hasName = [name isKindOfClass:[NSString class]];
100+
BOOL hasLabel = [label isKindOfClass:[NSString class]];
101+
if (!hasName && !hasLabel) {
102+
return nil; // This again should never be allowed in JS, but to be safe we check it here
103+
}
104+
if (hasLabel) {
105+
[message appendString:(NSString *)label];
106+
} else if (hasName) {
107+
[message appendString:(NSString *)name];
108+
}
109+
110+
id element = [item objectForKey:@"element"];
111+
id file = [item objectForKey:@"file"];
112+
BOOL hasElement = [element isKindOfClass:[NSString class]];
113+
BOOL hasFile = [file isKindOfClass:[NSString class]];
114+
if (hasElement && hasFile) {
115+
[message appendFormat:@"(%@, %@)", (NSString *)element, (NSString *)file];
116+
} else if (hasElement) {
117+
[message appendFormat:@"(%@)", (NSString *)element];
118+
} else if (hasFile) {
119+
[message appendFormat:@"(%@)", (NSString *)file];
120+
}
121+
122+
if (i > 0) {
123+
[message appendString:@" > "];
124+
}
125+
}
126+
127+
return message;
128+
}
129+
96130
- (id<SentryRRWebEvent> _Nullable)convertNavigation: (SentryBreadcrumb *_Nonnull)breadcrumb {
97131
NSNumber* startTimestamp = [breadcrumb.data[@"start_timestamp"] isKindOfClass:[NSNumber class]]
98132
? breadcrumb.data[@"start_timestamp"] : nil;

samples/react-native/src/App.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,13 @@ import { Provider } from 'react-redux';
2828
import { store } from './reduxApp';
2929
import { GestureHandlerRootView } from 'react-native-gesture-handler';
3030
import GesturesTracingScreen from './Screens/GesturesTracingScreen';
31-
import { Platform, StyleSheet, View } from 'react-native';
31+
import { LogBox, Platform, StyleSheet, View } from 'react-native';
3232
import { HttpClient } from '@sentry/integrations';
3333
import Ionicons from 'react-native-vector-icons/Ionicons';
3434
import PlaygroundScreen from './Screens/PlaygroundScreen';
3535

36+
LogBox.ignoreAllLogs();
37+
3638
const isMobileOs = Platform.OS === 'android' || Platform.OS === 'ios';
3739

3840
const reactNavigationInstrumentation =

0 commit comments

Comments
 (0)