Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
add connectivity integration
  • Loading branch information
denrase committed Nov 28, 2023
commit 6392c92f564dcb7292ece992464ae7290b1fb134
57 changes: 57 additions & 0 deletions flutter/lib/src/integrations/connectivity_integration.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import 'dart:async';

import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:meta/meta.dart';
import '../../sentry_flutter.dart';

class ConnectivityIntegration extends Integration<SentryFlutterOptions> {
Connectivity connectivity = Connectivity();
Hub? _hub;
StreamSubscription<ConnectivityResult>? _subscription;

@override
void call(Hub hub, SentryFlutterOptions options) {
_hub = hub;
_subscription = connectivity.onConnectivityChanged.listen(addBreadcrumb);

options.sdk.addIntegration('connectivityIntegration');
}

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

@internal
@visibleForTesting
void addBreadcrumb(ConnectivityResult result) {
_hub?.addBreadcrumb(
Breadcrumb(
category: 'device.connectivity',
level: SentryLevel.info,
type: 'connectivity',
data: {'connectivity': result.toSentryConnectivity()}),
);
}
}

extension on ConnectivityResult {
String toSentryConnectivity() {
switch (this) {
case ConnectivityResult.bluetooth:
case ConnectivityResult.vpn:
case ConnectivityResult.wifi:
return 'wifi';
case ConnectivityResult.ethernet:
return 'ethernet';
case ConnectivityResult.mobile:
return 'cellular';
case ConnectivityResult.none:
return 'none';
case ConnectivityResult.other:
return 'other';
}
}
}
1 change: 1 addition & 0 deletions flutter/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ dependencies:
package_info_plus: '>=1.0.0 <=5.0.1'
meta: ^1.3.0
ffi: ^2.0.0
connectivity_plus: ^5.0.2
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is kinda against https://develop.sentry.dev/philosophy/#dependencies-cost and as known from package_info_plus it's a quite frequent source of major updates.


dev_dependencies:
build_runner: ^2.4.2
Expand Down
149 changes: 149 additions & 0 deletions flutter/test/integrations/connectivity_integration_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import 'package:connectivity_plus/connectivity_plus.dart';
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_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: connectivity changed `bluetooth` adds `wifi` breadcrumb',
() {
final integration = fixture.getSut();
integration.call(fixture.hub, fixture.options);

integration.addBreadcrumb(ConnectivityResult.bluetooth);

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

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

test(
'$ConnectivityIntegration: connectivity changed `wifi` adds `wifi` breadcrumb',
() {
final integration = fixture.getSut();
integration.call(fixture.hub, fixture.options);

integration.addBreadcrumb(ConnectivityResult.wifi);

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

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

test(
'$ConnectivityIntegration: connectivity changed `vpn` adds `vpn` breadcrumb',
() {
final integration = fixture.getSut();
integration.call(fixture.hub, fixture.options);

integration.addBreadcrumb(ConnectivityResult.vpn);

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

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

test(
'$ConnectivityIntegration: connectivity changed `ethernet` adds `ethernet` breadcrumb',
() {
final integration = fixture.getSut();
integration.call(fixture.hub, fixture.options);

integration.addBreadcrumb(ConnectivityResult.ethernet);

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

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

test(
'$ConnectivityIntegration: connectivity changed `mobile` adds `cellular` breadcrumb',
() {
final integration = fixture.getSut();
integration.call(fixture.hub, fixture.options);

integration.addBreadcrumb(ConnectivityResult.mobile);

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

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

test(
'$ConnectivityIntegration: connectivity changed `other` adds `other` breadcrumb',
() {
final integration = fixture.getSut();
integration.call(fixture.hub, fixture.options);

integration.addBreadcrumb(ConnectivityResult.other);

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

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

test(
'$ConnectivityIntegration: connectivity changed `none` adds `none` breadcrumb',
() {
final integration = fixture.getSut();
integration.call(fixture.hub, fixture.options);

integration.addBreadcrumb(ConnectivityResult.none);

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

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

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

ConnectivityIntegration getSut() {
return ConnectivityIntegration();
}
}