Test Cases: Unsubscribe Flow

⚠️ Corrected — read the Communications index first. The unsubscribe page is the public route /unsubscribeNOT tenant-prefixed (no /rcme/unsubscribe). Email links carry ?token=…&memberId=…&tenantId=…&category=…; the SPA POSTs to /api/unsubscribe (and /api/resubscribe), both public. The token is a deterministic HMAC with no expiry. Valid categories: paymentReminders, eventReminders, membershipUpdates, broadcasts, all.

Module: Communications - Unsubscribe Flow

Backend Service: Email preferences service, unsubscribe token validation

Related Endpoints: POST /api/unsubscribe, POST /api/resubscribe, GET /api/email/unsubscribe/:token, PATCH /api/email/preferences

Priority: P2

Phase: 4

Prerequisites

Test Data

MemberEmailInitial Preferences
Test Member 1member1@test.comAll categories subscribed
Test Member 2member2@test.comOnly broadcasts subscribed
Test Member 3member3@test.comAll categories unsubscribed
Expired Token Memberexpired@test.comToken > 30 days old

Test Cases

TC-COMM-051: One-Click Unsubscribe (All Categories)

StepActionExpected Result
1Receive broadcast email as subscribed member.Email in inbox with unsubscribe link in footer.
2Click "Unsubscribe" link in email footer.One-click unsubscribe page displayed.
3Click "Unsubscribe from All".API POST /api/unsubscribe called with token and no category.
4Verify confirmation message."You have been unsubscribed from all emails" displayed.
5Check member email preferences.All preference categories set to OFF/false.
6Send new broadcast to member's segment.Member excluded from recipient list.
7Verify member does NOT receive email.No email delivered to unsubscribed member.

TC-COMM-052: Unsubscribe by Specific Category

StepActionExpected Result
1Receive broadcast email.Email in inbox.
2Click "Unsubscribe" link.Unsubscribe page displayed.
3Select "Unsubscribe from Broadcasts only".Category selection visible.
4Confirm unsubscribe from broadcasts.API POST /api/unsubscribe called with category: "broadcasts".
5Verify confirmation."You have been unsubscribed from broadcasts" displayed.
6Check email preferences.Only broadcasts set to OFF; other categories unchanged.
7Trigger payment reminder email.Member receives payment reminder (still subscribed).
8Send broadcast email.Member does NOT receive broadcast.

TC-COMM-053: Unsubscribe from Event Reminders

StepActionExpected Result
1Access unsubscribe page via event reminder email.Unsubscribe page displayed.
2Select "Unsubscribe from Event Reminders".Category selection made.
3Confirm.API called with category: "eventReminders".
4Verify preferences.eventReminders OFF; other categories unchanged.
5Trigger event reminder.Member does NOT receive event reminder.

TC-COMM-054: Unsubscribe from Payment Reminders

StepActionExpected Result
1Access unsubscribe page via payment reminder email.Unsubscribe page displayed.
2Select "Unsubscribe from Payment Reminders".Category selection made.
3Confirm.API called with category: "paymentReminders".
4Verify preferences.paymentReminders OFF; other categories unchanged.
5Trigger payment reminder.Member does NOT receive payment reminder.

TC-COMM-055: Unsubscribe Link Token Validation - Valid Token

StepActionExpected Result
1Send broadcast email to member.Email sent with unique unsubscribe token.
2Extract unsubscribe token from email link.Token embedded in URL.
3Call GET /api/email/unsubscribe/:token.API validates token.
4Verify response.200 OK with member info and preferences.
5Use token to unsubscribe.Unsubscribe successful.

TC-COMM-056: Invalid Unsubscribe Token

StepActionExpected Result
1Navigate to unsubscribe URL with invalid token.e.g., /unsubscribe?token=invalid123.
2Verify API response.400 Bad Request or 404 Not Found.
3Verify error page displayed."Invalid unsubscribe link" message shown.
4Verify no preferences changed.Member preferences remain unchanged.
5Provide alternative action.Link to login and manage preferences manually.

