Waiting for Emails
VaultSandbox provides powerful methods for waiting for emails with filtering and timeout support.
Basic Waiting
Section titled “Basic Waiting”Wait for Any Email
Section titled “Wait for Any Email”const email = await inbox.waitForEmail({ timeout: 30000, // 30 seconds});
console.log('Received:', email.subject);With Default Timeout
Section titled “With Default Timeout”// Uses default 30 second timeoutconst email = await inbox.waitForEmail();Filtering Options
Section titled “Filtering Options”Filter by Subject
Section titled “Filter by Subject”// Exact matchconst email = await inbox.waitForEmail({ timeout: 10000, subject: 'Password Reset',});
// Regex matchconst email = await inbox.waitForEmail({ timeout: 10000, subject: /reset/i, // Case-insensitive});Filter by Sender
Section titled “Filter by Sender”// Exact matchconst email = await inbox.waitForEmail({ timeout: 10000,});
// Regex matchconst email = await inbox.waitForEmail({ timeout: 10000, from: /@example\.com$/, // Any @example.com address});Multiple Filters
Section titled “Multiple Filters”const email = await inbox.waitForEmail({ timeout: 10000, subject: /welcome/i,});Custom Predicate
Section titled “Custom Predicate”const email = await inbox.waitForEmail({ timeout: 10000, predicate: (email) => { // Custom logic return email.to.includes('[email protected]') && email.links.length > 0 && email.subject.includes('Verify'); },});Waiting for Multiple Emails
Section titled “Waiting for Multiple Emails”Wait for Specific Count
Section titled “Wait for Specific Count”// Trigger multiple emailsawait sendNotifications(inbox.emailAddress, 3);
// Wait for all 3 to arriveawait inbox.waitForEmailCount(3, { timeout: 30000, pollInterval: 1000, // Check every second});
// Now list all emailsconst emails = await inbox.listEmails();expect(emails.length).toBe(3);Process as They Arrive
Section titled “Process as They Arrive”async function waitForEmails(inbox, count) { const emails = [];
for (let i = 0; i < count; i++) { const email = await inbox.waitForEmail({ timeout: 30000 }); emails.push(email); console.log(`Received ${i + 1}/${count}: ${email.subject}`); }
return emails;}
// Usageconst emails = await waitForEmails(inbox, 3);Timeout Handling
Section titled “Timeout Handling”With Error Handling
Section titled “With Error Handling”try { const email = await inbox.waitForEmail({ timeout: 5000 }); console.log('Email received:', email.subject);} catch (error) { if (error instanceof TimeoutError) { console.error('No email received within 5 seconds'); } else { throw error; }}With Fallback
Section titled “With Fallback”async function waitForEmailWithFallback(inbox, options) { try { return await inbox.waitForEmail(options); } catch (error) { if (error instanceof TimeoutError) { console.log('Timeout, checking if email arrived anyway'); const emails = await inbox.listEmails(); return emails[emails.length - 1]; // Return latest } throw error; }}Retry Pattern
Section titled “Retry Pattern”async function waitWithRetry(inbox, options, maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { try { return await inbox.waitForEmail(options); } catch (error) { if (error instanceof TimeoutError && i < maxRetries - 1) { console.log(`Attempt ${i + 1} failed, retrying...`); continue; } throw error; } }}Polling Configuration
Section titled “Polling Configuration”Custom Poll Interval
Section titled “Custom Poll Interval”// Poll every 500ms (more responsive)const email = await inbox.waitForEmail({ timeout: 10000, pollInterval: 500,});
// Poll every 5 seconds (less frequent)const email = await inbox.waitForEmail({ timeout: 60000, pollInterval: 5000,});Efficient Polling
Section titled “Efficient Polling”// For quick tests - poll frequentlyconst email = await inbox.waitForEmail({ timeout: 5000, pollInterval: 200, // Check 5 times per second});
// For slow email services - poll less frequentlyconst email = await inbox.waitForEmail({ timeout: 120000, // 2 minutes pollInterval: 10000, // Check every 10 seconds});Real-World Examples
Section titled “Real-World Examples”Password Reset Flow
Section titled “Password Reset Flow”test('password reset email', async () => { // Trigger reset await app.requestPasswordReset(inbox.emailAddress);
// Wait for reset email const email = await inbox.waitForEmail({ timeout: 10000, subject: /reset/i, });
// Validate content expect(email.subject).toContain('Password Reset'); expect(email.links.length).toBeGreaterThan(0);
// Extract and test link const resetLink = email.links.find((url) => url.includes('/reset')); expect(resetLink).toBeDefined();});Welcome Email with Verification
Section titled “Welcome Email with Verification”test('welcome email with verification link', async () => { // Sign up await app.signup({ email: inbox.emailAddress, name: 'Test User', });
// Wait for welcome email const email = await inbox.waitForEmail({ timeout: 10000, subject: /welcome/i, predicate: (e) => e.links.some((link) => link.includes('/verify')), });
// Extract verification link const verifyLink = email.links.find((url) => url.includes('/verify'));
// Test verification const response = await fetch(verifyLink); expect(response.ok).toBe(true);});Multi-Step Email Flow
Section titled “Multi-Step Email Flow”test('order confirmation and shipping notification', async () => { // Place order await app.placeOrder({ email: inbox.emailAddress, items: ['widget'], });
// Wait for confirmation const confirmation = await inbox.waitForEmail({ timeout: 10000, subject: /order.*confirmed/i, });
expect(confirmation.subject).toContain('Order Confirmed'); expect(confirmation.text).toContain('Order #');
// Simulate shipping await app.shipOrder(orderId);
// Wait for shipping notification const shipping = await inbox.waitForEmail({ timeout: 10000, subject: /shipped/i, });
expect(shipping.subject).toContain('Shipped'); expect(shipping.text).toContain('tracking');});Email with Attachments
Section titled “Email with Attachments”test('invoice email with PDF attachment', async () => { await app.sendInvoice(inbox.emailAddress);
const email = await inbox.waitForEmail({ timeout: 10000, subject: /invoice/i, predicate: (e) => e.attachments.length > 0, });
// Validate attachment const pdf = email.attachments.find((att) => att.contentType === 'application/pdf');
expect(pdf).toBeDefined(); expect(pdf.filename).toMatch(/invoice.*\.pdf/i); expect(pdf.size).toBeGreaterThan(0);});Advanced Patterns
Section titled “Advanced Patterns”Wait for First Matching Email
Section titled “Wait for First Matching Email”async function waitForFirstMatch(inbox, matchers, timeout = 30000) { const startTime = Date.now();
while (Date.now() - startTime < timeout) { const emails = await inbox.listEmails();
for (const matcher of matchers) { const match = emails.find(matcher); if (match) return match; }
await new Promise((resolve) => setTimeout(resolve, 1000)); }
throw new TimeoutError('No matching email found');}
// Usageconst email = await waitForFirstMatch(inbox, [ (e) => e.subject.includes('Welcome'), (e) => e.subject.includes('Verify'),]);Wait with Progress Callback
Section titled “Wait with Progress Callback”async function waitWithProgress(inbox, options, onProgress) { const startTime = Date.now(); let attempts = 0;
try { return await inbox.waitForEmail({ ...options, pollInterval: options.pollInterval || 1000, }); } catch (error) { if (error instanceof TimeoutError) { const elapsed = Date.now() - startTime; onProgress({ attempts, elapsed, timedOut: true }); } throw error; }}
// Usageconst email = await waitWithProgress(inbox, { timeout: 10000, subject: /test/i }, (progress) => { console.log(`Attempt ${progress.attempts}, ${progress.elapsed}ms elapsed`);});Conditional Waiting
Section titled “Conditional Waiting”async function waitConditionally(inbox, options) { // First check if email already exists const existing = await inbox.listEmails(); const match = existing.find((e) => options.subject.test(e.subject));
if (match) { console.log('Email already present'); return match; }
// Wait for new email console.log('Waiting for email...'); return await inbox.waitForEmail(options);}Testing Patterns
Section titled “Testing Patterns”Flake-Free Tests
Section titled “Flake-Free Tests”// ✅ Good: Use waitForEmail, not sleeptest('receives email', async () => { await sendEmail(inbox.emailAddress); const email = await inbox.waitForEmail({ timeout: 10000 }); expect(email).toBeDefined();});
// ❌ Bad: Arbitrary sleep causes flakinesstest('receives email', async () => { await sendEmail(inbox.emailAddress); await sleep(5000); // May not be enough, or wastes time const emails = await inbox.listEmails(); expect(emails.length).toBe(1);});Fast Tests
Section titled “Fast Tests”// ✅ Good: Short timeout for fast-sending systemsconst email = await inbox.waitForEmail({ timeout: 2000 });
// ❌ Bad: Unnecessarily long timeout slows testsconst email = await inbox.waitForEmail({ timeout: 60000 });Parallel Email Tests
Section titled “Parallel Email Tests”test('multiple users receive emails', async () => { const inbox1 = await client.createInbox(); const inbox2 = await client.createInbox();
// Send emails await Promise.all([sendWelcome(inbox1.emailAddress), sendWelcome(inbox2.emailAddress)]);
// Wait in parallel const [email1, email2] = await Promise.all([ inbox1.waitForEmail({ timeout: 10000 }), inbox2.waitForEmail({ timeout: 10000 }), ]);
expect(email1.subject).toContain('Welcome'); expect(email2.subject).toContain('Welcome');
await Promise.all([inbox1.delete(), inbox2.delete()]);});Troubleshooting
Section titled “Troubleshooting”Email Not Arriving
Section titled “Email Not Arriving”// Add debug loggingtry { console.log('Waiting for email...'); const email = await inbox.waitForEmail({ timeout: 10000, subject: /test/i, }); console.log('Received:', email.subject);} catch (error) { console.error('Timeout! Checking inbox manually:'); const emails = await inbox.listEmails(); console.log(`Found ${emails.length} emails:`); emails.forEach((e) => console.log(` - ${e.subject}`)); throw error;}Filter Not Matching
Section titled “Filter Not Matching”// Log filter mismatchesconst email = await inbox.waitForEmail({ timeout: 10000, predicate: (e) => { const matches = e.subject.includes('Test'); if (!matches) { console.log(`Subject "${e.subject}" doesn't match`); } return matches; },});Next Steps
Section titled “Next Steps”- Managing Inboxes - Learn inbox operations
- Real-time Monitoring - Subscribe to emails as they arrive
- Testing Patterns - Real-world testing examples
- API Reference: Inbox - Complete API documentation