Skip to content

Commit

Permalink
chore: Return identiy feature states data on endpoints response
Browse files Browse the repository at this point in the history
Apply additional code optimisations.
  • Loading branch information
novakzaballa committed Apr 24, 2024
1 parent d59c38c commit 9112d97
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 68 deletions.
20 changes: 19 additions & 1 deletion api/edge_api/identities/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,25 @@ def clone_from_given_identity(self, request, *args, **kwargs) -> Response:
user=request.user.id,
master_api_key=getattr(request, "master_api_key", None),
)
return Response(status=status.HTTP_200_OK)

# Prepare response
(
feature_states,
identity_feature_names,
) = self.identity.get_all_feature_states()

serializer = IdentityAllFeatureStatesSerializer(
instance=feature_states,
many=True,
context={
"request": request,
"identity": self.identity,
"environment_api_key": self.identity.environment_api_key,
"identity_feature_names": identity_feature_names,
},
)

return Response(serializer.data)


class EdgeIdentityWithIdentifierFeatureStateView(APIView):
Expand Down
14 changes: 13 additions & 1 deletion api/features/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,19 @@ def clone_from_given_identity(self, request, *args, **kwargs) -> Response:
target_identity=target_identity, source_identity=source_identity
)

return Response(status=status.HTTP_200_OK)
# Prepare response
feature_states = target_identity.get_all_feature_states()
serializer_target = IdentityAllFeatureStatesSerializer(
instance=feature_states,
many=True,
context={
"request": request,
"identity": target_identity,
"environment_api_key": target_identity.environment.api_key,
},
)

return Response(data=serializer_target.data)


