Skip to content
This repository has been archived by the owner on Jul 17, 2023. It is now read-only.

Commit

Permalink
refactor: replace asserts with exceptions (#58)
Browse files Browse the repository at this point in the history
To make it possible to catch attempts navigating past boundaries.
  • Loading branch information
jpnurmi authored Jun 16, 2023
1 parent f739cfc commit df8b73d
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 20 deletions.
35 changes: 23 additions & 12 deletions lib/src/controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,10 @@ class WizardController extends SafeChangeNotifier {

/// Requests the wizard to show the first page.
void home() {
assert(state.length > 1,
'`Wizard.home()` called from the first route ${state.last.name}');
if (state.length <= 1) {
throw WizardException(
'`Wizard.home()` called from the first route ${state.last.name}');
}

_updateState((state) {
final copy = List<WizardRouteSettings>.of(state);
Expand All @@ -61,14 +63,18 @@ class WizardController extends SafeChangeNotifier {
/// Requests the wizard to show the previous page. Optionally, `result` can be
/// returned to the previous page.
void back<T extends Object?>([T? result]) async {
assert(state.length > 1,
'`Wizard.back()` called from the first route ${state.last.name}');
if (state.length <= 1) {
throw WizardException(
'`Wizard.back()` called from the first route ${state.last.name}');
}

// go back to a specific route, or pick the previous route on the list
final previous = await routes[currentRoute]!.onBack?.call(state.last);
if (previous != null) {
assert(routes.keys.contains(previous),
'`Wizard.routes` is missing route \'$previous\'.');
if (!routes.keys.contains(previous)) {
throw WizardException(
'`Wizard.routes` is missing route \'$previous\'.');
}
}

final start = previous != null
Expand Down Expand Up @@ -116,14 +122,17 @@ class WizardController extends SafeChangeNotifier {
String nextRoute() {
final routeNames = routes.keys.toList();
final index = routeNames.indexOf(previous.name!);
assert(index < routeNames.length - 1,
'`Wizard.next()` called from the last route ${previous.name}.');
if (index == routeNames.length - 1) {
throw WizardException(
'`Wizard.next()` called from the last route ${previous.name}.');
}
return routeNames[index + 1];
}

final name = await onNext() ?? nextRoute();
assert(routes.keys.contains(name),
'`Wizard.routes` is missing route \'$name\'.');
if (!routes.keys.contains(name)) {
throw WizardException('`Wizard.routes` is missing route \'$name\'.');
}

return WizardRouteSettings<T>(name: name, arguments: arguments);
}
Expand All @@ -146,8 +155,10 @@ class WizardController extends SafeChangeNotifier {
/// Requests the wizard to jump to a specific page. Optionally, `arguments`
/// can be passed to the page.
Future<T?> jump<T extends Object?>(String route, {Object? arguments}) async {
assert(routes.keys.contains(route),
'`Wizard.jump()` called with an unknown route $route.');
if (!routes.keys.contains(route)) {
throw WizardException(
'`Wizard.jump()` called with an unknown route $route.');
}
final settings = await _loadRoute(route, (name) async {
return WizardRouteSettings<T>(name: name, arguments: arguments);
});
Expand Down
8 changes: 8 additions & 0 deletions lib/src/exception.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class WizardException implements Exception {
const WizardException(this.message);

final String message;

@override
String toString() => message;
}
1 change: 1 addition & 0 deletions lib/src/wizard.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:flow_builder/flow_builder.dart';
import 'package:flutter/material.dart';
import 'package:safe_change_notifier/safe_change_notifier.dart';

import 'exception.dart';
import 'route.dart';
import 'scope.dart';
import 'settings.dart';
Expand Down
1 change: 1 addition & 0 deletions lib/wizard_router.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
/// ![wizard_router](https://github.com/ubuntu-flutter-community/wizard_router/raw/main/images/wizard_router.png)
library wizard_router;

export 'src/exception.dart';
export 'src/route.dart';
export 'src/scope.dart';
export 'src/wizard.dart';
20 changes: 12 additions & 8 deletions test/wizard_router_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -186,13 +186,13 @@ void main() {
await tester.pumpAndSettle();
wizard.next();
await tester.pumpAndSettle();
await expectLater(wizard.next, throwsAssertionError);
await expectLater(wizard.next, throwsA(isA<WizardException>()));

wizard.back();
await tester.pumpAndSettle();
wizard.back();
await tester.pumpAndSettle();
await expectLater(wizard.back, throwsAssertionError);
await expectLater(wizard.back, throwsA(isA<WizardException>()));
});

testWidgets('route conditions', (tester) async {
Expand Down Expand Up @@ -305,15 +305,15 @@ void main() {

final firstWizardScope = Wizard.of(tester.element(firstPage));
nextRoute = 'unknown';
await expectLater(firstWizardScope.next, throwsAssertionError);
await expectLater(firstWizardScope.next, throwsA(isA<WizardException>()));

nextRoute = Routes.second;
firstWizardScope.next();
await tester.pumpAndSettle();

final secondWizardScope = Wizard.of(tester.element(secondPage));
backRoute = 'invalid';
await expectLater(secondWizardScope.back, throwsAssertionError);
await expectLater(secondWizardScope.back, throwsA(isA<WizardException>()));
});

testWidgets('pass arguments', (tester) async {
Expand Down Expand Up @@ -354,7 +354,7 @@ void main() {
final wizard = Wizard.of(tester.element(firstPage));

// 1st -> home
await expectLater(wizard.home, throwsAssertionError);
await expectLater(wizard.home, throwsA(isA<WizardException>()));

// 2nd -> home
wizard.next();
Expand Down Expand Up @@ -426,7 +426,7 @@ void main() {
expect(secondWizardScope.hasNext, isTrue);

// 2nd -> 1st
await expectLater(secondWizardScope.back, throwsAssertionError);
await expectLater(secondWizardScope.back, throwsA(isA<WizardException>()));

// 2nd -> 3rd
secondWizardScope.replace();
Expand All @@ -444,7 +444,7 @@ void main() {
expect(thirdWizardScope.hasNext, isFalse);

// 3rd -> 2nd
await expectLater(thirdWizardScope.back, throwsAssertionError);
await expectLater(thirdWizardScope.back, throwsA(isA<WizardException>()));
});

testWidgets('jump', (tester) async {
Expand Down Expand Up @@ -490,6 +490,10 @@ void main() {
expect(firstPage, findsOneWidget);
expect(secondPage, findsNothing);
expect(thirdPage, findsNothing);

// unknown
await expectLater(
firstWizardScope.jump('/unknown'), throwsA(isA<WizardException>()));
});

testWidgets('has next or previous', (tester) async {
Expand Down Expand Up @@ -843,7 +847,7 @@ void main() {
expect(root3Scope.hasPrevious, isTrue);
expect(root3Scope.hasNext, isTrue);

await expectLater(nested3Scope.next, throwsAssertionError);
await expectLater(nested3Scope.next, throwsA(isA<WizardException>()));

root3Scope.next();
await tester.pumpAndSettle();
Expand Down

0 comments on commit df8b73d

Please sign in to comment.