mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
feat: integration tests
This commit is contained in:
165
docker-compose.it.yaml
Normal file
165
docker-compose.it.yaml
Normal file
@@ -0,0 +1,165 @@
|
||||
# EDR Freight — API integration stack (headless).
|
||||
#
|
||||
# Overlay on docker-compose.e2e.yaml. Same base services (postgres, minio,
|
||||
# mocks, freight-api), except the payment microservice is REAL here instead of
|
||||
# `payment-mock-e2e`, and only the bank gateways are stubbed:
|
||||
#
|
||||
# freight-api-it ──HTTP──> payment-api-it ──HTTP──> gateway-mock-it
|
||||
# ^ │
|
||||
# └────── RabbitMQ ───────┘ (outbox → payment.events → consumer)
|
||||
#
|
||||
# Its own compose project (`name:` below overrides the base) and its own host
|
||||
# ports, so it can run side by side with the Cypress e2e stack.
|
||||
#
|
||||
# node integration/scripts/it.mjs up|test|down|logs
|
||||
#
|
||||
# Never start it with plain `docker compose -f docker-compose.it.yaml` — it is
|
||||
# an OVERLAY and needs the base file first:
|
||||
# docker compose -f docker-compose.e2e.yaml -f docker-compose.it.yaml ...
|
||||
name: edr-freight-it
|
||||
|
||||
services:
|
||||
# Outbox transport. The payment API publishes payment.succeeded/failed here
|
||||
# and freight consumes it — the production path. Copied from the passenger
|
||||
# harness (e2e/docker-compose.yml).
|
||||
rabbitmq-it:
|
||||
image: rabbitmq:3-management
|
||||
environment:
|
||||
RABBITMQ_DEFAULT_USER: edr
|
||||
RABBITMQ_DEFAULT_PASS: edr_secret
|
||||
RABBITMQ_DEFAULT_VHOST: payment
|
||||
ports:
|
||||
- "${IT_RABBIT_PORT:-5772}:5672"
|
||||
- "${IT_RABBIT_UI_PORT:-15772}:15672"
|
||||
healthcheck:
|
||||
test: ["CMD", "rabbitmq-diagnostics", "-q", "ping"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 20
|
||||
|
||||
# Stand-in for every bank/wallet gateway the payment API talks to, plus a
|
||||
# control plane the tests drive (force a provider to fail/hang, fire a
|
||||
# correctly-signed webhook, read back what was called). See
|
||||
# integration/gateway-mock/server.js.
|
||||
gateway-mock-it:
|
||||
image: node:20-alpine
|
||||
volumes:
|
||||
- ./integration/gateway-mock:/app:ro
|
||||
working_dir: /app
|
||||
environment:
|
||||
PORT: "4600"
|
||||
# Same secrets the payment API gets — so webhooks the mock signs pass the
|
||||
# API's REAL signature verification instead of bypassing it.
|
||||
CBE_SECRET_KEY: it-cbe-secret
|
||||
CBE_MERCHANT_ID: it-cbe-merchant
|
||||
PAYMENT_API_URL: http://payment-api-it:3003
|
||||
command: ["node", "server.js"]
|
||||
ports:
|
||||
- "${IT_GATEWAY_PORT:-4600}:4600"
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD",
|
||||
"node",
|
||||
"-e",
|
||||
"fetch('http://localhost:4600/__control/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))",
|
||||
]
|
||||
interval: 3s
|
||||
timeout: 3s
|
||||
retries: 10
|
||||
|
||||
payment-api-it:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: apps/edr-payment-api/Dockerfile
|
||||
secrets:
|
||||
- npmrc
|
||||
depends_on:
|
||||
postgres-freight-e2e:
|
||||
condition: service_healthy
|
||||
rabbitmq-it:
|
||||
condition: service_healthy
|
||||
gateway-mock-it:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
PORT: "3003"
|
||||
NODE_ENV: test
|
||||
# Payment tables live in their own schema of the same throwaway DB;
|
||||
# main.ts ensurePaymentSchema() creates it, migrationsRun does the rest.
|
||||
DB_HOST: postgres-freight-e2e
|
||||
DB_PORT: "5432"
|
||||
DB_USER: edr_e2e
|
||||
DB_PASSWORD: edr_e2e
|
||||
DB_NAME: edr_freight_e2e
|
||||
DB_SCHEMA: edr_payment
|
||||
# Same token freight already uses in the base stack.
|
||||
SERVICE_AUTH_TOKEN: e2e-service-token
|
||||
PUBLISHER_TRANSPORT: rabbitmq
|
||||
PAYMENT_RABBITMQ_URL: amqp://edr:edr_secret@rabbitmq-it:5672/payment
|
||||
# HTTP fallback targets (only used with PUBLISHER_TRANSPORT=http).
|
||||
PAYMENT_NOTIFY_FREIGHT_URL: http://freight-api-e2e:3001/api/internal/payments/mark-paid
|
||||
# Fast relay + sweep so retry/reconciliation are observable inside a test
|
||||
# rather than a minute later.
|
||||
OUTBOX_RELAY_INTERVAL_MS: "1000"
|
||||
RECONCILE_STALE_AFTER_MS: "5000"
|
||||
# Every gateway points at the one mock. Paths are per-provider prefixes.
|
||||
CBE_BASE_URL: http://gateway-mock-it:4600/cbe-birr
|
||||
CBE_MERCHANT_ID: it-cbe-merchant
|
||||
CBE_SECRET_KEY: it-cbe-secret
|
||||
CBE_NOTIFY_URL: http://payment-api-it:3003/webhooks/cbe-birr
|
||||
CBE_RETURN_URL: http://localhost/return
|
||||
TELEBIRR_BASE_URL: http://gateway-mock-it:4600/telebirr
|
||||
TELEBIRR_WEB_BASE_URL: http://gateway-mock-it:4600/telebirr/web
|
||||
TELEBIRR_FABRIC_APP_ID: it-fabric
|
||||
TELEBIRR_APP_SECRET: it-secret
|
||||
TELEBIRR_MERCHANT_APP_ID: it-merchant-app
|
||||
TELEBIRR_MERCHANT_CODE: "999999"
|
||||
TELEBIRR_NOTIFY_URL: http://payment-api-it:3003/webhooks/telebirr
|
||||
# Telebirr PSS-signs every request object — a throwaway key generated per
|
||||
# launch by it.mjs (nothing key-shaped lives in git).
|
||||
TELEBIRR_PRIVATE_KEY: ${IT_TELEBIRR_PRIVATE_KEY}
|
||||
EBIRR_BASE_URL: http://gateway-mock-it:4600/ebirr
|
||||
DMONEY_BASE_URL: http://gateway-mock-it:4600/dmoney
|
||||
CARD_BASE_URL: http://gateway-mock-it:4600/card
|
||||
WAAFI_BASE_URL: http://gateway-mock-it:4600/waafi
|
||||
CAC_BASE_URL: http://gateway-mock-it:4600/cac
|
||||
CAC_USERNAME: it-cac
|
||||
CAC_PASSWORD: it-cac
|
||||
CAC_APP_KEY: it-cac-key
|
||||
CAC_API_KEY: it-cac-api
|
||||
CAC_COMPANY_SERVICES_ID: "1"
|
||||
# Inbound CBE Unified Bill — we are the biller; bill-query hops back into
|
||||
# the freight API, so this direction runs real code on both sides.
|
||||
CBE_BILL_ENABLED: "true"
|
||||
CBE_BILL_CLIENT_ID: it-cbe-bill
|
||||
CBE_BILL_CLIENT_SECRET: it-cbe-bill-secret
|
||||
CBE_BILL_JWT_SECRET: it-cbe-bill-jwt
|
||||
FREIGHT_API_BASE_URL: http://freight-api-e2e:3001/api
|
||||
ports:
|
||||
- "${IT_PAYMENT_PORT:-3113}:3003"
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD",
|
||||
"node",
|
||||
"-e",
|
||||
"fetch('http://localhost:3003/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))",
|
||||
]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 12
|
||||
start_period: 40s
|
||||
|
||||
# Base-stack service, re-pointed at the real payment API.
|
||||
freight-api-e2e:
|
||||
depends_on:
|
||||
payment-api-it:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
PAYMENT_API_URL: http://payment-api-it:3003
|
||||
# Freight's payment module skips RabbitMQModule entirely when this is
|
||||
# unset (payment.module.ts) — without it, outbox events never arrive.
|
||||
PAYMENT_RABBITMQ_URL: amqp://edr:edr_secret@rabbitmq-it:5672/payment
|
||||
# RABBITMQ_ENABLED stays "false" (base stack) — it only gates the SMS/email
|
||||
# clients, which must remain off. The payment consumer is wired by
|
||||
# PAYMENT_RABBITMQ_URL alone.
|
||||
Reference in New Issue
Block a user