diff --git a/posthog/cdp/templates/google_cloud_storage/test_template_google_cloud_storage.py b/posthog/cdp/templates/google_cloud_storage/test_template_google_cloud_storage.py index 60b2cb4382cad..27fac416b5692 100644 --- a/posthog/cdp/templates/google_cloud_storage/test_template_google_cloud_storage.py +++ b/posthog/cdp/templates/google_cloud_storage/test_template_google_cloud_storage.py @@ -4,94 +4,10 @@ from inline_snapshot import snapshot from posthog.cdp.templates.google_cloud_storage.template_google_cloud_storage import TemplateGoogleCloudStorageMigrator -from posthog.cdp.templates.helpers import BaseHogFunctionTemplateTest -from posthog.cdp.templates.hubspot.template_hubspot import template as template_hubspot from posthog.models import PluginConfig, PluginAttachment, Plugin, Integration from posthog.test.base import BaseTest -class TestTemplateGoogleCloudStorage(BaseHogFunctionTemplateTest): - template = template_hubspot - - def _inputs(self, **kwargs): - inputs = { - "oauth": {"access_token": "TOKEN"}, - "email": "example@posthog.com", - "properties": { - "company": "PostHog", - }, - } - inputs.update(kwargs) - return inputs - - def test_function_works(self): - self.mock_fetch_response = lambda *args: {"status": 200, "body": {"status": "success"}} # type: ignore - - res = self.run_function(inputs=self._inputs()) - - assert res.result is None - - assert self.get_mock_fetch_calls() == [ - ( - "https://api.hubapi.com/crm/v3/objects/contacts", - { - "method": "POST", - "headers": {"Authorization": "Bearer TOKEN", "Content-Type": "application/json"}, - "body": {"properties": {"company": "PostHog", "email": "example@posthog.com"}}, - }, - ) - ] - assert self.get_mock_print_calls() == [("Contact created successfully!",)] - - def test_exits_if_no_email(self): - for email in [None, ""]: - self.mock_print.reset_mock() - res = self.run_function(inputs=self._inputs(email=email)) - - assert res.result is None - assert self.get_mock_fetch_calls() == [] - assert self.get_mock_print_calls() == [("`email` input is empty. Not creating a contact.",)] - - def test_handles_updates(self): - call_count = 0 - - # First call respond with 409, second one 200 and increment call_count - def mock_fetch(*args): - nonlocal call_count - call_count += 1 - return ( - {"status": 409, "body": {"message": "Contact already exists. Existing ID: 12345"}} - if call_count == 1 - else {"status": 200, "body": {"status": "success"}} - ) - - self.mock_fetch_response = mock_fetch # type: ignore - - res = self.run_function(inputs=self._inputs()) - - assert res.result is None - - assert len(self.get_mock_fetch_calls()) == 2 - - assert self.get_mock_fetch_calls()[0] == ( - "https://api.hubapi.com/crm/v3/objects/contacts", - { - "method": "POST", - "headers": {"Authorization": "Bearer TOKEN", "Content-Type": "application/json"}, - "body": {"properties": {"company": "PostHog", "email": "example@posthog.com"}}, - }, - ) - - assert self.get_mock_fetch_calls()[1] == ( - "https://api.hubapi.com/crm/v3/objects/contacts/12345", - { - "method": "PATCH", - "headers": {"Authorization": "Bearer TOKEN", "Content-Type": "application/json"}, - "body": {"properties": {"company": "PostHog", "email": "example@posthog.com"}}, - }, - ) - - class TestTemplateMigration(BaseTest): def get_plugin_config(self, config: dict): _config = { diff --git a/posthog/cdp/templates/google_pubsub/test_template_google_pubsub.py b/posthog/cdp/templates/google_pubsub/test_template_google_pubsub.py index 6aff353b9762b..157aa137b6998 100644 --- a/posthog/cdp/templates/google_pubsub/test_template_google_pubsub.py +++ b/posthog/cdp/templates/google_pubsub/test_template_google_pubsub.py @@ -4,94 +4,10 @@ from inline_snapshot import snapshot from posthog.cdp.templates.google_pubsub.template_google_pubsub import TemplateGooglePubSubMigrator -from posthog.cdp.templates.helpers import BaseHogFunctionTemplateTest -from posthog.cdp.templates.hubspot.template_hubspot import template as template_hubspot from posthog.models import PluginConfig, PluginAttachment, Plugin, Integration from posthog.test.base import BaseTest -class TestTemplateGooglePubSub(BaseHogFunctionTemplateTest): - template = template_hubspot - - def _inputs(self, **kwargs): - inputs = { - "oauth": {"access_token": "TOKEN"}, - "email": "example@posthog.com", - "properties": { - "company": "PostHog", - }, - } - inputs.update(kwargs) - return inputs - - def test_function_works(self): - self.mock_fetch_response = lambda *args: {"status": 200, "body": {"status": "success"}} # type: ignore - - res = self.run_function(inputs=self._inputs()) - - assert res.result is None - - assert self.get_mock_fetch_calls() == [ - ( - "https://api.hubapi.com/crm/v3/objects/contacts", - { - "method": "POST", - "headers": {"Authorization": "Bearer TOKEN", "Content-Type": "application/json"}, - "body": {"properties": {"company": "PostHog", "email": "example@posthog.com"}}, - }, - ) - ] - assert self.get_mock_print_calls() == [("Contact created successfully!",)] - - def test_exits_if_no_email(self): - for email in [None, ""]: - self.mock_print.reset_mock() - res = self.run_function(inputs=self._inputs(email=email)) - - assert res.result is None - assert self.get_mock_fetch_calls() == [] - assert self.get_mock_print_calls() == [("`email` input is empty. Not creating a contact.",)] - - def test_handles_updates(self): - call_count = 0 - - # First call respond with 409, second one 200 and increment call_count - def mock_fetch(*args): - nonlocal call_count - call_count += 1 - return ( - {"status": 409, "body": {"message": "Contact already exists. Existing ID: 12345"}} - if call_count == 1 - else {"status": 200, "body": {"status": "success"}} - ) - - self.mock_fetch_response = mock_fetch # type: ignore - - res = self.run_function(inputs=self._inputs()) - - assert res.result is None - - assert len(self.get_mock_fetch_calls()) == 2 - - assert self.get_mock_fetch_calls()[0] == ( - "https://api.hubapi.com/crm/v3/objects/contacts", - { - "method": "POST", - "headers": {"Authorization": "Bearer TOKEN", "Content-Type": "application/json"}, - "body": {"properties": {"company": "PostHog", "email": "example@posthog.com"}}, - }, - ) - - assert self.get_mock_fetch_calls()[1] == ( - "https://api.hubapi.com/crm/v3/objects/contacts/12345", - { - "method": "PATCH", - "headers": {"Authorization": "Bearer TOKEN", "Content-Type": "application/json"}, - "body": {"properties": {"company": "PostHog", "email": "example@posthog.com"}}, - }, - ) - - class TestTemplateMigration(BaseTest): def get_plugin_config(self, config: dict): _config = { diff --git a/posthog/cdp/templates/hubspot/template_hubspot.py b/posthog/cdp/templates/hubspot/template_hubspot.py index 916bb4a6f5002..78c0eb4dda73b 100644 --- a/posthog/cdp/templates/hubspot/template_hubspot.py +++ b/posthog/cdp/templates/hubspot/template_hubspot.py @@ -12,8 +12,16 @@ icon_url="/static/services/hubspot.png", category=["CRM", "Customer Success"], hog=""" -let properties := inputs.properties -properties.email := inputs.email +let properties := { + 'email': inputs.email +} +for (let key, value in inputs.properties) { + if (typeof(value) in ('object', 'array', 'tuple')) { + properties[key] := jsonStringify(value) + } else { + properties[key] := value + } +} if (empty(properties.email)) { print('`email` input is empty. Not creating a contact.') @@ -24,36 +32,26 @@ 'Authorization': f'Bearer {inputs.oauth.access_token}', 'Content-Type': 'application/json' } +let body := { + 'inputs': [ + { + 'properties': properties, + 'id': properties.email, + 'idProperty': 'email' + } + ] +} -let res := fetch('https://api.hubapi.com/crm/v3/objects/contacts', { - 'method': 'POST', - 'headers': headers, - 'body': { - 'properties': properties - } +let res := fetch('https://api.hubapi.com/crm/v3/objects/contacts/batch/upsert', { + 'method': 'POST', + 'headers': headers, + 'body': body }) -if (res.status == 409) { - let existingId := replaceOne(res.body.message, 'Contact already exists. Existing ID: ', '') - let updateRes := fetch(f'https://api.hubapi.com/crm/v3/objects/contacts/{existingId}', { - 'method': 'PATCH', - 'headers': headers, - 'body': { - 'properties': properties - } - }) - - if (updateRes.status != 200 or updateRes.body.status == 'error') { - print('Error updating contact:', updateRes.body) - return - } - print('Contact updated successfully!') - return -} else if (res.status >= 300 or res.body.status == 'error') { - print('Error creating contact:', res.body) - return +if (res.status == 200) { + print(f'Contact {properties.email} updated successfully!') } else { - print('Contact created successfully!') + throw Error(f'Error updating contact {properties.email} (status {res.status}): {res.body}') } """.strip(), inputs_schema=[ diff --git a/posthog/cdp/templates/hubspot/test_template_hubspot.py b/posthog/cdp/templates/hubspot/test_template_hubspot.py index 8e2d457ba7265..0d59bd141f72a 100644 --- a/posthog/cdp/templates/hubspot/test_template_hubspot.py +++ b/posthog/cdp/templates/hubspot/test_template_hubspot.py @@ -29,15 +29,23 @@ def test_function_works(self): assert self.get_mock_fetch_calls() == [ ( - "https://api.hubapi.com/crm/v3/objects/contacts", + "https://api.hubapi.com/crm/v3/objects/contacts/batch/upsert", { "method": "POST", "headers": {"Authorization": "Bearer TOKEN", "Content-Type": "application/json"}, - "body": {"properties": {"company": "PostHog", "email": "example@posthog.com"}}, + "body": { + "inputs": [ + { + "properties": {"company": "PostHog", "email": "example@posthog.com"}, + "id": "example@posthog.com", + "idProperty": "email", + } + ] + }, }, ) ] - assert self.get_mock_print_calls() == [("Contact created successfully!",)] + assert self.get_mock_print_calls() == [("Contact example@posthog.com updated successfully!",)] def test_exits_if_no_email(self): for email in [None, ""]: @@ -48,45 +56,6 @@ def test_exits_if_no_email(self): assert self.get_mock_fetch_calls() == [] assert self.get_mock_print_calls() == [("`email` input is empty. Not creating a contact.",)] - def test_handles_updates(self): - call_count = 0 - - # First call respond with 409, second one 200 and increment call_count - def mock_fetch(*args): - nonlocal call_count - call_count += 1 - return ( - {"status": 409, "body": {"message": "Contact already exists. Existing ID: 12345"}} - if call_count == 1 - else {"status": 200, "body": {"status": "success"}} - ) - - self.mock_fetch_response = mock_fetch # type: ignore - - res = self.run_function(inputs=self._inputs()) - - assert res.result is None - - assert len(self.get_mock_fetch_calls()) == 2 - - assert self.get_mock_fetch_calls()[0] == ( - "https://api.hubapi.com/crm/v3/objects/contacts", - { - "method": "POST", - "headers": {"Authorization": "Bearer TOKEN", "Content-Type": "application/json"}, - "body": {"properties": {"company": "PostHog", "email": "example@posthog.com"}}, - }, - ) - - assert self.get_mock_fetch_calls()[1] == ( - "https://api.hubapi.com/crm/v3/objects/contacts/12345", - { - "method": "PATCH", - "headers": {"Authorization": "Bearer TOKEN", "Content-Type": "application/json"}, - "body": {"properties": {"company": "PostHog", "email": "example@posthog.com"}}, - }, - ) - class TestTemplateMigration(BaseTest): def get_plugin_config(self, config: dict):