Files
MySMSAPio/GATEWAY_TESTING.md
2025-10-22 17:22:17 +08:00

15 KiB

Gateway Testing via Admin Interface

Overview

The admin interface now includes a comprehensive gateway testing module that allows you to:

  • Check gateway connection status in real-time
  • Send test SMS messages through specific gateways
  • Verify gateway functionality without external tools
  • Debug connection issues

Features

1. Connection Status Check

Real-time Gateway Status:

  • Online/Offline detection
  • Last heartbeat timestamp
  • 🕐 Time since last connection
  • 🔄 One-click refresh

How It Works:

  • Checks if gateway sent heartbeat within last 2 minutes
  • Displays exact last heartbeat time
  • Shows human-readable "time ago" format
  • Updates with AJAX (no page reload)

2. Send Test SMS

Test Message Features:

  • 📱 Phone number validation
  • ✉️ Custom message composition
  • 📊 Character counter (160 char SMS limit)
  • 📝 Multi-part SMS detection
  • Success/failure feedback
  • 🔍 Message ID tracking

Message Tracking:

  • Test messages marked with metadata: { test: true }
  • Identifies sender as "admin_interface"
  • Full message history in logs
  • Same queue as regular messages

Access Points

From Gateway List

URL: /admin/gateways

Each gateway has a Test button in the Actions column:

  • Blue button with flask icon
  • Located next to Activate/Deactivate button
  • Available for all gateways (online or offline)

From Gateway Details

URL: /admin/gateways/:id

Test Gateway button at the bottom:

  • Blue button with flask icon
  • Located above Activate/Deactivate button
  • Opens dedicated testing page

Direct Testing Page

URL: /admin/gateways/:id/test

Full testing interface with:

  • Connection status card
  • Gateway information
  • Test SMS form
  • Real-time updates

Testing Interface

Page Layout

┌─────────────────────────────────────────┐
│  Test Gateway: [Gateway Name]          │
│  [Back to Gateway Details]              │
├─────────────────────────────────────────┤
│  Gateway Status                         │
│  ┌───────────────────────┐              │
│  │ ✅ Gateway is Online  │ [Refresh]    │
│  │ Last heartbeat: 30s   │              │
│  └───────────────────────┘              │
├─────────────────────────────────────────┤
│  Connection Information                 │
│  Device ID: android-001                 │
│  Name: Office Phone                     │
│  Priority: 5                            │
│  Active: Yes                            │
├─────────────────────────────────────────┤
│  Send Test SMS                          │
│  Phone Number: [+959123456789____]     │
│  Message: [This is a test___________]  │
│           [________________________]  │
│           160 characters remaining      │
│                                         │
│  [Send Test SMS] [Reset Form]          │
└─────────────────────────────────────────┘

Status Indicators

Online (Green):

┌──────────────────────────────┐
│ ✅ Gateway is Online         │
│ Last heartbeat: 1 minute ago │
│ 2025-10-20 13:45:30         │
└──────────────────────────────┘

Offline (Red):

┌──────────────────────────────┐
│ ❌ Gateway is Offline        │
│ Gateway is offline           │
│ Last seen: 5 hours ago       │
└──────────────────────────────┘

Never Connected (Red):

┌──────────────────────────────┐
│ ❌ Gateway is Offline        │
│ Gateway is offline           │
│ Never connected              │
└──────────────────────────────┘

Using the Test Feature

Step 1: Access Testing Page

Option A: From Gateway List

  1. Navigate to /admin/gateways
  2. Find the gateway you want to test
  3. Click the blue Test button

Option B: From Gateway Details

  1. Navigate to /admin/gateways/:id
  2. Scroll to bottom
  3. Click Test Gateway button

Step 2: Check Connection Status

The page loads with automatic status check:

  1. Wait for status: Shows loading spinner
  2. View result: Green (online) or Red (offline)
  3. Refresh if needed: Click Refresh Status button

Connection Check Details:

  • Verifies last_heartbeat_at timestamp
  • Must be within 2 minutes to be "online"
  • Shows exact time of last heartbeat
  • Displays human-readable time ago

Step 3: Send Test SMS

  1. Enter phone number:

    • Include country code (e.g., +959123456789)
    • Required field
    • Validated on submission
  2. Enter message:

    • Default test message provided
    • Customizable content
    • Character counter updates live
    • Warns if over 160 chars
  3. Click "Send Test SMS":

    • Button shows spinner: "Sending..."
    • Waits for response
    • Displays result
  4. View result:

