Skip to content

Commit

Permalink
refactor(cat-voices): Refactor application bootstrap to allow running…
Browse files Browse the repository at this point in the history
… it in integration tests (#848)

* wip

* refactor: app initialization logic in tests

* chore: improve FPS

* refactor: bootstrap

* docs(cat-voices): bootstrap docs

* refactor(cat-voices): cleanup

* refactor(cat-voices): lints

* docs(cat-voices): add more documentation

* refactor(cat-voices): cleanup

* refactor(cat-voices): cleanup

* refactor(cat-voices): cleanup name

---------

Co-authored-by: kukkok3 <[email protected]>
  • Loading branch information
dtscalac and kukkok3 committed Sep 20, 2024
1 parent 42bee43 commit 6e47284
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 18 deletions.
23 changes: 23 additions & 0 deletions catalyst_voices/integration_test/app_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import 'package:catalyst_voices/app/view/app.dart';
import 'package:catalyst_voices/configs/bootstrap.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';

void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

group('end-to-end test', () {
testWidgets('run app', (tester) async {
final args = await bootstrap();
await tester.pumpWidget(App(routerConfig: args.routerConfig));
// let the application load
await tester.pump(const Duration(seconds: 5));

// pump and settle every 100ms to simulate almost production-like FPS
await tester.pumpAndSettle(const Duration(milliseconds: 100));

// wait 10s until the test is finished
await Future<void>.delayed(const Duration(seconds: 10));
});
});
}
47 changes: 34 additions & 13 deletions catalyst_voices/lib/configs/bootstrap.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,39 +31,59 @@ final class BootstrapArgs {
}

// TODO(damian-molinski): Add Isolate.current.addErrorListener
Future<void> bootstrap([
//
/// The entry point for Catalyst Voices,
/// initializes and runs the application.
///
/// Should configure dependency injection, setup logger and do
/// all the things which are necessary before the actual app is run.
///
/// You can customize the default app by providing
/// your own instance via [builder].
Future<void> bootstrapAndRun([
BootstrapWidgetBuilder builder = _defaultBuilder,
]) async {
await runZonedGuarded(
() => _safeBootstrap(builder),
() => _safeBootstrapAndRun(builder),
_reportUncaughtZoneError,
);
}

Future<void> _safeBootstrap(BootstrapWidgetBuilder builder) async {
Future<void> _safeBootstrapAndRun(BootstrapWidgetBuilder builder) async {
try {
await _doBootstrap(builder);
await _doBootstrapAndRun(builder);
} catch (error, stack) {
await _reportBootstrapError(error, stack);
}
}

Future<void> _doBootstrap(BootstrapWidgetBuilder builder) async {
Future<void> _doBootstrapAndRun(BootstrapWidgetBuilder builder) async {
// There's no need to call WidgetsFlutterBinding.ensureInitialized()
// since this is already done internally by SentryFlutter.init()
// More info here: https://github.com/getsentry/sentry-dart/issues/2063
if (!kReleaseMode) {
WidgetsFlutterBinding.ensureInitialized();
}

_loggingService
..level = kDebugMode ? Level.ALL : Level.OFF
..printLogs = kDebugMode;

FlutterError.onError = _reportFlutterError;
PlatformDispatcher.instance.onError = _reportPlatformDispatcherError;

await Dependencies.instance.init();
final args = await bootstrap();
final app = await builder(args);
await _runApp(app);
}

/// Initializes the application before it can be run. Should setup all
/// the things which are necessary before the actual app is run,
/// either via [runApp] or injected into a test environment during
/// integration tests.
///
/// Initialization logic that is relevant for [runApp] scenario
/// only should be added to [_doBootstrapAndRun], not here.
Future<BootstrapArgs> bootstrap() async {
_loggingService
..level = kDebugMode ? Level.ALL : Level.OFF
..printLogs = kDebugMode;

GoRouter.optionURLReflectsImperativeAPIs = true;
setPathUrlStrategy();
Expand All @@ -76,10 +96,9 @@ Future<void> _doBootstrap(BootstrapWidgetBuilder builder) async {

Bloc.observer = AppBlocObserver();

final args = BootstrapArgs(routerConfig: router);
final app = await builder(args);
await Dependencies.instance.init();

await _runApp(app);
return BootstrapArgs(routerConfig: router);
}

Future<void> _runApp(Widget app) async {
Expand Down Expand Up @@ -112,6 +131,8 @@ Future<void> _reportFlutterError(FlutterErrorDetails details) async {
/// Platform Dispatcher Errors reporting
bool _reportPlatformDispatcherError(Object error, StackTrace stack) {
_platformDispatcherLogger.severe('Platform Error', error, stack);

// return true to prevent default error handling
return true;
}

Expand Down
2 changes: 1 addition & 1 deletion catalyst_voices/lib/configs/main_dev.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import 'package:catalyst_voices/configs/bootstrap.dart';

void main() async {
await bootstrap();
await bootstrapAndRun();
}
2 changes: 1 addition & 1 deletion catalyst_voices/lib/configs/main_preprod.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import 'package:catalyst_voices/configs/bootstrap.dart';

void main() async {
await bootstrap();
await bootstrapAndRun();
}
2 changes: 1 addition & 1 deletion catalyst_voices/lib/configs/main_prod.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import 'package:catalyst_voices/configs/bootstrap.dart';

void main() async {
await bootstrap();
await bootstrapAndRun();
}
2 changes: 1 addition & 1 deletion catalyst_voices/lib/configs/main_qa.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import 'package:catalyst_voices/configs/bootstrap.dart';

void main() async {
await bootstrap();
await bootstrapAndRun();
}
2 changes: 1 addition & 1 deletion catalyst_voices/lib/configs/main_web.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import 'package:catalyst_voices/configs/bootstrap.dart';

void main() async {
await bootstrap();
await bootstrapAndRun();
}

0 comments on commit 6e47284

Please sign in to comment.