Aller au contenu

Story NOTIF-S0: Dev environment + test infrastructure for NOTIF (v0.0.0)

Module: notifications Slice: NOTIF-S0 (Tier 0, serial) Side: [BACKEND] Version target: V0.0.0 Sub-version: v0.0.0 (architecture-backed) Priority: 1 Depends on: TENANT S0 merged; AUDIT S0 merged Can develop concurrently with: None (Tier 0 is serial) Merge order: Before NOTIF-001a/b/c/d Estimated complexity: S PRD User Stories: N/A — Technical Story Wireframe: N/A — backend only


Objective

Establish the dev + test infrastructure required to develop any NOTIF v0.0.0 slice: WireMock service for SMS/WhatsApp provider stubs, Testcontainers wiring (reusing Postgres from TENANT S0), and a NotifFixtures helper that loads a CI tenant + a seeded country_profile.CI row + signed-link fixtures into the platform DB. This unblocks NOTIF-001a/b/c/d to develop in parallel.


Backend Scope

Entities

None new (this story creates no production tables — those land in NOTIF-001a).

Migrations

None.

Service Layer

  • NotifTestContainersConfig — Spring @TestConfiguration: declares the Postgres testcontainer (reused from TENANT S0), starts a per-suite WireMock WireMockExtension for SMS + WA stubs, injects a fixed Clock bean.
  • NotifFixtures — test-only helper bean. Methods:
  • Tenant tenant(String countryCode) — inserts a tenant + a country_profile row for the country (seeds CI by default).
  • DispatchRequest dispatchRequest(Tenant t) — builds a valid POST /dispatch payload pointing at the test tenant.
  • Jwt operatorJwt(Tenant t) — mints a Keycloak-shaped JWT with tenant_id + operator role for tests.

API Endpoints

None.

Validation Rules

None (no production code path introduced).

Multi-Tenant Considerations

NotifFixtures.tenant(...) MUST produce a fresh tenant_id per call; tests rely on this to assert tenant-isolation. The CI seed row in country_profile columns notif_provider_sms='letstalk_sms_ci', notif_provider_wa='meta_wa_cloud_ci', sms_sender_id_default='PAPILLON' (per architecture §9.1 step 4 — TENANT-owned migration; this story only references it).

Audit & Logging

None.


Frontend Scope

N/A — backend only.


Acceptance Criteria

AC-S0.1: WireMock services boot via docker-compose
Given the repository at this story's HEAD
When the developer runs `docker-compose up -d wiremock` from the project root
Then the WireMock container starts on host port 8089
And it serves the SMS stub library at /sms-letstalk/* (200 OK for POST /v2/messages with a JSON body)
And it serves the WA stub library at /wa-meta/* (200 OK for POST /v17.0/{phone_number_id}/messages)

AC-S0.2: Testcontainers + NotifFixtures sample test passes
Given a Spring Boot test class importing NotifTestContainersConfig
When it calls `notifFixtures.tenant("CI")` then inserts and queries a row in a NOTIF-owned table scoped by tenant_id
Then the test passes against the Postgres testcontainer
And Flyway migrations from db/migration/platform/ replay cleanly per suite

AC-S0.3: CI country_profile seed row is present in test DB
Given the testcontainer is freshly migrated
When the test queries `SELECT notif_provider_sms, notif_provider_wa, sms_sender_id_default FROM country_profile WHERE country_code='CI'`
Then it returns exactly one row with values ('letstalk_sms_ci', 'meta_wa_cloud_ci', 'PAPILLON')

Compliance Rules

None (no production data path).


Standards & Conventions

  • docs/standards/critical-rules.md (full)
  • docs/standards/tech-stack.md — Postgres / Flyway / Spring versions
  • docs/standards/java-spring-guidelines.md@TestConfiguration, JdbcClient usage
  • docs/standards/multi-datasource-patterns.mdplatformDataSource is the target for all NOTIF tables (TV-05)
  • docs/standards/git-workflow.md

Testing Requirements

Unit Tests

None — this story IS the test infrastructure.

Integration Tests

  • NotifSmokeTestContainersTest — boots the testcontainer, applies migrations, runs AC-S0.2 and AC-S0.3 assertions.
  • Verify WireMock stub library responds to POST /sms-letstalk/v2/messages with a 200 + JSON {"provider_message_id":"..."}.

What QA Will Validate

  • docker-compose up -d wiremock succeeds on a clean checkout.
  • ./gradlew :backend:test passes the smoke test suite.
  • No flaky cross-test pollution: each test gets a fresh tenant + a fresh notification row.

Out of Scope

  • Production dispatch code path — lands in NOTIF-001a/b/c/d.
  • Redis (cache / rate-limit) — Redis is inherited from TENANT S0; NOTIF does not add Redis primitives in v0.0.0.
  • Production WireMock — WireMock is dev/test only; production points at real provider URLs (configured via env vars per architecture §14.1).
  • The country_profile migration itself — TENANT-owned (architecture §9.1 step 4). This story references the seeded row but does not own the schema change.

Definition of Done

  • [ ] docker-compose.yml includes the wiremock service per architecture §14
  • [ ] backend/src/test/resources/wiremock/sms-letstalk/*.json and wiremock/wa-meta/*.json stub libraries present
  • [ ] NotifTestContainersConfig.java + NotifFixtures.java present and used by at least one sample test
  • [ ] AC-S0.1, AC-S0.2, AC-S0.3 pass
  • [ ] Tenant isolation pattern verified (every fixture row carries tenant_id; both V1 DB profiles SHARED and BYO boot — though NOTIF tables stay on platformDataSource per TV-05)
  • [ ] No silent failures: missing WireMock stub returns 404, test fails loudly