Skip to content

Commit

Permalink
feat(cdp): test site function javascript (#26943)
Browse files Browse the repository at this point in the history
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
mariusandra and github-actions[bot] authored Dec 17, 2024
1 parent 4e1e418 commit daa0a27
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 14 deletions.
4 changes: 2 additions & 2 deletions posthog/cdp/site_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def get_transpiled_function(hog_function: HogFunction) -> str:
"""
let processEvent = undefined;
if ('onEvent' in source) {
processEvent = function processEvent(globals) {
processEvent = function processEvent(globals, posthog) {
if (!('onEvent' in source)) { return; };
const inputs = buildInputs(globals);
const filterGlobals = { ...globals.groups, ...globals.event, person: globals.person, inputs, pdi: { distinct_id: globals.event.distinct_id, person: globals.person } };
Expand Down Expand Up @@ -123,7 +123,7 @@ def get_transpiled_function(hog_function: HogFunction) -> str:
}
return {
processEvent: processEvent
processEvent: (globals) => processEvent(globals, posthog)
}
}
Expand Down
73 changes: 67 additions & 6 deletions posthog/cdp/test/test_site_functions.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import json
import subprocess
import tempfile
from inline_snapshot import snapshot
Expand Down Expand Up @@ -71,7 +72,7 @@ def test_get_transpiled_function_basic(self):
};return exports;})();
let processEvent = undefined;
if ('onEvent' in source) {
processEvent = function processEvent(globals) {
processEvent = function processEvent(globals, posthog) {
if (!('onEvent' in source)) { return; };
const inputs = buildInputs(globals);
const filterGlobals = { ...globals.groups, ...globals.event, person: globals.person, inputs, pdi: { distinct_id: globals.event.distinct_id, person: globals.person } };
Expand All @@ -98,7 +99,7 @@ def test_get_transpiled_function_basic(self):
}
return {
processEvent: processEvent
processEvent: (globals) => processEvent(globals, posthog)
}
}
Expand Down Expand Up @@ -129,12 +130,12 @@ def test_get_transpiled_function_with_template_input(self):
assert '__getGlobal("person")' in result

def test_get_transpiled_function_with_filters(self):
self.hog_function.hog = "export function onEvent(event) { console.log(event.event); }"
self.hog_function.hog = "export function onEvent(globals) { console.log(globals); }"
self.hog_function.filters = {"events": [{"id": "$pageview", "name": "$pageview", "type": "events", "order": 0}]}

result = self.compile_and_run()

assert "console.log(event.event);" in result
assert "console.log(globals);" in result
assert "const filterMatches = " in result
assert '__getGlobal("event") == "$pageview"' in result
assert "const filterMatches = !!(!!((__getGlobal" in result
Expand Down Expand Up @@ -249,7 +250,7 @@ def test_get_transpiled_function_with_complex_filters(self):
action.steps = [{"event": "$pageview", "url": "https://example.com"}] # type: ignore
action.save()

self.hog_function.hog = "export function onEvent(event) { console.log(event.event); }"
self.hog_function.hog = "export function onEvent(globals) { console.log(globals); }"
self.hog_function.filters = {
"events": [{"id": "$pageview", "name": "$pageview", "type": "events"}],
"actions": [{"id": str(action.pk), "name": "Test Action", "type": "actions"}],
Expand All @@ -258,7 +259,7 @@ def test_get_transpiled_function_with_complex_filters(self):

result = self.compile_and_run()

assert "console.log(event.event);" in result
assert "console.log(globals);" in result
assert "const filterMatches = " in result
assert '__getGlobal("event") == "$pageview"' in result
assert "https://example.com" in result
Expand All @@ -283,3 +284,63 @@ def test_get_transpiled_function_with_mappings(self):
assert 'if (!!(!!((__getGlobal("event") == "$autocapture")))) {' in result
assert "const newInputs = structuredClone(inputs);" in result
assert 'newInputs["greeting"] = concat("Hallo, ", __getProperty' in result

def test_run_function_onload(self):
self.hog_function.hog = "export function onLoad({ inputs, posthog }) { console.log(inputs.message); }"
self.hog_function.filters = {"events": [{"id": "$pageview", "name": "$pageview", "type": "events", "order": 0}]}
self.hog_function.inputs = {"message": {"value": "Hello World {person.properties.name}"}}

result = self.compile_and_run()
assert "Hello World" in result

response = self._execute_javascript(
result
+ "().init({ posthog: { get_property: () => ({name: 'Bob'}) }, callback: () => { console.log('Loaded') } })"
)
assert "Hello World Bob\nLoaded" == response.strip()

def test_run_function_onevent(self):
self.hog_function.hog = "export function onEvent({ inputs }) { console.log(inputs.message); }"
# self.hog_function.filters = {"events": [{"id": "$pageview", "name": "$pageview", "type": "events", "order": 0}]}
self.hog_function.inputs = {"message": {"value": "Hello World {event.properties.id}"}}
self.hog_function.mappings = [
{
"inputs": {"greeting": {"value": "Hallo, {person.properties.nonexistent_property}!"}},
"filters": {"events": [{"id": "$pageview", "name": "$pageview", "type": "events"}]},
}
]

result = self.compile_and_run()
assert "Hello World" in result

globals = {
"event": {"event": "$pageview", "properties": {"id": "banana"}},
"groups": {},
"person": {"properties": {"name": "Bob"}},
}
response = self._execute_javascript(
result
+ "().init({ posthog: { get_property: () => ({name: 'Bob'}) }, callback: () => { console.log('Loaded') } }).processEvent("
+ json.dumps(globals)
+ ")"
)
assert "Loaded\nHello World banana" == response.strip()

globals = {
"event": {"event": "$autocapture", "properties": {"id": "banana"}},
"groups": {},
"person": {"properties": {"name": "Bob"}},
}
response = self._execute_javascript(
result
+ "().init({ posthog: { get_property: () => ({name: 'Bob'}) }, callback: () => { console.log('Loaded') } }).processEvent("
+ json.dumps(globals)
+ ")"
)
assert "Loaded" == response.strip()

def _execute_javascript(self, js) -> str:
with tempfile.NamedTemporaryFile(delete=False) as f:
f.write(js.encode("utf-8"))
f.flush()
return subprocess.check_output(["node", f.name]).decode("utf-8")
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
FROM events LEFT JOIN (
SELECT person_id AS cohort_person_id, 1 AS matched, cohort_id
FROM static_cohort_people
WHERE in(cohort_id, [8])) AS __in_cohort ON equals(__in_cohort.cohort_person_id, person_id)
WHERE in(cohort_id, [11])) AS __in_cohort ON equals(__in_cohort.cohort_person_id, person_id)
WHERE and(1, equals(__in_cohort.matched, 1))
LIMIT 100
'''
Expand All @@ -66,7 +66,7 @@
FROM events LEFT JOIN (
SELECT person_id AS cohort_person_id, 1 AS matched, cohort_id
FROM static_cohort_people
WHERE in(cohort_id, [9])) AS __in_cohort ON equals(__in_cohort.cohort_person_id, person_id)
WHERE in(cohort_id, [12])) AS __in_cohort ON equals(__in_cohort.cohort_person_id, person_id)
WHERE and(1, equals(__in_cohort.matched, 1))
LIMIT 100
'''
Expand Down
8 changes: 4 additions & 4 deletions posthog/models/test/test_remote_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,7 @@ def test_renders_js_including_site_functions(self):
const source = (function () {let exports={};"use strict";;return exports;})();
let processEvent = undefined;
if ('onEvent' in source) {
processEvent = function processEvent(globals) {
processEvent = function processEvent(globals, posthog) {
if (!('onEvent' in source)) { return; };
const inputs = buildInputs(globals);
const filterGlobals = { ...globals.groups, ...globals.event, person: globals.person, inputs, pdi: { distinct_id: globals.event.distinct_id, person: globals.person } };
Expand All @@ -727,7 +727,7 @@ def test_renders_js_including_site_functions(self):
}
return {
processEvent: processEvent
processEvent: (globals) => processEvent(globals, posthog)
}
}
Expand All @@ -746,7 +746,7 @@ def test_renders_js_including_site_functions(self):
const source = (function () {let exports={};"use strict";;return exports;})();
let processEvent = undefined;
if ('onEvent' in source) {
processEvent = function processEvent(globals) {
processEvent = function processEvent(globals, posthog) {
if (!('onEvent' in source)) { return; };
const inputs = buildInputs(globals);
const filterGlobals = { ...globals.groups, ...globals.event, person: globals.person, inputs, pdi: { distinct_id: globals.event.distinct_id, person: globals.person } };
Expand All @@ -773,7 +773,7 @@ def test_renders_js_including_site_functions(self):
}
return {
processEvent: processEvent
processEvent: (globals) => processEvent(globals, posthog)
}
}
Expand Down

0 comments on commit daa0a27

Please sign in to comment.