Overview
This guide walks you through testing your BOOP Network integration using our development environment at dev.app.boop.it. You’ll learn how to simulate authentication flows, test edge cases, and verify your integration works correctly.
Test Environment Setup
1. Get Test Credentials
Request test credentials from our team:
# Test credentials format
Vendor ID: ven_test_abc123
API Key: sk_test_xyz789
Environment: https://dev.app.boop.it
Test credentials only work in the development environment. They cannot process real transactions.
Set up environment-specific configuration:
# Development
BOOP_ENV = development
BOOP_API_URL = https : //dev.app.boop.it
BOOP_WS_URL = wss : //dev.app.boop.it/ws/vendor
BOOP_API_KEY = sk_test_xyz789
BOOP_VENDOR_ID = ven_test_abc123
# Production ( for later )
# BOOP_ENV = production
# BOOP_API_URL = https : //app.boop.it
# BOOP_WS_URL = wss : //app.boop.it/ws/vendor
# BOOP_API_KEY = sk_live_ [ your_production_key ]
# BOOP_VENDOR_ID = ven_live_ [ your_production_id ]
Palm Vein Scanner Simulator
Access our mock PVS interface to simulate palm scans:
URL : https://mock-pvs.dev.event-vendor.boop.it
Features :
Register test users
Simulate successful/failed scans
Test different authentication scenarios
Generate test biometric data
Test User Management
Create and manage test users for your integration:
// Register a test user
const registerTestUser = async ( userId , attributes ) => {
const response = await fetch ( 'https://dev.app.boop.it/api/v1/test-users' , {
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'X-API-Key' : 'sk_test_xyz789'
},
body: JSON . stringify ({
user_id: userId ,
attributes: {
email: ` ${ userId } @test.boop.network` ,
name: `Test User ${ userId } ` ,
age_verified: true ,
... attributes
}
})
});
return response . json ();
};
// Create test users with different profiles
await registerTestUser ( 'test_adult_user' , { age_verified: true });
await registerTestUser ( 'test_minor_user' , { age_verified: false });
await registerTestUser ( 'test_vip_user' , { membership_level: 'vip' });
Testing Scenarios
1. Basic Authentication Flow
Test the complete authentication cycle:
// Test script for basic authentication
async function testBasicAuth () {
console . log ( '🧪 Testing Basic Authentication Flow' );
// 1. Create authentication context
const contextId = await client . createAuthContext (
'payment' ,
[ 'email' , 'name' ],
{ amount: 10.00 , test_mode: true }
);
console . log ( `✓ Context created: ${ contextId } ` );
// 2. Simulate user scanning palm
// Use mock PVS interface at mock-pvs.dev.event-vendor.boop.it
await simulatePalmScan ( contextId , 'test_user_1' );
// 3. Wait for authentication result
const result = await waitForAuthResult ( contextId , 30000 );
if ( result . success ) {
console . log ( '✓ Authentication successful' );
console . log ( ' User ID:' , result . user_id );
console . log ( ' Attributes:' , result . attributes );
} else {
console . log ( '✗ Authentication failed:' , result . reason );
}
}
2. Attribute Verification
Test requesting and receiving user attributes:
// Test different attribute combinations
const attributeTests = [
{
name: 'Basic Attributes' ,
attributes: [ 'email' , 'name' ],
expectedFields: [ 'email' , 'name' ]
},
{
name: 'Age Verification' ,
attributes: [ 'age_verified' ],
expectedFields: [ 'age_verified' ]
},
{
name: 'Complete Profile' ,
attributes: [ 'email' , 'name' , 'phone' , 'address' ],
expectedFields: [ 'email' , 'name' , 'phone' , 'address' ]
}
];
for ( const test of attributeTests ) {
console . log ( ` \n 🧪 Testing: ${ test . name } ` );
const contextId = await client . createAuthContext (
'verification' ,
test . attributes ,
{ test_scenario: test . name }
);
const result = await performAuthentication ( contextId );
// Verify all requested attributes are returned
for ( const field of test . expectedFields ) {
if ( field in result . attributes ) {
console . log ( ` ✓ ${ field } : ${ result . attributes [ field ] } ` );
} else {
console . log ( ` ✗ Missing attribute: ${ field } ` );
}
}
}
3. Error Handling
Test error scenarios and recovery:
// Error scenario testing
async function testErrorScenarios () {
console . log ( '🧪 Testing Error Scenarios' );
// Test 1: Invalid API key
try {
const badClient = new BOOPClient ( 'invalid_key' , 'ven_test' );
await badClient . connect ();
} catch ( error ) {
console . log ( '✓ Invalid API key rejected:' , error . message );
}
// Test 2: Missing required attributes
try {
await client . createAuthContext ( 'payment' , null );
} catch ( error ) {
console . log ( '✓ Missing attributes caught:' , error . message );
}
// Test 3: Context timeout
const contextId = await client . createAuthContext (
'payment' ,
[ 'email' ],
{ timeout: 1 } // 1 second timeout
);
await sleep ( 2000 ); // Wait for timeout
const status = await getContextStatus ( contextId );
console . log ( '✓ Context timeout handled:' , status );
// Test 4: Network disconnection
await client . connect ();
client . ws . close (); // Simulate disconnect
console . log ( '✓ Disconnection detected' );
// Verify reconnection
await sleep ( 6000 );
if ( client . ws . readyState === WebSocket . OPEN ) {
console . log ( '✓ Automatic reconnection successful' );
}
}
Measure latency and throughput:
// Performance testing
async function performanceTest () {
console . log ( '🧪 Performance Testing' );
const iterations = 100 ;
const latencies = [];
for ( let i = 0 ; i < iterations ; i ++ ) {
const startTime = Date . now ();
const contextId = await client . createAuthContext (
'payment' ,
[ 'email' ],
{ test_iteration: i }
);
await simulatePalmScan ( contextId , 'test_user_perf' );
const result = await waitForAuthResult ( contextId , 5000 );
const latency = Date . now () - startTime ;
latencies . push ( latency );
if ( i % 10 === 0 ) {
console . log ( ` Iteration ${ i } : ${ latency } ms` );
}
}
// Calculate statistics
const avg = latencies . reduce (( a , b ) => a + b , 0 ) / latencies . length ;
const min = Math . min ( ... latencies );
const max = Math . max ( ... latencies );
const p95 = latencies . sort (( a , b ) => a - b )[ Math . floor ( iterations * 0.95 )];
console . log ( ' \n 📊 Performance Results:' );
console . log ( ` Average: ${ avg . toFixed ( 2 ) } ms` );
console . log ( ` Min: ${ min } ms` );
console . log ( ` Max: ${ max } ms` );
console . log ( ` P95: ${ p95 } ms` );
}
Test Data Sets
User Profiles
Use these test user profiles for different scenarios:
User ID Profile Attributes Use Case test_adult_01Adult Customer age_verified: true, email, name Age-restricted purchases test_minor_01Minor Customer age_verified: false, email, name Age verification failure test_vip_01VIP Member membership: ‘vip’, email, name, phone Premium services test_employee_01Employee employee_id, department, access_level Access control test_restricted_01Limited Profile email only Minimal data sharing
Test Amounts
For payment contexts, use these amounts to trigger different behaviors:
Amount Behavior 0.01 - 0.99Always succeeds (test mode) 1.00 - 99.99Normal processing 100.00Triggers additional verification 666.66Simulates fraud detection 999.99Simulates timeout
Automated Testing
Integration Test Suite
Create automated tests for CI/CD:
// test/integration/boop.test.js
const { BOOPClient } = require ( '../src/boop-client' );
const assert = require ( 'assert' );
describe ( 'BOOP Integration Tests' , () => {
let client ;
before ( async () => {
client = new BOOPClient (
process . env . BOOP_TEST_API_KEY ,
process . env . BOOP_TEST_VENDOR_ID
);
await client . connect ();
});
after ( async () => {
await client . disconnect ();
});
describe ( 'Authentication' , () => {
it ( 'should connect and authenticate successfully' , async () => {
assert ( client . isConnected (), 'Client should be connected' );
});
it ( 'should reject invalid credentials' , async () => {
const badClient = new BOOPClient ( 'invalid' , 'invalid' );
try {
await badClient . connect ();
assert . fail ( 'Should have thrown error' );
} catch ( error ) {
assert ( error . message . includes ( 'Authentication failed' ));
}
});
});
describe ( 'Context Creation' , () => {
it ( 'should create payment context' , async () => {
const contextId = await client . createAuthContext (
'payment' ,
[ 'email' ],
{ amount: 10.00 }
);
assert ( contextId . startsWith ( 'ctx_' ), 'Context ID should have correct format' );
});
it ( 'should create access context' , async () => {
const contextId = await client . createAuthContext (
'access' ,
[ 'employee_id' ],
{ location: 'Test Location' }
);
assert ( contextId , 'Context should be created' );
});
});
describe ( 'Attribute Handling' , () => {
it ( 'should return requested attributes' , async () => {
const contextId = await client . createAuthContext (
'verification' ,
[ 'email' , 'name' ]
);
// Simulate authentication
const result = await simulateAuth ( contextId , 'test_user_attrs' );
assert ( result . attributes . email , 'Email should be present' );
assert ( result . attributes . name , 'Name should be present' );
});
it ( 'should handle optional attributes' , async () => {
const contextId = await client . createAuthContext (
'verification' ,
[ 'email' , 'phone' ] // Phone might not be available
);
const result = await simulateAuth ( contextId , 'test_user_partial' );
assert ( result . attributes . email , 'Email should be present' );
// Phone may or may not be present
});
});
});
Load Testing
Test your system under load:
// load-test.js
const { Worker } = require ( 'worker_threads' );
const os = require ( 'os' );
async function loadTest () {
const workers = os . cpus (). length ;
const requestsPerWorker = 100 ;
console . log ( `🚀 Starting load test with ${ workers } workers` );
console . log ( ` ${ requestsPerWorker } requests per worker` );
console . log ( ` Total requests: ${ workers * requestsPerWorker } ` );
const startTime = Date . now ();
const promises = [];
for ( let i = 0 ; i < workers ; i ++ ) {
promises . push (
new Promise (( resolve , reject ) => {
const worker = new Worker ( './worker.js' , {
workerData: {
requests: requestsPerWorker ,
workerId: i
}
});
worker . on ( 'message' , resolve );
worker . on ( 'error' , reject );
})
);
}
const results = await Promise . all ( promises );
const duration = Date . now () - startTime ;
const totalRequests = results . reduce (( sum , r ) => sum + r . completed , 0 );
const totalErrors = results . reduce (( sum , r ) => sum + r . errors , 0 );
console . log ( ' \n 📊 Load Test Results:' );
console . log ( ` Duration: ${ duration } ms` );
console . log ( ` Successful: ${ totalRequests } ` );
console . log ( ` Failed: ${ totalErrors } ` );
console . log ( ` Throughput: ${ ( totalRequests / ( duration / 1000 )). toFixed ( 2 ) } req/s` );
}
loadTest ();
Debugging
Enable Debug Logging
// Enable verbose logging for debugging
const client = new BOOPClient ( apiKey , vendorId , {
debug: true ,
logLevel: 'verbose'
});
client . on ( 'debug' , ( message ) => {
console . log ( `[DEBUG] ${ message } ` );
});
client . on ( 'raw' , ( data ) => {
console . log ( `[RAW] ${ JSON . stringify ( data , null , 2 ) } ` );
});
Message Tracing
Track message flow through your system:
class TrackedClient extends BOOPClient {
constructor ( apiKey , vendorId ) {
super ( apiKey , vendorId );
this . messageLog = [];
}
send ( data ) {
this . messageLog . push ({
direction: 'outbound' ,
timestamp: new Date (),
data: data
});
super . send ( data );
}
handleMessage ( message ) {
this . messageLog . push ({
direction: 'inbound' ,
timestamp: new Date (),
data: message
});
super . handleMessage ( message );
}
exportTrace () {
return this . messageLog ;
}
}
Monitoring & Metrics
Health Check Endpoint
Monitor your integration health:
// Health check endpoint for your service
app . get ( '/health/boop' , async ( req , res ) => {
const health = {
status: 'healthy' ,
timestamp: new Date (),
checks: {}
};
// Check WebSocket connection
health . checks . websocket = {
connected: client . isConnected (),
lastPing: client . lastPingTime ,
reconnectCount: client . reconnectCount
};
// Check authentication status
health . checks . authentication = {
authenticated: client . isAuthenticated (),
vendorId: client . vendorId
};
// Check recent activity
health . checks . activity = {
activeContexts: client . activeContexts . size ,
lastActivity: client . lastActivityTime
};
// Overall status
health . status = health . checks . websocket . connected ? 'healthy' : 'unhealthy' ;
res . status ( health . status === 'healthy' ? 200 : 503 ). json ( health );
});
Common Issues & Solutions
Connection keeps dropping
Problem : WebSocket disconnects frequentlySolutions :
Implement exponential backoff for reconnection
Check network stability
Ensure proper ping/pong handling
Verify firewall/proxy settings
// Robust reconnection logic
class StableClient extends BOOPClient {
async handleDisconnect () {
this . reconnectDelay = Math . min (
this . reconnectDelay * 2 ,
30000
);
await sleep ( this . reconnectDelay );
await this . connect ();
}
}
Problem : Users can’t authenticate successfullyChecklist :
Verify test user is registered
Check requested attributes exist
Ensure context hasn’t expired
Validate API credentials
// Debug authentication issues
client . on ( 'authentication_failed' , ( data ) => {
console . error ( 'Auth failed:' , {
context: data . context_id ,
reason: data . reason ,
details: data . details
});
});
Problem : Not receiving expected user attributesSolutions :
Verify attributes are configured in your vendor profile
Check user has granted permission
Ensure attributes exist for test user
// Handle partial attributes
const attributes = result . attributes || {};
const email = attributes . email || 'Not provided' ;
const name = attributes . name || 'Anonymous' ;
Next Steps