Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Allow overriding the route filtering using a ctor param routeFilter #95

Merged
merged 7 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ jobs:
working-directory: ./example
run: flutter pub get

- name: Test
run: flutter test

- name: Build iOS
working-directory: ./example
run: flutter build ios --simulator --no-codesign
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## Next

- Allow tracking non `PageRoute` screens using the `PosthogObserver` ([#95](https://github.com/PostHog/posthog-flutter/pull/95))

## 4.3.0

- add PrivacyInfo ([#94](https://github.com/PostHog/posthog-flutter/pull/94))
Expand Down
2 changes: 1 addition & 1 deletion lib/src/posthog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class Posthog {
static PosthogFlutterPlatformInterface get _posthog =>
PosthogFlutterPlatformInterface.instance;

static final Posthog _instance = Posthog._internal();
static final _instance = Posthog._internal();

factory Posthog() {
return _instance;
Expand Down
31 changes: 18 additions & 13 deletions lib/src/posthog_observer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,39 +12,44 @@ class PosthogObserver extends RouteObserver<PageRoute<dynamic>> {

final ScreenNameExtractor _nameExtractor;

void _sendScreenView(PageRoute<dynamic> route) {
String? screenName = _nameExtractor(route.settings);
if (screenName != null) {
bool _isTrackeableRoute(String? name) {
return name != null && name.trim().isNotEmpty;
}

void _sendScreenView(Route<dynamic>? route) {
if (route == null) {
return;
}

var screenName = _nameExtractor(route.settings);
if (_isTrackeableRoute(screenName)) {
// if the screen name is the root route, we send it as root ("/") instead of only "/"
if (screenName == '/') {
screenName = 'root (\'/\')';
}

Posthog().screen(screenName: screenName);
Posthog().screen(screenName: screenName!);
}
}

@override
void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
super.didPush(route, previousRoute);
if (route is PageRoute) {
_sendScreenView(route);
}

_sendScreenView(route);
}

@override
void didReplace({Route<dynamic>? newRoute, Route<dynamic>? oldRoute}) {
super.didReplace(newRoute: newRoute, oldRoute: oldRoute);
if (newRoute is PageRoute) {
_sendScreenView(newRoute);
}

_sendScreenView(newRoute);
}

@override
void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
super.didPop(route, previousRoute);
if (previousRoute is PageRoute && route is PageRoute) {
_sendScreenView(previousRoute);
}

_sendScreenView(previousRoute);
}
}
4 changes: 3 additions & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ dependencies:
plugin_platform_interface: ^2.0.2

dev_dependencies:
flutter_lints: ^2.0.0
flutter_lints: ^3.0.0
flutter_test:
sdk: flutter

# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
Expand Down
13 changes: 13 additions & 0 deletions test/posthog_flutter_platform_interface_fake.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import 'package:posthog_flutter/src/posthog_flutter_platform_interface.dart';

class PosthogFlutterPlatformFake extends PosthogFlutterPlatformInterface {
String? screenName;

@override
Future<void> screen({
required String screenName,
Map<String, Object>? properties,
}) async {
this.screenName = screenName;
}
}
81 changes: 81 additions & 0 deletions test/posthog_observer_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import 'dart:math';

import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:posthog_flutter/src/posthog.dart';
import 'package:posthog_flutter/src/posthog_flutter_io.dart';
import 'package:posthog_flutter/src/posthog_flutter_platform_interface.dart';
import 'package:posthog_flutter/src/posthog_observer.dart';

import 'posthog_flutter_platform_interface_fake.dart';

void main() {
PageRoute<dynamic> route(RouteSettings? settings) => PageRouteBuilder<void>(
pageBuilder: (_, __, ___) => Container(),
settings: settings,
);

final fake = PosthogFlutterPlatformFake();

setUp(() {
TestWidgetsFlutterBinding.ensureInitialized();
PosthogFlutterPlatformInterface.instance = fake;
});

tearDown(() {
fake.screenName = null;
PosthogFlutterPlatformInterface.instance = PosthogFlutterIO();
});

PosthogObserver getSut(
{ScreenNameExtractor nameExtractor = defaultNameExtractor}) {
return PosthogObserver(nameExtractor: nameExtractor);
}

test('returns current route name', () {
final currentRoute = route(const RouteSettings(name: 'Current Route'));

final sut = getSut();
sut.didPush(currentRoute, null);

expect(fake.screenName, 'Current Route');
});

test('returns overriden route name', () {
final currentRoute = route(const RouteSettings(name: 'Current Route'));

String? nameExtractor(RouteSettings settings) => 'overriden';

final sut = getSut(nameExtractor: nameExtractor);
sut.didPush(currentRoute, null);

expect(fake.screenName, 'overriden');
});

test('returns overriden root route name', () {
final currentRoute = route(const RouteSettings(name: '/'));

final sut = getSut();
sut.didPush(currentRoute, null);

expect(fake.screenName, 'root (\'/\')');
});

test('does not capture not named routes', () {
final currentRoute = route(const RouteSettings(name: null));

final sut = getSut();
sut.didPush(currentRoute, null);

expect(fake.screenName, null);
});

test('does not capture blank routes', () {
final currentRoute = route(const RouteSettings(name: ' '));

final sut = getSut();
sut.didPush(currentRoute, null);

expect(fake.screenName, null);
});
}