Skip to content

[go_router] Add routing functions to GoRouteData #9277

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
4 changes: 4 additions & 0 deletions packages/go_router/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 15.2.0

- `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

- Fixes focus request propagation from `GoRouter` to `Navigator` by properly handling the `requestFocus` parameter.
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 not code generated',
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
'It should throw beacuase there is not code generated',
'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