From 6490b9c2a6b1967526f4d3f60ba288b6bf4fca59 Mon Sep 17 00:00:00 2001 From: Cam Date: Wed, 10 Jun 2026 23:18:07 -0500 Subject: [PATCH] Add tests for editAccount and updateMembership Adding some basic automated tests for the editAccount and updateMembership (legacy) Neon webhooks. These tests just create an event in the correct format and verify that Alta Open was called with the correct account ID. I may expand these out later, but the webhook changes are mostly around the way data is structured or named, so rough smoke tests should be sufficient to show that we can parse the new format. --- tests/test_alta_open_lambda.py | 82 ++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/tests/test_alta_open_lambda.py b/tests/test_alta_open_lambda.py index fd86d8c..3eb36e6 100644 --- a/tests/test_alta_open_lambda.py +++ b/tests/test_alta_open_lambda.py @@ -22,6 +22,8 @@ """ import json +import logging +import random import sys from pathlib import Path @@ -61,6 +63,13 @@ def make_event(event_trigger, data, custom_parameters): NEW_PARAMS = {"webhook_name": "UpdateMembership20260509", "legacy": "false"} +def rand_id(): + """A random Neon-style numeric id. The handler passes ids straight through, + so the exact value is irrelevant -- randomizing makes that explicit and + keeps arbitrary numbers from looking meaningful.""" + return random.randint(1, 9_999_999) + + # =========================================================================== # Guard clauses -- trigger-independent; these exercise the harness end to end # =========================================================================== @@ -85,3 +94,76 @@ def test_body_as_dict_currently_raises(openpath): with pytest.raises(TypeError): lf.lambda_handler(event, {}) openpath.assert_not_called() + + +# =========================================================================== +# editAccount +# =========================================================================== + + +def legacy_edit_account(account_id=None): + # legacy: integer accountId, nested individualAccount + account_id = rand_id() if account_id is None else account_id + return make_event( + "editAccount", + { + "individualAccount": { + "accountId": account_id, + "primaryContact": {"contactId": account_id}, + "customFieldDataList": {"customFieldData": []}, + } + }, + UNKNOWN_PARAMS, + ) + + +def test_legacy_edit_account_passes_int_id(openpath): + account_id = rand_id() + lf.lambda_handler(legacy_edit_account(account_id), {}) + openpath.assert_called_once_with(account_id) + + +# =========================================================================== +# updateMembership +# =========================================================================== + + +def legacy_update_membership(account_id=None): + # legacy: nested membershipEnrollment + transaction + account_id = rand_id() if account_id is None else account_id + return make_event( + "updateMembership", + { + "membershipEnrollment": { + "accountId": account_id, + "membershipId": rand_id(), + "enrollmentType": "RENEW", + }, + "transaction": { + "transactionId": rand_id(), + "transactionStatus": "SUCCEEDED", + }, + }, + LEGACY_PARAMS, + ) + + +def test_legacy_update_membership_passes_int_id(openpath): + account_id = rand_id() + lf.lambda_handler(legacy_update_membership(account_id), {}) + openpath.assert_called_once_with(account_id) + + +# =========================================================================== +# Legacy-flag detection -- customParameters.legacy +# =========================================================================== + +def test_null_custom_parameters_does_not_warn_or_crash(openpath, caplog): + # Truly-legacy events deliver customParameters: null. This must not warn + # and must not raise (regression guard for the historical NoneType bug). + account_id = rand_id() + event = make_event("editAccount", {"individualAccount": {"accountId": account_id}}, UNKNOWN_PARAMS) + with caplog.at_level(logging.WARNING): + lf.lambda_handler(event, {}) + assert "LEGACY EVENT DETECTED" not in caplog.text + openpath.assert_called_once_with(account_id)