Skip to Content
Living documentation — last reviewed 2026-05-28
FeaturesAnnouncementsAnnouncements — QA Plan

Announcements — QA Plan

1. Create + fan-out

#ScenarioExpected
1.1Coach creates with title + content201; WS event to org:{id} room; push enqueued to N-1 members; PostHog event captured (prod)
1.2Member tries to create403
1.3Create with empty title400 from DTO
1.4500-member orgPush fan-out completes; verify queue handles chunking; no throttling errors
1.6Author opts out of announcement push prefAuthor still excluded; no push to author regardless
1.7One member opts out of announcement prefPush to that member skipped

2. List + counts

#ScenarioExpected
2.1Member fetches listReturns rows with per-member readAt
2.2Unread countMatches DB truth (count where no announcement_reads row exists for me)
2.3Cursor paginationStable

3. Read receipts

#ScenarioExpected
3.1Member marks readRow inserted; counts decrement
3.2Member marks read twiceIdempotent; same row
3.3Member of org A marks read for an announcement in org BShould 403/404 — confirm in service

4. WebSocket

#ScenarioExpected
4.1Member connected → coach createsMember’s UI receives announcement:new
4.2Member offline → comes online laterPicks up via REST list — no replay over WS

5. Detail view (staff)

#ScenarioExpected
5.1Staff opens detailSees read receipts
5.2Member opens detail endpoint403 (staff-only) — verify in code

5b. Announcement email

#ScenarioExpected
5b.1Email switch is off (default)No audience picker; no email; create request has no emailAudience
5b.2Switch on in an org with 120 membersList shows 50, “Showing 50 of 120”, “Load more” reaches 120. The recipient count is the server’s, not the loaded rows
5b.3Filter to not_paying, sendOnly matching members get the email; the count in the dialog equals the emails queued
5b.4Untick two members, sendThey get no email; the recipient count drops by two
5b.5Pick mode with nobody tickedSend is disabled
5b.6Pick three people across two searchesExactly those three get the email
5b.7A member switched announcement email offSkipped; “Skipped (announcement emails off)” shows their number
5b.8Author matches the filterAuthor gets no email
5b.9Audience over 2000Over-limit message; send disabled; the API refuses with 400 and publishes nothing
5b.10Hebrew org, Russian-speaking memberEmail in Russian, from the org’s name, Reply-To the org’s address
5b.11Title with <script> or a line breakEscaped in the body; no header injection in the subject
5b.12Stop Redis, send with emailAnnouncement published; warning toast says emails could not be queued
5b.13Open announcement.emailed in the audit logOne row with counts and no addresses
5b.15App off, email onEmails queued; no list entry in the app, no push, no realtime event; audit row has inApp: false
5b.16App off, email offSend is disabled and the dialog says to choose a channel; the API returns 400
5b.17Attach a 1 MB PDF, sendEvery email carries the PDF under the chosen name; the member can open it
5b.18Choose a 6 MB fileRefused at once: “larger than 5 MB… add a link”; no upload request; Send disabled; Remove re-enables Send
5b.19Choose an .exeRefused as an unsupported type
5b.20Rename virus.exe to plan.pdf and attachThe server checks the real type from the upload; a non-allowed type is refused
5b.21Attach, then switch Email offThe file is dropped; nothing is sent with it
5b.22Attach with App on and Email onEmail has the file; the in-app announcement does not
5b.23Send to 500 members with a 5 MB fileEmails queue quickly; the API returns at once; R2 is read by the email provider, not by our workers
5b.14Coach (not owner) sendsAllowed — same rule as creating an announcement

6. RTL + i18n

#ScenarioExpected
6.1Hebrew content renderedRTL preserved
6.2Mixed Hebrew + English in contentCorrect bidi

7. Smoke

  • Create announcement → push arrives on mobile.
  • Bell badge updates after mark-read.
  • Member from another org doesn’t see anything.