Skip to content

Commit

Permalink
Add ConnectivityIntegration for web (#1765)
Browse files Browse the repository at this point in the history
  • Loading branch information
denrase authored Dec 18, 2023
1 parent d8519f9 commit 117d988
Show file tree
Hide file tree
Showing 9 changed files with 206 additions and 24 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

- Add option to opt out of fatal level for automatically collected errors ([#1738](https://github.com/getsentry/sentry-dart/pull/1738))
- Add `Hive` breadcrumbs ([#1773](https://github.com/getsentry/sentry-dart/pull/1773))
- Add `ConnectivityIntegration` for web ([#1765](https://github.com/getsentry/sentry-dart/pull/1765))
- We only get the info if online/offline on web platform. The added breadcrumb is set to either `wifi` or `none`.

### Dependencies

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import 'package:meta/meta.dart';
import '../../../sentry_flutter.dart';
import 'connectivity_provider.dart';

class ConnectivityIntegration extends Integration<SentryFlutterOptions> {
Hub? _hub;
ConnectivityProvider? _connectivityProvider;

@override
void call(Hub hub, SentryFlutterOptions options) {
_hub = hub;
_connectivityProvider = ConnectivityProvider();
_connectivityProvider?.listen((connectivity) {
addBreadcrumb(connectivity);
});
options.sdk.addIntegration('connectivityIntegration');
}

@override
void close() {
_hub = null;
_connectivityProvider?.cancel();
}

@internal
@visibleForTesting
void addBreadcrumb(String connectivity) {
_hub?.addBreadcrumb(
Breadcrumb(
category: 'device.connectivity',
level: SentryLevel.info,
type: 'connectivity',
data: {'connectivity': connectivity}),
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import 'noop_connectivity_provider.dart'
if (dart.library.html) 'web_connectivity_provider.dart';

abstract class ConnectivityProvider {
factory ConnectivityProvider() => connectivityProvider();

void listen(void Function(String connectivity) onChange);
void cancel();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import 'connectivity_provider.dart';

ConnectivityProvider connectivityProvider() {
return NoOpConnectivityProvider();
}

class NoOpConnectivityProvider implements ConnectivityProvider {
@override
void listen(void Function(String connectivity) onChange) {
// NoOp
}

@override
void cancel() {
// NoOp
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import 'dart:async';
import 'dart:html' as html;

import 'connectivity_provider.dart';

ConnectivityProvider connectivityProvider() {
return WebConnectivityProvider();
}

class WebConnectivityProvider implements ConnectivityProvider {
StreamSubscription<html.Event>? _onOnlineSub;
StreamSubscription<html.Event>? _onOfflineSub;

@override
void listen(void Function(String connectivity) onChange) {
_onOnlineSub = html.window.onOnline.listen((_) {
onChange('wifi');
});
_onOfflineSub = html.window.onOffline.listen((_) {
onChange('none');
});
}

@override
void cancel() {
_onOnlineSub?.cancel();
_onOnlineSub = null;

_onOfflineSub?.cancel();
_onOfflineSub = null;
}
}
5 changes: 5 additions & 0 deletions flutter/lib/src/sentry_flutter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import '../sentry_flutter.dart';
import 'event_processor/android_platform_exception_event_processor.dart';
import 'event_processor/flutter_exception_event_processor.dart';
import 'event_processor/platform_exception_event_processor.dart';
import 'integrations/connectivity/connectivity_integration.dart';
import 'integrations/screenshot_integration.dart';
import 'native/factory.dart';
import 'native/native_scope_observer.dart';
Expand Down Expand Up @@ -171,6 +172,10 @@ mixin SentryFlutter {
integrations.add(ScreenshotIntegration());
}

if (platformChecker.isWeb) {
integrations.add(ConnectivityIntegration());
}

// works with Skia, CanvasKit and HTML renderer
integrations.add(SentryViewHierarchyIntegration());

Expand Down
56 changes: 56 additions & 0 deletions flutter/test/integrations/connectivity_integration_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:sentry/sentry.dart';
import 'package:sentry_flutter/src/integrations/connectivity/connectivity_integration.dart';
import 'package:sentry_flutter/src/sentry_flutter_options.dart';

import '../mocks.dart';
import '../mocks.mocks.dart';

void main() {
WidgetsFlutterBinding.ensureInitialized();

late Fixture fixture;

setUp(() {
fixture = Fixture();
});

verifyBreadcrumb(Breadcrumb crumb, String connectivityData) {
expect(crumb.category, 'device.connectivity');
expect(crumb.type, 'connectivity');
expect(crumb.level, SentryLevel.info);
expect(crumb.data?['connectivity'], connectivityData);
}

test('adds integration', () {
final sut = fixture.getSut();
sut(fixture.hub, fixture.options);

expect(fixture.options.sdk.integrations.contains('connectivityIntegration'),
true);
});

test('$ConnectivityIntegration: addsBreadcrumb', () {
final integration = fixture.getSut();
integration.call(fixture.hub, fixture.options);

integration.addBreadcrumb('wifi');

final crumb = verify(
fixture.hub.addBreadcrumb(captureAny),
).captured.first as Breadcrumb;

verifyBreadcrumb(crumb, 'wifi');
});
}

class Fixture {
final hub = MockHub();
final options = SentryFlutterOptions(dsn: fakeDsn);

ConnectivityIntegration getSut() {
return ConnectivityIntegration();
}
}
2 changes: 1 addition & 1 deletion flutter/test/sentry_flutter_options_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ void main() {
expect(options.enableAutoNativeBreadcrumbs, isFalse);
});

testWidgets('useFlutterBreadcrumbTracking', (WidgetTester tester) async {
testWidgets('useNativeBreadcrumbTracking', (WidgetTester tester) async {
final options = SentryFlutterOptions();
options.useNativeBreadcrumbTracking();

Expand Down
71 changes: 48 additions & 23 deletions flutter/test/sentry_flutter_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:sentry_flutter/src/integrations/connectivity/connectivity_integration.dart';
import 'package:sentry_flutter/src/integrations/integrations.dart';
import 'package:sentry_flutter/src/integrations/screenshot_integration.dart';
import 'package:sentry_flutter/src/profiling.dart';
Expand All @@ -23,6 +24,10 @@ final platformAgnosticIntegrations = [
SentryViewHierarchyIntegration,
];

final webIntegrations = [
ConnectivityIntegration,
];

final nonWebIntegrations = [
OnErrorIntegration,
];
Expand Down Expand Up @@ -81,14 +86,18 @@ void main() {
options: sentryFlutterOptions!, expectedHasNativeScopeObserver: true);

testConfiguration(
integrations: integrations,
shouldHaveIntegrations: [
...androidIntegrations,
...nativeIntegrations,
...platformAgnosticIntegrations,
...nonWebIntegrations,
],
shouldNotHaveIntegrations: iOsAndMacOsIntegrations);
integrations: integrations,
shouldHaveIntegrations: [
...androidIntegrations,
...nativeIntegrations,
...platformAgnosticIntegrations,
...nonWebIntegrations,
],
shouldNotHaveIntegrations: [
...iOsAndMacOsIntegrations,
...nonWebIntegrations,
],
);

integrations
.indexWhere((element) => element is WidgetsFlutterBindingIntegration);
Expand Down Expand Up @@ -138,7 +147,10 @@ void main() {
...platformAgnosticIntegrations,
...nonWebIntegrations,
],
shouldNotHaveIntegrations: androidIntegrations,
shouldNotHaveIntegrations: [
...androidIntegrations,
...nonWebIntegrations,
],
);

testBefore(
Expand Down Expand Up @@ -179,16 +191,15 @@ void main() {
testScopeObserver(
options: sentryFlutterOptions!, expectedHasNativeScopeObserver: true);

testConfiguration(
integrations: integrations,
shouldHaveIntegrations: [
...iOsAndMacOsIntegrations,
...nativeIntegrations,
...platformAgnosticIntegrations,
...nonWebIntegrations,
],
shouldNotHaveIntegrations: androidIntegrations,
);
testConfiguration(integrations: integrations, shouldHaveIntegrations: [
...iOsAndMacOsIntegrations,
...nativeIntegrations,
...platformAgnosticIntegrations,
...nonWebIntegrations,
], shouldNotHaveIntegrations: [
...androidIntegrations,
...nonWebIntegrations,
]);

testBefore(
integrations: integrations,
Expand Down Expand Up @@ -239,6 +250,7 @@ void main() {
...androidIntegrations,
...iOsAndMacOsIntegrations,
...nativeIntegrations,
...webIntegrations,
],
);

Expand Down Expand Up @@ -290,6 +302,7 @@ void main() {
...androidIntegrations,
...iOsAndMacOsIntegrations,
...nativeIntegrations,
...webIntegrations,
],
);

Expand Down Expand Up @@ -336,7 +349,10 @@ void main() {

testConfiguration(
integrations: integrations,
shouldHaveIntegrations: platformAgnosticIntegrations,
shouldHaveIntegrations: [
...platformAgnosticIntegrations,
...webIntegrations,
],
shouldNotHaveIntegrations: [
...androidIntegrations,
...iOsAndMacOsIntegrations,
Expand Down Expand Up @@ -383,7 +399,10 @@ void main() {

testConfiguration(
integrations: integrations,
shouldHaveIntegrations: platformAgnosticIntegrations,
shouldHaveIntegrations: [
...platformAgnosticIntegrations,
...webIntegrations,
],
shouldNotHaveIntegrations: [
...androidIntegrations,
...iOsAndMacOsIntegrations,
Expand Down Expand Up @@ -427,7 +446,10 @@ void main() {

testConfiguration(
integrations: integrations,
shouldHaveIntegrations: platformAgnosticIntegrations,
shouldHaveIntegrations: [
...platformAgnosticIntegrations,
...webIntegrations,
],
shouldNotHaveIntegrations: [
...androidIntegrations,
...iOsAndMacOsIntegrations,
Expand Down Expand Up @@ -472,7 +494,10 @@ void main() {

testConfiguration(
integrations: integrations,
shouldHaveIntegrations: platformAgnosticIntegrations,
shouldHaveIntegrations: [
...platformAgnosticIntegrations,
...webIntegrations,
],
shouldNotHaveIntegrations: [
...androidIntegrations,
...iOsAndMacOsIntegrations,
Expand Down

0 comments on commit 117d988

Please sign in to comment.