From 65c2195b63a950751a819bbaabccd6ca1e4382a7 Mon Sep 17 00:00:00 2001 From: Ahmed Tarek <7madak10@gmail.com> Date: Mon, 31 Mar 2025 18:09:32 +0200 Subject: [PATCH] notif: Use live value for app ID on registering APNs token MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #407. `await ZulipBinding.instance.packageInfo` was added to get the packageName, making `registerToken` take longer to complete. Previously, in "token initially unknown" test in the UpdateMachine.registerNotificationToken `start()` and `_registerNotificationToken()` finished in sync with the test’s expectations. Now, `flushMicrotasks` is added to ensure that the listener callback `_registerNotificationToken()` finishes its async work before continuing the test. Added packageInfo function in `example_data.dart` and updated tests that implicitly relied on packageInfo data to explicitly set it. --- lib/model/binding.dart | 3 +++ lib/notifications/receive.dart | 6 ++++-- test/api/core_test.dart | 2 +- test/example_data.dart | 13 +++++++++++++ test/model/binding.dart | 2 +- test/model/store_test.dart | 19 +++++++++++++++++++ 6 files changed, 41 insertions(+), 4 deletions(-) diff --git a/lib/model/binding.dart b/lib/model/binding.dart index d8e860dca0..d0412af750 100644 --- a/lib/model/binding.dart +++ b/lib/model/binding.dart @@ -303,10 +303,12 @@ class LinuxDeviceInfo implements BaseDeviceInfo { class PackageInfo { final String version; final String buildNumber; + final String packageName; const PackageInfo({ required this.version, required this.buildNumber, + required this.packageName, }); } @@ -411,6 +413,7 @@ class LiveZulipBinding extends ZulipBinding { _syncPackageInfo = PackageInfo( version: info.version, buildNumber: info.buildNumber, + packageName: info.packageName, ); } catch (e, st) { assert(debugLog('Failed to prefetch package info: $e\n$st')); // TODO(log) diff --git a/lib/notifications/receive.dart b/lib/notifications/receive.dart index 738bb98a2e..d60469ff30 100644 --- a/lib/notifications/receive.dart +++ b/lib/notifications/receive.dart @@ -149,8 +149,10 @@ class NotificationService { await addFcmToken(connection, token: token); case TargetPlatform.iOS: - const appBundleId = 'com.zulip.flutter'; // TODO(#407) find actual value live - await addApnsToken(connection, token: token, appid: appBundleId); + final packageInfo = await ZulipBinding.instance.packageInfo; + await addApnsToken(connection, + token: token, + appid: packageInfo!.packageName); case TargetPlatform.linux: case TargetPlatform.macOS: diff --git a/test/api/core_test.dart b/test/api/core_test.dart index 297dcfc441..e2c6e72ecb 100644 --- a/test/api/core_test.dart +++ b/test/api/core_test.dart @@ -460,7 +460,7 @@ void main() { }); } - const packageInfo = PackageInfo(version: '0.0.1', buildNumber: '1'); + final packageInfo = eg.packageInfo(version: '0.0.1', buildNumber: '1'); const testCases = [ ('ZulipFlutter/0.0.1+1 (Android 14)', AndroidDeviceInfo(release: '14', sdkInt: 34), ), diff --git a/test/example_data.dart b/test/example_data.dart index d44849bc6a..ecc6648c03 100644 --- a/test/example_data.dart +++ b/test/example_data.dart @@ -9,6 +9,7 @@ import 'package:zulip/api/model/submessage.dart'; import 'package:zulip/api/route/messages.dart'; import 'package:zulip/api/route/realm.dart'; import 'package:zulip/api/route/channels.dart'; +import 'package:zulip/model/binding.dart'; import 'package:zulip/model/database.dart'; import 'package:zulip/model/narrow.dart'; import 'package:zulip/model/settings.dart'; @@ -985,3 +986,15 @@ UpdateMachine updateMachine({ return UpdateMachine.fromInitialSnapshot( store: store, initialSnapshot: initialSnapshot); } + +PackageInfo packageInfo({ + String? version, + String? buildNumber, + String? packageName, +}) { + return PackageInfo( + version: version ?? '1.0.0', + buildNumber: buildNumber ?? '1', + packageName: packageName ?? 'com.example.app', + ); +} diff --git a/test/model/binding.dart b/test/model/binding.dart index 17c9565770..df0a7601f7 100644 --- a/test/model/binding.dart +++ b/test/model/binding.dart @@ -231,7 +231,7 @@ class TestZulipBinding extends ZulipBinding { /// The value that `ZulipBinding.instance.packageInfo` should return. PackageInfo packageInfoResult = _defaultPackageInfo; - static const _defaultPackageInfo = PackageInfo(version: '0.0.1', buildNumber: '1'); + static final _defaultPackageInfo = eg.packageInfo(); void _resetPackageInfo() { packageInfoResult = _defaultPackageInfo; diff --git a/test/model/store_test.dart b/test/model/store_test.dart index 4c83cd5da0..46328875c1 100644 --- a/test/model/store_test.dart +++ b/test/model/store_test.dart @@ -1132,6 +1132,7 @@ void main() { addTearDown(testBinding.reset); testBinding.firebaseMessagingInitialToken = '012abc'; addTearDown(NotificationService.debugReset); + testBinding.packageInfoResult = eg.packageInfo(packageName: 'com.zulip.flutter'); await NotificationService.instance.start(); // On store startup, send the token. @@ -1159,6 +1160,7 @@ void main() { addTearDown(testBinding.reset); testBinding.firebaseMessagingInitialToken = '012abc'; addTearDown(NotificationService.debugReset); + testBinding.packageInfoResult = eg.packageInfo(packageName: 'com.zulip.flutter'); final startFuture = NotificationService.instance.start(); // TODO this test is a bit brittle in its interaction with asynchrony; @@ -1177,6 +1179,7 @@ void main() { // When the token later appears, send it. connection.prepare(json: {}); await startFuture; + async.flushMicrotasks(); if (defaultTargetPlatform == TargetPlatform.android) { checkLastRequestFcm(token: '012abc'); } else { @@ -1191,6 +1194,22 @@ void main() { checkLastRequestFcm(token: '456def'); } })); + + test('on iOS, use provided app ID from packageInfo', () => awaitFakeAsync((async) async { + final origTargetPlatform = debugDefaultTargetPlatformOverride; + addTearDown(() => debugDefaultTargetPlatformOverride = origTargetPlatform); + debugDefaultTargetPlatformOverride = TargetPlatform.iOS; + addTearDown(testBinding.reset); + testBinding.firebaseMessagingInitialToken = '012abc'; + testBinding.packageInfoResult = eg.packageInfo(packageName: 'com.example.test'); + addTearDown(NotificationService.debugReset); + await NotificationService.instance.start(); + + prepareStore(); + connection.prepare(json: {}); + await updateMachine.registerNotificationToken(); + checkLastRequestApns(token: '012abc', appid: 'com.example.test'); + })); }); }