tauri-plugin-notifications 0.4.5

A Tauri v2 plugin for sending notifications on desktop and mobile platforms with support for system notifications and push delivery via FCM and APNs.
Documentation
package app.tauri.notification

import android.content.Context
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Assert.*
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class AssetUtilsInstrumentedTest {

    private lateinit var context: Context

    @Before
    fun setup() {
        context = InstrumentationRegistry.getInstrumentation().targetContext
    }

    @Test
    fun testGetResourceBaseName_withPath() {
        // When path contains /, it returns everything after last / (including extension)
        assertEquals("resource.png", AssetUtils.getResourceBaseName("path/to/resource.png"))
    }

    @Test
    fun testGetResourceBaseName_withExtension() {
        assertEquals("resource", AssetUtils.getResourceBaseName("resource.mp3"))
    }

    @Test
    fun testGetResourceBaseName_noExtension() {
        assertEquals("resource", AssetUtils.getResourceBaseName("resource"))
    }

    @Test
    fun testGetResourceBaseName_multipleExtensions() {
        assertEquals("file.backup", AssetUtils.getResourceBaseName("file.backup.zip"))
    }

    @Test
    fun testGetResourceBaseName_null() {
        assertNull(AssetUtils.getResourceBaseName(null))
    }

    @Test
    fun testGetResourceBaseName_empty() {
        assertEquals("", AssetUtils.getResourceBaseName(""))
    }

    @Test
    fun testGetResourceID_existingDrawable() {
        // Test with ic_transparent which should exist in this project
        val resId = AssetUtils.getResourceID(context, "ic_transparent", "drawable")

        // Should return non-zero if found, or zero if not found (both are acceptable)
        assertTrue(resId >= AssetUtils.RESOURCE_ID_ZERO_VALUE)
    }

    @Test
    fun testGetResourceID_nonExistentResource() {
        val resId = AssetUtils.getResourceID(context, "nonexistent_resource_xyz", "drawable")

        assertEquals(AssetUtils.RESOURCE_ID_ZERO_VALUE, resId)
    }

    @Test
    fun testGetResourceID_nullResourceName() {
        // Note: getResourceID doesn't handle null gracefully, Android API throws NPE
        // This tests the actual behavior
        try {
            val resId = AssetUtils.getResourceID(context, null, "drawable")
            // If it doesn't throw, it should return 0
            assertEquals(AssetUtils.RESOURCE_ID_ZERO_VALUE, resId)
        } catch (e: NullPointerException) {
            // Expected behavior - Android API throws NPE for null resource name
            assertTrue(true)
        }
    }

    @Test
    fun testGetResourceID_rawDirectory() {
        // Try to get a resource from raw directory (may not exist, but should not crash)
        val resId = AssetUtils.getResourceID(context, "test_sound", "raw")

        // Should return 0 if not found, or valid ID if found
        assertTrue(resId >= AssetUtils.RESOURCE_ID_ZERO_VALUE)
    }

    @Test
    fun testGetResourceID_drawableDirectory() {
        // Try to get a resource from drawable directory
        val resId = AssetUtils.getResourceID(context, "ic_transparent", "drawable")

        // Should return 0 if not found, or valid ID if found
        assertTrue(resId >= AssetUtils.RESOURCE_ID_ZERO_VALUE)
    }

    @Test
    fun testResourceIdZeroValueConstant() {
        assertEquals(0, AssetUtils.RESOURCE_ID_ZERO_VALUE)
    }

    @Test
    fun testGetResourceBaseName_pathProcessing() {
        // When path contains /, it returns everything after last / INCLUDING extension
        val testCases = mapOf(
            "sounds/notification.wav" to "notification.wav",
            "res/drawable/icon.png" to "icon.png",
            "assets/audio/beep.mp3" to "beep.mp3",
            "/absolute/path/file.jpg" to "file.jpg"
        )

        for ((input, expected) in testCases) {
            assertEquals("Failed for input: $input", expected, AssetUtils.getResourceBaseName(input))
        }
    }

    @Test
    fun testGetResourceBaseName_edgeCases() {
        // File with only extension (no slash, so extension is stripped)
        assertEquals("", AssetUtils.getResourceBaseName(".hidden"))

        // Path ending with slash
        assertEquals("", AssetUtils.getResourceBaseName("path/to/"))

        // Multiple slashes (has slash, so keeps extension)
        assertEquals("file.ext", AssetUtils.getResourceBaseName("path//to///file.ext"))

        // Dot in path but not in filename (has slash, returns as-is after /)
        assertEquals("file", AssetUtils.getResourceBaseName("path.v1/file"))
    }

    @Test
    fun testGetResourceID_packageContext() {
        // Verify it uses the correct package context (test package has .test suffix)
        val packageName = context.packageName
        assertEquals("app.tauri.notification.test", packageName)
    }

    @Test
    fun testGetResourceID_differentResourceTypes() {
        val resourceTypes = listOf("drawable", "raw", "string", "color", "layout", "id")

        for (type in resourceTypes) {
            val resId = AssetUtils.getResourceID(context, "test_resource", type)

            // Should not crash and return valid result (0 or positive)
            assertTrue("Failed for type: $type", resId >= 0)
        }
    }

    @Test
    fun testGetResourceBaseName_specialCharacters() {
        // With path (has /), keeps extension
        assertEquals("file_name.ext", AssetUtils.getResourceBaseName("path/file_name.ext"))
        // No path, strips extension
        assertEquals("file-name", AssetUtils.getResourceBaseName("file-name.ext"))
        assertEquals("file123", AssetUtils.getResourceBaseName("file123.ext"))
    }

    @Test
    fun testGetResourceBaseName_unicodeCharacters() {
        // Android resources typically don't support unicode, but test the base name extraction
        val result = AssetUtils.getResourceBaseName("path/файл.txt")
        assertTrue(result?.contains("файл") ?: false)
    }

    @Test
    fun testGetResourceID_emptyResourceName() {
        val resId = AssetUtils.getResourceID(context, "", "drawable")

        assertEquals(AssetUtils.RESOURCE_ID_ZERO_VALUE, resId)
    }

    @Test
    fun testGetResourceID_nullDirectory() {
        val resId = AssetUtils.getResourceID(context, "resource", null)

        // Should handle null directory gracefully
        assertEquals(AssetUtils.RESOURCE_ID_ZERO_VALUE, resId)
    }
}