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.cs13 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 firstGET 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 messagePOST 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 sendingPOST 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 webhookPOST 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 testPOST 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.