Skip to content
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 @@
## 8.0.3

- Makes namedLocation and route name related APIs case sensitive.

## 8.0.2

- Fixes a bug in `debugLogDiagnostics` to support StatefulShellRoute.
Expand Down
4 changes: 2 additions & 2 deletions packages/go_router/lib/src/configuration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ class RouteConfiguration {
'${queryParameters.isEmpty ? '' : ', queryParameters: $queryParameters'}');
return true;
}());
final String keyName = name.toLowerCase();
final String keyName = name;
assert(_nameToPath.containsKey(keyName), 'unknown route name: $name');
final String path = _nameToPath[keyName]!;
assert(() {
Expand Down Expand Up @@ -564,7 +564,7 @@ class RouteConfiguration {
final String fullPath = concatenatePaths(parentFullPath, route.path);

if (route.name != null) {
final String name = route.name!.toLowerCase();
final String name = route.name!;
assert(
!_nameToPath.containsKey(name),
'duplication fullpaths for name '
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: 8.0.2
version: 8.0.3
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
66 changes: 66 additions & 0 deletions packages/go_router/test/name_case_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:go_router/go_router.dart';

void main() {
testWidgets(
'Route names are case sensitive',
(WidgetTester tester) async {
// config router with 2 routes with the same name but different case (Name, name)
final GlobalKey<NavigatorState> navKey = GlobalKey<NavigatorState>();
final GoRouter router = GoRouter(
navigatorKey: navKey,
routes: <GoRoute>[
GoRoute(
path: '/',
name: 'Name',
builder: (_, __) => const ScreenA(),
),
GoRoute(
path: '/path',
name: 'name',
builder: (_, __) => const ScreenB(),
),
],
);

// run MaterialApp, initial screen path is '/' -> ScreenA
await tester.pumpWidget(
MaterialApp.router(
routerConfig: router,
title: 'GoRouter Testcase',
),
);

// go to ScreenB
navKey.currentContext!.goNamed('name');
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
navKey.currentContext!.goNamed('name');
router.goNamed('name');

assert(GoRouter.of(navKey.currentContext!).location == '/path');
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
assert(GoRouter.of(navKey.currentContext!).location == '/path');
expect(find.byType(ScreenB), findsOneWidget);


// go to ScreenA
navKey.currentContext!.goNamed('Name');
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
navKey.currentContext!.goNamed('Name');
router.goNamed('Name');

assert(GoRouter.of(navKey.currentContext!).location == '/');
Copy link
Contributor

Choose a reason for hiding this comment

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

expect(find.byType(ScreenA), findsOneWidget);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Suggestions are applied, thanks ✌️

},
);
}

class ScreenA extends StatelessWidget {
const ScreenA({super.key});

@override
Widget build(BuildContext context) {
return Container();
}
}

class ScreenB extends StatelessWidget {
const ScreenB({super.key});

@override
Widget build(BuildContext context) {
return Container();
}
}