Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
> make sure you follow our [migration guide](https://docs.sentry.io/platforms/react-native/migration/) first.
<!-- prettier-ignore-end -->

## Unreleased

### Features

- Expose screenshot masking options (`screenshot.maskAllText`, `screenshot.maskAllImages`) for error screenshots ([#6007](https://github.com/getsentry/sentry-react-native/pull/6007))

## 8.8.0

### Features
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,34 @@ final class RNSentryStartTests: XCTestCase {
}
}

func testScreenshotMaskingOptions() throws {
try startFromRN(options: [
"dsn": "https://abcd@efgh.ingest.sentry.io/123456",
"attachScreenshot": true,
"screenshot": [
"maskAllText": false,
"maskAllImages": true,
]
])

let actualOptions = PrivateSentrySDKOnly.options
XCTAssertTrue(actualOptions.attachScreenshot)
XCTAssertFalse(actualOptions.screenshot.maskAllText)
XCTAssertTrue(actualOptions.screenshot.maskAllImages)
}

func testScreenshotMaskingOptionsDefaults() throws {
try startFromRN(options: [
"dsn": "https://abcd@efgh.ingest.sentry.io/123456",
"attachScreenshot": true,
])

let actualOptions = PrivateSentrySDKOnly.options
XCTAssertTrue(actualOptions.attachScreenshot)
XCTAssertTrue(actualOptions.screenshot.maskAllText)
XCTAssertTrue(actualOptions.screenshot.maskAllImages)
}

func startFromRN(options: [String: Any]) throws {
var error: NSError?
RNSentryStart.start(options: options, error: &error)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,17 @@ static void getSentryAndroidOptions(
if (rnOptions.hasKey("attachScreenshot")) {
options.setAttachScreenshot(rnOptions.getBoolean("attachScreenshot"));
}
if (rnOptions.hasKey("screenshot")) {
@Nullable final ReadableMap screenshotOptions = rnOptions.getMap("screenshot");
if (screenshotOptions != null) {
if (screenshotOptions.hasKey("maskAllText")) {
options.getScreenshot().setMaskAllText(screenshotOptions.getBoolean("maskAllText"));
}
if (screenshotOptions.hasKey("maskAllImages")) {
options.getScreenshot().setMaskAllImages(screenshotOptions.getBoolean("maskAllImages"));
}
}
}
if (rnOptions.hasKey("attachViewHierarchy")) {
options.setAttachViewHierarchy(rnOptions.getBoolean("attachViewHierarchy"));
}
Expand Down
8 changes: 8 additions & 0 deletions packages/core/ios/RNSentryStart.m
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ + (SentryOptions *_Nullable)createOptionsWithDictionary:(NSDictionary *_Nonnull)
return nil;
}

#if SENTRY_TARGET_REPLAY_SUPPORTED
NSDictionary *screenshotDict = mutableOptions[@"screenshot"];
if ([screenshotDict isKindOfClass:[NSDictionary class]]) {
sentryOptions.screenshot =
[[SentryViewScreenshotOptions alloc] initWithDictionary:screenshotDict];
}
#endif
Comment thread
antonis marked this conversation as resolved.
Outdated

// Exclude Dev Server and Sentry Dsn request from Breadcrumbs
NSString *dsn = [self getURLFromDSN:[mutableOptions valueForKey:@"dsn"]];
// TODO: For Auto Init from JS dev server is resolved automatically, for init from options file
Expand Down
19 changes: 19 additions & 0 deletions packages/core/src/js/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,25 @@ export interface BaseReactNativeOptions {
*/
attachScreenshot?: boolean;

/**
* Options for configuring screenshot masking on error screenshots.
* When `attachScreenshot` is enabled, these options control what gets masked in the screenshot.
*/
screenshot?: {
/**
* Mask all text content in error screenshots.
*
* @default true
*/
maskAllText?: boolean;
/**
* Mask all images in error screenshots.
*
* @default true
*/
maskAllImages?: boolean;
};

/**
* When enabled Sentry includes the current view hierarchy in the error attachments.
*
Expand Down
22 changes: 22 additions & 0 deletions packages/core/test/wrapper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,28 @@ describe('Tests Native Wrapper', () => {
expect(initParameter.strictTraceContinuation).toBe(true);
});

test('passes screenshot options to native SDK', async () => {
await NATIVE.initNativeSdk({
dsn: 'test',
enableNative: true,
autoInitializeNativeSdk: true,
screenshot: {
maskAllText: false,
maskAllImages: true,
},
devServerUrl: undefined,
defaultSidecarUrl: undefined,
mobileReplayOptions: undefined,
});

expect(RNSentry.initNativeSdk).toHaveBeenCalled();
const initParameter = (RNSentry.initNativeSdk as jest.MockedFunction<any>).mock.calls[0][0];
expect(initParameter.screenshot).toEqual({
maskAllText: false,
maskAllImages: true,
});
});

test('passes orgId option to native SDK', async () => {
await NATIVE.initNativeSdk({
dsn: 'test',
Expand Down
5 changes: 5 additions & 0 deletions samples/react-native/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,11 @@ Sentry.init({
attachStacktrace: true,
// Attach screenshots to events.
attachScreenshot: true,
// Screenshot masking options.
screenshot: {
maskAllText: true,
maskAllImages: true,
},
// Attach view hierarchy to events.
attachViewHierarchy: true,
// Enables capture failed requests in JS and native.
Expand Down
Loading