Skip to content

Test Specification

Language-agnostic specification for testing VaultSandbox SDK implementations.


This document defines the minimum required tests for any VaultSandbox SDK implementation. Tests are categorized by their dependencies and purpose.

CategoryServer RequiredSMTP RequiredPurpose
UnitNoNoTest isolated functions and classes
IntegrationYesNoTest API interactions
E2EYesYesTest complete email workflows
  • [REQUIRED] - Must be implemented
  • [RECOMMENDED] - Should be implemented if feasible
  • [OPTIONAL] - Nice to have

Tests that require no external dependencies. Use mocks where necessary.

TestDescriptionExpected
Round-tripEncode then decode arbitrary bytesOriginal bytes recovered
No paddingEncode data that would require paddingNo = characters in output
URL-safe charsEncode data that produces + and / in standard base64Uses - and _ instead
TestDescriptionExpected
Generate keypairCall keypair generationReturns public key (1184 bytes), secret key (2400 bytes), and base64 public key
Unique keypairsGenerate two keypairsDifferent public keys
Correct sizesCheck ML-KEM-768 key sizesPublic: 1184 bytes, Secret: 2400 bytes
TestDescriptionExpected
Valid keypairValidate a correctly generated keypairReturns true
Invalid sizesValidate keypair with wrong key sizesReturns false
Mismatched base64Validate keypair where base64 doesn’t match public keyReturns false
Missing fieldsValidate incomplete keypair objectReturns false
TestDescriptionExpected
All passSPF=pass, DKIM=pass, DMARC=passpassed=true, no failures
SPF failSPF=fail, others passpassed=false, spfPassed=false, failure message
DKIM failDKIM=fail, others passpassed=false, dkimPassed=false, failure message
DMARC failDMARC=fail, others passpassed=false, dmarcPassed=false, failure message
DKIM partial passMultiple DKIM results, at least one passesdkimPassed=true
None statusAll statuses are “none”passed=false (requires explicit “pass”)
Empty resultsNo auth data presentpassed=false, all checks false
Reverse DNS failReverse DNS fails, others passpassed=true (reverse DNS doesn’t affect overall)
TestDescriptionExpected
Default valuesCreate client with only API keyUses default URL, timeout, retries, strategy
Verify defaultsCheck specific default valuesTimeout=30000ms, retries=3, strategy=auto
TestDescriptionExpected
Custom URLProvide custom base URLClient uses provided URL
Custom timeoutProvide custom timeoutClient uses provided timeout
Custom retriesProvide custom retry settingsClient uses provided settings
Custom strategySpecify polling/SSE/autoClient uses specified strategy
Polling configCustom polling interval and backoffStrategy uses provided config
SSE configCustom reconnect interval and max attemptsStrategy uses provided config

Tests that require a running VaultSandbox server but no SMTP.

Skip condition: Skip all integration tests if API key is not configured or equals a placeholder value.

TestDescriptionExpected
Valid keyCall checkKey with valid API keyReturns true
Invalid keyCall checkKey with invalid API keyReturns false or throws ApiError(401)
TestDescriptionExpected
Get server infoFetch server capabilitiesReturns server_sig_pk, algorithms, max_ttl, default_ttl, allowed_domains
Algorithm valuesCheck returned algorithmskem=ML-KEM-768, sig=ML-DSA-65, aead=AES-256-GCM, kdf=HKDF-SHA-512
TestDescriptionExpected
Graceful closeClose client after operationsNo errors thrown
Resource cleanupClose with active subscriptionsSubscriptions cleaned up
TestDescriptionExpected
Basic creationCreate inbox with defaultsReturns email_address, inbox_hash, expires_at
Email formatCheck created email addressContains @ symbol
With custom TTLCreate inbox with TTL parameterInbox created with specified TTL
TestDescriptionExpected
Delete existingDelete a created inboxNo error
Access after deleteTry to access deleted inboxThrows InboxNotFoundError or similar
TestDescriptionExpected
Delete allCreate multiple inboxes, delete allReturns count >= created count
TestDescriptionExpected
Empty inboxGet sync status of new inboxemailCount=0, emailsHash defined
Consistent hashMultiple calls without changesSame emailsHash returned
TestDescriptionExpected
Empty inboxList emails in new inboxReturns empty array
TestDescriptionExpected
Invalid IDGet email with fake IDThrows EmailNotFoundError
TestDescriptionExpected
Invalid hostConnect to non-existent serverThrows NetworkError
TestDescriptionExpected
Operations before initCall methods before initializationThrows RuntimeError or similar

Tests that require both a VaultSandbox server and SMTP access.

Skip condition: Skip if SMTP host is not configured.

