-
Ensure Supabase is configured with environment variables:
SUPABASE_URL=your_supabase_url SUPABASE_SERVICE_ROLE_KEY=your_service_role_key
-
Run database migrations:
# In Supabase SQL Editor, run: backend/database/migrations/002_notifications.sql -
Start backend server:
cd backend npm install npm run start:dev
-
Configure environment variables:
VITE_API_BASE_URL=http://localhost:3001
-
Start frontend development server:
cd client npm install npm run dev
Steps:
- Open browser to
http://localhost:5173 - Navigate to any raffle detail page
- Locate the "Stay Updated" section
- Click "Notify Me" button
Expected Result:
- Alert message: "Please sign in to subscribe to notifications"
- User is not subscribed
- Button remains in "Notify Me" state
Steps:
- Click "Sign In" button in navbar
- Connect Stellar wallet (Freighter/xBull)
- Sign the authentication message
- Verify JWT token is stored in sessionStorage
Expected Result:
- User is authenticated
- Token stored as
tikka_auth_tokenin sessionStorage - "Sign In" button changes to show wallet address
Steps:
- Ensure user is authenticated
- Navigate to raffle detail page (e.g.,
/details?raffle=1) - Click "Notify Me" button in "Stay Updated" section
Expected Result:
- Button shows loading spinner briefly
- Success message: "Subscribed successfully!"
- Button changes to "Unsubscribe" with gray background
- Bell icon changes to filled state
API Call Verification:
# Check network tab for:
POST http://localhost:3001/notifications/subscribe
Headers: Authorization: Bearer <JWT>
Body: { "raffleId": 1, "channel": "email" }
Response: { "id": "uuid", "raffleId": 1, "userAddress": "G...", "channel": "email", "createdAt": "2024-..." }Steps:
- Subscribe to a raffle (as in Test 2.1)
- Click "Unsubscribe" then "Notify Me" again
Expected Result:
- Backend returns existing subscription (no error)
- Frontend shows success message
- Subscription status updates correctly
Steps:
- Subscribe to raffle #1
- Navigate to raffle #2
- Subscribe to raffle #2
- Navigate to raffle #3
- Subscribe to raffle #3
Expected Result:
- Each subscription succeeds independently
- All subscriptions are tracked separately
- No conflicts between subscriptions
Steps:
- Subscribe to a raffle
- Click "Unsubscribe" button
Expected Result:
- Button shows loading spinner briefly
- Success message: "Unsubscribed successfully!"
- Button changes back to "Notify Me" with gradient background
- Bell icon changes to outline state
API Call Verification:
# Check network tab for:
DELETE http://localhost:3001/notifications/subscribe/1
Headers: Authorization: Bearer <JWT>
Response: 204 No ContentSteps:
- Subscribe to multiple raffles
- Navigate to
/settings - Click "Notifications" tab
- Click trash icon next to a subscription
Expected Result:
- Subscription shows loading spinner on trash icon
- Subscription is removed from list
- Other subscriptions remain intact
- If last subscription, shows empty state
Steps:
- Subscribe to 2-3 raffles
- Navigate to
/settings - View "Notifications" tab
Expected Result:
- All active subscriptions are listed
- Each shows:
- Raffle ID
- Channel (email/push)
- Subscription date
- Unsubscribe button
- Subscriptions ordered by date (newest first)
API Call Verification:
# Check network tab for:
GET http://localhost:3001/notifications/subscriptions
Headers: Authorization: Bearer <JWT>
Response: [
{ "id": "uuid1", "raffleId": 1, "channel": "email", "createdAt": "..." },
{ "id": "uuid2", "raffleId": 2, "channel": "email", "createdAt": "..." }
]Steps:
- Ensure no active subscriptions
- Navigate to
/settings - View "Notifications" tab
Expected Result:
- Bell icon displayed
- Message: "No active subscriptions"
- Helpful text about subscribing to raffles
Steps:
- Navigate to
/settings - Click "Profile" tab
Expected Result:
- Shows wallet address
- Displays informational message about profile features
Steps:
- Check desktop navbar
- Check mobile navbar (hamburger menu)
Expected Result:
- "Settings" link visible in both views
- Clicking navigates to
/settings - Link highlights when on settings page
Steps:
- Stop backend server
- Try to subscribe to a raffle
Expected Result:
- Error message displayed
- Button returns to original state
- User can dismiss error
- No subscription created
Steps:
- Manually expire or clear JWT token
- Try to subscribe to a raffle
Expected Result:
- 401 error from backend
- Token cleared from sessionStorage
- Error message: "Unauthorized - please sign in again"
- User prompted to sign in again
Steps:
- Try to subscribe to non-existent raffle (e.g., raffle ID 99999)
Expected Result:
- Backend may accept subscription (no validation)
- Or returns error if raffle validation exists
- Error displayed to user if applicable
Steps:
- Observe all loading states during operations
Expected Result:
- Subscribe button shows spinner during API call
- Unsubscribe button shows spinner during API call
- Settings page shows spinner while loading subscriptions
- Trash icon shows spinner during unsubscribe
Steps:
- Subscribe to a raffle
- Unsubscribe from a raffle
Expected Result:
- Success messages appear briefly (2 seconds)
- Messages are clearly visible
- Messages auto-dismiss
- Visual feedback on button state changes
Steps:
- Test on desktop (1920x1080)
- Test on tablet (768x1024)
- Test on mobile (375x667)
Expected Result:
- All components render correctly
- Buttons are appropriately sized
- Text is readable
- No layout breaks
- Touch targets are adequate on mobile
Steps:
- Start as unauthenticated user
- Browse raffles
- Sign in with wallet
- Subscribe to 3 different raffles
- Navigate to settings
- Verify all 3 subscriptions appear
- Unsubscribe from 1 raffle
- Navigate back to that raffle detail
- Verify "Notify Me" button is shown
- Navigate to another subscribed raffle
- Verify "Unsubscribe" button is shown
Expected Result:
- All steps complete successfully
- State is consistent across pages
- No errors in console
- API calls are correct
Steps:
- Subscribe to a raffle
- Refresh the page
- Check subscription status
Expected Result:
- Subscription status persists after refresh
- Button shows correct state ("Unsubscribe")
- Settings page shows subscription
Steps:
- Open app in two browser tabs
- Subscribe in tab 1
- Refresh tab 2
- Check subscription status in tab 2
Expected Result:
- Tab 2 shows updated subscription status
- Both tabs show consistent state
-- View all subscriptions
SELECT * FROM notifications ORDER BY created_at DESC;
-- View subscriptions for specific user
SELECT * FROM notifications
WHERE user_address = 'GXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
ORDER BY created_at DESC;
-- View subscriptions for specific raffle
SELECT * FROM notifications
WHERE raffle_id = 1;
-- Count subscriptions per raffle
SELECT raffle_id, COUNT(*) as subscriber_count
FROM notifications
GROUP BY raffle_id
ORDER BY subscriber_count DESC;curl -X POST http://localhost:3001/notifications/subscribe \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-d '{"raffleId": 1, "channel": "email"}'curl -X DELETE http://localhost:3001/notifications/subscribe/1 \
-H "Authorization: Bearer YOUR_JWT_TOKEN"curl -X GET http://localhost:3001/notifications/subscriptions \
-H "Authorization: Bearer YOUR_JWT_TOKEN"Steps:
- Quickly subscribe/unsubscribe multiple times
Expected Result:
- All requests complete successfully
- No race conditions
- Final state is consistent
- No duplicate subscriptions
Steps:
- Create 20+ subscriptions
- Load settings page
Expected Result:
- Page loads within 2 seconds
- All subscriptions render correctly
- Scrolling is smooth
- No performance degradation
Steps:
- Remove JWT token from sessionStorage
- Try to access API endpoints directly
Expected Result:
- All requests return 401 Unauthorized
- No data is exposed
- User is prompted to sign in
Steps:
- Use invalid/expired JWT token
- Try to subscribe to raffle
Expected Result:
- Backend rejects request
- 401 error returned
- Token cleared from storage
Steps:
- Sign in as User A
- Subscribe to raffles
- Sign out and sign in as User B
- Check subscriptions
Expected Result:
- User B only sees their own subscriptions
- User A's subscriptions are not visible
- No data leakage between users
Test on:
- ✅ Chrome (latest)
- ✅ Firefox (latest)
- ✅ Safari (latest)
- ✅ Edge (latest)
- ✅ Mobile Safari (iOS)
- ✅ Chrome Mobile (Android)
-
Raffle Deletion: If a raffle is deleted, subscriptions remain in database
- Consider cleanup job or cascade delete
-
Email Validation: No email validation currently
- Users subscribe but may not receive emails if no email on file
-
Push Notifications: UI supports push channel but delivery not implemented
- Backend accepts "push" but doesn't send notifications
-
Notification Delivery: Subscription works but actual notification sending not implemented
- Need email service integration
- Need raffle end event triggers
All tests should pass with:
- ✅ No console errors
- ✅ Correct API responses
- ✅ Proper state management
- ✅ Good user experience
- ✅ Responsive design
- ✅ Secure authentication
- ✅ Data persistence
- ✅ Error handling
When reporting issues, include:
- Test scenario number
- Steps to reproduce
- Expected vs actual result
- Browser and version
- Console errors (if any)
- Network tab screenshots
- Database state (if relevant)