TC-COMM-057: Expired Unsubscribe Token

StepActionExpected Result
1Use unsubscribe token older than 30 days.Token has expiration.
2Navigate to unsubscribe page.API validates token age.
3Verify response.400 Bad Request with TOKEN_EXPIRED error.
4Verify user-friendly message."This unsubscribe link has expired" displayed.
5Provide alternative.Option to request new unsubscribe link or login.

TC-COMM-058: Unsubscribe Confirmation Page Display

StepActionExpected Result
1Click unsubscribe link from email.Page loads.
2Verify page elements.Organization branding displayed.
3Verify member identification.Member email displayed (partial/masked).
4Verify options displayed."Unsubscribe All", category options, "Manage Preferences" link.
5Verify mobile responsiveness.Page displays correctly on mobile device.

TC-COMM-059: Resubscribe Flow - Single Category

StepActionExpected Result
1Member previously unsubscribed from broadcasts.broadcasts preference is OFF.
2Access email preferences page (logged in).Preferences displayed.
3Toggle "Broadcasts" to ON.Checkbox/toggle enabled.
4Save preferences.API PATCH /api/email/preferences called.
5Verify confirmation."Preferences updated" message.
6Verify database update.broadcasts preference is ON.
7Send broadcast.Member receives broadcast email.

TC-COMM-060: Resubscribe Flow - Via Public Endpoint

StepActionExpected Result
1Member is fully unsubscribed.All preferences OFF.
2Member requests resubscription (support request).Token generated.
3Call POST /api/resubscribe with token.API processes resubscription.
4Verify response.200 OK with updated preferences.
5Verify all preferences restored.All categories set to ON.
6Verify member receives future emails.Emails delivered successfully.

TC-COMM-061: Resubscribe Specific Categories Only

StepActionExpected Result
1Member unsubscribed from all categories.All preferences OFF.
2Access preferences page.Current preferences shown (all OFF).
3Enable only "Membership Updates" and "Payment Reminders".Selective toggle.
4Save preferences.API called with partial preferences.
5Verify selective subscription.Only selected categories ON.
6Verify email behavior.Receives membership/payment emails, not broadcasts.

TC-COMM-062: Manage Preferences Option from Unsubscribe Page

StepActionExpected Result
1Click unsubscribe link from email.Unsubscribe page displayed.
2Click "Manage Preferences" link.Redirected to login or preferences page.
3If not logged in, authenticate.Login required for full preferences.
4Access full preferences page.All email categories with toggles displayed.
5Make granular changes.Individual category toggles.
6Save and verify.All changes persisted correctly.

TC-COMM-063: Unsubscribe - Already Unsubscribed Member

StepActionExpected Result
1Member already unsubscribed from all.Preferences all OFF.
2Click old unsubscribe link from previous email.Page loads with valid token.
3Attempt to unsubscribe again.Graceful handling.
4Verify message."You are already unsubscribed" or confirmation without error.
5Verify preferences unchanged.Still all OFF.

TC-COMM-064: Unsubscribe Token - One-Time Use Enforcement

StepActionExpected Result
1Use unsubscribe token to unsubscribe.Successful unsubscription.
2Attempt to use same token again.Token may be single-use or multi-use.
3If single-use, verify error."Token already used" or similar.
4If multi-use, verify idempotent behavior.Same result without error.

TC-COMM-065: Unsubscribe Link Format in Email

StepActionExpected Result
1Receive broadcast email.Email delivered.
2Inspect email footer.Unsubscribe link visible.
3Verify link text.Clear "Unsubscribe" or "Manage preferences" text.
4Verify link URL structure.Contains organization domain and token.
5Verify link is clickable.Not broken or malformed.
6Verify compliance.Meets CAN-SPAM / GDPR requirements.

TC-COMM-066: Unsubscribe Does Not Affect System Notifications

