Files
amethyst/tools/notification-e2e/README.md
T
Claude 853229a2c6 test(notifications): add Layer-3 end-to-end harness (amy + adb)
An agent-runnable script that drives the whole push-notification pipeline on a
real device/emulator: a second identity publishes each notification kind through
`amy` to the account on the phone, and the script reads back the notification
shade over `adb` to assert the right notification on the right channel — then
exercises cold-push metadata enrichment (title flips from raw pubkey to display
name in place) and dismiss-on-read (opening the note clears the tray entry).

Covers mention, reply, reaction, repost, picture, and DM; prints PASS/WARN/FAIL
and exits non-zero on any hard failure. tools/notification-e2e/{run.sh,README.md}.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0122uQ8BLHLeHDni81RBP26r
2026-07-23 14:26:41 +00:00

3.5 KiB

Notification end-to-end test (Layer 3)

Drives the whole push-notification pipeline on a real device/emulator: a second identity publishes each notification kind through amy to the account logged into the phone, and the script reads the system notification shade back over adb to assert the right notification landed on the right channel — then tests the two behaviors unit tests can't reach: cold-push metadata enrichment and dismiss-on-read.

It's written to be run unattended by an agent: every check prints PASS / WARN / FAIL, and the script exits non-zero if any hard assertion fails.

What it covers

Check How it's triggered Asserted from the shade
Mention (+ liveness) amy event --kind 1 p-tagging A MentionsID + "mentioned you"
Reply kind 1 with e+p tags to A's note RepliesID + "replied"
Reaction kind 7 to A's note ReactionsID + "reacted"
Repost (new kind) kind 6 to A's note RepostsID + "reposted"
Picture (new kind) kind 20 with imeta + p MediaID + "shared a photo"
DM amy dm send PrivateMessagesID + the body
Enrichment cold-start, then publish sender kind:0 title flips from raw pubkey → display name in place
Dismiss-on-read deep-link the note, then re-check notification gone

Zaps (need a Lightning wallet), git/badge/nutzap/onchain (need repo / badge definition / cashu proofs) aren't automated here — they follow the same amy event --kind … pattern with the appropriate tags if you want to extend it.

Prerequisites

  • A device/emulator on adb with the debug app installed and an account logged in — this is identity A, the receiver.

  • amy built: ./gradlew :cli:installDist (binary at cli/build/install/amy/bin/amy).

  • jq on PATH.

  • A relay both sides use. It must be in A's inbox/read relays and A's always-on notification service must be enabled, so events arrive while the app is backgrounded. For an emulator with a local relay:

    amy serve --port 7777 &                 # embeds the geode relay
    adb reverse tcp:7777 tcp:7777           # phone's 127.0.0.1:7777 → host
    # then add ws://127.0.0.1:7777 to the account's relays in the app
    

Run

A_NPUB=npub1…  RELAY=wss://relay.example  ./tools/notification-e2e/run.sh

Reply/reaction/repost need a note authored by A on the relay; if A has none the script warns and skips those three — post one from the phone first for full coverage.

Knobs

Env Default
A_NPUB (required) receiver npub (the phone's account)
RELAY (required) relay both sides use
APP_PKG com.vitorpamplona.amethyst.debug app id
ADB_SERIAL first device adb -s target
AMY cli/build/install/amy/bin/amy amy binary
TIMEOUT 40 seconds to wait for a notification
IMG_URL a small public jpg image for the media test

Notes / limitations

  • Verification greps dumpsys notification --noredact for the channel id and a content string; it doesn't bind them to the same record, so run it against a reasonably quiet device.
  • The dismiss-on-read step depends on the note deep-link format; if it can't confirm the clear it WARNs rather than failing, so eyeball it once.
  • It exercises the always-on relay delivery path (no FCM/UnifiedPush server needed). To test the real push transport, send through your push server and keep the rest of the flow identical.