Skip to content

feat(whatsapp): upgrade SDK to 2.0.0, add pytest unit + integration tests#333

Open
Tram-Nguyen87 wants to merge 5 commits into
masterfrom
feat/whatsapp-sdk-v2-upgrade
Open

feat(whatsapp): upgrade SDK to 2.0.0, add pytest unit + integration tests#333
Tram-Nguyen87 wants to merge 5 commits into
masterfrom
feat/whatsapp-sdk-v2-upgrade

Conversation

@Tram-Nguyen87
Copy link
Copy Markdown
Contributor

@Tram-Nguyen87 Tram-Nguyen87 commented May 20, 2026

Summary

  • Bumps autohive-integrations-sdk to ~=2.0.0 and converts all context.fetch() callers in whatsapp.py to the new FetchResponse shape (response.data).
  • Replaces every error-path ActionResult(data={"error": ...}) with ActionError(message=...) and strips error / result properties from config.json output schemas.
  • Replaces the legacy asyncio testbed (test_whatsapp.py) with a full pytest suite: 118 unit tests (mocked fetch via FetchResponse) and 9 integration tests (live Graph API via aiohttp) with a destructive marker on write tests.
  • Refreshes README.md to drop v1-era result: bool / error: str output rows, replace the legacy test runner with the pytest pattern, and clarify that phone_number_id is a per-action input (not an auth field).

Changes

SDK 2.0.0 upgrade

  • whatsapp/requirements.txt bumped to autohive-integrations-sdk~=2.0.0
  • whatsapp/config.json version bumped to 2.0.0
  • All 4 context.fetch() call sites in whatsapp.py now use response.data for the body
  • All error returns now use ActionError(message=...) (validation, API error envelopes, exception handlers, missing-token paths)
  • Output schemas in config.json tightened: error / result fields removed; only documented success fields remain (message_id, status, quality_rating)

Tests

  • Removed tests/context.py and the legacy tests/test_whatsapp.py
  • Added tests/conftest.py for sys.path setup
  • Added tests/test_whatsapp_unit.py — 118 tests covering:
    • Every helper function (get_whatsapp_creds, _extract_api_error, validate_phone_number, validate_phone_number_id, validate_media_url) with parametrized edge cases
    • Every action: happy path, request URL/method, payload structure, headers, validation errors, API errors, exceptions, missing-token, non-dict responses, empty-list responses, plus media-type-specific behavior (audio doesn't get caption, filename only added for documents, etc.)
    • Mocks use accurate HTTP status codes (200 for success, 400/404 for error envelopes)
    • Platform OAuth auth envelope {"auth_type": "PlatformOauth2", "credentials": {...}}
  • Added tests/test_whatsapp_integration.py — 9 live tests:
    • Read-only: get_phone_number_health (status + quality rating, invalid ID, nonexistent ID), plus input-validation paths for send_message and send_media_message that short-circuit before fetch
    • @pytest.mark.destructive: one test each for send_message, send_template_message, send_media_message (sends real messages to WHATSAPP_RECIPIENT_PHONE — review before running)
  • real_fetch uses real resp.status + resp.headers, passes through params=, and falls back to resp.text() if the body isn't JSON

Docs

  • whatsapp/README.md — added global "Error handling" note explaining ActionError; removed success / error output rows from every action; corrected provider name (WhatsAppWhatsApp Business); rewrote Authentication section to clarify phone_number_id is a per-action input rather than an auth field; replaced legacy python tests/test_whatsapp.py instructions with the pytest unit + integration pattern (safe command first, destructive command second with warning)
  • .env.example — added WHATSAPP_* section with the 6 variables the integration tests read (ACCESS_TOKEN, PHONE_NUMBER_ID, RECIPIENT_PHONE, TEMPLATE_NAME, TEMPLATE_LANG, MEDIA_URL)

Validation

Local build pipeline (all green):

  • python ../autohive-integrations-tooling/scripts/validate_integration.py whatsapp → 0 errors, 0 warnings
  • python ../autohive-integrations-tooling/scripts/check_code.py whatsapp → all 9 sub-checks pass (syntax, imports, JSON, ruff lint, ruff format, bandit, pip-audit, config-code sync, fetch patterns)
  • python -m pytest whatsapp/ -v → 118 passed
  • ruff check + ruff format --config ../autohive-integrations-tooling/ruff.toml whatsapp → clean

Test plan

  • pytest whatsapp/tests/test_whatsapp_unit.py -v passes 118/118
  • pytest whatsapp/tests/test_whatsapp_integration.py -m "integration and not destructive" passes with a valid WHATSAPP_ACCESS_TOKEN + WHATSAPP_PHONE_NUMBER_ID
  • pytest whatsapp/tests/test_whatsapp_integration.py -m "integration and destructive" passes after setting WHATSAPP_RECIPIENT_PHONE (sends real messages — review first)
image

…ests

Converts context.fetch() callers to FetchResponse.data, replaces error
ActionResults with ActionError, bumps config.json to 2.0.0, and replaces
the legacy asyncio testbed with pytest suites (118 unit tests covering
every branch + 8 integration tests with destructive marker).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 20, 2026

🔍 Integration Validation Results

Commit: 727cdff39c9d9a33aa9744b4875b3519f9b4d081 · style(whatsapp): fix line-length lint failures from review-fix commit
Updated: 2026-05-22T01:13:02Z

Changed directories: whatsapp

Check Result
Structure ✅ Passed
Code ✅ Passed
Tests ✅ Passed
README ✅ Passed
Version ✅ Passed
✅ Structure Check output
Validating 1 integration(s)...

============================================================
Integration: whatsapp
============================================================
✅ All checks passed!

============================================================
SUMMARY
============================================================
Integrations validated: 1
Total errors: 0
Total warnings: 0

✅ All validations passed!
✅ Code Check output
----------------------------------------
Checking: whatsapp
----------------------------------------

📦 Installing dependencies...

🐍 Checking Python syntax...
   ✅ Syntax OK

📥 Checking imports...
   ✅ Imports OK

📄 Checking JSON files...
   ✅ JSON files OK

🔍 Linting with ruff...
   ✅ Lint OK

🎨 Checking formatting with ruff...
   ✅ Formatting OK

🔒 Scanning for security issues with bandit...
   ✅ Security OK

🛡️ Checking dependencies for vulnerabilities with pip-audit...
   ✅ Dependencies OK

🔗 Checking config-code sync...
   ✅ Config-code sync OK

🔄 Checking fetch patterns...
   ✅ Fetch patterns OK

========================================
✅ CODE CHECK PASSED
========================================
✅ Tests Check output

Integration   Tests  Coverage        Status
-------------------------------------------
whatsapp   118/118      100%      ✅ Passed
-------------------------------------------
Total      118/118            ✅ All passed

✅ Tests passed: whatsapp
✅ README Check output
========================================
✅ README CHECK PASSED
========================================
✅ Version Check output
✅ whatsapp: 1.0.0 → 2.0.0 (major bump)

========================================
✅ VERSION CHECK PASSED
========================================

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9d5f1ca482

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread whatsapp/tests/conftest.py Outdated
…ves as a package

The previous sys.path entry pointed at whatsapp/, which made `import whatsapp`
resolve to whatsapp/whatsapp.py (a module), breaking `from whatsapp.whatsapp import ...`
in the test suites with "whatsapp is not a package". Pointing at the repo root
makes whatsapp/ load as a package via its __init__.py.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Tram-Nguyen87
Copy link
Copy Markdown
Contributor Author

@Tram-Nguyen87 ran the full live e2e tests locally — 9/9 integration tests pass (read-only get_phone_number_health + input validation green; destructive sends covered text message, hello_world template, and image media to a test recipient). All 118 unit tests also passing.

Copy link
Copy Markdown
Collaborator

@TheRealAgentK TheRealAgentK left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice SDK v2 migration overall. I left a few comments on aligning the template language default and trimming docs/catalog wording to the actual action surface.

Comment thread whatsapp/whatsapp.py Outdated
@@ -121,67 +105,42 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):
language_code = inputs.get("language_code", "en")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

