From f1031c994d93c23a2aada511ae4839f90a57e973 Mon Sep 17 00:00:00 2001 From: Michael Grosse Huelsewiesche Date: Mon, 2 Mar 2026 16:03:38 -0500 Subject: [PATCH] fix: handle UnimplementedError for linkStream on web platform The web platform implementation doesn't override linkStream, causing a crash when trackDeeplinks is enabled. This adds two layers of defense: 1. analytics_web.dart: returns an empty stream (correct platform behavior) 2. analytics.dart: catches UnimplementedError for any platform that doesn't implement linkStream Also fixes a pre-existing flaky test (createClient) that used a real StoreImpl instead of a mock, causing async PlatformNotSupportedError from path_provider to leak across test boundaries. Fixes #191 Co-Authored-By: Claude Opus 4.6 --- packages/core/lib/analytics.dart | 14 +++++++---- packages/core/lib/analytics_web.dart | 4 +++- packages/core/test/analytics_test.dart | 33 +++++++++++++++++++++----- 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/packages/core/lib/analytics.dart b/packages/core/lib/analytics.dart index 1508d12..932f277 100644 --- a/packages/core/lib/analytics.dart +++ b/packages/core/lib/analytics.dart @@ -86,11 +86,15 @@ class Analytics with ClientMethods { /// @param isReady void _onStateReady() { if (state.configuration.state.trackDeeplinks) { - AnalyticsPlatform.instance.linkStream.listen((event) { - if (state.configuration.state.trackDeeplinks) { - _trackDeepLinkEvent(DeepLinkData.fromJson(event)); - } - }); + try { + AnalyticsPlatform.instance.linkStream.listen((event) { + if (state.configuration.state.trackDeeplinks) { + _trackDeepLinkEvent(DeepLinkData.fromJson(event)); + } + }); + } on UnimplementedError { + // Deep link tracking not available on this platform (e.g. web) + } } for (var plugin in _pluginsToAdd) { diff --git a/packages/core/lib/analytics_web.dart b/packages/core/lib/analytics_web.dart index d1d9ada..1a21672 100644 --- a/packages/core/lib/analytics_web.dart +++ b/packages/core/lib/analytics_web.dart @@ -12,7 +12,9 @@ class AnalyticsPlatformImpl extends AnalyticsPlatform { /// Constructs a AnalyticsWeb AnalyticsPlatformImpl(); - /// Returns a [String] containing the version of the platform. + @override + Stream> get linkStream => const Stream.empty(); + @override Future getContext({bool collectDeviceId = false}) async => NativeContext( diff --git a/packages/core/test/analytics_test.dart b/packages/core/test/analytics_test.dart index 8d1e42b..6062cb5 100644 --- a/packages/core/test/analytics_test.dart +++ b/packages/core/test/analytics_test.dart @@ -1,6 +1,5 @@ import 'package:segment_analytics/analytics.dart'; import 'package:segment_analytics/analytics_platform_interface.dart'; -import 'package:segment_analytics/client.dart'; import 'package:segment_analytics/event.dart'; import 'package:segment_analytics/flush_policies/count_flush_policy.dart'; import 'package:segment_analytics/flush_policies/flush_policy.dart'; @@ -128,15 +127,37 @@ void main() { ); }); - test("it createClient", () async { - Analytics analytics = createClient(Configuration("123", - debug: false, + test("it creates Analytics with trackDeeplinks and lifecycle events enabled", () async { + final analytics = Analytics( + Configuration("123", trackApplicationLifecycleEvents: true, trackDeeplinks: true, - token: "abcdef12345") - ); + token: "abcdef12345"), + Mocks.store(), + httpClient: (_) => httpClient); + await analytics.init(); expect(analytics, isA()); }); + + test("trackDeeplinks should not crash on platform without linkStream", () async { + // Reproduces https://github.com/segmentio/analytics_flutter/issues/191 + // MockPlatform does not override linkStream, simulating web platform behavior + AnalyticsPlatform.instance = MockPlatform(); + + final analytics = Analytics( + Configuration("123", + trackApplicationLifecycleEvents: false, + trackDeeplinks: true), + Mocks.store(), + httpClient: (_) => httpClient); + await analytics.init(); + + // Allow _onStateReady to fire via state.ready.then() + await Future.delayed(Duration(milliseconds: 100)); + + // If we get here without UnimplementedError, the test passes + analytics.track("test event after deeplink init"); + }); }); }