Skip to content

Commit

Permalink
feat(tracker): Improve router observer tracker (#75)
Browse files Browse the repository at this point in the history
* feat(tracker): Added routeFilter parameter to navigatorObservers and improved screen tracking functionality

* refactor(app): Change deprecated method

* refactor: Refactor scripts in melos.yaml

* test: fix trackScreenView test

* chore(tracker): Added an example for sending screen transition events
  • Loading branch information
naipaka authored Mar 18, 2024
1 parent ad679a2 commit 8e1f7af
Show file tree
Hide file tree
Showing 11 changed files with 110 additions and 70 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/code-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,10 @@ jobs:
uses: bluefireteam/melos-action@v3

- name: Analyze packages
run: melos run analyze --no-select
run: melos analyze

- name: Check for the existence of unformatted files
# Cannot use `melos format` as it requires excluding files generated from the target file
run: melos run format:ci --no-select

test:
Expand Down
68 changes: 11 additions & 57 deletions melos.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,58 +31,14 @@ command:
workspaceChangelog: false

scripts:
upgrade:
run: |
melos exec -- \
"flutter pub upgrade --major-versions && flutter pub upgrade"
description: Run upgrade the major version of the pub.
packageFilters:
flutter: true
dirExists: lib

analyze:
run: |
melos run analyze:dart --no-select && \
melos run analyze:flutter --no-select && \
melos run analyze:custom_lint --no-select
description: Run all analyze.
packageFilters:
dirExists: lib

analyze:dart:
run: |
melos exec -- \
dart analyze . --fatal-infos
description: Run analyze.
packageFilters:
flutter: false
dirExists: lib

analyze:flutter:
run: |
melos exec -- \
flutter analyze . --fatal-infos
description: Run analyze.
packageFilters:
flutter: true
dirExists: lib

analyze:custom_lint:
run: |
melos exec -- \
dart run custom_lint
custom_lint:
exec: dart run custom_lint
description: Run custom_lint.
packageFilters:
dependsOn: "custom_lint"

format:
run: |
melos exec -- \
dart format lib/
description: Run dart format.
packageFilters:
dirExists: lib

# Issue on file exclusion feature: https://github.com/dart-lang/dart_style/issues/864
# NOTE: Using the `exec:` format causes processing to stop
format:ci:
run: |
melos exec -- \
Expand All @@ -92,25 +48,23 @@ scripts:
dirExists: lib

fix:
run: |
melos exec -- \
dart fix --apply lib
exec: dart fix --apply lib
description: Run dart fix.
packageFilters:
dirExists: lib

test:
run: |
melos exec --fail-fast -- \
flutter test
run: flutter test
exec:
failFast: true
description: Run flutter test.
packageFilters:
dirExists: test

test:ci:
run: |
melos exec --fail-fast -- \
flutter test --coverage
run: flutter test --coverage
exec:
failFast: true
description: Run flutter test for CI.
packageFilters:
dirExists: test
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>11.0</string>
<string>12.0</string>
</dict>
</plist>
2 changes: 1 addition & 1 deletion packages/altfire_tracker/example/ios/Podfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '11.0'
# platform :ios, '12.0'

# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
Expand Down
6 changes: 3 additions & 3 deletions packages/altfire_tracker/example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -165,14 +165,14 @@ SPEC CHECKSUMS:
FirebaseCrashlytics: 86d5bce01f42fa1db265f87ff1d591f04db610ec
FirebaseInstallations: e842042ec6ac1fd2e37d7706363ebe7f662afea4
FirebaseSessions: f90fe9212ee2818641eda051c0835c9c4e30d9ae
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
GoogleAppMeasurement: 70ce9aa438cff1cfb31ea3e660bcc67734cb716e
GoogleDataTransport: 57c22343ab29bc686febbf7cbb13bad167c2d8fe
GoogleUtilities: 0759d1a57ebb953965c2dfe0ba4c82e95ccc2e34
nanopb: d4d75c12cd1316f4a64e3c6963f879ecd4b5e0d5
PromisesObjC: c50d2056b5253dadbd6c2bea79b0674bd5a52fa4
PromisesSwift: 28dca69a9c40779916ac2d6985a0192a5cb4a265

PODFILE CHECKSUM: 70d9d25280d0dd177a5f637cdb0f0b0b12c6a189
PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796

COCOAPODS: 1.14.3
COCOAPODS: 1.15.2
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
LastUpgradeCheck = 1430;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
331C8080294A63A400263BE5 = {
Expand Down Expand Up @@ -481,7 +481,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
Expand Down Expand Up @@ -609,7 +609,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
Expand Down Expand Up @@ -658,7 +658,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
29 changes: 29 additions & 0 deletions packages/altfire_tracker/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ Future<void> main() async {
runApp(
MaterialApp(
home: HomePage(tracker: tracker),
initialRoute: '/',
navigatorObservers: [
...tracker.navigatorObservers(),
],
),
);
}
Expand Down Expand Up @@ -71,6 +75,31 @@ class HomePage extends StatelessWidget {
},
child: const Text('Record unhandled Exception'),
),
FilledButton(
onPressed: () async {
await Navigator.of(context).push<void>(
MaterialPageRoute(
builder: (context) {
return Scaffold(
appBar: AppBar(
title: const Text('Track Screen Page'),
),
body: Center(
child: FilledButton(
onPressed: () {
tracker.trackScreenView('/example');
},
child: const Text('Send Screen View Event'),
),
),
);
},
settings: const RouteSettings(name: '/track'),
),
);
},
child: const Text('Track Screen'),
),
],
),
),
Expand Down
10 changes: 10 additions & 0 deletions packages/altfire_tracker/lib/src/trackable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ abstract interface class Trackable {
bool fatal = false,
});

