Files
anthropics--knowledge-work-…/partner-built/zoom-plugin/skills/general/use-cases/testing-development.md
T
2026-07-13 12:20:06 +08:00

7.2 KiB

Testing & Development Environment

Set up development and testing environments for Zoom integrations.

Overview

Zoom provides several options for development and testing:

  • Development app credentials (separate from production)
  • Test accounts
  • Local webhook testing tools
  • SDK sandbox modes

Skills Needed

  • general - App configuration
  • webhooks - Webhook testing

Development vs Production Apps

Create Separate Apps

Always create separate apps for development and production:

Environment Purpose Credentials
Development Testing, debugging Dev Client ID/Secret
Production Live users Prod Client ID/Secret
  1. Go to Zoom Marketplace
  2. Create "MyApp - Development" for testing
  3. Create "MyApp - Production" for live deployment
  4. Use environment variables to switch between them
// .env.development
ZOOM_CLIENT_ID=dev_client_id_here
ZOOM_CLIENT_SECRET=dev_secret_here
ZOOM_ACCOUNT_ID=dev_account_id

// .env.production
ZOOM_CLIENT_ID=prod_client_id_here
ZOOM_CLIENT_SECRET=prod_secret_here
ZOOM_ACCOUNT_ID=prod_account_id

Test Accounts

Option 1: Developer Account

Use your own Zoom account for initial development:

  • Free tier works for basic API testing
  • Pro account needed for SDK testing
  • Create test meetings manually

Option 2: Zoom Developer Sandbox (ISV Partners)

ISV partners can request sandbox accounts:

  • Contact Zoom partnership team
  • Isolated test environment
  • Multiple test users

Option 3: Programmatic Test Users

Create test users via API (requires admin account):

// Create a test user
const response = await axios.post(
  'https://api.zoom.us/v2/users',
  {
    action: 'create',
    user_info: {
      email: 'testuser+1@yourcompany.com',  // Use + alias
      type: 1,  // Basic user
      first_name: 'Test',
      last_name: 'User'
    }
  },
  { headers: { 'Authorization': `Bearer ${accessToken}` }}
);

Tip: Use email aliases (testuser+1@company.com, testuser+2@company.com) that all route to one inbox.


Local Webhook Testing

Expose your local development webhook server to the internet for testing:

# Install ngrok
npm install -g ngrok

# Start your local server
node server.js  # Running on port 3000

# In another terminal, create tunnel
ngrok http 3000

Output:

Forwarding  https://abc123.ngrok.io -> http://YOUR_DEV_HOST:3000

Use https://abc123.ngrok.io/webhook as your webhook URL in Zoom Marketplace.

Option 2: Cloudflare Tunnel

# Install cloudflared
brew install cloudflare/cloudflare/cloudflared

# Create tunnel
LOCAL_WEBHOOK_BASE_URL="http://YOUR_DEV_HOST:3000"
cloudflared tunnel --url "$LOCAL_WEBHOOK_BASE_URL"

Option 3: localtunnel

npm install -g localtunnel
lt --port 3000

Webhook URL Validation

Zoom requires validating your webhook endpoint. Your server must respond to the challenge:

app.post('/webhook', (req, res) => {
  // Handle Zoom's endpoint validation
  if (req.body.event === 'endpoint.url_validation') {
    const hashForValidate = crypto
      .createHmac('sha256', ZOOM_WEBHOOK_SECRET)
      .update(req.body.payload.plainToken)
      .digest('hex');
    
    return res.json({
      plainToken: req.body.payload.plainToken,
      encryptedToken: hashForValidate
    });
  }
  
  // Handle actual events
  // ...
});

SDK Development Mode

Meeting SDK Web

Enable debug logging:

const client = ZoomMtgEmbedded.createClient();

client.init({
  debug: true,  // Enable debug logs
  zoomAppRoot: document.getElementById('meetingSDKElement'),
  language: 'en-US',
});

Video SDK Web

const client = ZoomVideo.createClient();

await client.init('en-US', 'CDN', {
  enforceMultipleVideos: true,
  stayAwake: true,
  patchJsMedia: true,
  leaveOnPageUnload: true,
});

// Enable debug mode
ZoomVideo.setLogLevel('debug');

Native SDKs (iOS/Android/Desktop)

Enable verbose logging:

// iOS
let initParams = ZoomVideoSDKInitParams()
initParams.enableLog = true
initParams.logFilePrefix = "videosdk_debug"
// Android
val initParams = ZoomVideoSDKInitParams().apply {
    enableLog = true
    logFilePrefix = "videosdk_debug"
}

Mock Webhook Events

Manual Testing with curl

Test your webhook handler locally:

LOCAL_WEBHOOK_BASE_URL="http://YOUR_DEV_HOST:3000"

# Simulate meeting.started event
curl -X POST "$LOCAL_WEBHOOK_BASE_URL/webhook" \
  -H "Content-Type: application/json" \
  -H "x-zm-signature: v0=test" \
  -H "x-zm-request-timestamp: $(date +%s)" \
  -d '{
    "event": "meeting.started",
    "payload": {
      "account_id": "abc123",
      "object": {
        "id": "123456789",
        "uuid": "abcd-1234-efgh",
        "topic": "Test Meeting",
        "host_id": "xyz789"
      }
    }
  }'

Webhook Replay Tool

Build a simple replay tool for testing:

const fs = require('fs');

// Save incoming webhooks to file
app.post('/webhook', (req, res) => {
  const filename = `webhooks/${Date.now()}_${req.body.event}.json`;
  fs.writeFileSync(filename, JSON.stringify(req.body, null, 2));
  
  // Process normally...
});

// Replay saved webhook
async function replayWebhook(filename) {
  const payload = JSON.parse(fs.readFileSync(filename));
  await processWebhook(payload);
}

Testing Checklist

Before Going Live

  • Test OAuth flow end-to-end
  • Verify webhook signature validation
  • Test with multiple user types (host, participant, admin)
  • Handle rate limiting gracefully
  • Test error scenarios (invalid tokens, network failures)
  • Verify recording download permissions
  • Test SDK on all target platforms
  • Load test with expected user volume

API Testing

// Test helper for API calls
async function testAPICall(name, fn) {
  console.log(`Testing: ${name}`);
  try {
    const result = await fn();
    console.log(`Pass: ${name}`);
    return result;
  } catch (error) {
    console.error(`Fail: ${name}:`, error.message);
    throw error;
  }
}

// Run tests
await testAPICall('Create meeting', () => 
  createMeeting({ topic: 'Test' })
);
await testAPICall('Get meeting', () => 
  getMeeting(meetingId)
);
await testAPICall('Delete meeting', () => 
  deleteMeeting(meetingId)
);

Debugging Tips

Enable Request Logging

const axios = require('axios');

// Log all requests
axios.interceptors.request.use(config => {
  console.log(`-> ${config.method.toUpperCase()} ${config.url}`);
  return config;
});

axios.interceptors.response.use(
  response => {
    console.log(`<- ${response.status} ${response.config.url}`);
    return response;
  },
  error => {
    console.error(`<- ${error.response?.status} ${error.config?.url}`);
    console.error('Error:', error.response?.data);
    throw error;
  }
);

SDK Log Collection

See SDK Logs & Troubleshooting for collecting SDK debug logs.

Resources