Repository: Unleash/unleash-client-go
Pull request #93 (2021-09-29 11:58:53)

fix: Make GetVariant call use custom context.
fixes: #92


Patch:
diff --git a/client.go b/client.go
index e1a2259..e804093 100644
--- a/client.go
+++ b/client.go
@@ -297,23 +297,22 @@ func (uc *Client) isEnabled(feature string, options ...FeatureOption) (enabled b
 // It is safe to call this method from multiple goroutines concurrently.
 func (uc *Client) GetVariant(feature string, options ...VariantOption) *api.Variant {
 	defaultVariant := api.GetDefaultVariant()
-
-	if !uc.isEnabled(feature) {
-		return defaultVariant;
-	}
-
-	f := uc.repository.getToggle(feature)
-
 	var opts variantOption
 	for _, o := range options {
 		o(&opts)
 	}
 
 	ctx := uc.staticContext
-	if (opts.ctx != nil) {
+	if opts.ctx != nil {
 		ctx = ctx.Override(*opts.ctx)
 	}
 
+	if !uc.isEnabled(feature, WithContext(*ctx)) {
+		return defaultVariant
+	}
+
+	f := uc.repository.getToggle(feature)
+
 	if f == nil {
 		if opts.variantFallbackFunc != nil {
 			return opts.variantFallbackFunc(feature, ctx)
diff --git a/config.go b/config.go
index 19ce0a9..4b8097a 100644
--- a/config.go
+++ b/config.go
@@ -175,7 +175,7 @@ func WithContext(ctx context.Context) FeatureOption {
 	}
 }
 
-// WithVariantContext specifies a context for the GetVariant 
+// WithVariantContext specifies a context for the GetVariant
 // call
 func WithVariantContext(ctx context.Context) VariantOption {
 	return func(opts *variantOption) {
@@ -189,7 +189,7 @@ type VariantFallbackFunc func(feature string, ctx *context.Context) *api.Variant
 type variantOption struct {
 	variantFallback     *api.Variant
 	variantFallbackFunc VariantFallbackFunc
-	ctx          *context.Context
+	ctx                 *context.Context
 }
 
 // VariantOption provides options for querying if a variant is found or not.
diff --git a/metrics.go b/metrics.go
index 7ce5160..6945941 100644
--- a/metrics.go
+++ b/metrics.go
@@ -234,13 +234,13 @@ func (m *metrics) countVariants(name string, variantName string) {
 	if m.options.disableMetrics {
 		return
 	}
-	
+
 	t, _ := m.bucket.Toggles[name]
 	if len(t.Variants) == 0 {
 		t.Variants = make(map[string]int32)
-	} 
+	}
 
-	if _ , ok := t.Variants[variantName]; !ok {
+	if _, ok := t.Variants[variantName]; !ok {
 		t.Variants[variantName] = 1
 	} else {
 		t.Variants[variantName] += 1


Test patch:
diff --git a/client_test.go b/client_test.go
index bb2f873..bd3c811 100644
--- a/client_test.go
+++ b/client_test.go
@@ -222,4 +222,84 @@ func TestClientWithoutProjectName(t *testing.T) {
 	assert.NoError(err)
 	assert.Equal(client.options.projectName, "")
 	assert.True(gock.IsDone(), "there should be no more mocks")
-}
\ No newline at end of file
+}
+
+func TestClientWithVariantContext(t *testing.T) {
+	assert := assert.New(t)
+	defer gock.OffAll()
+
+	gock.New(mockerServer).
+		Post("/client/register").
+		Reply(200)
+
+	features := []api.Feature{
+		{
+			Name:        "feature-name",
+			Description: "feature-desc",
+			Enabled:     true,
+			CreatedAt:   time.Date(1974, time.May, 19, 1, 2, 3, 4, time.UTC),
+			Strategy:    "feature-strategy",
+			Strategies: []api.Strategy{
+				{
+					Id:   1,
+					Name: "default",
+					Constraints: []api.Constraint{
+						{
+							ContextName: "custom-id",
+							Operator:    api.OperatorIn,
+							Values:      []string{"custom-ctx"},
+						},
+					},
+					Parameters: map[string]interface{}{
+						"strategy-param-1": "strategy-value-1",
+					},
+				},
+			},
+			Parameters: map[string]interface{}{
+				"feature-param-1": "feature-value-1",
+			},
+			Variants: []api.VariantInternal{
+				{
+					Variant: api.Variant{
+						Name:    "custom-variant",
+						Payload: api.Payload{},
+						Enabled: true,
+					},
+					Weight:     100,
+					WeightType: "",
+					Overrides:  nil,
+				},
+			},
+		},
+	}
+
+	gock.New(mockerServer).
+		Get("/client/features").
+		Reply(200).
+		JSON(api.FeatureResponse{
+			Features: features,
+		})
+
+	mockListener := &MockedListener{}
+	mockListener.On("OnReady").Return()
+	mockListener.On("OnRegistered", mock.AnythingOfType("ClientData"))
+
+	client, err := NewClient(
+		WithUrl(mockerServer),
+		WithAppName(mockAppName),
+		WithInstanceId(mockInstanceId),
+		WithListener(mockListener),
+	)
+
+	assert.NoError(err)
+
+	client.WaitForReady()
+
+	defaultVariant := client.GetVariant("feature-name")
+	assert.Equal(api.GetDefaultVariant(), defaultVariant)
+	variant := client.GetVariant("feature-name", WithVariantContext(context.Context{
+		Properties: map[string]string{"custom-id": "custom-ctx"},
+	}))
+	assert.Equal("custom-variant", variant.Name)
+	assert.True(gock.IsDone(), "there should be no more mocks")
+}