Testing Guide

Comprehensive testing strategies and best practices for integrating the Vehicle Custody Identity Verification SDKs.

Applies To

This testing guide applies to all Vehicle Custody SDKs. Use sandbox mode for all testing scenarios.

Quick Integration Test

import { createVecuIDVSDK } from 'vec-idp-web-sdk';

// Initialize SDK in sandbox mode
const sdk = createVecuIDVSDK({
  deploymentStage: 'sandbox',
  bearerToken: 'your-bearer-token-here',
  debug: true,
  logLevel: 'debug',
});

// Start verification with test customer data
async function test() {
  const cleanup = await sdk.startVerificationWithCustomer(
    '#verification-container',
    {
      customerInfo: {
        firstName: 'John',
        lastName: 'Doe',
        email: 'john.doe@example.com',
        address: { country: 'US' },
      },
      onProgress: event => {
        console.log(`Progress: ${event.step} (${event.percentage}%)`);
      },
      onSuccess: result => {
        console.log('Verification completed!', result);
        cleanup();
      },
      onError: error => {
        console.error('Verification failed:', error);
        cleanup();
      },
    }
  );
}

Test Customer Data

Use these predefined test customer profiles to test different verification scenarios in sandbox mode.

Successful Verification

This customer profile will pass all verification checks with high confidence.

const successfulCustomer = {
  firstName: 'John',
  lastName: 'Doe',
  email: 'john.doe@example.com',
  phone: '+1-555-123-4567',
  dateOfBirth: '1990-01-15',
  address: {
    line1: '123 Main Street',
    line2: 'Apt 4B',
    locality: 'Springfield',
    majorAdminDivision: 'IL',
    country: 'US',
    postalCode: '62701',
    type: 'residential',
  },
};

Failed Verification

This customer profile will fail verification for testing error handling.

const failedCustomer = {
  firstName: 'Jane',
  lastName: 'Smith',
  email: 'jane.fail@example.com',
  phone: '+1-555-987-6543',
  dateOfBirth: '1985-05-20',
  address: {
    line1: '456 Test Avenue',
    locality: 'Failtown',
    majorAdminDivision: 'TX',
    country: 'US',
    postalCode: '12345',
    type: 'residential',
  },
};

Manual Review Required

This customer profile will require manual review to test pending states.

const manualReviewCustomer = {
  firstName: 'Robert',
  lastName: 'Johnson',
  email: 'robert.review@example.com',
  phone: '+1-555-444-3333',
  dateOfBirth: '1975-12-08',
  address: {
    line1: '789 Review Street',
    locality: 'Reviewville',
    majorAdminDivision: 'CA',
    country: 'US',
    postalCode: '90210',
    type: 'residential',
  },
};

Validation Error Testing

Use these incomplete profiles to test client-side validation.

// Missing required fields
const incompleteCustomer = {
  firstName: 'Alice',
  // lastName missing - will trigger validation error
  email: 'alice@example.com',
  // address missing - will trigger validation error
};

// Invalid format
const invalidFormatCustomer = {
  firstName: 'Bob',
  lastName: 'Wilson',
  email: 'invalid-email-format', // Invalid email
  phone: '123', // Invalid phone format
  address: {
    line1: '123 Test St',
    locality: 'Test City',
    majorAdminDivision: 'ZZ', // Invalid state code
    country: 'XX', // Invalid country code
    postalCode: '1', // Invalid postal code format
    type: 'residential',
  },
};

Backend Validation Error Testing (v1.5.5+)

Test data that triggers specific backend validation errors. These errors include a recoverable: true flag, allowing users to correct their data and retry.

// Invalid ZIP code - triggers INVALID_ZIP_CODE
const invalidZipCustomer = {
  firstName: 'John',
  lastName: 'Doe',
  email: 'john.doe@example.com',
  phone: '+1-555-123-4567',
  address: {
    line1: '123 Main Street',
    locality: 'Springfield',
    majorAdminDivision: 'IL',
    country: 'US',
    postalCode: '12', // Too short - triggers backend error
    type: 'residential',
  },
};

// Invalid country - triggers INVALID_COUNTRY
const invalidCountryCustomer = {
  firstName: 'Jane',
  lastName: 'Smith',
  email: 'jane.smith@example.com',
  phone: '+1-555-987-6543',
  address: {
    line1: '456 Oak Avenue',
    locality: 'Test City',
    majorAdminDivision: 'TX',
    country: 'XX', // Invalid country code - triggers backend error
    postalCode: '75001',
    type: 'residential',
  },
};

// Invalid state - triggers INVALID_STATE
const invalidStateCustomer = {
  firstName: 'Bob',
  lastName: 'Johnson',
  email: 'bob.johnson@example.com',
  phone: '+1-555-444-3333',
  address: {
    line1: '789 Pine Road',
    locality: 'Testville',
    majorAdminDivision: 'XX', // Non-existent state - triggers backend error
    country: 'US',
    postalCode: '90210',
    type: 'residential',
  },
};

