Skip to content

Commit

Permalink
Navigator.pushAndRemoveUntil throws exception in Bugsnag (#242)
Browse files Browse the repository at this point in the history
* Navigator.pushAndRemoveUntil throws exception in Bugsnag #238

* Updated changelog

* Extended the solution to other cases

* Fixed an issue

* Fixed an issue

* Fixed metadata handling on Android

* Apply suggestions from code review

Co-authored-by: Jason <lemnik@users.noreply.github.com>

* Changes requested in code review

* Added E2E tests

---------

Co-authored-by: Robert <robert.smartbear@gmail.com>
Co-authored-by: Jason <lemnik@users.noreply.github.com>
  • Loading branch information
3 people committed Apr 23, 2024
1 parent d7c6d59 commit faa15d0
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 19 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

## TBD

- Fixed: Navigator.pushAndRemoveUntil throws exception [#242](https://github.com/bugsnag/bugsnag-flutter/pull/242)

## 3.1.0 (2024-04-09)

Expand Down
11 changes: 11 additions & 0 deletions features/fixtures/app/lib/scenarios/null_context_scenario.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import 'package:bugsnag_flutter/bugsnag_flutter.dart';
import 'scenario.dart';

class NullContextScenario extends Scenario {
@override
Future<void> run() async {
await bugsnag.start(endpoints: endpoints);
await bugsnag.setContext(null);
await bugsnag.notify(Exception(), null);
}
}
11 changes: 11 additions & 0 deletions features/fixtures/app/lib/scenarios/null_user_scenario.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import 'package:bugsnag_flutter/bugsnag_flutter.dart';
import 'scenario.dart';

class NullUserScenario extends Scenario {
@override
Future<void> run() async {
await bugsnag.start(endpoints: endpoints);
await bugsnag.setUser(id: null, email: null, name: null);
await bugsnag.notify(Exception(), null);
}
}
8 changes: 7 additions & 1 deletion features/fixtures/app/lib/scenarios/scenarios.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import 'package:MazeRunner/scenarios/null_context_scenario.dart';
import 'package:MazeRunner/scenarios/null_user_scenario.dart';

import 'app_hang_scenario.dart';
import 'attach_bugsnag_scenario.dart';
import 'breadcrumbs_scenario.dart';
Expand Down Expand Up @@ -58,5 +61,8 @@ final List<ScenarioInfo<Scenario>> scenarios = [
ScenarioInfo(
'UnhandledExceptionScenario', () => UnhandledExceptionScenario()),
ScenarioInfo("HttpBreadcrumbScenario", () => HttpBreadcrumbScenario()),
ScenarioInfo("DartIoHttpBreadcrumbScenario", () => DartIoHttpBreadcrumbScenario()),
ScenarioInfo(
"DartIoHttpBreadcrumbScenario", () => DartIoHttpBreadcrumbScenario()),
ScenarioInfo("NullContextScenario", () => NullContextScenario()),
ScenarioInfo("NullUserScenario", () => NullUserScenario()),
];
15 changes: 15 additions & 0 deletions features/null_parameters.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Feature: nullParameters

Scenario: Context is set to null
When I run "NullContextScenario"
Then I wait to receive an error
And the error is valid for the error reporting API version "4.0" for the "Flutter Bugsnag Notifier" notifier
And the exception "errorClass" equals "_Exception"
And the event "severity" equals "warning"

Scenario: User is set to null
When I run "NullUserScenario"
Then I wait to receive an error
And the error is valid for the error reporting API version "4.0" for the "Flutter Bugsnag Notifier" notifier
And the exception "errorClass" equals "_Exception"
And the event "severity" equals "warning"
Original file line number Diff line number Diff line change
Expand Up @@ -104,18 +104,18 @@ Void start(@Nullable JSONObject args) throws Exception {
? new Configuration(arguments.getString("apiKey"))
: Configuration.load(context);

configuration.setAppType(arguments.optString("appType", configuration.getAppType()));
configuration.setAppVersion(arguments.optString("appVersion", configuration.getAppVersion()));
configuration.setAppType(getString(arguments, "appType", configuration.getAppType()));
configuration.setAppVersion(getString(arguments, "appVersion", configuration.getAppVersion()));
configuration.setAutoTrackSessions(arguments.optBoolean("autoTrackSessions", configuration.getAutoTrackSessions()));
configuration.setAutoDetectErrors(arguments.optBoolean("autoDetectErrors", configuration.getAutoDetectErrors()));
configuration.setContext(arguments.optString("context", configuration.getContext()));
configuration.setContext(getString(arguments, "context", configuration.getContext()));
configuration.setLaunchDurationMillis(arguments.optLong("launchDurationMillis", configuration.getLaunchDurationMillis()));
configuration.setSendLaunchCrashesSynchronously(arguments.optBoolean("sendLaunchCrashesSynchronously", configuration.getSendLaunchCrashesSynchronously()));
configuration.setMaxBreadcrumbs(arguments.optInt("maxBreadcrumbs", configuration.getMaxBreadcrumbs()));
configuration.setMaxPersistedEvents(arguments.optInt("maxPersistedEvents", configuration.getMaxPersistedEvents()));
configuration.setMaxPersistedSessions(arguments.optInt("maxPersistedSessions", configuration.getMaxPersistedSessions()));
configuration.setMaxStringValueLength(arguments.optInt("maxStringValueLength", configuration.getMaxStringValueLength()));
configuration.setReleaseStage(arguments.optString("releaseStage", configuration.getReleaseStage()));
configuration.setReleaseStage(getString(arguments, "releaseStage", configuration.getReleaseStage()));
configuration.setPersistUser(arguments.optBoolean("persistUser", configuration.getPersistUser()));

if (arguments.has("redactedKeys")) {
Expand All @@ -133,9 +133,9 @@ Void start(@Nullable JSONObject args) throws Exception {
JSONObject user = arguments.optJSONObject("user");
if (user != null) {
configuration.setUser(
user.optString("id", null),
user.optString("email", null),
user.optString("name", null)
getString(user, "id"),
getString(user, "email"),
getString(user, "name")
);
}

Expand Down Expand Up @@ -228,9 +228,9 @@ JSONObject getUser(@Nullable JSONObject args) {
Void setUser(@Nullable JSONObject user) {
if (user != null) {
Bugsnag.setUser(
(String) user.opt("id"),
(String) user.opt("email"),
(String) user.opt("name")
getString(user, "id"),
getString(user, "email"),
getString(user, "name")
);
} else {
Bugsnag.setUser(null, null, null);
Expand All @@ -241,7 +241,7 @@ Void setUser(@Nullable JSONObject user) {

Void setContext(@Nullable JSONObject args) {
if (args != null) {
Bugsnag.setContext((String) args.opt("context"));
Bugsnag.setContext(getString(args, "context"));
}

return null;
Expand All @@ -253,9 +253,9 @@ String getContext(@Nullable JSONObject args) {

Void leaveBreadcrumb(@Nullable JSONObject args) throws Exception {
if (args != null &&
args.has("name") &&
hasString(args, "name") &&
args.has("metaData") &&
args.has("type")) {
hasString(args, "type")) {
Bugsnag.leaveBreadcrumb(args.getString("name"),
JsonHelper.unwrap(args.getJSONObject("metaData")),
JsonHelper.unpackBreadcrumbType(args.getString("type")));
Expand All @@ -279,7 +279,7 @@ Void addFeatureFlags(@Nullable JSONArray args) {
}

Void clearFeatureFlag(@Nullable JSONObject args) throws JSONException {
if (args != null && args.has("name")) {
if (args != null && hasString(args, "name")) {
Bugsnag.clearFeatureFlag(args.getString("name"));
}
return null;
Expand All @@ -291,7 +291,7 @@ Void clearFeatureFlags(@Nullable JSONObject args) {
}

Void addMetadata(@Nullable JSONObject args) throws JSONException {
if (args == null || !args.has("section") || !args.has("metadata")) {
if (args == null || !hasString(args,"section") || !args.has("metadata")) {
return null;
}

Expand All @@ -303,11 +303,11 @@ Void addMetadata(@Nullable JSONObject args) throws JSONException {
}

Void clearMetadata(@Nullable JSONObject args) throws JSONException {
if (args == null || !args.has("section")) {
if (args == null || !hasString(args, "section")) {
return null;
}

if (args.has("key")) {
if (hasString(args, "key")) {
Bugsnag.clearMetadata(args.getString("section"), args.getString("key"));
} else {
Bugsnag.clearMetadata(args.getString("section"));
Expand All @@ -317,7 +317,7 @@ Void clearMetadata(@Nullable JSONObject args) throws JSONException {
}

JSONObject getMetadata(@Nullable JSONObject args) throws JSONException {
if (args == null || !args.has("section")) {
if (args == null || !hasString(args, "section")) {
return null;
}

Expand Down Expand Up @@ -403,4 +403,18 @@ JSONObject deliverEvent(@Nullable JSONObject eventJson) {
client.deliverEvent(event);
return null;
}

@Nullable String getString(JSONObject args, String key) {
Object value = args.opt(key);
return value instanceof String ? (String) value : null;
}

@Nullable String getString(JSONObject args, String key, @Nullable String fallback) {
String value = getString(args, key);
return value != null ? value : fallback;
}

boolean hasString(JSONObject args, String key) {
return getString(args, key) != null;
}
}

0 comments on commit faa15d0

Please sign in to comment.