Success (Green):

┌──────────────────────────────────────┐
│ ✅ Test SMS Sent Successfully!      │
│ Test SMS queued for sending         │
│ Message ID: msg_abc123...           │
│ Status: pending                     │
└──────────────────────────────────────┘

Error (Red):

┌──────────────────────────────────────┐
│ ❌ Failed to Send Test SMS          │
│ Phone number is not valid           │
└──────────────────────────────────────┘

Step 4: Verify in Logs

  1. Navigate to /admin/logs
  2. Look for test message:
    • Message ID from success response
    • Phone number you entered
    • Status: pending → sent → delivered
  3. Filter by gateway to see only this gateway's messages

API Endpoints

Check Connection

Endpoint: POST /admin/gateways/:id/check_connection

Response (Online):

{
  "status": "success",
  "message": "Gateway is online",
  "last_heartbeat": "2025-10-20T13:45:30.000Z",
  "time_ago": "1 minute"
}

Response (Offline):

{
  "status": "error",
  "message": "Gateway is offline",
  "last_heartbeat": "2025-10-20T08:30:15.000Z",
  "time_ago": "5 hours"
}

Send Test SMS

Endpoint: POST /admin/gateways/:id/send_test_sms

Request:

{
  "phone_number": "+959123456789",
  "message_body": "This is a test message"
}

Response (Success):

{
  "status": "success",
  "message": "Test SMS queued for sending",
  "message_id": "msg_abc123def456...",
  "sms_status": "pending"
}

Response (Error):

{
  "status": "error",
  "message": "Phone number and message are required"
}

Routes Added

resources :gateways do
  member do
    get :test                  # Testing page
    post :check_connection     # AJAX status check
    post :send_test_sms        # AJAX send test
    post :toggle               # Activate/deactivate (existing)
  end
end

New Routes:

  • GET /admin/gateways/:id/test - Testing page
  • POST /admin/gateways/:id/check_connection - Check status
  • POST /admin/gateways/:id/send_test_sms - Send test SMS

Controller Actions

test

def test
  @gateway = Gateway.find(params[:id])
end

Renders the testing page.

check_connection

def check_connection
  @gateway = Gateway.find(params[:id])

  if @gateway.online?
    render json: {
      status: "success",
      message: "Gateway is online",
      last_heartbeat: @gateway.last_heartbeat_at,
      time_ago: helpers.time_ago_in_words(@gateway.last_heartbeat_at)
    }
  else
    render json: {
      status: "error",
      message: "Gateway is offline",
      last_heartbeat: @gateway.last_heartbeat_at,
      time_ago: @gateway.last_heartbeat_at ? helpers.time_ago_in_words(@gateway.last_heartbeat_at) : "never"
    }
  end
end

send_test_sms

def send_test_sms
  @gateway = Gateway.find(params[:id])
  phone_number = params[:phone_number]
  message_body = params[:message_body]

  sms = SmsMessage.create!(
    direction: "outbound",
    phone_number: phone_number,
    message_body: message_body,
    gateway: @gateway,
    metadata: { test: true, sent_from: "admin_interface" }
  )

  render json: {
    status: "success",
    message: "Test SMS queued for sending",
    message_id: sms.message_id,
    sms_status: sms.status
  }
end

JavaScript Features

Auto-load Status

document.addEventListener('DOMContentLoaded', function() {
  checkConnection();  // Check on page load
});

Refresh Button

async function checkConnection() {
  // Show loading
  container.innerHTML = '<div class="spinner">...</div>';

  // Fetch status
  const response = await fetch('/admin/gateways/:id/check_connection', {
    method: 'POST',
    headers: {
      'X-CSRF-Token': csrfToken
    }
  });

  const data = await response.json();
  // Display result
}

Character Counter

messageBody.addEventListener('input', updateCharCount);

function updateCharCount() {
  const length = messageBody.value.length;
  const remaining = 160 - length;

  if (remaining < 0) {
    const parts = Math.ceil(length / 160);
    charCount.textContent = `${Math.abs(remaining)} characters over (${parts} parts)`;
    charCount.classList.add('text-red-600');
  } else {
    charCount.textContent = `${remaining} characters remaining`;
  }
}

