Skip to content

Commit ccc09e4

Browse files
authored
enha: Flutter min version test (#1061)
1 parent cdf7172 commit ccc09e4

File tree

6 files changed

+238
-28
lines changed

6 files changed

+238
-28
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
name: flutter integration tests
2+
on:
3+
push:
4+
branches:
5+
- main
6+
pull_request:
7+
8+
jobs:
9+
cancel-previous-workflow:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Cancel Previous Runs
13+
uses: styfle/cancel-workflow-action@b173b6ec0100793626c2d9e6b90435061f4fc3e5 # [email protected]
14+
with:
15+
access_token: ${{ github.token }}
16+
17+
test-android:
18+
runs-on: macos-latest
19+
defaults:
20+
run:
21+
working-directory: ./flutter/example
22+
strategy:
23+
matrix:
24+
sdk: ['stable', 'beta']
25+
steps:
26+
- name: checkout
27+
uses: actions/checkout@v3
28+
29+
- uses: actions/setup-java@v3
30+
with:
31+
distribution: 'adopt'
32+
java-version: '8'
33+
34+
- uses: subosito/flutter-action@1e6ee87cb840500837bcd50a667fb28815d8e310 # pin@v2
35+
with:
36+
channel: ${{ matrix.sdk }}
37+
38+
- name: flutter upgrade
39+
run: flutter upgrade
40+
41+
- name: flutter pub get
42+
run: flutter pub get
43+
44+
- name: launch android emulator & run android integration test
45+
uses: reactivecircus/android-emulator-runner@d7b53ddc6e44254e1f4cf4a6ad67345837027a66 #[email protected]
46+
with:
47+
working-directory: ./flutter/example
48+
api-level: 21
49+
arch: x86_64
50+
profile: Nexus 6
51+
script: flutter test integration_test/integration_test.dart
52+
test-ios:
53+
runs-on: macos-11
54+
defaults:
55+
run:
56+
working-directory: ./flutter/example
57+
strategy:
58+
matrix:
59+
sdk: ['stable', 'beta']
60+
steps:
61+
- name: checkout
62+
uses: actions/checkout@v3
63+
64+
- uses: subosito/flutter-action@1e6ee87cb840500837bcd50a667fb28815d8e310 # pin@v2
65+
with:
66+
channel: ${{ matrix.sdk }}
67+
68+
- name: flutter upgrade
69+
run: flutter upgrade
70+
71+
- name: flutter pub get
72+
run: flutter pub get
73+
74+
- name: launch ios emulator
75+
uses: futureware-tech/simulator-action@ee05c113b79f056b47f354d7b313555f5491e158 #pin@v2
76+
with:
77+
model: 'iPhone 8'
78+
os_version: '15.2'
79+
80+
- name: run ios integration test
81+
run: flutter test integration_test/integration_test.dart
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import 'package:flutter/widgets.dart';
2+
import 'package:flutter_test/flutter_test.dart';
3+
import 'package:integration_test/integration_test.dart';
4+
import 'package:sentry_flutter/sentry_flutter.dart';
5+
import 'package:sentry_flutter_example/main.dart';
6+
7+
void main() {
8+
final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized();
9+
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
10+
11+
Future<void> setupSentryAndApp(WidgetTester tester) async {
12+
await setupSentry(() async {
13+
await tester.pumpWidget(SentryScreenshotWidget(
14+
child: DefaultAssetBundle(
15+
bundle: SentryAssetBundle(enableStructuredDataTracing: true),
16+
child: MyApp(),
17+
)));
18+
await tester.pumpAndSettle();
19+
});
20+
}
21+
22+
// Tests
23+
24+
testWidgets('setup sentry and render app', (tester) async {
25+
await setupSentryAndApp(tester);
26+
27+
// Find any UI element and verify it is present.
28+
expect(find.text('Open another Scaffold'), findsOneWidget);
29+
});
30+
31+
testWidgets('setup sentry and capture event', (tester) async {
32+
await setupSentryAndApp(tester);
33+
34+
final event = SentryEvent();
35+
final sentryId = await Sentry.captureEvent(event);
36+
37+
expect(sentryId != SentryId.empty(), true);
38+
});
39+
40+
testWidgets('setup sentry and capture exception', (tester) async {
41+
await setupSentryAndApp(tester);
42+
43+
try {
44+
throw SentryException(
45+
type: 'StarError', value: 'I have a bad feeling about this...');
46+
} catch (exception, stacktrace) {
47+
final sentryId =
48+
await Sentry.captureException(exception, stackTrace: stacktrace);
49+
50+
expect(sentryId != SentryId.empty(), true);
51+
}
52+
});
53+
54+
testWidgets('setup sentry and capture message', (tester) async {
55+
await setupSentryAndApp(tester);
56+
57+
final sentryId = await Sentry.captureMessage('hello world!');
58+
59+
expect(sentryId != SentryId.empty(), true);
60+
});
61+
62+
testWidgets('setup sentry and capture user feedback', (tester) async {
63+
await setupSentryAndApp(tester);
64+
65+
final feedback = SentryUserFeedback(
66+
eventId: SentryId.newId(),
67+
name: 'fixture-name',
68+
69+
comments: 'fixture-comments');
70+
await Sentry.captureUserFeedback(feedback);
71+
});
72+
73+
testWidgets('setup sentry and close', (tester) async {
74+
await setupSentryAndApp(tester);
75+
76+
await Sentry.close();
77+
});
78+
79+
testWidgets('setup sentry and add breadcrumb', (tester) async {
80+
await setupSentryAndApp(tester);
81+
82+
final breadcrumb = Breadcrumb(message: 'fixture-message');
83+
await Sentry.addBreadcrumb(breadcrumb);
84+
});
85+
86+
testWidgets('setup sentry and configure scope', (tester) async {
87+
await setupSentryAndApp(tester);
88+
89+
await Sentry.configureScope((scope) async {
90+
await scope.setContexts('contexts-key', 'contexts-value');
91+
await scope.removeContexts('contexts-key');
92+
93+
final user = SentryUser(id: 'fixture-id');
94+
await scope.setUser(user);
95+
await scope.setUser(null);
96+
97+
final breadcrumb = Breadcrumb(message: 'fixture-message');
98+
await scope.addBreadcrumb(breadcrumb);
99+
await scope.clearBreadcrumbs();
100+
101+
await scope.setExtra('extra-key', 'extra-value');
102+
await scope.removeExtra('extra-key');
103+
104+
await scope.setTag('tag-key', 'tag-value');
105+
await scope.removeTag('tag-key');
106+
});
107+
});
108+
109+
testWidgets('setup sentry and start transaction', (tester) async {
110+
await setupSentryAndApp(tester);
111+
112+
final transaction = Sentry.startTransaction('transaction', 'test');
113+
await transaction.finish();
114+
});
115+
116+
testWidgets('setup sentry and start transaction with context',
117+
(tester) async {
118+
await setupSentryAndApp(tester);
119+
120+
final context = SentryTransactionContext('transaction', 'test');
121+
final transaction = Sentry.startTransactionWithContext(context);
122+
await transaction.finish();
123+
});
124+
}

flutter/example/lib/main.dart

+27-25
Original file line numberDiff line numberDiff line change
@@ -21,32 +21,34 @@ const String _exampleDsn =
2121
final _channel = const MethodChannel('example.flutter.sentry.io');
2222

2323
Future<void> main() async {
24-
await SentryFlutter.init(
25-
(options) {
26-
options.dsn = _exampleDsn;
27-
options.tracesSampleRate = 1.0;
28-
options.reportPackages = false;
29-
options.addInAppInclude('sentry_flutter_example');
30-
options.considerInAppFramesByDefault = false;
31-
options.attachThreads = true;
32-
options.enableWindowMetricBreadcrumbs = true;
33-
options.addIntegration(LoggingIntegration());
34-
options.attachScreenshot = true;
35-
// We can enable Sentry debug logging during development. This is likely
36-
// going to log too much for your app, but can be useful when figuring out
37-
// configuration issues, e.g. finding out why your events are not uploaded.
38-
options.debug = true;
39-
},
40-
// Init your App.
41-
appRunner: () => runApp(
42-
SentryScreenshotWidget(
43-
child: DefaultAssetBundle(
44-
bundle: SentryAssetBundle(enableStructuredDataTracing: true),
45-
child: MyApp(),
24+
await setupSentry(() => runApp(
25+
SentryScreenshotWidget(
26+
child: DefaultAssetBundle(
27+
bundle: SentryAssetBundle(enableStructuredDataTracing: true),
28+
child: MyApp(),
29+
),
4630
),
47-
),
48-
),
49-
);
31+
));
32+
}
33+
34+
Future<void> setupSentry(AppRunner appRunner) async {
35+
await SentryFlutter.init((options) {
36+
options.dsn = _exampleDsn;
37+
options.tracesSampleRate = 1.0;
38+
options.reportPackages = false;
39+
options.addInAppInclude('sentry_flutter_example');
40+
options.considerInAppFramesByDefault = false;
41+
options.attachThreads = true;
42+
options.enableWindowMetricBreadcrumbs = true;
43+
options.addIntegration(LoggingIntegration());
44+
options.attachScreenshot = true;
45+
// We can enable Sentry debug logging during development. This is likely
46+
// going to log too much for your app, but can be useful when figuring out
47+
// configuration issues, e.g. finding out why your events are not uploaded.
48+
options.debug = true;
49+
},
50+
// Init your App.
51+
appRunner: appRunner);
5052
}
5153

5254
class MyApp extends StatefulWidget {

flutter/example/pubspec.yaml

+4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ dependencies:
2525
dev_dependencies:
2626
pedantic: ^1.11.1
2727
sentry_dart_plugin: ^1.0.0-beta.1
28+
integration_test:
29+
sdk: flutter
30+
flutter_test:
31+
sdk: flutter
2832

2933
flutter:
3034
uses-material-design: true

flutter/lib/src/sentry_native_channel.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class SentryNativeChannel {
2828

2929
Future<void> beginNativeFrames() async {
3030
try {
31-
await _channel.invokeMapMethod<String, dynamic>('beginNativeFrames');
31+
await _channel.invokeMethod('beginNativeFrames');
3232
} catch (error, stackTrace) {
3333
_logError('beginNativeFrames', error, stackTrace);
3434
}

flutter/test/sentry_native_channel_test.dart

+1-2
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ void main() {
3737
final sut = fixture.getSut();
3838
await sut.beginNativeFrames();
3939

40-
verify(fixture.methodChannel
41-
.invokeMapMethod<String, dynamic>('beginNativeFrames'));
40+
verify(fixture.methodChannel.invokeMethod('beginNativeFrames'));
4241
});
4342

4443
test('endNativeFrames', () async {

0 commit comments

Comments
 (0)