Expected Error Response Structure:

{
  code: 'INVALID_ZIP_CODE',  // or INVALID_COUNTRY, INVALID_STATE, etc.
  message: 'The zip code is invalid',
  provider: 'identity_provider',
  details: {
    category: 'validation_error',
    recoverable: true,
    timestamp: '2026-01-07T14:54:33.251Z'
  }
}

Backend Validation Error Testing Notes

  • Confirmed error codes: INVALID_ZIP_CODE, INVALID_COUNTRY, INVALID_STATE, INVALID_ADDRESS, INVALID_CITY, INVALID_PHONE - Backend validation errors (v1.5.5+) are marked as recoverable: true - Users should be guided to correct the invalid data and retry verification - Error messages are human-readable and can be displayed directly to users - Test error handling by checking for specific error codes in the onError callback

Reverification Testing

Test the reverification flow using reference IDs from completed verifications.

Successful Reverification

// First, complete a regular verification
const verificationCleanup = await sdk.startVerificationWithCustomer(
  '#container',
  {
    customerInfo: {
      firstName: 'John',
      lastName: 'Doe',
      email: 'john.doe@example.com',
      address: { country: 'US' },
    },
    referenceId: 'test-customer-123',
    onSuccess: result => {
      console.log('Initial verification completed:', result.verificationId);
    },
  }
);

// Later, perform reverification using the same referenceId
const reverifyCleanup = await sdk.startReverification('#container', {
  referenceId: 'test-customer-123', // Same referenceId as original
  phoneNumber: '+1-555-123-4567', // Optional
  onProgress: event => {
    console.log(`Reverification progress: ${event.percentage}%`);
  },
  onSuccess: result => {
    console.log('Reverification completed!', result);
  },
  onError: error => {
    console.error('Reverification failed:', error);
  },
});

Test Reference IDs

Use these test reference IDs in sandbox mode to trigger specific reverification scenarios:

Reference IDScenario
test-reverify-success-001Successful Reverification
test-reverify-fail-selfieFailed (Selfie Mismatch)
test-reverify-fail-qualityFailed (Quality Issues)
test-reverify-review-pendingManual Review Required

Reverification Testing Tips

  • Always test reverification in sandbox mode before production - Verify that webhook events use reverification.* event types - Test both success and failure scenarios - Confirm that verification IDs start with reverify prefix

Mock Webhook Server

Set up a local webhook server for testing webhook events during development.

Express.js Mock Server

// webhook-server.js
const express = require('express');
const app = express();

app.use(express.json());

// Webhook endpoint for VECU events
app.post('/webhooks/vecu-idv', (req, res) => {
  const event = req.body;

  console.log('Received webhook event:');
  console.log('Event ID:', event.eventId);
  console.log('Event Type:', event.eventType);
  console.log('Timestamp:', event.timestamp);
  console.log('Decision:', event.data?.decision);
  console.log('Reason Codes:', event.data?.reasons);
  console.log('Full Data:', JSON.stringify(event.data, null, 2));
  console.log('---');

  // Always return success to acknowledge receipt
  res.status(200).json({
    status: 'received',
    eventId: event.eventId,
    timestamp: new Date().toISOString(),
  });
});

// Health check endpoint
app.get('/health', (req, res) => {
  res.json({ status: 'healthy', timestamp: new Date().toISOString() });
});

const PORT = process.env.PORT || 3001;
app.listen(PORT, () => {
  console.log(`Webhook server running on http://localhost:${PORT}`);
  console.log(`Webhook URL: http://localhost:${PORT}/webhooks/vecu-idv`);
});

Setup Instructions:

  1. Save the code above as webhook-server.js
  2. Install dependencies: npm install express
  3. Run the server: node webhook-server.js
  4. Use ngrok to expose locally: ngrok http 3001
  5. Configure the ngrok URL as your webhook endpoint

Python (Flask) Mock Server

# webhook_server.py
from flask import Flask, request, jsonify
from datetime import datetime
import json

app = Flask(__name__)

@app.route('/webhooks/vecu-idv', methods=['POST'])
def handle_webhook():
    event = request.get_json()

    print('Received webhook event:')
    print(f'Event ID: {event.get("eventId")}')
    print(f'Event Type: {event.get("eventType")}')
    print(f'Timestamp: {event.get("timestamp")}')
    print(f'Data: {json.dumps(event.get("data"), indent=2)}')
    print('---')

    return jsonify({
        'status': 'received',
        'eventId': event.get('eventId'),
        'timestamp': datetime.utcnow().isoformat() + 'Z'
    }), 200

