diff --git a/.circleci/config.yml b/.circleci/config.yml index 7784e1c83..f12107ee9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,20 +1,42 @@ version: 2.1 + orbs: android: circleci/android@2.0 + advanced-checkout: vsco/advanced-checkout@1.0.0 + +commands: + install_pods: + parameters: + working_directory: + type: string + steps: + - restore_cache: + name: Restore Pods Cache + keys: + - v1-pods-{{ checksum "<< parameters.working_directory >>/Podfile.lock" }} + - run: + name: Install Pods + working_directory: << parameters.working_directory >> + command: pod install --deployment + - save_cache: + name: Save Pods Cache + key: v1-pods-{{ checksum "<< parameters.working_directory >>/Podfile.lock" }} + paths: + - << parameters.working_directory >>/Pods jobs: danger: docker: - - image: dantoml/danger:latest + - image: circleci/ruby:2.6.4 steps: - - checkout - - run: danger + - advanced-checkout/shallow-checkout + - run: bundle install + - run: bundle exec danger lint: - working_directory: ~/project docker: - image: cimg/node:16.17.1 steps: - - checkout + - advanced-checkout/shallow-checkout - run: name: Install Node Packages command: yarn @@ -26,44 +48,23 @@ jobs: command: yarn lint:ci test_module: - working_directory: ~/project docker: - image: cimg/node:16.17.1 steps: - - checkout: - path: ~/project - + - advanced-checkout/shallow-checkout - run: name: Install Node Packages command: yarn - - run: - name: jest tests - command: | - mkdir -p test-results/jest - yarn run test - environment: - JEST_JUNIT_OUTPUT: test-results/jest/junit.xml - - - persist_to_workspace: - root: ~/project - paths: - - node_modules - - - store_test_results: - path: test-results - - - store_artifacts: - path: test-results + name: Run Tests + command: yarn test test_android: executor: name: android/android-machine tag: '2022.03.1' - working_directory: ~/project steps: - - checkout: - path: ~/project + - advanced-checkout/shallow-checkout - run: name: Install Yarn command: npm install -g yarn @@ -73,15 +74,13 @@ jobs: command: yarn - android/run-tests: working-directory: ./example/android - test-command: ./gradlew test + test-command: ./gradlew test -PinstabugUploadEnable=false validate_shell_files: machine: image: ubuntu-2004:current - working_directory: ~/project steps: - - checkout: - path: ~/project + - advanced-checkout/shallow-checkout - run: name: Validate Android Script command: bash -n android/upload_sourcemap.sh @@ -95,12 +94,12 @@ jobs: sync_generated_files: macos: xcode: 13.4.1 - working_directory: ~/project steps: - - checkout + - advanced-checkout/shallow-checkout - run: yarn - run: cd example && yarn - - run: cd example/ios && pod install + - install_pods: + working_directory: example/ios - run: git --no-pager diff - run: git diff-index HEAD --exit-code -p -I EXCLUDED_ARCHS # Ignore Arch Changes @@ -109,20 +108,14 @@ jobs: xcode: 13.4.1 working_directory: ~/project/example environment: - FL_OUTPUT_DIR: output + INSTABUG_SOURCEMAPS_UPLOAD_DISABLE: true steps: - - checkout: - path: ~/project - - run: - name: Install CocoaPods - command: sudo gem install cocoapods + - advanced-checkout/shallow-checkout - run: name: Install node_modules command: yarn - - run: - name: Install Pods + - install_pods: working_directory: ios - command: pod install - run: name: Build and run tests working_directory: ios @@ -134,7 +127,6 @@ jobs: -sdk iphonesimulator \ -destination 'platform=iOS Simulator,name=iPhone 13 Pro Max,OS=15.5' \ test | xcpretty - no_output_timeout: 30m - run: name: Convert xcresult into JSON report working_directory: ios/coverage @@ -151,17 +143,10 @@ jobs: macos: xcode: 13.4.1 resource_class: large - working_directory: ~/project environment: - FL_OUTPUT_DIR: output + INSTABUG_SOURCEMAPS_UPLOAD_DISABLE: true steps: - - checkout - - run: - name: Install CocoaPods - command: sudo gem install cocoapods - - run: - name: Install React Native CLI - command: npm install -g react-native-cli + - advanced-checkout/shallow-checkout - run: name: Install Detox CLI command: npm install -g detox-cli @@ -171,17 +156,12 @@ jobs: - run: name: Install Node Packages command: yarn - - run: - name: Build Project - command: yarn build:lib - run: name: Install Example's Node Packages working_directory: example command: yarn - - run: - name: Install Pods + - install_pods: working_directory: example/ios - command: pod install - run: name: Detox - Build Release App working_directory: example @@ -196,21 +176,17 @@ jobs: name: android/android-machine tag: 2022.03.1 resource-class: large - working_directory: ~/project steps: - - checkout + - advanced-checkout/shallow-checkout - run: name: Install Yarn - command: npm install --global yarn + command: npm install -g yarn - run: name: Install Detox CLI - command: npm install --global detox-cli + command: npm install -g detox-cli - run: name: Install Node Packages command: yarn - - run: - name: Build Project - command: yarn build:lib - run: name: Install Example's Node Packages working_directory: example @@ -237,9 +213,8 @@ jobs: xcode: 13.4.1 working_directory: '~' steps: - - checkout: - path: ~/project - - run: git clone https://InstabugCI:$RELEASE_GITHUB_TOKEN@github.com/Instabug/Escape.git + - advanced-checkout/shallow-checkout + - run: git clone git@github.com:Instabug/Escape.git - run: cd Escape && swift build -c release - run: cd Escape/.build/release && cp -f Escape /usr/local/bin/escape - run: cd project && yarn && yarn build diff --git a/.github/stale.yml b/.github/stale.yml index 736996641..9f384ab85 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -29,3 +29,6 @@ closeComment: > This issue has been automatically closed since we haven't heard back from you. Please feel free to re-open the issue if you have more information to add. + +# Limit to only `issues` or `pulls` +only: issues diff --git a/Gemfile b/Gemfile new file mode 100644 index 000000000..09a8c1e13 --- /dev/null +++ b/Gemfile @@ -0,0 +1,3 @@ +source "https://rubygems.org" + +gem 'danger', '~> 8.6', '>= 8.6.1' diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 000000000..982ec2834 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,84 @@ +GEM + remote: https://rubygems.org/ + specs: + addressable (2.8.1) + public_suffix (>= 2.0.2, < 6.0) + claide (1.1.0) + claide-plugins (0.9.2) + cork + nap + open4 (~> 1.3) + colored2 (3.1.2) + cork (0.3.0) + colored2 (~> 3.1) + danger (8.6.1) + claide (~> 1.0) + claide-plugins (>= 0.9.2) + colored2 (~> 3.1) + cork (~> 0.1) + faraday (>= 0.9.0, < 2.0) + faraday-http-cache (~> 2.0) + git (~> 1.7) + kramdown (~> 2.3) + kramdown-parser-gfm (~> 1.0) + no_proxy_fix + octokit (~> 4.7) + terminal-table (>= 1, < 4) + faraday (1.10.2) + faraday-em_http (~> 1.0) + faraday-em_synchrony (~> 1.0) + faraday-excon (~> 1.1) + faraday-httpclient (~> 1.0) + faraday-multipart (~> 1.0) + faraday-net_http (~> 1.0) + faraday-net_http_persistent (~> 1.0) + faraday-patron (~> 1.0) + faraday-rack (~> 1.0) + faraday-retry (~> 1.0) + ruby2_keywords (>= 0.0.4) + faraday-em_http (1.0.0) + faraday-em_synchrony (1.0.0) + faraday-excon (1.1.0) + faraday-http-cache (2.4.1) + faraday (>= 0.8) + faraday-httpclient (1.0.1) + faraday-multipart (1.0.4) + multipart-post (~> 2) + faraday-net_http (1.0.1) + faraday-net_http_persistent (1.2.0) + faraday-patron (1.0.0) + faraday-rack (1.0.0) + faraday-retry (1.0.3) + git (1.12.0) + addressable (~> 2.8) + rchardet (~> 1.8) + kramdown (2.4.0) + rexml + kramdown-parser-gfm (1.1.0) + kramdown (~> 2.0) + multipart-post (2.2.3) + nap (1.1.0) + no_proxy_fix (0.1.2) + octokit (4.25.1) + faraday (>= 1, < 3) + sawyer (~> 0.9) + open4 (1.3.4) + public_suffix (5.0.0) + rchardet (1.8.0) + rexml (3.2.5) + ruby2_keywords (0.0.5) + sawyer (0.9.2) + addressable (>= 2.3.5) + faraday (>= 0.17.3, < 3) + terminal-table (3.0.2) + unicode-display_width (>= 1.1.1, < 3) + unicode-display_width (2.3.0) + +PLATFORMS + ruby + +DEPENDENCIES + danger (~> 8.6, >= 8.6.1) + +BUNDLED WITH + 1.17.2 diff --git a/android/build.gradle b/android/build.gradle index 510effb27..fc3eee7b7 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -53,8 +53,11 @@ task upload_sourcemap(type: Exec) { } tasks.whenTaskAdded { task -> - if (task.name == 'preReleaseBuild' && - (rootProject.hasProperty("instabugUploadEnable") ? rootProject.instabugUploadEnable : true)) { + def isEnabled = rootProject.hasProperty('instabugUploadEnable') + ? new Boolean(rootProject.property('instabugUploadEnable')) + : true + + if (task.name == 'preReleaseBuild' && isEnabled) { task.dependsOn upload_sourcemap } } diff --git a/android/src/main/java/com/instabug/reactlibrary/ArgsRegistry.java b/android/src/main/java/com/instabug/reactlibrary/ArgsRegistry.java index c112d7c31..e9278f5a2 100644 --- a/android/src/main/java/com/instabug/reactlibrary/ArgsRegistry.java +++ b/android/src/main/java/com/instabug/reactlibrary/ArgsRegistry.java @@ -1,6 +1,7 @@ package com.instabug.reactlibrary; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.instabug.apm.model.LogLevel; import com.instabug.bug.BugReporting; @@ -41,6 +42,17 @@ public ArrayList getAll(ArrayList keys) { } return values; } + + @Nullable + public String getKey(T value) { + for (Entry entry : this.entrySet()) { + if (entry.getValue().equals(value)) { + return entry.getKey(); + } + } + + return null; + } } static Map getAll() { @@ -53,6 +65,7 @@ static Map getAll() { putAll(recordButtonPositions); putAll(welcomeMessageStates); putAll(reportTypes); + putAll(sdkDismissReportTypes); putAll(dismissTypes); putAll(actionTypes); putAll(extendedBugReportStates); @@ -121,6 +134,13 @@ static Map getAll() { put("bugReportingReportTypeQuestion", BugReporting.ReportType.QUESTION); }}; + static final ArgsMap sdkDismissReportTypes = new ArgsMap() {{ + put("bugReportingReportTypeBug", OnSdkDismissCallback.ReportType.BUG); + put("bugReportingReportTypeFeedback", OnSdkDismissCallback.ReportType.FEEDBACK); + put("bugReportingReportTypeQuestion", OnSdkDismissCallback.ReportType.QUESTION); + put("bugReportingReportTypeOther", OnSdkDismissCallback.ReportType.OTHER); + }}; + static final ArgsMap dismissTypes = new ArgsMap() {{ put("dismissTypeSubmit", DismissType.SUBMIT); put("dismissTypeCancel", DismissType.CANCEL); diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugBugReportingModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugBugReportingModule.java index 5a0de326e..d17e8b94b 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugBugReportingModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugBugReportingModule.java @@ -6,7 +6,6 @@ import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.WritableMap; @@ -20,15 +19,14 @@ import com.instabug.library.invocation.util.InstabugFloatingButtonEdge; import com.instabug.library.invocation.util.InstabugVideoRecordingButtonPosition; import com.instabug.reactlibrary.utils.ArrayUtil; -import com.instabug.reactlibrary.utils.InstabugUtil; +import com.instabug.reactlibrary.utils.EventEmitterModule; import com.instabug.reactlibrary.utils.MainThreadHandler; import java.util.ArrayList; import javax.annotation.Nonnull; -public class RNInstabugBugReportingModule extends ReactContextBaseJavaModule { - +public class RNInstabugBugReportingModule extends EventEmitterModule { public RNInstabugBugReportingModule(ReactApplicationContext reactContext) { super(reactContext); } @@ -39,6 +37,16 @@ public String getName() { return "IBGBugReporting"; } + @ReactMethod + public void addListener(String event) { + super.addListener(event); + } + + @ReactMethod + public void removeListeners(Integer count) { + super.removeListeners(count); + } + /** * Enable or disable all BugReporting related features. * @param isEnabled boolean indicating enabled or disabled. @@ -235,10 +243,10 @@ public void setOnInvokeHandler(final Callback onInvokeHandler) { @Override public void run() { try { - BugReporting.setOnInvokeCallback(new OnInvokeCallback() { + BugReporting.setOnInvokeCallback(new OnInvokeCallback() { @Override public void onInvoke() { - InstabugUtil.sendEvent(getReactApplicationContext(), Constants.IBG_PRE_INVOCATION_HANDLER, null); + sendEvent(Constants.IBG_PRE_INVOCATION_HANDLER, null); } }); } catch (java.lang.Exception exception) { @@ -275,7 +283,7 @@ public void run() { * dismissing the SDK. */ @ReactMethod - public void setOnSDKDismissedHandler(final Callback handler) { + public void setOnDismissHandler(final Callback handler) { MainThreadHandler.runOnMainThread(new Runnable() { @Override public void run() { @@ -283,10 +291,14 @@ public void run() { BugReporting.setOnDismissCallback(new OnSdkDismissCallback() { @Override public void call(DismissType dismissType, ReportType reportType) { - WritableMap params = Arguments.createMap(); - params.putString("dismissType", dismissType.toString()); - params.putString("reportType", reportType.toString()); - InstabugUtil.sendEvent(getReactApplicationContext(), Constants.IBG_POST_INVOCATION_HANDLER, params); + final String dismissKey = ArgsRegistry.dismissTypes.getKey(dismissType); + final String reportKey = ArgsRegistry.sdkDismissReportTypes.getKey(reportType); + final WritableMap params = Arguments.createMap(); + + params.putString("dismissType", dismissKey); + params.putString("reportType", reportKey); + + sendEvent(Constants.IBG_POST_INVOCATION_HANDLER, params); } }); } catch (java.lang.Exception exception) { diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java index 85d29c05a..1c6f6f319 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java @@ -1,68 +1,44 @@ package com.instabug.reactlibrary; -import android.annotation.SuppressLint; -import android.app.Application; +import static com.instabug.reactlibrary.utils.InstabugUtil.getMethod; + import android.graphics.Bitmap; import android.net.Uri; -import android.os.Handler; -import android.os.Looper; import android.util.Log; import android.view.View; import com.facebook.react.bridge.Arguments; -import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableArray; -import com.facebook.react.bridge.WritableNativeArray; import com.facebook.react.bridge.WritableMap; +import com.facebook.react.bridge.WritableNativeArray; import com.facebook.react.bridge.WritableNativeMap; -import com.facebook.react.bridge.Callback; - -import com.facebook.react.modules.core.DeviceEventManagerModule; import com.facebook.react.uimanager.NativeViewHierarchyManager; import com.facebook.react.uimanager.UIBlock; import com.facebook.react.uimanager.UIManagerModule; import com.instabug.apm.APM; -import com.instabug.bug.BugReporting; import com.instabug.bug.instabugdisclaimer.Internal; -import com.instabug.bug.invocation.Option; -import com.instabug.chat.Replies; -import com.instabug.crash.CrashReporting; -import com.instabug.featuresrequest.FeatureRequests; -import com.instabug.featuresrequest.ActionType; import com.instabug.library.Feature; import com.instabug.library.Instabug; -import com.instabug.library.InstabugState; -import com.instabug.library.OnSdkDismissCallback; -import com.instabug.library.Platform; +import com.instabug.library.InstabugColorTheme; +import com.instabug.library.InstabugCustomTextPlaceHolder; import com.instabug.library.LogLevel; -import com.instabug.library.extendedbugreport.ExtendedBugReport; +import com.instabug.library.Platform; import com.instabug.library.internal.module.InstabugLocale; import com.instabug.library.invocation.InstabugInvocationEvent; -import com.instabug.library.InstabugColorTheme; -import com.instabug.library.invocation.OnInvokeCallback; -import com.instabug.library.invocation.util.InstabugFloatingButtonEdge; -import com.instabug.library.invocation.util.InstabugVideoRecordingButtonPosition; import com.instabug.library.logging.InstabugLog; -import com.instabug.library.ui.onboarding.WelcomeMessage; -import com.instabug.library.InstabugCustomTextPlaceHolder; -import com.instabug.library.model.Report; import com.instabug.library.model.NetworkLog; +import com.instabug.library.model.Report; +import com.instabug.library.ui.onboarding.WelcomeMessage; import com.instabug.library.visualusersteps.State; - import com.instabug.reactlibrary.utils.ArrayUtil; +import com.instabug.reactlibrary.utils.EventEmitterModule; import com.instabug.reactlibrary.utils.InstabugUtil; import com.instabug.reactlibrary.utils.MainThreadHandler; -import com.instabug.reactlibrary.utils.ReportUtil; -import com.instabug.survey.callbacks.*; -import com.instabug.survey.Survey; -import com.instabug.survey.Surveys; -import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONTokener; @@ -73,18 +49,15 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; -import static com.instabug.reactlibrary.utils.InstabugUtil.getMethod; - /** * The type Rn instabug reactnative module. */ -public class RNInstabugReactnativeModule extends ReactContextBaseJavaModule { +public class RNInstabugReactnativeModule extends EventEmitterModule { private static final String TAG = RNInstabugReactnativeModule.class.getSimpleName(); @@ -98,7 +71,7 @@ public class RNInstabugReactnativeModule extends ReactContextBaseJavaModule { */ public RNInstabugReactnativeModule(ReactApplicationContext reactContext) { super(reactContext); - //init placHolders + //init placeHolders placeHolders = new InstabugCustomTextPlaceHolder(); } @@ -106,7 +79,18 @@ public RNInstabugReactnativeModule(ReactApplicationContext reactContext) { public String getName() { return "Instabug"; } - + + + @ReactMethod + public void addListener(String event) { + super.addListener(event); + } + + @ReactMethod + public void removeListeners(Integer count) { + super.removeListeners(count); + } + /** * Enables or disables Instabug functionality. * @param isEnabled A boolean to enable/disable Instabug. @@ -233,28 +217,6 @@ public void run() { }); } - /** - * Sets whether the extended bug report mode should be disabled, - * enabled with required fields, or enabled with optional fields. - * - * @param extendedBugReportMode - */ - @ReactMethod - public void setExtendedBugReportMode(final String extendedBugReportMode) { - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - final ExtendedBugReport.State state = ArgsRegistry.extendedBugReportStates - .getOrDefault(extendedBugReportMode, ExtendedBugReport.State.DISABLED); - BugReporting.setExtendedBugReportState(state); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - } - /** * The file at filePath will be uploaded along upcoming reports with the name * fileNameWithExtension @@ -385,165 +347,6 @@ public void run() { }); } - /** - * Is enabled boolean. - * - * @return {@code true} if Instabug is enabled, {@code false} if it's disabled - * @see #enable() - * @see #disable() - */ - @ReactMethod - public boolean isEnabled() { - boolean isEnabled = false; - try { - isEnabled = Instabug.isEnabled(); - } catch (Exception e) { - e.printStackTrace(); - } - return isEnabled; - } - - - /** - * Enables all Instabug functionality - */ - @ReactMethod - public void enable() { - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - Instabug.enable(); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - } - - /** - * Disables all Instabug functionality - */ - @ReactMethod - public void disable() { - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - Instabug.disable(); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - } - - /** - * Shows the UI for feature requests list - */ - @ReactMethod - public void showFeatureRequests() { - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - FeatureRequests.show(); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - } - - /** - * @return application token - */ - @ReactMethod - public String getAppToken() { - String appToken = ""; - try { - appToken = Instabug.getAppToken(); - } catch (Exception e) { - e.printStackTrace(); - } - - return appToken; - } - - /** - * @deprecated - * Sets the event used to invoke Instabug SDK - * - * @param invocationEventValue the invocation event value - * @see InstabugInvocationEvent - */ - @ReactMethod - public void setInvocationEvent(final String invocationEventValue) { - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - final InstabugInvocationEvent invocationEvent = ArgsRegistry.invocationEvents - .getOrDefault(invocationEventValue, InstabugInvocationEvent.SHAKE); - BugReporting.setInvocationEvents(invocationEvent); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - } - - /** - * Sets the event used to invoke Instabug SDK - * - * @param invocationEventValues the invocation event value - * @see InstabugInvocationEvent - */ - @ReactMethod - public void setInvocationEvents(final ReadableArray invocationEventValues) { - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - final ArrayList keys = ArrayUtil.parseReadableArrayOfStrings(invocationEventValues); - final ArrayList parsedInvocationEvents = ArgsRegistry.invocationEvents.getAll(keys); - BugReporting.setInvocationEvents(parsedInvocationEvents.toArray(new InstabugInvocationEvent[0])); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - } - - /** - * Sets the event used to invoke Instabug SDK - * - * @param invocationOptionValues the invocation event value - * @see InstabugInvocationEvent - */ - @ReactMethod - public void setInvocationOptions(final ReadableArray invocationOptionValues) { - MainThreadHandler.runOnMainThread(new Runnable() { - @SuppressLint("WrongConstant") - @Override - public void run() { - try { - final ArrayList keys = ArrayUtil.parseReadableArrayOfStrings(invocationOptionValues); - final ArrayList options = ArgsRegistry.invocationOptions.getAll(keys); - - final int[] optionsInts = new int[options.size()]; - for (int i = 0; i < options.size(); i++) { - optionsInts[i] = options.get(i); - } - - BugReporting.setOptions(optionsInts); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - } - /** * Enable/Disable debug logs from Instabug SDK * Default state: disabled @@ -564,58 +367,6 @@ public void run() { }); } - - - - /** - * Appends a log message to Instabug internal log - *

