From 833d0e3d6f1f467dd4097214e6ce9fa7fc5b5822 Mon Sep 17 00:00:00 2001 From: Ayaan Zaidi Date: Mon, 30 Mar 2026 11:15:44 +0530 Subject: [PATCH] test: broaden android notification handlers --- .../app/node/NotificationsHandlerTest.kt | 63 +++++++++++++++++++ .../ai/openclaw/app/node/SystemHandlerTest.kt | 31 +++++++++ 2 files changed, 94 insertions(+) diff --git a/apps/android/app/src/test/java/ai/openclaw/app/node/NotificationsHandlerTest.kt b/apps/android/app/src/test/java/ai/openclaw/app/node/NotificationsHandlerTest.kt index dc609bff47f..ad6a833402d 100644 --- a/apps/android/app/src/test/java/ai/openclaw/app/node/NotificationsHandlerTest.kt +++ b/apps/android/app/src/test/java/ai/openclaw/app/node/NotificationsHandlerTest.kt @@ -140,6 +140,46 @@ class NotificationsHandlerTest { assertEquals(0, provider.actionRequests) } + @Test + fun notificationsActions_rejectsMissingKey() = + runTest { + val provider = + FakeNotificationsStateProvider( + DeviceNotificationSnapshot( + enabled = true, + connected = true, + notifications = listOf(sampleEntry("n3")), + ), + ) + val handler = NotificationsHandler.forTesting(appContext = appContext(), stateProvider = provider) + + val result = handler.handleNotificationsActions("""{"action":"open"}""") + + assertFalse(result.ok) + assertEquals("INVALID_REQUEST", result.error?.code) + assertEquals(0, provider.actionRequests) + } + + @Test + fun notificationsActions_rejectsInvalidAction() = + runTest { + val provider = + FakeNotificationsStateProvider( + DeviceNotificationSnapshot( + enabled = true, + connected = true, + notifications = listOf(sampleEntry("n3")), + ), + ) + val handler = NotificationsHandler.forTesting(appContext = appContext(), stateProvider = provider) + + val result = handler.handleNotificationsActions("""{"key":"n3","action":"archive"}""") + + assertFalse(result.ok) + assertEquals("INVALID_REQUEST", result.error?.code) + assertEquals(0, provider.actionRequests) + } + @Test fun notificationsActions_propagatesProviderError() = runTest { @@ -167,6 +207,29 @@ class NotificationsHandlerTest { assertEquals(1, provider.actionRequests) } + @Test + fun notificationsActions_fallsBackWhenProviderOmitsErrorDetails() = + runTest { + val provider = + FakeNotificationsStateProvider( + DeviceNotificationSnapshot( + enabled = true, + connected = true, + notifications = listOf(sampleEntry("n4")), + ), + ).also { + it.actionResult = NotificationActionResult(ok = false) + } + val handler = NotificationsHandler.forTesting(appContext = appContext(), stateProvider = provider) + + val result = handler.handleNotificationsActions("""{"key":"n4","action":"open"}""") + + assertFalse(result.ok) + assertEquals("UNAVAILABLE", result.error?.code) + assertEquals("notification action failed", result.error?.message) + assertEquals(1, provider.actionRequests) + } + @Test fun notificationsActions_requestsRebindWhenEnabledButDisconnected() = runTest { diff --git a/apps/android/app/src/test/java/ai/openclaw/app/node/SystemHandlerTest.kt b/apps/android/app/src/test/java/ai/openclaw/app/node/SystemHandlerTest.kt index 994864cf364..31b46b4b757 100644 --- a/apps/android/app/src/test/java/ai/openclaw/app/node/SystemHandlerTest.kt +++ b/apps/android/app/src/test/java/ai/openclaw/app/node/SystemHandlerTest.kt @@ -26,6 +26,16 @@ class SystemHandlerTest { assertEquals("INVALID_REQUEST", result.error?.code) } + @Test + fun handleSystemNotify_rejectsInvalidRequestObject() { + val handler = SystemHandler.forTesting(poster = FakePoster(authorized = true)) + + val result = handler.handleSystemNotify("""{"title":"OpenClaw"}""") + + assertFalse(result.ok) + assertEquals("INVALID_REQUEST", result.error?.code) + } + @Test fun handleSystemNotify_postsNotification() { val poster = FakePoster(authorized = true) @@ -37,6 +47,23 @@ class SystemHandlerTest { assertEquals(1, poster.posts) } + @Test + fun handleSystemNotify_trimsAndPassesOptionalFields() { + val poster = FakePoster(authorized = true) + val handler = SystemHandler.forTesting(poster = poster) + + val result = + handler.handleSystemNotify( + """{"title":" OpenClaw ","body":" done ","priority":" passive ","sound":" silent "}""", + ) + + assertTrue(result.ok) + assertEquals("OpenClaw", poster.lastRequest?.title) + assertEquals("done", poster.lastRequest?.body) + assertEquals("passive", poster.lastRequest?.priority) + assertEquals("silent", poster.lastRequest?.sound) + } + @Test fun handleSystemNotify_returnsUnauthorizedWhenPostFailsPermission() { val handler = SystemHandler.forTesting(poster = ThrowingPoster(authorized = true, error = SecurityException("denied"))) @@ -55,6 +82,7 @@ class SystemHandlerTest { assertFalse(result.ok) assertEquals("UNAVAILABLE", result.error?.code) + assertEquals("NOTIFICATION_FAILED: boom", result.error?.message) } } @@ -63,11 +91,14 @@ private class FakePoster( ) : SystemNotificationPoster { var posts: Int = 0 private set + var lastRequest: SystemNotifyRequest? = null + private set override fun isAuthorized(): Boolean = authorized override fun post(request: SystemNotifyRequest) { posts += 1 + lastRequest = request } }