@billdog.io/sandbox-testing
v1.1.1-beta.5
Published
Sandbox testing utilities for BillDog SDK - Create mock purchases, time travel, error simulation
Maintainers
Readme
@billdog.io/sandbox-testing
Sandbox testing utilities for BillDog SDK. Create mock purchases, simulate time travel, inject errors, and test subscription flows without real transactions.
Features
✅ Mock Purchases - Create test purchases with various scenarios
⏰ Time Travel - Fast-forward time to test subscriptions, trials, renewals
❌ Error Injection - Force specific errors to test error handling
🧪 Test User Management - Isolated test environments per user
🔄 Restore Testing - Simulate purchase restoration
🧹 Easy Cleanup - Clear test data between runs
Installation
npm install @billdog.io/sandbox-testing
# or
yarn add @billdog.io/sandbox-testingPrerequisites
- BillDog SDK installed (
@billdog.io/react-native,@billdog.io/web-sdk, etc.) - Sandbox API key (starts with
bd_public_test_)
Quick Start
import BillDog from '@billdog.io/react-native';
import { BillDogSandbox } from '@billdog.io/sandbox-testing';
// 1. Configure main SDK with sandbox key
BillDog.configure({
apiKey: 'bd_public_test_abc123...'
});
// 2. Configure sandbox utilities (uses same key)
BillDogSandbox.configure({
apiKey: 'bd_public_test_abc123...',
debug: true // Optional: Enable debug logs
});
// 3. Create a test purchase
await BillDogSandbox.createTestPurchase({
productId: 'premium_monthly',
scenario: 'successful_purchase'
});
// 4. Time travel to test renewal
await BillDogSandbox.advanceDays(30);
// 5. Clean up
await BillDogSandbox.clearPurchases();Core API
Configuration
BillDogSandbox.configure({
apiKey: 'bd_public_test_...', // Required: Sandbox API key
baseUrl?: string, // Optional: Custom backend URL
debug?: boolean // Optional: Enable debug logging
});Test Purchase Scenarios
type TestScenario =
| 'successful_purchase'
| 'failed_purchase'
| 'cancelled_purchase'
| 'trial_started'
| 'trial_converted'
| 'subscription_renewed'
| 'subscription_expired'
| 'subscription_cancelled'
| 'refunded_purchase'
| 'billing_issue'
| 'grace_period';
await BillDogSandbox.createTestPurchase({
productId: 'premium_annual',
scenario: 'trial_started',
testUserId: 'test_user_123', // Optional
customAttributes: { // Optional
promoCode: 'TESTCODE'
},
delayMs: 1000 // Optional: Simulate network delay
});Time Travel
// Advance time by specific duration
await BillDogSandbox.advanceTime({
duration: 7,
unit: 'days', // 'seconds' | 'minutes' | 'hours' | 'days' | 'weeks' | 'months'
testUserId: 'test_user_123' // Optional
});
// Convenience methods
await BillDogSandbox.advanceDays(7);
await BillDogSandbox.advanceWeeks(2);
await BillDogSandbox.advanceMonths(1);
// Reset to current time
await BillDogSandbox.resetTime();Error Simulation
// Force next purchase to fail
await BillDogSandbox.forceError('payment_declined');
// Force specific scenario
await BillDogSandbox.forceScenario('subscription_expired');
// Convenience methods
await BillDogSandbox.forceNetworkError();
await BillDogSandbox.forcePaymentDeclined();
await BillDogSandbox.forceUserCancelled();
// Clear forced behavior
await BillDogSandbox.clearForcedBehavior();Test Data Management
// Get purchase history
const purchases = await BillDogSandbox.getPurchaseHistory('test_user_123');
// Simulate restore purchases
const { restoredPurchases } = await BillDogSandbox.simulateRestorePurchases();
// Clear all test purchases
await BillDogSandbox.clearPurchases('test_user_123');Common Testing Patterns
Testing Trial to Paid Conversion
// 1. Start trial
await BillDogSandbox.createTestPurchase({
productId: 'premium_monthly',
scenario: 'trial_started'
});
// 2. Check entitlements
const info = await BillDog.getCustomerInfo();
console.log('Trial active:', info.entitlements.premium.isActive);
// 3. Fast-forward to end of trial
await BillDogSandbox.advanceDays(7);
// 4. Simulate conversion
await BillDogSandbox.createTestPurchase({
productId: 'premium_monthly',
scenario: 'trial_converted'
});
// 5. Verify paid subscription
const updatedInfo = await BillDog.getCustomerInfo();
console.log('Paid subscription:', updatedInfo.entitlements.premium.isActive);Testing Subscription Renewal
// 1. Create active subscription
await BillDogSandbox.createTestPurchase({
productId: 'premium_monthly',
scenario: 'successful_purchase'
});
// 2. Advance to renewal date
await BillDogSandbox.advanceMonths(1);
// 3. Simulate successful renewal
await BillDogSandbox.createTestPurchase({
productId: 'premium_monthly',
scenario: 'subscription_renewed'
});Testing Failed Payments
// 1. Active subscription
await BillDogSandbox.createTestPurchase({
productId: 'premium_monthly',
scenario: 'successful_purchase'
});
// 2. Advance to renewal date
await BillDogSandbox.advanceMonths(1);
// 3. Simulate failed renewal
await BillDogSandbox.forceScenario('billing_issue');
await BillDogSandbox.createTestPurchase({
productId: 'premium_monthly',
scenario: 'billing_issue'
});
// 4. Check grace period status
const info = await BillDog.getCustomerInfo();
console.log('Grace period:', info.entitlements.premium.gracePeriod);Testing Restore Purchases
// 1. Create purchases on "device 1"
await BillDogSandbox.createTestPurchase({
productId: 'premium_annual',
scenario: 'successful_purchase',
testUserId: 'user_device1'
});
// 2. Clear local state (simulate app reinstall)
await BillDogSandbox.clearPurchases('user_device1');
// 3. Restore on "device 2"
const { restoredPurchases } = await BillDogSandbox.simulateRestorePurchases('user_device1');
console.log('Restored:', restoredPurchases.length, 'purchases');Platform Support
| Platform | Status | Package |
|----------|--------|---------|
| TypeScript/JavaScript | ✅ Ready | @billdog.io/sandbox-testing |
| React Native | ✅ Ready | @billdog.io/sandbox-testing |
| Expo | ✅ Ready | @billdog.io/sandbox-testing |
| iOS Swift | 🚧 Coming Soon | BillDogSandbox.swift |
| Android Kotlin | 🚧 Coming Soon | BillDogSandbox.kt |
| Flutter | 🚧 Coming Soon | billdog_sandbox |
| Unity C# | 🚧 Coming Soon | BillDogSandbox.cs |
Important Notes
Sandbox API Key Required
The Sandbox SDK only works with sandbox API keys (bd_public_test_). Production keys (bd_live_) will throw an error:
// ❌ This will throw an error
BillDogSandbox.configure({ apiKey: 'bd_live_...' });
// ✅ This works
BillDogSandbox.configure({ apiKey: 'bd_public_test_...' });Separate Test Data
All test purchases are stored in a separate test database. They never affect your production data or analytics.
Not for Production
This module should never be included in production builds. Use tree-shaking or conditional imports:
// ✅ Good: Conditional import
if (__DEV__) {
const { BillDogSandbox } = await import('@billdog.io/sandbox-testing');
BillDogSandbox.configure({ apiKey: 'bd_public_test_...' });
}
// ✅ Good: Separate test file
// tests/sandbox.test.ts
import { BillDogSandbox } from '@billdog.io/sandbox-testing';Troubleshooting
"Sandbox SDK not initialized"
Call BillDogSandbox.configure() before using any methods:
BillDogSandbox.configure({ apiKey: 'bd_public_test_...' });"Production keys not allowed"
Use a sandbox API key (bd_public_test_) instead of production (bd_live_).
Time travel not affecting subscriptions
Make sure to create purchases before advancing time, and wait a moment for backend processing:
await BillDogSandbox.createTestPurchase({...});
await new Promise(r => setTimeout(r, 500)); // Wait 500ms
await BillDogSandbox.advanceDays(30);Contributing
See the main BillDog SDK repository for contribution guidelines.
License
MIT © BillDog
