End-to-end integration tests for the httpSMS API. These tests validate the complete SMS lifecycle by running the full application stack in Docker alongside a phone emulator service.
┌──────────────┐ HTTP ┌──────────────┐
│ Test Runner │─────────────▶│ API (Go) │
│ (Go test) │ │ Port 8000 │
└──────────────┘ └──────┬───────┘
│
FCM Push │ Events
(HTTP) │ (HTTP)
▼
┌──────────────┐
│ Emulator │
│ (Fiber v3) │
│ Port 9090 │
└──────────────┘
│
┌──────┴───────┐
│ CockroachDB │ │ Redis │
│ Port 26257 │ │ Port 6379 │
└──────────────┘ └─────────────┘
| Component | Description |
|---|---|
| API | The httpSMS Go API server running in Docker |
| Emulator | A Fiber v3 Go service that simulates an Android phone |
| CockroachDB | Database for the API (single-node, insecure mode) |
| Redis | Cache and queue backend |
| Seed | One-shot container that seeds test data into CockroachDB |
| Test Runner | Go test binary that runs on the host machine |
-
Send SMS flow: Test sends
POST /v1/messages/send→ API queues the message for the phone → Emulator long-pollsGET /v1/messages/outstanding→ Emulator firesSENTandDELIVEREDevents → Test pollsGET /v1/messages/{id}until status isdelivered -
Receive SMS flow: Test sends
POST /v1/messages/receive(as the phone) → API stores message → Test verifies viaGET /v1/messages/{id}
- Send SMS E2E — Full send lifecycle: API queues the message → emulator long-polls and responds with SENT/DELIVERED events → message reaches
deliveredstatus - Receive SMS E2E — Phone submits received message to API → message is stored and retrievable via GET endpoint
docker compose up -d --build --waitThis starts CockroachDB, Redis, the API, and the emulator. The --wait flag blocks until all health checks pass.
docker compose wait seed
sleep 2The seed container inserts test users, phones, and API keys into CockroachDB after the API has run its GORM migrations.
go test -v -timeout 120s ./...docker compose down -vThe -v flag removes volumes (database data) for a clean slate next run.
cd tests && \
docker compose up -d --build --wait && \
docker compose wait seed && \
sleep 2 && \
go test -v -timeout 120s ./... ; \
docker compose down -vIntegration tests run automatically via GitHub Actions (.github/workflows/integration-test.yml):
- Trigger: Push to
mainor pull request targetingmain - Flow: Starts Docker stack → Seeds DB → Runs tests → Collects logs on failure → Tears down
- Gate: Deployment should only proceed if integration tests pass
| Entity | Value |
|---|---|
| User API Key | test-user-api-key |
| Phone API Key | pk_test-phone-api-key |
| Phone Number | +18005550199 |
| Contact Number | +18005550100 |
| User ID | test-user-id |
| Phone ID | a1b2c3d4-e5f6-7890-abcd-ef1234567890 |
See seed.sql for the complete seed data.
tests/
├── docker-compose.yml # Full stack orchestration
├── seed.sql # Database seed data
├── .env.test # API environment variables
├── go.mod # Test runner Go module
├── go.sum
├── helpers_test.go # Test utilities (HTTP client, polling)
├── integration_test.go # E2E test cases
└── emulator/ # Phone emulator service
├── Dockerfile
├── go.mod
├── go.sum
├── main.go # Fiber v3 entry point
├── emulator.go # Emulator struct and config
├── token_handler.go # Fake OAuth2 token endpoint
├── fcm_handler.go # Fake FCM push receiver
└── events.go # Event firing logic (SENT/DELIVERED)
Check the API logs:
docker compose logs apiCommon issues:
- CockroachDB not ready (increase
start_periodin healthcheck)
Check the emulator logs:
docker compose logs emulatorThe emulator should show [EVENTS] entries while it long-polls GET /v1/messages/outstanding. If none appear, the emulator isn't reaching the API (check the API URL in .env.test).
docker compose logs seedIf you see "relation does not exist" errors, the API hasn't finished GORM migrations yet. Increase the API's start_period in docker-compose.yml.
- Add test functions to
integration_test.go(or create new*_test.gofiles) - Use
doRequest()helper for authenticated HTTP calls - Use
pollMessageStatus()to wait for async state changes - Update the test coverage checklist in this README