Skip to content

Latest commit

Β 

History

History
597 lines (447 loc) Β· 14.3 KB

File metadata and controls

597 lines (447 loc) Β· 14.3 KB

🌐 WebSocket Testing Guide

Overview

This guide provides comprehensive instructions for testing the HexFeed WebSocket real-time notification system.

Table of Contents

  1. Prerequisites
  2. Testing Methods
  3. Test Scenarios
  4. Troubleshooting
  5. Performance Testing

Prerequisites

1. Backend Running

Ensure the backend is running:

cd hexfeed-backend
./mvnw spring-boot:run

2. Get JWT Token

First, authenticate to get a JWT token:

# Login
curl -X POST http://localhost:8080/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "username": "testuser",
    "email": "test@example.com"
  }' | jq -r '.data.token'

Save the token - you'll need it for WebSocket authentication!


Testing Methods

Method 1: HTML Test Client (Recommended)

  1. Open the test client:

    open hexfeed-backend/websocket-test-client.html
    # Or navigate to: file:///path/to/hexfeed-backend/websocket-test-client.html
  2. Follow the UI:

    • Enter your JWT token
    • Click "Connect"
    • Enter latitude/longitude (e.g., 37.7749, -122.4194)
    • Click "Subscribe to Location"
    • Watch the message log for real-time updates!

Method 2: Browser Console (Quick Test)

// 1. Include libraries (paste in console)
var script1 = document.createElement('script');
script1.src = 'https://cdn.jsdelivr.net/npm/sockjs-client@1/dist/sockjs.min.js';
document.head.appendChild(script1);

var script2 = document.createElement('script');
script2.src = 'https://cdn.jsdelivr.net/npm/@stomp/stompjs@7/bundles/stomp.umd.min.js';
document.head.appendChild(script2);

// 2. Wait a few seconds for libraries to load, then connect
var token = 'YOUR_JWT_TOKEN_HERE';
var socket = new SockJS('http://localhost:8080/ws');
var stompClient = new StompJs.Client();
stompClient.webSocketFactory = () => socket;
stompClient.connectHeaders = { 'Authorization': `Bearer ${token}` };

stompClient.onConnect = function(frame) {
    console.log('βœ… Connected!');
    
    // Subscribe to messages
    stompClient.subscribe('/user/queue/feed', function(message) {
        console.log('πŸ“¨ Received:', JSON.parse(message.body));
    });
    
    // Subscribe to location
    stompClient.publish({
        destination: '/app/subscribe',
        body: JSON.stringify({ latitude: 37.7749, longitude: -122.4194 })
    });
};

stompClient.onStompError = (error) => console.error('❌ Error:', error);
stompClient.activate();

Method 3: Postman

  1. Create WebSocket Request:

    • New β†’ WebSocket Request
    • URL: ws://localhost:8080/ws
  2. Add Authentication:

    • In Headers tab, add:
      Authorization: Bearer YOUR_JWT_TOKEN
      
  3. Connect and Subscribe:

    • Click "Connect"
    • Send message to /app/subscribe:
      {
        "destination": "/app/subscribe",
        "body": {
          "latitude": 37.7749,
          "longitude": -122.4194
        }
      }

Method 4: Command Line (wscat)

# Install wscat
npm install -g wscat

# Connect (note: wscat doesn't support SockJS, so this is basic)
wscat -c ws://localhost:8080/ws \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Method 5: Python Script

# Install: pip install websocket-client
import websocket
import json

token = "YOUR_JWT_TOKEN"

def on_message(ws, message):
    print(f"πŸ“¨ Received: {message}")

def on_open(ws):
    print("βœ… Connected!")
    # Subscribe
    subscribe_msg = json.dumps({
        "latitude": 37.7749,
        "longitude": -122.4194
    })
    ws.send(f"SUBSCRIBE\ndestination:/app/subscribe\n\n{subscribe_msg}\x00")

ws = websocket.WebSocketApp(
    "ws://localhost:8080/ws",
    header={"Authorization": f"Bearer {token}"},
    on_open=on_open,
    on_message=on_message
)
ws.run_forever()

Test Scenarios

Scenario 1: Basic Connection Test

Objective: Verify WebSocket connection establishment

Steps:

  1. Start backend
  2. Open HTML test client
  3. Enter JWT token
  4. Click "Connect"

Expected Result:

  • Status changes to "Connected"
  • Log shows: "βœ… Connected to WebSocket successfully!"
  • Log shows: "πŸ“‘ Subscribed to /user/queue/feed"

Pass Criteria: βœ… Connection established without errors


Scenario 2: Location Subscription Test

Objective: Verify location-based subscription

Steps:

  1. Connect to WebSocket (Scenario 1)
  2. Enter coordinates:
    • Latitude: 37.7749
    • Longitude: -122.4194
  3. Click "Subscribe to Location"