StepActionExpected Result
1Member unsubscribes from all marketing emails.All marketing preferences OFF.
2Trigger transactional email (password reset).System email sent.
3Verify member receives transactional email.Password reset email delivered.
4Trigger membership renewal confirmation.System notification sent.
5Verify receipt.Critical system emails still delivered.

TC-COMM-067: Unsubscribe Statistics Tracking

StepActionExpected Result
1Send broadcast to 100 members.Broadcast delivered.
25 members click unsubscribe.Unsubscribe events recorded.
3View broadcast statistics.Unsubscribe count visible.
4Verify unsubscribe rate.(5/100) * 100 = 5% unsubscribe rate.
5Verify individual tracking.Each unsubscriber identified in report.

TC-COMM-068: Bulk Unsubscribe via Admin

StepActionExpected Result
1Admin accesses member management.Member list displayed.
2Select multiple members.Bulk selection enabled.
3Apply "Unsubscribe from all" action.Bulk action initiated.
4Confirm action.Warning about bulk operation.
5Verify all selected members unsubscribed.Preferences updated for all.
6Verify audit log.Bulk unsubscribe action logged.

API Test Cases

TC-COMM-API-015: POST /api/unsubscribe - Unsubscribe All

Request: POST /api/unsubscribe

{

"token": "valid_unsubscribe_token_abc123"

}

Expected Response: 200 OK

{

"success": true,

"message": "Successfully unsubscribed from all email communications",

"memberId": "MEM-2024-001",

"unsubscribedCategories": ["broadcasts", "eventReminders", "paymentReminders", "membershipUpdates"],

"timestamp": "2024-01-15T10:30:00Z"

}

TC-COMM-API-016: POST /api/unsubscribe - Unsubscribe by Category

Request: POST /api/unsubscribe

{

"token": "valid_unsubscribe_token_abc123",

"category": "broadcasts"

}

Expected Response: 200 OK

{

"success": true,

"message": "Successfully unsubscribed from broadcasts",

"memberId": "MEM-2024-001",

"unsubscribedCategories": ["broadcasts"],

"remainingSubscriptions": ["eventReminders", "paymentReminders", "membershipUpdates"],

"timestamp": "2024-01-15T10:35:00Z"

}

TC-COMM-API-017: POST /api/unsubscribe - Invalid Token

Request: POST /api/unsubscribe

{

"token": "invalid_token_xyz"

}

Expected Response: 400 Bad Request

{

"error": "INVALID_TOKEN",

"message": "The unsubscribe token is invalid or malformed"

}

TC-COMM-API-018: POST /api/unsubscribe - Expired Token

Request: POST /api/unsubscribe

{

"token": "expired_token_30_days_old"

}

Expected Response: 400 Bad Request

{

"error": "TOKEN_EXPIRED",

"message": "This unsubscribe link has expired. Please login to manage your preferences."

}

TC-COMM-API-019: POST /api/unsubscribe - Invalid Category

Request: POST /api/unsubscribe

{

"token": "valid_token",

"category": "invalidCategory"

}

Expected Response: 400 Bad Request

{

"error": "INVALID_CATEGORY",

"message": "Invalid email category specified"

}

TC-COMM-API-020: GET /api/email/unsubscribe/:token - Validate Token

Request: GET /api/email/unsubscribe/valid_token_abc123

Expected Response: 200 OK

{

"valid": true,

"memberEmail": "m*r@example.com",

"currentPreferences": {

"broadcasts": true,

"eventReminders": true,

"paymentReminders": true,

"membershipUpdates": true

},

"tokenExpiresAt": "2024-02-15T10:30:00Z"

}

TC-COMM-API-021: POST /api/resubscribe - Resubscribe All

Request: POST /api/resubscribe

{

"token": "resubscribe_token_abc123"

}

Expected Response: 200 OK

