From 2c8869f6669d2a7f780b91cfbb0447518d08b906 Mon Sep 17 00:00:00 2001 From: rahulsainani Date: Fri, 13 Jan 2023 11:15:08 +0000 Subject: [PATCH] [fenix] Bug 1810114 - Part 1: Add isNotificationChannelEnabled helper function and tests for NotificationManagerCompat.kt --- .../fenix/ext/NotificationManagerCompat.kt | 40 ++++++ .../ext/NotificationManagerCompatTest.kt | 119 ++++++++++++++++++ 2 files changed, 159 insertions(+) create mode 100644 app/src/test/java/org/mozilla/fenix/ext/NotificationManagerCompatTest.kt diff --git a/app/src/main/java/org/mozilla/fenix/ext/NotificationManagerCompat.kt b/app/src/main/java/org/mozilla/fenix/ext/NotificationManagerCompat.kt index da582acf01..779126d4e5 100644 --- a/app/src/main/java/org/mozilla/fenix/ext/NotificationManagerCompat.kt +++ b/app/src/main/java/org/mozilla/fenix/ext/NotificationManagerCompat.kt @@ -4,6 +4,8 @@ package org.mozilla.fenix.ext +import android.os.Build +import androidx.core.app.NotificationChannelCompat import androidx.core.app.NotificationManagerCompat /** @@ -18,3 +20,41 @@ fun NotificationManagerCompat.areNotificationsEnabledSafe(): Boolean { false } } + +/** + * If the channel does not exist or is null, this returns false. + * If the channel exists with importance more than [NotificationManagerCompat.IMPORTANCE_NONE] and + * notifications are enabled for the app, this returns true. + * On <= SDK 26, this checks if notifications are enabled for the app. + * + * @param channelId the id of the notification channel to check. + * @return true if the channel is enabled, false otherwise. + */ +fun NotificationManagerCompat.isNotificationChannelEnabled(channelId: String): Boolean { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val channel = getNotificationChannelSafe(channelId) + if (channel == null) { + false + } else { + areNotificationsEnabledSafe() && channel.importance != NotificationManagerCompat.IMPORTANCE_NONE + } + } else { + areNotificationsEnabledSafe() + } +} + +/** + * Returns the notification channel with the given [channelId], or null if the channel does not + * exist, catches any exception that was thrown by + * [NotificationManagerCompat.getNotificationChannelCompat] and returns null. + * + * @param channelId the id of the notification channel to check. + */ +@Suppress("TooGenericExceptionCaught") +private fun NotificationManagerCompat.getNotificationChannelSafe(channelId: String): NotificationChannelCompat? { + return try { + getNotificationChannelCompat(channelId) + } catch (e: Exception) { + null + } +} diff --git a/app/src/test/java/org/mozilla/fenix/ext/NotificationManagerCompatTest.kt b/app/src/test/java/org/mozilla/fenix/ext/NotificationManagerCompatTest.kt new file mode 100644 index 0000000000..f9edfc17fb --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/ext/NotificationManagerCompatTest.kt @@ -0,0 +1,119 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.ext + +import android.os.Build +import androidx.core.app.NotificationChannelCompat +import androidx.core.app.NotificationManagerCompat +import io.mockk.every +import io.mockk.mockk +import io.mockk.mockkStatic +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mozilla.fenix.helpers.FenixRobolectricTestRunner +import org.robolectric.util.ReflectionHelpers + +@RunWith(FenixRobolectricTestRunner::class) +class NotificationManagerCompatTest { + + private lateinit var tested: NotificationManagerCompat + + @Before + fun setup() { + tested = mockk(relaxed = true) + + mockkStatic("org.mozilla.fenix.ext.NotificationManagerCompatKt") + } + + @Test + fun `WHEN areNotificationsEnabled throws an exception THEN areNotificationsEnabledSafe returns false`() { + every { tested.areNotificationsEnabled() } throws RuntimeException() + + assertFalse(tested.areNotificationsEnabledSafe()) + } + + @Test + fun `WHEN areNotificationsEnabled returns false THEN areNotificationsEnabledSafe returns false`() { + every { tested.areNotificationsEnabled() } returns false + + assertFalse(tested.areNotificationsEnabledSafe()) + } + + @Test + fun `WHEN areNotificationsEnabled returns true THEN areNotificationsEnabledSafe returns true`() { + every { tested.areNotificationsEnabled() } returns true + + assertTrue(tested.areNotificationsEnabledSafe()) + } + + @Test + fun `WHEN getNotificationChannelCompat returns a channel with IMPORTANCE_DEFAULT and areNotificationsEnabled returns true THEN isNotificationChannelEnabled returns true`() { + val testChannel = "test-channel" + val notificationChannelCompat = + NotificationChannelCompat.Builder( + testChannel, + NotificationManagerCompat.IMPORTANCE_DEFAULT, + ).build() + + every { tested.getNotificationChannelCompat(testChannel) } returns notificationChannelCompat + every { tested.areNotificationsEnabled() } returns true + + assertTrue(tested.isNotificationChannelEnabled(testChannel)) + } + + @Test + fun `WHEN getNotificationChannelCompat returns a channel with IMPORTANCE_NONE and areNotificationsEnabled returns true THEN isNotificationChannelEnabled returns false`() { + val testChannel = "test-channel" + val notificationChannelCompat = + NotificationChannelCompat.Builder( + testChannel, + NotificationManagerCompat.IMPORTANCE_NONE, + ).build() + + every { tested.getNotificationChannelCompat(testChannel) } returns notificationChannelCompat + every { tested.areNotificationsEnabled() } returns true + + assertFalse(tested.isNotificationChannelEnabled(testChannel)) + } + + @Test + fun `WHEN getNotificationChannelCompat returns a channel and areNotificationsEnabled returns false THEN isNotificationChannelEnabled returns false`() { + val testChannel = "test-channel" + val notificationChannelCompat = + NotificationChannelCompat.Builder( + testChannel, + NotificationManagerCompat.IMPORTANCE_DEFAULT, + ).build() + + every { tested.getNotificationChannelCompat(testChannel) } returns notificationChannelCompat + every { tested.areNotificationsEnabled() } returns false + + assertFalse(tested.isNotificationChannelEnabled(testChannel)) + } + + @Test + fun `WHEN getNotificationChannelCompat returns null THEN isNotificationChannelEnabled returns false`() { + val testChannel = "test-channel" + + every { tested.getNotificationChannelCompat(testChannel) } returns null + every { tested.areNotificationsEnabled() } returns true + + assertFalse(tested.isNotificationChannelEnabled(testChannel)) + } + + @Test + fun `WHEN sdk less than 26 and areNotificationsEnabled returns true THEN isNotificationChannelEnabled returns true`() { + val testChannel = "test-channel" + + ReflectionHelpers.setStaticField(Build.VERSION::class.java, "SDK_INT", 25) + + every { tested.areNotificationsEnabled() } returns true + + assertTrue(tested.isNotificationChannelEnabled(testChannel)) + } +}