diff --git a/UnitTests/LocalNotification.UnitTests/CollectionDefinitions.cs b/UnitTests/LocalNotification.UnitTests/CollectionDefinitions.cs index 0e4bf51..e79c4a1 100644 --- a/UnitTests/LocalNotification.UnitTests/CollectionDefinitions.cs +++ b/UnitTests/LocalNotification.UnitTests/CollectionDefinitions.cs @@ -1,3 +1,5 @@ +[assembly: CollectionBehavior(DisableTestParallelization = true)] + namespace Plugin.LocalNotification.UnitTests; /// diff --git a/UnitTests/LocalNotification.UnitTests/LocalNotification.UnitTests.csproj b/UnitTests/LocalNotification.UnitTests/LocalNotification.UnitTests.csproj index ce87596..d488dbb 100644 --- a/UnitTests/LocalNotification.UnitTests/LocalNotification.UnitTests.csproj +++ b/UnitTests/LocalNotification.UnitTests/LocalNotification.UnitTests.csproj @@ -21,6 +21,7 @@ + all @@ -41,6 +42,7 @@ + \ No newline at end of file diff --git a/UnitTests/LocalNotification.UnitTests/Tests/CoverageTests.cs b/UnitTests/LocalNotification.UnitTests/Tests/CoverageTests.cs index 75d99ba..fec17dc 100644 --- a/UnitTests/LocalNotification.UnitTests/Tests/CoverageTests.cs +++ b/UnitTests/LocalNotification.UnitTests/Tests/CoverageTests.cs @@ -1,11 +1,14 @@ using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Plugin.LocalNotification.AndroidOption; using Plugin.LocalNotification.Core; using Plugin.LocalNotification.Core.Models; using Plugin.LocalNotification.Core.Models.AndroidOption; using Plugin.LocalNotification.Core.Models.AppleOption; using Plugin.LocalNotification.EventArgs; +using Plugin.LocalNotification.Geofence; using Plugin.LocalNotification.Platforms; +using Plugin.LocalNotification.Properties; using System.Reflection; using System.Threading.Tasks; @@ -854,4 +857,93 @@ public async Task Phase12_ActiveNotification_ShouldCoverModelAndGenericImplement var ifaceMethods = typeof(INotificationService).GetMethods(); ifaceMethods.Should().Contain(m => m.Name == nameof(INotificationService.GetActiveNotifications)); } + + [Fact] + public void Phase13_ChannelDefaultsAndResources_ShouldCoverRemainingSourceLines() + { + var channel = new AndroidNotificationChannelRequest(); + channel.LockScreenVisibility.Should().Be(AndroidVisibilityType.Private); + channel.CanBypassDnd.Should().BeFalse(); + + _ = new Resources(); + Resources.ResourceManager.Should().NotBeNull(); + Resources.Culture = null; + Resources.Culture.Should().BeNull(); + Resources.AndroidAlarmServiceNotFound.Should().NotBeNullOrEmpty(); + Resources.AndroidNotificationServiceNotFound.Should().NotBeNullOrEmpty(); + Resources.GeofencePackageMissing.Should().NotBeNullOrEmpty(); + Resources.PluginNotFound.Should().NotBeNullOrEmpty(); + Resources.PluginSerializerNotFound.Should().NotBeNullOrEmpty(); + } + + [Fact] + public void Phase14_MauiAndInitializeService_ShouldCoverInitializationAndExtensionReturnPath() + { + var useMethod = typeof(LocalNotificationExtensions).GetMethod(nameof(LocalNotificationExtensions.UseLocalNotification), BindingFlags.Public | BindingFlags.Static); + useMethod.Should().NotBeNull(); + var returnedBuilder = useMethod!.Invoke(null, [null, null]); + returnedBuilder.Should().BeNull(); + + var logger = NullLogger.Instance; + var notificationService = new Mock(); + LocalNotificationCenter.SetNotificationService(notificationService.Object); + + var customSerializer = new Mock().Object; + var localBuilder = new LocalNotificationBuilder(); + var category = new NotificationCategory(NotificationCategoryType.Status); + localBuilder.SetSerializer(customSerializer); + localBuilder.AddCategory(category); + + var serviceProvider = new Mock(); + serviceProvider.Setup(s => s.GetService(typeof(ILogger))).Returns(logger); + serviceProvider.Setup(s => s.GetService(typeof(LocalNotificationBuilder))).Returns(localBuilder); + + var initializer = new LocalNotificationInitializeService(); + initializer.Initialize(serviceProvider.Object); + + LocalNotificationLogger.Logger.Should().NotBeNull(); + LocalNotificationCenter.Serializer.Should().BeSameAs(customSerializer); + notificationService.Verify(s => s.RegisterCategoryList(It.Is>(set => set.Contains(category))), Times.Once); + } + + [Fact] + public void Phase15_TrimImageBinary_ShouldCoverExceptionPath() + { + const int notificationId = 777; + var imageDir = Path.Combine(Path.GetTempPath(), "Plugin.LocalNotification", "images"); + var imagePath = Path.Combine(imageDir, $"img_{notificationId}.bin"); + Directory.CreateDirectory(imageDir); + File.WriteAllBytes(imagePath, [1, 2, 3]); + File.SetAttributes(imagePath, FileAttributes.ReadOnly); + + var request = new NotificationRequest + { + NotificationId = notificationId, + Image = new NotificationImage { Binary = new byte[100_001] } + }; + + try + { + var serialized = LocalNotificationCenter.GetRequestSerialize(request); + serialized.Should().NotBeNullOrWhiteSpace(); + request.Image.Binary.Should().BeEmpty(); + } + finally + { + if (File.Exists(imagePath)) + { + File.SetAttributes(imagePath, FileAttributes.Normal); + File.Delete(imagePath); + } + } + } + + [Fact] + public void Phase16_GeofenceExtension_ShouldCoverReturnPath() + { + var useMethod = typeof(GeofenceExtensions).GetMethod(nameof(GeofenceExtensions.UseLocalNotificationGeofence), BindingFlags.Public | BindingFlags.Static); + useMethod.Should().NotBeNull(); + var returnedBuilder = useMethod!.Invoke(null, [null]); + returnedBuilder.Should().BeNull(); + } }