@method_decorator(
Expand Down
20 changes: 0 additions & 20 deletions api/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import typing

import pytest
from mypy_boto3_dynamodb.service_resource import DynamoDBServiceResource, Table
from pytest_django.fixtures import SettingsWrapper
Expand Down Expand Up @@ -113,21 +111,3 @@ def app_settings_for_dynamodb(
settings.ENVIRONMENTS_V2_TABLE_NAME_DYNAMO = flagsmith_environments_v2_table.name
settings.IDENTITIES_TABLE_NAME_DYNAMO = flagsmith_identities_table.name
return


@pytest.fixture()
def features_for_identity_clone_flag_states_from() -> (
typing.Callable[[Project], tuple[Feature, ...]]
):
def make(project: Project) -> tuple[Feature, ...]:
# Create 3 features
features: list[Feature] = []
for i in range(1, 4):
features.append(
Feature.objects.create(
name=f"feature_{i}", project=project, default_enabled=True
)
)
return tuple(features)

return make
Original file line number Diff line number Diff line change
Expand Up @@ -1053,9 +1053,6 @@ def test_edge_identity_clone_flag_states_from(
dynamo_enabled_project: int,
environment_api_key: str,
flagsmith_identities_table: Table,
features_for_identity_clone_flag_states_from: typing.Callable[
[Project], tuple[Feature, ...]
],
) -> None:
def create_identity(identifier: str) -> EdgeIdentity:
identity_model = IdentityModel(
Expand All @@ -1066,11 +1063,19 @@ def create_identity(identifier: str) -> EdgeIdentity:
)
return EdgeIdentity(engine_identity_model=identity_model)

# GIVEN
def features_for_identity_clone_flag_states_from(project: Project) -> tuple[Feature, ...]:
features: list[Feature] = []
for i in range(1, 4):
features.append(
Feature.objects.create(
name=f"feature_{i}", project=project, default_enabled=True
)
)
return tuple(features)

# Given
project: Project = Project.objects.get(id=dynamo_enabled_project)

# Create 3 features
feature_1, feature_2, feature_3 = features_for_identity_clone_flag_states_from(
project
)
Expand All @@ -1079,12 +1084,9 @@ def create_identity(identifier: str) -> EdgeIdentity:
feature_model_2: FeatureModel = map_feature_to_engine(feature=feature_2)
feature_model_3: FeatureModel = map_feature_to_engine(feature=feature_3)

# Create source and target identities
source_identity: EdgeIdentity = create_identity(identifier="source_identity")
target_identity: EdgeIdentity = create_identity(identifier="target_identity")

# Create 2 feature states for source identity for feature 1 and feature 2

source_feature_state_1_value = "Source Identity for feature value 1"
source_feature_state_1 = FeatureStateModel(
feature=feature_model_1,
Expand All @@ -1101,7 +1103,6 @@ def create_identity(identifier: str) -> EdgeIdentity:
feature_state_value=source_feature_state_2_value,
)

# Create 2 feature states for target identity for feature 2 and feature 3
target_feature_state_2_value = "Target Identity value for feature 2"
target_feature_state_2 = FeatureStateModel(
feature=feature_model_2,
Expand All @@ -1121,7 +1122,6 @@ def create_identity(identifier: str) -> EdgeIdentity:
source_identity.add_feature_override(feature_state=source_feature_state_2)

# Add feature states for features 2 and 3 to target identity.
# This feature state must be deleted as part of the cloning process.
target_identity.add_feature_override(feature_state=target_feature_state_2)
target_identity.add_feature_override(feature_state=target_feature_state_3)

Expand All @@ -1136,14 +1136,9 @@ def create_identity(identifier: str) -> EdgeIdentity:
viewname="api-v1:environments:edge-identity-featurestates-clone-from-given-identity",
args=(environment_api_key, target_identity.identity_uuid),
)
get_all_feature_states_url: str = reverse(
viewname="api-v1:environments:edge-identity-featurestates-all",
args=(environment_api_key, target_identity.identity_uuid),
)

# WHEN
# When

# Clone feature states from source identity to target identity
clone_identity_feature_states_response = admin_client.post(
path=clone_from_given_identity_url,
data=json.dumps(
Expand All @@ -1152,22 +1147,15 @@ def create_identity(identifier: str) -> EdgeIdentity:
content_type="application/json",
)

# Get current feature states for fixture target identity
get_feature_states_response = admin_client.get(path=get_all_feature_states_url)

# THEN
# Then

# Assert API calls responses status are HTTP OK (200)
assert clone_identity_feature_states_response.status_code == status.HTTP_200_OK
assert get_feature_states_response.status_code == status.HTTP_200_OK

# Assert target identity contains only the 2 cloned features states
response = get_feature_states_response.json()
response = clone_identity_feature_states_response.json()

# Assert target identity contains only the 2 cloned overridden features states and 1 environment feature state
# Target identity contains only the 2 cloned overridden features states and 1 environment feature state
assert len(response) == 3

# Assert cloned data is correct
assert response[0]["feature"]["id"] == feature_1.id
assert response[0]["enabled"] == source_feature_state_1.enabled
assert response[0]["feature_state_value"] == source_feature_state_1_value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
UPDATE_FEATURE_STATE,
VIEW_ENVIRONMENT,
)
from features.models import FeatureState, FeatureStateValue
from features.models import Feature, FeatureState, FeatureStateValue
from projects.models import Project
from tests.unit.environments.helpers import get_environment_user_client

Expand Down Expand Up @@ -118,24 +118,30 @@ def test_identity_clone_flag_states_from(
project: Project,
environment: Environment,
admin_client: Client,
features_for_identity_clone_flag_states_from: typing.Callable,
) -> None:
# GIVEN

# Create 3 features
def features_for_identity_clone_flag_states_from(project: Project) -> tuple[Feature, ...]:
features: list[Feature] = []
for i in range(1, 4):
features.append(
Feature.objects.create(
name=f"feature_{i}", project=project, default_enabled=True
)
)
return tuple(features)

# Given
feature_1, feature_2, feature_3 = features_for_identity_clone_flag_states_from(
project
)

# Create source and target identities
source_identity: Identity = Identity.objects.create(
identifier="source_identity", environment=environment
)
target_identity: Identity = Identity.objects.create(
identifier="target_identity", environment=environment
)

# Create 2 feature states for source identity for feature 1 and feature 2
source_feature_state_1: FeatureState = FeatureState.objects.create(
feature=feature_1,
environment=environment,
Expand All @@ -158,7 +164,6 @@ def test_identity_clone_flag_states_from(
string_value=source_feature_state_2_value
)

# Create 2 feature states for target identity for feature 2 and feature 3
target_feature_state_2: FeatureState = FeatureState.objects.create(
feature=feature_2,
environment=environment,
Expand Down Expand Up @@ -187,26 +192,19 @@ def test_identity_clone_flag_states_from(
args=[environment.api_key, target_identity.id],
)

# WHEN

# When
clone_identity_feature_states_response = admin_client.post(
clone_identity_feature_states_url,
data=json.dumps({"source_identity_id": str(source_identity.id)}),
content_type="application/json",
)

# And getting feature states for target identity
get_feature_states_response = admin_client.get(get_feature_states_url)

# THEN

# Assert API calls responses status are HTTP OK (200)
# Then
assert clone_identity_feature_states_response.status_code == status.HTTP_200_OK
assert get_feature_states_response.status_code == status.HTTP_200_OK

response = get_feature_states_response.json()
response = clone_identity_feature_states_response.json()

# Assert target identity contains only the 2 cloned overridden features states and 1 environment feature state
# Target identity contains only the 2 cloned overridden features states and 1 environment feature state
assert len(response) == 3

# Assert cloned data is correct
Expand All @@ -225,8 +223,7 @@ def test_identity_clone_flag_states_from(
assert response[2]["feature_state_value"] == feature_3.initial_value
assert response[2]["overridden_by"] is None

# Assert target identity feature 3 override has been removed
# since it was not present in source identity
# Target identity feature 3 override has been removed
assert not FeatureState.objects.filter(
feature=feature_3,
environment=environment,
Expand Down

0 comments on commit 9112d97

Please sign in to comment.