Expected Result:

  • Log shows: "πŸ“ Subscribing to location: 37.7749, -122.4194"
  • Receive subscription confirmation with:
    {
      "centerHexId": "872830828ffffff",
      "subscribedHexIds": ["872830828ffffff", "872830829ffffff", ...],
      "status": "success",
      "message": "Subscribed to 7 hex regions..."
    }

Pass Criteria: βœ… Received 7 hex IDs in confirmation


Scenario 3: Real-time Post Notification Test

Objective: Verify real-time post notifications

Steps:

  1. Connect and subscribe to location (Scenarios 1-2)
  2. In another terminal, create a post:
    curl -X POST http://localhost:8080/api/v1/posts \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer YOUR_JWT_TOKEN" \
      -d '{
        "content": "Test post for WebSocket notification",
        "latitude": 37.7749,
        "longitude": -122.4194
      }'

Expected Result:

  • WebSocket client receives notification:
    {
      "type": "new_post",
      "hex_id": "872830828ffffff",
      "post": {
        "postId": "...",
        "content": "Test post...",
        "latitude": 37.7749,
        "longitude": -122.4194
      }
    }

Pass Criteria: βœ… Notification received within 1-2 seconds of post creation


Scenario 4: Heartbeat Test

Objective: Verify heartbeat mechanism

Steps:

  1. Connect to WebSocket
  2. Subscribe to location
  3. Wait and observe

Expected Result:

  • Every 30 seconds, receive heartbeat:
    {
      "type": "heartbeat",
      "timestamp": "2024-01-15T10:30:00"
    }
  • Client automatically sends pong response

Pass Criteria: βœ… Heartbeats received regularly, connection stays alive


Scenario 5: Multiple Subscriptions Test

Objective: Verify user can update subscription

Steps:

  1. Connect and subscribe to location A (37.7749, -122.4194)
  2. Subscribe to different location B (34.0522, -118.2437)
  3. Create posts in both locations

Expected Result:

  • New subscription replaces old one
  • Only receive notifications for location B

Pass Criteria: βœ… Subscription updates correctly


Scenario 6: Disconnect/Reconnect Test

Objective: Verify reconnection handling

Steps:

  1. Connect and subscribe
  2. Click "Disconnect"
  3. Wait 5 seconds
  4. Click "Connect" again
  5. Subscribe to same location

Expected Result:

  • Clean disconnection
  • Successful reconnection
  • Subscription works after reconnect

Pass Criteria: βœ… No errors, subscription restored


Scenario 7: Authentication Failure Test

Objective: Verify authentication is enforced

Steps:

  1. Try to connect with invalid JWT token
  2. Try to connect without JWT token

Expected Result:

  • Connection fails with error message
  • Log shows: "❌ STOMP error" or "WebSocket authentication required"

Pass Criteria: βœ… Connection rejected for invalid/missing auth


Scenario 8: Unsubscribe Test

Objective: Verify unsubscribe functionality

Steps:

  1. Connect and subscribe to location
  2. Click "Unsubscribe"
  3. Create a post in that location

Expected Result:

  • Receive unsubscribe confirmation
  • Do NOT receive new post notification

Pass Criteria: βœ… No notifications after unsubscribe


Scenario 9: Multiple Concurrent Users Test

Objective: Verify system handles multiple users

Steps:

  1. Open 3 browser tabs with test client
  2. Login with different users in each tab
  3. Subscribe all to same location
  4. Create a post in that location

Expected Result:

  • All 3 users receive the notification
  • Each user sees their own userId in logs

Pass Criteria: βœ… All users receive notifications independently


Scenario 10: Stress Test

Objective: Verify system handles rapid messages

Steps:

  1. Connect and subscribe
  2. Create 10 posts rapidly in the same location:
    for i in {1..10}; do
      curl -X POST http://localhost:8080/api/v1/posts \
        -H "Content-Type: application/json" \
        -H "Authorization: Bearer $TOKEN" \
        -d '{
          "content": "Stress test post '$i'",
          "latitude": 37.7749,
          "longitude": -122.4194
        }' &
    done

Expected Result:

  • Receive all 10 notifications
  • No dropped messages
  • No connection errors

Pass Criteria: βœ… All notifications received, no errors


Troubleshooting

Problem: Cannot Connect

Symptoms:

  • "WebSocket connection error"
  • "Connection refused"

Solutions:

  1. Verify backend is running: curl http://localhost:8080/actuator/health
  2. Check if port 8080 is available: lsof -i :8080
  3. Check backend logs for errors
  4. Verify JWT token is valid (not expired)

Problem: Authentication Fails

Symptoms:

  • "WebSocket authentication required"
  • "Invalid JWT token"

Solutions:

  1. Get fresh JWT token from login API
  2. Ensure token includes "Bearer " prefix
  3. Check token expiration time
  4. Verify SecurityConfig allows WebSocket authentication

