diff --git a/CHANGELOG.md b/CHANGELOG.md index 57446c8..20eb667 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,51 @@ +## 2.0.0 + +### Breaking changes + +`BaseEvent.getName()` and `BaseEvent.getProperties()` have been removed. Event implementations must now override the `name` and `properties` getters. + +Before: + +```dart +class PurchaseEvent extends BaseEvent { + @override + String getName() => 'purchase'; + + @override + Map? getProperties() => {'amount': 29.99}; +} +``` + +After: + +```dart +class PurchaseEvent extends BaseEvent { + @override + String get name => 'purchase'; + + @override + Map? get properties => {'amount': 29.99}; +} +``` + +### Added + +* Add an `EventTransformer` pipeline for enriching and normalizing events before routing and dispatch. +* Add `EnrichedEvent` for layering additional properties onto an event while preserving its routing, consent, and privacy metadata. +* Add support for custom event categories and subcategories. +* Add the interactive FlexTrack guide at [flextrack.taghizadeh.dev](https://flextrack.taghizadeh.dev/). + +### Changed + +* Replace `BaseEvent.getName()` and `BaseEvent.getProperties()` with the `BaseEvent.name` and `BaseEvent.properties` getter API. +* Update examples, tests, and documentation to use the getter API. + +### Fixed + +* Align transformer signatures around `BaseEvent` so transformed events flow consistently through clients, widgets, routing, and trackers. + +--- + ## 1.0.1 * Improve package presentation and pub.dev listing metadata. diff --git a/LICENSE b/LICENSE index bd39460..2d2d250 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2025 [Reza Taghizadeh] +Copyright (c) 2025-2026 Reza Taghizadeh Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file +SOFTWARE. diff --git a/README.md b/README.md index c8fea30..846aa2a 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Multi-tracker analytics orchestration for Flutter: route events, enforce consent [![CI](https://github.com/alirezat66/flex_track/actions/workflows/ci.yml/badge.svg)](https://github.com/alirezat66/flex_track/actions) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/alirezat66/flex_track/blob/main/LICENSE) -**Settings → Pages** to that branch if the site is not live yet). API reference: [pub.dev documentation](https://pub.dev/documentation/flex_track/latest/). +[Interactive guide](https://flextrack.taghizadeh.dev/) · [API reference](https://pub.dev/documentation/flex_track/latest/) --- @@ -52,6 +52,10 @@ One call site, multiple tracker destinations, centralized policy. ## Table of contents - [FlexTrack](#flextrack) + - [The Problem](#the-problem) + - [The Solution](#the-solution) + - [Visual Demo](#visual-demo) + - [Quick Example](#quick-example) - [Table of contents](#table-of-contents) - [Quick start](#quick-start) - [Compare with the usual approach](#compare-with-the-usual-approach) @@ -66,6 +70,7 @@ One call site, multiple tracker destinations, centralized policy. - [Creating events](#creating-events) - [Event flags](#event-flags) - [EventCategory values](#eventcategory-values) + - [Custom categories](#custom-categories) - [Event transformers](#event-transformers) - [App-wide context (setup once)](#app-wide-context-setup-once) - [Dynamic values (evaluated at dispatch time)](#dynamic-values-evaluated-at-dispatch-time) @@ -130,8 +135,8 @@ class FirebaseTracker extends BaseTrackerStrategy { @override Future doTrack(BaseEvent event) async { await FirebaseAnalytics.instance.logEvent( - name: event.getName(), - parameters: event.getProperties(), + name: event.name, + parameters: event.properties, ); } } @@ -308,7 +313,7 @@ This package does not bundle Firebase, Mixpanel, Amplitude, or any other analyti ## Creating events -Extend `BaseEvent` and implement `getName()` and `getProperties()`. Everything else is optional. +Extend `BaseEvent` and implement the `name` and `properties` getters. Everything else is optional. ```dart class PurchaseEvent extends BaseEvent { @@ -316,10 +321,10 @@ class PurchaseEvent extends BaseEvent { PurchaseEvent({required this.amount}); @override - String getName() => 'purchase'; + String get name => 'purchase'; @override - Map getProperties() => {'amount': amount}; + Map get properties => {'amount': amount}; @override EventCategory get category => EventCategory.business; @@ -467,7 +472,7 @@ FlexTrack.addTransformer((event) => EnrichedEvent(event, { ### EnrichedEvent -`EnrichedEvent` is a `BaseEvent` wrapper. It forwards all metadata from the original event (`category`, `containsPII`, `requiresConsent`, etc.) and overrides `getProperties()` to merge the original properties with the extra ones. Extra properties win on key collision. +`EnrichedEvent` is a `BaseEvent` wrapper. It forwards all metadata from the original event (`category`, `containsPII`, `requiresConsent`, etc.) and overrides `properties` to merge the original properties with the extra ones. Extra properties win on key collision. ```dart // Extra properties override originals on the same key. @@ -523,8 +528,8 @@ class MyTracker extends BaseTrackerStrategy { @override Future doTrack(BaseEvent event) async { // Called for each routed event. - // event.getName() → String - // event.getProperties() → Map + // event.name → String + // event.properties → Map // event.category → EventCategory? } } @@ -556,8 +561,8 @@ class FirebaseTracker extends BaseTrackerStrategy { @override Future doTrack(BaseEvent event) async { await FirebaseAnalytics.instance.logEvent( - name: event.getName(), - parameters: event.getProperties(), + name: event.name, + parameters: event.properties, ); } } @@ -582,7 +587,7 @@ class MixpanelTracker extends BaseTrackerStrategy { @override Future doTrack(BaseEvent event) async { - _mixpanel.track(event.getName(), properties: event.getProperties()); + _mixpanel.track(event.name, properties: event.properties); } } ``` @@ -675,7 +680,7 @@ Rules are evaluated in priority order. The first matching rule wins. | `.routePII()` | `event.containsPII == true` | | `.routeMatching(RegExp(...))` | event name matches the regex | | `.routeNamed('pattern')` | event name contains the substring | -| `.routeWithProperty('key')` | `getProperties()` contains the key | +| `.routeWithProperty('key')` | `properties` contains the key | | `.routeDefault()` | catch-all (put this last) | **Full list of targets:** @@ -1072,8 +1077,8 @@ void main() { await FlexTrack.track(PurchaseEvent(amount: 9.99)); expect(mock.capturedEvents, hasLength(1)); - expect(mock.capturedEvents.single.getName(), 'purchase'); - expect(mock.capturedEvents.single.getProperties()['amount'], 9.99); + expect(mock.capturedEvents.single.name, 'purchase'); + expect(mock.capturedEvents.single.properties['amount'], 9.99); }); test('does not send event without consent', () async { diff --git a/example/lib/events/app_events.dart b/example/lib/events/app_events.dart index 569008b..ebaf130 100644 --- a/example/lib/events/app_events.dart +++ b/example/lib/events/app_events.dart @@ -15,10 +15,10 @@ class AppStartEvent extends BaseEvent { platform = platform ?? 'unknown'; @override - String getName() => 'app_start'; + String get name => 'app_start'; @override - Map getProperties() => { + Map get properties => { 'app_version': appVersion, 'build_number': buildNumber, 'platform': platform, @@ -49,10 +49,10 @@ class PageViewEvent extends BaseEvent { }) : timestamp = timestamp ?? DateTime.now(); @override - String getName() => 'page_view'; + String get name => 'page_view'; @override - Map getProperties() => { + Map get properties => { 'page_name': pageName, if (parameters != null) 'parameters': parameters!, 'timestamp': timestamp.millisecondsSinceEpoch, @@ -78,10 +78,10 @@ class ButtonClickEvent extends BaseEvent { }); @override - String getName() => 'button_click'; + String get name => 'button_click'; @override - Map getProperties() => { + Map get properties => { 'button_id': buttonId, 'button_text': buttonText, if (screenName != null) 'screen_name': screenName!, @@ -110,10 +110,10 @@ class ErrorEvent extends BaseEvent { }); @override - String getName() => 'error'; + String get name => 'error'; @override - Map getProperties() => { + Map get properties => { 'error_type': errorType, 'error_message': errorMessage, if (stackTrace != null) 'stack_trace': stackTrace!, @@ -146,10 +146,10 @@ class PerformanceEvent extends BaseEvent { }); @override - String getName() => 'performance_metric'; + String get name => 'performance_metric'; @override - Map getProperties() => { + Map get properties => { 'metric_name': metricName, 'value': value, 'unit': unit, diff --git a/example/lib/events/business_events.dart b/example/lib/events/business_events.dart index 6e2970c..d4dda42 100644 --- a/example/lib/events/business_events.dart +++ b/example/lib/events/business_events.dart @@ -21,10 +21,10 @@ class PurchaseEvent extends BaseEvent { }); @override - String getName() => 'purchase'; + String get name => 'purchase'; @override - Map getProperties() => { + Map get properties => { 'product_id': productId, 'product_name': productName, 'amount': amount, @@ -62,10 +62,10 @@ class CartAbandonmentEvent extends BaseEvent { }); @override - String getName() => 'cart_abandonment'; + String get name => 'cart_abandonment'; @override - Map getProperties() => { + Map get properties => { 'product_ids': productIds, 'total_value': totalValue, 'currency': currency, @@ -98,10 +98,10 @@ class AddToCartEvent extends BaseEvent { }); @override - String getName() => 'add_to_cart'; + String get name => 'add_to_cart'; @override - Map getProperties() => { + Map get properties => { 'product_id': productId, 'product_name': productName, 'price': price, @@ -133,10 +133,10 @@ class SubscriptionEvent extends BaseEvent { }); @override - String getName() => 'subscription_$action'; + String get name => 'subscription_$action'; @override - Map getProperties() => { + Map get properties => { 'plan_id': planId, 'plan_name': planName, 'price': price, diff --git a/example/lib/events/demo_routing_and_widgets_events.dart b/example/lib/events/demo_routing_and_widgets_events.dart index a0b2444..d8a89f4 100644 --- a/example/lib/events/demo_routing_and_widgets_events.dart +++ b/example/lib/events/demo_routing_and_widgets_events.dart @@ -7,10 +7,10 @@ class DemoBannerImpressionEvent extends BaseEvent { final String slotId; @override - String getName() => 'demo_banner_impression'; + String get name => 'demo_banner_impression'; @override - Map? getProperties() => { + Map? get properties => { 'slot_id': slotId, 'surface': 'home_demo_scroll', }; @@ -25,10 +25,10 @@ class DemoBannerImpressionEvent extends BaseEvent { /// Routed only to `console` + `firebase` (see [AnalyticsSetup] rules). class DemoFreeTierOnlyEvent extends BaseEvent { @override - String getName() => 'demo_free_tier_only'; + String get name => 'demo_free_tier_only'; @override - Map? getProperties() => const { + Map? get properties => const { 'note': 'premium trackers intentionally excluded', }; @@ -39,10 +39,10 @@ class DemoFreeTierOnlyEvent extends BaseEvent { /// Routed only to `mixpanel` + `amplitude` when consent allows. class DemoPremiumOnlyEvent extends BaseEvent { @override - String getName() => 'demo_premium_only'; + String get name => 'demo_premium_only'; @override - Map? getProperties() => const { + Map? get properties => const { 'note': 'free-tier-only trackers excluded', }; } diff --git a/example/lib/events/user_events.dart b/example/lib/events/user_events.dart index 85a403a..130cdb2 100644 --- a/example/lib/events/user_events.dart +++ b/example/lib/events/user_events.dart @@ -13,10 +13,10 @@ class UserRegistrationEvent extends BaseEvent { }); @override - String getName() => 'user_registration'; + String get name => 'user_registration'; @override - Map getProperties() => { + Map get properties => { 'registration_method': registrationMethod, 'accepted_terms': hasAcceptedTerms, 'accepted_marketing': hasAcceptedMarketing, @@ -44,10 +44,10 @@ class UserLoginEvent extends BaseEvent { }); @override - String getName() => 'user_login'; + String get name => 'user_login'; @override - Map getProperties() => { + Map get properties => { 'login_method': loginMethod, 'is_first_login': isFirstLogin, 'timestamp': timestamp.millisecondsSinceEpoch, @@ -71,10 +71,10 @@ class UserProfileUpdateEvent extends BaseEvent { }); @override - String getName() => 'user_profile_update'; + String get name => 'user_profile_update'; @override - Map getProperties() => { + Map get properties => { 'updated_fields': updatedFields, 'is_complete': isComplete, 'field_count': updatedFields.length, @@ -103,10 +103,10 @@ class FeatureUsageEvent extends BaseEvent { }); @override - String getName() => 'feature_usage'; + String get name => 'feature_usage'; @override - Map getProperties() => { + Map get properties => { 'feature_name': featureName, 'action': action, if (duration != null) 'duration_seconds': duration!, @@ -137,10 +137,10 @@ class UserEngagementEvent extends BaseEvent { }); @override - String getName() => 'user_engagement'; + String get name => 'user_engagement'; @override - Map getProperties() => { + Map get properties => { 'engagement_type': engagementType, if (sessionDuration != null) 'session_duration_seconds': sessionDuration!, diff --git a/example/lib/screens/event_enrichment_screen.dart b/example/lib/screens/event_enrichment_screen.dart index 3fd3220..23f0e06 100644 --- a/example/lib/screens/event_enrichment_screen.dart +++ b/example/lib/screens/event_enrichment_screen.dart @@ -23,8 +23,8 @@ class _EventEnrichmentScreenState extends State { super.initState(); _subscription = FlexTrack.eventDispatchStream.listen((record) { if (!mounted) return; - final name = record.event.getName(); - final props = record.event.getProperties(); + final name = record.event.name; + final props = record.event.properties; setState(() { _log.insert(0, '[$name] ${props ?? {}}'); }); diff --git a/example/lib/screens/home_screen.dart b/example/lib/screens/home_screen.dart index 4ed4f12..d8d30f0 100644 --- a/example/lib/screens/home_screen.dart +++ b/example/lib/screens/home_screen.dart @@ -689,7 +689,7 @@ class _AdditionalDemoSection extends StatelessWidget { final routingResults = testEvents.map((event) { final debug = FlexTrack.debugEvent(event); return { - 'event': event.getName(), + 'event': event.name, 'category': event.category?.name ?? 'none', 'trackers': debug.routingResult.targetTrackers, 'rules': debug.routingResult.appliedRules.length, @@ -746,10 +746,10 @@ class HighVolumeTestEvent extends BaseEvent { }); @override - String getName() => 'high_volume_test'; + String get name => 'high_volume_test'; @override - Map getProperties() => { + Map get properties => { 'sequence_number': sequenceNumber, 'batch_id': batchId, 'timestamp': timestamp.millisecondsSinceEpoch, @@ -826,10 +826,10 @@ class DebugEvent extends BaseEvent { }); @override - String getName() => 'debug_event'; + String get name => 'debug_event'; @override - Map getProperties() => { + Map get properties => { 'debug_info': debugInfo, 'level': level, 'timestamp': timestamp.millisecondsSinceEpoch, diff --git a/example/lib/screens/setting_screen.dart b/example/lib/screens/setting_screen.dart index 8433e44..9c5240e 100644 --- a/example/lib/screens/setting_screen.dart +++ b/example/lib/screens/setting_screen.dart @@ -491,7 +491,7 @@ class _SettingsScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ - Text('Event: ${testEvent.getName()}'), + Text('Event: ${testEvent.name}'), SizedBox(height: 8), Text( 'Target Trackers: ${debugInfo.routingResult.targetTrackers.join(', ')}'), diff --git a/example/lib/trackers/amplitude_tracker.dart b/example/lib/trackers/amplitude_tracker.dart index c5a9898..ed6b916 100644 --- a/example/lib/trackers/amplitude_tracker.dart +++ b/example/lib/trackers/amplitude_tracker.dart @@ -36,7 +36,7 @@ class AmplitudeTracker extends BaseTrackerStrategy { @override Future doTrack(BaseEvent event) async { - final properties = event.getProperties() ?? {}; + final properties = event.properties ?? {}; // Add event metadata for Amplitude final enhancedProperties = { @@ -49,11 +49,11 @@ class AmplitudeTracker extends BaseTrackerStrategy { // In real implementation: // await Amplitude.getInstance().logEvent( - // event.getName(), + // event.name, // eventProperties: enhancedProperties, // ); - debugPrint('📊 Amplitude tracking: ${event.getName()} $enhancedProperties'); + debugPrint('📊 Amplitude tracking: ${event.name} $enhancedProperties'); // Handle revenue events if (event is PurchaseEvent) { diff --git a/example/lib/trackers/custom_api_tracker.dart b/example/lib/trackers/custom_api_tracker.dart index 7f4c06f..54b2b84 100644 --- a/example/lib/trackers/custom_api_tracker.dart +++ b/example/lib/trackers/custom_api_tracker.dart @@ -91,8 +91,8 @@ class CustomAPITracker extends BaseTrackerStrategy { final payload = { 'events': eventsToSend .map((event) => { - 'name': event.getName(), - 'properties': event.getProperties(), + 'name': event.name, + 'properties': event.properties, 'timestamp': event.timestamp.toIso8601String(), 'category': event.category?.name, 'contains_pii': event.containsPII, diff --git a/example/lib/trackers/firebase_tracker.dart b/example/lib/trackers/firebase_tracker.dart index 84e66df..acdd893 100644 --- a/example/lib/trackers/firebase_tracker.dart +++ b/example/lib/trackers/firebase_tracker.dart @@ -43,12 +43,11 @@ class FirebaseTracker extends BaseTrackerStrategy { Future doTrack(BaseEvent event) async { // In real implementation: // await _analytics.logEvent( - // name: event.getName(), - // parameters: _convertProperties(event.getProperties()), + // name: event.name, + // parameters: _convertProperties(event.properties), // ); - debugPrint( - '🔥 Firebase tracking: ${event.getName()} ${event.getProperties()}'); + debugPrint('🔥 Firebase tracking: ${event.name} ${event.properties}'); // Handle special business events if (event is PurchaseEvent) { diff --git a/example/lib/trackers/mixpanel_tracker.dart b/example/lib/trackers/mixpanel_tracker.dart index 68c6c56..53813b5 100644 --- a/example/lib/trackers/mixpanel_tracker.dart +++ b/example/lib/trackers/mixpanel_tracker.dart @@ -47,7 +47,7 @@ class MixpanelTracker extends BaseTrackerStrategy { @override Future doTrack(BaseEvent event) async { - final properties = event.getProperties() ?? {}; + final properties = event.properties ?? {}; // Add event metadata final enhancedProperties = { @@ -59,9 +59,9 @@ class MixpanelTracker extends BaseTrackerStrategy { }; // In real implementation: - // _mixpanel.track(event.getName(), properties: enhancedProperties); + // _mixpanel.track(event.name, properties: enhancedProperties); - debugPrint('🎯 Mixpanel tracking: ${event.getName()} $enhancedProperties'); + debugPrint('🎯 Mixpanel tracking: ${event.name} $enhancedProperties'); // Handle special events if (event is PurchaseEvent) { diff --git a/example/lib/utils/gdpr_manager.dart b/example/lib/utils/gdpr_manager.dart index cdf90a5..eb387d7 100644 --- a/example/lib/utils/gdpr_manager.dart +++ b/example/lib/utils/gdpr_manager.dart @@ -242,10 +242,10 @@ class ConsentChangeEvent extends BaseEvent { }); @override - String getName() => 'consent_change'; + String get name => 'consent_change'; @override - Map getProperties() => { + Map get properties => { 'general_consent': hasGeneralConsent, 'pii_consent': hasPIIConsent, 'marketing_consent': hasMarketingConsent, diff --git a/examples/bloc_getit_app/lib/main.dart b/examples/bloc_getit_app/lib/main.dart index 6280f9d..b209c69 100644 --- a/examples/bloc_getit_app/lib/main.dart +++ b/examples/bloc_getit_app/lib/main.dart @@ -10,10 +10,10 @@ class _DemoEvent extends BaseEvent { final Map? _props; @override - String getName() => _name; + String get name => _name; @override - Map? getProperties() => _props; + Map? get properties => _props; @override bool get requiresConsent => false; diff --git a/examples/riverpod_app/lib/main.dart b/examples/riverpod_app/lib/main.dart index aa96695..f6d43ea 100644 --- a/examples/riverpod_app/lib/main.dart +++ b/examples/riverpod_app/lib/main.dart @@ -9,10 +9,10 @@ class _DemoEvent extends BaseEvent { final Map? _props; @override - String getName() => _name; + String get name => _name; @override - Map? getProperties() => _props; + Map? get properties => _props; @override bool get requiresConsent => false; diff --git a/examples/static_app/lib/main.dart b/examples/static_app/lib/main.dart index c806790..6acde82 100644 --- a/examples/static_app/lib/main.dart +++ b/examples/static_app/lib/main.dart @@ -9,10 +9,10 @@ class _DemoEvent extends BaseEvent { final Map? _props; @override - String getName() => _name; + String get name => _name; @override - Map? getProperties() => _props; + Map? get properties => _props; @override bool get requiresConsent => false; diff --git a/lib/flex_track.dart b/lib/flex_track.dart index 3e89526..f1ba26d 100644 --- a/lib/flex_track.dart +++ b/lib/flex_track.dart @@ -9,9 +9,9 @@ /// ```dart /// class UserSignupEvent extends BaseEvent { /// @override -/// String getName() => 'user_signup'; +/// String get name => 'user_signup'; /// @override -/// Map? getProperties() => const {}; +/// Map? get properties => const {}; /// } /// /// await FlexTrack.setup([ diff --git a/lib/src/core/event_processor.dart b/lib/src/core/event_processor.dart index 1f79262..4c58fa9 100644 --- a/lib/src/core/event_processor.dart +++ b/lib/src/core/event_processor.dart @@ -144,7 +144,7 @@ class EventProcessor { error: TrackerException( 'Tracker not found: $trackerId', trackerId: trackerId, - eventName: processedEvent.getName(), + eventName: processedEvent.name, code: 'NOT_FOUND', ), )); @@ -158,7 +158,7 @@ class EventProcessor { error: TrackerException( 'Tracker is disabled: $trackerId', trackerId: trackerId, - eventName: processedEvent.getName(), + eventName: processedEvent.name, code: 'DISABLED', ), )); @@ -181,7 +181,7 @@ class EventProcessor { : TrackerException( 'Failed to track event: $e', trackerId: trackerId, - eventName: processedEvent.getName(), + eventName: processedEvent.name, originalError: e, ), )); @@ -297,7 +297,7 @@ class EventProcessingResult { @override String toString() { return 'EventProcessingResult(' - 'event: ${event.getName()}, ' + 'event: ${event.name}, ' 'routed: $wasRouted, ' 'tracked: $wasTracked, ' 'successful: $successfulTrackingCount/${trackingResults.length}' diff --git a/lib/src/inspector/inspector_event_buffer.dart b/lib/src/inspector/inspector_event_buffer.dart index 015bc09..f161ee7 100644 --- a/lib/src/inspector/inspector_event_buffer.dart +++ b/lib/src/inspector/inspector_event_buffer.dart @@ -61,9 +61,9 @@ class InspectorEventRecord { return InspectorEventRecord( id: id, timeLabel: timeLabel, - name: event.getName(), + name: event.name, category: event.category?.name, - properties: jsonSafeProperties(event.getProperties()), + properties: jsonSafeProperties(event.properties), flags: { 'essential': event.isEssential, 'highVolume': event.isHighVolume, diff --git a/lib/src/models/event/base_event.dart b/lib/src/models/event/base_event.dart index f2e0adf..f1cc6f5 100644 --- a/lib/src/models/event/base_event.dart +++ b/lib/src/models/event/base_event.dart @@ -2,11 +2,11 @@ import 'package:flex_track/src/models/routing/event_category.dart'; import 'package:flex_track/src/models/routing/tracker_group.dart'; abstract class BaseEvent { - /// Returns the name of the event - String getName(); + /// Returns the name of the event. + String get name; - /// Returns the properties associated with the event - Map? getProperties(); + /// Returns the properties associated with the event. + Map? get properties; /// Optional category for automatic routing /// Override this in subclasses to enable category-based routing @@ -47,8 +47,8 @@ abstract class BaseEvent { /// Useful for debugging and serialization Map toMap() { return { - 'name': getName(), - 'properties': getProperties(), + 'name': name, + 'properties': properties, 'category': category?.name, 'preferredGroup': preferredGroup?.name, 'containsPII': containsPII, @@ -63,6 +63,6 @@ abstract class BaseEvent { @override String toString() { - return 'Event(${getName()}${category != null ? ', category: ${category!.name}' : ''})'; + return 'Event($name${category != null ? ', category: ${category!.name}' : ''})'; } } diff --git a/lib/src/models/event/enriched_event.dart b/lib/src/models/event/enriched_event.dart index d801185..baa5519 100644 --- a/lib/src/models/event/enriched_event.dart +++ b/lib/src/models/event/enriched_event.dart @@ -5,7 +5,7 @@ import 'package:flex_track/src/models/routing/tracker_group.dart'; /// A [BaseEvent] wrapper that merges extra properties onto an existing event /// without requiring mutation of the original. /// -/// All metadata getters are forwarded to [original]. [getProperties] returns +/// All metadata getters are forwarded to [original]. [properties] returns /// original properties merged with [extraProperties]; extra properties take /// precedence on key collision. /// @@ -34,11 +34,11 @@ class EnrichedEvent extends BaseEvent { Map get extraProperties => _extraProperties; @override - String getName() => _original.getName(); + String get name => _original.name; @override - Map getProperties() => { - ...?_original.getProperties(), + Map get properties => { + ...?_original.properties, ..._extraProperties, }; diff --git a/lib/src/models/routing/routing_rule.dart b/lib/src/models/routing/routing_rule.dart index 2e8ab43..8e4bfa1 100644 --- a/lib/src/models/routing/routing_rule.dart +++ b/lib/src/models/routing/routing_rule.dart @@ -60,13 +60,12 @@ class RoutingRule { } // Check event name pattern (contains check) - if (eventNamePattern != null && - !event.getName().contains(eventNamePattern!)) { + if (eventNamePattern != null && !event.name.contains(eventNamePattern!)) { return false; } // Check regex pattern - if (eventNameRegex != null && !eventNameRegex!.hasMatch(event.getName())) { + if (eventNameRegex != null && !eventNameRegex!.hasMatch(event.name)) { return false; } @@ -77,7 +76,7 @@ class RoutingRule { // Check property existence and value if (hasProperty != null) { - final props = event.getProperties(); + final props = event.properties; if (props == null || !props.containsKey(hasProperty)) { return false; } diff --git a/lib/src/routing/routing_engine.dart b/lib/src/routing/routing_engine.dart index 3061f8c..2f4d3c3 100644 --- a/lib/src/routing/routing_engine.dart +++ b/lib/src/routing/routing_engine.dart @@ -103,8 +103,8 @@ class RoutingEngine { ); } catch (e, stackTrace) { throw RoutingException( - 'Failed to route event ${event.getName()}: $e', - eventName: event.getName(), + 'Failed to route event ${event.name}: $e', + eventName: event.name, originalError: e, stackTrace: stackTrace, ); @@ -187,15 +187,15 @@ class RoutingEngine { } if (rule.eventNamePattern != null && - !event.getName().contains(rule.eventNamePattern!)) { + !event.name.contains(rule.eventNamePattern!)) { reasons.add( - 'Event name pattern mismatch: "${event.getName()}" does not contain "${rule.eventNamePattern}"'); + 'Event name pattern mismatch: "${event.name}" does not contain "${rule.eventNamePattern}"'); } if (rule.eventNameRegex != null && - !rule.eventNameRegex!.hasMatch(event.getName())) { + !rule.eventNameRegex!.hasMatch(event.name)) { reasons.add( - 'Event name regex mismatch: "${event.getName()}" does not match /${rule.eventNameRegex!.pattern}/'); + 'Event name regex mismatch: "${event.name}" does not match /${rule.eventNameRegex!.pattern}/'); } if (rule.category != null && event.category != rule.category) { diff --git a/lib/src/strategies/base_tracker_strategy.dart b/lib/src/strategies/base_tracker_strategy.dart index cc22b31..47994cc 100644 --- a/lib/src/strategies/base_tracker_strategy.dart +++ b/lib/src/strategies/base_tracker_strategy.dart @@ -66,9 +66,9 @@ abstract class BaseTrackerStrategy implements TrackerStrategy { await doTrack(event); } catch (e) { throw TrackerException( - 'Failed to track event ${event.getName()} with tracker $_id: $e', + 'Failed to track event ${event.name} with tracker $_id: $e', trackerId: _id, - eventName: event.getName(), + eventName: event.name, originalError: e, ); } diff --git a/lib/src/strategies/built_in/console_tracker.dart b/lib/src/strategies/built_in/console_tracker.dart index 0b85ca1..e1dbe19 100644 --- a/lib/src/strategies/built_in/console_tracker.dart +++ b/lib/src/strategies/built_in/console_tracker.dart @@ -59,7 +59,7 @@ class ConsoleTracker extends BaseTrackerStrategy { buffer.write('$_prefix: '); // Add event name - buffer.write(event.getName()); + buffer.write(event.name); // Add category if available if (event.category != null) { @@ -78,8 +78,8 @@ class ConsoleTracker extends BaseTrackerStrategy { _log(buffer.toString()); // Show properties if enabled - if (_showProperties && event.getProperties() != null) { - final properties = event.getProperties()!; + if (_showProperties && event.properties != null) { + final properties = event.properties!; if (properties.isNotEmpty) { _log(' Properties: ${_formatProperties(properties)}', indent: 2); } @@ -109,7 +109,7 @@ class ConsoleTracker extends BaseTrackerStrategy { _eventHistory.add(event); final buffer = StringBuffer(); - buffer.write(' ${i + 1}. ${event.getName()}'); + buffer.write(' ${i + 1}. ${event.name}'); if (event.category != null) { buffer.write(' (${event.category!.name})'); @@ -121,8 +121,8 @@ class ConsoleTracker extends BaseTrackerStrategy { _log(buffer.toString()); - if (_showProperties && event.getProperties() != null) { - final properties = event.getProperties()!; + if (_showProperties && event.properties != null) { + final properties = event.properties!; if (properties.isNotEmpty) { _log(' Props: ${_formatProperties(properties, compact: true)}', indent: 6); diff --git a/pubspec.yaml b/pubspec.yaml index 90f1791..3bcdf39 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,10 +1,10 @@ name: flex_track description: A flexible analytics tracking system for Flutter with intelligent routing, GDPR compliance, and multi-platform support -version: 1.0.1 # Use semantic versioning -homepage: https://github.com/alirezat66/flex_track +version: 2.0.0 +homepage: https://flextrack.taghizadeh.dev/ repository: https://github.com/alirezat66/flex_track issue_tracker: https://github.com/alirezat66/flex_track/issues -documentation: https://alirezat66.github.io/flex_track/ +documentation: https://flextrack.taghizadeh.dev/ topics: - analytics @@ -41,5 +41,3 @@ dev_dependencies: build_runner: ^2.0.0 # Add build_runner for mock generation flutter: {} - - diff --git a/test/core/event_processor_test.dart b/test/core/event_processor_test.dart index 2b4068d..72aac43 100644 --- a/test/core/event_processor_test.dart +++ b/test/core/event_processor_test.dart @@ -223,7 +223,7 @@ void main() { final stringResult = result.toString(); expect(stringResult, contains('EventProcessingResult')); - expect(stringResult, contains(event.getName())); + expect(stringResult, contains(event.name)); expect(stringResult, contains('routed: true')); expect(stringResult, contains('tracked: true')); expect(stringResult, contains('successful: 1/1')); @@ -302,10 +302,10 @@ class _TestEvent extends BaseEvent { _TestEvent(this.eventName); @override - String getName() => eventName; + String get name => eventName; @override - Map? getProperties() => {'test': 'value'}; + Map? get properties => {'test': 'value'}; } class _NonTrackerExceptionTracker extends BaseTrackerStrategy { @@ -339,7 +339,7 @@ class _TrackerExceptionTracker extends BaseTrackerStrategy { throw TrackerException( 'Custom tracker error', trackerId: id, - eventName: event.getName(), + eventName: event.name, ); } } diff --git a/test/core/event_processor_transformer_test.dart b/test/core/event_processor_transformer_test.dart index 477a333..e579066 100644 --- a/test/core/event_processor_transformer_test.dart +++ b/test/core/event_processor_transformer_test.dart @@ -38,7 +38,7 @@ void main() { await eventProcessor.processEvent(event); final captured = mockTracker.capturedEvents.single; - expect(captured.getProperties()!['route'], '/home'); + expect(captured.properties!['route'], '/home'); }); test('multiple transformers are applied in registration order', () async { @@ -56,8 +56,8 @@ void main() { expect(order, [1, 2]); final captured = mockTracker.capturedEvents.single; - expect(captured.getProperties()!['step1'], 'a'); - expect(captured.getProperties()!['step2'], 'b'); + expect(captured.properties!['step1'], 'a'); + expect(captured.properties!['step2'], 'b'); }); test('throwing transformer is skipped and pipeline completes', () async { @@ -70,7 +70,7 @@ void main() { expect(result.successful, isTrue); final captured = mockTracker.capturedEvents.single; - expect(captured.getProperties()!['after_throw'], 'yes'); + expect(captured.properties!['after_throw'], 'yes'); }); test('EventProcessingResult.event is the enriched event', () async { @@ -82,7 +82,7 @@ void main() { await eventProcessor.processEvent(CustomEvent.named('test')); expect(result.event, isA()); - expect(result.event.getProperties()!['enriched'], true); + expect(result.event.properties!['enriched'], true); }); test('disabled processor returns early without applying transformers', @@ -114,7 +114,7 @@ void main() { await eventProcessor.processEvent(CustomEvent.named('test')); final captured = mockTracker.capturedEvents.single; - expect(captured.getProperties()?.containsKey('route'), isNot(true)); + expect(captured.properties?.containsKey('route'), isNot(true)); }); test('removeTransformer removes only the specified transformer', () async { @@ -127,7 +127,7 @@ void main() { await eventProcessor.processEvent(CustomEvent.named('test')); - final props = mockTracker.capturedEvents.single.getProperties()!; + final props = mockTracker.capturedEvents.single.properties!; expect(props.containsKey('t1'), isFalse); expect(props['t2'], 'yes'); }); diff --git a/test/core/flex_track_client_test.dart b/test/core/flex_track_client_test.dart index c4f13e5..daf64df 100644 --- a/test/core/flex_track_client_test.dart +++ b/test/core/flex_track_client_test.dart @@ -241,7 +241,7 @@ void main() { ]); expect( - mock.capturedEvents.map((e) => e.getName()).toList(), + mock.capturedEvents.map((e) => e.name).toList(), ['first', 'second', 'third'], ); @@ -262,7 +262,7 @@ void main() { expect(mock.capturedEvents, hasLength(2)); expect( - mock.capturedEvents.map((e) => e.getName()).toSet(), + mock.capturedEvents.map((e) => e.name).toSet(), {'a', 'b'}, ); @@ -379,10 +379,10 @@ Future _clientWithRelaxedRouting( class _TestEvent extends BaseEvent { @override - String getName() => 'test_event'; + String get name => 'test_event'; @override - Map? getProperties() => const {}; + Map? get properties => const {}; } class _NamedTestEvent extends BaseEvent { @@ -391,10 +391,10 @@ class _NamedTestEvent extends BaseEvent { final String _name; @override - String getName() => _name; + String get name => _name; @override - Map? getProperties() => const {}; + Map? get properties => const {}; } class _BrokenInitTracker extends NoOpTracker { diff --git a/test/core/flex_track_client_transformer_test.dart b/test/core/flex_track_client_transformer_test.dart index f9298cf..955b310 100644 --- a/test/core/flex_track_client_transformer_test.dart +++ b/test/core/flex_track_client_transformer_test.dart @@ -22,7 +22,7 @@ void main() { client.addTransformer((e) => EnrichedEvent(e, {'route': '/home'})); await client.track(CustomEvent.named('tap')); - expect(mock.capturedEvents.single.getProperties()!['route'], '/home'); + expect(mock.capturedEvents.single.properties!['route'], '/home'); await client.dispose(); }); @@ -38,7 +38,7 @@ void main() { await client.track(CustomEvent.named('tap')); - final props = mock.capturedEvents.single.getProperties()!; + final props = mock.capturedEvents.single.properties!; expect(props.containsKey('t1'), isFalse); expect(props['t2'], 'yes'); await client.dispose(); @@ -52,7 +52,7 @@ void main() { await client.track(CustomEvent.named('tap')); - expect(mock.capturedEvents.single.getProperties()?.containsKey('route'), + expect(mock.capturedEvents.single.properties?.containsKey('route'), isNot(true)); await client.dispose(); }); @@ -66,8 +66,8 @@ void main() { await client1.track(CustomEvent.named('e1')); await client2.track(CustomEvent.named('e2')); - expect(mock1.capturedEvents.single.getProperties()!['client'], '1'); - expect(mock2.capturedEvents.single.getProperties()?.containsKey('client'), + expect(mock1.capturedEvents.single.properties!['client'], '1'); + expect(mock2.capturedEvents.single.properties?.containsKey('client'), isNot(true)); await client1.dispose(); diff --git a/test/core/flex_track_facade_test.dart b/test/core/flex_track_facade_test.dart index 7b8b93b..adc68f1 100644 --- a/test/core/flex_track_facade_test.dart +++ b/test/core/flex_track_facade_test.dart @@ -45,7 +45,7 @@ void main() { await FlexTrack.track(_FacadeTestEvent('e2')); expect(second.capturedEvents, hasLength(1)); - expect(second.capturedEvents.single.getName(), 'e2'); + expect(second.capturedEvents.single.name, 'e2'); }, ); @@ -59,7 +59,7 @@ void main() { await FlexTrack.instance.client.track(_FacadeTestEvent('via_client')); expect( - mock.capturedEvents.map((e) => e.getName()).toList(), + mock.capturedEvents.map((e) => e.name).toList(), ['via_static', 'via_client'], ); }, @@ -73,8 +73,8 @@ class _FacadeTestEvent extends BaseEvent { final String _name; @override - String getName() => _name; + String get name => _name; @override - Map? getProperties() => const {}; + Map? get properties => const {}; } diff --git a/test/core/flex_track_test.dart b/test/core/flex_track_test.dart index e8f0e98..9ea0594 100644 --- a/test/core/flex_track_test.dart +++ b/test/core/flex_track_test.dart @@ -8,10 +8,10 @@ class TestEvent extends BaseEvent { TestEvent({required this.testProperty}); @override - String getName() => 'test_event'; + String get name => 'test_event'; @override - Map getProperties() => {'test_property': testProperty}; + Map get properties => {'test_property': testProperty}; } class PurchaseTestEvent extends BaseEvent { @@ -20,10 +20,10 @@ class PurchaseTestEvent extends BaseEvent { PurchaseTestEvent({required this.amount}); @override - String getName() => 'purchase'; + String get name => 'purchase'; @override - Map getProperties() => {'amount': amount}; + Map get properties => {'amount': amount}; @override EventCategory get category => EventCategory.business; @@ -34,10 +34,10 @@ class PurchaseTestEvent extends BaseEvent { class DebugTestEvent extends BaseEvent { @override - String getName() => 'debug_test'; + String get name => 'debug_test'; @override - Map? getProperties() => null; + Map? get properties => null; @override EventCategory get category => EventCategory.technical; @@ -49,10 +49,10 @@ class PIITestEvent extends BaseEvent { PIITestEvent({required this.email}); @override - String getName() => 'user_data'; + String get name => 'user_data'; @override - Map getProperties() => {'email': email}; + Map get properties => {'email': email}; @override bool get containsPII => true; @@ -63,10 +63,10 @@ class PIITestEvent extends BaseEvent { class EssentialTestEvent extends BaseEvent { @override - String getName() => 'system_essential'; + String get name => 'system_essential'; @override - Map? getProperties() => null; + Map? get properties => null; @override bool get isEssential => true; @@ -123,8 +123,7 @@ void main() { expect(mockTracker1.capturedEvents, hasLength(1)); expect(mockTracker2.capturedEvents, hasLength(1)); - expect( - mockTracker1.capturedEvents.first.getName(), equals('test_event')); + expect(mockTracker1.capturedEvents.first.name, equals('test_event')); }); test('should track multiple events', () async { diff --git a/test/core/flex_track_transformer_test.dart b/test/core/flex_track_transformer_test.dart index d4990bd..8d42069 100644 --- a/test/core/flex_track_transformer_test.dart +++ b/test/core/flex_track_transformer_test.dart @@ -25,7 +25,7 @@ void main() { FlexTrack.addTransformer((e) => EnrichedEvent(e, {'route': '/test'})); await FlexTrack.track(CustomEvent.named('tap')); - expect(mock.capturedEvents.single.getProperties()!['route'], '/test'); + expect(mock.capturedEvents.single.properties!['route'], '/test'); }); test('removeTransformer stops enrichment', () async { @@ -38,7 +38,7 @@ void main() { await FlexTrack.track(CustomEvent.named('tap')); expect( - mock.capturedEvents.single.getProperties()?.containsKey('route'), + mock.capturedEvents.single.properties?.containsKey('route'), isNot(true), ); }); @@ -50,7 +50,7 @@ void main() { await FlexTrack.track(CustomEvent.named('tap')); - final props = mock.capturedEvents.single.getProperties(); + final props = mock.capturedEvents.single.properties; expect(props?.containsKey('a'), isNot(true)); expect(props?.containsKey('b'), isNot(true)); }); diff --git a/test/core/tracker_registry_test.dart b/test/core/tracker_registry_test.dart index 68db255..2afc051 100644 --- a/test/core/tracker_registry_test.dart +++ b/test/core/tracker_registry_test.dart @@ -392,8 +392,8 @@ void main() { class FakeBaseEvent extends Fake implements BaseEvent { @override - String getName() => 'FakeEvent'; + String get name => 'FakeEvent'; @override - Map? getProperties() => {}; + Map? get properties => {}; } diff --git a/test/inspector/inspector_event_buffer_test.dart b/test/inspector/inspector_event_buffer_test.dart index d1857f7..8015254 100644 --- a/test/inspector/inspector_event_buffer_test.dart +++ b/test/inspector/inspector_event_buffer_test.dart @@ -11,10 +11,10 @@ class _BufEvent extends BaseEvent { final EventCategory? cat; @override - String getName() => _name; + String get name => _name; @override - Map? getProperties() => {'n': 1}; + Map? get properties => {'n': 1}; @override EventCategory? get category => cat; diff --git a/test/models/event/base_event_test.dart b/test/models/event/base_event_test.dart new file mode 100644 index 0000000..71b33f8 --- /dev/null +++ b/test/models/event/base_event_test.dart @@ -0,0 +1,30 @@ +import 'package:flex_track/src/models/event/base_event.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('BaseEvent API', () { + test('name and properties getters are the preferred API', () { + final event = _SampleEvent(); + + expect(event.name, 'sample'); + expect(event.properties, {'key': 'value'}); + }); + + test('deprecated getName/getProperties still work for callers', () { + final event = _SampleEvent(); + + // ignore: deprecated_member_use_from_same_package + expect(event.name, event.name); + // ignore: deprecated_member_use_from_same_package + expect(event.properties, event.properties); + }); + }); +} + +class _SampleEvent extends BaseEvent { + @override + String get name => 'sample'; + + @override + Map? get properties => const {'key': 'value'}; +} diff --git a/test/models/event/enriched_event_test.dart b/test/models/event/enriched_event_test.dart index 5d0c6cb..45daf9d 100644 --- a/test/models/event/enriched_event_test.dart +++ b/test/models/event/enriched_event_test.dart @@ -23,25 +23,25 @@ void main() { test('forwards getName from original', () { final enriched = EnrichedEvent(original, {}); - expect(enriched.getName(), 'test_event'); + expect(enriched.name, 'test_event'); }); test('returns only extra properties when original has none', () { final bare = CustomEvent.named('bare'); final enriched = EnrichedEvent(bare, {'route': '/home'}); - expect(enriched.getProperties(), {'route': '/home'}); + expect(enriched.properties, {'route': '/home'}); }); test('merges original and extra properties', () { final enriched = EnrichedEvent(original, {'extra_key': 'extra_value'}); - final props = enriched.getProperties(); + final props = enriched.properties; expect(props['original_key'], 'original_value'); expect(props['extra_key'], 'extra_value'); }); test('extra properties take precedence over original on key collision', () { final enriched = EnrichedEvent(original, {'shared_key': 'enriched'}); - expect(enriched.getProperties()['shared_key'], 'enriched'); + expect(enriched.properties['shared_key'], 'enriched'); }); test('forwards category from original', () { @@ -108,7 +108,7 @@ void main() { test('stacking EnrichedEvents layers properties correctly', () { final first = EnrichedEvent(original, {'layer1': 'a'}); final second = EnrichedEvent(first, {'layer2': 'b', 'shared_key': 'top'}); - final props = second.getProperties(); + final props = second.properties; expect(props['original_key'], 'original_value'); expect(props['layer1'], 'a'); expect(props['layer2'], 'b'); @@ -122,10 +122,10 @@ class _FixedTimestampEvent extends BaseEvent { _FixedTimestampEvent(this._timestamp); @override - String getName() => 'fixed'; + String get name => 'fixed'; @override - Map? getProperties() => null; + Map? get properties => null; @override DateTime get timestamp => _timestamp; diff --git a/test/models/event/event_transformer_test.dart b/test/models/event/event_transformer_test.dart index 152403e..f3acde0 100644 --- a/test/models/event/event_transformer_test.dart +++ b/test/models/event/event_transformer_test.dart @@ -14,7 +14,7 @@ void main() { final result = transformer(event); expect(result, isA()); - expect(result.getProperties()!['added'], 'yes'); + expect(result.properties!['added'], 'yes'); }); test('passes event through unchanged when condition is false', () { diff --git a/test/models/routing/routing_config_test.dart b/test/models/routing/routing_config_test.dart index 756b69a..db561ae 100644 --- a/test/models/routing/routing_config_test.dart +++ b/test/models/routing/routing_config_test.dart @@ -60,7 +60,7 @@ void main() { id: 'rule3', priority: 15, targetGroup: TrackerGroup.all); final config = RoutingConfiguration(rules: [rule1, rule2, rule3]); final event = MockBaseEvent(); - when(event.getName()).thenReturn('test_event'); + when(event.name).thenReturn('test_event'); final matchingRules = config.getMatchingRules(event); expect(matchingRules, @@ -74,7 +74,7 @@ void main() { id: 'default', isDefault: true, targetGroup: TrackerGroup.all); final config = RoutingConfiguration(rules: [defaultRule]); final event = MockBaseEvent(); - when(event.getName()).thenReturn('non_matching_event'); + when(event.name).thenReturn('non_matching_event'); final matchingRules = config.getMatchingRules(event); expect(matchingRules, [defaultRule]); @@ -86,7 +86,7 @@ void main() { final config = RoutingConfiguration(rules: [], defaultGroup: TrackerGroup.all); final event = MockBaseEvent(); - when(event.getName()).thenReturn('non_matching_event'); + when(event.name).thenReturn('non_matching_event'); final matchingRules = config.getMatchingRules(event); expect(matchingRules.length, 1); @@ -100,7 +100,7 @@ void main() { () { final config = RoutingConfiguration.empty(); final event = MockBaseEvent(); - when(event.getName()).thenReturn('non_matching_event'); + when(event.name).thenReturn('non_matching_event'); expect(config.getMatchingRules(event), isEmpty); }); @@ -112,7 +112,7 @@ void main() { final config = RoutingConfiguration( rules: [debugRule, normalRule], isDebugMode: false); final event = MockBaseEvent(); - when(event.getName()).thenReturn('test_event'); + when(event.name).thenReturn('test_event'); final matchingRules = config.getMatchingRules(event); expect(matchingRules, contains(normalRule)); @@ -127,7 +127,7 @@ void main() { final config = RoutingConfiguration( rules: [debugRule, normalRule], isDebugMode: true); final event = MockBaseEvent(); - when(event.getName()).thenReturn('test_event'); + when(event.name).thenReturn('test_event'); final matchingRules = config.getMatchingRules(event); expect(matchingRules, contains(normalRule)); @@ -143,7 +143,7 @@ void main() { id: 'rule2', priority: 5, targetGroup: TrackerGroup.all); final config = RoutingConfiguration(rules: [rule1, rule2]); final event = MockBaseEvent(); - when(event.getName()).thenReturn('test_event'); + when(event.name).thenReturn('test_event'); expect(config.getPrimaryRule(event), rule1); }); @@ -151,7 +151,7 @@ void main() { test('should return null if no rules match', () { final config = RoutingConfiguration.empty(); final event = MockBaseEvent(); - when(event.getName()).thenReturn('test_event'); + when(event.name).thenReturn('test_event'); expect(config.getPrimaryRule(event), isNull); }); }); @@ -172,7 +172,7 @@ void main() { requirePIIConsent: true); final config = RoutingConfiguration(rules: [rule1, rule2, rule3]); final event = MockBaseEvent(); - when(event.getName()).thenReturn('test_event'); + when(event.name).thenReturn('test_event'); when(event.isEssential).thenReturn(false); when(event.requiresConsent).thenReturn(true); when(event.containsPII).thenReturn(true); @@ -218,7 +218,7 @@ void main() { id: 'rule2', priority: 5, targetGroup: TrackerGroup.development); final config = RoutingConfiguration(rules: [rule1, rule2]); final event = MockBaseEvent(); - when(event.getName()).thenReturn('test_event'); + when(event.name).thenReturn('test_event'); when(event.isEssential).thenReturn(false); when(event.requiresConsent).thenReturn(true); when(event.containsPII).thenReturn(false); @@ -235,7 +235,7 @@ void main() { id: 'rule2', priority: 10, targetGroup: TrackerGroup.development); final config = RoutingConfiguration(rules: [rule1, rule2]); final event = MockBaseEvent(); - when(event.getName()).thenReturn('test_event'); + when(event.name).thenReturn('test_event'); when(event.isEssential).thenReturn(false); when(event.requiresConsent).thenReturn(true); when(event.containsPII).thenReturn(false); diff --git a/test/models/routing/routing_config_test.mocks.dart b/test/models/routing/routing_config_test.mocks.dart index 5a5f32c..52c4a7d 100644 --- a/test/models/routing/routing_config_test.mocks.dart +++ b/test/models/routing/routing_config_test.mocks.dart @@ -73,7 +73,7 @@ class MockBaseEvent extends _i1.Mock implements _i2.BaseEvent { ) as DateTime); @override - String getName() => (super.noSuchMethod( + String get name => (super.noSuchMethod( Invocation.method( #getName, [], diff --git a/test/routing/example_analytics_mirror_routing_test.dart b/test/routing/example_analytics_mirror_routing_test.dart index a6269ec..74274e0 100644 --- a/test/routing/example_analytics_mirror_routing_test.dart +++ b/test/routing/example_analytics_mirror_routing_test.dart @@ -11,10 +11,10 @@ import 'package:flutter_test/flutter_test.dart'; class _DemoFreeTier extends BaseEvent { @override - String getName() => 'demo_free_tier_only'; + String get name => 'demo_free_tier_only'; @override - Map? getProperties() => const {'note': 'x'}; + Map? get properties => const {'note': 'x'}; @override bool get requiresConsent => false; @@ -22,10 +22,10 @@ class _DemoFreeTier extends BaseEvent { class _DemoBanner extends BaseEvent { @override - String getName() => 'demo_banner_impression'; + String get name => 'demo_banner_impression'; @override - Map? getProperties() => const {'slot_id': '1'}; + Map? get properties => const {'slot_id': '1'}; @override EventCategory get category => EventCategory.user; diff --git a/test/routing/presets/smart_defaults_test.dart b/test/routing/presets/smart_defaults_test.dart index 7313c28..0a1eb18 100644 --- a/test/routing/presets/smart_defaults_test.dart +++ b/test/routing/presets/smart_defaults_test.dart @@ -590,15 +590,15 @@ void main() { class TestEvent extends BaseEvent { final String eventName; final EventCategory? eventCategory; - final Map? properties; + final Map? _properties; - TestEvent(this.eventName, [this.eventCategory, this.properties]); + TestEvent(this.eventName, [this.eventCategory, this._properties]); @override - String getName() => eventName; + String get name => eventName; @override - Map? getProperties() => properties; + Map? get properties => _properties; @override EventCategory? get category => eventCategory; @@ -610,10 +610,10 @@ class HighVolumeTestEvent extends BaseEvent { HighVolumeTestEvent(this.eventName); @override - String getName() => eventName; + String get name => eventName; @override - Map? getProperties() => null; + Map? get properties => null; @override bool get isHighVolume => true; @@ -625,10 +625,10 @@ class EssentialTestEvent extends BaseEvent { EssentialTestEvent(this.eventName); @override - String getName() => eventName; + String get name => eventName; @override - Map? getProperties() => null; + Map? get properties => null; @override bool get isEssential => true; diff --git a/test/routing/route_config_builder_test.dart b/test/routing/route_config_builder_test.dart index 322c4d7..31db35a 100644 --- a/test/routing/route_config_builder_test.dart +++ b/test/routing/route_config_builder_test.dart @@ -568,10 +568,10 @@ class TestEvent extends BaseEvent { TestEvent(this.eventName); @override - String getName() => eventName; + String get name => eventName; @override - Map? getProperties() => null; + Map? get properties => null; } class BusinessEvent extends BaseEvent { @@ -581,10 +581,10 @@ class BusinessEvent extends BaseEvent { BusinessEvent(this.eventName, this.revenue); @override - String getName() => eventName; + String get name => eventName; @override - Map getProperties() => {'revenue': revenue}; + Map get properties => {'revenue': revenue}; @override EventCategory get category => EventCategory.business; diff --git a/test/routing/routing_builder_test.dart b/test/routing/routing_builder_test.dart index ad9c9ff..711dd18 100644 --- a/test/routing/routing_builder_test.dart +++ b/test/routing/routing_builder_test.dart @@ -797,8 +797,8 @@ class TestEvent extends BaseEvent { TestEvent(this.eventName); @override - String getName() => eventName; + String get name => eventName; @override - Map? getProperties() => null; + Map? get properties => null; } diff --git a/test/routing/routing_engine_test.dart b/test/routing/routing_engine_test.dart index 797285f..2de741f 100644 --- a/test/routing/routing_engine_test.dart +++ b/test/routing/routing_engine_test.dart @@ -1384,15 +1384,15 @@ void main() { // Test Event Classes class TestEvent extends BaseEvent { final String eventName; - final Map? properties; + final Map? _properties; - TestEvent(this.eventName, [this.properties]); + TestEvent(this.eventName, [this._properties]); @override - String getName() => eventName; + String get name => eventName; @override - Map? getProperties() => properties; + Map? get properties => _properties; } class BusinessTestEvent extends BaseEvent { @@ -1402,10 +1402,10 @@ class BusinessTestEvent extends BaseEvent { BusinessTestEvent(this.eventName, this.amount); @override - String getName() => eventName; + String get name => eventName; @override - Map getProperties() => {'amount': amount}; + Map get properties => {'amount': amount}; @override EventCategory get category => EventCategory.business; @@ -1420,10 +1420,10 @@ class DebugTestEvent extends BaseEvent { DebugTestEvent(this.eventName); @override - String getName() => eventName; + String get name => eventName; @override - Map? getProperties() => null; + Map? get properties => null; @override EventCategory get category => EventCategory.technical; @@ -1436,10 +1436,10 @@ class PIITestEvent extends BaseEvent { PIITestEvent(this.eventName, this.email); @override - String getName() => eventName; + String get name => eventName; @override - Map getProperties() => {'email': email}; + Map get properties => {'email': email}; @override bool get containsPII => true; @@ -1454,10 +1454,10 @@ class EssentialTestEvent extends BaseEvent { EssentialTestEvent(this.eventName); @override - String getName() => eventName; + String get name => eventName; @override - Map? getProperties() => null; + Map? get properties => null; @override bool get isEssential => true; @@ -1472,10 +1472,10 @@ class HighVolumeTestEvent extends BaseEvent { HighVolumeTestEvent(this.eventName); @override - String getName() => eventName; + String get name => eventName; @override - Map? getProperties() => null; + Map? get properties => null; @override bool get isHighVolume => true; @@ -1488,10 +1488,10 @@ class MarketingTestEvent extends BaseEvent { MarketingTestEvent(this.eventName, this.campaign); @override - String getName() => eventName; + String get name => eventName; @override - Map getProperties() => {'campaign': campaign}; + Map get properties => {'campaign': campaign}; @override EventCategory get category => EventCategory.marketing; @@ -1503,10 +1503,10 @@ class SystemTestEvent extends BaseEvent { SystemTestEvent(this.eventName); @override - String getName() => eventName; + String get name => eventName; @override - Map? getProperties() => null; + Map? get properties => null; @override EventCategory get category => EventCategory.system; @@ -1521,10 +1521,10 @@ class SecurityTestEvent extends BaseEvent { SecurityTestEvent(this.eventName); @override - String getName() => eventName; + String get name => eventName; @override - Map? getProperties() => null; + Map? get properties => null; @override EventCategory get category => EventCategory.security; @@ -1544,10 +1544,10 @@ class PropertyTestEvent extends BaseEvent { PropertyTestEvent(this.eventName, this.eventProperties); @override - String getName() => eventName; + String get name => eventName; @override - Map getProperties() => eventProperties; + Map get properties => eventProperties; @override bool get containsPII => mockContainsPII; @@ -1560,10 +1560,10 @@ class CustomCategoryTestEvent extends BaseEvent { CustomCategoryTestEvent(this.eventName, this._category); @override - String getName() => eventName; + String get name => eventName; @override - Map? getProperties() => null; + Map? get properties => null; @override EventCategory get category => _category; diff --git a/test/routing/routing_rule_builder_test.dart b/test/routing/routing_rule_builder_test.dart index 19f7c85..a5ef651 100644 --- a/test/routing/routing_rule_builder_test.dart +++ b/test/routing/routing_rule_builder_test.dart @@ -687,8 +687,8 @@ class TestEvent extends BaseEvent { TestEvent(this.eventName); @override - String getName() => eventName; + String get name => eventName; @override - Map? getProperties() => null; + Map? get properties => null; } diff --git a/test/strategies/base_tracker_strategy_test.dart b/test/strategies/base_tracker_strategy_test.dart index d679d1f..27e4d78 100644 --- a/test/strategies/base_tracker_strategy_test.dart +++ b/test/strategies/base_tracker_strategy_test.dart @@ -106,7 +106,7 @@ void main() { setUp(() { tracker = TestTrackerStrategy(id: 'testId', name: 'Test Tracker'); mockEvent = MockBaseEvent(); - when(mockEvent.getName()).thenReturn('testEvent'); + when(mockEvent.name).thenReturn('testEvent'); }); test('constructor sets id, name, and enabled status correctly', () { @@ -216,8 +216,8 @@ void main() { setUp(() async { mockEvents = [MockBaseEvent(), MockBaseEvent()]; - when(mockEvents[0].getName()).thenReturn('event1'); - when(mockEvents[1].getName()).thenReturn('event2'); + when(mockEvents[0].name).thenReturn('event1'); + when(mockEvents[1].name).thenReturn('event2'); await tracker.initialize(); }); diff --git a/test/strategies/base_tracker_strategy_test.mocks.dart b/test/strategies/base_tracker_strategy_test.mocks.dart index 188b4c2..ae3a5a2 100644 --- a/test/strategies/base_tracker_strategy_test.mocks.dart +++ b/test/strategies/base_tracker_strategy_test.mocks.dart @@ -73,7 +73,7 @@ class MockBaseEvent extends _i1.Mock implements _i2.BaseEvent { ) as DateTime); @override - String getName() => (super.noSuchMethod( + String get name => (super.noSuchMethod( Invocation.method( #getName, [], diff --git a/test/strategies/console_tracker_test.dart b/test/strategies/console_tracker_test.dart index 3a6b19c..8f568f2 100644 --- a/test/strategies/console_tracker_test.dart +++ b/test/strategies/console_tracker_test.dart @@ -18,7 +18,7 @@ void main() { await tracker.initialize(); await tracker.track(_ConsoleTestEvent('hello')); expect(tracker.eventHistory, hasLength(1)); - expect(tracker.eventHistory.single.getName(), 'hello'); + expect(tracker.eventHistory.single.name, 'hello'); }); test('track includes category, user, and session in log output path', @@ -35,7 +35,7 @@ void main() { test('logs non-empty properties when showProperties is true', () async { await tracker.initialize(); await tracker.track(_ConsoleTestEvent('x', props: {'k': 1})); - expect(tracker.eventHistory.single.getProperties(), isNotEmpty); + expect(tracker.eventHistory.single.properties, isNotEmpty); }); test('skips property lines when showProperties is false', () async { @@ -64,7 +64,7 @@ void main() { ]); expect(tracker.eventHistory, hasLength(2)); expect( - tracker.eventHistory.map((e) => e.getName()).toList(), + tracker.eventHistory.map((e) => e.name).toList(), ['one', 'two'], ); }); @@ -113,7 +113,7 @@ void main() { 'many_props', props: {'a': 1, 'b': 2, 'c': 3, 'd': 4}, )); - expect(t.eventHistory.single.getProperties()!.length, 4); + expect(t.eventHistory.single.properties!.length, 4); }); }); } @@ -125,15 +125,15 @@ class _ConsoleTestEvent extends BaseEvent { final Map? props; @override - String getName() => _name; + String get name => _name; @override - Map? getProperties() => props; + Map? get properties => props; } class _RichEvent extends BaseEvent { @override - String getName() => 'rich'; + String get name => 'rich'; @override EventCategory? get category => EventCategory.user; @@ -145,12 +145,12 @@ class _RichEvent extends BaseEvent { String? get sessionId => 's1'; @override - Map? getProperties() => const {'x': 1}; + Map? get properties => const {'x': 1}; } class _FlaggedEvent extends BaseEvent { @override - String getName() => 'flagged'; + String get name => 'flagged'; @override bool get containsPII => true; @@ -165,5 +165,5 @@ class _FlaggedEvent extends BaseEvent { bool get requiresConsent => false; @override - Map? getProperties() => const {}; + Map? get properties => const {}; } diff --git a/test/strategies/tracker_strategy_test.dart b/test/strategies/tracker_strategy_test.dart index c0f380d..8c2ffc4 100644 --- a/test/strategies/tracker_strategy_test.dart +++ b/test/strategies/tracker_strategy_test.dart @@ -90,7 +90,7 @@ class _BareTracker extends TrackerStrategy { @override Future track(BaseEvent event) async { - trackedNames.add(event.getName()); + trackedNames.add(event.name); } @override @@ -110,8 +110,8 @@ class _NamedEvent extends BaseEvent { final String _name; @override - String getName() => _name; + String get name => _name; @override - Map? getProperties() => const {}; + Map? get properties => const {}; } diff --git a/test/test_utils/mock_events.dart b/test/test_utils/mock_events.dart index 8570e78..e6fbfeb 100644 --- a/test/test_utils/mock_events.dart +++ b/test/test_utils/mock_events.dart @@ -41,12 +41,12 @@ class CustomEvent extends BaseEvent { } @override - String getName() => _name; + String get name => _name; @override @override @override - Map? getProperties() => _properties?.cast(); + Map? get properties => _properties?.cast(); @override EventCategory? get category => _category; diff --git a/test/widgets/flex_click_track_test.dart b/test/widgets/flex_click_track_test.dart index feb7522..50c1e45 100644 --- a/test/widgets/flex_click_track_test.dart +++ b/test/widgets/flex_click_track_test.dart @@ -34,7 +34,7 @@ void main() { await tester.tap(find.text('Go')); await tester.pump(); - expect(mock.capturedEvents.single.getName(), 'cta_tap'); + expect(mock.capturedEvents.single.name, 'cta_tap'); }); testWidgets('sends event when child is plain Text (tap on text)', @@ -55,7 +55,7 @@ void main() { await tester.tap(find.text('Tap me')); await tester.pump(); - expect(mock.capturedEvents.single.getName(), 'label_tap'); + expect(mock.capturedEvents.single.name, 'label_tap'); }); testWidgets( @@ -83,7 +83,7 @@ void main() { expect(buttonPressed, isTrue, reason: 'Material button must still receive the tap'); - expect(mock.capturedEvents.single.getName(), 'button_wrap'); + expect(mock.capturedEvents.single.name, 'button_wrap'); }); testWidgets( @@ -115,7 +115,7 @@ void main() { await tester.pump(); expect(buttonPressed, isTrue); - expect(mock.capturedEvents.single.getName(), 'nested_container'); + expect(mock.capturedEvents.single.name, 'nested_container'); }); testWidgets( @@ -152,7 +152,7 @@ void main() { expect(buttonPressed, isFalse, reason: 'tap should not hit the ElevatedButton'); - expect(mock.capturedEvents.single.getName(), 'padding_area'); + expect(mock.capturedEvents.single.name, 'padding_area'); }); testWidgets('does NOT track on scroll/drag over widget', (tester) async { @@ -207,7 +207,7 @@ void main() { await tester.tap(find.text('Scoped')); await tester.pump(); - expect(mock.capturedEvents.single.getName(), 'scoped_only'); + expect(mock.capturedEvents.single.name, 'scoped_only'); }); testWidgets('scoped client is preferred when global is also set up', @@ -236,7 +236,7 @@ void main() { await tester.tap(find.text('Tap')); await tester.pump(); - expect(scopedMock.capturedEvents.single.getName(), 'scoped_wins'); + expect(scopedMock.capturedEvents.single.name, 'scoped_wins'); expect(globalMock.capturedEvents, isEmpty); }); diff --git a/test/widgets/flex_impression_track_test.dart b/test/widgets/flex_impression_track_test.dart index 30d8bad..c734ae3 100644 --- a/test/widgets/flex_impression_track_test.dart +++ b/test/widgets/flex_impression_track_test.dart @@ -47,7 +47,7 @@ void main() { expect(mock.capturedEvents, isNotEmpty); expect( - mock.capturedEvents.map((e) => e.getName()), + mock.capturedEvents.map((e) => e.name), contains('banner_impression'), ); }); @@ -84,7 +84,7 @@ void main() { await tester.pump(const Duration(milliseconds: 350)); await tester.pump(); - expect(mock.capturedEvents.single.getName(), 'delayed_impression'); + expect(mock.capturedEvents.single.name, 'delayed_impression'); }); testWidgets('fires only once even if visibility updates multiple times', @@ -116,7 +116,7 @@ void main() { } expect(mock.capturedEvents, hasLength(1)); - expect(mock.capturedEvents.single.getName(), 'once_only'); + expect(mock.capturedEvents.single.name, 'once_only'); }); testWidgets('does NOT fire when visibility stays below threshold', @@ -238,7 +238,7 @@ void main() { VisibilityDetectorController.instance.notifyNow(); await tester.pump(); - expect(mock.capturedEvents.single.getName(), 'scoped_impression'); + expect(mock.capturedEvents.single.name, 'scoped_impression'); }); testWidgets('scoped client is preferred when global is also set up', @@ -274,8 +274,7 @@ void main() { VisibilityDetectorController.instance.notifyNow(); await tester.pump(); - expect( - scopedMock.capturedEvents.single.getName(), 'impression_scoped_wins'); + expect(scopedMock.capturedEvents.single.name, 'impression_scoped_wins'); expect(globalMock.capturedEvents, isEmpty); }); diff --git a/test/widgets/flex_mount_track_test.dart b/test/widgets/flex_mount_track_test.dart index 8541cad..ca72130 100644 --- a/test/widgets/flex_mount_track_test.dart +++ b/test/widgets/flex_mount_track_test.dart @@ -25,7 +25,7 @@ void main() { ); await tester.pump(); - expect(mock.capturedEvents.single.getName(), 'mounted_view'); + expect(mock.capturedEvents.single.name, 'mounted_view'); await tester.pump(); expect(mock.capturedEvents, hasLength(1)); @@ -42,7 +42,7 @@ void main() { ); await tester.pump(); - expect(mock.capturedEvents.single.getName(), 'mount_first'); + expect(mock.capturedEvents.single.name, 'mount_first'); await tester.tap(find.text('toggle off')); await tester.pump(); @@ -51,7 +51,7 @@ void main() { await tester.pump(); expect(mock.capturedEvents, hasLength(2)); - expect(mock.capturedEvents.map((e) => e.getName()).toList(), + expect(mock.capturedEvents.map((e) => e.name).toList(), ['mount_first', 'mount_first']); }); @@ -99,7 +99,7 @@ void main() { await tester.pumpAndSettle(); expect(mock.capturedEvents, hasLength(1)); - expect(mock.capturedEvents.single.getName(), 'lazy_mount'); + expect(mock.capturedEvents.single.name, 'lazy_mount'); }); testWidgets('uses FlexTrackScope client without FlexTrack.setup', @@ -125,7 +125,7 @@ void main() { ); await tester.pump(); - expect(mock.capturedEvents.single.getName(), 'scoped_mount'); + expect(mock.capturedEvents.single.name, 'scoped_mount'); }); testWidgets('scoped client is preferred when global is also set up', @@ -152,7 +152,7 @@ void main() { ); await tester.pump(); - expect(scopedMock.capturedEvents.single.getName(), 'mount_scoped_wins'); + expect(scopedMock.capturedEvents.single.name, 'mount_scoped_wins'); expect(globalMock.capturedEvents, isEmpty); }); diff --git a/test/widgets/flex_route_track_test.dart b/test/widgets/flex_route_track_test.dart index 220e552..b96a12c 100644 --- a/test/widgets/flex_route_track_test.dart +++ b/test/widgets/flex_route_track_test.dart @@ -183,7 +183,7 @@ void main() { ); await tester.pump(); - expect(mock.capturedEvents.single.getName(), 'home_screen'); + expect(mock.capturedEvents.single.name, 'home_screen'); }); testWidgets('didPopNext fires when trackWhenReturningFromChildRoute', @@ -198,7 +198,7 @@ void main() { ), ); await tester.pump(); - expect(mock.capturedEvents.single.getName(), 'resume_screen'); + expect(mock.capturedEvents.single.name, 'resume_screen'); await tester.tap(find.text('push')); await tester.pumpAndSettle(); @@ -207,7 +207,7 @@ void main() { await tester.pumpAndSettle(); expect( - mock.capturedEvents.map((e) => e.getName()).toList(), + mock.capturedEvents.map((e) => e.name).toList(), ['resume_screen', 'resume_screen'], ); }); @@ -224,13 +224,13 @@ void main() { ), ); await tester.pump(); - expect(mock.capturedEvents.single.getName(), 'home_only'); + expect(mock.capturedEvents.single.name, 'home_only'); await tester.tap(find.text('open second')); await tester.pumpAndSettle(); expect(mock.capturedEvents, hasLength(1)); - expect(mock.capturedEvents.single.getName(), 'home_only'); + expect(mock.capturedEvents.single.name, 'home_only'); }); testWidgets( @@ -253,7 +253,7 @@ void main() { await tester.pumpAndSettle(); expect(mock.capturedEvents, hasLength(1)); - expect(mock.capturedEvents.single.getName(), 'home_sticky'); + expect(mock.capturedEvents.single.name, 'home_sticky'); }); testWidgets( @@ -269,13 +269,13 @@ void main() { ), ); await tester.pump(); - expect(mock.capturedEvents.single.getName(), 'screen_a'); + expect(mock.capturedEvents.single.name, 'screen_a'); await tester.tap(find.text('open tracked second')); await tester.pumpAndSettle(); expect( - mock.capturedEvents.map((e) => e.getName()).toList(), + mock.capturedEvents.map((e) => e.name).toList(), ['screen_a', 'screen_b'], ); @@ -308,7 +308,7 @@ void main() { ); await tester.pump(); - expect(mock.capturedEvents.single.getName(), 'scoped_route_home'); + expect(mock.capturedEvents.single.name, 'scoped_route_home'); }); testWidgets('scoped client is preferred when global is also set up', @@ -335,7 +335,7 @@ void main() { ); await tester.pump(); - expect(scopedMock.capturedEvents.single.getName(), 'route_scoped_wins'); + expect(scopedMock.capturedEvents.single.name, 'route_scoped_wins'); expect(globalMock.capturedEvents, isEmpty); }); diff --git a/test/widgets/transformer_widget_test.dart b/test/widgets/transformer_widget_test.dart index 3af52fb..2346a14 100644 --- a/test/widgets/transformer_widget_test.dart +++ b/test/widgets/transformer_widget_test.dart @@ -40,8 +40,8 @@ void main() { expect(mock.capturedEvents, hasLength(1)); final captured = mock.capturedEvents.single; - expect(captured.getName(), 'tap_test'); - expect(captured.getProperties()!['current_route'], '/test_route'); + expect(captured.name, 'tap_test'); + expect(captured.properties!['current_route'], '/test_route'); await client.dispose(); }); @@ -80,7 +80,7 @@ void main() { await tester.pump(); expect(mock.capturedEvents, hasLength(1)); - final props = mock.capturedEvents.single.getProperties(); + final props = mock.capturedEvents.single.properties; expect(props?.containsKey('current_route'), isNot(true)); await client.dispose(); @@ -117,7 +117,7 @@ void main() { await tester.tap(find.text('Click')); await tester.pump(); - expect(mock.capturedEvents.single.getName(), 'my_event'); + expect(mock.capturedEvents.single.name, 'my_event'); await client.dispose(); });