fix(context): forward all BucketingAttributes to ExperienceManager - #382
Merged
JosephSamirL merged 1 commit intoMay 21, 2026
Merged
Conversation
Context.runExperience and Context.runExperiences rebuilt a fresh attributes object with only four hardcoded keys (visitorProperties, locationProperties, updateVisitorProperties, environment) before forwarding to ExperienceManager.selectVariation/selectVariations. This silently dropped every other BucketingAttributes field — enableTracking, forceVariationId, ignoreLocationProperties, typeCasting, experienceKeys — so callers opting out of tracking, forcing a variation, or ignoring location targeting were silently ignored. DataManager._getBucketingByField destructures these by name with enableTracking defaulting to `true`, which is how the opt-out was being lost. Switch to spread-then-override so all caller-supplied attributes pass through while still applying the two transforms Context must do: merging visitorProperties via getVisitorProperties() and defaulting environment to the Context's own environment. Add tests covering forwarding of enableTracking, forceVariationId, ignoreLocationProperties, and updateVisitorProperties through both runExperience and runExperiences. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
There was a problem hiding this comment.
Code Review
This pull request updates the Context class to forward all attributes to the ExperienceManager using the spread operator, enabling support for properties like enableTracking and forceVariationId. Corresponding tests were added to verify this behavior. However, feedback indicates that the Context layer still emits SystemEvents.BUCKETING events even when enableTracking is set to false. It is recommended to conditionally suppress these events based on the attribute flag and to update the test suite to verify this suppression.
3 tasks
JosephSamirL
approved these changes
May 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Summary
Context.runExperienceandContext.runExperiencesrebuilt a fresh attributes object with only four hardcoded keys (visitorProperties,locationProperties,updateVisitorProperties,environment) before forwarding toExperienceManager.selectVariation/selectVariations. Every otherBucketingAttributesfield —enableTracking,forceVariationId,ignoreLocationProperties,typeCasting,experienceKeys— was silently dropped.The most user-visible consequence: a caller invoking
context.runExperience(key, { enableTracking: false })still fires the bucketing track event, because by the time the call reachesDataManager._getBucketingByField(which destructuresenableTracking = trueas a default), the field has been discarded one layer up. Same forforceVariationId(the forced variation was never honored) andignoreLocationProperties.Root cause
A whitelist-then-rebuild pattern in
Contextinstead of spread-then-override. Two transforms must happen at the Context layer:visitorPropertiesmust be merged with stored visitor props viagetVisitorProperties().environmentmust default tothis._environmentwhen the caller omits it.Everything else can pass through unmodified; downstream destructures by name and ignores unknown keys.
Fix
Applied identically to
runExperience(line 135) andrunExperiences(line 190).{...undefined}evaluates to{}in JS, so the optional-attributes case is safe.Tests
Added two cases in
packages/js-sdk/tests/context.tests.ts:Should forward BucketingAttributes (enableTracking, forceVariationId, ignoreLocationProperties) through runExperienceShould forward BucketingAttributes (enableTracking, forceVariationId, ignoreLocationProperties) through runExperiencesBoth monkey-patch
experienceManager.selectVariation/selectVariationsto capture the attributes argument, then assert the previously-dropped fields are forwarded. UseenableTracking: falseto suppress the tracking request so the tests stay deterministic.Test plan
yarn test:mochafrompackages/js-sdk/— 143 passing, 0 failingyarn lintinpackages/js-sdk/— cleanShoud successfully get variation from specific experienceandShoud successfully get variations across all experiencesstill pass (no regression in the standard path)Notes
BucketingAttributestype all along.BucketingAttributestyping,DataManager,ExperienceManager, or any downstream layer.🤖 Generated with Claude Code