send_template_message defaults language_code to "en", but the live destructive test harness defaults WHATSAPP_TEMPLATE_LANG to "en_US" for the default hello_world template. That means the tested live path and the production omitted-input path can send different payloads. Can we align code/config/README/tests here — either default to en_US everywhere, or make language_code required so callers must provide the approved locale?

Comment thread whatsapp/README.md Outdated
@@ -51,9 +49,7 @@ Configure the integration within Autohive using platform authentication for What
- `language_code` (optional): Template language code (default: "en")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update this default to match the code/config decision above. Right now the docs say omitted language_code means "en", but the live template test path uses "en_US".

Comment thread whatsapp/README.md
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The README/config descriptions still say the integration can “manage conversations”, but the current action surface only sends messages/templates/media and checks phone-number health. Since this PR is refreshing the public docs, can we trim this wording so the README/catalog matches the actual actions? I’d do the same for the config description.

Comment thread whatsapp/config.json
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same default mismatch as the action code: config advertises "en" for send_template_message.language_code, while the live test default is "en_US". Please keep the schema default in sync with whichever behavior we want to support.

Tram-Nguyen87 and others added 3 commits May 22, 2026 13:04
Make language_code a required input on send_template_message so callers
explicitly pass the locale matching their approved template. WhatsApp
templates are approved per-locale on Meta (e.g. the stock hello_world
template only exists in en_US), so no default is universally correct;
the previous "en" default silently mismatched the live test path that
uses en_US.

- whatsapp.py: read language_code as a required input (no fallback)
- config.json: drop default, add language_code to required[], reword
  description to flag the per-locale approval constraint
- README.md: mark language_code (required), update example to en_US
- test_whatsapp_unit.py: replace default-is-"en" test with a
  validation-error test (SDK 2.0 rejects missing required inputs at
  the validator); pass language_code on all other template tests
- test_whatsapp_integration.py: clarify TEMPLATE_LANG env-var doc

Also trim README + config descriptions to match the actual action
surface (send text/template/media, read phone-number health) instead
of the inaccurate "manage conversations" / "contact validation"
wording from the previous draft.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Long inline dict literals from adding language_code to template tests
exceeded 120 cols; ruff format breaks them across multiple lines.
Also wraps the WHATSAPP_TEMPLATE_LANG docstring line.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Tram-Nguyen87
Copy link
Copy Markdown
Contributor Author

Addressed all four threads and here is a general summary:

  • language_code is now a required input rather than defaulting to anything (rationale in thread 1)
  • README + config descriptions trimmed to match the actual action surface
  • .env.example merge conflict with master resolved (kept both WhatsApp + YouTube blocks)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants