Press the Cancel button in the notification #235

Merged
JMR-dev merged 1 commits from test/notification-cancel-action into main 2026-09-06 04:45:53 +00:00
JMR-dev commented 2026-09-06 04:20:51 +00:00 (Migrated from github.com)

Closes #227.

ConversionNotifications.build attaches one action, wired to WorkManager.createCancelPendingIntent(id). Until now createCancelPendingIntent had no references anywhere outside its own declaration — no JVM test, no instrumented test.

That is worth more than an ordinary uncovered line. A conversion runs in a foreground service and the user is invited to leave the app; once they do, this action is the only way to stop it. If the PendingIntent carries the wrong id the button does nothing, the notification stays, and the job runs to completion — with no error, no log, and no screen to look at.

Two decisions worth stating

Why it fires the intent rather than reading the shade. The obvious version asks NotificationManager.getActiveNotifications() for id 1001 and taps what it finds. Rejected: the instrumented suite grants no runtime permissions, so POST_NOTIFICATIONS is denied throughout, and whether a suppressed foreground-service notification is returned there is a platform detail that varies — the test would be asserting something about notification visibility rather than about cancellation. The PendingIntent is the subject; where it is read from is incidental.

Why the job is delayed rather than running. A conversion of the committed 3 s fixture finishes in well under a second on an emulator (HardwareFallbackTest completed one in 448 ms), so racing a cancel against a running job would be flaky in the direction that fails. An initial delay keeps it reliably ENQUEUED, a state cancelWorkById acts on identically. What is under test is whether firing the action reaches WorkManager with the right id.

Verification — both directions, on a local API 34 emulator

As written:

API 34: tests=61 failures=0 errors=0 skipped=3

Mutated — createCancelPendingIntent(UUID.randomUUID()) instead of the request's id:

NotificationCancelActionTest > theNotificationsCancelActionCancelsThatJob  FAILED
API 34: tests=61 failures=1 errors=0 skipped=3

The notification looks identical and the job is never cancelled. Nothing else in either suite notices — which is the gap this closes.

🤖 Generated with Claude Code

Closes #227. `ConversionNotifications.build` attaches one action, wired to `WorkManager.createCancelPendingIntent(id)`. Until now `createCancelPendingIntent` had **no references anywhere outside its own declaration** — no JVM test, no instrumented test. That is worth more than an ordinary uncovered line. A conversion runs in a foreground service and the user is invited to leave the app; once they do, this action is the only way to stop it. If the `PendingIntent` carries the wrong id the button does nothing, the notification stays, and the job runs to completion — with no error, no log, and no screen to look at. ## Two decisions worth stating **Why it fires the intent rather than reading the shade.** The obvious version asks `NotificationManager.getActiveNotifications()` for id 1001 and taps what it finds. Rejected: the instrumented suite grants no runtime permissions, so `POST_NOTIFICATIONS` is denied throughout, and whether a suppressed foreground-service notification is returned there is a platform detail that varies — the test would be asserting something about notification *visibility* rather than about cancellation. The `PendingIntent` is the subject; where it is read from is incidental. **Why the job is delayed rather than running.** A conversion of the committed 3 s fixture finishes in well under a second on an emulator (`HardwareFallbackTest` completed one in 448 ms), so racing a cancel against a running job would be flaky in the direction that fails. An initial delay keeps it reliably `ENQUEUED`, a state `cancelWorkById` acts on identically. What is under test is whether firing the action reaches WorkManager with the right id. ## Verification — both directions, on a local API 34 emulator As written: ``` API 34: tests=61 failures=0 errors=0 skipped=3 ``` Mutated — `createCancelPendingIntent(UUID.randomUUID())` instead of the request's id: ``` NotificationCancelActionTest > theNotificationsCancelActionCancelsThatJob FAILED API 34: tests=61 failures=1 errors=0 skipped=3 ``` The notification looks identical and the job is never cancelled. Nothing else in either suite notices — which is the gap this closes. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.