Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion api/integrations/mixpanel/mixpanel.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,13 @@ def generate_user_data(

for feature_state in feature_states:
value = feature_state.get_feature_state_value(identity=identity)
# enabled + value set (incl. falsy like 0 or "") -> value
# enabled + value is None -> True
# disabled -> False
feature_properties[feature_state.feature.name] = (
value if (feature_state.enabled and value) else feature_state.enabled
value
if (feature_state.enabled and value is not None)
else feature_state.enabled
Comment thread
coderabbitai[bot] marked this conversation as resolved.
)

return [
Expand Down
7 changes: 6 additions & 1 deletion api/integrations/rudderstack/rudderstack.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,13 @@ def generate_user_data(

for feature_state in feature_states:
value = feature_state.get_feature_state_value(identity=identity)
# enabled + value set (incl. falsy like 0 or "") -> value
# enabled + value is None -> True
# disabled -> False
feature_properties[feature_state.feature.name] = (
value if (feature_state.enabled and value) else feature_state.enabled
value
if (feature_state.enabled and value is not None)
else feature_state.enabled
)

return {
Expand Down
77 changes: 75 additions & 2 deletions api/tests/unit/integrations/mixpanel/test_unit_mixpanel.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import typing
from logging import DEBUG
from typing import TYPE_CHECKING

Expand All @@ -13,7 +14,7 @@

from environments.identities.models import Identity
from environments.models import Environment
from features.models import Feature
from features.models import Feature, FeatureState
from projects.models import Project


Expand Down Expand Up @@ -140,7 +141,9 @@ def test_mixpanel_generate_user_data__identity_with_features__returns_expected_f
for feature_state in feature_states:
value = feature_state.get_feature_state_value()
feature_properties[feature_state.feature.name] = (
value if (feature_state.enabled and value) else feature_state.enabled
value
if (feature_state.enabled and value is not None)
else feature_state.enabled
)

expected_user_data = [
Expand Down Expand Up @@ -199,3 +202,73 @@ def test_identify_integrations__mixpanel_configured__posts_to_expected_url(
# Then
assert mocked_post.call_args.args[0] == expected_url
assert mocked_post.call_args.kwargs["json"][0]["$token"] == api_key


@pytest.mark.django_db
@pytest.mark.parametrize(
"feature_state_with_value,expected_property_value",
[
(False, False),
(True, True),
("foo", "foo"),
(1, 1),
(0, 0),
("", ""),
(None, True),
],
indirect=["feature_state_with_value"],
)
def test_mixpanel_generate_user_data__falsy_values__returns_value_not_enabled_state(
expected_property_value: typing.Any,
environment: "Environment",
feature_state: "FeatureState",
feature_state_with_value: "FeatureState",
identity: "Identity",
) -> None:
# Given
config = MixpanelConfiguration(api_key="123key")
mixpanel = MixpanelWrapper(config)

# When
user_data = mixpanel.generate_user_data(
identity=identity,
feature_states=[feature_state, feature_state_with_value],
trait_models=[],
)

# Then
expected_user_data = [
{
"$token": config.api_key,
"$distinct_id": identity.identifier,
"$set": {
feature_state.feature.name: feature_state.enabled,
feature_state_with_value.feature.name: expected_property_value,
},
"$ip": "0",
}
]
assert user_data == expected_user_data


@pytest.mark.django_db
def test_mixpanel_generate_user_data__disabled_flag__returns_enabled_state(
feature: "Feature",
environment: "Environment",
identity: "Identity",
) -> None:
# Given
config = MixpanelConfiguration(api_key="123key")
mixpanel = MixpanelWrapper(config)
feature_states = [*feature.feature_states.all()]

# When
user_data = mixpanel.generate_user_data(
identity=identity,
feature_states=feature_states,
trait_models=[],
)

# Then
# Default feature is not enabled, so the value should be False
assert user_data[0]["$set"][feature.name] is False
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import typing

import pytest

from environments.identities.models import Identity
from environments.models import Environment
from features.models import Feature, FeatureState
Expand Down Expand Up @@ -27,3 +31,46 @@ def test_rudderstack_generate_user_data__valid_identity__returns_expected_data(
"user_id": identity.identifier,
"traits": {feature.name: False},
}


@pytest.mark.django_db
@pytest.mark.parametrize(
"feature_state_with_value,expected_property_value",
[
(False, False),
(True, True),
("foo", "foo"),
(1, 1),
(0, 0),
("", ""),
(None, True),
],
indirect=["feature_state_with_value"],
)
def test_rudderstack_generate_user_data__falsy_values__returns_value_not_enabled_state(
expected_property_value: typing.Any,
environment: Environment,
feature_state: FeatureState,
feature_state_with_value: FeatureState,
identity: Identity,
) -> None:
# Given
config = RudderstackConfiguration(
api_key="123key", base_url="https://api.rudderstack.com/"
)
rudderstack_wrapper = RudderstackWrapper(config)

# When
user_data = rudderstack_wrapper.generate_user_data(
identity=identity,
feature_states=[feature_state, feature_state_with_value],
)

# Then
assert user_data == {
"user_id": identity.identifier,
"traits": {
feature_state.feature.name: feature_state.enabled,
feature_state_with_value.feature.name: expected_property_value,
},
}
Loading