@app.route('/health', methods=['GET'])
def health_check():
    return jsonify({
        'status': 'healthy',
        'timestamp': datetime.utcnow().isoformat() + 'Z'
    }), 200

if __name__ == '__main__':
    print('Webhook server running on http://localhost:3001')
    app.run(host='0.0.0.0', port=3001, debug=True)

Testing Scenarios

Happy Path Testing

  • Successful verification with high confidence
  • Proper webhook event handling
  • Correct UI state transitions
  • Customer data persistence
  • Cleanup function execution

Error Handling

  • Network connectivity failures
  • Invalid customer data validation
  • Authentication failures
  • Timeout scenarios
  • SDK initialization errors

Edge Cases

  • Manual review required scenarios
  • Multiple verification attempts
  • Browser compatibility issues
  • Mobile device testing
  • Slow network conditions

Integration Testing

  • Framework-specific implementations
  • Multiple SDK instances
  • Webhook delivery reliability
  • Database state consistency
  • User experience flows

Compliance Testing (v1.3.3+)

Test SSN/National ID field visibility for different compliance scenarios.

SSN Field Hidden (GDPR Compliance)

const sdk = createVecuIDVSDK({
  deploymentStage: 'sandbox',
  bearerToken: 'your-bearer-token',
});

const cleanup = await sdk.startVerificationWithCustomer(
  '#verification-container',
  {
    customerInfo: {
      firstName: 'John',
      lastName: 'Doe',
      email: 'john.doe@example.com',
      phone: '+1-555-123-4567',
      address: { country: 'DE' }, // German user
    },
    referenceId: 'eu-customer-123',
    config: {
      showSsnOnInitialForm: false, // Hide SSN field
    },
  }
);

// Expected: Address form shows NO SSN field
// API payload will NOT include national_id

Conditional Visibility (Location-Based)

// Determine SSN requirement based on user's country
function shouldShowSsn(country) {
  const gdprCountries = ['AT', 'BE', 'DE', 'FR', 'IT', 'ES'];
  return !gdprCountries.includes(country);
}

const userCountry = getUserCountry();

await sdk.startVerificationWithCustomer('#container', {
  customerInfo: {
    /* ... */
  },
  config: {
    showSsnOnInitialForm: shouldShowSsn(userCountry),
  },
});

// Test with different countries:
// - US, CA, MX: SSN field visible
// - DE, FR, IT: SSN field hidden

Environment Configuration

Development Environment

# .env.development
VECU_DEPLOYMENT_STAGE=sandbox
VECU_CLIENT_ID=dev-client-id-here
VECU_CLIENT_SECRET=dev-client-secret-here
VECU_DEBUG=true
VECU_LOG_LEVEL=debug
const sdk = createVecuIDVSDK({
  deploymentStage: process.env.VECU_DEPLOYMENT_STAGE,
  bearerToken: process.env.VECU_BEARER_TOKEN,
  debug: process.env.VECU_DEBUG === 'true',
  logLevel: process.env.VECU_LOG_LEVEL,
});

Testing Environment

# .env.test
VECU_DEPLOYMENT_STAGE=sandbox
VECU_DEBUG=false
VECU_LOG_LEVEL=error
VECU_WEBHOOK_URL=http://localhost:3001/webhooks/vecu-idv
// Jest setup - jest.setup.js
import { createVecuIDVSDK } from 'vec-idp-web-sdk';

// Mock SDK for testing
jest.mock('vec-idp-web-sdk', () => ({
  createVecuIDVSDK: jest.fn(() => ({
    startVerificationWithCustomer: jest.fn().mockResolvedValue(() => {}),
    destroy: jest.fn(),
  })),
}));

Development Tools

Local Development

ToolPurpose
ngrokExpose local webhook server publicly
PostmanTest webhook endpoints and SDK integrations
curlCommand-line webhook testing
Browser DevToolsDebug SDK integration and network requests

Testing Services

ServicePurpose
RequestBinTemporary webhook endpoint for testing
Webhook.siteInspect webhook payloads in real-time
MockoonMock backend responses for SDK testing
JSONPlaceholderMock REST API for development

Debugging Checklist

SDK Integration Issues

  • Check browser console for error messages
  • Verify SDK configuration parameters
  • Ensure container element exists and is visible
  • Check network tab for failed API requests
  • Validate customer data format

Webhook Issues

  • Verify webhook URL is publicly accessible
  • Check webhook server logs for incoming requests
  • Ensure proper HTTP response codes (200)
  • Validate webhook authentication if configured
  • Test webhook endpoint with curl or Postman

Environment Issues

  • Verify all environment variables are set
  • Check API credentials are valid and not expired
  • Ensure correct deployment stage (sandbox/production)
  • Test network connectivity to VECU services
  • Review CORS configuration for your domain

Need More Help?

If you're still experiencing issues, enable debug mode and check the SDK troubleshooting guide for detailed solutions.

Next Steps