/// Tracks an screen view.
///
/// This method allows for logging of screen views within the application.
/// Screen views are typically logged when a new screen is displayed
/// to the user.
///
/// Parameters:
/// [screenName] - The name of the screen to track.
Future<void> trackScreenView(String screenName);

/// Tracks an event.
///
/// This method allows for logging of custom events within the application.
Expand Down
12 changes: 11 additions & 1 deletion packages/altfire_tracker/lib/src/tracker.dart
Original file line number Diff line number Diff line change
Expand Up @@ -139,17 +139,27 @@ class Tracker {
/// Returns a list of NavigatorObservers to register with Navigator.
/// Use [nameExtractor] to set the parameter value to send.
List<NavigatorObserver> navigatorObservers({
required String? Function(RouteSettings) nameExtractor,
String? Function(RouteSettings) nameExtractor = defaultNameExtractor,
bool Function(Route<dynamic>?) routeFilter = defaultRouteFilter,
}) {
return [
// Returns a NavigatorObserver of FirebaseAnalytics.
FirebaseAnalyticsObserver(
analytics: _analytics,
nameExtractor: nameExtractor,
routeFilter: routeFilter,
),
];
}

/// Send a screen view to Analytics.
Future<void> trackScreenView(String screenName) async {
await Future.wait([
_analytics.logScreenView(screenName: screenName),
..._trackers.map((tracker) => tracker.trackScreenView(screenName)),
]);
}

/// Send an event to Analytics.
Future<void> logEvent(
String eventName, {
Expand Down
38 changes: 37 additions & 1 deletion packages/altfire_tracker/test/src/tracker_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -254,13 +254,49 @@ void main() {
);

String nameExtractor(RouteSettings settings) => settings.name!;
final got = tracker.navigatorObservers(nameExtractor: nameExtractor);
bool routerFilter(Route<dynamic>? route) => route != null;
final got = tracker.navigatorObservers(
nameExtractor: nameExtractor,
routeFilter: routerFilter,
);

expect(got, isA<List<NavigatorObserver>>());
expect(got.length, 1);
expect(got[0], isA<FirebaseAnalyticsObserver>());
});

test('trackScreenView should call setCurrentScreen on analytics', () async {
final crashlytics = MockFirebaseCrashlytics();
final analytics = MockFirebaseAnalytics();
final trackable = MockTrackable();
final tracker = Tracker(
crashlytics: crashlytics,
analytics: analytics,
trackers: [trackable],
);

const screenName = 'screen';
when(
() => analytics.logScreenView(
screenName: screenName,
),
).thenAnswer((_) async {});
when(
() => trackable.trackScreenView(screenName),
).thenAnswer((_) async {});

await tracker.trackScreenView(screenName);

verify(
() => analytics.logScreenView(
screenName: screenName,
),
).called(1);
verify(() => trackable.trackScreenView(screenName)).called(1);
verifyNoMoreInteractions(crashlytics);
verifyNoMoreInteractions(analytics);
});

test('logEvent should call logEvent on analytics and trackers', () async {
final crashlytics = MockFirebaseCrashlytics();
final analytics = MockFirebaseAnalytics();
Expand Down

0 comments on commit 8e1f7af

Please sign in to comment.