From f7cf359c6209d3fb5d88d118c4b9b4bd6dce68b4 Mon Sep 17 00:00:00 2001 From: fulleni Date: Sat, 8 Nov 2025 10:01:13 +0100 Subject: [PATCH 1/8] refactor(push-notifications): replace token and provider with providerTokens map - Remove `token` and `provider` properties - Add `providerTokens` map to store tokens for multiple providers - Update JSON serialization and deserialization for the new `providerTokens` map - Adjust `props` and `copyWith` methods to accommodate the new change --- .../push_notification_device.dart | 41 ++++++++++++------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/lib/src/models/push_notifications/push_notification_device.dart b/lib/src/models/push_notifications/push_notification_device.dart index 55dcd6e..54efda3 100644 --- a/lib/src/models/push_notifications/push_notification_device.dart +++ b/lib/src/models/push_notifications/push_notification_device.dart @@ -20,9 +20,8 @@ class PushNotificationDevice extends Equatable { const PushNotificationDevice({ required this.id, required this.userId, - required this.token, - required this.provider, required this.platform, + required this.providerTokens, required this.createdAt, required this.updatedAt, }); @@ -37,15 +36,13 @@ class PushNotificationDevice extends Equatable { /// The ID of the user who owns this device. final String userId; - /// The unique token issued by the push notification provider for this device. - final String token; - - /// The push notification provider (e.g., Firebase, OneSignal). - final PushNotificationProvider provider; - /// The mobile operating system of the device. final DevicePlatform platform; + /// A map of push notification provider tokens for this device. + @JsonKey(fromJson: _providerTokensFromJson, toJson: _providerTokensToJson) + final Map providerTokens; + /// The timestamp when this device was first registered. @JsonKey(fromJson: dateTimeFromJson, toJson: dateTimeToJson) final DateTime createdAt; @@ -57,13 +54,31 @@ class PushNotificationDevice extends Equatable { /// Converts this [PushNotificationDevice] instance to JSON data. Map toJson() => _$PushNotificationDeviceToJson(this); + /// Custom deserializer for the `providerTokens` map. + static Map _providerTokensFromJson( + Map json, + ) { + return json.map( + (key, value) => MapEntry( + PushNotificationProvider.values.byName(key), + value as String, + ), + ); + } + + /// Custom serializer for the `providerTokens` map. + static Map _providerTokensToJson( + Map tokens, + ) { + return tokens.map((key, value) => MapEntry(key.name, value)); + } + @override List get props => [ id, userId, - token, - provider, platform, + providerTokens, createdAt, updatedAt, ]; @@ -73,18 +88,16 @@ class PushNotificationDevice extends Equatable { PushNotificationDevice copyWith({ String? id, String? userId, - String? token, - PushNotificationProvider? provider, DevicePlatform? platform, + Map? providerTokens, DateTime? createdAt, DateTime? updatedAt, }) { return PushNotificationDevice( id: id ?? this.id, userId: userId ?? this.userId, - token: token ?? this.token, - provider: provider ?? this.provider, platform: platform ?? this.platform, + providerTokens: providerTokens ?? this.providerTokens, createdAt: createdAt ?? this.createdAt, updatedAt: updatedAt ?? this.updatedAt, ); From 4025183721420a17abaac1d9d3d7768624954b8e Mon Sep 17 00:00:00 2001 From: fulleni Date: Sat, 8 Nov 2025 10:06:12 +0100 Subject: [PATCH 2/8] refactor(config): remove unused push notification provider configs - Remove FirebaseProviderConfig, OneSignalProviderConfig, and PushNotificationProviderConfig - Update imports and exports in config.dart - Simplify PushNotificationConfig by removing providerConfigs --- lib/src/models/config/config.dart | 3 - .../config/firebase_provider_config.dart | 59 --------------- .../config/firebase_provider_config.g.dart | 26 ------- .../config/one_signal_provider_config.dart | 48 ------------- .../config/one_signal_provider_config.g.dart | 24 ------- .../config/push_notification_config.dart | 58 ++------------- .../push_notification_provider_config.dart | 71 ------------------- 7 files changed, 4 insertions(+), 285 deletions(-) delete mode 100644 lib/src/models/config/firebase_provider_config.dart delete mode 100644 lib/src/models/config/firebase_provider_config.g.dart delete mode 100644 lib/src/models/config/one_signal_provider_config.dart delete mode 100644 lib/src/models/config/one_signal_provider_config.g.dart delete mode 100644 lib/src/models/config/push_notification_provider_config.dart diff --git a/lib/src/models/config/config.dart b/lib/src/models/config/config.dart index 91dee86..80c7281 100644 --- a/lib/src/models/config/config.dart +++ b/lib/src/models/config/config.dart @@ -6,13 +6,10 @@ export 'feed_ad_configuration.dart'; export 'feed_ad_frequency_config.dart'; export 'feed_decorator_config.dart'; export 'feed_decorator_role_config.dart'; -export 'firebase_provider_config.dart'; export 'interstitial_ad_configuration.dart'; export 'interstitial_ad_frequency_config.dart'; -export 'one_signal_provider_config.dart'; export 'push_notification_config.dart'; export 'push_notification_delivery_config.dart'; export 'push_notification_delivery_role_config.dart'; -export 'push_notification_provider_config.dart'; export 'remote_config.dart'; export 'user_preference_config.dart'; diff --git a/lib/src/models/config/firebase_provider_config.dart b/lib/src/models/config/firebase_provider_config.dart deleted file mode 100644 index b1ec5db..0000000 --- a/lib/src/models/config/firebase_provider_config.dart +++ /dev/null @@ -1,59 +0,0 @@ -import 'package:core/src/models/config/config.dart'; -import 'package:json_annotation/json_annotation.dart'; -import 'package:meta/meta.dart'; - -part 'firebase_provider_config.g.dart'; - -/// {@template firebase_provider_config} -/// A concrete implementation of [PushNotificationProviderConfig] for Firebase. -/// -/// This model holds the specific credentials required for the backend to -/// authenticate with Firebase Cloud Messaging (FCM) using a service account. -/// {@endtemplate} -@immutable -@JsonSerializable(explicitToJson: true, includeIfNull: true, checked: true) -class FirebaseProviderConfig extends PushNotificationProviderConfig { - /// {@macro firebase_provider_config} - const FirebaseProviderConfig({ - required this.projectId, - required this.clientEmail, - required this.privateKey, - }) : super(provider: 'firebase'); - - /// Creates a [FirebaseProviderConfig] from JSON data. - factory FirebaseProviderConfig.fromJson(Map json) => - _$FirebaseProviderConfigFromJson(json); - - /// The project ID from the Firebase service account credentials. - final String projectId; - - /// The client email from the Firebase service account credentials. - final String clientEmail; - - /// The private key from the Firebase service account credentials. - final String privateKey; - - /// Converts this [FirebaseProviderConfig] instance to a JSON map, - /// including the provider discriminator. - Map toJson() { - final json = _$FirebaseProviderConfigToJson(this); - json['provider'] = provider; - return json; - } - - @override - List get props => [provider, projectId, clientEmail, privateKey]; - - /// Creates a copy of this instance with the given fields replaced. - FirebaseProviderConfig copyWith({ - String? projectId, - String? clientEmail, - String? privateKey, - }) { - return FirebaseProviderConfig( - projectId: projectId ?? this.projectId, - clientEmail: clientEmail ?? this.clientEmail, - privateKey: privateKey ?? this.privateKey, - ); - } -} diff --git a/lib/src/models/config/firebase_provider_config.g.dart b/lib/src/models/config/firebase_provider_config.g.dart deleted file mode 100644 index 43853d5..0000000 --- a/lib/src/models/config/firebase_provider_config.g.dart +++ /dev/null @@ -1,26 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'firebase_provider_config.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -FirebaseProviderConfig _$FirebaseProviderConfigFromJson( - Map json, -) => $checkedCreate('FirebaseProviderConfig', json, ($checkedConvert) { - final val = FirebaseProviderConfig( - projectId: $checkedConvert('projectId', (v) => v as String), - clientEmail: $checkedConvert('clientEmail', (v) => v as String), - privateKey: $checkedConvert('privateKey', (v) => v as String), - ); - return val; -}); - -Map _$FirebaseProviderConfigToJson( - FirebaseProviderConfig instance, -) => { - 'projectId': instance.projectId, - 'clientEmail': instance.clientEmail, - 'privateKey': instance.privateKey, -}; diff --git a/lib/src/models/config/one_signal_provider_config.dart b/lib/src/models/config/one_signal_provider_config.dart deleted file mode 100644 index 8f12813..0000000 --- a/lib/src/models/config/one_signal_provider_config.dart +++ /dev/null @@ -1,48 +0,0 @@ -import 'package:core/src/models/config/config.dart'; -import 'package:json_annotation/json_annotation.dart'; -import 'package:meta/meta.dart'; - -part 'one_signal_provider_config.g.dart'; - -/// {@template one_signal_provider_config} -/// A concrete implementation of [PushNotificationProviderConfig] for OneSignal. -/// -/// This model holds the specific credentials required for the backend to -/// authenticate with the OneSignal REST API. -/// {@endtemplate} -@immutable -@JsonSerializable(explicitToJson: true, includeIfNull: true, checked: true) -class OneSignalProviderConfig extends PushNotificationProviderConfig { - /// {@macro one_signal_provider_config} - const OneSignalProviderConfig({required this.appId, required this.restApiKey}) - : super(provider: 'oneSignal'); - - /// Creates a [OneSignalProviderConfig] from JSON data. - factory OneSignalProviderConfig.fromJson(Map json) => - _$OneSignalProviderConfigFromJson(json); - - /// The OneSignal App ID for your application. - final String appId; - - /// The OneSignal REST API Key for server-side operations. - final String restApiKey; - - /// Converts this [OneSignalProviderConfig] instance to a JSON map, - /// including the provider discriminator. - Map toJson() { - final json = _$OneSignalProviderConfigToJson(this); - json['provider'] = provider; - return json; - } - - @override - List get props => [provider, appId, restApiKey]; - - /// Creates a copy of this instance with the given fields replaced. - OneSignalProviderConfig copyWith({String? appId, String? restApiKey}) { - return OneSignalProviderConfig( - appId: appId ?? this.appId, - restApiKey: restApiKey ?? this.restApiKey, - ); - } -} diff --git a/lib/src/models/config/one_signal_provider_config.g.dart b/lib/src/models/config/one_signal_provider_config.g.dart deleted file mode 100644 index 0262ecd..0000000 --- a/lib/src/models/config/one_signal_provider_config.g.dart +++ /dev/null @@ -1,24 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'one_signal_provider_config.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -OneSignalProviderConfig _$OneSignalProviderConfigFromJson( - Map json, -) => $checkedCreate('OneSignalProviderConfig', json, ($checkedConvert) { - final val = OneSignalProviderConfig( - appId: $checkedConvert('appId', (v) => v as String), - restApiKey: $checkedConvert('restApiKey', (v) => v as String), - ); - return val; -}); - -Map _$OneSignalProviderConfigToJson( - OneSignalProviderConfig instance, -) => { - 'appId': instance.appId, - 'restApiKey': instance.restApiKey, -}; diff --git a/lib/src/models/config/push_notification_config.dart b/lib/src/models/config/push_notification_config.dart index 3826062..ff68552 100644 --- a/lib/src/models/config/push_notification_config.dart +++ b/lib/src/models/config/push_notification_config.dart @@ -10,9 +10,9 @@ part 'push_notification_config.g.dart'; /// Defines the global configuration for the push notification system. /// /// This model is part of the overall `RemoteConfig` and allows for remotely -/// managing all aspects of push notifications, including provider credentials, -/// feature availability, and user-specific limits. -/// {@endtemplate} +/// managing all aspects of push notifications, including feature availability +/// and user-specific limits. +/// {@endtemplate}push_notification_provider_config @immutable @JsonSerializable(explicitToJson: true, includeIfNull: true, checked: true) class PushNotificationConfig extends Equatable { @@ -20,7 +20,6 @@ class PushNotificationConfig extends Equatable { const PushNotificationConfig({ required this.enabled, required this.primaryProvider, - required this.providerConfigs, required this.deliveryConfigs, }); @@ -38,15 +37,6 @@ class PushNotificationConfig extends Equatable { /// This allows for dynamically switching between providers like Firebase final PushNotificationProvider primaryProvider; - /// A map holding the credentials for each potential push provider. - /// - /// This uses custom fromJson/toJson helpers to handle the polymorphic nature - /// of [PushNotificationProviderConfig] within a map structure, which is not - /// natively supported by `json_serializable`. - @JsonKey(fromJson: _providerConfigsFromJson, toJson: _providerConfigsToJson) - final Map - providerConfigs; - /// A map to globally enable or disable each specific notification type /// and define its role-based limits using the `visibleTo` pattern. final Map< @@ -58,53 +48,14 @@ class PushNotificationConfig extends Equatable { /// Converts this [PushNotificationConfig] instance to JSON data. Map toJson() => _$PushNotificationConfigToJson(this); - /// A custom deserializer for the `providerConfigs` map. - /// - /// This function manually iterates through the incoming JSON map, converting - /// string keys into [PushNotificationProvider] enum values and delegating - /// the value deserialization to the polymorphic - /// [PushNotificationProviderConfig.fromJson] factory. - static Map - _providerConfigsFromJson(Map json) { - return json.map((key, value) { - final provider = PushNotificationProvider.values.byName(key); - return MapEntry( - provider, - PushNotificationProviderConfig.fromJson(value as Map), - ); - }); - } - - /// A custom serializer for the `providerConfigs` map. - /// - /// This function manually iterates through the map, converting the - /// [PushNotificationProvider] enum keys into strings and delegating the - /// value serialization to the polymorphic - /// [PushNotificationProviderConfig.toJson] static method. - static Map _providerConfigsToJson( - Map configs, - ) { - return configs.map( - (key, value) => - MapEntry(key.name, PushNotificationProviderConfig.toJson(value)), - ); - } - @override - List get props => [ - enabled, - primaryProvider, - providerConfigs, - deliveryConfigs, - ]; + List get props => [enabled, primaryProvider, deliveryConfigs]; /// Creates a copy of this [PushNotificationConfig] but with the given fields /// replaced with the new values. PushNotificationConfig copyWith({ bool? enabled, PushNotificationProvider? primaryProvider, - Map? - providerConfigs, Map< PushNotificationSubscriptionDeliveryType, PushNotificationDeliveryConfig @@ -114,7 +65,6 @@ class PushNotificationConfig extends Equatable { return PushNotificationConfig( enabled: enabled ?? this.enabled, primaryProvider: primaryProvider ?? this.primaryProvider, - providerConfigs: providerConfigs ?? this.providerConfigs, deliveryConfigs: deliveryConfigs ?? this.deliveryConfigs, ); } diff --git a/lib/src/models/config/push_notification_provider_config.dart b/lib/src/models/config/push_notification_provider_config.dart deleted file mode 100644 index 582ea7a..0000000 --- a/lib/src/models/config/push_notification_provider_config.dart +++ /dev/null @@ -1,71 +0,0 @@ -import 'package:core/src/models/config/firebase_provider_config.dart'; -import 'package:core/src/models/config/one_signal_provider_config.dart'; -import 'package:equatable/equatable.dart'; - -/// {@template push_notification_provider_config} -/// An abstract base class for push notification provider configurations. -/// -/// This class uses a factory constructor to enable polymorphic deserialization, -/// allowing for different concrete configuration models (e.g., -/// [FirebaseProviderConfig], [OneSignalProviderConfig]) based on a -/// `providerName` discriminator field in the JSON data. -/// {@endtemplate} -abstract class PushNotificationProviderConfig extends Equatable { - /// {@macro push_notification_provider_config} - const PushNotificationProviderConfig({required this.provider}); - - /// Factory method to create a [PushNotificationProviderConfig] instance from a JSON map. - /// - /// This factory uses the `provider` field in the JSON map to dispatch to the - /// correct concrete `fromJson` constructor. - /// - /// Throws [FormatException] if the `provider` field is missing or unknown. - factory PushNotificationProviderConfig.fromJson(Map json) { - final provider = json['provider'] as String?; - if (provider == null) { - throw const FormatException( - 'Missing "provider" field in PushNotificationProviderConfig JSON.', - ); - } - - switch (provider) { - case 'firebase': - return FirebaseProviderConfig.fromJson(json); - case 'oneSignal': - return OneSignalProviderConfig.fromJson(json); - default: - throw FormatException('Unknown push notification provider: $provider'); - } - } - - /// Static method to serialize a [PushNotificationProviderConfig] instance - /// to a JSON map. - /// - /// This method acts as a dispatcher, using the `provider` field of the - /// provided [providerConfig] to delegate to the correct concrete `toJson` - /// instance method. - /// - /// Throws [FormatException] if the `provider` field is missing or unknown. - static Map toJson( - PushNotificationProviderConfig providerConfig, - ) { - switch (providerConfig.provider) { - case 'firebase': - final provider = providerConfig as FirebaseProviderConfig; - return provider.toJson(); - case 'oneSignal': - final provider = providerConfig as OneSignalProviderConfig; - return provider.toJson(); - default: - throw FormatException( - 'Unknown PushNotificationProviderConfig type: ${providerConfig.provider}', - ); - } - } - - /// The name of the provider, used as a discriminator for deserialization. - final String provider; - - @override - List get props => [provider]; -} From fc13f8b225c8db5c9f57ad07baa482fa2c84b427 Mon Sep 17 00:00:00 2001 From: fulleni Date: Sat, 8 Nov 2025 10:11:30 +0100 Subject: [PATCH 3/8] build(serialization): regeneration --- .../config/push_notification_config.g.dart | 9 -------- .../push_notification_device.g.dart | 21 ++++++++----------- 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/lib/src/models/config/push_notification_config.g.dart b/lib/src/models/config/push_notification_config.g.dart index 7dd4639..693f9ea 100644 --- a/lib/src/models/config/push_notification_config.g.dart +++ b/lib/src/models/config/push_notification_config.g.dart @@ -15,12 +15,6 @@ PushNotificationConfig _$PushNotificationConfigFromJson( 'primaryProvider', (v) => $enumDecode(_$PushNotificationProviderEnumMap, v), ), - providerConfigs: $checkedConvert( - 'providerConfigs', - (v) => PushNotificationConfig._providerConfigsFromJson( - v as Map, - ), - ), deliveryConfigs: $checkedConvert( 'deliveryConfigs', (v) => (v as Map).map( @@ -40,9 +34,6 @@ Map _$PushNotificationConfigToJson( 'enabled': instance.enabled, 'primaryProvider': _$PushNotificationProviderEnumMap[instance.primaryProvider]!, - 'providerConfigs': PushNotificationConfig._providerConfigsToJson( - instance.providerConfigs, - ), 'deliveryConfigs': instance.deliveryConfigs.map( (k, e) => MapEntry( _$PushNotificationSubscriptionDeliveryTypeEnumMap[k]!, diff --git a/lib/src/models/push_notifications/push_notification_device.g.dart b/lib/src/models/push_notifications/push_notification_device.g.dart index aeb7303..ef2a29f 100644 --- a/lib/src/models/push_notifications/push_notification_device.g.dart +++ b/lib/src/models/push_notifications/push_notification_device.g.dart @@ -12,15 +12,16 @@ PushNotificationDevice _$PushNotificationDeviceFromJson( final val = PushNotificationDevice( id: $checkedConvert('id', (v) => v as String), userId: $checkedConvert('userId', (v) => v as String), - token: $checkedConvert('token', (v) => v as String), - provider: $checkedConvert( - 'provider', - (v) => $enumDecode(_$PushNotificationProviderEnumMap, v), - ), platform: $checkedConvert( 'platform', (v) => $enumDecode(_$DevicePlatformEnumMap, v), ), + providerTokens: $checkedConvert( + 'providerTokens', + (v) => PushNotificationDevice._providerTokensFromJson( + v as Map, + ), + ), createdAt: $checkedConvert( 'createdAt', (v) => dateTimeFromJson(v as String?), @@ -38,18 +39,14 @@ Map _$PushNotificationDeviceToJson( ) => { 'id': instance.id, 'userId': instance.userId, - 'token': instance.token, - 'provider': _$PushNotificationProviderEnumMap[instance.provider]!, 'platform': _$DevicePlatformEnumMap[instance.platform]!, + 'providerTokens': PushNotificationDevice._providerTokensToJson( + instance.providerTokens, + ), 'createdAt': dateTimeToJson(instance.createdAt), 'updatedAt': dateTimeToJson(instance.updatedAt), }; -const _$PushNotificationProviderEnumMap = { - PushNotificationProvider.firebase: 'firebase', - PushNotificationProvider.oneSignal: 'oneSignal', -}; - const _$DevicePlatformEnumMap = { DevicePlatform.ios: 'ios', DevicePlatform.android: 'android', From c40cb398a357c0287e72f2893910b99848456322 Mon Sep 17 00:00:00 2001 From: fulleni Date: Sat, 8 Nov 2025 10:11:43 +0100 Subject: [PATCH 4/8] fix(remote_configs): remove push notification config examples - Removed hardcoded example values for push notification configurations - This change improves security by eliminating sensitive data in the codebase - It also enhances code clarity by removing specific configuration examples --- lib/src/fixtures/remote_configs.dart | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/lib/src/fixtures/remote_configs.dart b/lib/src/fixtures/remote_configs.dart index 1196205..5d8a7c0 100644 --- a/lib/src/fixtures/remote_configs.dart +++ b/lib/src/fixtures/remote_configs.dart @@ -113,17 +113,6 @@ final List remoteConfigsFixturesData = [ pushNotificationConfig: const PushNotificationConfig( enabled: true, primaryProvider: PushNotificationProvider.firebase, - providerConfigs: { - PushNotificationProvider.firebase: FirebaseProviderConfig( - projectId: 'your-firebase-project-id', - clientEmail: 'your-firebase-client-email', - privateKey: 'your-firebase-private-key', - ), - PushNotificationProvider.oneSignal: OneSignalProviderConfig( - appId: 'your-onesignal-app-id', - restApiKey: 'your-onesignal-rest-api-key', - ), - }, deliveryConfigs: { PushNotificationSubscriptionDeliveryType.breakingOnly: PushNotificationDeliveryConfig( From 9d407344c64093bf9235217dca3a401aeb83d100 Mon Sep 17 00:00:00 2001 From: fulleni Date: Sat, 8 Nov 2025 10:12:49 +0100 Subject: [PATCH 5/8] test(models): remove obsolete provider config tests - Remove FirebaseProviderConfig tests - Remove OneSignalProviderConfig tests - Remove PushNotificationProviderConfig tests - All related test files have been deleted --- .../config/firebase_provider_config_test.dart | 90 ------------------- .../one_signal_provider_config_test.dart | 82 ----------------- ...ush_notification_provider_config_test.dart | 87 ------------------ 3 files changed, 259 deletions(-) delete mode 100644 test/src/models/config/firebase_provider_config_test.dart delete mode 100644 test/src/models/config/one_signal_provider_config_test.dart delete mode 100644 test/src/models/config/push_notification_provider_config_test.dart diff --git a/test/src/models/config/firebase_provider_config_test.dart b/test/src/models/config/firebase_provider_config_test.dart deleted file mode 100644 index b6dcea2..0000000 --- a/test/src/models/config/firebase_provider_config_test.dart +++ /dev/null @@ -1,90 +0,0 @@ -import 'package:core/src/enums/push_notification_provider.dart'; -import 'package:core/src/fixtures/remote_configs.dart'; -import 'package:core/src/models/config/firebase_provider_config.dart'; -import 'package:test/test.dart'; - -void main() { - group('FirebaseProviderConfig', () { - // Retrieve the FirebaseProviderConfig from the remoteConfigsFixturesData. - // This ensures consistency with predefined application configurations. - final config = - remoteConfigsFixturesData - .first - .pushNotificationConfig - .providerConfigs[PushNotificationProvider.firebase]! - as FirebaseProviderConfig; - - // Generate the expected JSON from the fixture config for comparison. - final json = config.toJson(); - - test('supports value equality', () { - // Arrange: Create another instance with the same values. - final anotherConfig = - remoteConfigsFixturesData - .first - .pushNotificationConfig - .providerConfigs[PushNotificationProvider.firebase]! - as FirebaseProviderConfig; - - // Assert: The two instances should be equal. - expect(config, equals(anotherConfig)); - }); - - test('props are correct', () { - // Assert: The props list should contain all the fields including provider. - expect( - config.props, - equals([ - config.provider, - config.projectId, - config.clientEmail, - config.privateKey, - ]), - ); - }); - - test('can be created from JSON', () { - // Act: Create an instance from the JSON map. - final fromJson = FirebaseProviderConfig.fromJson(json); - - // Assert: The created instance should be equal to the original. - expect(fromJson, equals(config)); - }); - - test('can be converted to JSON', () { - // Act: Convert the instance to a JSON map. - final toJson = config.toJson(); - - // Assert: The resulting map should match the original JSON map. - expect(toJson, equals(json)); - }); - - test('copyWith creates a copy with updated values', () { - // Arrange: Define new values. - const newProjectId = 'updated-project-id'; - - // Act: Create a copy with the new value. - final copiedConfig = config.copyWith( - projectId: newProjectId, - ); // Using a new value for projectId - - // Assert: The new instance should have the updated value. - expect(copiedConfig.projectId, equals(newProjectId)); - expect(copiedConfig.clientEmail, equals(config.clientEmail)); - - // Assert: The original instance should remain unchanged. - expect(config.projectId, isNot(equals(newProjectId))); - }); - - test( - 'copyWith creates an identical copy when no arguments are provided', - () { - // Act: Create a copy without providing any arguments. - final copiedConfig = config.copyWith(); - - // Assert: The copied instance should be equal to the original. - expect(copiedConfig, equals(config)); - }, - ); - }); -} diff --git a/test/src/models/config/one_signal_provider_config_test.dart b/test/src/models/config/one_signal_provider_config_test.dart deleted file mode 100644 index f4953d2..0000000 --- a/test/src/models/config/one_signal_provider_config_test.dart +++ /dev/null @@ -1,82 +0,0 @@ -import 'package:core/src/enums/push_notification_provider.dart'; -import 'package:core/src/fixtures/remote_configs.dart'; -import 'package:core/src/models/config/one_signal_provider_config.dart'; -import 'package:test/test.dart'; - -void main() { - group('OneSignalProviderConfig', () { - // Retrieve the OneSignalProviderConfig from the remoteConfigsFixturesData. - // This ensures consistency with predefined application configurations. - final config = - remoteConfigsFixturesData - .first - .pushNotificationConfig - .providerConfigs[PushNotificationProvider.oneSignal]! - as OneSignalProviderConfig; - - // Generate the expected JSON from the fixture config for comparison. - final json = config.toJson(); - - test('supports value equality', () { - // Arrange: Create another instance with the same values. - final anotherConfig = - remoteConfigsFixturesData - .first - .pushNotificationConfig - .providerConfigs[PushNotificationProvider.oneSignal]! - as OneSignalProviderConfig; - - // Assert: The two instances should be equal. - expect(config, equals(anotherConfig)); - }); - - test('props are correct', () { - // Assert: The props list should contain all the fields including provider. - expect( - config.props, - equals([config.provider, config.appId, config.restApiKey]), - ); - }); - - test('can be created from JSON', () { - // Act: Create an instance from the JSON map. - final fromJson = OneSignalProviderConfig.fromJson(json); - - // Assert: The created instance should be equal to the original. - expect(fromJson, equals(config)); - }); - - test('can be converted to JSON', () { - // Act: Convert the instance to a JSON map. - final toJson = config.toJson(); - - // Assert: The resulting map should match the original JSON map. - expect(toJson, equals(json)); - }); - - test('copyWith creates a copy with updated values', () { - // Arrange: Define new values. - const newAppId = 'updated-app-id'; - - // Act: Create a copy with the new value. - final copiedConfig = config.copyWith( - appId: newAppId, - ); // Using a new value for appId - - // Assert: The new instance should have the updated value. - expect(copiedConfig.appId, equals(newAppId)); - expect(copiedConfig.restApiKey, equals(config.restApiKey)); - - // Assert: The original instance should remain unchanged. - expect(config.appId, isNot(equals(newAppId))); - }); - - test('copyWith creates an identical copy when no arguments are provided', () { - // Act: Create a copy without providing any arguments, expecting an identical instance. - final copiedConfig = config.copyWith(); - - // Assert: The copied instance should be equal to the original. - expect(copiedConfig, equals(config)); - }); - }); -} diff --git a/test/src/models/config/push_notification_provider_config_test.dart b/test/src/models/config/push_notification_provider_config_test.dart deleted file mode 100644 index 5a97bde..0000000 --- a/test/src/models/config/push_notification_provider_config_test.dart +++ /dev/null @@ -1,87 +0,0 @@ -import 'package:core/src/enums/push_notification_provider.dart'; -import 'package:core/src/fixtures/remote_configs.dart'; -import 'package:core/src/models/config/firebase_provider_config.dart'; -import 'package:core/src/models/config/one_signal_provider_config.dart'; -import 'package:core/src/models/config/push_notification_provider_config.dart'; -import 'package:test/test.dart'; - -void main() { - group('PushNotificationProviderConfig', () { - // Arrange: Retrieve sample concrete instances from the fixtures. - final firebaseConfig = remoteConfigsFixturesData - .first - .pushNotificationConfig - .providerConfigs[PushNotificationProvider.firebase]!; - - final oneSignalConfig = remoteConfigsFixturesData - .first - .pushNotificationConfig - .providerConfigs[PushNotificationProvider.oneSignal]!; - - // Arrange: Create corresponding JSON maps with the 'provider' discriminator. - final firebaseJson = (firebaseConfig as FirebaseProviderConfig).toJson(); - final oneSignalJson = (oneSignalConfig as OneSignalProviderConfig).toJson(); - - group('fromJson factory (polymorphic)', () { - test('correctly deserializes to FirebaseProviderConfig', () { - // Act: Deserialize the Firebase JSON using the base factory. - final result = PushNotificationProviderConfig.fromJson(firebaseJson); - - // Assert: The result should be the correct concrete type and value. - expect(result, isA()); - expect(result, equals(firebaseConfig)); - }); - - test('correctly deserializes to OneSignalProviderConfig', () { - // Act: Deserialize the OneSignal JSON using the base factory. - final result = PushNotificationProviderConfig.fromJson(oneSignalJson); - - // Assert: The result should be the correct concrete type and value. - expect(result, isA()); - expect(result, equals(oneSignalConfig)); - }); - - test('throws FormatException for missing provider field', () { - // Arrange: Create JSON without the discriminator field. - final jsonWithoutProvider = {'appId': 'test-app-id'}; - - // Assert: Deserializing should throw a FormatException. - expect( - () => PushNotificationProviderConfig.fromJson(jsonWithoutProvider), - throwsA(isA()), - ); - }); - - test('throws FormatException for unknown provider field', () { - // Arrange: Create JSON with an invalid discriminator. - final jsonWithUnknownProvider = { - 'provider': 'unknownProvider', - 'appId': 'test-app-id', - }; - - // Assert: Deserializing should throw a FormatException. - expect( - () => - PushNotificationProviderConfig.fromJson(jsonWithUnknownProvider), - throwsA(isA()), - ); - }); - }); - - group('toJson static method (polymorphic)', () { - test('correctly serializes a FirebaseProviderConfig instance', () { - expect( - PushNotificationProviderConfig.toJson(firebaseConfig), - equals(firebaseJson), - ); - }); - - test('correctly serializes a OneSignalProviderConfig instance', () { - expect( - PushNotificationProviderConfig.toJson(oneSignalConfig), - equals(oneSignalJson), - ); - }); - }); - }); -} From de18a1b9a54d4e41b0e2cf05acea1a23d6b7008e Mon Sep 17 00:00:00 2001 From: fulleni Date: Sat, 8 Nov 2025 10:13:08 +0100 Subject: [PATCH 6/8] test: remove providerConfigs from equality check - Remove providerConfigs from the equality comparison in PushNotificationConfig test - Exclude providerConfigs when copying and comparing PushNotificationConfig instances --- test/src/models/config/push_notification_config_test.dart | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/src/models/config/push_notification_config_test.dart b/test/src/models/config/push_notification_config_test.dart index 295529a..5410019 100644 --- a/test/src/models/config/push_notification_config_test.dart +++ b/test/src/models/config/push_notification_config_test.dart @@ -29,7 +29,6 @@ void main() { equals([ pushNotificationConfig.enabled, pushNotificationConfig.primaryProvider, - pushNotificationConfig.providerConfigs, pushNotificationConfig.deliveryConfigs, ]), ); @@ -65,10 +64,6 @@ void main() { // Assert: The new instance should have the updated values. expect(copiedConfig.enabled, equals(newEnabled)); expect(copiedConfig.primaryProvider, equals(newPrimaryProvider)); - expect( - copiedConfig.providerConfigs, - equals(pushNotificationConfig.providerConfigs), - ); expect( copiedConfig.deliveryConfigs, equals(pushNotificationConfig.deliveryConfigs), From 80206528bed7ad990a2adce13c01dde29e1bd606 Mon Sep 17 00:00:00 2001 From: fulleni Date: Sat, 8 Nov 2025 10:16:45 +0100 Subject: [PATCH 7/8] test(models): update PushNotificationDevice tests for providerTokens - Replace single token and provider with map of provider tokens - Update test cases to reflect new providerTokens structure - Adjust JSON representation to include multiple provider tokens - Modify copyWith test to use new providerTokens map --- .../push_notification_device_test.dart | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/test/src/models/push_notifications/push_notification_device_test.dart b/test/src/models/push_notifications/push_notification_device_test.dart index 9f3d39a..e83b3a3 100644 --- a/test/src/models/push_notifications/push_notification_device_test.dart +++ b/test/src/models/push_notifications/push_notification_device_test.dart @@ -7,18 +7,19 @@ void main() { group('PushNotificationDevice', () { const id = 'device-id-1'; const userId = 'user-id-1'; - const token = 'device-token-string'; - const provider = PushNotificationProvider.firebase; const platform = DevicePlatform.android; + const providerTokens = { + PushNotificationProvider.firebase: 'firebase-token-string', + PushNotificationProvider.oneSignal: 'onesignal-token-string', + }; final createdAt = DateTime.parse('2023-01-01T10:00:00.000Z'); final updatedAt = DateTime.parse('2023-01-01T11:00:00.000Z'); final device = PushNotificationDevice( id: id, userId: userId, - token: token, - provider: provider, platform: platform, + providerTokens: providerTokens, createdAt: createdAt, updatedAt: updatedAt, ); @@ -26,9 +27,11 @@ void main() { final json = { 'id': id, 'userId': userId, - 'token': token, - 'provider': 'firebase', 'platform': 'android', + 'providerTokens': { + 'firebase': 'firebase-token-string', + 'oneSignal': 'onesignal-token-string', + }, 'createdAt': '2023-01-01T10:00:00.000Z', 'updatedAt': '2023-01-01T11:00:00.000Z', }; @@ -38,9 +41,8 @@ void main() { final anotherDevice = PushNotificationDevice( id: id, userId: userId, - token: token, - provider: provider, platform: platform, + providerTokens: providerTokens, createdAt: createdAt, updatedAt: updatedAt, ); @@ -53,7 +55,7 @@ void main() { // Assert: The props list should contain all the fields. expect( device.props, - equals([id, userId, token, provider, platform, createdAt, updatedAt]), + equals([id, userId, platform, providerTokens, createdAt, updatedAt]), ); }); @@ -75,21 +77,23 @@ void main() { test('copyWith creates a copy with updated values', () { // Arrange: Define the updated values. - const newToken = 'new-device-token'; + const newProviderTokens = { + PushNotificationProvider.firebase: 'new-firebase-token', + }; final newUpdatedAt = DateTime.parse('2023-02-01T12:00:00.000Z'); // Act: Create a copy with the updated values. final copiedDevice = device.copyWith( - token: newToken, + providerTokens: newProviderTokens, updatedAt: newUpdatedAt, ); // Assert: The new instance should have the updated values. - expect(copiedDevice.token, equals(newToken)); + expect(copiedDevice.providerTokens, equals(newProviderTokens)); expect(copiedDevice.updatedAt, equals(newUpdatedAt)); // Assert: The original instance should remain unchanged. - expect(device.token, equals(token)); + expect(device.providerTokens, equals(providerTokens)); expect(device.updatedAt, equals(updatedAt)); }); From 9ce86e6446ab1a7e3fb71b80e638eb5170cc79c8 Mon Sep 17 00:00:00 2001 From: fulleni Date: Sat, 8 Nov 2025 10:25:36 +0100 Subject: [PATCH 8/8] docs(fix): correct dartdoc comment typo - Remove incorrect dartdoc tag 'push_notification_provider_config' - Improve documentation formatting for PushNotificationConfig class --- lib/src/models/config/push_notification_config.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/models/config/push_notification_config.dart b/lib/src/models/config/push_notification_config.dart index ff68552..3fe7efa 100644 --- a/lib/src/models/config/push_notification_config.dart +++ b/lib/src/models/config/push_notification_config.dart @@ -12,7 +12,7 @@ part 'push_notification_config.g.dart'; /// This model is part of the overall `RemoteConfig` and allows for remotely /// managing all aspects of push notifications, including feature availability /// and user-specific limits. -/// {@endtemplate}push_notification_provider_config +/// {@endtemplate} @immutable @JsonSerializable(explicitToJson: true, includeIfNull: true, checked: true) class PushNotificationConfig extends Equatable {