import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:patbond_flutter/analytics/analytics_page_name.dart'; import 'package:patbond_flutter/analytics/analytics_route_observer.dart'; import 'package:patbond_flutter/analytics/page_view_tracker.dart'; void main() { group('AnalyticsRouteObserver', () { testWidgets('push 路由报 page_viewed', (tester) async { final events = >[]; final tracker = PageViewTracker((name, [props]) async { events.add({'event': name, ...?props}); }); final observer = AnalyticsRouteObserver(tracker: tracker); await tester.pumpWidget( MaterialApp( navigatorObservers: [observer], home: Builder( builder: (context) => ElevatedButton( onPressed: () => Navigator.of(context).push( MaterialPageRoute( settings: RouteSettings( name: AnalyticsPageName.login.pageName, ), builder: (_) => const Placeholder(), ), ), child: const Text('Go'), ), ), ), ); await tester.tap(find.text('Go')); await tester.pumpAndSettle(); expect(events, hasLength(1)); expect(events.first['event'], 'page_viewed'); expect(events.first['pageName'], 'login'); }); testWidgets('push 两页 referrer 链正确,pop 返回补报前一页', (tester) async { final events = >[]; final tracker = PageViewTracker((name, [props]) async { events.add({'event': name, ...?props}); }); final observer = AnalyticsRouteObserver(tracker: tracker); await tester.pumpWidget( MaterialApp( navigatorObservers: [observer], home: Builder( builder: (context) => ElevatedButton( onPressed: () => Navigator.of(context).push( MaterialPageRoute( settings: RouteSettings( name: AnalyticsPageName.login.pageName, ), builder: (loginContext) => ElevatedButton( onPressed: () => Navigator.of(loginContext).push( MaterialPageRoute( settings: RouteSettings( name: AnalyticsPageName.register.pageName, ), builder: (registerContext) => ElevatedButton( onPressed: () => Navigator.of(registerContext).pop(), child: const Text('Back'), ), ), ), child: const Text('Next'), ), ), ), child: const Text('Go'), ), ), ), ); await tester.tap(find.text('Go')); await tester.pumpAndSettle(); await tester.tap(find.text('Next')); await tester.pumpAndSettle(); // push 两页:两条事件,referrer 链正确(06 §5.2 验收 5)。 expect(events.map((e) => e['pageName']), ['login', 'register']); expect(events[0].containsKey('referrer'), isFalse); expect(events[1]['referrer'], 'login'); // pop 返回:didPop 补报重新曝光的前一页,referrer 为弹出页。 await tester.tap(find.text('Back')); await tester.pumpAndSettle(); expect(events, hasLength(3)); expect(events[2]['pageName'], 'login'); expect(events[2]['referrer'], 'register'); }); testWidgets('pop 回无名根路由经 resolveRootPage 补报', (tester) async { final events = >[]; final tracker = PageViewTracker((name, [props]) async { events.add({'event': name, ...?props}); }); final observer = AnalyticsRouteObserver( tracker: tracker, resolveRootPage: () => AnalyticsPageName.home, ); await tester.pumpWidget( MaterialApp( navigatorObservers: [observer], home: Builder( builder: (context) => ElevatedButton( onPressed: () => Navigator.of(context).push( MaterialPageRoute( settings: RouteSettings( name: AnalyticsPageName.profile.pageName, ), builder: (innerContext) => ElevatedButton( onPressed: () => Navigator.of(innerContext).pop(), child: const Text('Back'), ), ), ), child: const Text('Go'), ), ), ), ); await tester.tap(find.text('Go')); await tester.pumpAndSettle(); await tester.tap(find.text('Back')); await tester.pumpAndSettle(); expect(events.map((e) => e['pageName']), ['profile', 'home']); expect(events[1]['referrer'], 'profile'); }); testWidgets('未在枚举的路由名不上报', (tester) async { final events = >[]; final tracker = PageViewTracker((name, [props]) async { events.add({'event': name, ...?props}); }); final observer = AnalyticsRouteObserver(tracker: tracker); await tester.pumpWidget( MaterialApp( navigatorObservers: [observer], home: Builder( builder: (context) => ElevatedButton( onPressed: () => Navigator.of(context).push( MaterialPageRoute( settings: const RouteSettings(name: '/debug/unknown'), builder: (_) => const Placeholder(), ), ), child: const Text('Go'), ), ), ), ); await tester.tap(find.text('Go')); await tester.pumpAndSettle(); expect(events, isEmpty); }); testWidgets('dialog 不上报(PopupRoute 不是 PageRoute)', (tester) async { final events = >[]; final tracker = PageViewTracker((name, [props]) async { events.add({'event': name, ...?props}); }); final observer = AnalyticsRouteObserver(tracker: tracker); await tester.pumpWidget( MaterialApp( navigatorObservers: [observer], home: Builder( builder: (context) => ElevatedButton( onPressed: () => showDialog( context: context, builder: (_) => const AlertDialog(title: Text('Dialog')), ), child: const Text('Show'), ), ), ), ); await tester.tap(find.text('Show')); await tester.pumpAndSettle(); expect(events, isEmpty); }); }); group('PageViewTracker', () { test('连续相同页面去重(Tab 重复点选)', () { final events = >[]; final tracker = PageViewTracker((name, [props]) async { events.add({'event': name, ...?props}); }); tracker.report(AnalyticsPageName.home); tracker.report(AnalyticsPageName.home); tracker.report(AnalyticsPageName.profile); tracker.report(AnalyticsPageName.home); expect(events, hasLength(3)); expect(events.map((e) => e['pageName']), ['home', 'profile', 'home']); }); test('referrer 链跨机制连贯(首页无 referrer)', () { final events = >[]; final tracker = PageViewTracker((name, [props]) async { events.add({'event': name, ...?props}); }); tracker.report(AnalyticsPageName.home); tracker.report(AnalyticsPageName.login); tracker.report(AnalyticsPageName.profile); expect(events[0].containsKey('referrer'), isFalse); expect(events[1]['referrer'], 'home'); expect(events[2]['referrer'], 'login'); }); test('reportTab 记录当前 Tab', () { final events = >[]; final tracker = PageViewTracker((name, [props]) async { events.add({'event': name, ...?props}); }); tracker.reportTab(AnalyticsPageName.petArchive); expect(tracker.currentTab, AnalyticsPageName.petArchive); expect(events.single['pageName'], 'pet_archive'); }); }); }