{

"success": true,

"message": "Successfully resubscribed to email communications",

"memberId": "MEM-2024-001",

"subscribedCategories": ["broadcasts", "eventReminders", "paymentReminders", "membershipUpdates"],

"timestamp": "2024-01-16T09:00:00Z"

}

TC-COMM-API-022: POST /api/resubscribe - Resubscribe Specific Category

Request: POST /api/resubscribe

{

"token": "resubscribe_token_abc123",

"category": "broadcasts"

}

Expected Response: 200 OK

{

"success": true,

"message": "Successfully resubscribed to broadcasts",

"memberId": "MEM-2024-001",

"subscribedCategories": ["broadcasts"],

"timestamp": "2024-01-16T09:15:00Z"

}

TC-COMM-API-023: PATCH /api/email/preferences - Update Preferences (Authenticated)

Auth Required: Yes

Request: PATCH /api/email/preferences

{

"paymentReminders": true,

"eventReminders": false,

"membershipUpdates": true,

"broadcasts": false

}

Expected Response: 200 OK

{

"success": true,

"message": "Email preferences updated",

"preferences": {

"paymentReminders": true,

"eventReminders": false,

"membershipUpdates": true,

"broadcasts": false

},

"updatedAt": "2024-01-16T10:00:00Z"

}

TC-COMM-API-024: GET /api/email/preferences - Get Current Preferences

Auth Required: Yes

Request: GET /api/email/preferences

Expected Response: 200 OK

{

"memberId": "MEM-2024-001",

"email": "member@example.com",

"preferences": {

"paymentReminders": true,

"eventReminders": true,

"membershipUpdates": true,

"broadcasts": true

},

"lastUpdated": "2024-01-10T14:30:00Z",

"globalUnsubscribe": false

}


Edge Cases & Error Handling

TC-COMM-069: Unsubscribe with Missing Token

StepActionExpected Result
1Call POST /api/unsubscribe without token.-
2Verify response.400 Bad Request - "Token is required".

TC-COMM-070: Unsubscribe - Member Account Deleted

StepActionExpected Result
1Member account was deleted after email sent.Token still exists.
2Click unsubscribe link from old email.Token validation.
3Verify graceful handling."Member not found" or silent success.

TC-COMM-071: Concurrent Unsubscribe Requests

StepActionExpected Result
1Open unsubscribe link in two browser tabs.Two sessions active.
2Click unsubscribe in both tabs simultaneously.Race condition test.
3Verify no errors.Both requests handled gracefully.
4Verify final state.Member is unsubscribed (idempotent).

TC-COMM-072: Unsubscribe Page - Session Timeout

StepActionExpected Result
1Open unsubscribe page.Page displayed.
2Wait extended period without action.Session may timeout.
3Click unsubscribe.Either works or refreshes token.
4Verify user experience.Clear error or success message.

Security Test Cases

TC-COMM-073: Token Enumeration Prevention

StepActionExpected Result
1Attempt to enumerate tokens via API.Sequential token guessing.
2Verify rate limiting.Requests throttled after threshold.
3Verify response consistency.Same error for invalid/nonexistent tokens.

TC-COMM-074: Cross-Member Token Usage

StepActionExpected Result
1Member A obtains Member B's unsubscribe token.Token shared/leaked.
2Member A attempts to use Member B's token.Token processed.
3Verify only Member B affected.Token tied to specific member.
4Verify no additional member data exposed.Email masked in responses.

TC-COMM-075: SQL Injection in Token Parameter

StepActionExpected Result
1Submit malicious token: ' OR '1'='1.Injection attempt.
2Verify sanitization.Token rejected as invalid.
3Verify no database errors.Clean error handling.

Accessibility Test Cases

TC-COMM-076: Unsubscribe Page Accessibility

StepActionExpected Result
1Navigate unsubscribe page with screen reader.All elements announced.
2Verify keyboard navigation.Tab through all interactive elements.
3Verify button/link focus states.Clear visual focus indicators.
4Verify color contrast.WCAG AA compliant.
5Verify form labels.All inputs properly labeled.