Files
amethyst/tools/notification-e2e/README.md
T
Claude 5001d4a27a test(notifications): cover Buzz reactions in the e2e harness + document Buzz DM
- run.sh: add a Buzz-style bare reaction check (kind-7 with an `e` tag but no `p`
  tag) asserting it still lands on the Reactions channel, and a note that Buzz DM
  isn't auto-triggered.
- README: coverage row for the bare reaction, plus a "Buzz DM (manual)" section
  with the channel-setup steps (kind-39000 `t=dm` + participant, then post
  kind-9/40002) since participant-routing needs cached channel metadata.

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

100 lines
4.6 KiB
Markdown

# 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" |
| Buzz bare reaction | kind 7 with `e` tag, **no `p` tag** | `ReactionsID` (routed via `tagsAnEventByUser`) |
| 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.
### Buzz DM (manual)
Buzz DM notifications (`StreamMessageV2Event` k40002 / `ChatEvent` k9 in a `t=dm`
relay-group channel) are participant-routed off the channel's kind-39000
metadata, so they can't be triggered in one `amy event` call. To verify by hand:
1. Create a Buzz DM channel whose kind-39000 metadata has `["t","dm"]` and a
`["p", <A_hex>]` participant tag (use the Buzz UI, or `amy relaygroup` /
`amy event --kind 39000` as the relay/group admin), on a relay A is connected
to. Let A load the channel (open it once) so its 39000 metadata is cached —
push only fires when the participant list is known.
2. As B, post a message into it: `amy event --kind 9 --content "buzz dm hi"
--tags '[["h","<groupId>"]]' --relay <groupRelay>` (or kind 40002).
3. Background the app; expect a `PrivateMessagesID` notification titled with the
channel name and body `B: buzz dm hi`, tapping it opens the chatroom.
The gate is intentionally strict (participant metadata must be loaded), matching
the in-app feed — a cold push with no cached channel won't notify.
## 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:
```bash
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
```bash
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 `WARN`s 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.