From d120deb04897955ac1506ccabda921fb16ed2c33 Mon Sep 17 00:00:00 2001 From: fulleni Date: Mon, 1 Sep 2025 07:53:46 +0100 Subject: [PATCH 01/10] feat(LocalAd): add unique identifier property - Add 'id' property to LocalAd class to provide a unique identifier for each local ad instance - Update documentation to reflect the new property --- lib/src/models/feed_decorators/local_ad.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/src/models/feed_decorators/local_ad.dart b/lib/src/models/feed_decorators/local_ad.dart index 0cae3c1..e188c44 100644 --- a/lib/src/models/feed_decorators/local_ad.dart +++ b/lib/src/models/feed_decorators/local_ad.dart @@ -69,6 +69,9 @@ abstract class LocalAd extends FeedItem { /// The type of the ad (e.g., banner, native, interstitial, video). final String adType; + /// A unique identifier for the local ad instance, typically a UUID. + String get id; + @override List get props => [adType, type]; } From 525345f5c8de8498c3238cb03032c3fcbdcaf19a Mon Sep 17 00:00:00 2001 From: fulleni Date: Mon, 1 Sep 2025 08:02:29 +0100 Subject: [PATCH 02/10] feat(LocalBannerAd): add createdAt, updatedAt, and status fields - Add 'createdAt' and 'updatedAt' DateTime fields for timestamp tracking - Add 'status' field to store the current status of the local banner ad - Update constructor and toJson method to include new fields - Modify props list to include new fields for equality checking - Update copyWith method to support new fields --- lib/src/models/local_ads/local_banner_ad.dart | 40 ++++++++++++++++++- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/lib/src/models/local_ads/local_banner_ad.dart b/lib/src/models/local_ads/local_banner_ad.dart index 31f5ea7..65fe606 100644 --- a/lib/src/models/local_ads/local_banner_ad.dart +++ b/lib/src/models/local_ads/local_banner_ad.dart @@ -1,4 +1,6 @@ import 'package:core/core.dart'; +import 'package:core/src/enums/enums.dart'; +import 'package:core/src/utils/utils.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:meta/meta.dart'; @@ -17,6 +19,9 @@ class LocalBannerAd extends LocalAd { required this.id, required this.imageUrl, required this.targetUrl, + required this.createdAt, + required this.updatedAt, + required this.status, }) : super(adType: 'banner'); /// Creates a [LocalBannerAd] from JSON data. @@ -24,6 +29,7 @@ class LocalBannerAd extends LocalAd { _$LocalBannerAdFromJson(json); /// Unique identifier for the local banner ad. + @override final String id; /// The URL of the image for the local banner ad. @@ -32,6 +38,17 @@ class LocalBannerAd extends LocalAd { /// The URL to navigate to when the local banner ad is clicked. final String targetUrl; + /// The creation timestamp of the local banner ad. + @JsonKey(fromJson: dateTimeFromJson, toJson: dateTimeToJson) + final DateTime createdAt; + + /// The last update timestamp of the local banner ad. + @JsonKey(fromJson: dateTimeFromJson, toJson: dateTimeToJson) + final DateTime updatedAt; + + /// The current status of the local banner ad. + final ContentStatus status; + Map toJson() { final json = _$LocalBannerAdToJson(this); json['adType'] = adType; @@ -40,15 +57,34 @@ class LocalBannerAd extends LocalAd { } @override - List get props => [id, imageUrl, targetUrl, adType, type]; + List get props => [ + id, + imageUrl, + targetUrl, + createdAt, + updatedAt, + status, + adType, + type, + ]; /// Creates a copy of this [LocalBannerAd] but with the given fields replaced with /// the new values. - LocalBannerAd copyWith({String? id, String? imageUrl, String? targetUrl}) { + LocalBannerAd copyWith({ + String? id, + String? imageUrl, + String? targetUrl, + DateTime? createdAt, + DateTime? updatedAt, + ContentStatus? status, + }) { return LocalBannerAd( id: id ?? this.id, imageUrl: imageUrl ?? this.imageUrl, targetUrl: targetUrl ?? this.targetUrl, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + status: status ?? this.status, ); } } From 6a956dfd6ce07745bd0b041b0f194658d0c8ebdb Mon Sep 17 00:00:00 2001 From: fulleni Date: Mon, 1 Sep 2025 08:02:39 +0100 Subject: [PATCH 03/10] feat(LocalInterstitialAd): add createdAt, updatedAt, and status fields - Add createdAt and updatedAt fields for tracking ad creation and update timestamps - Add status field to indicate the current status of the ad - Update props list to include new fields - Modify copyWith method to support new fields - Import necessary enums and utils for new fields --- .../local_ads/local_interstitial_ad.dart | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/lib/src/models/local_ads/local_interstitial_ad.dart b/lib/src/models/local_ads/local_interstitial_ad.dart index 82d2895..b00f71b 100644 --- a/lib/src/models/local_ads/local_interstitial_ad.dart +++ b/lib/src/models/local_ads/local_interstitial_ad.dart @@ -1,4 +1,6 @@ import 'package:core/core.dart'; +import 'package:core/src/enums/enums.dart'; +import 'package:core/src/utils/utils.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:meta/meta.dart'; @@ -18,6 +20,9 @@ class LocalInterstitialAd extends LocalAd { required this.id, required this.imageUrl, required this.targetUrl, + required this.createdAt, + required this.updatedAt, + required this.status, }) : super(adType: 'interstitial'); /// Creates a [LocalInterstitialAd] from JSON data. @@ -25,6 +30,7 @@ class LocalInterstitialAd extends LocalAd { _$LocalInterstitialAdFromJson(json); /// Unique identifier for the local interstitial ad. + @override final String id; /// The URL of the image for the local interstitial ad. @@ -33,6 +39,17 @@ class LocalInterstitialAd extends LocalAd { /// The URL to navigate to when the local interstitial ad is clicked. final String targetUrl; + /// The creation timestamp of the local interstitial ad. + @JsonKey(fromJson: dateTimeFromJson, toJson: dateTimeToJson) + final DateTime createdAt; + + /// The last update timestamp of the local interstitial ad. + @JsonKey(fromJson: dateTimeFromJson, toJson: dateTimeToJson) + final DateTime updatedAt; + + /// The current status of the local interstitial ad. + final ContentStatus status; + Map toJson() { final json = _$LocalInterstitialAdToJson(this); json['adType'] = adType; @@ -41,7 +58,16 @@ class LocalInterstitialAd extends LocalAd { } @override - List get props => [id, imageUrl, targetUrl, adType, type]; + List get props => [ + id, + imageUrl, + targetUrl, + createdAt, + updatedAt, + status, + adType, + type, + ]; /// Creates a copy of this [LocalInterstitialAd] but with the given fields /// replaced with the new values. @@ -49,11 +75,17 @@ class LocalInterstitialAd extends LocalAd { String? id, String? imageUrl, String? targetUrl, + DateTime? createdAt, + DateTime? updatedAt, + ContentStatus? status, }) { return LocalInterstitialAd( id: id ?? this.id, imageUrl: imageUrl ?? this.imageUrl, targetUrl: targetUrl ?? this.targetUrl, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + status: status ?? this.status, ); } } From 4553830f39058448be1a87361adc1734c341aec2 Mon Sep 17 00:00:00 2001 From: fulleni Date: Mon, 1 Sep 2025 08:02:49 +0100 Subject: [PATCH 04/10] feat(LocalNativeAd): add createdAt, updatedAt and status fields - Add 'createdAt' and 'updatedAt' DateTime fields for timestamp tracking - Add 'status' field of type ContentStatus for ad status management - Implement serialization and deserialization for new fields - Update constructor, copyWith method, and toJson/fromJson methods --- lib/src/models/local_ads/local_native_ad.dart | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/lib/src/models/local_ads/local_native_ad.dart b/lib/src/models/local_ads/local_native_ad.dart index a6b366d..11a80f8 100644 --- a/lib/src/models/local_ads/local_native_ad.dart +++ b/lib/src/models/local_ads/local_native_ad.dart @@ -1,4 +1,6 @@ import 'package:core/core.dart'; +import 'package:core/src/enums/enums.dart'; +import 'package:core/src/utils/utils.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:meta/meta.dart'; @@ -20,6 +22,9 @@ class LocalNativeAd extends LocalAd { required this.subtitle, required this.imageUrl, required this.targetUrl, + required this.createdAt, + required this.updatedAt, + required this.status, }) : super(adType: 'native'); /// Creates a [LocalNativeAd] from JSON data. @@ -27,6 +32,7 @@ class LocalNativeAd extends LocalAd { _$LocalNativeAdFromJson(json); /// Unique identifier for the local native ad. + @override final String id; /// The main title or headline of the local native ad. @@ -41,6 +47,17 @@ class LocalNativeAd extends LocalAd { /// The URL to navigate to when the local native ad is clicked. final String targetUrl; + /// The creation timestamp of the local native ad. + @JsonKey(fromJson: dateTimeFromJson, toJson: dateTimeToJson) + final DateTime createdAt; + + /// The last update timestamp of the local native ad. + @JsonKey(fromJson: dateTimeFromJson, toJson: dateTimeToJson) + final DateTime updatedAt; + + /// The current status of the local native ad. + final ContentStatus status; + Map toJson() { final json = _$LocalNativeAdToJson(this); json['adType'] = adType; @@ -55,6 +72,9 @@ class LocalNativeAd extends LocalAd { subtitle, imageUrl, targetUrl, + createdAt, + updatedAt, + status, adType, type, ]; @@ -67,6 +87,9 @@ class LocalNativeAd extends LocalAd { String? subtitle, String? imageUrl, String? targetUrl, + DateTime? createdAt, + DateTime? updatedAt, + ContentStatus? status, }) { return LocalNativeAd( id: id ?? this.id, @@ -74,6 +97,9 @@ class LocalNativeAd extends LocalAd { subtitle: subtitle ?? this.subtitle, imageUrl: imageUrl ?? this.imageUrl, targetUrl: targetUrl ?? this.targetUrl, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + status: status ?? this.status, ); } } From f092ebbc16dcd4d12e3ea19b8eea9d53c309e5de Mon Sep 17 00:00:00 2001 From: fulleni Date: Mon, 1 Sep 2025 08:03:00 +0100 Subject: [PATCH 05/10] feat(LocalVideoAd): enhance with additional properties and methods - Add createdAt, updatedAt, and status fields with JSON serialization support - Implement equality and props for new fields - Extend copyWith method to include new properties - Update imports to include necessary packages --- lib/src/models/local_ads/local_video_ad.dart | 40 +++++++++++++++++++- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/lib/src/models/local_ads/local_video_ad.dart b/lib/src/models/local_ads/local_video_ad.dart index 855d295..2bd80fa 100644 --- a/lib/src/models/local_ads/local_video_ad.dart +++ b/lib/src/models/local_ads/local_video_ad.dart @@ -1,4 +1,6 @@ import 'package:core/core.dart'; +import 'package:core/src/enums/enums.dart'; +import 'package:core/src/utils/utils.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:meta/meta.dart'; @@ -17,6 +19,9 @@ class LocalVideoAd extends LocalAd { required this.id, required this.videoUrl, required this.targetUrl, + required this.createdAt, + required this.updatedAt, + required this.status, }) : super(adType: 'video'); /// Creates a [LocalVideoAd] from JSON data. @@ -24,6 +29,7 @@ class LocalVideoAd extends LocalAd { _$LocalVideoAdFromJson(json); /// Unique identifier for the local video ad. + @override final String id; /// The URL of the video content for the local video ad. @@ -32,6 +38,17 @@ class LocalVideoAd extends LocalAd { /// The URL to navigate to when the local video ad is clicked. final String targetUrl; + /// The creation timestamp of the local video ad. + @JsonKey(fromJson: dateTimeFromJson, toJson: dateTimeToJson) + final DateTime createdAt; + + /// The last update timestamp of the local video ad. + @JsonKey(fromJson: dateTimeFromJson, toJson: dateTimeToJson) + final DateTime updatedAt; + + /// The current status of the local video ad. + final ContentStatus status; + Map toJson() { final json = _$LocalVideoAdToJson(this); json['adType'] = adType; @@ -40,15 +57,34 @@ class LocalVideoAd extends LocalAd { } @override - List get props => [id, videoUrl, targetUrl, adType, type]; + List get props => [ + id, + videoUrl, + targetUrl, + createdAt, + updatedAt, + status, + adType, + type, + ]; /// Creates a copy of this [LocalVideoAd] but with the given fields /// replaced with the new values. - LocalVideoAd copyWith({String? id, String? videoUrl, String? targetUrl}) { + LocalVideoAd copyWith({ + String? id, + String? videoUrl, + String? targetUrl, + DateTime? createdAt, + DateTime? updatedAt, + ContentStatus? status, + }) { return LocalVideoAd( id: id ?? this.id, videoUrl: videoUrl ?? this.videoUrl, targetUrl: targetUrl ?? this.targetUrl, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + status: status ?? this.status, ); } } From 5dd3980941c24f1d97c98d78985c00a1286c1e10 Mon Sep 17 00:00:00 2001 From: fulleni Date: Mon, 1 Sep 2025 08:04:01 +0100 Subject: [PATCH 06/10] chore: build files --- .../models/local_ads/local_banner_ad.g.dart | 21 +++++++++++++++++++ .../local_ads/local_interstitial_ad.g.dart | 21 +++++++++++++++++++ .../models/local_ads/local_native_ad.g.dart | 21 +++++++++++++++++++ .../models/local_ads/local_video_ad.g.dart | 21 +++++++++++++++++++ 4 files changed, 84 insertions(+) diff --git a/lib/src/models/local_ads/local_banner_ad.g.dart b/lib/src/models/local_ads/local_banner_ad.g.dart index c4dfc78..fbdfd7e 100644 --- a/lib/src/models/local_ads/local_banner_ad.g.dart +++ b/lib/src/models/local_ads/local_banner_ad.g.dart @@ -12,6 +12,18 @@ LocalBannerAd _$LocalBannerAdFromJson(Map json) => id: $checkedConvert('id', (v) => v as String), imageUrl: $checkedConvert('imageUrl', (v) => v as String), targetUrl: $checkedConvert('targetUrl', (v) => v as String), + createdAt: $checkedConvert( + 'createdAt', + (v) => dateTimeFromJson(v as String?), + ), + updatedAt: $checkedConvert( + 'updatedAt', + (v) => dateTimeFromJson(v as String?), + ), + status: $checkedConvert( + 'status', + (v) => $enumDecode(_$ContentStatusEnumMap, v), + ), ); return val; }); @@ -21,4 +33,13 @@ Map _$LocalBannerAdToJson(LocalBannerAd instance) => 'id': instance.id, 'imageUrl': instance.imageUrl, 'targetUrl': instance.targetUrl, + 'createdAt': dateTimeToJson(instance.createdAt), + 'updatedAt': dateTimeToJson(instance.updatedAt), + 'status': _$ContentStatusEnumMap[instance.status]!, }; + +const _$ContentStatusEnumMap = { + ContentStatus.active: 'active', + ContentStatus.draft: 'draft', + ContentStatus.archived: 'archived', +}; diff --git a/lib/src/models/local_ads/local_interstitial_ad.g.dart b/lib/src/models/local_ads/local_interstitial_ad.g.dart index 3b135bd..5e7dac4 100644 --- a/lib/src/models/local_ads/local_interstitial_ad.g.dart +++ b/lib/src/models/local_ads/local_interstitial_ad.g.dart @@ -12,6 +12,18 @@ LocalInterstitialAd _$LocalInterstitialAdFromJson(Map json) => id: $checkedConvert('id', (v) => v as String), imageUrl: $checkedConvert('imageUrl', (v) => v as String), targetUrl: $checkedConvert('targetUrl', (v) => v as String), + createdAt: $checkedConvert( + 'createdAt', + (v) => dateTimeFromJson(v as String?), + ), + updatedAt: $checkedConvert( + 'updatedAt', + (v) => dateTimeFromJson(v as String?), + ), + status: $checkedConvert( + 'status', + (v) => $enumDecode(_$ContentStatusEnumMap, v), + ), ); return val; }); @@ -22,4 +34,13 @@ Map _$LocalInterstitialAdToJson( 'id': instance.id, 'imageUrl': instance.imageUrl, 'targetUrl': instance.targetUrl, + 'createdAt': dateTimeToJson(instance.createdAt), + 'updatedAt': dateTimeToJson(instance.updatedAt), + 'status': _$ContentStatusEnumMap[instance.status]!, +}; + +const _$ContentStatusEnumMap = { + ContentStatus.active: 'active', + ContentStatus.draft: 'draft', + ContentStatus.archived: 'archived', }; diff --git a/lib/src/models/local_ads/local_native_ad.g.dart b/lib/src/models/local_ads/local_native_ad.g.dart index 23695f7..9a55202 100644 --- a/lib/src/models/local_ads/local_native_ad.g.dart +++ b/lib/src/models/local_ads/local_native_ad.g.dart @@ -14,6 +14,18 @@ LocalNativeAd _$LocalNativeAdFromJson(Map json) => subtitle: $checkedConvert('subtitle', (v) => v as String), imageUrl: $checkedConvert('imageUrl', (v) => v as String), targetUrl: $checkedConvert('targetUrl', (v) => v as String), + createdAt: $checkedConvert( + 'createdAt', + (v) => dateTimeFromJson(v as String?), + ), + updatedAt: $checkedConvert( + 'updatedAt', + (v) => dateTimeFromJson(v as String?), + ), + status: $checkedConvert( + 'status', + (v) => $enumDecode(_$ContentStatusEnumMap, v), + ), ); return val; }); @@ -25,4 +37,13 @@ Map _$LocalNativeAdToJson(LocalNativeAd instance) => 'subtitle': instance.subtitle, 'imageUrl': instance.imageUrl, 'targetUrl': instance.targetUrl, + 'createdAt': dateTimeToJson(instance.createdAt), + 'updatedAt': dateTimeToJson(instance.updatedAt), + 'status': _$ContentStatusEnumMap[instance.status]!, }; + +const _$ContentStatusEnumMap = { + ContentStatus.active: 'active', + ContentStatus.draft: 'draft', + ContentStatus.archived: 'archived', +}; diff --git a/lib/src/models/local_ads/local_video_ad.g.dart b/lib/src/models/local_ads/local_video_ad.g.dart index b500ce2..6e02f21 100644 --- a/lib/src/models/local_ads/local_video_ad.g.dart +++ b/lib/src/models/local_ads/local_video_ad.g.dart @@ -12,6 +12,18 @@ LocalVideoAd _$LocalVideoAdFromJson(Map json) => id: $checkedConvert('id', (v) => v as String), videoUrl: $checkedConvert('videoUrl', (v) => v as String), targetUrl: $checkedConvert('targetUrl', (v) => v as String), + createdAt: $checkedConvert( + 'createdAt', + (v) => dateTimeFromJson(v as String?), + ), + updatedAt: $checkedConvert( + 'updatedAt', + (v) => dateTimeFromJson(v as String?), + ), + status: $checkedConvert( + 'status', + (v) => $enumDecode(_$ContentStatusEnumMap, v), + ), ); return val; }); @@ -21,4 +33,13 @@ Map _$LocalVideoAdToJson(LocalVideoAd instance) => 'id': instance.id, 'videoUrl': instance.videoUrl, 'targetUrl': instance.targetUrl, + 'createdAt': dateTimeToJson(instance.createdAt), + 'updatedAt': dateTimeToJson(instance.updatedAt), + 'status': _$ContentStatusEnumMap[instance.status]!, }; + +const _$ContentStatusEnumMap = { + ContentStatus.active: 'active', + ContentStatus.draft: 'draft', + ContentStatus.archived: 'archived', +}; From 3082e5c3ee480e5c1bb2a2aed064b1c8dbd64d63 Mon Sep 17 00:00:00 2001 From: fulleni Date: Mon, 1 Sep 2025 08:05:45 +0100 Subject: [PATCH 07/10] fix(mock): update local ads fixtures with missing properties - Add createdAt, updatedAt, and status fields to local ads - Remove const keyword to allow property initialization - Import ContentStatus enum from core package --- lib/src/fixtures/local_ads.dart | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/lib/src/fixtures/local_ads.dart b/lib/src/fixtures/local_ads.dart index 68b7f75..f4c2a3f 100644 --- a/lib/src/fixtures/local_ads.dart +++ b/lib/src/fixtures/local_ads.dart @@ -1,39 +1,58 @@ import 'package:core/core.dart'; +import 'package:core/src/enums/enums.dart'; // Import ContentStatus /// A list of predefined local ads for fixture data. final localAdsFixturesData = [ - const LocalNativeAd( + LocalNativeAd( id: kLocalAd1Id, title: 'Discover Our Premium Content', subtitle: 'Unlock exclusive articles and an ad-free experience.', imageUrl: 'https://example.com/ads/premium_native.png', targetUrl: 'https://example.com/premium', + createdAt: DateTime.now(), + updatedAt: DateTime.now(), + status: ContentStatus.active, ), - const LocalBannerAd( + LocalBannerAd( id: kLocalAd2Id, imageUrl: 'https://example.com/ads/banner_ad_1.png', targetUrl: 'https://example.com/offer1', + createdAt: DateTime.now(), + updatedAt: DateTime.now(), + status: ContentStatus.active, ), - const LocalInterstitialAd( + LocalInterstitialAd( id: kLocalAd3Id, imageUrl: 'https://example.com/ads/interstitial_ad_1.png', targetUrl: 'https://example.com/special_offer', + createdAt: DateTime.now(), + updatedAt: DateTime.now(), + status: ContentStatus.active, ), - const LocalVideoAd( + LocalVideoAd( id: kLocalAd4Id, videoUrl: 'https://example.com/ads/promo_video.mp4', targetUrl: 'https://example.com/watch_more', + createdAt: DateTime.now(), + updatedAt: DateTime.now(), + status: ContentStatus.active, ), - const LocalNativeAd( + LocalNativeAd( id: kLocalAd5Id, title: 'Stay Informed with Daily Briefings', subtitle: 'Get the top news delivered straight to your inbox.', imageUrl: 'https://example.com/ads/briefing_native.png', targetUrl: 'https://example.com/subscribe', + createdAt: DateTime.now(), + updatedAt: DateTime.now(), + status: ContentStatus.active, ), - const LocalBannerAd( + LocalBannerAd( id: kLocalAd6Id, imageUrl: 'https://example.com/ads/banner_ad_2.png', targetUrl: 'https://example.com/offer2', + createdAt: DateTime.now(), + updatedAt: DateTime.now(), + status: ContentStatus.active, ), ]; From db9b6c32372cb0eaf1f44b46545dde211b386ac8 Mon Sep 17 00:00:00 2001 From: fulleni Date: Mon, 1 Sep 2025 08:06:04 +0100 Subject: [PATCH 08/10] lint: misc --- lib/src/fixtures/local_ads.dart | 2 +- lib/src/models/local_ads/local_banner_ad.dart | 1 - lib/src/models/local_ads/local_interstitial_ad.dart | 1 - lib/src/models/local_ads/local_native_ad.dart | 1 - lib/src/models/local_ads/local_video_ad.dart | 1 - 5 files changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/src/fixtures/local_ads.dart b/lib/src/fixtures/local_ads.dart index f4c2a3f..692a379 100644 --- a/lib/src/fixtures/local_ads.dart +++ b/lib/src/fixtures/local_ads.dart @@ -1,5 +1,5 @@ import 'package:core/core.dart'; -import 'package:core/src/enums/enums.dart'; // Import ContentStatus +// Import ContentStatus /// A list of predefined local ads for fixture data. final localAdsFixturesData = [ diff --git a/lib/src/models/local_ads/local_banner_ad.dart b/lib/src/models/local_ads/local_banner_ad.dart index 65fe606..62341c6 100644 --- a/lib/src/models/local_ads/local_banner_ad.dart +++ b/lib/src/models/local_ads/local_banner_ad.dart @@ -1,5 +1,4 @@ import 'package:core/core.dart'; -import 'package:core/src/enums/enums.dart'; import 'package:core/src/utils/utils.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:meta/meta.dart'; diff --git a/lib/src/models/local_ads/local_interstitial_ad.dart b/lib/src/models/local_ads/local_interstitial_ad.dart index b00f71b..9ddcb70 100644 --- a/lib/src/models/local_ads/local_interstitial_ad.dart +++ b/lib/src/models/local_ads/local_interstitial_ad.dart @@ -1,5 +1,4 @@ import 'package:core/core.dart'; -import 'package:core/src/enums/enums.dart'; import 'package:core/src/utils/utils.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:meta/meta.dart'; diff --git a/lib/src/models/local_ads/local_native_ad.dart b/lib/src/models/local_ads/local_native_ad.dart index 11a80f8..d86d42d 100644 --- a/lib/src/models/local_ads/local_native_ad.dart +++ b/lib/src/models/local_ads/local_native_ad.dart @@ -1,5 +1,4 @@ import 'package:core/core.dart'; -import 'package:core/src/enums/enums.dart'; import 'package:core/src/utils/utils.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:meta/meta.dart'; diff --git a/lib/src/models/local_ads/local_video_ad.dart b/lib/src/models/local_ads/local_video_ad.dart index 2bd80fa..f94bad9 100644 --- a/lib/src/models/local_ads/local_video_ad.dart +++ b/lib/src/models/local_ads/local_video_ad.dart @@ -1,5 +1,4 @@ import 'package:core/core.dart'; -import 'package:core/src/enums/enums.dart'; import 'package:core/src/utils/utils.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:meta/meta.dart'; From 110b856056ba6bf568bd4c9e20459d3de301072b Mon Sep 17 00:00:00 2001 From: fulleni Date: Mon, 1 Sep 2025 08:18:32 +0100 Subject: [PATCH 09/10] test(local_ad): refactor and enhance unit tests for LocalAd and subclasses - Refactor test structure to focus on LocalAd class - Add tests for toJson method and unknown adType - Remove redundant tests and improve code readability - Introduce helper class for unknown LocalAd type testing --- .../models/feed_decorators/local_ad_test.dart | 210 ++++++------------ 1 file changed, 67 insertions(+), 143 deletions(-) diff --git a/test/src/models/feed_decorators/local_ad_test.dart b/test/src/models/feed_decorators/local_ad_test.dart index 20fdf9c..5d0e42f 100644 --- a/test/src/models/feed_decorators/local_ad_test.dart +++ b/test/src/models/feed_decorators/local_ad_test.dart @@ -2,53 +2,51 @@ import 'package:core/core.dart'; import 'package:test/test.dart'; void main() { - group('LocalAd (Abstract Class)', () { - // Test that LocalAd.fromJson correctly dispatches to concrete types - group('fromJson dispatching', () { + group('LocalAd', () { + final mockLocalNativeAd = + localAdsFixturesData.firstWhere((ad) => ad.adType == 'native') + as LocalNativeAd; + final mockLocalBannerAd = + localAdsFixturesData.firstWhere((ad) => ad.adType == 'banner') + as LocalBannerAd; + final mockLocalInterstitialAd = + localAdsFixturesData.firstWhere((ad) => ad.adType == 'interstitial') + as LocalInterstitialAd; + final mockLocalVideoAd = + localAdsFixturesData.firstWhere((ad) => ad.adType == 'video') + as LocalVideoAd; + + group('fromJson', () { test('dispatches to LocalNativeAd.fromJson', () { - final json = - (localAdsFixturesData.firstWhere((ad) => ad.adType == 'native') - as LocalNativeAd) - .toJson(); + final json = mockLocalNativeAd.toJson(); final localAd = LocalAd.fromJson(json); expect(localAd, isA()); - expect(localAd, equals(localAdsFixturesData[0])); + expect(localAd, equals(mockLocalNativeAd)); }); test('dispatches to LocalBannerAd.fromJson', () { - final json = - (localAdsFixturesData.firstWhere((ad) => ad.adType == 'banner') - as LocalBannerAd) - .toJson(); + final json = mockLocalBannerAd.toJson(); final localAd = LocalAd.fromJson(json); expect(localAd, isA()); - expect(localAd, equals(localAdsFixturesData[1])); + expect(localAd, equals(mockLocalBannerAd)); }); test('dispatches to LocalInterstitialAd.fromJson', () { - final json = - (localAdsFixturesData.firstWhere( - (ad) => ad.adType == 'interstitial', - ) - as LocalInterstitialAd) - .toJson(); + final json = mockLocalInterstitialAd.toJson(); final localAd = LocalAd.fromJson(json); expect(localAd, isA()); - expect(localAd, equals(localAdsFixturesData[2])); + expect(localAd, equals(mockLocalInterstitialAd)); }); test('dispatches to LocalVideoAd.fromJson', () { - final json = - (localAdsFixturesData.firstWhere((ad) => ad.adType == 'video') - as LocalVideoAd) - .toJson(); + final json = mockLocalVideoAd.toJson(); final localAd = LocalAd.fromJson(json); expect(localAd, isA()); - expect(localAd, equals(localAdsFixturesData[3])); + expect(localAd, equals(mockLocalVideoAd)); }); test('throws FormatException if adType is missing', () { - final json = {'id': 'some-id', 'type': 'localAd'}; + final json = {'id': 'some-id'}; expect( () => LocalAd.fromJson(json), throwsA( @@ -62,151 +60,77 @@ void main() { }); test('throws FormatException if adType is unknown', () { - final json = { - 'id': 'some-id', - 'type': 'localAd', - 'adType': 'unknown_type', - }; + final json = {'adType': 'unknown_ad_type'}; expect( () => LocalAd.fromJson(json), throwsA( isA().having( (e) => e.message, 'message', - 'Unknown LocalAd type: unknown_type', // Corrected from LocalAds + 'Unknown LocalAd type: unknown_ad_type', ), ), ); }); }); - group('toJson dispatching', () { - test('serializes LocalNativeAd correctly via LocalAd.toJson', () { - final mockLocalNativeAd = - localAdsFixturesData.firstWhere((ad) => ad.adType == 'native') - as LocalNativeAd; + group('toJson', () { + test('serializes LocalNativeAd correctly', () { final json = mockLocalNativeAd.toJson(); - expect(LocalAd.toJson(mockLocalNativeAd), equals(json)); + final deserialized = LocalAd.fromJson(json) as LocalNativeAd; + expect(LocalAd.toJson(deserialized), equals(json)); }); - test('serializes LocalBannerAd correctly via LocalAd.toJson', () { - final mockLocalBannerAd = - localAdsFixturesData.firstWhere((ad) => ad.adType == 'banner') - as LocalBannerAd; + test('serializes LocalBannerAd correctly', () { final json = mockLocalBannerAd.toJson(); - expect(LocalAd.toJson(mockLocalBannerAd), equals(json)); + final deserialized = LocalAd.fromJson(json) as LocalBannerAd; + expect(LocalAd.toJson(deserialized), equals(json)); }); - test('serializes LocalInterstitialAd correctly via LocalAd.toJson', () { - final mockLocalInterstitialAd = - localAdsFixturesData.firstWhere((ad) => ad.adType == 'interstitial') - as LocalInterstitialAd; + test('serializes LocalInterstitialAd correctly', () { final json = mockLocalInterstitialAd.toJson(); - expect(LocalAd.toJson(mockLocalInterstitialAd), equals(json)); + final deserialized = LocalAd.fromJson(json) as LocalInterstitialAd; + expect(LocalAd.toJson(deserialized), equals(json)); }); - test('serializes LocalVideoAd correctly via LocalAd.toJson', () { - final mockLocalVideoAd = - localAdsFixturesData.firstWhere((ad) => ad.adType == 'video') - as LocalVideoAd; + test('serializes LocalVideoAd correctly', () { final json = mockLocalVideoAd.toJson(); - expect(LocalAd.toJson(mockLocalVideoAd), equals(json)); + final deserialized = LocalAd.fromJson(json) as LocalVideoAd; + expect(LocalAd.toJson(deserialized), equals(json)); }); - }); - - // Test props for a concrete LocalAd subclass (LocalNativeAd) - // The test name is misleading as it tests a concrete instance's props. - // The expectation is updated to reflect all properties of LocalNativeAd. - test('props are correct for LocalNativeAd instance', () { - final localAd = - localAdsFixturesData.firstWhere((ad) => ad.adType == 'native') - as LocalNativeAd; - expect(localAd.props, [ - localAd.id, - localAd.title, - localAd.subtitle, - localAd.imageUrl, - localAd.targetUrl, - localAd.adType, - localAd.type, - ]); - }); - }); - - group('LocalNativeAd (Concrete Subclass)', () { - final mockLocalNativeAd = - localAdsFixturesData.firstWhere((ad) => ad.adType == 'native') - as LocalNativeAd; - - test('supports value equality', () { - final item1 = - localAdsFixturesData.firstWhere((ad) => ad.adType == 'native') - as LocalNativeAd; - expect(item1, equals(mockLocalNativeAd)); - }); - - test('props are correct', () { - expect(mockLocalNativeAd.props, [ - mockLocalNativeAd.id, - mockLocalNativeAd.title, - mockLocalNativeAd.subtitle, - mockLocalNativeAd.imageUrl, - mockLocalNativeAd.targetUrl, - mockLocalNativeAd.adType, - mockLocalNativeAd.type, - ]); - }); - group('copyWith', () { - test('returns a new instance with updated fields', () { - const newTitle = 'New Title'; - final updatedLocalAd = mockLocalNativeAd.copyWith(title: newTitle); - - expect(updatedLocalAd.id, mockLocalNativeAd.id); - expect(updatedLocalAd.title, newTitle); - expect(updatedLocalAd.subtitle, mockLocalNativeAd.subtitle); - expect(updatedLocalAd.imageUrl, mockLocalNativeAd.imageUrl); - expect(updatedLocalAd.targetUrl, mockLocalNativeAd.targetUrl); - expect(updatedLocalAd.adType, mockLocalNativeAd.adType); - expect(updatedLocalAd.type, mockLocalNativeAd.type); - }); - - test('returns an identical copy if no updates provided', () { - final copiedLocalAd = mockLocalNativeAd.copyWith(); - expect(copiedLocalAd, mockLocalNativeAd); - expect(identical(copiedLocalAd, mockLocalNativeAd), isFalse); + test('throws FormatException if adType is unknown for toJson', () { + // Create a mock LocalAd with an unknown adType for testing toJson + const unknownLocalAd = _UnknownLocalAd( + id: 'unknown-id', + adType: 'unknown_ad_type', + ); + expect( + () => LocalAd.toJson(unknownLocalAd), + throwsA( + isA().having( + (e) => e.message, + 'message', + 'Unknown LocalAd type for toJson: unknown_ad_type', + ), + ), + ); }); }); + }); +} - group('JSON serialization', () { - test('serializes full LocalNativeAd object to JSON', () { - final json = mockLocalNativeAd.toJson(); +// Helper class to simulate an unknown LocalAd type for testing toJson error +class _UnknownLocalAd extends LocalAd { + const _UnknownLocalAd({required super.adType, required this.id}); - expect(json, { - 'id': mockLocalNativeAd.id, - 'title': mockLocalNativeAd.title, - 'subtitle': mockLocalNativeAd.subtitle, - 'imageUrl': mockLocalNativeAd.imageUrl, - 'targetUrl': mockLocalNativeAd.targetUrl, - 'adType': 'native', - 'type': 'localAd', - }); - }); + @override + final String id; - test('deserializes full JSON to LocalNativeAd object', () { - final json = { - 'id': mockLocalNativeAd.id, - 'title': mockLocalNativeAd.title, - 'subtitle': mockLocalNativeAd.subtitle, - 'imageUrl': mockLocalNativeAd.imageUrl, - 'targetUrl': mockLocalNativeAd.targetUrl, - 'adType': 'native', - 'type': 'localAd', - }; - final localAd = LocalNativeAd.fromJson(json); + Map toJson() { + throw UnimplementedError(); + } - expect(localAd, equals(mockLocalNativeAd)); - }); - }); - }); + @override + List get props => [...super.props, id]; } From 8b3d79c15703fb0a2667b739997bed4179fd9f2c Mon Sep 17 00:00:00 2001 From: fulleni Date: Mon, 1 Sep 2025 08:18:41 +0100 Subject: [PATCH 10/10] docs(README): update code coverage percentage - Update coverage badge in README.md from 98% to 97% --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e35ca02..2674b3f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # 🛠️ core -![coverage: percentage](https://img.shields.io/badge/coverage-98-green) +![coverage: percentage](https://img.shields.io/badge/coverage-97-green) [![style: very good analysis](https://img.shields.io/badge/style-very_good_analysis-B22C89.svg)](https://pub.dev/packages/very_good_analysis) [![License: PolyForm Free Trial](https://img.shields.io/badge/License-PolyForm%20Free%20Trial-blue)](https://polyformproject.org/licenses/free-trial/1.0.0)