From 97ab95466ededebe2ce5e4725b0d20e83ea03b1c Mon Sep 17 00:00:00 2001 From: Andrew McKnight Date: Thu, 12 Dec 2024 11:40:41 -0900 Subject: [PATCH 1/9] prefill user info --- .../xcshareddata/xcschemes/iOS-Swift.xcscheme | 4 ++++ Samples/iOS-Swift/iOS-Swift/AppDelegate.swift | 1 + .../UserFeedback/SentryUserFeedbackForm.swift | 8 ++++++++ 3 files changed, 13 insertions(+) diff --git a/Samples/iOS-Swift/iOS-Swift.xcodeproj/xcshareddata/xcschemes/iOS-Swift.xcscheme b/Samples/iOS-Swift/iOS-Swift.xcodeproj/xcshareddata/xcschemes/iOS-Swift.xcscheme index 75721f0cd2a..ee025e48e4e 100644 --- a/Samples/iOS-Swift/iOS-Swift.xcodeproj/xcshareddata/xcschemes/iOS-Swift.xcscheme +++ b/Samples/iOS-Swift/iOS-Swift.xcodeproj/xcshareddata/xcschemes/iOS-Swift.xcscheme @@ -73,6 +73,10 @@ argument = "--disable-file-io-tracing" isEnabled = "NO"> + + diff --git a/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift b/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift index 523bdd81d85..bac656e65ff 100644 --- a/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift +++ b/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift @@ -174,6 +174,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { return } config.animations = !args.contains("--io.sentry.feedback.no-animations") + config.useSentryUser = args.contains("--io.sentry.feedback.use-sentry-user") config.useShakeGesture = true config.showFormForScreenshots = true config.configureWidget = { widget in diff --git a/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackForm.swift b/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackForm.swift index b49555afcef..cde3ee3de82 100644 --- a/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackForm.swift +++ b/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackForm.swift @@ -261,6 +261,10 @@ class SentryUserFeedbackForm: UIViewController { field.accessibilityLabel = config.formConfig.nameTextFieldAccessibilityLabel field.accessibilityIdentifier = "io.sentry.feedback.form.name" field.delegate = self + field.autocapitalizationType = .words + if config.useSentryUser { + field.text = SentrySDK.currentHub().scope.userObject?.name + } return field }() @@ -277,6 +281,10 @@ class SentryUserFeedbackForm: UIViewController { field.accessibilityIdentifier = "io.sentry.feedback.form.email" field.delegate = self field.keyboardType = .emailAddress + field.autocapitalizationType = .none + if config.useSentryUser { + field.text = SentrySDK.currentHub().scope.userObject?.email + } return field }() From 8a9fe4909bca74db249d6f39d9a578822acec227 Mon Sep 17 00:00:00 2001 From: Andrew McKnight Date: Thu, 12 Dec 2024 12:27:17 -0900 Subject: [PATCH 2/9] fix build and add ui test --- .../iOS-Swift-UITests/UserFeedbackUITests.swift | 13 +++++++++++++ .../xcshareddata/xcschemes/iOS-Swift.xcscheme | 9 +++++++++ Samples/iOS-Swift/iOS-Swift/AppDelegate.swift | 1 + Sources/Sentry/include/SentryPrivate.h | 2 ++ 4 files changed, 25 insertions(+) diff --git a/Samples/iOS-Swift/iOS-Swift-UITests/UserFeedbackUITests.swift b/Samples/iOS-Swift/iOS-Swift-UITests/UserFeedbackUITests.swift index 4ca524f2ee9..bd8cf37ae3a 100644 --- a/Samples/iOS-Swift/iOS-Swift-UITests/UserFeedbackUITests.swift +++ b/Samples/iOS-Swift/iOS-Swift-UITests/UserFeedbackUITests.swift @@ -54,7 +54,9 @@ class UserFeedbackUITests: BaseUITest { // Input field placeholders XCTAssertEqual(try XCTUnwrap(nameField.placeholderValue), "Your Name") + XCTAssertNil(nameField.value) XCTAssertEqual(try XCTUnwrap(emailField.placeholderValue), "your.email@example.org") + XCTAssertNil(emailField.value) XCTAssert(app.staticTexts["What's the bug? What did you expect?"].exists) // Input field labels @@ -97,6 +99,17 @@ class UserFeedbackUITests: BaseUITest { XCTAssertFalse(app.staticTexts["Thy name (Required)"].exists) } + func testPrefilledUserInformation() throws { + launchApp(args: ["--io.sentry.feedback.use-sentry-user"], env: [ + "--io.sentry.user.name": "ui test user", + "--io.sentry.user.email": "ui-testing@sentry.io" + ]) + + widgetButton.tap() + XCTAssertEqual(try XCTUnwrap(nameField.value as? String), "ui test user") + XCTAssertEqual(try XCTUnwrap(emailField.value as? String), "ui-testing@sentry.io") + } + // MARK: Tests validating happy path / successful submission func testSubmitFullyFilledForm() throws { diff --git a/Samples/iOS-Swift/iOS-Swift.xcodeproj/xcshareddata/xcschemes/iOS-Swift.xcscheme b/Samples/iOS-Swift/iOS-Swift.xcodeproj/xcshareddata/xcschemes/iOS-Swift.xcscheme index ee025e48e4e..a091d4c0abb 100644 --- a/Samples/iOS-Swift/iOS-Swift.xcodeproj/xcshareddata/xcschemes/iOS-Swift.xcscheme +++ b/Samples/iOS-Swift/iOS-Swift.xcodeproj/xcshareddata/xcschemes/iOS-Swift.xcscheme @@ -69,6 +69,10 @@ + + @@ -240,6 +244,11 @@ value = "" isEnabled = "NO"> + + Date: Thu, 12 Dec 2024 15:52:56 -0900 Subject: [PATCH 3/9] dont assert nil value bc it uses the placeholder string when empty --- Samples/iOS-Swift/iOS-Swift-UITests/UserFeedbackUITests.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/Samples/iOS-Swift/iOS-Swift-UITests/UserFeedbackUITests.swift b/Samples/iOS-Swift/iOS-Swift-UITests/UserFeedbackUITests.swift index bd8cf37ae3a..a5f1eb50b69 100644 --- a/Samples/iOS-Swift/iOS-Swift-UITests/UserFeedbackUITests.swift +++ b/Samples/iOS-Swift/iOS-Swift-UITests/UserFeedbackUITests.swift @@ -54,9 +54,7 @@ class UserFeedbackUITests: BaseUITest { // Input field placeholders XCTAssertEqual(try XCTUnwrap(nameField.placeholderValue), "Your Name") - XCTAssertNil(nameField.value) XCTAssertEqual(try XCTUnwrap(emailField.placeholderValue), "your.email@example.org") - XCTAssertNil(emailField.value) XCTAssert(app.staticTexts["What's the bug? What did you expect?"].exists) // Input field labels From a2764d80ee5718b243ff35450b68f211e799cb93 Mon Sep 17 00:00:00 2001 From: Andrew McKnight Date: Thu, 12 Dec 2024 17:05:20 -0900 Subject: [PATCH 4/9] default user.name in addition to user.username --- Samples/iOS-Swift/iOS-Swift/AppDelegate.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift b/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift index c5d4c1a2cc6..3db52b6b001 100644 --- a/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift +++ b/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift @@ -152,9 +152,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate { user.email = env["--io.sentry.user.email"] ?? "tony@example.com" // first check if the username has been overridden in the scheme for testing purposes; then try to use the system username so each person gets an automatic way to easily filter things on the dashboard; then fall back on a hardcoded value if none of these are present let username = env["--io.sentry.user.username"] ?? (env["SIMULATOR_HOST_HOME"] as? NSString)? - .lastPathComponent ?? "cocoa developer" + .lastPathComponent ?? "cocoadev" user.username = username - user.name = env["--io.sentry.user.name"] + user.name = env["--io.sentry.user.name"] ?? "cocoa developer" scope.setUser(user) if let path = Bundle.main.path(forResource: "Tongariro", ofType: "jpg") { From 237f9b4278f5e137751a91dba71c3245af66c592 Mon Sep 17 00:00:00 2001 From: Andrew McKnight Date: Thu, 12 Dec 2024 17:31:53 -0900 Subject: [PATCH 5/9] these should not have been in the public SentrySDK header --- Sources/Sentry/Public/SentrySDK.h | 31 +++++++--------------- Sources/Sentry/include/SentrySDK+Private.h | 22 +++++++++++++++ 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/Sources/Sentry/Public/SentrySDK.h b/Sources/Sentry/Public/SentrySDK.h index d11431f7074..b93a8243349 100644 --- a/Sources/Sentry/Public/SentrySDK.h +++ b/Sources/Sentry/Public/SentrySDK.h @@ -6,11 +6,18 @@ @protocol SentrySpan; -@class SentryOptions, SentryEvent, SentryBreadcrumb, SentryScope, SentryUser, SentryId, - SentryUserFeedback, SentryTransactionContext; +@class SentryBreadcrumb; +@class SentryEvent; +@class SentryFeedback; +@class SentryId; @class SentryMetricsAPI; -@class UIView; +@class SentryOptions; @class SentryReplayApi; +@class SentryScope; +@class SentryTransactionContext; +@class SentryUser; +@class SentryUserFeedback; +@class UIView; NS_ASSUME_NONNULL_BEGIN @@ -246,28 +253,10 @@ SENTRY_NO_INIT /** * Captures user feedback that was manually gathered and sends it to Sentry. * @param userFeedback The user feedback to send to Sentry. - * @note If you'd prefer not to have to build the UI required to gather the feedback from the user, - * consider using `showUserFeedbackForm`, which delivers a prepackaged user feedback experience. See - * @c SentryOptions.configureUserFeedback to customize a fully managed integration. See - * https://docs.sentry.io/platforms/apple/user-feedback/#user-feedback-api and (TODO: add link to - * new docs) for more information on each approach. */ + (void)captureUserFeedback:(SentryUserFeedback *)userFeedback NS_SWIFT_NAME(capture(userFeedback:)); -/** - * Display a form to gather information from an end user in the app to send to Sentry as a user - * feedback event. - * @see @c SentryOptions.enableUserFeedbackIntegration and @c SentryOptions.configureUserFeedback to - * enable the functionality and customize the experience. - * @note If @c SentryOptions.enableUserFeedbackIntegration is @c NO, this method is a no-op. - * @note This is a fully managed user feedback flow; there will be no need to call - * @c SentrySDK.captureUserFeedback . See - * https://docs.sentry.io/platforms/apple/user-feedback/#user-feedback-api and (TODO: add link to - * new docs) for more information on each approach. - */ -+ (void)showUserFeedbackForm; - /** * Adds a Breadcrumb to the current Scope of the current Hub. If the total number of breadcrumbs * exceeds the @c SentryOptions.maxBreadcrumbs the SDK removes the oldest breadcrumb. diff --git a/Sources/Sentry/include/SentrySDK+Private.h b/Sources/Sentry/include/SentrySDK+Private.h index c4e486e89c9..374b8d0c107 100644 --- a/Sources/Sentry/include/SentrySDK+Private.h +++ b/Sources/Sentry/include/SentrySDK+Private.h @@ -50,6 +50,28 @@ NS_ASSUME_NONNULL_BEGIN * Needed by hybrid SDKs as react-native to synchronously capture an envelope. */ + (void)captureEnvelope:(SentryEnvelope *)envelope; +/** + * Captures user feedback that was manually gathered and sends it to Sentry. + * @param feedback The feedback to send to Sentry. + * @note If you'd prefer not to have to build the UI required to gather the feedback from the user, + * consider using `showUserFeedbackForm`, which delivers a prepackaged user feedback experience. See + * @c SentryOptions.configureUserFeedback to customize a fully managed integration. See + * https://docs.sentry.io/platforms/apple/user-feedback/ for more information. + */ ++ (void)captureFeedback:(SentryFeedback *)feedback NS_SWIFT_NAME(capture(feedback:)); + +#if TARGET_OS_IOS && SENTRY_HAS_UIKIT +/** + * Display a form to gather information from an end user in the app to send to Sentry as a user + * feedback event. + * @see @c SentryOptions.configureUserFeedback to customize the experience, currently only on iOS. + * @warning This is an experimental feature and may still have bugs. + * @note This is a fully managed user feedback flow; there will be no need to call + * @c SentrySDK.captureUserFeedback . See + * https://docs.sentry.io/platforms/apple/user-feedback/ for more information. + */ ++ (void)showUserFeedbackForm; +#endif // TARGET_OS_IOS && SENTRY_HAS_UIKIT @end From 1d1031187be1b463203daf87969d667b9e4a13cb Mon Sep 17 00:00:00 2001 From: Andrew McKnight Date: Fri, 13 Dec 2024 13:31:35 -0900 Subject: [PATCH 6/9] Apply suggestions from code review --- .../xcshareddata/xcschemes/iOS-Swift.xcscheme | 4 ---- Sources/Sentry/Public/SentrySDK.h | 12 ++---------- Sources/Sentry/include/SentryPrivate.h | 2 -- 3 files changed, 2 insertions(+), 16 deletions(-) diff --git a/Samples/iOS-Swift/iOS-Swift.xcodeproj/xcshareddata/xcschemes/iOS-Swift.xcscheme b/Samples/iOS-Swift/iOS-Swift.xcodeproj/xcshareddata/xcschemes/iOS-Swift.xcscheme index a091d4c0abb..090c3ca5e59 100644 --- a/Samples/iOS-Swift/iOS-Swift.xcodeproj/xcshareddata/xcschemes/iOS-Swift.xcscheme +++ b/Samples/iOS-Swift/iOS-Swift.xcodeproj/xcshareddata/xcschemes/iOS-Swift.xcscheme @@ -69,10 +69,6 @@ - - diff --git a/Sources/Sentry/Public/SentrySDK.h b/Sources/Sentry/Public/SentrySDK.h index b93a8243349..372e0b96b74 100644 --- a/Sources/Sentry/Public/SentrySDK.h +++ b/Sources/Sentry/Public/SentrySDK.h @@ -6,17 +6,9 @@ @protocol SentrySpan; -@class SentryBreadcrumb; -@class SentryEvent; -@class SentryFeedback; -@class SentryId; +@class SentryOptions, SentryEvent, SentryBreadcrumb, SentryScope, SentryUser, SentryId, + SentryUserFeedback, SentryTransactionContext; @class SentryMetricsAPI; -@class SentryOptions; -@class SentryReplayApi; -@class SentryScope; -@class SentryTransactionContext; -@class SentryUser; -@class SentryUserFeedback; @class UIView; NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/Sentry/include/SentryPrivate.h b/Sources/Sentry/include/SentryPrivate.h index a9e4eb9cbd3..27c7ad8d640 100644 --- a/Sources/Sentry/include/SentryPrivate.h +++ b/Sources/Sentry/include/SentryPrivate.h @@ -4,8 +4,6 @@ #import "SentryDispatchQueueWrapper.h" #import "SentryNSDataUtils.h" #import "SentryRandom.h" -#import "SentrySDK+Private.h" -#import "SentryScope+Private.h" #import "SentryTime.h" #import "SentryUserAccess.h" From 00fd06d310ec8138297b320debced2be9b53fd93 Mon Sep 17 00:00:00 2001 From: Sentry Github Bot Date: Fri, 13 Dec 2024 22:32:47 +0000 Subject: [PATCH 7/9] Format code --- Sources/Sentry/Public/SentrySDK.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Sentry/Public/SentrySDK.h b/Sources/Sentry/Public/SentrySDK.h index 372e0b96b74..1eacda89b39 100644 --- a/Sources/Sentry/Public/SentrySDK.h +++ b/Sources/Sentry/Public/SentrySDK.h @@ -7,7 +7,7 @@ @protocol SentrySpan; @class SentryOptions, SentryEvent, SentryBreadcrumb, SentryScope, SentryUser, SentryId, - SentryUserFeedback, SentryTransactionContext; + SentryUserFeedback, SentryTransactionContext; @class SentryMetricsAPI; @class UIView; From f4d440e099ca1cdd06619bc9e9da9c8558b92fe4 Mon Sep 17 00:00:00 2001 From: Andrew McKnight Date: Fri, 13 Dec 2024 13:33:43 -0900 Subject: [PATCH 8/9] put back --- Sources/Sentry/Public/SentrySDK.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Sources/Sentry/Public/SentrySDK.h b/Sources/Sentry/Public/SentrySDK.h index 1eacda89b39..35f9eb15766 100644 --- a/Sources/Sentry/Public/SentrySDK.h +++ b/Sources/Sentry/Public/SentrySDK.h @@ -10,6 +10,7 @@ SentryUserFeedback, SentryTransactionContext; @class SentryMetricsAPI; @class UIView; +@class SentryReplayApi; NS_ASSUME_NONNULL_BEGIN From b1dffae98c5f7252e4c981b8b15eefd21e978b94 Mon Sep 17 00:00:00 2001 From: Andrew McKnight Date: Fri, 13 Dec 2024 14:08:21 -0900 Subject: [PATCH 9/9] fix build --- Sources/Sentry/include/SentrySDK+Private.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Sources/Sentry/include/SentrySDK+Private.h b/Sources/Sentry/include/SentrySDK+Private.h index 374b8d0c107..26bb3a89eb5 100644 --- a/Sources/Sentry/include/SentrySDK+Private.h +++ b/Sources/Sentry/include/SentrySDK+Private.h @@ -10,7 +10,11 @@ # import "SentrySDK.h" #endif -@class SentryHub, SentryId, SentryAppStartMeasurement, SentryEnvelope; +@class SentryAppStartMeasurement; +@class SentryEnvelope; +@class SentryFeedback; +@class SentryHub; +@class SentryId; NS_ASSUME_NONNULL_BEGIN