import 'dart:io'; import 'package:eaimar/routes/app_pages.dart'; import 'package:flutter_test/flutter_test.dart'; /// 路由表卫生:每条 Routes 常量都要在 AppPages 里注册,且至少有一处跳转; /// 每个 GetPage 的 name 唯一。死路由曾经堆到 20 个,这里守住不再长回来。 void main() { TestWidgetsFlutterBinding.ensureInitialized(); final routesSrc = File('lib/routes/app_routes.dart').readAsStringSync(); final constRe = RegExp(r"static const (\w+) = '([^']+)';"); final declared = { for (final m in constRe.allMatches(routesSrc)) m.group(1)!: m.group(2)! }; test('每条路由常量都在 AppPages 注册(initial 与 home 共用同一路径)', () { final registered = AppPages.pages.map((p) => p.name).toSet(); final missing = declared.entries .where((e) => !registered.contains(e.value)) .map((e) => e.key) .toList(); expect(missing, isEmpty, reason: '声明了但没注册: $missing'); }); test('GetPage name 唯一(home/initial 例外,两个常量同一路径)', () { final names = AppPages.pages.map((p) => p.name).toList(); final dup = {}; final seen = {}; for (final n in names) { if (!seen.add(n)) dup.add(n); } dup.remove('/home'); expect(dup, isEmpty, reason: '重复注册: $dup'); }); test('每条路由常量至少有一处跳转方(routes/ 目录之外)', () { final files = Directory('lib') .listSync(recursive: true) .whereType() .where((f) => f.path.endsWith('.dart') && !f.path.contains('lib/routes/')) .map((f) => f.readAsStringSync()) .join('\n'); final unused = declared.keys .where((k) => !RegExp('Routes\\.$k\\b').hasMatch(files)) .where((k) => k != 'initial') // GetMaterialApp 的 initialRoute 在 main.dart 直接用 .toList(); expect(unused, isEmpty, reason: '没人跳转的死路由: $unused'); }); }