Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
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
5 changes: 3 additions & 2 deletions packages/go_router/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## NEXT
## 15.2.0

* Updates minimum supported SDK version to Flutter 3.27/Dart 3.6.
- Updates minimum supported SDK version to Flutter 3.27/Dart 3.6.
- `GoRouteData` now defines `.location`, `.go(context)`, `.push(context)`, `.pushReplacement(context)`, and `replace(context)` to be used for [Type-safe routing](https://pub.dev/documentation/go_router/latest/topics/Type-safe%20routes-topic.html). **Requires go_router_builder >= 3.0.0**.

## 15.1.2

Expand Down
24 changes: 24 additions & 0 deletions packages/go_router/lib/src/route_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,30 @@ abstract class GoRouteData extends RouteData {
static final Expando<GoRouteData> _stateObjectExpando = Expando<GoRouteData>(
'GoRouteState to GoRouteData expando',
);

/// The location of this route.
String get location => throw _shouldBeGeneratedError;

/// Navigate to the route.
void go(BuildContext context) => throw _shouldBeGeneratedError;

/// Push the route onto the page stack.
Future<T?> push<T>(BuildContext context) => throw _shouldBeGeneratedError;

/// Replaces the top-most page of the page stack with the route.
void pushReplacement(BuildContext context) => throw _shouldBeGeneratedError;

/// Replaces the top-most page of the page stack with the route but treats
/// it as the same page.
///
/// The page key will be reused. This will preserve the state and not run any
/// page animation.
///
void replace(BuildContext context) => throw _shouldBeGeneratedError;

static UnimplementedError get _shouldBeGeneratedError => UnimplementedError(
'Should be generated using [Type-safe routing](https://pub.dev/documentation/go_router/latest/topics/Type-safe%20routes-topic.html).',
);
}

/// A class to represent a [ShellRoute] in
Expand Down
2 changes: 1 addition & 1 deletion packages/go_router/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: go_router
description: A declarative router for Flutter based on Navigation 2 supporting
deep linking, data-driven routes and more
version: 15.1.2
version: 15.2.0
repository: https://github.com/flutter/packages/tree/main/packages/go_router
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+go_router%22

Expand Down
70 changes: 70 additions & 0 deletions packages/go_router/test/route_data_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,76 @@ void main() {
expect(routeWithDefaultCaseSensitivity.caseSensitive, false);
},
);

testWidgets(
'It should throw beacuase there is no code generated',
(WidgetTester tester) async {
final List<FlutterErrorDetails> errors = <FlutterErrorDetails>[];

FlutterError.onError =
(FlutterErrorDetails details) => errors.add(details);

const String errorText = 'Should be generated';

Widget buildWidget(void Function(BuildContext) onTap) {
return MaterialApp(
home: Builder(
builder: (BuildContext context) => GestureDetector(
child: const Text('Tap'),
onTap: () => onTap(context),
),
),
);
}

final Widget pushThrower = buildWidget((BuildContext context) {
const _GoRouteDataBuild().push<void>(context);
});
await tester.pumpWidget(pushThrower);
await tester.tap(find.text('Tap'));

expect(errors.first.exception, isA<UnimplementedError>());
expect(errors.first.exception.toString(), contains(errorText));

errors.clear();

final Widget goThrower = buildWidget((BuildContext context) {
const _GoRouteDataBuild().go(context);
});
await tester.pumpWidget(goThrower);
await tester.tap(find.text('Tap'));

expect(errors.first.exception, isA<UnimplementedError>());
expect(errors.first.exception.toString(), contains(errorText));

errors.clear();

final Widget pushReplacementThrower =
buildWidget((BuildContext context) {
const _GoRouteDataBuild().pushReplacement(context);
});
await tester.pumpWidget(pushReplacementThrower);
await tester.tap(find.text('Tap'));

expect(errors.first.exception, isA<UnimplementedError>());
expect(errors.first.exception.toString(), contains(errorText));

errors.clear();

final Widget replaceThrower = buildWidget((BuildContext context) {
const _GoRouteDataBuild().pushReplacement(context);
});
await tester.pumpWidget(replaceThrower);
await tester.tap(find.text('Tap'));

expect(errors.first.exception, isA<UnimplementedError>());
expect(errors.first.exception.toString(), contains(errorText));

errors.clear();

FlutterError.onError = FlutterError.dumpErrorToConsole;
},
);
});

group('ShellRouteData', () {
Expand Down