mirror of
https://github.com/PostHog/posthog.git
synced 2024-11-30 19:41:46 +01:00
191 lines
6.7 KiB
Python
191 lines
6.7 KiB
Python
from typing import cast
|
|
from unittest.mock import ANY
|
|
|
|
from ee.api.hooks import valid_domain
|
|
from ee.api.test.base import APILicensedTest
|
|
from ee.models.hook import Hook
|
|
from hogvm.python.operation import HOGQL_BYTECODE_VERSION
|
|
from posthog.models.action.action import Action
|
|
from posthog.models.hog_functions.hog_function import HogFunction
|
|
from posthog.test.base import ClickhouseTestMixin
|
|
|
|
|
|
class TestHooksAPI(ClickhouseTestMixin, APILicensedTest):
|
|
action: Action
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.action = Action.objects.create(
|
|
team=self.team,
|
|
name="Test Action",
|
|
steps_json=[
|
|
{
|
|
"event": "$pageview",
|
|
"properties": [],
|
|
}
|
|
],
|
|
)
|
|
|
|
def test_create_hook(self):
|
|
data = {"target": "https://hooks.zapier.com/abcd/", "event": "action_performed"}
|
|
response = self.client.post(f"/api/projects/{self.team.id}/hooks/", data)
|
|
response_data = response.json()
|
|
|
|
hook = Hook.objects.get(id=response_data["id"])
|
|
self.assertEqual(response.status_code, 201)
|
|
self.assertEqual(hook.team, self.team)
|
|
self.assertEqual(hook.target, data["target"])
|
|
self.assertEqual(hook.event, data["event"])
|
|
self.assertEqual(hook.resource_id, None)
|
|
self.assertDictContainsSubset(
|
|
{
|
|
"id": hook.id,
|
|
"event": data["event"],
|
|
"target": data["target"],
|
|
"resource_id": None,
|
|
"team": self.team.id,
|
|
},
|
|
cast(dict, response.json()),
|
|
)
|
|
|
|
def test_create_hook_with_resource_id(self):
|
|
data = {
|
|
"target": "https://hooks.zapier.com/abcd/",
|
|
"event": "action_performed",
|
|
"resource_id": "66",
|
|
}
|
|
response = self.client.post(f"/api/projects/{self.team.id}/hooks/", data)
|
|
response_data = response.json()
|
|
|
|
hook = Hook.objects.get(id=response_data["id"])
|
|
self.assertEqual(response.status_code, 201)
|
|
self.assertEqual(hook.team, self.team)
|
|
self.assertEqual(hook.target, data["target"])
|
|
self.assertEqual(hook.event, data["event"])
|
|
self.assertEqual(str(hook.resource_id), data["resource_id"])
|
|
self.assertDictContainsSubset(
|
|
{
|
|
"id": hook.id,
|
|
"event": data["event"],
|
|
"target": data["target"],
|
|
"resource_id": int(data["resource_id"]),
|
|
"team": self.team.id,
|
|
},
|
|
cast(dict, response.json()),
|
|
)
|
|
|
|
def test_delete_hook(self):
|
|
hook_id = "abc123"
|
|
Hook.objects.create(id=hook_id, user=self.user, team=self.team, resource_id=20)
|
|
response = self.client.delete(f"/api/projects/{self.team.id}/hooks/{hook_id}")
|
|
self.assertEqual(response.status_code, 204)
|
|
|
|
def test_invalid_target(self):
|
|
data = {
|
|
"target": "https://hooks.non-zapier.com/abcd/",
|
|
"event": "action_performed",
|
|
}
|
|
response = self.client.post(f"/api/projects/{self.team.id}/hooks/", data)
|
|
self.assertEqual(response.status_code, 400)
|
|
|
|
def test_create_hog_function_via_hook(self):
|
|
data = {
|
|
"target": "https://hooks.zapier.com/hooks/standard/1234/abcd",
|
|
"event": "action_performed",
|
|
"resource_id": self.action.id,
|
|
}
|
|
|
|
with self.settings(HOOK_HOG_FUNCTION_TEAMS="*"):
|
|
res = self.client.post(f"/api/projects/{self.team.id}/hooks/", data)
|
|
|
|
assert res.status_code == 201, res.json()
|
|
json = res.json()
|
|
|
|
assert not Hook.objects.exists()
|
|
assert HogFunction.objects.count() == 1
|
|
hog_function = HogFunction.objects.first()
|
|
assert hog_function
|
|
assert json == {
|
|
"id": str(hog_function.id),
|
|
"event": "action_performed",
|
|
"target": "https://hooks.zapier.com/hooks/standard/1234/abcd",
|
|
"resource_id": self.action.id,
|
|
}
|
|
|
|
assert hog_function.filters == {
|
|
"actions": [{"id": str(self.action.id), "name": "", "type": "actions", "order": 0}],
|
|
"bytecode": ["_H", HOGQL_BYTECODE_VERSION, 32, "$pageview", 32, "event", 1, 1, 11, 3, 1, 4, 1],
|
|
}
|
|
|
|
assert hog_function.inputs == {
|
|
"body": {
|
|
"bytecode": ANY,
|
|
"value": {
|
|
"data": {
|
|
"distinctId": "{event.distinct_id}",
|
|
"event": "{event.name}",
|
|
"eventUuid": "{event.uuid}",
|
|
"person": {
|
|
"properties": "{person.properties}",
|
|
"uuid": "{person.uuid}",
|
|
},
|
|
"properties": "{event.properties}",
|
|
"teamId": "{project.id}",
|
|
"timestamp": "{event.timestamp}",
|
|
},
|
|
"hook": {
|
|
"event": "{event}",
|
|
"id": "{eventUuid}",
|
|
"target": "https://hooks.zapier.com/{inputs.hook}",
|
|
},
|
|
},
|
|
},
|
|
"debug": {},
|
|
"hook": {
|
|
"bytecode": [
|
|
"_H",
|
|
HOGQL_BYTECODE_VERSION,
|
|
32,
|
|
"hooks/standard/1234/abcd",
|
|
],
|
|
"value": "hooks/standard/1234/abcd",
|
|
},
|
|
}
|
|
|
|
def test_delete_hog_function_via_hook(self):
|
|
data = {
|
|
"target": "https://hooks.zapier.com/hooks/standard/1234/abcd",
|
|
"event": "action_performed",
|
|
"resource_id": self.action.id,
|
|
}
|
|
|
|
with self.settings(HOOK_HOG_FUNCTION_TEAMS="*"):
|
|
res = self.client.post(f"/api/projects/{self.team.id}/hooks/", data)
|
|
|
|
hook_id = res.json()["id"]
|
|
|
|
assert HogFunction.objects.count() == 1
|
|
|
|
with self.settings(HOOK_HOG_FUNCTION_TEAMS="*"):
|
|
res = self.client.delete(f"/api/projects/{self.team.id}/hooks/{hook_id}")
|
|
assert res.status_code == 204
|
|
|
|
assert not HogFunction.objects.exists()
|
|
|
|
|
|
def test_valid_domain() -> None:
|
|
test_cases = {
|
|
"http://hooks.zapier.com": True,
|
|
"https://hooks.zapier.com": True,
|
|
"http://hooks.zapier.com/something": True,
|
|
"https://hooks.zapier.com/something": True,
|
|
"http://hooks.zapierz.com": False,
|
|
"https://hooks.zapierz.com": False,
|
|
"http://hoos.zapier.com/something": False,
|
|
"https://hoos.zapier.com/something": False,
|
|
}
|
|
|
|
for test_input, expected_test_output in test_cases.items():
|
|
test_output = valid_domain(test_input)
|
|
assert test_output == expected_test_output
|