- * These logs are then sent along the next uploaded report. - * All log messages are timestamped
- * Logs aren't cleared per single application run. If you wish to reset the logs, - * use {@link #clearLogs()} ()} - *

- * Note: logs passed to this method are NOT printed to Logcat - * - * @param level the level - * @param message the message - */ - @ReactMethod - public void log(final String level, final String message) { - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - switch (level) { - case "v": - InstabugLog.v(message); - break; - case "i": - InstabugLog.i(message); - break; - case "d": - InstabugLog.d(message); - break; - case "e": - InstabugLog.e(message); - break; - case "w": - InstabugLog.w(message); - break; - case "wtf": - InstabugLog.wtf(message); - break; - default: - InstabugLog.d(message); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - - } - @ReactMethod public void logVerbose(final String message) { MainThreadHandler.runOnMainThread(new Runnable() { @@ -703,52 +454,6 @@ public void run() { }); } - /** - * Returns true if the survey with a specific token was answered before. - * Will return false if the token does not exist or if the survey was not answered before. - * - * @param surveyToken the attribute key as string - * @param hasRespondedCallback A callback that gets invoked with the returned value of whether - * the user has responded to the survey or not. - * @return the desired value of whether the user has responded to the survey or not. - */ - @ReactMethod - public void hasRespondedToSurveyWithToken(final String surveyToken, final Callback hasRespondedCallback) { - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - boolean hasResponded; - try { - hasResponded = Surveys.hasRespondToSurvey(surveyToken); - hasRespondedCallback.invoke(hasResponded); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - } - - /** - * Shows survey with a specific token. - * Does nothing if there are no available surveys with that specific token. - * Answered and cancelled surveys won't show up again. - * - * @param surveyToken A String with a survey token. - */ - @ReactMethod - public void showSurveyWithToken(final String surveyToken) { - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - Surveys.showSurvey(surveyToken); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - } - /** * Sets user attribute to overwrite it's value or create a new one if it doesn't exist. * @@ -936,33 +641,6 @@ public void run() { }); } - /** - * Sets a block of code to be executed just before the SDK's UI is presented. - * This block is executed on the UI thread. Could be used for performing any - * UI changes before the SDK's UI is shown. - * - * @param preInvocationHandler - A callback that gets executed before - * invoking the SDK - */ - @ReactMethod - public void setPreInvocationHandler(final Callback preInvocationHandler) { - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - BugReporting.setOnInvokeCallback(new OnInvokeCallback() { - @Override - public void onInvoke() { - sendEvent(getReactApplicationContext(), "IBGpreInvocationHandler", null); - } - }); - } catch (java.lang.Exception exception) { - exception.printStackTrace(); - } - } - }); - } - /** * Sets a block of code to be executed before sending each report. * This block is executed in the background before sending each report. Could @@ -986,7 +664,7 @@ public void onReportCreated(Report report) { reportParam.putString("userData", report.getUserData()); reportParam.putMap("userAttributes", convertFromHashMapToWriteableMap(report.getUserAttributes())); reportParam.putMap("fileAttachments", convertFromHashMapToWriteableMap(report.getFileAttachments())); - sendEvent(getReactApplicationContext(), "IBGpreSendingHandler", reportParam); + sendEvent("IBGpreSendingHandler", reportParam); currentReport = report; } }); @@ -1069,33 +747,6 @@ public void addFileAttachmentWithDataToReport(String data, String fileName) { } } - - @ReactMethod - public void getReport(Promise promise) { - try { - Method method = getMethod(Class.forName("com.instabug.library.Instabug"), "getReport"); - if (method != null) { - Report report = (Report) method.invoke(null); - WritableMap reportParam = Arguments.createMap(); - reportParam.putArray("tagsArray", convertArrayListToWritableArray(report.getTags())); - reportParam.putArray("consoleLogs", ReportUtil.parseConsoleLogs(report.getConsoleLog())); - reportParam.putString("userData", report.getUserData()); - reportParam.putMap("userAttributes", convertFromHashMapToWriteableMap(report.getUserAttributes())); - reportParam.putMap("fileAttachments", convertFromHashMapToWriteableMap(report.getFileAttachments())); - promise.resolve(reportParam); - currentReport = report; - } - - } catch (ClassNotFoundException e) { - promise.reject(e); - } catch (IllegalAccessException e) { - promise.reject(e); - } catch (InvocationTargetException e) { - promise.reject(e); - } - } - - private WritableMap convertFromHashMapToWriteableMap(HashMap hashMap) { WritableMap writableMap = new WritableNativeMap(); for(int i = 0; i < hashMap.size(); i++) { @@ -1139,100 +790,6 @@ private WritableArray convertArrayListToWritableArray(List arrayList) { } - /** - * Sets a block of code to be executed right after the SDK's UI is dismissed. - * This block is executed on the UI thread. Could be used for performing any - * UI changes after the SDK's UI is dismissed. - * - * @param postInvocationHandler - A callback to get executed after - * dismissing the SDK. - */ - @ReactMethod - public void setPostInvocationHandler(final Callback postInvocationHandler) { - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - BugReporting.setOnDismissCallback(new OnSdkDismissCallback() { - @Override - public void call(DismissType dismissType, ReportType reportType) { - WritableMap params = Arguments.createMap(); - params.putString("dismissType", dismissType.toString()); - params.putString("reportType", reportType.toString()); - sendEvent(getReactApplicationContext(), "IBGpostInvocationHandler", params); - } - }); - } catch (java.lang.Exception exception) { - exception.printStackTrace(); - } - } - }); - } - - /** - * Show any valid survey if exist - * - * @return true if a valid survey was shown otherwise false - */ - @ReactMethod - public void showSurveysIfAvailable() { - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - Surveys.showSurveyIfAvailable(); - } catch (java.lang.Exception exception) { - exception.printStackTrace(); - } - } - }); - } - - /** - * Sets the runnable that gets executed just before showing any valid survey
- * WARNING: This runs on your application's main UI thread. Please do not include - * any blocking operations to avoid ANRs. - * - * @param willShowSurveyHandler to run on the UI thread before showing any valid survey - */ - @ReactMethod - public void setWillShowSurveyHandler(final Callback willShowSurveyHandler) { - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - Surveys.setOnShowCallback(new OnShowCallback() { - @Override - public void onShow() { - sendEvent(getReactApplicationContext(), "IBGWillShowSurvey", null); - } - }); - } - }); - } - - /** - * Sets the runnable that gets executed just after showing any valid survey
- * WARNING: This runs on your application's main UI thread. Please do not include - * any blocking operations to avoid ANRs. - * - * @param didDismissSurveyHandler to run on the UI thread after showing any valid survey - */ - @ReactMethod - public void setDidDismissSurveyHandler(final Callback didDismissSurveyHandler) { - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - Surveys.setOnDismissCallback(new OnDismissCallback() { - @Override - public void onDismiss() { - sendEvent(getReactApplicationContext(), "IBGDidDismissSurvey", null); - } - }); - } - }); - } - - /** * Clears all Uris of the attached files. * The URIs which added via {@link Instabug#addFileAttachment} API not the physical files. @@ -1316,70 +873,6 @@ public void run() { }); } - /** - * Sets the threshold value of the shake gesture for android devices. - * Default for android is an integer value equals 350. - * you could increase the shaking difficulty level by - * increasing the `350` value and vice versa. - * - * @param androidThreshold Threshold for android devices. - */ - @ReactMethod - public void setShakingThresholdForAndroid(final int androidThreshold) { - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - BugReporting.setShakingThreshold(androidThreshold); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - } - - @ReactMethod - public void setOnNewReplyReceivedCallback(final Callback onNewReplyReceivedCallback) { - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - Runnable onNewReplyReceivedRunnable = new Runnable() { - @Override - public void run() { - sendEvent(getReactApplicationContext(), "IBGOnNewReplyReceivedCallback", null); - } - }; - Replies.setOnNewReplyReceivedCallback(onNewReplyReceivedRunnable); - } catch (java.lang.Exception exception) { - exception.printStackTrace(); - } - } - }); - } - - /** - * Returns an array containing the available surveys. - * @param availableSurveysCallback - Callback with the returned value of the available surveys - * - */ - @ReactMethod - public void getAvailableSurveys(final Callback availableSurveysCallback) { - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - List availableSurveys = Surveys.getAvailableSurveys(); - JSONArray surveysArray = toJson(availableSurveys); - WritableArray array = convertJsonToArray(surveysArray); - availableSurveysCallback.invoke(array); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - } - @ReactMethod public void show() { MainThreadHandler.runOnMainThread(new Runnable() { @@ -1390,64 +883,6 @@ public void run() { }); } - @ReactMethod - public void setBugReportingEnabled(final boolean isEnabled) { - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - if (isEnabled) { - BugReporting.setState(Feature.State.ENABLED); - } else { - BugReporting.setState(Feature.State.DISABLED); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - - } - - @ReactMethod - public void setRepliesEnabled(final boolean isEnabled) { - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - if (isEnabled) { - Replies.setState(Feature.State.ENABLED); - } else { - Replies.setState(Feature.State.DISABLED); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - } - - @ReactMethod - public void hasChats(final Callback callback) { - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - boolean hasChats = Replies.hasChats(); - callback.invoke(hasChats); - } - }); - } - - @ReactMethod - public void showReplies() { - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - Replies.show(); - } - }); - } - @ReactMethod public void callPrivateApi(String apiName, String param) { try { @@ -1466,95 +901,6 @@ public void callPrivateApi(String apiName, String param) { } } - - - private static WritableMap convertJsonToMap(JSONObject jsonObject) throws JSONException { - WritableMap map = new WritableNativeMap(); - - Iterator iterator = jsonObject.keys(); - while (iterator.hasNext()) { - String key = iterator.next(); - Object value = jsonObject.get(key); - if (value instanceof JSONObject) { - map.putMap(key, convertJsonToMap((JSONObject) value)); - } else if (value instanceof JSONArray) { - map.putArray(key, convertJsonToArray((JSONArray) value)); - } else if (value instanceof Boolean) { - map.putBoolean(key, (Boolean) value); - } else if (value instanceof Integer) { - map.putInt(key, (Integer) value); - } else if (value instanceof Double) { - map.putDouble(key, (Double) value); - } else if (value instanceof String) { - map.putString(key, (String) value); - } else { - map.putString(key, value.toString()); - } - } - return map; - } - - private static WritableArray convertJsonToArray(JSONArray jsonArray) throws JSONException { - WritableArray array = Arguments.createArray(); - - for (int i = 0; i < jsonArray.length(); i++) { - Object value = jsonArray.get(i); - if (value instanceof JSONObject) { - array.pushMap(convertJsonToMap((JSONObject) value)); - } else if (value instanceof JSONArray) { - array.pushArray(convertJsonToArray((JSONArray) value)); - } else if (value instanceof Boolean) { - array.pushBoolean((Boolean) value); - } else if (value instanceof Integer) { - array.pushInt((Integer) value); - } else if (value instanceof Double) { - array.pushDouble((Double) value); - } else if (value instanceof String) { - array.pushString((String) value); - } - } - return array; - } - - /** - * Convenience method to convert from a list of Surveys to a JSON array - * - * @param list - * List of Surveys to be converted to JSON array - */ - public static JSONArray toJson(List list) { - JSONArray jsonArray = new JSONArray(); - try{ - for (Survey obj : list) { - JSONObject object = new JSONObject(); - object.put("title", obj.getTitle()); - jsonArray.put(object); - } - } catch (JSONException e) { - e.printStackTrace(); - } - return jsonArray; - } - - /** - * Set Surveys auto-showing state, default state auto-showing enabled - * - * @param autoShowingSurveysEnabled whether Surveys should be auto-showing or not - */ - @ReactMethod - public void setAutoShowingSurveysEnabled(final boolean autoShowingSurveysEnabled) { - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - Surveys.setAutoShowingEnabled(autoShowingSurveysEnabled); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - } - /** * Enable/disable session profiler * @@ -1578,36 +924,6 @@ public void run() { }); } - /** - * Sets whether email field is required or not when submitting - * new-feature-request/new-comment-on-feature - * - * @param isEmailRequired set true to make email field required - * @param actionTypes Bitwise-or of actions - */ - @SuppressLint("WrongConstant") - @ReactMethod - public void setEmailFieldRequiredForFeatureRequests(final boolean isEmailRequired, final ReadableArray actionTypes) { - MainThreadHandler.runOnMainThread(new Runnable() { - @Override - public void run() { - try { - final ArrayList keys = ArrayUtil.parseReadableArrayOfStrings(actionTypes); - final ArrayList types = ArgsRegistry.actionTypes.getAll(keys); - - final int[] typesInts = new int[types.size()]; - for (int i = 0; i < types.size(); i++) { - typesInts[i] = types.get(i); - } - - FeatureRequests.setEmailFieldRequired(isEmailRequired, typesInts); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - } - /** * Extracts HTTP connection properties. Request method, Headers, Date, Url and Response code * @@ -1697,14 +1013,6 @@ public void run() { }); } - private void sendEvent(ReactApplicationContext reactContext, - String eventName, - WritableMap params) { - reactContext - .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) - .emit(eventName, params); - } - @ReactMethod public void addExperiments(final ReadableArray experiments) { MainThreadHandler.runOnMainThread(new Runnable() { diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugRepliesModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugRepliesModule.java index c83fd61db..25e14575f 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugRepliesModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugRepliesModule.java @@ -1,25 +1,21 @@ package com.instabug.reactlibrary; -import android.os.Handler; -import android.os.Looper; - import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableType; import com.facebook.react.bridge.ReadableMapKeySetIterator; import com.instabug.chat.Replies; import com.instabug.library.Feature; -import com.instabug.reactlibrary.utils.InstabugUtil; +import com.instabug.reactlibrary.utils.EventEmitterModule; import com.instabug.reactlibrary.utils.MainThreadHandler; import javax.annotation.Nonnull; import java.util.HashMap; import java.util.Map; -public class RNInstabugRepliesModule extends ReactContextBaseJavaModule { +public class RNInstabugRepliesModule extends EventEmitterModule { public RNInstabugRepliesModule(ReactApplicationContext reactApplicationContext) { super(reactApplicationContext); @@ -31,6 +27,16 @@ public String getName() { return "IBGReplies"; } + @ReactMethod + public void addListener(String event) { + super.addListener(event); + } + + @ReactMethod + public void removeListeners(Integer count) { + super.removeListeners(count); + } + @ReactMethod public void setEnabled(final boolean isEnabled) { MainThreadHandler.runOnMainThread(new Runnable() { @@ -278,7 +284,7 @@ public void run() { Runnable onNewReplyReceivedRunnable = new Runnable() { @Override public void run() { - InstabugUtil.sendEvent(getReactApplicationContext(), Constants.IBG_ON_NEW_REPLY_RECEIVED_CALLBACK, null); + sendEvent(Constants.IBG_ON_NEW_REPLY_RECEIVED_CALLBACK, null); } }; Replies.setOnNewReplyReceivedCallback(onNewReplyReceivedRunnable); diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugSurveysModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugSurveysModule.java index 349d02f67..c3e59be8f 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugSurveysModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugSurveysModule.java @@ -1,15 +1,12 @@ package com.instabug.reactlibrary; -import android.os.Handler; -import android.os.Looper; - import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.WritableArray; import com.instabug.library.Feature; import com.instabug.reactlibrary.utils.ArrayUtil; +import com.instabug.reactlibrary.utils.EventEmitterModule; import com.instabug.reactlibrary.utils.InstabugUtil; import com.instabug.reactlibrary.utils.MainThreadHandler; import com.instabug.survey.callbacks.*; @@ -22,7 +19,7 @@ import javax.annotation.Nonnull; -public class RNInstabugSurveysModule extends ReactContextBaseJavaModule { +public class RNInstabugSurveysModule extends EventEmitterModule { public RNInstabugSurveysModule(ReactApplicationContext reactContext) { super(reactContext); @@ -34,6 +31,16 @@ public String getName() { return "IBGSurveys"; } + @ReactMethod + public void addListener(String event) { + super.addListener(event); + } + + @ReactMethod + public void removeListeners(Integer count) { + super.removeListeners(count); + } + /** * Returns true if the survey with a specific token was answered before. * Will return false if the token does not exist or if the survey was not answered before. @@ -137,7 +144,7 @@ public void run() { Surveys.setOnShowCallback(new OnShowCallback() { @Override public void onShow() { - InstabugUtil.sendEvent(getReactApplicationContext(), Constants.IBG_ON_SHOW_SURVEY_HANDLER, null); + sendEvent(Constants.IBG_ON_SHOW_SURVEY_HANDLER, null); } }); } @@ -159,7 +166,7 @@ public void run() { Surveys.setOnDismissCallback(new OnDismissCallback() { @Override public void onDismiss() { - InstabugUtil.sendEvent(getReactApplicationContext(), Constants.IBG_ON_DISMISS_SURVEY_HANDLER, null); + sendEvent(Constants.IBG_ON_DISMISS_SURVEY_HANDLER, null); } }); } diff --git a/android/src/main/java/com/instabug/reactlibrary/utils/EventEmitterModule.java b/android/src/main/java/com/instabug/reactlibrary/utils/EventEmitterModule.java new file mode 100644 index 000000000..d2226cc49 --- /dev/null +++ b/android/src/main/java/com/instabug/reactlibrary/utils/EventEmitterModule.java @@ -0,0 +1,34 @@ +package com.instabug.reactlibrary.utils; + +import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; + +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.modules.core.DeviceEventManagerModule; + +public abstract class EventEmitterModule extends ReactContextBaseJavaModule { + private int listenerCount = 0; + + public EventEmitterModule(ReactApplicationContext context) { + super(context); + } + + @VisibleForTesting + public void sendEvent(String event, @Nullable WritableMap params) { + if (listenerCount > 0) { + getReactApplicationContext() + .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) + .emit(event, params); + } + } + + protected void addListener(String ignoredEvent) { + listenerCount++; + } + + protected void removeListeners(Integer count) { + listenerCount -= count; + } +} diff --git a/android/src/main/java/com/instabug/reactlibrary/utils/InstabugUtil.java b/android/src/main/java/com/instabug/reactlibrary/utils/InstabugUtil.java index f2ca2505b..2b64a2538 100644 --- a/android/src/main/java/com/instabug/reactlibrary/utils/InstabugUtil.java +++ b/android/src/main/java/com/instabug/reactlibrary/utils/InstabugUtil.java @@ -41,14 +41,6 @@ public static Method getMethod(Class clazz, String methodName, Class... paramete return null; } - public static void sendEvent(ReactApplicationContext reactContext, - String eventName, - WritableMap params) { - reactContext - .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) - .emit(eventName, params); - } - /** * Convenience method to convert from a list of Surveys to a JSON array * diff --git a/android/src/test/java/com/instabug/reactlibrary/RNInstabugBugReportingModuleTest.java b/android/src/test/java/com/instabug/reactlibrary/RNInstabugBugReportingModuleTest.java index dab156cbe..f9548fae7 100644 --- a/android/src/test/java/com/instabug/reactlibrary/RNInstabugBugReportingModuleTest.java +++ b/android/src/test/java/com/instabug/reactlibrary/RNInstabugBugReportingModuleTest.java @@ -37,12 +37,13 @@ import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; public class RNInstabugBugReportingModuleTest { - private RNInstabugBugReportingModule bugReportingModule = new RNInstabugBugReportingModule(mock(ReactApplicationContext.class)); + private RNInstabugBugReportingModule bugReportingModule = spy(new RNInstabugBugReportingModule(mock(ReactApplicationContext.class))); private final static ScheduledExecutorService mainThread = Executors.newSingleThreadScheduledExecutor(); // Mock Objects @@ -240,34 +241,34 @@ public Object answer(InvocationOnMock invocation) { bugReportingModule.setOnInvokeHandler(null); // then - verify(InstabugUtil.class,VerificationModeFactory.times(1)); - InstabugUtil.sendEvent(any(ReactApplicationContext.class), eq(Constants.IBG_PRE_INVOCATION_HANDLER), Matchers.isNull(WritableMap.class)); + verify(bugReportingModule).sendEvent(Constants.IBG_PRE_INVOCATION_HANDLER, null); } @Test - public void given$setOnSDKDismissedHandler_whenQuery_thenShouldSetNativeCallback() { + public void given$setOnDismissHandler_whenQuery_thenShouldSetNativeCallback() { // given MockedStatic mockArgument = mockStatic(Arguments.class); MockedStatic mockReactApplicationContext = mockStatic(ReactApplicationContext.class); + final OnSdkDismissCallback.DismissType dismissType = OnSdkDismissCallback.DismissType.CANCEL; + final OnSdkDismissCallback.ReportType reportType = OnSdkDismissCallback.ReportType.BUG; // when when(Arguments.createMap()).thenReturn(new JavaOnlyMap()); mockBugReporting.when(() -> BugReporting.setOnDismissCallback(any(OnSdkDismissCallback.class))).thenAnswer(new Answer() { public Object answer(InvocationOnMock invocation) { - InstabugUtil.sendEvent(any(),any(),any()); ((OnSdkDismissCallback) invocation.getArguments()[0]) - .call(OnSdkDismissCallback.DismissType.CANCEL, OnSdkDismissCallback.ReportType.BUG); + .call(dismissType, reportType); return null; }}); - bugReportingModule.setOnSDKDismissedHandler(null); + bugReportingModule.setOnDismissHandler(null); // then WritableMap params = new JavaOnlyMap(); - params.putString("dismissType", OnSdkDismissCallback.DismissType.CANCEL.toString()); - params.putString("reportType", OnSdkDismissCallback.ReportType.BUG.toString()); - verify(InstabugUtil.class,VerificationModeFactory.times(1)); - InstabugUtil.sendEvent(any(ReactApplicationContext.class), eq(Constants.IBG_POST_INVOCATION_HANDLER), eq(params)); + params.putString("dismissType", ArgsRegistry.dismissTypes.getKey(dismissType)); + params.putString("reportType", ArgsRegistry.sdkDismissReportTypes.getKey(reportType)); + + verify(bugReportingModule).sendEvent(Constants.IBG_POST_INVOCATION_HANDLER, params); mockArgument.close(); mockReactApplicationContext.close(); } diff --git a/android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java b/android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java index 2907387bc..cf0c6a56c 100644 --- a/android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java +++ b/android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java @@ -228,54 +228,6 @@ public void tearDown() { Instabug.resetTags(); } - @Test - public void given$isEnabled_whenQuery_thenShouldCallNativeApiAndReturnValue() { - // given - - when(Instabug.isEnabled()).thenReturn(true); - // when - boolean isEnabled = rnModule.isEnabled(); - // then - verify(Instabug.class,times(1)); - Instabug.isEnabled(); - Assert.assertTrue(isEnabled); - } - - @Test - public void given$enable_whenQuery_thenShouldCallNativeApi() { - // given - - // when - rnModule.enable(); - // then - verify(Instabug.class,times(1)); - Instabug.enable(); - } - - @Test - public void given$disable_whenQuery_thenShouldCallNativeApi() { - // given - - // when - rnModule.disable(); - // then - verify(Instabug.class,times(1)); - Instabug.disable(); - } - - @Test - public void given$getAppToken_whenQuery_thenShouldCallNativeApiAndReturnValue() { - // given - - when(Instabug.getAppToken()).thenReturn("APP_TOKEN"); - // when - String appToken = rnModule.getAppToken(); - // then - verify(Instabug.class,times(1)); - Instabug.getAppToken(); - Assert.assertEquals("APP_TOKEN", appToken); - } - @Test public void given$logOut_whenQuery_thenShouldCallNativeApi() { // given diff --git a/android/src/test/java/com/instabug/reactlibrary/RNInstabugSurveysModuleTest.java b/android/src/test/java/com/instabug/reactlibrary/RNInstabugSurveysModuleTest.java index 38d666a7c..e216ce433 100644 --- a/android/src/test/java/com/instabug/reactlibrary/RNInstabugSurveysModuleTest.java +++ b/android/src/test/java/com/instabug/reactlibrary/RNInstabugSurveysModuleTest.java @@ -7,7 +7,6 @@ import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.JavaOnlyArray; import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.WritableMap; import com.instabug.library.Feature; import com.instabug.reactlibrary.utils.InstabugUtil; import com.instabug.survey.Survey; @@ -23,7 +22,6 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.mockito.Matchers; import org.mockito.MockedStatic; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; @@ -34,19 +32,17 @@ import java.util.concurrent.ScheduledExecutorService; import static org.mockito.Matchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; public class RNInstabugSurveysModuleTest { - private RNInstabugSurveysModule surveysModule = new RNInstabugSurveysModule(mock(ReactApplicationContext.class)); - - private final static ScheduledExecutorService mainThread = Executors.newSingleThreadScheduledExecutor(); + private RNInstabugSurveysModule surveysModule = spy(new RNInstabugSurveysModule(mock(ReactApplicationContext.class))); // Mock Objects private MockedStatic mockLooper; @@ -180,8 +176,7 @@ public Object answer(InvocationOnMock invocation) { surveysModule.setOnShowHandler(null); // then - verify(InstabugUtil.class,times(1)); - InstabugUtil.sendEvent(any(ReactApplicationContext.class), eq(Constants.IBG_ON_SHOW_SURVEY_HANDLER), Matchers.isNull(WritableMap.class)); + verify(surveysModule).sendEvent(Constants.IBG_ON_SHOW_SURVEY_HANDLER, null); } @Test @@ -200,8 +195,7 @@ public Object answer(InvocationOnMock invocation) { surveysModule.setOnDismissHandler(null); // then - verify(InstabugUtil.class,times(1)); - InstabugUtil.sendEvent(any(ReactApplicationContext.class), eq(Constants.IBG_ON_DISMISS_SURVEY_HANDLER), Matchers.isNull(WritableMap.class)); + verify(surveysModule).sendEvent(Constants.IBG_ON_DISMISS_SURVEY_HANDLER, null); } @Test diff --git a/cli/UploadSourcemaps.ts b/cli/UploadSourcemaps.ts index 5f86329e1..d2a9315b4 100755 --- a/cli/UploadSourcemaps.ts +++ b/cli/UploadSourcemaps.ts @@ -2,11 +2,10 @@ import axios from 'axios'; import { Command, Option } from 'commander'; import FormData from 'form-data'; import fs from 'fs'; -import path from 'path'; interface UploadSourcemapsOptions { platform: 'android' | 'ios'; - dir: string; + file: string; token: string; name: string; code: string; @@ -23,10 +22,7 @@ uploadSourcemapsCommand .makeOptionMandatory(), ) .addOption( - new Option( - '-d, --dir ', - 'The path of the directory including the source map file', - ).makeOptionMandatory(), + new Option('-f, --file ', 'The path of the source map file').makeOptionMandatory(), ) .addOption( new Option('-t, --token ', 'Your App Token') @@ -56,8 +52,7 @@ uploadSourcemapsCommand const uploadSourcemaps = async (opts: UploadSourcemapsOptions) => { const fileName = `${opts.platform}-sourcemap.json`; - const filePath = path.join(opts.dir, fileName); - const fileBlob = fs.readFileSync(filePath); + const fileBlob = fs.readFileSync(opts.file); const version = { code: opts.code, diff --git a/example/.detoxrc.json b/example/.detoxrc.json index 7461e99a3..7357f9794 100644 --- a/example/.detoxrc.json +++ b/example/.detoxrc.json @@ -22,7 +22,7 @@ }, "android.emu.release": { "binaryPath": "android/app/build/outputs/apk/release/app-release.apk", - "build": "cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release && cd ..", + "build": "cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release -PinstabugUploadEnable=false && cd ..", "type": "android.emulator", "name": "Nexus_6P_API_27" } diff --git a/example/ios/InstabugTests/InstabugBugReportingTests.m b/example/ios/InstabugTests/InstabugBugReportingTests.m index 73d13357c..4a3f08f04 100644 --- a/example/ios/InstabugTests/InstabugBugReportingTests.m +++ b/example/ios/InstabugTests/InstabugBugReportingTests.m @@ -70,40 +70,51 @@ - (void) testgivenHandler$setOnInvokeHandler_whenQuery_thenShouldCallNativeApi { } -- (void) testgivenHandlerCANCEL$setOnSDKDismissedHandler_whenQuery_thenShouldCallNativeApi { +- (void) testgivenHandlerCANCEL$setOnDismissHandler_whenQuery_thenShouldCallNativeApi { id partialMock = OCMPartialMock(self.instabugBridge); + IBGDismissType dismissType = IBGDismissTypeCancel; + IBGReportType reportType = IBGReportTypeBug; + RCTResponseSenderBlock callback = ^(NSArray *response) {}; - [partialMock setOnSDKDismissedHandler:callback]; + [partialMock setOnDismissHandler:callback]; XCTAssertNotNil(IBGBugReporting.didDismissHandler); - NSDictionary *result = @{ @"dismissType": @"CANCEL", - @"reportType": @"bug"}; + NSDictionary *result = @{ @"dismissType": @(dismissType), + @"reportType": @(reportType)}; + OCMStub([partialMock sendEventWithName:@"IBGpostInvocationHandler" body:result]); - IBGBugReporting.didDismissHandler(IBGDismissTypeCancel,IBGReportTypeBug); + IBGBugReporting.didDismissHandler(dismissType, reportType); OCMVerify([partialMock sendEventWithName:@"IBGpostInvocationHandler" body:result]); } -- (void) testgivenHandlerSUBMIT$setOnSDKDismissedHandler_whenQuery_thenShouldCallNativeApi { +- (void) testgivenHandlerSUBMIT$setOnDismissHandler_whenQuery_thenShouldCallNativeApi { id partialMock = OCMPartialMock(self.instabugBridge); + IBGDismissType dismissType = IBGDismissTypeSubmit; + IBGReportType reportType = IBGReportTypeFeedback; + RCTResponseSenderBlock callback = ^(NSArray *response) {}; - [partialMock setOnSDKDismissedHandler:callback]; + [partialMock setOnDismissHandler:callback]; XCTAssertNotNil(IBGBugReporting.didDismissHandler); - - NSDictionary *result = @{ @"dismissType": @"SUBMIT", - @"reportType": @"feedback"}; + NSDictionary *result = @{ @"dismissType": @(dismissType), + @"reportType": @(reportType)}; + OCMStub([partialMock sendEventWithName:@"IBGpostInvocationHandler" body:result]); - IBGBugReporting.didDismissHandler(IBGDismissTypeSubmit,IBGReportTypeFeedback); + IBGBugReporting.didDismissHandler(dismissType, reportType); OCMVerify([partialMock sendEventWithName:@"IBGpostInvocationHandler" body:result]); } -- (void) testgivenHandlerADD_ATTACHMENT$setOnSDKDismissedHandler_whenQuery_thenShouldCallNativeApi { +- (void) testgivenHandlerADD_ATTACHMENT$setOnDismissHandler_whenQuery_thenShouldCallNativeApi { id partialMock = OCMPartialMock(self.instabugBridge); + IBGDismissType dismissType = IBGDismissTypeAddAttachment; + IBGReportType reportType = IBGReportTypeFeedback; + RCTResponseSenderBlock callback = ^(NSArray *response) {}; - [partialMock setOnSDKDismissedHandler:callback]; + [partialMock setOnDismissHandler:callback]; XCTAssertNotNil(IBGBugReporting.didDismissHandler); - NSDictionary *result = @{ @"dismissType": @"ADD_ATTACHMENT", - @"reportType": @"feedback"}; + NSDictionary *result = @{ @"dismissType": @(dismissType), + @"reportType": @(reportType)}; + OCMStub([partialMock sendEventWithName:@"IBGpostInvocationHandler" body:result]); - IBGBugReporting.didDismissHandler(IBGDismissTypeAddAttachment,IBGReportTypeFeedback); + IBGBugReporting.didDismissHandler(dismissType, reportType); OCMVerify([partialMock sendEventWithName:@"IBGpostInvocationHandler" body:result]); } diff --git a/ios/RNInstabug/ArgsRegistry.m b/ios/RNInstabug/ArgsRegistry.m index 09317194a..8256141d8 100644 --- a/ios/RNInstabug/ArgsRegistry.m +++ b/ios/RNInstabug/ArgsRegistry.m @@ -14,6 +14,7 @@ + (NSMutableDictionary *) getAll { [all addEntriesFromDictionary:ArgsRegistry.recordButtonPositions]; [all addEntriesFromDictionary:ArgsRegistry.welcomeMessageStates]; [all addEntriesFromDictionary:ArgsRegistry.reportTypes]; + [all addEntriesFromDictionary:ArgsRegistry.sdkDimissReportTypes]; [all addEntriesFromDictionary:ArgsRegistry.dismissTypes]; [all addEntriesFromDictionary:ArgsRegistry.actionTypes]; [all addEntriesFromDictionary:ArgsRegistry.extendedBugReportStates]; @@ -112,6 +113,15 @@ + (ArgsDictionary *) reportTypes { }; } ++ (ArgsDictionary *) sdkDimissReportTypes { + return @{ + @"bugReportingReportTypeBug": @(IBGReportTypeBug), + @"bugReportingReportTypeFeedback": @(IBGReportTypeFeedback), + @"bugReportingReportTypeQuestion": @(IBGReportTypeQuestion), + @"bugReportingReportTypeOther": @(IBGReportTypeOther), + }; +} + + (ArgsDictionary *) dismissTypes { return @{ @"dismissTypeSubmit": @(IBGDismissTypeSubmit), diff --git a/ios/RNInstabug/InstabugBugReportingBridge.h b/ios/RNInstabug/InstabugBugReportingBridge.h index ffb393a0a..c7cdddd95 100644 --- a/ios/RNInstabug/InstabugBugReportingBridge.h +++ b/ios/RNInstabug/InstabugBugReportingBridge.h @@ -29,7 +29,7 @@ - (void)setOnInvokeHandler:(RCTResponseSenderBlock)callBack; -- (void)setOnSDKDismissedHandler:(RCTResponseSenderBlock)callBack; +- (void)setOnDismissHandler:(RCTResponseSenderBlock)callBack; - (void)setShakingThresholdForiPhone:(double)iPhoneShakingThreshold; diff --git a/ios/RNInstabug/InstabugBugReportingBridge.m b/ios/RNInstabug/InstabugBugReportingBridge.m index 121a33cf5..e93553c07 100644 --- a/ios/RNInstabug/InstabugBugReportingBridge.m +++ b/ios/RNInstabug/InstabugBugReportingBridge.m @@ -57,31 +57,17 @@ + (BOOL)requiresMainQueueSetup } } -RCT_EXPORT_METHOD(setOnSDKDismissedHandler:(RCTResponseSenderBlock)callBack) { +RCT_EXPORT_METHOD(setOnDismissHandler:(RCTResponseSenderBlock)callBack) { if (callBack != nil) { IBGBugReporting.didDismissHandler = ^(IBGDismissType dismissType, IBGReportType reportType) { - - //parse dismiss type enum - NSString* dismissTypeString; - if (dismissType == IBGDismissTypeCancel) { - dismissTypeString = @"CANCEL"; - } else if (dismissType == IBGDismissTypeSubmit) { - dismissTypeString = @"SUBMIT"; - } else if (dismissType == IBGDismissTypeAddAttachment) { - dismissTypeString = @"ADD_ATTACHMENT"; - } - - //parse report type enum - NSString* reportTypeString; - if (reportType == IBGReportTypeBug) { - reportTypeString = @"bug"; - } else if (reportType == IBGReportTypeFeedback) { - reportTypeString = @"feedback"; - } else { - reportTypeString = @"other"; - } - NSDictionary *result = @{ @"dismissType": dismissTypeString, - @"reportType": reportTypeString}; + // Unlinke Android, we do NOT need to map the iOS Enums to their JS constant names. + // This is because the JS Enums are mapped to the actual values of the + // iOS Enums (NSInteger), not strings as it's implemented on Android. + NSDictionary *result = @{ + @"dismissType": @(dismissType), + @"reportType": @(reportType) + }; + [self sendEventWithName:@"IBGpostInvocationHandler" body: result]; }; } else { diff --git a/ios/RNInstabug/InstabugReactBridge.m b/ios/RNInstabug/InstabugReactBridge.m index 3989f8a58..3f8025db7 100644 --- a/ios/RNInstabug/InstabugReactBridge.m +++ b/ios/RNInstabug/InstabugReactBridge.m @@ -24,10 +24,7 @@ + (void)setWillSendReportHandler_private:(void(^)(IBGReport *report, void(^repor @implementation InstabugReactBridge - (NSArray *)supportedEvents { - return @[ - @"IBGpreSendingHandler", - @"IBGSetNetworkDataObfuscationHandler", - ]; + return @[@"IBGpreSendingHandler"]; } RCT_EXPORT_MODULE(Instabug) diff --git a/src/index.ts b/src/index.ts index dc26cb2dc..75d434101 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,7 +9,7 @@ import * as CrashReporting from './modules/CrashReporting'; import * as FeatureRequests from './modules/FeatureRequests'; import * as Instabug from './modules/Instabug'; import * as NetworkLogger from './modules/NetworkLogger'; -import type { NetworkData } from './modules/NetworkLogger'; +import type { NetworkData, NetworkDataObfuscationHandler } from './modules/NetworkLogger'; import * as Replies from './modules/Replies'; import type { Survey } from './modules/Surveys'; import * as Surveys from './modules/Surveys'; @@ -26,8 +26,6 @@ export { Replies, Surveys, }; -export type { InstabugConfig }; -export type { Survey }; -export type { NetworkData }; +export type { InstabugConfig, Survey, NetworkData, NetworkDataObfuscationHandler }; export default Instabug; diff --git a/src/models/Report.ts b/src/models/Report.ts index b61da4dc9..4af0a8458 100644 --- a/src/models/Report.ts +++ b/src/models/Report.ts @@ -1,6 +1,6 @@ import { Platform } from 'react-native'; -import { NativeInstabug } from '../native'; +import { NativeInstabug } from '../native/NativeInstabug'; interface LogInfo { log: string; diff --git a/src/models/Trace.ts b/src/models/Trace.ts index ab86ba05f..6baa5aec2 100644 --- a/src/models/Trace.ts +++ b/src/models/Trace.ts @@ -1,4 +1,4 @@ -import { NativeAPM } from '../native'; +import { NativeAPM } from '../native/NativeAPM'; export default class Trace { constructor( diff --git a/src/modules/APM.ts b/src/modules/APM.ts index a9df302f0..26170375a 100644 --- a/src/modules/APM.ts +++ b/src/modules/APM.ts @@ -1,7 +1,8 @@ import { Platform } from 'react-native'; import Trace from '../models/Trace'; -import { NativeAPM, NativeInstabug } from '../native'; +import { NativeAPM } from '../native/NativeAPM'; +import { NativeInstabug } from '../native/NativeInstabug'; import { logLevel } from '../utils/ArgsRegistry'; export { logLevel }; diff --git a/src/modules/BugReporting.ts b/src/modules/BugReporting.ts index 0efee28da..aabb75be3 100644 --- a/src/modules/BugReporting.ts +++ b/src/modules/BugReporting.ts @@ -1,6 +1,6 @@ import { Platform } from 'react-native'; -import { NativeBugReporting } from '../native'; +import { NativeBugReporting, NativeEvents, emitter } from '../native/NativeBugReporting'; import { dismissType, extendedBugReportMode, @@ -19,8 +19,6 @@ import type { RecordingButtonPosition, ReportType, } from '../utils/Enums'; -import IBGEventEmitter from '../utils/IBGEventEmitter'; -import InstabugConstants from '../utils/InstabugConstants'; export { invocationEvent, extendedBugReportMode, reportType, option, position }; @@ -57,11 +55,14 @@ export const setOptions = (options: option[] | InvocationOption[]) => { * @param handler A callback that gets executed before invoking the SDK */ export const onInvokeHandler = (handler: () => void) => { - IBGEventEmitter.addListener(NativeBugReporting, InstabugConstants.ON_INVOKE_HANDLER, handler); + emitter.addListener(NativeEvents.ON_INVOKE_HANDLER, handler); NativeBugReporting.setOnInvokeHandler(handler); }; /** + * @deprecated Use {@link onDismissHandler} instead as it has correct types + * for the `handler` parameters. + * * Sets a block of code to be executed right after the SDK's UI is dismissed. * This block is executed on the UI thread. Could be used for performing any * UI changes after the SDK's UI is dismissed. @@ -70,14 +71,42 @@ export const onInvokeHandler = (handler: () => void) => { export const onSDKDismissedHandler = ( handler: (dismissType: dismissType | DismissType, reportType: reportType | ReportType) => void, ) => { - IBGEventEmitter.addListener( - NativeBugReporting, - InstabugConstants.ON_SDK_DISMISSED_HANDLER, - (payload) => { + // Remapped to new API, while keeping the old incorrect behavior. + onDismissHandler((dismiss: dismissType, report: reportType) => { + const dismissTypes: Record = { + [dismissType.addAttachment]: 'ADD_ATTACHMENT', + [dismissType.submit]: 'SUBMIT', + [dismissType.cancel]: 'CANCEL', + }; + + const reportTypes: Record = { + [reportType.bug]: 'bug', + [reportType.feedback]: 'feedback', + [reportType.question]: 'question', + [reportType.other]: 'other', + }; + + handler(dismissTypes[dismiss] as any, reportTypes[report] as any); + }); +}; + +/** + * Sets a block of code to be executed right after the SDK's UI is dismissed. + * This block is executed on the UI thread. Could be used for performing any + * UI changes after the SDK's UI is dismissed. + * @param handler A callback to get executed after dismissing the SDK. + */ +export const onDismissHandler = ( + handler: (dismissType: dismissType | DismissType, reportType: reportType | ReportType) => void, +) => { + emitter.addListener( + NativeEvents.ON_DISMISS_HANDLER, + (payload: { dismissType: any; reportType: any }) => { handler(payload.dismissType, payload.reportType); }, ); - NativeBugReporting.setOnSDKDismissedHandler(handler); + + NativeBugReporting.setOnDismissHandler(handler); }; /** @@ -193,13 +222,9 @@ export const setDidSelectPromptOptionHandler = (handler: (promptOption: string) if (Platform.OS === 'android') { return; } - IBGEventEmitter.addListener( - NativeBugReporting, - InstabugConstants.DID_SELECT_PROMPT_OPTION_HANDLER, - (payload) => { - handler(payload.promptOption); - }, - ); + emitter.addListener(NativeEvents.DID_SELECT_PROMPT_OPTION_HANDLER, (payload) => { + handler(payload.promptOption); + }); NativeBugReporting.setDidSelectPromptOptionHandler(handler); }; diff --git a/src/modules/CrashReporting.ts b/src/modules/CrashReporting.ts index c9b827eea..5687b2f53 100644 --- a/src/modules/CrashReporting.ts +++ b/src/modules/CrashReporting.ts @@ -1,8 +1,8 @@ import { Platform } from 'react-native'; import type { ExtendedError } from 'react-native/Libraries/Core/Devtools/parseErrorStack'; -import { NativeCrashReporting } from '../native'; -import type { CrashData } from '../native/CrashReportingNativeModule'; +import type { CrashData } from '../native/NativeCrashReporting'; +import { NativeCrashReporting } from '../native/NativeCrashReporting'; import InstabugUtils from '../utils/InstabugUtils'; /** diff --git a/src/modules/FeatureRequests.ts b/src/modules/FeatureRequests.ts index 08453a7ee..aa5d2596d 100644 --- a/src/modules/FeatureRequests.ts +++ b/src/modules/FeatureRequests.ts @@ -1,4 +1,4 @@ -import { NativeFeatureRequests } from '../native'; +import { NativeFeatureRequests } from '../native/NativeFeatureRequests'; import { actionTypes } from '../utils/ArgsRegistry'; import type { ActionType } from '../utils/Enums'; diff --git a/src/modules/Instabug.ts b/src/modules/Instabug.ts index dd569ebb9..051d8263b 100644 --- a/src/modules/Instabug.ts +++ b/src/modules/Instabug.ts @@ -7,7 +7,7 @@ import type { NavigationAction, NavigationState as NavigationStateV4 } from 'rea import type { InstabugConfig } from '../models/InstabugConfig'; import Report from '../models/Report'; -import { NativeInstabug } from '../native'; +import { NativeEvents, NativeInstabug, emitter } from '../native/NativeInstabug'; import { IBGPosition, actionTypes, @@ -31,8 +31,6 @@ import { StringKey, WelcomeMessageMode, } from '../utils/Enums'; -import IBGEventEmitter from '../utils/IBGEventEmitter'; -import InstabugConstants from '../utils/InstabugConstants'; import InstabugUtils, { stringifyIfNotString } from '../utils/InstabugUtils'; import * as NetworkLogger from './NetworkLogger'; @@ -435,7 +433,7 @@ export const setDebugEnabled = (isEnabled: boolean) => { */ export const enable = () => { if (Platform.OS === 'android') { - NativeInstabug.enable(); + setEnabled(true); } }; @@ -447,7 +445,7 @@ export const enable = () => { */ export const disable = () => { if (Platform.OS === 'android') { - NativeInstabug.disable(); + setEnabled(false); } }; @@ -533,7 +531,7 @@ export const show = () => { }; export const onReportSubmitHandler = (handler?: (report: Report) => void) => { - IBGEventEmitter.addListener(NativeInstabug, InstabugConstants.PRESENDING_HANDLER, (report) => { + emitter.addListener(NativeEvents.PRESENDING_HANDLER, (report) => { const { tags, consoleLogs, instabugLogs, userAttributes, fileAttachments } = report; const reportObj = new Report(tags, consoleLogs, instabugLogs, userAttributes, fileAttachments); handler && handler(reportObj); diff --git a/src/modules/NetworkLogger.ts b/src/modules/NetworkLogger.ts index 3ec57c705..8e102e3ab 100644 --- a/src/modules/NetworkLogger.ts +++ b/src/modules/NetworkLogger.ts @@ -2,14 +2,15 @@ import { Platform } from 'react-native'; import type { RequestHandler } from '@apollo/client'; -import { NativeAPM, NativeInstabug } from '../native'; -import IBGEventEmitter from '../utils/IBGEventEmitter'; +import { NativeAPM } from '../native/NativeAPM'; +import { NativeInstabug } from '../native/NativeInstabug'; import InstabugConstants from '../utils/InstabugConstants'; import xhr, { NetworkData, ProgressCallback } from '../utils/XhrNetworkInterceptor'; export type { NetworkData }; -let _networkDataObfuscationHandlerSet = false; +export type NetworkDataObfuscationHandler = (data: NetworkData) => Promise; +let _networkDataObfuscationHandler: NetworkDataObfuscationHandler | null | undefined; let _requestFilterExpression = 'false'; /** @@ -20,23 +21,23 @@ let _requestFilterExpression = 'false'; export const setEnabled = (isEnabled: boolean) => { if (isEnabled) { xhr.enableInterception(); - xhr.setOnDoneCallback((network) => { + xhr.setOnDoneCallback(async (network) => { // eslint-disable-next-line no-new-func const predicate = Function('network', 'return ' + _requestFilterExpression); if (!predicate(network)) { - if (_networkDataObfuscationHandlerSet) { - IBGEventEmitter.emit(InstabugConstants.NETWORK_DATA_OBFUSCATION_HANDLER_EVENT, network); - } else { - try { - if (Platform.OS === 'android') { - NativeInstabug.networkLog(JSON.stringify(network)); - NativeAPM.networkLog(JSON.stringify(network)); - } else { - NativeInstabug.networkLog(network); - } - } catch (e) { - console.error(e); + try { + if (_networkDataObfuscationHandler) { + network = await _networkDataObfuscationHandler(network); } + + if (Platform.OS === 'android') { + NativeInstabug.networkLog(JSON.stringify(network)); + NativeAPM.networkLog(JSON.stringify(network)); + } else { + NativeInstabug.networkLog(network); + } + } catch (e) { + console.error(e); } } }); @@ -50,32 +51,9 @@ export const setEnabled = (isEnabled: boolean) => { * @param handler */ export const setNetworkDataObfuscationHandler = ( - handler: (data: NetworkData) => Promise, + handler?: NetworkDataObfuscationHandler | null | undefined, ) => { - if (handler === null) { - _networkDataObfuscationHandlerSet = false; - return; - } - _networkDataObfuscationHandlerSet = true; - - IBGEventEmitter.addListener( - NativeInstabug, - InstabugConstants.NETWORK_DATA_OBFUSCATION_HANDLER_EVENT, - async (data: NetworkData) => { - try { - const newData = await handler(data); - - if (Platform.OS === 'android') { - NativeInstabug.networkLog(JSON.stringify(newData)); - NativeAPM.networkLog(JSON.stringify(newData)); - } else { - NativeInstabug.networkLog(newData); - } - } catch (e) { - console.error(e); - } - }, - ); + _networkDataObfuscationHandler = handler; }; /** diff --git a/src/modules/Replies.ts b/src/modules/Replies.ts index 5d2317a60..26d253d50 100644 --- a/src/modules/Replies.ts +++ b/src/modules/Replies.ts @@ -1,8 +1,6 @@ import { Platform } from 'react-native'; -import { NativeReplies } from '../native'; -import IBGEventEmitter from '../utils/IBGEventEmitter'; -import InstabugConstants from '../utils/InstabugConstants'; +import { NativeEvents, NativeReplies, emitter } from '../native/NativeReplies'; /** * Enables and disables everything related to receiving replies. @@ -32,7 +30,7 @@ export const show = () => { * @param handler A callback that gets executed when a new message is received. */ export const setOnNewReplyReceivedHandler = (handler: () => void) => { - IBGEventEmitter.addListener(NativeReplies, InstabugConstants.ON_REPLY_RECEIVED_HANDLER, handler); + emitter.addListener(NativeEvents.ON_REPLY_RECEIVED_HANDLER, handler); NativeReplies.setOnNewReplyReceivedHandler(handler); }; diff --git a/src/modules/Surveys.ts b/src/modules/Surveys.ts index b66fdbff0..790cf4fb0 100644 --- a/src/modules/Surveys.ts +++ b/src/modules/Surveys.ts @@ -1,9 +1,7 @@ import { Platform } from 'react-native'; -import { NativeSurveys } from '../native'; -import type { Survey } from '../native/SurveysNativeModule'; -import IBGEventEmitter from '../utils/IBGEventEmitter'; -import InstabugConstants from '../utils/InstabugConstants'; +import { NativeEvents, NativeSurveys, emitter } from '../native/NativeSurveys'; +import type { Survey } from '../native/NativeSurveys'; export type { Survey }; @@ -55,11 +53,7 @@ export const setAutoShowingEnabled = (autoShowingSurveysEnabled: boolean) => { * presenting the survey's UI. */ export const setOnShowHandler = (onShowHandler: () => void) => { - IBGEventEmitter.addListener( - NativeSurveys, - InstabugConstants.WILL_SHOW_SURVEY_HANDLER, - onShowHandler, - ); + emitter.addListener(NativeEvents.WILL_SHOW_SURVEY_HANDLER, onShowHandler); NativeSurveys.setOnShowHandler(onShowHandler); }; @@ -71,11 +65,7 @@ export const setOnShowHandler = (onShowHandler: () => void) => { * the survey's UI is dismissed. */ export const setOnDismissHandler = (onDismissHandler: () => void) => { - IBGEventEmitter.addListener( - NativeSurveys, - InstabugConstants.DID_DISMISS_SURVEY_HANDLER, - onDismissHandler, - ); + emitter.addListener(NativeEvents.DID_DISMISS_SURVEY_HANDLER, onDismissHandler); NativeSurveys.setOnDismissHandler(onDismissHandler); }; diff --git a/src/native/ApmNativeModule.ts b/src/native/NativeAPM.ts similarity index 89% rename from src/native/ApmNativeModule.ts rename to src/native/NativeAPM.ts index f398509ea..30067b779 100644 --- a/src/native/ApmNativeModule.ts +++ b/src/native/NativeAPM.ts @@ -1,6 +1,7 @@ import type { NativeModule } from 'react-native'; import type { logLevel } from '../utils/ArgsRegistry'; +import { NativeModules } from './NativePackage'; export interface ApmNativeModule extends NativeModule { // Essential APIs // @@ -28,3 +29,5 @@ export interface ApmNativeModule extends NativeModule { /** @deprecated */ setLogLevel(level: logLevel): void; } + +export const NativeAPM = NativeModules.IBGAPM; diff --git a/src/native/BugReportingNativeModule.ts b/src/native/NativeBugReporting.ts similarity index 81% rename from src/native/BugReportingNativeModule.ts rename to src/native/NativeBugReporting.ts index cc4dbe59d..0fb501b99 100644 --- a/src/native/BugReportingNativeModule.ts +++ b/src/native/NativeBugReporting.ts @@ -1,4 +1,4 @@ -import type { NativeModule } from 'react-native'; +import { NativeEventEmitter, NativeModule } from 'react-native'; import type { dismissType, @@ -18,6 +18,7 @@ import type { RecordingButtonPosition, ReportType, } from '../utils/Enums'; +import { NativeModules } from './NativePackage'; export interface BugReportingNativeModule extends NativeModule { // Essential APIs // @@ -53,7 +54,17 @@ export interface BugReportingNativeModule extends NativeModule { // Callbacks // setOnInvokeHandler(handler: () => void): void; setDidSelectPromptOptionHandler(handler: (promptOption: string) => void): void; - setOnSDKDismissedHandler( + setOnDismissHandler( handler: (dismissType: dismissType | DismissType, reportType: reportType | ReportType) => void, ): void; } + +export const NativeBugReporting = NativeModules.IBGBugReporting; + +export enum NativeEvents { + ON_INVOKE_HANDLER = 'IBGpreInvocationHandler', + ON_DISMISS_HANDLER = 'IBGpostInvocationHandler', + DID_SELECT_PROMPT_OPTION_HANDLER = 'IBGDidSelectPromptOptionHandler', +} + +export const emitter = new NativeEventEmitter(NativeBugReporting); diff --git a/src/native/NativeConstants.ts b/src/native/NativeConstants.ts index 2d754bdbf..89905331a 100644 --- a/src/native/NativeConstants.ts +++ b/src/native/NativeConstants.ts @@ -76,6 +76,7 @@ interface NativeReportType { bugReportingReportTypeBug: any; bugReportingReportTypeFeedback: any; bugReportingReportTypeQuestion: any; + bugReportingReportTypeOther: any; } interface NativeDismissType { diff --git a/src/native/CrashReportingNativeModule.ts b/src/native/NativeCrashReporting.ts similarity index 81% rename from src/native/CrashReportingNativeModule.ts rename to src/native/NativeCrashReporting.ts index 8124c2a0f..b10d9674b 100644 --- a/src/native/CrashReportingNativeModule.ts +++ b/src/native/NativeCrashReporting.ts @@ -1,6 +1,8 @@ import type { NativeModule, Platform } from 'react-native'; import type { StackFrame } from 'react-native/Libraries/Core/Devtools/parseErrorStack'; +import { NativeModules } from './NativePackage'; + export interface CrashData { message: string; e_message: string; @@ -15,3 +17,5 @@ export interface CrashReportingNativeModule extends NativeModule { sendJSCrash(data: CrashData | string): void; sendHandledJSCrash(data: CrashData | string): void; } + +export const NativeCrashReporting = NativeModules.IBGCrashReporting; diff --git a/src/native/FeatureRequestsNativeModule.ts b/src/native/NativeFeatureRequests.ts similarity index 77% rename from src/native/FeatureRequestsNativeModule.ts rename to src/native/NativeFeatureRequests.ts index 6fc8d6529..dc74690d6 100644 --- a/src/native/FeatureRequestsNativeModule.ts +++ b/src/native/NativeFeatureRequests.ts @@ -2,6 +2,7 @@ import type { NativeModule } from 'react-native'; import type { actionTypes } from '../utils/ArgsRegistry'; import type { ActionType } from '../utils/Enums'; +import { NativeModules } from './NativePackage'; export interface FeatureRequestsNativeModule extends NativeModule { setEnabled(isEnabled: boolean): void; @@ -11,3 +12,5 @@ export interface FeatureRequestsNativeModule extends NativeModule { types: actionTypes[] | ActionType[], ): void; } + +export const NativeFeatureRequests = NativeModules.IBGFeatureRequests; diff --git a/src/native/InstabugNativeModule.ts b/src/native/NativeInstabug.ts similarity index 91% rename from src/native/InstabugNativeModule.ts rename to src/native/NativeInstabug.ts index ab37e9c6b..a7bca6cef 100644 --- a/src/native/InstabugNativeModule.ts +++ b/src/native/NativeInstabug.ts @@ -1,4 +1,4 @@ -import type { NativeModule, ProcessedColorValue } from 'react-native'; +import { NativeEventEmitter, NativeModule, ProcessedColorValue } from 'react-native'; import type Report from '../models/Report'; import type { @@ -21,6 +21,7 @@ import type { } from '../utils/Enums'; import type { NetworkData } from '../utils/XhrNetworkInterceptor'; import type { NativeConstants } from './NativeConstants'; +import { NativeModules } from './NativePackage'; export interface InstabugNativeModule extends NativeModule { getConstants(): NativeConstants; @@ -112,11 +113,15 @@ export interface InstabugNativeModule extends NativeModule { /** @deprecated */ setDebugEnabled(isEnabled: boolean): void; /** @deprecated */ - enable(): void; - /** @deprecated */ - disable(): void; - /** @deprecated */ isRunningLive(callback: (isLive: boolean) => void): void; /** @deprecated */ callPrivateApi(apiName: string, param: any[]): void; } + +export const NativeInstabug = NativeModules.Instabug; + +export enum NativeEvents { + PRESENDING_HANDLER = 'IBGpreSendingHandler', +} + +export const emitter = new NativeEventEmitter(NativeInstabug); diff --git a/src/native/NativePackage.ts b/src/native/NativePackage.ts new file mode 100644 index 000000000..2f74572f0 --- /dev/null +++ b/src/native/NativePackage.ts @@ -0,0 +1,21 @@ +import { NativeModules as ReactNativeModules } from 'react-native'; + +import type { ApmNativeModule } from './NativeAPM'; +import type { BugReportingNativeModule } from './NativeBugReporting'; +import type { CrashReportingNativeModule } from './NativeCrashReporting'; +import type { FeatureRequestsNativeModule } from './NativeFeatureRequests'; +import type { InstabugNativeModule } from './NativeInstabug'; +import type { RepliesNativeModule } from './NativeReplies'; +import type { SurveysNativeModule } from './NativeSurveys'; + +export interface InstabugNativePackage { + IBGAPM: ApmNativeModule; + IBGBugReporting: BugReportingNativeModule; + IBGCrashReporting: CrashReportingNativeModule; + IBGFeatureRequests: FeatureRequestsNativeModule; + Instabug: InstabugNativeModule; + IBGReplies: RepliesNativeModule; + IBGSurveys: SurveysNativeModule; +} + +export const NativeModules = ReactNativeModules as InstabugNativePackage; diff --git a/src/native/RepliesNativeModule.ts b/src/native/NativeReplies.ts similarity index 72% rename from src/native/RepliesNativeModule.ts rename to src/native/NativeReplies.ts index b3db292da..e7624d5dc 100644 --- a/src/native/RepliesNativeModule.ts +++ b/src/native/NativeReplies.ts @@ -1,4 +1,6 @@ -import type { NativeModule } from 'react-native'; +import { NativeEventEmitter, NativeModule } from 'react-native'; + +import { NativeModules } from './NativePackage'; export interface RepliesNativeModule extends NativeModule { // Essential APIs // @@ -22,3 +24,11 @@ export interface RepliesNativeModule extends NativeModule { setPushNotificationChannelId(id: string): void; setSystemReplyNotificationSoundEnabled(isEnabled: boolean): void; } + +export const NativeReplies = NativeModules.IBGReplies; + +export enum NativeEvents { + ON_REPLY_RECEIVED_HANDLER = 'IBGOnNewReplyReceivedCallback', +} + +export const emitter = new NativeEventEmitter(NativeReplies); diff --git a/src/native/SurveysNativeModule.ts b/src/native/NativeSurveys.ts similarity index 67% rename from src/native/SurveysNativeModule.ts rename to src/native/NativeSurveys.ts index 575a26d3e..9c1233c27 100644 --- a/src/native/SurveysNativeModule.ts +++ b/src/native/NativeSurveys.ts @@ -1,4 +1,6 @@ -import type { NativeModule } from 'react-native'; +import { NativeEventEmitter, NativeModule } from 'react-native'; + +import { NativeModules } from './NativePackage'; export interface Survey { title: string; @@ -24,3 +26,12 @@ export interface SurveysNativeModule extends NativeModule { setOnShowHandler(onShowHandler: () => void): void; setOnDismissHandler(onDismissHandler: () => void): void; } + +export const NativeSurveys = NativeModules.IBGSurveys; + +export enum NativeEvents { + WILL_SHOW_SURVEY_HANDLER = 'IBGWillShowSurvey', + DID_DISMISS_SURVEY_HANDLER = 'IBGDidDismissSurvey', +} + +export const emitter = new NativeEventEmitter(NativeSurveys); diff --git a/src/native/index.ts b/src/native/index.ts deleted file mode 100644 index ba8940177..000000000 --- a/src/native/index.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { NativeModules as ReactNativeModules } from 'react-native'; - -import type { ApmNativeModule } from './ApmNativeModule'; -import type { BugReportingNativeModule } from './BugReportingNativeModule'; -import type { CrashReportingNativeModule } from './CrashReportingNativeModule'; -import type { FeatureRequestsNativeModule } from './FeatureRequestsNativeModule'; -import type { InstabugNativeModule } from './InstabugNativeModule'; -import type { RepliesNativeModule } from './RepliesNativeModule'; -import type { SurveysNativeModule } from './SurveysNativeModule'; - -export interface InstabugNativePackage { - IBGAPM: ApmNativeModule; - IBGBugReporting: BugReportingNativeModule; - IBGCrashReporting: CrashReportingNativeModule; - IBGFeatureRequests: FeatureRequestsNativeModule; - Instabug: InstabugNativeModule; - IBGReplies: RepliesNativeModule; - IBGSurveys: SurveysNativeModule; -} - -export const NativeModules = ReactNativeModules as InstabugNativePackage; - -export const NativeAPM = NativeModules.IBGAPM; -export const NativeBugReporting = NativeModules.IBGBugReporting; -export const NativeCrashReporting = NativeModules.IBGCrashReporting; -export const NativeFeatureRequests = NativeModules.IBGFeatureRequests; -export const NativeInstabug = NativeModules.Instabug; -export const NativeReplies = NativeModules.IBGReplies; -export const NativeSurveys = NativeModules.IBGSurveys; diff --git a/src/utils/ArgsRegistry.ts b/src/utils/ArgsRegistry.ts index 028d57039..810b87a67 100644 --- a/src/utils/ArgsRegistry.ts +++ b/src/utils/ArgsRegistry.ts @@ -1,4 +1,4 @@ -import { NativeInstabug } from '../native'; +import { NativeInstabug } from '../native/NativeInstabug'; const constants = NativeInstabug.getConstants(); @@ -118,6 +118,7 @@ export enum reportType { bug = constants.bugReportingReportTypeBug, feedback = constants.bugReportingReportTypeFeedback, question = constants.bugReportingReportTypeQuestion, + other = constants.bugReportingReportTypeOther, } /** diff --git a/src/utils/Enums.ts b/src/utils/Enums.ts index e5f3fcaae..890956b8c 100644 --- a/src/utils/Enums.ts +++ b/src/utils/Enums.ts @@ -1,4 +1,4 @@ -import { NativeInstabug } from '../native'; +import { NativeInstabug } from '../native/NativeInstabug'; const constants = NativeInstabug.getConstants(); @@ -76,6 +76,7 @@ export enum ReportType { bug = constants.bugReportingReportTypeBug, feedback = constants.bugReportingReportTypeFeedback, question = constants.bugReportingReportTypeQuestion, + other = constants.bugReportingReportTypeOther, } /** diff --git a/src/utils/IBGEventEmitter.ts b/src/utils/IBGEventEmitter.ts deleted file mode 100644 index 556f9ccaf..000000000 --- a/src/utils/IBGEventEmitter.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { DeviceEventEmitter, NativeAppEventEmitter, NativeModule, Platform } from 'react-native'; - -export default { - addListener: (nativeModule: NativeModule, eventName: string, callback: (data: any) => void) => { - if (Platform.OS === 'ios') { - nativeModule.addListener(eventName); - NativeAppEventEmitter.addListener(eventName, callback); - } else { - DeviceEventEmitter.addListener(eventName, callback); - } - }, - emit: (eventName: string, ...eventParams: any[]) => { - if (Platform.OS === 'ios') { - NativeAppEventEmitter.emit(eventName, ...eventParams); - } else { - DeviceEventEmitter.emit(eventName, ...eventParams); - } - }, - removeAllListeners: () => { - if (Platform.OS === 'ios') { - NativeAppEventEmitter.removeAllListeners(); - } else { - DeviceEventEmitter.removeAllListeners(); - } - }, - getListeners: (eventName: string) => { - // Dirty trick to get tests passing before the events migration - if (Platform.OS === 'ios') { - return { length: NativeAppEventEmitter.listenerCount(eventName) }; - } else { - return { length: DeviceEventEmitter.listenerCount(eventName) }; - } - }, -}; diff --git a/src/utils/InstabugConstants.ts b/src/utils/InstabugConstants.ts index cd42e77c5..c7b498877 100644 --- a/src/utils/InstabugConstants.ts +++ b/src/utils/InstabugConstants.ts @@ -1,12 +1,4 @@ enum InstabugConstants { - NETWORK_DATA_OBFUSCATION_HANDLER_EVENT = 'IBGSetNetworkDataObfuscationHandler', - PRESENDING_HANDLER = 'IBGpreSendingHandler', - ON_INVOKE_HANDLER = 'IBGpreInvocationHandler', - ON_SDK_DISMISSED_HANDLER = 'IBGpostInvocationHandler', - ON_REPLY_RECEIVED_HANDLER = 'IBGOnNewReplyReceivedCallback', - WILL_SHOW_SURVEY_HANDLER = 'IBGWillShowSurvey', - DID_DISMISS_SURVEY_HANDLER = 'IBGDidDismissSurvey', - DID_SELECT_PROMPT_OPTION_HANDLER = 'IBGDidSelectPromptOptionHandler', GRAPHQL_HEADER = 'ibg-graphql-header', } diff --git a/src/utils/InstabugUtils.ts b/src/utils/InstabugUtils.ts index f107eb137..d88bce470 100644 --- a/src/utils/InstabugUtils.ts +++ b/src/utils/InstabugUtils.ts @@ -7,8 +7,8 @@ import parseErrorStackLib, { import type { NavigationState as NavigationStateV5, PartialState } from '@react-navigation/native'; import type { NavigationState as NavigationStateV4 } from 'react-navigation'; -import { NativeCrashReporting } from '../native'; -import type { CrashData } from '../native/CrashReportingNativeModule'; +import type { CrashData } from '../native/NativeCrashReporting'; +import { NativeCrashReporting } from '../native/NativeCrashReporting'; export const parseErrorStack = (error: ExtendedError): StackFrame[] => { return parseErrorStackLib(error); diff --git a/test/mocks/mockAPM.ts b/test/mocks/mockAPM.ts index 8b8c4c681..c0465c7bb 100644 --- a/test/mocks/mockAPM.ts +++ b/test/mocks/mockAPM.ts @@ -1,4 +1,4 @@ -import type { ApmNativeModule } from '../../src/native/ApmNativeModule'; +import type { ApmNativeModule } from '../../src/native/NativeAPM'; const mockAPM: ApmNativeModule = { addListener: jest.fn(), diff --git a/test/mocks/mockBugReporting.ts b/test/mocks/mockBugReporting.ts index fa0f07d19..49c0f3467 100644 --- a/test/mocks/mockBugReporting.ts +++ b/test/mocks/mockBugReporting.ts @@ -1,4 +1,4 @@ -import type { BugReportingNativeModule } from '../../src/native/BugReportingNativeModule'; +import type { BugReportingNativeModule } from '../../src/native/NativeBugReporting'; const mockBugReporting: BugReportingNativeModule = { addListener: jest.fn(), @@ -14,7 +14,7 @@ const mockBugReporting: BugReportingNativeModule = { setReportTypes: jest.fn(), show: jest.fn(), setOnInvokeHandler: jest.fn(), - setOnSDKDismissedHandler: jest.fn(), + setOnDismissHandler: jest.fn(), setAutoScreenRecordingEnabled: jest.fn(), setAutoScreenRecordingDuration: jest.fn(), setViewHierarchyEnabled: jest.fn(), diff --git a/test/mocks/mockCrashReporting.ts b/test/mocks/mockCrashReporting.ts index 43daecca0..0d2685156 100644 --- a/test/mocks/mockCrashReporting.ts +++ b/test/mocks/mockCrashReporting.ts @@ -1,4 +1,4 @@ -import type { CrashReportingNativeModule } from '../../src/native/CrashReportingNativeModule'; +import type { CrashReportingNativeModule } from '../../src/native/NativeCrashReporting'; const mockCrashReporting: CrashReportingNativeModule = { addListener: jest.fn(), diff --git a/test/mocks/mockFeatureRequests.ts b/test/mocks/mockFeatureRequests.ts index 9ed48c02b..1e1023e46 100644 --- a/test/mocks/mockFeatureRequests.ts +++ b/test/mocks/mockFeatureRequests.ts @@ -1,4 +1,4 @@ -import type { FeatureRequestsNativeModule } from '../../src/native/FeatureRequestsNativeModule'; +import type { FeatureRequestsNativeModule } from '../../src/native/NativeFeatureRequests'; const mockFeatureRequests: FeatureRequestsNativeModule = { addListener: jest.fn(), diff --git a/test/mocks/mockInstabug.ts b/test/mocks/mockInstabug.ts index f8bf85ff1..bfd049019 100644 --- a/test/mocks/mockInstabug.ts +++ b/test/mocks/mockInstabug.ts @@ -1,4 +1,4 @@ -import type { InstabugNativeModule } from '../../src/native/InstabugNativeModule'; +import type { InstabugNativeModule } from '../../src/native/NativeInstabug'; const mockInstabug: InstabugNativeModule = { addListener: jest.fn(), @@ -34,8 +34,6 @@ const mockInstabug: InstabugNativeModule = { getAllUserAttributes: jest.fn((cb) => cb({ age: '24' })), clearAllUserAttributes: jest.fn(), setDebugEnabled: jest.fn(), - enable: jest.fn(), - disable: jest.fn(), isRunningLive: jest.fn((cb) => cb(true)), showWelcomeMessageWithMode: jest.fn(), setWelcomeMessageMode: jest.fn(), diff --git a/test/mocks/mockNativeModules.ts b/test/mocks/mockNativeModules.ts index 9112004f1..b53fa2351 100644 --- a/test/mocks/mockNativeModules.ts +++ b/test/mocks/mockNativeModules.ts @@ -1,4 +1,4 @@ -import type { InstabugNativePackage } from '../../src/native'; +import type { InstabugNativePackage } from '../../src/native/NativePackage'; import mockAPM from './mockAPM'; import mockBugReporting from './mockBugReporting'; import mockCrashReporting from './mockCrashReporting'; diff --git a/test/mocks/mockReplies.ts b/test/mocks/mockReplies.ts index c2c86b731..3247155cb 100644 --- a/test/mocks/mockReplies.ts +++ b/test/mocks/mockReplies.ts @@ -1,4 +1,4 @@ -import type { RepliesNativeModule } from '../../src/native/RepliesNativeModule'; +import type { RepliesNativeModule } from '../../src/native/NativeReplies'; const mockReplies: RepliesNativeModule = { addListener: jest.fn(), diff --git a/test/mocks/mockSurveys.ts b/test/mocks/mockSurveys.ts index d94af4f51..4f886536e 100644 --- a/test/mocks/mockSurveys.ts +++ b/test/mocks/mockSurveys.ts @@ -1,4 +1,4 @@ -import type { SurveysNativeModule } from '../../src/native/SurveysNativeModule'; +import type { SurveysNativeModule } from '../../src/native/NativeSurveys'; const mockSurveys: SurveysNativeModule = { addListener: jest.fn(), diff --git a/test/models/Report.spec.ts b/test/models/Report.spec.ts index c75d46e8a..20c6c8952 100644 --- a/test/models/Report.spec.ts +++ b/test/models/Report.spec.ts @@ -1,7 +1,7 @@ import { Platform } from 'react-native'; import Report from '../../src/models/Report'; -import { NativeInstabug } from '../../src/native'; +import { NativeInstabug } from '../../src/native/NativeInstabug'; describe('Report Model', () => { let report: Report; diff --git a/test/models/Trace.spec.ts b/test/models/Trace.spec.ts index a37d72216..8421b419a 100644 --- a/test/models/Trace.spec.ts +++ b/test/models/Trace.spec.ts @@ -1,5 +1,5 @@ import Trace from '../../src/models/Trace'; -import { NativeAPM } from '../../src/native'; +import { NativeAPM } from '../../src/native/NativeAPM'; describe('Trace Model', () => { it('should set the id, name and attributes if passed', () => { diff --git a/test/modules/APM.spec.ts b/test/modules/APM.spec.ts index b8dcfd29d..fdf90a967 100644 --- a/test/modules/APM.spec.ts +++ b/test/modules/APM.spec.ts @@ -4,7 +4,8 @@ import { mocked } from 'ts-jest/utils'; import Trace from '../../src/models/Trace'; import * as APM from '../../src/modules/APM'; -import { NativeAPM, NativeInstabug } from '../../src/native'; +import { NativeAPM } from '../../src/native/NativeAPM'; +import { NativeInstabug } from '../../src/native/NativeInstabug'; describe('APM Module', () => { it('should call the native method setEnabled', () => { diff --git a/test/modules/BugReporting.spec.ts b/test/modules/BugReporting.spec.ts index 93003fee8..654d5e596 100644 --- a/test/modules/BugReporting.spec.ts +++ b/test/modules/BugReporting.spec.ts @@ -1,7 +1,7 @@ import { Platform } from 'react-native'; import * as BugReporting from '../../src/modules/BugReporting'; -import { NativeBugReporting } from '../../src/native'; +import { NativeBugReporting, NativeEvents, emitter } from '../../src/native/NativeBugReporting'; import { ExtendedBugReportMode, FloatingButtonPosition, @@ -10,10 +10,15 @@ import { RecordingButtonPosition, ReportType, } from '../../src/utils/Enums'; -import IBGEventEmitter from '../../src/utils/IBGEventEmitter'; -import IBGConstants from '../../src/utils/InstabugConstants'; describe('Testing BugReporting Module', () => { + beforeEach(() => { + const events = Object.values(NativeEvents); + events.forEach((event) => { + emitter.removeAllListeners(event); + }); + }); + it('should call the native method setBugReportingEnabled', () => { BugReporting.setEnabled(true); @@ -131,32 +136,32 @@ describe('Testing BugReporting Module', () => { it('should invoke callback on emitting the event IBGpreInvocationHandler', () => { const callback = jest.fn(); BugReporting.onInvokeHandler(callback); - IBGEventEmitter.emit(IBGConstants.ON_INVOKE_HANDLER); + emitter.emit(NativeEvents.ON_INVOKE_HANDLER); - expect(IBGEventEmitter.getListeners(IBGConstants.ON_INVOKE_HANDLER).length).toEqual(1); + expect(emitter.listenerCount(NativeEvents.ON_INVOKE_HANDLER)).toBe(1); expect(callback).toHaveBeenCalled(); }); - it('should call the native method setOnSDKDismissedHandler with a function', () => { + it('should call the native method setOnDismissHandler with a function', () => { const callback = jest.fn(); - BugReporting.onSDKDismissedHandler(callback); + BugReporting.onDismissHandler(callback); - expect(NativeBugReporting.setOnSDKDismissedHandler).toBeCalledTimes(1); - expect(NativeBugReporting.setOnSDKDismissedHandler).toBeCalledWith(callback); + expect(NativeBugReporting.setOnDismissHandler).toBeCalledTimes(1); + expect(NativeBugReporting.setOnDismissHandler).toBeCalledWith(callback); }); it('should invoke callback on emitting the event IBGpostInvocationHandler', () => { - const dismissType = 'cancel'; - const reportType = 'bug'; + const dismissType = Instabug.dismissType.cancel; + const reportType = BugReporting.reportType.bug; const callback = jest.fn(); - BugReporting.onSDKDismissedHandler(callback); - IBGEventEmitter.emit(IBGConstants.ON_SDK_DISMISSED_HANDLER, { + BugReporting.onDismissHandler(callback); + emitter.emit(NativeEvents.ON_DISMISS_HANDLER, { dismissType: dismissType, reportType: reportType, }); - expect(IBGEventEmitter.getListeners(IBGConstants.ON_SDK_DISMISSED_HANDLER).length).toEqual(1); + expect(emitter.listenerCount(NativeEvents.ON_DISMISS_HANDLER)).toBe(1); expect(callback).toBeCalledTimes(1); expect(callback).toBeCalledWith(dismissType, reportType); }); @@ -192,12 +197,10 @@ describe('Testing BugReporting Module', () => { Platform.OS = 'android'; BugReporting.setDidSelectPromptOptionHandler(jest.fn()); - IBGEventEmitter.emit(IBGConstants.DID_SELECT_PROMPT_OPTION_HANDLER, {}); + emitter.emit(NativeEvents.DID_SELECT_PROMPT_OPTION_HANDLER, {}); expect(NativeBugReporting.setDidSelectPromptOptionHandler).not.toBeCalled(); - expect( - IBGEventEmitter.getListeners(IBGConstants.DID_SELECT_PROMPT_OPTION_HANDLER).length, - ).toEqual(0); + expect(emitter.listenerCount(NativeEvents.DID_SELECT_PROMPT_OPTION_HANDLER)).toBe(0); }); it('should call setDidSelectPromptOptionHandler event listener when platform is iOS', () => { @@ -206,10 +209,9 @@ describe('Testing BugReporting Module', () => { const payload = { promptOption: 'bug' }; BugReporting.setDidSelectPromptOptionHandler(callback); - IBGEventEmitter.emit(IBGConstants.DID_SELECT_PROMPT_OPTION_HANDLER, payload); + emitter.emit(NativeEvents.DID_SELECT_PROMPT_OPTION_HANDLER, payload); - const listeners = IBGEventEmitter.getListeners(IBGConstants.DID_SELECT_PROMPT_OPTION_HANDLER); - expect(listeners.length).toBe(1); + expect(emitter.listenerCount(NativeEvents.DID_SELECT_PROMPT_OPTION_HANDLER)).toBe(1); expect(callback).toBeCalledTimes(1); expect(callback).toBeCalledWith(payload.promptOption); }); diff --git a/test/modules/CrashReporting.spec.ts b/test/modules/CrashReporting.spec.ts index f998a3930..62f4ed3c9 100644 --- a/test/modules/CrashReporting.spec.ts +++ b/test/modules/CrashReporting.spec.ts @@ -3,7 +3,7 @@ import '../mocks/mockInstabugUtils'; import { Platform } from 'react-native'; import * as CrashReporting from '../../src/modules/CrashReporting'; -import { NativeCrashReporting } from '../../src/native'; +import { NativeCrashReporting } from '../../src/native/NativeCrashReporting'; describe('CrashReporting Module', () => { it('should call the native method setEnabled', () => { diff --git a/test/modules/FeatureRequests.spec.ts b/test/modules/FeatureRequests.spec.ts index b19aeeb49..6f7c02860 100644 --- a/test/modules/FeatureRequests.spec.ts +++ b/test/modules/FeatureRequests.spec.ts @@ -1,5 +1,5 @@ import * as FeatureRequests from '../../src/modules/FeatureRequests'; -import { NativeFeatureRequests } from '../../src/native'; +import { NativeFeatureRequests } from '../../src/native/NativeFeatureRequests'; import { ActionType } from '../../src/utils/Enums'; describe('Feature Requests Module', () => { diff --git a/test/modules/Instabug.spec.ts b/test/modules/Instabug.spec.ts index b208caf1b..f4c5fb1c6 100644 --- a/test/modules/Instabug.spec.ts +++ b/test/modules/Instabug.spec.ts @@ -6,7 +6,7 @@ import waitForExpect from 'wait-for-expect'; import Report from '../../src/models/Report'; import * as Instabug from '../../src/modules/Instabug'; -import { NativeInstabug } from '../../src/native'; +import { NativeEvents, NativeInstabug, emitter } from '../../src/native/NativeInstabug'; import { ColorTheme, InvocationEvent, @@ -16,11 +16,16 @@ import { StringKey, WelcomeMessageMode, } from '../../src/utils/Enums'; -import IBGEventEmitter from '../../src/utils/IBGEventEmitter'; -import IBGConstants from '../../src/utils/InstabugConstants'; import InstabugUtils from '../../src/utils/InstabugUtils'; describe('Instabug Module', () => { + beforeEach(() => { + const events = Object.values(NativeEvents); + events.forEach((event) => { + emitter.removeAllListeners(event); + }); + }); + it('should call the native method setEnabled', () => { Instabug.setEnabled(true); @@ -498,32 +503,46 @@ describe('Instabug Module', () => { expect(NativeInstabug.setDebugEnabled).not.toBeCalled(); }); - it('should call the native method enable', () => { + it('should map deprecated enable to setEnabled on android', () => { + const setEnabled = jest.spyOn(Instabug, 'setEnabled'); Platform.OS = 'android'; Instabug.enable(); - expect(NativeInstabug.enable).toBeCalledTimes(1); + expect(setEnabled).toBeCalledTimes(1); + expect(setEnabled).toBeCalledWith(true); + + setEnabled.mockRestore(); }); - it('should not call the native method enable when platform is ios', () => { + it('should not map deprecated enable to setEnabled on ios', () => { + const setEnabled = jest.spyOn(Instabug, 'setEnabled'); Platform.OS = 'ios'; Instabug.enable(); - expect(NativeInstabug.enable).not.toBeCalled(); + expect(setEnabled).not.toBeCalled(); + + setEnabled.mockRestore(); }); - it('should call the native method disable', () => { + it('should map deprecated disable to setEnabled on android', () => { + const setEnabled = jest.spyOn(Instabug, 'setEnabled'); Platform.OS = 'android'; Instabug.disable(); - expect(NativeInstabug.disable).toBeCalledTimes(1); + expect(setEnabled).toBeCalledTimes(1); + expect(setEnabled).toBeCalledWith(false); + + setEnabled.mockRestore(); }); - it('should not call the native method disable when platform is ios', () => { + it('should not map deprecated disable to setEnabled on ios', () => { + const setEnabled = jest.spyOn(Instabug, 'setEnabled'); Platform.OS = 'ios'; Instabug.disable(); - expect(NativeInstabug.disable).not.toBeCalled(); + expect(setEnabled).not.toBeCalled(); + + setEnabled.mockRestore(); }); it('should call the native method isRunningLive', (done) => { @@ -636,9 +655,9 @@ describe('Instabug Module', () => { done(); }; Instabug.onReportSubmitHandler(callback); - IBGEventEmitter.emit(IBGConstants.PRESENDING_HANDLER, report); + emitter.emit(NativeEvents.PRESENDING_HANDLER, report); - expect(IBGEventEmitter.getListeners(IBGConstants.PRESENDING_HANDLER).length).toEqual(1); + expect(emitter.listenerCount(NativeEvents.PRESENDING_HANDLER)).toBe(1); }); it('should invoke the native method callPrivateApi', () => { diff --git a/test/modules/NetworkLogger.spec.ts b/test/modules/NetworkLogger.spec.ts index 758d4466b..de121c636 100644 --- a/test/modules/NetworkLogger.spec.ts +++ b/test/modules/NetworkLogger.spec.ts @@ -5,9 +5,8 @@ import { Platform } from 'react-native'; import waitForExpect from 'wait-for-expect'; import * as NetworkLogger from '../../src/modules/NetworkLogger'; -import { NativeAPM, NativeInstabug } from '../../src/native'; -import IBGEventEmitter from '../../src/utils/IBGEventEmitter'; -import IBGConstants from '../../src/utils/InstabugConstants'; +import { NativeAPM } from '../../src/native/NativeAPM'; +import { NativeInstabug } from '../../src/native/NativeInstabug'; import Interceptor from '../../src/utils/XhrNetworkInterceptor'; const clone = (obj: any) => { @@ -109,9 +108,6 @@ describe('NetworkLogger Module', () => { }); NetworkLogger.setEnabled(true); - expect( - IBGEventEmitter.getListeners(IBGConstants.NETWORK_DATA_OBFUSCATION_HANDLER_EVENT).length, - ).toEqual(1); await waitForExpect(() => { const newData = clone(network); newData.requestHeaders.token = randomString; @@ -131,9 +127,6 @@ describe('NetworkLogger Module', () => { }); NetworkLogger.setEnabled(true); - expect( - IBGEventEmitter.getListeners(IBGConstants.NETWORK_DATA_OBFUSCATION_HANDLER_EVENT).length, - ).toEqual(1); await waitForExpect(() => { const newData = clone(network); newData.requestHeaders.token = randomString; diff --git a/test/modules/Replies.spec.ts b/test/modules/Replies.spec.ts index d8784364d..26fc49b1d 100644 --- a/test/modules/Replies.spec.ts +++ b/test/modules/Replies.spec.ts @@ -1,11 +1,16 @@ import { Platform } from 'react-native'; import * as Replies from '../../src/modules/Replies'; -import { NativeReplies } from '../../src/native'; -import IBGEventEmitter from '../../src/utils/IBGEventEmitter'; -import IBGConstants from '../../src/utils/InstabugConstants'; +import { NativeEvents, NativeReplies, emitter } from '../../src/native/NativeReplies'; describe('Replies Module', () => { + beforeEach(() => { + const events = Object.values(NativeEvents); + events.forEach((event) => { + emitter.removeAllListeners(event); + }); + }); + it('should call the native method setRepliesEnabled', () => { Replies.setEnabled(true); @@ -39,9 +44,9 @@ describe('Replies Module', () => { it('should invoke callback on emitting the event IBGOnNewReplyReceivedCallback', () => { const callback = jest.fn(); Replies.setOnNewReplyReceivedHandler(callback); - IBGEventEmitter.emit(IBGConstants.ON_REPLY_RECEIVED_HANDLER); + emitter.emit(NativeEvents.ON_REPLY_RECEIVED_HANDLER); - expect(IBGEventEmitter.getListeners(IBGConstants.ON_REPLY_RECEIVED_HANDLER).length).toEqual(1); + expect(emitter.listenerCount(NativeEvents.ON_REPLY_RECEIVED_HANDLER)).toBe(1); expect(callback).toHaveBeenCalled(); }); diff --git a/test/modules/Surveys.spec.ts b/test/modules/Surveys.spec.ts index ebb842118..d55760752 100644 --- a/test/modules/Surveys.spec.ts +++ b/test/modules/Surveys.spec.ts @@ -1,11 +1,16 @@ import { Platform } from 'react-native'; import * as Surveys from '../../src/modules/Surveys'; -import { NativeSurveys } from '../../src/native'; -import IBGEventEmitter from '../../src/utils/IBGEventEmitter'; -import IBGConstants from '../../src/utils/InstabugConstants'; +import { NativeEvents, NativeSurveys, emitter } from '../../src/native/NativeSurveys'; describe('Surveys Module', () => { + beforeEach(() => { + const events = Object.values(NativeEvents); + events.forEach((event) => { + emitter.removeAllListeners(event); + }); + }); + it('should call the native method setSurveysEnabled', () => { Surveys.setEnabled(true); @@ -60,9 +65,9 @@ describe('Surveys Module', () => { it('should invoke callback on emitting the event IBGWillShowSurvey', () => { const callback = jest.fn(); Surveys.setOnShowHandler(callback); - IBGEventEmitter.emit(IBGConstants.WILL_SHOW_SURVEY_HANDLER); + emitter.emit(NativeEvents.WILL_SHOW_SURVEY_HANDLER); - expect(IBGEventEmitter.getListeners(IBGConstants.WILL_SHOW_SURVEY_HANDLER).length).toEqual(1); + expect(emitter.listenerCount(NativeEvents.WILL_SHOW_SURVEY_HANDLER)).toBe(1); expect(callback).toHaveBeenCalled(); }); @@ -77,9 +82,9 @@ describe('Surveys Module', () => { it('should invoke callback on emitting the event IBGDidDismissSurvey', () => { const callback = jest.fn(); Surveys.setOnDismissHandler(callback); - IBGEventEmitter.emit(IBGConstants.DID_DISMISS_SURVEY_HANDLER); + emitter.emit(NativeEvents.DID_DISMISS_SURVEY_HANDLER); - expect(IBGEventEmitter.getListeners(IBGConstants.DID_DISMISS_SURVEY_HANDLER).length).toEqual(1); + expect(emitter.listenerCount(NativeEvents.DID_DISMISS_SURVEY_HANDLER)).toBe(1); expect(callback).toHaveBeenCalled(); }); diff --git a/test/setup.ts b/test/setup.ts index 62dcf6a7c..f18030d28 100644 --- a/test/setup.ts +++ b/test/setup.ts @@ -7,15 +7,11 @@ import 'react-native/Libraries/Network/fetch'; import nock from 'nock'; import XHR from 'xhr2'; -import IBGEventEmitter from '../src/utils/IBGEventEmitter'; - global.XMLHttpRequest = XHR; nock.disableNetConnect(); beforeEach(() => { - IBGEventEmitter.removeAllListeners(); - jest.spyOn(Platform, 'constants', 'get').mockReturnValue({ isTesting: true, reactNativeVersion: { diff --git a/test/utils/InstabugUtils.spec.ts b/test/utils/InstabugUtils.spec.ts index b60aeef73..1e28530ad 100644 --- a/test/utils/InstabugUtils.spec.ts +++ b/test/utils/InstabugUtils.spec.ts @@ -4,7 +4,7 @@ import { Platform } from 'react-native'; import parseErrorStackLib from 'react-native/Libraries/Core/Devtools/parseErrorStack'; import * as Instabug from '../../src/modules/Instabug'; -import { NativeCrashReporting } from '../../src/native'; +import { NativeCrashReporting } from '../../src/native/NativeCrashReporting'; import { InvocationEvent } from '../../src/utils/Enums'; import InstabugUtils from '../../src/utils/InstabugUtils';