Forms E2E Testing Protocol
Forms E2E Testing Protocol
Purpose
This protocol defines the mandatory end-to-end validation steps for all contact forms, waitlist submissions, and user-facing form handlers. HTTP 200 response is NOT sufficient evidence of success — inbox delivery or database persistence MUST be verified.
Scope
Applies to:
- Contact forms (alai.no, snowit.ba, merdzanovic.ba, etc.)
- Waitlist/signup forms (getdrop.no, product landing pages)
- Feedback forms
- Any form that sends email or stores user data
Test Levels
Level 1 — HTTP Layer (Necessary but NOT Sufficient)
- Submit form via browser (real user flow)
- Verify HTTP response: 200 OK or 201 Created
- Verify UI feedback: success message displayed
- ⚠️ STOP: This is NOT proof the form works. Proceed to Level 2.
Level 2 — Delivery Verification (MANDATORY)
For Email-Based Forms
- Submit test form with known test data (e.g.,
[email protected], subject: "E2E Test YYYY-MM-DD HH:MM") - Check target inbox within 60 seconds:
- Via Himalaya CLI:
himalaya search --account [email protected] --folder INBOX "subject:E2E Test" - Via webmail: Log into one.com or Gmail, verify message received
- Via IMAP client: Thunderbird, Apple Mail, etc.
- Via Himalaya CLI:
- Verify message contents:
- All form fields present in email body
- From address is correct (e.g.,
[email protected]or form submitter) - Reply-to is user's submitted email (if applicable)
- Verify SMTP logs (if accessible):
- Check Resend dashboard (for Resend API)
- Check Cloudflare Email Workers logs
- Check backend logs (
journalctl -u form-handleror PM2 logs)
For Database-Based Forms (e.g., waitlist with D1)
- Submit test form with unique identifier (e.g., email
[email protected]) - Query database:
- CF D1:
wrangler d1 execute drop-waitlist --command "SELECT * FROM submissions WHERE email LIKE 'test+%'" - PostgreSQL:
psql -h localhost -U user -d dbname -c "SELECT * FROM waitlist WHERE email = '[email protected]';" - SQLite:
sqlite3 ~/path/to/db.sqlite "SELECT * FROM forms WHERE email = '[email protected]';"
- CF D1:
- Verify record fields:
- Timestamp is recent (within last 2 minutes)
- All form fields stored correctly
- No NULL values where data expected
Level 3 — Error Handling (Recommended for Production Forms)
- Submit invalid data:
- Missing required fields
- Invalid email format
- XSS/SQL injection attempts (if validation implemented)
- Verify error responses:
- HTTP 400 Bad Request (not 500 Internal Server Error)
- Clear error message to user ("Email is required")
- No server crash or 500 error
- Simulate backend failure:
- Temporarily break SMTP credentials or DB connection
- Verify graceful failure (user sees "Failed to send, please try again" — not silent success)
- Verify logging of failure (so ops team can detect issue)
Himalaya CLI Setup (for Email Verification)
Install
brew install himalaya
Configure Account
Add to ~/.config/himalaya/config.toml:
[accounts.info-alai]
default = false
email = "[email protected]"
display-name = "ALAI Info"
[accounts.info-alai.imap]
host = "imap.one.com"
port = 993
encryption = "tls"
login = "[email protected]"
passwd.cmd = "bw get password 'Email - [email protected]' --session $(cat /tmp/bw-session)"
[accounts.info-alai.smtp]
host = "send.one.com"
port = 587
encryption = "start-tls"
login = "[email protected]"
passwd.cmd = "bw get password 'Email - [email protected]' --session $(cat /tmp/bw-session)"
Usage
# List recent messages
himalaya list --account info-alai --folder INBOX --page-size 20
# Search for test submissions
himalaya search --account info-alai --folder INBOX "subject:E2E Test"
# Search by sender
himalaya search --account info-alai --folder INBOX "from:[email protected]"
# Search by date
himalaya search --account info-alai --folder INBOX "since:2026-04-21"
Credentials: Store IMAP password in Bitwarden item "Email - [email protected]"
Pre-Deployment Checklist
Before marking any form handler as "ready for production":
- [ ] Level 1 HTTP test passed (200 OK + UI feedback)
- [ ] Level 2 delivery test passed (inbox check OR database record confirmed)
- [ ] Level 3 error handling tested (invalid input returns 400, backend failure does NOT return silent success)
- [ ] Form submission logged to application logs (even if email/DB write fails)
- [ ] Monitoring/alerting configured (e.g., Grafana alert if zero submissions for 7 days)
- [ ] Documentation updated (which inbox receives submissions, which DB table stores records)
Migration Checklist (Static Hosting Migrations)
When migrating sites from Vercel/Netlify to Cloudflare Pages:
- [ ] Inventory all POST endpoints (forms, webhooks, API routes)
- [ ] Verify each has CF Pages Function equivalent (
/functions/*.js) - [ ] Update form action URLs if needed (e.g.,
/api/contact→ CF Pages route) - [ ] Run full E2E test (this protocol) BEFORE declaring migration complete
- [ ] Monitor inbox/DB for 24 hours post-migration to catch silent failures
Known Silent Failure Patterns
Pattern 1: Catch-All Webhook Returns False Success
- Symptom: HTTP 200 +
{ok: true}but no email sent - Cause: Reverse proxy or tunnel routes form POST to wrong backend (e.g., Documenso webhook with
app.post('/*', ...)) - Example: alai.no contact form incident (2026-04-21, MC #8587)
- Prevention: Audit all catch-all routes; prefer explicit path matching
Pattern 2: Serverless Function Not Migrated
- Symptom: 404 Not Found or 200 OK (if static fallback serves index.html)
- Cause: Vercel API routes (
/api/contact.js) not ported to CF Pages Functions (/functions/contact.js) - Prevention: Explicit checklist during migration (see above)
Pattern 3: SMTP Credentials Not Migrated
- Symptom: Backend logs show "SMTP authentication failed" but frontend receives 200 OK
- Cause: Environment variables not set in new hosting platform
- Prevention: Verify env vars (RESEND_API_KEY, SMTP_PASSWORD) before testing
Related Pages
- Email Pipeline Runbook
- Incident — 2026-04-21 alai.no Contact Form Failure
- Static Hosting Migration — Progress Log
- Definition of Done
MC Task References
- #8587 — alai.no contact form fix + documentation (this page)
- #8538 — Master quality gate (references forms E2E testing requirement)
- #8591 — snowit.ba contact form migration (same risk)