From 3b21283cc0d83de764022e1aa06a99ef388a09c2 Mon Sep 17 00:00:00 2001 From: Gagan Trivedi Date: Wed, 24 Jun 2026 13:12:39 +0530 Subject: [PATCH] feat: only track exposure when experiment feature is enabled get_experiment_flag now skips the exposure event when the resolved flag is disabled, in addition to the existing DefaultFlag skip, to keep experimentation data clean. --- flagsmith/flagsmith.py | 5 +++-- tests/test_flagsmith.py | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/flagsmith/flagsmith.py b/flagsmith/flagsmith.py index c5860d8..82a9a4b 100644 --- a/flagsmith/flagsmith.py +++ b/flagsmith/flagsmith.py @@ -357,12 +357,13 @@ def get_experiment_flag( Skips the exposure event when the resolved flag is a `DefaultFlag` (i.e. the feature was not present and was served via the - `default_flag_handler`), to keep experimentation data clean. + `default_flag_handler`) or when the feature is disabled, to keep + experimentation data clean. """ if not self._event_processor: raise ValueError("Events must be enabled to use experiment flags.") flag = self.get_identity_flags(identifier, traits).get_flag(feature_name) - if isinstance(flag, Flag): + if isinstance(flag, Flag) and flag.enabled: self.track_exposure_event( feature_name=feature_name, identifier=identifier, diff --git a/tests/test_flagsmith.py b/tests/test_flagsmith.py index 6703e14..95c9605 100644 --- a/tests/test_flagsmith.py +++ b/tests/test_flagsmith.py @@ -1178,3 +1178,35 @@ def test_get_experiment_flag_falls_back_to_value_without_variant( traits=None, metadata=None, ) + + +def test_get_experiment_flag_skips_exposure_for_disabled_feature( + mocker: MockerFixture, api_key: str +) -> None: + # Given - a resolved flag for a disabled feature + config = EventProcessorConfig(events_api_url="http://test/") + flagsmith = Flagsmith( + environment_key=api_key, enable_events=True, event_processor_config=config + ) + flag = Flag( + enabled=False, + value="blue", + feature_name="checkout_v2", + feature_id=1, + variant="control", + ) + mocker.patch.object( + flagsmith, + "get_identity_flags", + return_value=Flags(flags={"checkout_v2": flag}), + ) + mock_track = mocker.patch.object(flagsmith._event_processor, "track_exposure_event") + + # When + result = flagsmith.get_experiment_flag( + feature_name="checkout_v2", identifier="user1" + ) + + # Then - the flag is returned but no exposure event is tracked + assert result is flag + mock_track.assert_not_called()