Form Submission

form.addEventListener('submit', async function(e) {
  e.preventDefault();

  // Disable button
  submitButton.disabled = true;
  submitText.innerHTML = 'Sending...';

  // Send request
  const response = await fetch('/admin/gateways/:id/send_test_sms', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-CSRF-Token': csrfToken
    },
    body: JSON.stringify({
      phone_number: phoneNumber.value,
      message_body: messageBody.value
    })
  });

  const data = await response.json();
  // Display result and re-enable button
});

Test Message Metadata

All test messages include metadata for identification:

{
  test: true,
  sent_from: "admin_interface"
}

Benefits:

  • Easy to filter test messages in logs
  • Distinguish from production messages
  • Audit trail of admin testing
  • Can be excluded from analytics

Troubleshooting

Connection Check Fails

Symptom: Can't check gateway status

Causes:

  1. Database connection issue
  2. Gateway record not found
  3. JavaScript error

Solutions:

# Check Rails logs
tail -f log/development.log

# Verify gateway exists
bin/rails runner "puts Gateway.find(1).inspect"

# Check browser console for JavaScript errors

Test SMS Not Sending

Symptom: SMS queued but never sent

Causes:

  1. Gateway offline
  2. Sidekiq not running
  3. Redis not running
  4. Queue backed up

Solutions:

# Check gateway status
bin/rails console
> Gateway.find(1).online?

# Check Sidekiq
ps aux | grep sidekiq

# Start Sidekiq if needed
bundle exec sidekiq

# Check Redis
redis-cli ping

Invalid Phone Number

Symptom: "Phone number is not valid" error

Causes:

  1. Missing country code
  2. Invalid format
  3. Phonelib validation failed

Solutions:

  • Always include country code: +959123456789
  • Check number format for your country
  • Test number in console:
Phonelib.parse("+959123456789").valid?

Security Considerations

Admin Authentication Required

  • All testing endpoints require admin login
  • CSRF protection enabled
  • Session validation
  • No public access

Consider adding rate limiting:

# config/initializers/rack_attack.rb
Rack::Attack.throttle('test_sms_per_admin', limit: 10, period: 1.hour) do |req|
  if req.path == '/admin/gateways/*/send_test_sms' && req.post?
    req.session[:admin_id]
  end
end

Test Message Limits

Best Practices:

  • Limit test messages to prevent abuse
  • Log all test SMS sends
  • Monitor for unusual patterns
  • Alert on excessive testing

Phone Number Privacy

Considerations:

  • Test messages go to real phone numbers
  • Recipients will receive actual SMS
  • Use dedicated test numbers
  • Don't test with customer numbers

Best Practices

When to Use Testing

Good Use Cases:

  • After gateway registration (verify it works)
  • After configuration changes
  • Diagnosing offline issues
  • Verifying app updates
  • Training new staff

Avoid:

  • Testing with production phone numbers
  • Excessive testing (generates costs)
  • Testing offline gateways repeatedly
  • Using for regular message sending

Test Message Guidelines

Recommended Content:

This is a test message from MySMSAPio admin interface.
Gateway: [Gateway Name]
Date: [Date/Time]
Ignore this message.

Avoid:

  • Long messages (keep under 160 chars)
  • Multiple consecutive tests
  • Testing during peak hours
  • Sensitive information in tests

Monitoring Test Messages

View in Logs

  1. Navigate to /admin/logs
  2. Filter by:
    • Gateway name
    • Phone number
    • Date range
  3. Look for status progression:
    • pendingsentdelivered
  4. Check error messages if failed

Identify Test Messages

Test messages have:

  • metadata.test = true
  • metadata.sent_from = "admin_interface"

Query in console:

# Find all test messages
SmsMessage.where("metadata->>'test' = 'true'").count

# Find recent test messages
SmsMessage.where("metadata->>'test' = 'true'")
          .where("created_at > ?", 1.day.ago)
          .order(created_at: :desc)

Summary

Implemented: Gateway testing via admin interface Features: Connection check + Test SMS sending Access: From gateway list or details page Real-time: AJAX status updates Tracking: Full metadata and logging Security: Admin authentication required

Test any gateway easily:

  1. Click "Test" button
  2. Check status (auto-loads)
  3. Send test SMS
  4. View in logs

Perfect for debugging, verification, and training! 🚀