Problem: No Notifications Received

Symptoms:

  • Connected and subscribed, but no messages when creating posts

Solutions:

  1. Check if Kafka is running: docker ps | grep kafka
  2. Verify subscription confirmation was received
  3. Check if post is in same location as subscription
  4. Check backend logs for Kafka consumer errors
  5. Verify WebSocketManagerService is broadcasting messages

Problem: Connection Drops

Symptoms:

  • Connection disconnects randomly
  • "Disconnected" status after few minutes

Solutions:

  1. Check if heartbeat is working (should see "πŸ’“ Heartbeat received")
  2. Verify pong responses are being sent
  3. Check network stability
  4. Increase connection timeout in configuration
  5. Check for firewall/proxy issues

Problem: Duplicate Notifications

Symptoms:

  • Receive same notification multiple times

Solutions:

  1. Check if multiple subscriptions are active
  2. Verify user isn't connected multiple times
  3. Check Kafka consumer group configuration
  4. Review WebSocketManagerService subscription logic

Performance Testing

Load Test Setup

# Install Apache Bench WebSocket extension
npm install -g websocket-bench

# Run load test
wsbench -c 100 -n 1000 \
  -H "Authorization: Bearer YOUR_TOKEN" \
  ws://localhost:8080/ws

Performance Metrics to Monitor

  1. Connection Time: < 100ms
  2. Subscription Response: < 200ms
  3. Notification Latency: < 500ms from post creation
  4. Concurrent Connections: Support 1000+ users
  5. Memory Usage: Monitor with JProfiler or VisualVM

Monitoring Commands

# Monitor active WebSocket connections
curl http://localhost:8080/actuator/metrics/websocket.connections

# Monitor message throughput
curl http://localhost:8080/actuator/metrics/websocket.messages

# Check backend logs
tail -f hexfeed-backend/logs/hexfeed-backend.log | grep WebSocket

Automated Test Script

Save this as test-websocket.sh:

#!/bin/bash

echo "πŸ§ͺ HexFeed WebSocket Automated Test"
echo "==================================="

# 1. Login and get token
echo "1️⃣ Getting JWT token..."
TOKEN=$(curl -s -X POST http://localhost:8080/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username":"testuser","email":"test@example.com"}' \
  | jq -r '.data.token')

if [ -z "$TOKEN" ] || [ "$TOKEN" = "null" ]; then
    echo "❌ Failed to get JWT token"
    exit 1
fi
echo "βœ… Got JWT token: ${TOKEN:0:20}..."

# 2. Test WebSocket connection using HTML client
echo ""
echo "2️⃣ Opening WebSocket test client..."
open websocket-test-client.html
echo "πŸ“‹ Token copied to clipboard:"
echo "$TOKEN" | pbcopy
echo "βœ… Paste the token in the browser and click Connect"

# 3. Wait for manual connection
read -p "Press Enter after connecting in browser..."

# 4. Create test post
echo ""
echo "3️⃣ Creating test post..."
POST_RESPONSE=$(curl -s -X POST http://localhost:8080/api/v1/posts \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "content": "Automated test post - you should receive this via WebSocket!",
    "latitude": 37.7749,
    "longitude": -122.4194
  }')

echo "βœ… Post created:"
echo "$POST_RESPONSE" | jq .

echo ""
echo "4️⃣ Check the browser - you should see a notification!"
echo ""
echo "Test complete! πŸŽ‰"

Make it executable:

chmod +x test-websocket.sh
./test-websocket.sh

Test Checklist

Use this checklist to verify all functionality:

  • βœ… WebSocket connection establishes successfully
  • βœ… JWT authentication works
  • βœ… Location subscription returns 7 hex IDs
  • βœ… Real-time notifications received for new posts
  • βœ… Heartbeat mechanism works (pings every 30s)
  • βœ… Unsubscribe works correctly
  • βœ… Reconnection works after disconnect
  • βœ… Multiple concurrent users supported
  • βœ… No memory leaks with long connections
  • βœ… Proper cleanup on disconnect
  • βœ… Test endpoint (/app/test) works
  • βœ… Status endpoint (/app/status) works
  • βœ… Authentication failures handled gracefully
  • βœ… Invalid subscriptions handled with error messages
  • βœ… Performance acceptable under load

Next Steps

After completing WebSocket testing:

  1. βœ… Integration Testing: Test complete flow (REST β†’ Kafka β†’ WebSocket)
  2. βœ… Load Testing: Test with 1000+ concurrent connections
  3. βœ… Frontend Integration: Connect React/Vue frontend
  4. βœ… Production Setup: Configure external message broker (RabbitMQ/Redis)
  5. βœ… Monitoring: Setup Grafana dashboards for WebSocket metrics

Additional Resources


Need Help? Check the troubleshooting section or review backend logs in logs/hexfeed-backend.log