Skip to main content
Version: Latest

12. Testing

12.1 Standalone Library Tests​

Shumoul.Saas.WhatsAppIntegration/Tests — xUnit, 29 test cases across 4 files:

FileCasesCovers
WhatsAppWebhookParserTests.cs9Text/media/status message parsing; the ProfileName regression suite: single contact/message, multi-contact matching by wa_id, no matching contact, no contacts array at all
WhatsAppSignatureValidatorTests.cs7Valid signature, invalid signature, missing header, malformed header, missing AppSecret, case-insensitive sha256= prefix
WhatsAppCloudApiClientRequestConstructionTests.cs8Text send and template send HTTP request shape (URL, headers, JSON body)
WhatsAppCloudApiClientMediaTests.cs5GetMediaMetaAsync happy path / missing-token short-circuit / HTTP-error path; DownloadMediaBytesAsync happy path and metadata-failure short-circuit

Run with dotnet test from the repository root.

12.2 ERP Tests​

Shumoul.Application.Tests/HelpersTests/WhatsAppPhoneHelperTests.cs — 13 test cases, [Theory]-driven, covering the single consolidated phone normalizer (WhatsAppPhoneHelper.TryNormalizePhone):

  • 6 accepted formats: already-normalized 966XXXXXXXXX, local 0XXXXXXXXX, bare 9-digit 5XXXXXXXX, leading +, embedded spaces, embedded dashes.
  • 7 rejected inputs: null, empty, whitespace, non-numeric, too-short, and two wrong-length variants.

No dedicated ERP-side test exists for TenantWhatsAppSender's send path itself — its behavior is fully delegated to WhatsAppCloudApiClient, already covered on the library side (§12.1); an ERP-side HTTP-mocking test for the same client would duplicate rather than add coverage.

12.3 Webhook Parser Tests​

See §12.1's WhatsAppWebhookParserTests.cs row. The most important regression to be aware of when modifying this parser: the original test payload never included wa_id on its contact object, because the old (buggy) code never checked it — the test was corrected to include wa_id and assert the populated ProfileName, turning a "passes accidentally" test into a real regression guard.

12.4 Signature Tests​

See §12.1's WhatsAppSignatureValidatorTests.cs row. Tests construct a real HMAC-SHA256 digest over a known body/secret pair and assert both the positive (IsValid: true) and negative (IsValid: false, with Reason populated) cases.

12.5 Phone Normalization Tests​

See §12.2. This is the one piece of WhatsApp-related business logic tested in the ERP repository rather than the standalone library, consistent with WhatsAppPhoneHelper living in Shumoul.Application.Helpers by design (see ADR-001).

12.6 How QA Should Test Using Postman​

  1. Authenticate against the tenant's auth endpoint to obtain a JWT; set Authorization: Bearer {token} as a Postman collection-level header.
  2. Verify configuration first — GET api/v1/Communication/Diagnostics/WhatsApp and GET api/v1/Communication/Health reveal whether credentials are configured before attempting any send.
  3. Test connectivity without sending a message — POST api/v1/Communication/Test/WhatsApp performs a business-account lookup only; safe to run repeatedly.
  4. Test a real template send to a controlled test number — POST api/v1/WhatsApp/SendTestTemplate (uses the platform's own number) or POST api/v1/Communication/Send/WhatsApp (uses the tenant's own number, requires WhatsAppOperationalSettings.EnableSending).
  5. Preview before sending — POST api/v1/Communication/Preview shows the resolved template/body without dispatching, useful for validating template parameter mapping before a real send.
  6. Simulate an inbound webhook — POST api/v1/notifications/webhook with a payload matching §8.5 and a correctly-computed X-Hub-Signature-256 header (compute HMAC-SHA256 of the exact request body bytes using the configured AppSecret; a Postman pre-request script can compute this if the secret is available in a QA-only environment). Note this endpoint requires no JWT — only the signature.
  7. Run the full WhatsApp smoke test — POST api/v1/Communication/SmokeTest/WhatsApp against a test phone number; inspect the steps[] array in the response for the first failing step rather than only the top-level passed flag.

Never point step 4 or step 7 at a real customer's phone number, and never run them against a production tenant unless the intent is genuinely to send that customer a message.