feat(typeform): upgrade to SDK 2.0.0 with unit + integration tests#379
Conversation
Migrate all 24 actions to the SDK 2.0.0 FetchResponse contract and ActionError error model: - Access .data on every context.fetch() result (forms, responses, workspaces, themes, images, webhooks + the chained update_form/update_workspace fetches). - Convert genuine exception paths to ActionError(message=...). - Intentionally keep the structured 429 rate-limit response as an ActionResult so the documented retry contract (retry_after_seconds, _retry_attempt) survives. - Guard the two chained-fetch actions against v2 empty-body (.data is None). - Bump config.json to 2.0.0 and pin autohive-integrations-sdk~=2.0.0. Tests: - test_typeform_unit.py: 107 tests (mock_context + FetchResponse) covering every action's happy path, request verification, ActionError, structured rate-limit, and validation-error cases, plus the rate-limit helpers. - test_typeform_integration.py: live_context (platform-OAuth) read-only + destructive lifecycle tests; real_fetch mirrors the SDK contract (raises on 429/non-ok). - Replace the legacy script-style test_typeform.py; document env vars in .env.example. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
🔍 Integration Validation ResultsCommit: Changed directories:
|
Replace the param_keys loop with explicit inputs.get() guards so the
config-code sync checker can see each parameter (it only detects literal
inputs["key"]/inputs.get("key") access, not loop variables). Clears the 8
list_responses sync warnings. Behaviour is identical — same truthy guards.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
create_theme requires a font property; add it to the theme lifecycle payload. Make the webhook lifecycle test create its own throwaway form instead of depending on a pre-existing one, so destructive e2e passes on empty accounts. Co-authored-by: Cursor <cursoragent@cursor.com>
Local validation + live E2E resultsRan the full CI-equivalent pipeline plus live end-to-end tests against the real Typeform API. Validation pipeline
Live E2ERead-only (
Destructive (
Fixes included in this push (
|
…tency Co-authored-by: Cursor <cursoragent@cursor.com>
TheRealAgentK
left a comment
There was a problem hiding this comment.
Approved — the SDK v2 migration, tests, and validation look good. I left one nit about confirming the potentially-unused Typeform scopes, but it is not blocking.
There was a problem hiding this comment.
Nit: local validate_integration.py typeform passes, but it flags accounts:read and offline as potentially unused scopes. If those are required for Typeform/platform OAuth refresh behavior, this is fine as-is; otherwise consider trimming them to keep the OAuth request minimal.
There was a problem hiding this comment.
Both scopes are intentional:
- accounts:read is required by Typeform's /me endpoint, used by get_current_user.
- offline is the standard OAuth2 refresh-token scope — without it the platform can't refresh the access token after expiry.
The validator can't detect these statically, hence the warning.
Summary
Upgrades the Typeform integration from SDK
1.0.2to2.0.0, covering source, tests,requirements.txt, andconfig.json. Adds full unit + integration test suites (the integration previously had only a legacy script-style test).What changed
Source (
typeform.py) — all 24 actions.dataon everycontext.fetch()result (user, forms, responses, workspaces, themes, images, webhooks — including the chainedupdate_form/update_workspacefetches).ActionError(message=...).ActionResult(create_rate_limit_response) rather than converting toActionError, so the documented retry contract (error_type,retry_after_seconds,_retry_attempt,can_retry) the agent relies on survives. Verified it still passes output-schema validation..data is None) so an unexpected body returns a cleanActionErrorinstead of anAttributeError/VALIDATION_ERROR.Config / deps
config.jsonversion1.1.0→2.0.0. Output schemas unchanged: there was noerrorproperty to remove, andresultis a genuine success flag (returned on success), not error-only.requirements.txtpinsautohive-integrations-sdk~=2.0.0.Tests
tests/test_typeform_unit.py— 107 tests (mock_context+FetchResponse). Every action covered for: happy path, request verification (URL/method/body/params),ActionErroron exceptions, structured rate-limit, andVALIDATION_ERRORon missing required inputs; plus direct tests of theis_rate_limit_error/create_rate_limit_responsehelpers.tests/test_typeform_integration.py—live_contextplatform-OAuth fixture; 13 read-only tests (chained list→get, skip gracefully on empty accounts) + 4 destructive lifecycle tests (form / workspace / theme / webhook, each cleans up after itself).real_fetchmirrors the SDK contract — raisesRateLimitErroron 429 andHTTPErroron other non-ok — so error-path assertions exercise the same code production does.tests/conftest.pyadded (sys.path + platform-OAuthmock_context). Legacytest_typeform.py/context.pyremoved..env.exampledocumentsTYPEFORM_ACCESS_TOKEN(+ optionalTYPEFORM_TEST_FORM_ID,TYPEFORM_TEST_WORKSPACE_ID).Test runs (local, this branch)
Integration tests collect correctly (13 read-only + 4 destructive) and skip cleanly without a token.
To run the integration tests (after setting
TYPEFORM_ACCESS_TOKEN):Reviewer notes
ActionResultretention is intentional (see above) — not an overlooked error-path conversion.list_responsesconfig-code-sync warnings are false positives: those params are read via aparam_keysloop the linter can't trace.