TestDescriptionExpected
Simple text emailSend text email via SMTP, wait for itEmail received with correct subject, body, from
Timeout on receiveWait for email without sendingThrows TimeoutError after specified timeout
TestDescriptionExpected
HTML contentSend email with HTML bodyEmail has both text and html fields populated
TestDescriptionExpected
Single attachmentSend email with one attachmentAttachment accessible with filename, content_type, size, content
Multiple attachmentsSend email with multiple attachmentsAll attachments accessible
TestDescriptionExpected
String matchWait for email with subject containing stringCorrect email returned
Regex matchWait for email with subject matching patternCorrect email returned
No match timeoutWait for subject that doesn’t existThrows TimeoutError
TestDescriptionExpected
String matchWait for email from specific addressCorrect email returned
Regex matchWait for email from address matching patternCorrect email returned
TestDescriptionExpected
Predicate functionWait with custom filter functionReturns email matching predicate
TestDescriptionExpected
Multiple emailsSend N emails, list allReturns all N emails decrypted
TestDescriptionExpected
By IDGet email by its IDReturns same email as wait_for_email
TestDescriptionExpected
Via inbox methodMark email as read via inboxis_read changes to true
Via email methodMark email as read via email objectis_read changes to true
TestDescriptionExpected
Via inbox methodDelete email via inboxEmail no longer in list
Via email methodDelete email via email objectEmail no longer in list
TestDescriptionExpected
Get raw contentFetch raw MIME sourceReturns raw string containing headers and subject
TestDescriptionExpected
Links in HTMLSend email with links in HTMLlinks array contains URLs
TestDescriptionExpected
Standard headersAccess email headersfrom, subject, date headers accessible
TestDescriptionExpected
Results presentReceive email, check authResultsauthResults object exists
Validate methodCall authResults.validate()Returns validation object with passed, failures
Direct send fails SPFSend directly without authorizationSPF status is NOT “pass”
Direct send fails DKIMSend without signingDKIM status is NOT “pass”
TestDescriptionExpected
Wait for NSend N emails, wait for count NReturns when count reached
Timeout on countWait for more emails than sentThrows TimeoutError

TestDescriptionExpected
Default configCreate strategy without configUses default interval, backoff, jitter
Custom configCreate strategy with custom configUses provided values
TestDescriptionExpected
Timeout with backoffWait without emailTimes out near specified timeout
Custom intervalSpecify poll intervalRespects provided interval
Concurrent pollingPoll multiple inboxes concurrentlyAll eventually timeout
TestDescriptionExpected
SubscribeSubscribe to inboxReturns subscription object
UnsubscribeUnsubscribe from inboxStops polling for that inbox
CloseClose strategyAll polling tasks cancelled
TestDescriptionExpected
Default configCreate strategy without configUses default reconnect settings
Custom configCreate strategy with custom configUses provided values
TestDescriptionExpected
SubscribeSubscribe to inboxReturns subscription object
UnsubscribeUnsubscribe from inboxRemoves subscription
Multiple unsubscribeCall unsubscribe multiple timesNo error (idempotent)
CloseClose strategyAll subscriptions cleaned up
TestDescriptionExpected
Connection errorConnect to invalid URLHandles error gracefully
No connect when closingSubscribe after closeDoes not attempt connection
TestDescriptionExpected
Receive via callbackSubscribe, send emailCallback invoked with email
Unsubscribe stops callbackUnsubscribe, send emailCallback not invoked
TestDescriptionExpected
Multiple inboxesMonitor 2+ inboxesEvents received for all
Unsubscribe allUnsubscribe from monitorAll subscriptions stopped

TestDescriptionExpected
Export to objectExport inboxReturns all required fields
Required fieldsCheck exported dataHas email_address, inbox_hash, expires_at, server_sig_pk, public_key_b64, secret_key_b64, exported_at
Valid timestampsCheck timestamp fieldsValid ISO 8601 format
Valid base64 keysCheck key fieldsValid base64 encoding
Export by addressExport using email address stringWorks same as inbox object
Not found errorExport non-existent inboxThrows InboxNotFoundError
TestDescriptionExpected
Import valid dataImport previously exported inboxReturns functional inbox
Access emailsList emails from imported inboxReturns emails that were sent before export
Missing fieldsImport with missing required fieldsThrows InvalidImportDataError
Empty fieldsImport with empty required fieldsThrows InvalidImportDataError
Invalid timestampImport with invalid timestampThrows InvalidImportDataError
Invalid base64Import with invalid base64 keysThrows InvalidImportDataError
Wrong key lengthImport with incorrect key sizesThrows InvalidImportDataError
Server mismatchImport with different server_sig_pkThrows InvalidImportDataError
Already existsImport inbox that’s already loadedThrows InboxAlreadyExistsError
TestDescriptionExpected
Export to fileExport inbox to JSON fileFile created with valid JSON
Import from fileImport inbox from JSON fileReturns functional inbox
Invalid JSON fileImport from file with invalid JSONThrows InvalidImportDataError
Non-existent fileImport from missing fileThrows error
Formatted JSONCheck exported file formatJSON is indented/formatted

TestDescriptionExpected
Timeout value 0Wait with timeout=0Returns immediately with timeout error
Deleted inbox during waitDelete inbox while waitingThrows appropriate error
Empty inbox arrayMonitor empty arrayNo crash, returns valid monitor
TestDescriptionExpected
Retry on 5xxServer returns 500, then 200Eventually succeeds
Max retries exceededServer always returns 500Throws error after max retries
No retry on 4xxServer returns 400Fails immediately (no retry)
TestDescriptionExpected
404 inboxAccess non-existent inboxThrows InboxNotFoundError
404 emailAccess non-existent emailThrows EmailNotFoundError

Ensure all code examples in README documentation work correctly.

TestDescriptionExpected
Basic flowCreate inbox, send email, receive, verifyAll steps succeed
TestDescriptionExpected
All client optionsUse all documented optionsClient initializes correctly
Environment variablesLoad config from env varsWorks as documented
TestDescriptionExpected
Filter examplesAll documented filter patternsWork as documented
Attachment exampleDocumented attachment accessWorks as documented
Auth results exampleDocumented auth checkingWorks as documented
Monitor exampleDocumented monitoring patternWorks as documented
Export/import exampleDocumented import/exportWorks as documented
Error handling exampleDocumented error catchingCatches expected errors

Each implementation should provide:

UtilityPurpose
SMTP clientSend test emails to inboxes
Cleanup hooksDelete created inboxes after tests
Skip conditionsSkip integration tests when server unavailable
Timeout helpersReasonable timeouts for async operations

Tests should respect these environment variables:

VariablePurposeDefault
VAULTSANDBOX_URLServer URLImplementation default
VAULTSANDBOX_API_KEYAPI key for testingNone (skip if missing)
SMTP_HOSTSMTP server hostnamelocalhost
SMTP_PORTSMTP server port25

When VSB_DEVELOPMENT=true is set on the gateway, a test endpoint becomes available that allows creating emails with controlled authentication results. This eliminates the need for a real SMTP server when testing email authentication flows in SDK implementations.

PropertyValue
EndpointPOST /api/test/emails
AuthenticationAPI Key (X-API-Key header)
AvailabilityOnly when VSB_DEVELOPMENT=true
{
"to": "[email protected]", // Required: inbox email address
"from": "[email protected]", // Optional, default: "[email protected]"
"subject": "Test Subject", // Optional, default: "Test Email"
"text": "Plain text body", // Optional, default: "Test email body"
"html": "<p>HTML body</p>", // Optional
"auth": {
"spf": "pass", // "pass" | "fail" | "softfail" | "neutral" | "none" | "temperror" | "permerror"
"dkim": "pass", // "pass" | "fail" | "none"
"dmarc": "pass", // "pass" | "fail" | "none"
"reverseDns": true // boolean
}
}
{
"emailId": "uuid-of-created-email"
}

This endpoint is useful for:

  • Testing authentication validation logic without configuring SPF/DKIM/DMARC
  • Simulating authentication failures to verify SDK error handling
  • Running E2E tests in CI/CD without SMTP infrastructure
  • Rapid local development of email-dependent features
# Pseudocode
# Create an email with failing SPF
response = http_post(
url=f"{base_url}/api/test/emails",
headers={
"Content-Type": "application/json",
"X-API-Key": api_key,
},
body={
"to": inbox.email_address,
"subject": "Auth Test",
"auth": {
"spf": "fail",
"dkim": "pass",
"dmarc": "fail",
},
},
)
# Now fetch the email and verify authResults
email = inbox.waitForEmail(timeout=5000)
validation = email.authResults.validate()
assert validation.passed == False
assert validation.spfPassed == False
assert validation.dmarcPassed == False

Minimum required tests by category:

CategoryRequired Tests
Unit - Crypto9
Unit - Types8
Unit - Config6
Integration - Client6
Integration - Inbox7
Integration - Errors2
E2E - Basic Flow4
E2E - Filtering6
E2E - Operations8
E2E - Content6
E2E - Multiple2
Strategy - Polling6
Strategy - SSE6
Strategy - Monitoring4
Import/Export15
Edge Cases5
README Examples8
Total~108

VersionDateChanges
1.02025-12-17Initial specification based on Node.js and Python implementations