From 194e214d8795e2a74a6f883d2f930a5f9263c0b6 Mon Sep 17 00:00:00 2001 From: Evandro Myller Date: Mon, 16 Feb 2026 17:11:55 -0300 Subject: [PATCH 1/7] Sort features by segment override --- api/features/views.py | 17 ++++++++-- .../unit/features/test_unit_features_views.py | 34 +++++++++++++++++++ 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/api/features/views.py b/api/features/views.py index de01c33a700d..f541ed09070f 100644 --- a/api/features/views.py +++ b/api/features/views.py @@ -7,7 +7,7 @@ from common.projects.permissions import VIEW_PROJECT from django.conf import settings from django.core.cache import caches -from django.db.models import Max, Q, QuerySet +from django.db.models import Exists, Max, OuterRef, Q, QuerySet from django.utils import timezone from django.utils.decorators import method_decorator from django.views.decorators.cache import cache_page @@ -56,7 +56,7 @@ from .constants import INTERSECTION, UNION from .features_service import get_overrides_data -from .models import Feature, FeatureState +from .models import Feature, FeatureSegment, FeatureState from .multivariate.serializers import ( FeatureMVOptionsValuesResponseSerializer, ) @@ -224,7 +224,18 @@ def get_queryset(self): # type: ignore[no-untyped-def] "-" if query_data["sort_direction"] == "DESC" else "", query_data["sort_field"], ) - queryset = queryset.order_by(sort) + if segment_id := query_data.get("segment"): + queryset = queryset.annotate( + has_segment_override=Exists( + FeatureSegment.objects.filter( + feature=OuterRef("pk"), + segment_id=segment_id, + ) + ), + ) + queryset = queryset.order_by("-has_segment_override", sort) + else: + queryset = queryset.order_by(sort) if environment_id: page = self.paginate_queryset(queryset) diff --git a/api/tests/unit/features/test_unit_features_views.py b/api/tests/unit/features/test_unit_features_views.py index 05abbecf7562..a7cd62e4b51f 100644 --- a/api/tests/unit/features/test_unit_features_views.py +++ b/api/tests/unit/features/test_unit_features_views.py @@ -4150,6 +4150,40 @@ def test_list_features_segment_query_param_with_invalid_segment( assert feature_data["segment_feature_state"] is None +@pytest.mark.parametrize("sort_field", ["name", "created_date"]) +def test_list_features__segment_query__sorts_by_field_with_overrides_first( + admin_client_new: APIClient, + project: Project, + environment: Environment, + segment: Segment, + sort_field: str, +) -> None: + # Given + Feature.objects.create(project=project, name="feature_a") + Feature.objects.create(project=project, name="feature_b") + feature_c = Feature.objects.create(project=project, name="feature_c") + + # feature_c has a segment override + FeatureSegment.objects.create( + feature=feature_c, segment=segment, environment=environment + ) + + # When + response = admin_client_new.get( + f"/api/v1/projects/{project.id}/features/" + f"?environment={environment.id}" + f"&segment={segment.id}" + f"&sort_field={sort_field}&sort_direction=ASC" + ) + + # Then + assert response.status_code == status.HTTP_200_OK + results = response.json()["results"] + result_names = [r["name"] for r in results] + assert result_names[0] == "feature_c" + assert result_names[1:] == ["feature_a", "feature_b"] + + def test_create_multiple_features_with_metadata_keeps_metadata_isolated( admin_client_new: APIClient, project: Project, From 2f3c4a6583ff7919e8d53700c6ecf1efbae2c69e Mon Sep 17 00:00:00 2001 From: Evandro Myller Date: Mon, 16 Feb 2026 18:15:51 -0300 Subject: [PATCH 2/7] Sort features by identity override --- api/features/serializers.py | 4 +++ api/features/views.py | 16 +++++++-- .../unit/features/test_unit_features_views.py | 34 +++++++++++++++++++ frontend/web/components/pages/UserPage.tsx | 8 ++--- 4 files changed, 55 insertions(+), 7 deletions(-) diff --git a/api/features/serializers.py b/api/features/serializers.py index 134181afe3a0..41a97ffee7e2 100644 --- a/api/features/serializers.py +++ b/api/features/serializers.py @@ -95,6 +95,10 @@ class FeatureQuerySerializer(serializers.Serializer): # type: ignore[type-arg] required=False, help_text="Integer ID of the segment to retrieve segment overrides for.", ) + identity = serializers.CharField( + required=False, + help_text="ID of the identity to sort features with identity overrides first.", + ) is_enabled = serializers.BooleanField( allow_null=True, required=False, diff --git a/api/features/views.py b/api/features/views.py index f541ed09070f..116586dc9d21 100644 --- a/api/features/views.py +++ b/api/features/views.py @@ -224,6 +224,7 @@ def get_queryset(self): # type: ignore[no-untyped-def] "-" if query_data["sort_direction"] == "DESC" else "", query_data["sort_field"], ) + override_ordering: list[str] = [] if segment_id := query_data.get("segment"): queryset = queryset.annotate( has_segment_override=Exists( @@ -233,9 +234,18 @@ def get_queryset(self): # type: ignore[no-untyped-def] ) ), ) - queryset = queryset.order_by("-has_segment_override", sort) - else: - queryset = queryset.order_by(sort) + override_ordering.append("-has_segment_override") + if identity_id := query_data.get("identity"): + queryset = queryset.annotate( + has_identity_override=Exists( + FeatureState.objects.filter( + feature=OuterRef("pk"), + identity_id=identity_id, + ) + ), + ) + override_ordering.append("-has_identity_override") + queryset = queryset.order_by(*override_ordering, sort) if environment_id: page = self.paginate_queryset(queryset) diff --git a/api/tests/unit/features/test_unit_features_views.py b/api/tests/unit/features/test_unit_features_views.py index a7cd62e4b51f..be8808e885e2 100644 --- a/api/tests/unit/features/test_unit_features_views.py +++ b/api/tests/unit/features/test_unit_features_views.py @@ -4184,6 +4184,40 @@ def test_list_features__segment_query__sorts_by_field_with_overrides_first( assert result_names[1:] == ["feature_a", "feature_b"] +@pytest.mark.parametrize("sort_field", ["name", "created_date"]) +def test_list_features__identity_query__sorts_by_field_with_overrides_first( + admin_client_new: APIClient, + project: Project, + environment: Environment, + identity: Identity, + sort_field: str, +) -> None: + # Given + Feature.objects.create(project=project, name="feature_a") + Feature.objects.create(project=project, name="feature_b") + feature_c = Feature.objects.create(project=project, name="feature_c") + + # feature_c has an identity override + FeatureState.objects.create( + feature=feature_c, environment=environment, identity=identity + ) + + # When + response = admin_client_new.get( + f"/api/v1/projects/{project.id}/features/" + f"?environment={environment.id}" + f"&identity={identity.id}" + f"&sort_field={sort_field}&sort_direction=ASC" + ) + + # Then + assert response.status_code == status.HTTP_200_OK + results = response.json()["results"] + result_names = [r["name"] for r in results] + assert result_names[0] == "feature_c" + assert result_names[1:] == ["feature_a", "feature_b"] + + def test_create_multiple_features_with_metadata_keeps_metadata_isolated( admin_client_new: APIClient, project: Project, diff --git a/frontend/web/components/pages/UserPage.tsx b/frontend/web/components/pages/UserPage.tsx index cbb1a27315cb..7775d68e747a 100644 --- a/frontend/web/components/pages/UserPage.tsx +++ b/frontend/web/components/pages/UserPage.tsx @@ -88,9 +88,9 @@ const UserPage: FC = () => { true, search, sort, - getServerFilter(filter), + { ...getServerFilter(filter), identity: id }, ) - }, [filter, environmentId, projectId]) + }, [filter, environmentId, projectId, id]) useEffect(() => { AppActions.getIdentity(environmentId, id) @@ -141,10 +141,10 @@ const UserPage: FC = () => { search, sort, pageNumber, - getServerFilter(filter), + { ...getServerFilter(filter), identity: id }, ) }, - [environmentId, projectId, filter], + [environmentId, projectId, filter, id], ) return ( From 36917da24b1bb17334f7c743239f626b023f4d2b Mon Sep 17 00:00:00 2001 From: Evandro Myller Date: Tue, 17 Feb 2026 14:18:37 -0300 Subject: [PATCH 3/7] Fix sorting based on segment overrides --- api/features/views.py | 3 ++- api/tests/unit/features/test_unit_features_views.py | 11 +++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/api/features/views.py b/api/features/views.py index 116586dc9d21..3e753537aabb 100644 --- a/api/features/views.py +++ b/api/features/views.py @@ -225,12 +225,13 @@ def get_queryset(self): # type: ignore[no-untyped-def] query_data["sort_field"], ) override_ordering: list[str] = [] - if segment_id := query_data.get("segment"): + if environment_id and (segment_id := query_data.get("segment")): queryset = queryset.annotate( has_segment_override=Exists( FeatureSegment.objects.filter( feature=OuterRef("pk"), segment_id=segment_id, + environment_id=environment_id, ) ), ) diff --git a/api/tests/unit/features/test_unit_features_views.py b/api/tests/unit/features/test_unit_features_views.py index be8808e885e2..cc50ddb6f5e9 100644 --- a/api/tests/unit/features/test_unit_features_views.py +++ b/api/tests/unit/features/test_unit_features_views.py @@ -4160,13 +4160,20 @@ def test_list_features__segment_query__sorts_by_field_with_overrides_first( ) -> None: # Given Feature.objects.create(project=project, name="feature_a") - Feature.objects.create(project=project, name="feature_b") + feature_b = Feature.objects.create(project=project, name="feature_b") feature_c = Feature.objects.create(project=project, name="feature_c") + other_environment = Environment.objects.create( + project=project, name="other_environment" + ) - # feature_c has a segment override + # feature_c has a segment override in the requested environment FeatureSegment.objects.create( feature=feature_c, segment=segment, environment=environment ) + # feature_b has a segment override in a different environment + FeatureSegment.objects.create( + feature=feature_b, segment=segment, environment=other_environment + ) # When response = admin_client_new.get( From 520db304b21a6818ae0c65afe00291c252a73aca Mon Sep 17 00:00:00 2001 From: Evandro Myller Date: Tue, 17 Feb 2026 14:44:37 -0300 Subject: [PATCH 4/7] Fix identity URI param --- api/features/serializers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/features/serializers.py b/api/features/serializers.py index 41a97ffee7e2..d4bcb387b027 100644 --- a/api/features/serializers.py +++ b/api/features/serializers.py @@ -95,9 +95,9 @@ class FeatureQuerySerializer(serializers.Serializer): # type: ignore[type-arg] required=False, help_text="Integer ID of the segment to retrieve segment overrides for.", ) - identity = serializers.CharField( + identity = serializers.IntegerField( required=False, - help_text="ID of the identity to sort features with identity overrides first.", + help_text="Integer ID of the identity to sort features with identity overrides first.", ) is_enabled = serializers.BooleanField( allow_null=True, From ec88a8231d0ebb7b5d891ba88498a20e3fb79b3a Mon Sep 17 00:00:00 2001 From: Evandro Myller Date: Fri, 20 Feb 2026 14:56:13 -0300 Subject: [PATCH 5/7] Sort features by **edge** identity overrides --- .../identities/edge_identity_service.py | 14 +++++- api/features/serializers.py | 4 +- api/features/views.py | 46 +++++++++++++++---- .../unit/features/test_unit_features_views.py | 36 +++++++++++++++ 4 files changed, 87 insertions(+), 13 deletions(-) diff --git a/api/edge_api/identities/edge_identity_service.py b/api/edge_api/identities/edge_identity_service.py index e269747a57b6..e66b57fca833 100644 --- a/api/edge_api/identities/edge_identity_service.py +++ b/api/edge_api/identities/edge_identity_service.py @@ -1,10 +1,16 @@ -from environments.dynamodb import DynamoEnvironmentV2Wrapper +from flag_engine.identities.models import IdentityModel + +from environments.dynamodb import ( + DynamoEnvironmentV2Wrapper, + DynamoIdentityWrapper, +) from environments.dynamodb.types import ( IdentityOverridesV2List, IdentityOverrideV2, ) ddb_environment_v2_wrapper = DynamoEnvironmentV2Wrapper() +ddb_identity_wrapper = DynamoIdentityWrapper() def get_edge_identity_overrides( @@ -53,3 +59,9 @@ def get_edge_identity_overrides_for_feature_ids( ) return results + + +def get_overridden_feature_ids_for_edge_identity(identity_uuid: str) -> set[int]: + identity_document = ddb_identity_wrapper.get_item_from_uuid_or_404(identity_uuid) + identity_model = IdentityModel.model_validate(identity_document) + return {fs.feature.id for fs in identity_model.identity_features} diff --git a/api/features/serializers.py b/api/features/serializers.py index d4bcb387b027..41a97ffee7e2 100644 --- a/api/features/serializers.py +++ b/api/features/serializers.py @@ -95,9 +95,9 @@ class FeatureQuerySerializer(serializers.Serializer): # type: ignore[type-arg] required=False, help_text="Integer ID of the segment to retrieve segment overrides for.", ) - identity = serializers.IntegerField( + identity = serializers.CharField( required=False, - help_text="Integer ID of the identity to sort features with identity overrides first.", + help_text="ID of the identity to sort features with identity overrides first.", ) is_enabled = serializers.BooleanField( allow_null=True, diff --git a/api/features/views.py b/api/features/views.py index 3e753537aabb..4d8e6027ba05 100644 --- a/api/features/views.py +++ b/api/features/views.py @@ -7,7 +7,17 @@ from common.projects.permissions import VIEW_PROJECT from django.conf import settings from django.core.cache import caches -from django.db.models import Exists, Max, OuterRef, Q, QuerySet +from django.db.models import ( + BooleanField, + Case, + Exists, + Max, + OuterRef, + Q, + QuerySet, + Value, + When, +) from django.utils import timezone from django.utils.decorators import method_decorator from django.views.decorators.cache import cache_page @@ -35,6 +45,9 @@ from app_analytics.throttles import InfluxQueryThrottle from core.constants import FLAGSMITH_UPDATED_AT_HEADER, SDK_ENVIRONMENT_KEY_HEADER from core.request_origin import RequestOrigin +from edge_api.identities.edge_identity_service import ( + get_overridden_feature_ids_for_edge_identity, +) from environments.authentication import EnvironmentKeyAuthentication from environments.identities.models import Identity from environments.identities.serializers import ( @@ -236,15 +249,28 @@ def get_queryset(self): # type: ignore[no-untyped-def] ), ) override_ordering.append("-has_segment_override") - if identity_id := query_data.get("identity"): - queryset = queryset.annotate( - has_identity_override=Exists( - FeatureState.objects.filter( - feature=OuterRef("pk"), - identity_id=identity_id, - ) - ), - ) + if identity := query_data.get("identity"): + if project.enable_dynamo_db: + # Bounded by Project.max_features_allowed + override_feature_ids = get_overridden_feature_ids_for_edge_identity( + identity + ) + queryset = queryset.annotate( + has_identity_override=Case( + When(pk__in=override_feature_ids, then=Value(True)), + default=Value(False), + output_field=BooleanField(), + ), + ) + else: + queryset = queryset.annotate( + has_identity_override=Exists( + FeatureState.objects.filter( + feature=OuterRef("pk"), + identity_id=identity, + ) + ), + ) override_ordering.append("-has_identity_override") queryset = queryset.order_by(*override_ordering, sort) diff --git a/api/tests/unit/features/test_unit_features_views.py b/api/tests/unit/features/test_unit_features_views.py index cc50ddb6f5e9..71aaba110ae5 100644 --- a/api/tests/unit/features/test_unit_features_views.py +++ b/api/tests/unit/features/test_unit_features_views.py @@ -4225,6 +4225,42 @@ def test_list_features__identity_query__sorts_by_field_with_overrides_first( assert result_names[1:] == ["feature_a", "feature_b"] +@pytest.mark.parametrize("sort_field", ["name", "created_date"]) +def test_list_features__edge_identity_query__sorts_with_overrides_first( + admin_client_new: APIClient, + project: Project, + environment: Environment, + sort_field: str, + mocker: MockerFixture, +) -> None: + # Given + project.enable_dynamo_db = True + project.save() + + Feature.objects.create(project=project, name="feature_a") + feature_b = Feature.objects.create(project=project, name="feature_b") + Feature.objects.create(project=project, name="feature_c") + mocker.patch.object( + views, + "get_overridden_feature_ids_for_edge_identity", + return_value={feature_b.id}, + ) + + # When + response = admin_client_new.get( + f"/api/v1/projects/{project.id}/features/" + f"?environment={environment.id}" + f"&identity=59efa2a7-6a45-46d6-b953-a7073a90eacf" + f"&sort_field={sort_field}&sort_direction=ASC" + ) + + # Then + assert response.status_code == status.HTTP_200_OK + results = response.json()["results"] + result_names = [r["name"] for r in results] + assert result_names == ["feature_b", "feature_a", "feature_c"] + + def test_create_multiple_features_with_metadata_keeps_metadata_isolated( admin_client_new: APIClient, project: Project, From 2c612c94116ad5482b676b6d2919e6a2f9ce9edd Mon Sep 17 00:00:00 2001 From: Evandro Myller Date: Fri, 20 Feb 2026 14:59:25 -0300 Subject: [PATCH 6/7] Trim tests nails --- .../identities/edge_identity_service.py | 17 ++- .../identities/test_edge_identity_service.py | 104 ++++++++++++++++++ .../unit/features/test_unit_features_views.py | 22 ++-- 3 files changed, 121 insertions(+), 22 deletions(-) create mode 100644 api/tests/unit/edge_api/identities/test_edge_identity_service.py diff --git a/api/edge_api/identities/edge_identity_service.py b/api/edge_api/identities/edge_identity_service.py index e66b57fca833..ce5cef2d067a 100644 --- a/api/edge_api/identities/edge_identity_service.py +++ b/api/edge_api/identities/edge_identity_service.py @@ -1,16 +1,11 @@ -from flag_engine.identities.models import IdentityModel - -from environments.dynamodb import ( - DynamoEnvironmentV2Wrapper, - DynamoIdentityWrapper, -) +from edge_api.identities.models import EdgeIdentity +from environments.dynamodb import DynamoEnvironmentV2Wrapper from environments.dynamodb.types import ( IdentityOverridesV2List, IdentityOverrideV2, ) ddb_environment_v2_wrapper = DynamoEnvironmentV2Wrapper() -ddb_identity_wrapper = DynamoIdentityWrapper() def get_edge_identity_overrides( @@ -62,6 +57,8 @@ def get_edge_identity_overrides_for_feature_ids( def get_overridden_feature_ids_for_edge_identity(identity_uuid: str) -> set[int]: - identity_document = ddb_identity_wrapper.get_item_from_uuid_or_404(identity_uuid) - identity_model = IdentityModel.model_validate(identity_document) - return {fs.feature.id for fs in identity_model.identity_features} + identity_document = EdgeIdentity.dynamo_wrapper.get_item_from_uuid_or_404( + identity_uuid + ) + identity = EdgeIdentity.from_identity_document(identity_document) + return {fs.feature.id for fs in identity.feature_overrides} diff --git a/api/tests/unit/edge_api/identities/test_edge_identity_service.py b/api/tests/unit/edge_api/identities/test_edge_identity_service.py new file mode 100644 index 000000000000..f2dc3f398f37 --- /dev/null +++ b/api/tests/unit/edge_api/identities/test_edge_identity_service.py @@ -0,0 +1,104 @@ +from unittest.mock import MagicMock + +import pytest +from pytest_mock import MockerFixture + +from edge_api.identities.edge_identity_service import ( + get_overridden_feature_ids_for_edge_identity, +) + + +@pytest.fixture() +def _mock_ddb_identity_wrapper(mocker: MockerFixture) -> MagicMock: + return mocker.patch( + "edge_api.identities.models.EdgeIdentity.dynamo_wrapper", + ) + + +def _make_identity_document( + *, + environment_api_key: str, + identity_features: list[dict], # type: ignore[type-arg] +) -> dict: # type: ignore[type-arg] + return { + "composite_key": f"{environment_api_key}_test_user", + "identity_traits": [], + "identity_features": identity_features, + "identifier": "test_user", + "created_date": "2021-09-21T10:12:42.230257+00:00", + "environment_api_key": environment_api_key, + "identity_uuid": "59efa2a7-6a45-46d6-b953-a7073a90eacf", + "django_id": None, + } + + +def test_get_overridden_feature_ids_for_edge_identity__identity_with_overrides__returns_feature_ids( + _mock_ddb_identity_wrapper: MagicMock, +) -> None: + # Given + feature_a_id = 101 + feature_b_id = 202 + identity_document = _make_identity_document( + environment_api_key="test_key", + identity_features=[ + { + "feature": { + "id": feature_a_id, + "name": "feature_a", + "type": "STANDARD", + }, + "enabled": True, + "featurestate_uuid": "a7495917-ee57-41d1-a64e-e0697dbc57fb", + "feature_state_value": None, + "feature_segment": None, + "multivariate_feature_state_values": [], + }, + { + "feature": { + "id": feature_b_id, + "name": "feature_b", + "type": "STANDARD", + }, + "enabled": False, + "featurestate_uuid": "b8506028-ff68-42e2-b75f-f1708ecd68fc", + "feature_state_value": None, + "feature_segment": None, + "multivariate_feature_state_values": [], + }, + ], + ) + _mock_ddb_identity_wrapper.get_item_from_uuid_or_404.return_value = ( + identity_document + ) + + # When + result = get_overridden_feature_ids_for_edge_identity( + "59efa2a7-6a45-46d6-b953-a7073a90eacf" + ) + + # Then + assert result == {feature_a_id, feature_b_id} + _mock_ddb_identity_wrapper.get_item_from_uuid_or_404.assert_called_once_with( + "59efa2a7-6a45-46d6-b953-a7073a90eacf" + ) + + +def test_get_overridden_feature_ids_for_edge_identity__identity_without_overrides__returns_empty_set( + _mock_ddb_identity_wrapper: MagicMock, +) -> None: + # Given + identity_document = _make_identity_document( + environment_api_key="test_key", + identity_features=[], + ) + _mock_ddb_identity_wrapper.get_item_from_uuid_or_404.return_value = ( + identity_document + ) + + # When + result = get_overridden_feature_ids_for_edge_identity( + "59efa2a7-6a45-46d6-b953-a7073a90eacf" + ) + + # Then + assert result == set() diff --git a/api/tests/unit/features/test_unit_features_views.py b/api/tests/unit/features/test_unit_features_views.py index 71aaba110ae5..983f4b94a74a 100644 --- a/api/tests/unit/features/test_unit_features_views.py +++ b/api/tests/unit/features/test_unit_features_views.py @@ -4185,10 +4185,9 @@ def test_list_features__segment_query__sorts_by_field_with_overrides_first( # Then assert response.status_code == status.HTTP_200_OK - results = response.json()["results"] - result_names = [r["name"] for r in results] - assert result_names[0] == "feature_c" - assert result_names[1:] == ["feature_a", "feature_b"] + assert ["feature_c", "feature_a", "feature_b"] == [ + f["name"] for f in response.json()["results"] + ] @pytest.mark.parametrize("sort_field", ["name", "created_date"]) @@ -4219,14 +4218,13 @@ def test_list_features__identity_query__sorts_by_field_with_overrides_first( # Then assert response.status_code == status.HTTP_200_OK - results = response.json()["results"] - result_names = [r["name"] for r in results] - assert result_names[0] == "feature_c" - assert result_names[1:] == ["feature_a", "feature_b"] + assert ["feature_c", "feature_a", "feature_b"] == [ + f["name"] for f in response.json()["results"] + ] @pytest.mark.parametrize("sort_field", ["name", "created_date"]) -def test_list_features__edge_identity_query__sorts_with_overrides_first( +def test_list_features__edge_identity_query__sorts_by_field_with_overrides_first( admin_client_new: APIClient, project: Project, environment: Environment, @@ -4256,9 +4254,9 @@ def test_list_features__edge_identity_query__sorts_with_overrides_first( # Then assert response.status_code == status.HTTP_200_OK - results = response.json()["results"] - result_names = [r["name"] for r in results] - assert result_names == ["feature_b", "feature_a", "feature_c"] + assert ["feature_b", "feature_a", "feature_c"] == [ + f["name"] for f in response.json()["results"] + ] def test_create_multiple_features_with_metadata_keeps_metadata_isolated( From 71738c028486dced596e9793ee54867642a6b7e7 Mon Sep 17 00:00:00 2001 From: Evandro Myller Date: Fri, 20 Feb 2026 19:06:42 -0300 Subject: [PATCH 7/7] Reorder clicks in e2e tests --- frontend/e2e/tests/segment-test.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/frontend/e2e/tests/segment-test.ts b/frontend/e2e/tests/segment-test.ts index 916cb257af27..15e2916afc79 100644 --- a/frontend/e2e/tests/segment-test.ts +++ b/frontend/e2e/tests/segment-test.ts @@ -258,7 +258,8 @@ export const testSegment3 = async () => { await click(byId('user-feature-switch-1-on')) await click('#confirm-toggle-feature-btn') await waitAndRefresh() // wait and refresh to avoid issues with data sync from UK -> US in github workflows - await waitForElementVisible(byId('user-feature-switch-1-off')) + // After toggling, 'flag' has an identity override and sorts first (index 0). + await waitForElementVisible(byId('user-feature-switch-0-off')) log('Edit flag for user') await click(byId('user-feature-0')) @@ -268,8 +269,8 @@ export const testSegment3 = async () => { await assertTextContent(byId('user-feature-value-0'), '"small"') log('Toggle flag for user again') - await click(byId('user-feature-switch-1-off')) + await click(byId('user-feature-switch-0-off')) await click('#confirm-toggle-feature-btn') await waitAndRefresh() // wait and refresh to avoid issues with data sync from UK -> US in github workflows - await waitForElementVisible(byId('user-feature-switch-1-on')) + await waitForElementVisible(byId('user-feature-switch-0-on')) }