diff --git a/client_test.go b/client_test.go index 4047061..f80abdc 100644 --- a/client_test.go +++ b/client_test.go @@ -1,9 +1,11 @@ package unleash import ( + "fmt" "time" "github.com/Unleash/unleash-client-go/v4/api" + "github.com/Unleash/unleash-client-go/v4/context" "testing" @@ -258,820 +260,820 @@ func TestClientWithProjectName(t *testing.T) { assert.True(gock.IsDone(), "there should be no more mocks") } -// func TestClientWithoutProjectName(t *testing.T) { -// assert := assert.New(t) -// defer gock.OffAll() +func TestClientWithoutProjectName(t *testing.T) { + assert := assert.New(t) + defer gock.OffAll() -// gock.New(mockerServer). -// Post("/client/register"). -// Reply(200) + gock.New(mockerServer). + Post("/client/register"). + Reply(200) -// gock.New(mockerServer). -// Get("/client/features"). -// Reply(200). -// JSON(api.FeatureResponse{}) + gock.New(mockerServer). + Get("/client/features"). + Reply(200). + JSON(api.FeatureResponse{}) -// mockListener := &MockedListener{} -// mockListener.On("OnReady").Return() -// mockListener.On("OnRegistered", mock.AnythingOfType("ClientData")) -// mockListener.On("OnError").Return() + mockListener := &MockedListener{} + mockListener.On("OnReady").Return() + mockListener.On("OnRegistered", mock.AnythingOfType("ClientData")) + mockListener.On("OnError").Return() -// client, err := NewClient( -// WithUrl(mockerServer), -// WithAppName(mockAppName), -// WithInstanceId(mockInstanceId), -// WithListener(mockListener), -// ) + client, err := NewClient( + WithUrl(mockerServer), + WithAppName(mockAppName), + WithInstanceId(mockInstanceId), + WithListener(mockListener), + ) -// client.WaitForReady() + client.WaitForReady() -// assert.NoError(err) -// assert.Equal(client.options.projectName, "") -// assert.True(gock.IsDone(), "there should be no more mocks") -// } + assert.NoError(err) + assert.Equal(client.options.projectName, "") + assert.True(gock.IsDone(), "there should be no more mocks") +} -// func TestClientWithVariantContext(t *testing.T) { -// assert := assert.New(t) -// defer gock.OffAll() +func TestClientWithVariantContext(t *testing.T) { + assert := assert.New(t) + defer gock.OffAll() -// gock.New(mockerServer). -// Post("/client/register"). -// Reply(200) + 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, -// }, -// }, -// }, -// } + 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, -// Segments: []api.Segment{}, -// }) + gock.New(mockerServer). + Get("/client/features"). + Reply(200). + JSON(api.FeatureResponse{ + Features: features, + Segments: []api.Segment{}, + }) -// mockListener := &MockedListener{} -// mockListener.On("OnReady").Return() -// mockListener.On("OnCount", mock.AnythingOfType("string"), mock.AnythingOfType("bool")).Return() -// mockListener.On("OnRegistered", mock.AnythingOfType("ClientData")) -// mockListener.On("OnError", mock.AnythingOfType("*errors.errorString")) + mockListener := &MockedListener{} + mockListener.On("OnReady").Return() + mockListener.On("OnCount", mock.AnythingOfType("string"), mock.AnythingOfType("bool")).Return() + mockListener.On("OnRegistered", mock.AnythingOfType("ClientData")) + mockListener.On("OnError", mock.AnythingOfType("*errors.errorString")) -// client, err := NewClient( -// WithUrl(mockerServer), -// WithAppName(mockAppName), -// WithInstanceId(mockInstanceId), -// WithListener(mockListener), -// ) + client, err := NewClient( + WithUrl(mockerServer), + WithAppName(mockAppName), + WithInstanceId(mockInstanceId), + WithListener(mockListener), + ) -// assert.NoError(err) + assert.NoError(err) -// client.WaitForReady() + 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) - -// variantFromResolver := client.GetVariant("feature-name", WithVariantContext(context.Context{ -// Properties: map[string]string{"custom-id": "custom-ctx"}, -// }), WithVariantResolver(func(featureName string) *api.Feature { -// if featureName == features[0].Name { -// return &features[0] -// } else { -// t.Fatalf("the feature name passed %s was not the expected one %s", featureName, features[0].Name) -// return nil -// } -// })) + defaultVariant := client.GetVariant("feature-name") -// assert.Equal("custom-variant", variantFromResolver.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") -// } + variantFromResolver := client.GetVariant("feature-name", WithVariantContext(context.Context{ + Properties: map[string]string{"custom-id": "custom-ctx"}, + }), WithVariantResolver(func(featureName string) *api.Feature { + if featureName == features[0].Name { + return &features[0] + } else { + t.Fatalf("the feature name passed %s was not the expected one %s", featureName, features[0].Name) + return nil + } + })) -// func TestClient_WithSegment(t *testing.T) { -// assert := assert.New(t) -// defer gock.OffAll() + assert.Equal("custom-variant", variantFromResolver.Name) -// gock.New(mockerServer). -// Post("/client/register"). -// MatchHeader("UNLEASH-APPNAME", mockAppName). -// MatchHeader("UNLEASH-INSTANCEID", mockInstanceId). -// Reply(200) + assert.True(gock.IsDone(), "there should be no more mocks") +} -// feature := "feature-segment" -// features := []api.Feature{ -// { -// Name: feature, -// 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{}, -// Parameters: map[string]interface{}{}, -// Segments: []int{1}, -// }, -// }, -// Parameters: map[string]interface{}{ -// "feature-param-1": "feature-value-1", -// }, -// }, -// } +func TestClient_WithSegment(t *testing.T) { + assert := assert.New(t) + defer gock.OffAll() -// gock.New(mockerServer). -// Get("/client/features"). -// Reply(200). -// JSON(api.FeatureResponse{ -// Features: features, -// Segments: []api.Segment{ -// {Id: 1, Constraints: []api.Constraint{ -// { -// ContextName: "custom-id", -// Operator: api.OperatorIn, -// Values: []string{"custom-ctx"}, -// }}}, -// }}) + gock.New(mockerServer). + Post("/client/register"). + MatchHeader("UNLEASH-APPNAME", mockAppName). + MatchHeader("UNLEASH-INSTANCEID", mockInstanceId). + Reply(200) -// mockListener := &MockedListener{} -// mockListener.On("OnReady").Return() -// mockListener.On("OnRegistered", mock.AnythingOfType("ClientData")) -// mockListener.On("OnCount", feature, true).Return() -// mockListener.On("OnError").Return() + feature := "feature-segment" + features := []api.Feature{ + { + Name: feature, + 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{}, + Parameters: map[string]interface{}{}, + Segments: []int{1}, + }, + }, + Parameters: map[string]interface{}{ + "feature-param-1": "feature-value-1", + }, + }, + } -// client, err := NewClient( -// WithUrl(mockerServer), -// WithAppName(mockAppName), -// WithInstanceId(mockInstanceId), -// WithListener(mockListener), -// ) + gock.New(mockerServer). + Get("/client/features"). + Reply(200). + JSON(api.FeatureResponse{ + Features: features, + Segments: []api.Segment{ + {Id: 1, Constraints: []api.Constraint{ + { + ContextName: "custom-id", + Operator: api.OperatorIn, + Values: []string{"custom-ctx"}, + }}}, + }}) -// assert.NoError(err) -// client.WaitForReady() + mockListener := &MockedListener{} + mockListener.On("OnReady").Return() + mockListener.On("OnRegistered", mock.AnythingOfType("ClientData")) + mockListener.On("OnCount", feature, true).Return() + mockListener.On("OnError").Return() -// isEnabled := client.IsEnabled(feature, WithContext(context.Context{ -// Properties: map[string]string{"custom-id": "custom-ctx"}, -// })) + client, err := NewClient( + WithUrl(mockerServer), + WithAppName(mockAppName), + WithInstanceId(mockInstanceId), + WithListener(mockListener), + ) -// assert.True(isEnabled) + assert.NoError(err) + client.WaitForReady() -// isEnabledWithResolver := client.IsEnabled(feature, WithContext(context.Context{ -// Properties: map[string]string{"custom-id": "custom-ctx"}, -// }), WithResolver(func(featureName string) *api.Feature { -// if featureName == features[0].Name { -// return &features[0] -// } else { -// t.Fatalf("the feature name passed %s was not the expected one %s", featureName, features[0].Name) -// return nil -// } -// })) + isEnabled := client.IsEnabled(feature, WithContext(context.Context{ + Properties: map[string]string{"custom-id": "custom-ctx"}, + })) -// assert.True(isEnabledWithResolver) + assert.True(isEnabled) -// assert.True(gock.IsDone(), "there should be no more mocks") -// } + isEnabledWithResolver := client.IsEnabled(feature, WithContext(context.Context{ + Properties: map[string]string{"custom-id": "custom-ctx"}, + }), WithResolver(func(featureName string) *api.Feature { + if featureName == features[0].Name { + return &features[0] + } else { + t.Fatalf("the feature name passed %s was not the expected one %s", featureName, features[0].Name) + return nil + } + })) -// func TestClient_WithNonExistingSegment(t *testing.T) { -// assert := assert.New(t) -// defer gock.OffAll() + assert.True(isEnabledWithResolver) -// gock.New(mockerServer). -// Post("/client/register"). -// MatchHeader("UNLEASH-APPNAME", mockAppName). -// MatchHeader("UNLEASH-INSTANCEID", mockInstanceId). -// Reply(200) + assert.True(gock.IsDone(), "there should be no more mocks") +} -// feature := "feature-segment-non-existing" -// features := []api.Feature{ -// { -// Name: feature, -// 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{}, -// Parameters: map[string]interface{}{}, -// Segments: []int{1}, -// }, -// }, -// Parameters: map[string]interface{}{ -// "feature-param-1": "feature-value-1", -// }, -// }, -// } +func TestClient_WithNonExistingSegment(t *testing.T) { + assert := assert.New(t) + defer gock.OffAll() -// gock.New(mockerServer). -// Get("/client/features"). -// Reply(200). -// JSON(api.FeatureResponse{ -// Features: features, -// Segments: []api.Segment{}}) + gock.New(mockerServer). + Post("/client/register"). + MatchHeader("UNLEASH-APPNAME", mockAppName). + MatchHeader("UNLEASH-INSTANCEID", mockInstanceId). + Reply(200) -// mockListener := &MockedListener{} -// mockListener.On("OnReady").Return() -// mockListener.On("OnRegistered", mock.AnythingOfType("ClientData")) -// mockListener.On("OnCount", feature, false).Return() -// mockListener.On("OnError", mock.AnythingOfType("*errors.errorString")) + feature := "feature-segment-non-existing" + features := []api.Feature{ + { + Name: feature, + 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{}, + Parameters: map[string]interface{}{}, + Segments: []int{1}, + }, + }, + Parameters: map[string]interface{}{ + "feature-param-1": "feature-value-1", + }, + }, + } -// client, err := NewClient( -// WithUrl(mockerServer), -// WithAppName(mockAppName), -// WithInstanceId(mockInstanceId), -// WithListener(mockListener), -// ) + gock.New(mockerServer). + Get("/client/features"). + Reply(200). + JSON(api.FeatureResponse{ + Features: features, + Segments: []api.Segment{}}) -// assert.NoError(err) + mockListener := &MockedListener{} + mockListener.On("OnReady").Return() + mockListener.On("OnRegistered", mock.AnythingOfType("ClientData")) + mockListener.On("OnCount", feature, false).Return() + mockListener.On("OnError", mock.AnythingOfType("*errors.errorString")) -// client.WaitForReady() + client, err := NewClient( + WithUrl(mockerServer), + WithAppName(mockAppName), + WithInstanceId(mockInstanceId), + WithListener(mockListener), + ) -// isEnabled := client.IsEnabled(feature, WithContext(context.Context{ -// Properties: map[string]string{"custom-id": "custom-ctx"}, -// })) + assert.NoError(err) -// assert.False(isEnabled) + client.WaitForReady() -// isEnabledWithResolver := client.IsEnabled(feature, WithContext(context.Context{ -// Properties: map[string]string{"custom-id": "custom-ctx"}, -// }), WithResolver(func(featureName string) *api.Feature { -// if featureName == features[0].Name { -// return &features[0] -// } else { -// t.Fatalf("the feature name passed %s was not the expected one %s", featureName, features[0].Name) -// return nil -// } -// })) + isEnabled := client.IsEnabled(feature, WithContext(context.Context{ + Properties: map[string]string{"custom-id": "custom-ctx"}, + })) -// assert.False(isEnabledWithResolver) + assert.False(isEnabled) -// assert.True(gock.IsDone(), "there should be no more mocks") -// } + isEnabledWithResolver := client.IsEnabled(feature, WithContext(context.Context{ + Properties: map[string]string{"custom-id": "custom-ctx"}, + }), WithResolver(func(featureName string) *api.Feature { + if featureName == features[0].Name { + return &features[0] + } else { + t.Fatalf("the feature name passed %s was not the expected one %s", featureName, features[0].Name) + return nil + } + })) -// func TestClient_WithMultipleSegments(t *testing.T) { -// assert := assert.New(t) -// defer gock.OffAll() + assert.False(isEnabledWithResolver) -// gock.New(mockerServer). -// Post("/client/register"). -// MatchHeader("UNLEASH-APPNAME", mockAppName). -// MatchHeader("UNLEASH-INSTANCEID", mockInstanceId). -// Reply(200) + assert.True(gock.IsDone(), "there should be no more mocks") +} -// feature := "feature-segment-multiple" -// features := []api.Feature{ -// { -// Name: feature, -// 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{}, -// Parameters: map[string]interface{}{}, -// Segments: []int{1, 4, 6, 2}, -// }, -// }, -// Parameters: map[string]interface{}{ -// "feature-param-1": "feature-value-1", -// }, -// }, -// } +func TestClient_WithMultipleSegments(t *testing.T) { + assert := assert.New(t) + defer gock.OffAll() -// gock.New(mockerServer). -// Get("/client/features"). -// Reply(200). -// JSON(api.FeatureResponse{ -// Features: features, -// Segments: []api.Segment{ -// {Id: 1, Constraints: []api.Constraint{ -// { -// ContextName: "custom-id", -// Operator: api.OperatorIn, -// Values: []string{"custom-ctx"}, -// }}}, -// {Id: 2, Constraints: []api.Constraint{ -// { -// ContextName: "semver", -// Operator: api.OperatorSemverGt, -// Value: "3.2.1", -// }}}, -// {Id: 4, Constraints: []api.Constraint{ -// { -// ContextName: "age", -// Operator: api.OperatorNumEq, -// Value: "18", -// }}}, -// {Id: 6, Constraints: []api.Constraint{ -// { -// ContextName: "domain", -// Operator: api.OperatorStrStartsWith, -// Values: []string{"unleash"}, -// }}}, -// }}) + gock.New(mockerServer). + Post("/client/register"). + MatchHeader("UNLEASH-APPNAME", mockAppName). + MatchHeader("UNLEASH-INSTANCEID", mockInstanceId). + Reply(200) -// mockListener := &MockedListener{} -// mockListener.On("OnReady").Return() -// mockListener.On("OnRegistered", mock.AnythingOfType("ClientData")) -// mockListener.On("OnCount", feature, true).Return() -// mockListener.On("OnError").Return() + feature := "feature-segment-multiple" + features := []api.Feature{ + { + Name: feature, + 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{}, + Parameters: map[string]interface{}{}, + Segments: []int{1, 4, 6, 2}, + }, + }, + Parameters: map[string]interface{}{ + "feature-param-1": "feature-value-1", + }, + }, + } -// client, err := NewClient( -// WithUrl(mockerServer), -// WithAppName(mockAppName), -// WithInstanceId(mockInstanceId), -// WithListener(mockListener), -// ) + gock.New(mockerServer). + Get("/client/features"). + Reply(200). + JSON(api.FeatureResponse{ + Features: features, + Segments: []api.Segment{ + {Id: 1, Constraints: []api.Constraint{ + { + ContextName: "custom-id", + Operator: api.OperatorIn, + Values: []string{"custom-ctx"}, + }}}, + {Id: 2, Constraints: []api.Constraint{ + { + ContextName: "semver", + Operator: api.OperatorSemverGt, + Value: "3.2.1", + }}}, + {Id: 4, Constraints: []api.Constraint{ + { + ContextName: "age", + Operator: api.OperatorNumEq, + Value: "18", + }}}, + {Id: 6, Constraints: []api.Constraint{ + { + ContextName: "domain", + Operator: api.OperatorStrStartsWith, + Values: []string{"unleash"}, + }}}, + }}) -// assert.NoError(err) -// client.WaitForReady() + mockListener := &MockedListener{} + mockListener.On("OnReady").Return() + mockListener.On("OnRegistered", mock.AnythingOfType("ClientData")) + mockListener.On("OnCount", feature, true).Return() + mockListener.On("OnError").Return() -// fmt.Printf("%v", client.repository.segments) + client, err := NewClient( + WithUrl(mockerServer), + WithAppName(mockAppName), + WithInstanceId(mockInstanceId), + WithListener(mockListener), + ) -// isEnabled := client.IsEnabled(feature, WithContext(context.Context{ -// Properties: map[string]string{"custom-id": "custom-ctx", "semver": "3.2.2", "age": "18", "domain": "unleashtest"}, -// })) + assert.NoError(err) + client.WaitForReady() -// assert.True(isEnabled) + fmt.Printf("%v", client.repository.segments) -// isEnabledWithResolver := client.IsEnabled(feature, WithContext(context.Context{ -// Properties: map[string]string{"custom-id": "custom-ctx", "semver": "3.2.2", "age": "18", "domain": "unleashtest"}, -// }), WithResolver(func(featureName string) *api.Feature { -// if featureName == features[0].Name { -// return &features[0] -// } else { -// t.Fatalf("the feature name passed %s was not the expected one %s", featureName, features[0].Name) -// return nil -// } -// })) + isEnabled := client.IsEnabled(feature, WithContext(context.Context{ + Properties: map[string]string{"custom-id": "custom-ctx", "semver": "3.2.2", "age": "18", "domain": "unleashtest"}, + })) -// assert.True(isEnabledWithResolver) + assert.True(isEnabled) -// assert.True(gock.IsDone(), "there should be no more mocks") -// } + isEnabledWithResolver := client.IsEnabled(feature, WithContext(context.Context{ + Properties: map[string]string{"custom-id": "custom-ctx", "semver": "3.2.2", "age": "18", "domain": "unleashtest"}, + }), WithResolver(func(featureName string) *api.Feature { + if featureName == features[0].Name { + return &features[0] + } else { + t.Fatalf("the feature name passed %s was not the expected one %s", featureName, features[0].Name) + return nil + } + })) -// func TestClient_VariantShouldRespectConstraint(t *testing.T) { -// assert := assert.New(t) -// defer gock.OffAll() + assert.True(isEnabledWithResolver) -// gock.New(mockerServer). -// Post("/client/register"). -// MatchHeader("UNLEASH-APPNAME", mockAppName). -// MatchHeader("UNLEASH-INSTANCEID", mockInstanceId). -// Reply(200) + assert.True(gock.IsDone(), "there should be no more mocks") +} -// feature := "feature-segment-multiple" -// features := []api.Feature{ -// { -// Name: feature, -// 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{}, -// Parameters: map[string]interface{}{}, -// Segments: []int{1, 4, 6, 2}, -// }, -// }, -// 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, -// }, -// }, -// }, -// } +func TestClient_VariantShouldRespectConstraint(t *testing.T) { + assert := assert.New(t) + defer gock.OffAll() -// gock.New(mockerServer). -// Get("/client/features"). -// Reply(200). -// JSON(api.FeatureResponse{ -// Features: features, -// Segments: []api.Segment{ -// {Id: 1, Constraints: []api.Constraint{ -// { -// ContextName: "custom-id", -// Operator: api.OperatorIn, -// Values: []string{"custom-ctx"}, -// }}}, -// {Id: 2, Constraints: []api.Constraint{ -// { -// ContextName: "semver", -// Operator: api.OperatorSemverGt, -// Value: "3.2.1", -// }}}, -// {Id: 4, Constraints: []api.Constraint{ -// { -// ContextName: "age", -// Operator: api.OperatorNumEq, -// Value: "18", -// }}}, -// {Id: 6, Constraints: []api.Constraint{ -// { -// ContextName: "domain", -// Operator: api.OperatorStrStartsWith, -// Values: []string{"unleash"}, -// }}}, -// }}) + gock.New(mockerServer). + Post("/client/register"). + MatchHeader("UNLEASH-APPNAME", mockAppName). + MatchHeader("UNLEASH-INSTANCEID", mockInstanceId). + Reply(200) + + feature := "feature-segment-multiple" + features := []api.Feature{ + { + Name: feature, + 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{}, + Parameters: map[string]interface{}{}, + Segments: []int{1, 4, 6, 2}, + }, + }, + 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, + Segments: []api.Segment{ + {Id: 1, Constraints: []api.Constraint{ + { + ContextName: "custom-id", + Operator: api.OperatorIn, + Values: []string{"custom-ctx"}, + }}}, + {Id: 2, Constraints: []api.Constraint{ + { + ContextName: "semver", + Operator: api.OperatorSemverGt, + Value: "3.2.1", + }}}, + {Id: 4, Constraints: []api.Constraint{ + { + ContextName: "age", + Operator: api.OperatorNumEq, + Value: "18", + }}}, + {Id: 6, Constraints: []api.Constraint{ + { + ContextName: "domain", + Operator: api.OperatorStrStartsWith, + Values: []string{"unleash"}, + }}}, + }}) -// mockListener := &MockedListener{} -// mockListener.On("OnReady").Return() -// mockListener.On("OnRegistered", mock.AnythingOfType("ClientData")) -// mockListener.On("OnCount", feature, true).Return() -// mockListener.On("OnError").Return() + mockListener := &MockedListener{} + mockListener.On("OnReady").Return() + mockListener.On("OnRegistered", mock.AnythingOfType("ClientData")) + mockListener.On("OnCount", feature, true).Return() + mockListener.On("OnError").Return() -// client, err := NewClient( -// WithUrl(mockerServer), -// WithAppName(mockAppName), -// WithInstanceId(mockInstanceId), -// WithListener(mockListener), -// ) + client, err := NewClient( + WithUrl(mockerServer), + WithAppName(mockAppName), + WithInstanceId(mockInstanceId), + WithListener(mockListener), + ) -// assert.NoError(err) -// client.WaitForReady() + assert.NoError(err) + client.WaitForReady() -// fmt.Printf("%v", client.repository.segments) + fmt.Printf("%v", client.repository.segments) -// variant := client.GetVariant(feature, WithVariantContext(context.Context{ -// Properties: map[string]string{"custom-id": "custom-ctx", "semver": "3.2.2", "age": "18", "domain": "unleashtest"}, -// })) + variant := client.GetVariant(feature, WithVariantContext(context.Context{ + Properties: map[string]string{"custom-id": "custom-ctx", "semver": "3.2.2", "age": "18", "domain": "unleashtest"}, + })) -// assert.True(variant.Enabled) + assert.True(variant.Enabled) -// variantFromResolver := client.GetVariant(feature, WithVariantContext(context.Context{ -// Properties: map[string]string{"custom-id": "custom-ctx", "semver": "3.2.2", "age": "18", "domain": "unleashtest"}, -// }), WithVariantResolver(func(featureName string) *api.Feature { -// if featureName == features[0].Name { -// return &features[0] -// } else { -// t.Fatalf("the feature name passed %s was not the expected one %s", featureName, features[0].Name) -// return nil -// } -// })) + variantFromResolver := client.GetVariant(feature, WithVariantContext(context.Context{ + Properties: map[string]string{"custom-id": "custom-ctx", "semver": "3.2.2", "age": "18", "domain": "unleashtest"}, + }), WithVariantResolver(func(featureName string) *api.Feature { + if featureName == features[0].Name { + return &features[0] + } else { + t.Fatalf("the feature name passed %s was not the expected one %s", featureName, features[0].Name) + return nil + } + })) -// assert.True(variantFromResolver.Enabled) + assert.True(variantFromResolver.Enabled) -// assert.True(gock.IsDone(), "there should be no more mocks") -// } + assert.True(gock.IsDone(), "there should be no more mocks") +} -// func TestClient_VariantShouldFailWhenSegmentConstraintsDontMatch(t *testing.T) { -// assert := assert.New(t) -// defer gock.OffAll() +func TestClient_VariantShouldFailWhenSegmentConstraintsDontMatch(t *testing.T) { + assert := assert.New(t) + defer gock.OffAll() -// gock.New(mockerServer). -// Post("/client/register"). -// MatchHeader("UNLEASH-APPNAME", mockAppName). -// MatchHeader("UNLEASH-INSTANCEID", mockInstanceId). -// Reply(200) + gock.New(mockerServer). + Post("/client/register"). + MatchHeader("UNLEASH-APPNAME", mockAppName). + MatchHeader("UNLEASH-INSTANCEID", mockInstanceId). + Reply(200) -// feature := "feature-segment-multiple" -// features := []api.Feature{ -// { -// Name: feature, -// 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{}, -// Parameters: map[string]interface{}{}, -// Segments: []int{1, 4, 6, 2}, -// }, -// }, -// 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, -// }, -// }, -// }, -// } + feature := "feature-segment-multiple" + features := []api.Feature{ + { + Name: feature, + 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{}, + Parameters: map[string]interface{}{}, + Segments: []int{1, 4, 6, 2}, + }, + }, + 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, -// Segments: []api.Segment{ -// {Id: 1, Constraints: []api.Constraint{ -// { -// ContextName: "custom-id", -// Operator: api.OperatorIn, -// Values: []string{"custom-ctx"}, -// }}}, -// {Id: 2, Constraints: []api.Constraint{ -// { -// ContextName: "semver", -// Operator: api.OperatorSemverGt, -// Value: "3.2.1", -// }}}, -// {Id: 4, Constraints: []api.Constraint{ -// { -// ContextName: "age", -// Operator: api.OperatorNumEq, -// Value: "15", -// }}}, -// {Id: 6, Constraints: []api.Constraint{ -// { -// ContextName: "domain", -// Operator: api.OperatorStrStartsWith, -// Values: []string{"unleash"}, -// }}}, -// }}) + gock.New(mockerServer). + Get("/client/features"). + Reply(200). + JSON(api.FeatureResponse{ + Features: features, + Segments: []api.Segment{ + {Id: 1, Constraints: []api.Constraint{ + { + ContextName: "custom-id", + Operator: api.OperatorIn, + Values: []string{"custom-ctx"}, + }}}, + {Id: 2, Constraints: []api.Constraint{ + { + ContextName: "semver", + Operator: api.OperatorSemverGt, + Value: "3.2.1", + }}}, + {Id: 4, Constraints: []api.Constraint{ + { + ContextName: "age", + Operator: api.OperatorNumEq, + Value: "15", + }}}, + {Id: 6, Constraints: []api.Constraint{ + { + ContextName: "domain", + Operator: api.OperatorStrStartsWith, + Values: []string{"unleash"}, + }}}, + }}) -// mockListener := &MockedListener{} -// mockListener.On("OnReady").Return() -// mockListener.On("OnCount", mock.AnythingOfType("string"), mock.AnythingOfType("bool")).Return() -// mockListener.On("OnRegistered", mock.AnythingOfType("ClientData")) -// mockListener.On("OnError").Return() + mockListener := &MockedListener{} + mockListener.On("OnReady").Return() + mockListener.On("OnCount", mock.AnythingOfType("string"), mock.AnythingOfType("bool")).Return() + mockListener.On("OnRegistered", mock.AnythingOfType("ClientData")) + mockListener.On("OnError").Return() -// client, err := NewClient( -// WithUrl(mockerServer), -// WithAppName(mockAppName), -// WithInstanceId(mockInstanceId), -// WithListener(mockListener), -// ) + client, err := NewClient( + WithUrl(mockerServer), + WithAppName(mockAppName), + WithInstanceId(mockInstanceId), + WithListener(mockListener), + ) -// assert.NoError(err) -// client.WaitForReady() + assert.NoError(err) + client.WaitForReady() -// fmt.Printf("%v", client.repository.segments) + fmt.Printf("%v", client.repository.segments) -// variant := client.GetVariant(feature, WithVariantContext(context.Context{ -// Properties: map[string]string{"custom-id": "custom-ctx", "semver": "3.2.2", "age": "18", "domain": "unleashtest"}, -// })) + variant := client.GetVariant(feature, WithVariantContext(context.Context{ + Properties: map[string]string{"custom-id": "custom-ctx", "semver": "3.2.2", "age": "18", "domain": "unleashtest"}, + })) -// assert.False(variant.Enabled) + assert.False(variant.Enabled) -// variantFromResolver := client.GetVariant(feature, WithVariantContext(context.Context{ -// Properties: map[string]string{"custom-id": "custom-ctx", "semver": "3.2.2", "age": "18", "domain": "unleashtest"}, -// }), WithVariantResolver(func(featureName string) *api.Feature { -// if featureName == features[0].Name { -// return &features[0] -// } else { -// t.Fatalf("the feature name passed %s was not the expected one %s", featureName, features[0].Name) -// return nil -// } -// })) + variantFromResolver := client.GetVariant(feature, WithVariantContext(context.Context{ + Properties: map[string]string{"custom-id": "custom-ctx", "semver": "3.2.2", "age": "18", "domain": "unleashtest"}, + }), WithVariantResolver(func(featureName string) *api.Feature { + if featureName == features[0].Name { + return &features[0] + } else { + t.Fatalf("the feature name passed %s was not the expected one %s", featureName, features[0].Name) + return nil + } + })) -// assert.False(variantFromResolver.Enabled) + assert.False(variantFromResolver.Enabled) -// assert.True(gock.IsDone(), "there should be no more mocks") -// } + assert.True(gock.IsDone(), "there should be no more mocks") +} -// func TestClient_ShouldFavorStrategyVariantOverFeatureVariant(t *testing.T) { -// assert := assert.New(t) -// defer gock.OffAll() +func TestClient_ShouldFavorStrategyVariantOverFeatureVariant(t *testing.T) { + assert := assert.New(t) + defer gock.OffAll() -// gock.New(mockerServer). -// Post("/client/register"). -// Reply(200) + gock.New(mockerServer). + Post("/client/register"). + Reply(200) -// features := []api.Feature{ -// { -// Name: "feature-x", -// 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{}, -// Parameters: map[string]interface{}{ -// "groupId": "strategyVariantName", -// }, -// Variants: []api.VariantInternal{ -// { -// Variant: api.Variant{ -// Name: "strategyVariantName", -// Payload: api.Payload{ -// Type: "string", -// Value: "strategyVariantValue", -// }, -// }, -// Weight: 1000, -// }, -// }, -// }, -// }, -// Variants: []api.VariantInternal{ -// { -// Variant: api.Variant{ -// Name: "willBeIgnored", -// Payload: api.Payload{ -// Type: "string", -// Value: "willBeIgnored", -// }, -// Enabled: true, -// }, -// Weight: 100, -// }, -// }, -// }, -// } + features := []api.Feature{ + { + Name: "feature-x", + 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{}, + Parameters: map[string]interface{}{ + "groupId": "strategyVariantName", + }, + Variants: []api.VariantInternal{ + { + Variant: api.Variant{ + Name: "strategyVariantName", + Payload: api.Payload{ + Type: "string", + Value: "strategyVariantValue", + }, + }, + Weight: 1000, + }, + }, + }, + }, + Variants: []api.VariantInternal{ + { + Variant: api.Variant{ + Name: "willBeIgnored", + Payload: api.Payload{ + Type: "string", + Value: "willBeIgnored", + }, + Enabled: true, + }, + Weight: 100, + }, + }, + }, + } -// gock.New(mockerServer). -// Get("/client/features"). -// Reply(200). -// JSON(api.FeatureResponse{ -// Features: features, -// Segments: []api.Segment{}, -// }) + gock.New(mockerServer). + Get("/client/features"). + Reply(200). + JSON(api.FeatureResponse{ + Features: features, + Segments: []api.Segment{}, + }) -// mockListener := &MockedListener{} -// mockListener.On("OnReady").Return() -// mockListener.On("OnCount", mock.AnythingOfType("string"), mock.AnythingOfType("bool")).Return() -// mockListener.On("OnRegistered", mock.AnythingOfType("ClientData")) -// mockListener.On("OnError", mock.AnythingOfType("*errors.errorString")) + mockListener := &MockedListener{} + mockListener.On("OnReady").Return() + mockListener.On("OnCount", mock.AnythingOfType("string"), mock.AnythingOfType("bool")).Return() + mockListener.On("OnRegistered", mock.AnythingOfType("ClientData")) + mockListener.On("OnError", mock.AnythingOfType("*errors.errorString")) -// client, err := NewClient( -// WithUrl(mockerServer), -// WithAppName(mockAppName), -// WithInstanceId(mockInstanceId), -// WithListener(mockListener), -// ) + client, err := NewClient( + WithUrl(mockerServer), + WithAppName(mockAppName), + WithInstanceId(mockInstanceId), + WithListener(mockListener), + ) -// assert.NoError(err) + assert.NoError(err) -// client.WaitForReady() + client.WaitForReady() -// strategyVariant := client.GetVariant("feature-x") + strategyVariant := client.GetVariant("feature-x") -// assert.True(strategyVariant.Enabled) + assert.True(strategyVariant.Enabled) -// assert.Equal("strategyVariantName", strategyVariant.Name) + assert.Equal("strategyVariantName", strategyVariant.Name) -// assert.True(gock.IsDone(), "there should be no more mocks") -// } + assert.True(gock.IsDone(), "there should be no more mocks") +} -// func TestClient_ShouldReturnOldVariantForNonMatchingStrategyVariant(t *testing.T) { -// assert := assert.New(t) -// defer gock.OffAll() +func TestClient_ShouldReturnOldVariantForNonMatchingStrategyVariant(t *testing.T) { + assert := assert.New(t) + defer gock.OffAll() -// gock.New(mockerServer). -// Post("/client/register"). -// Reply(200) + gock.New(mockerServer). + Post("/client/register"). + Reply(200) -// features := []api.Feature{ -// { -// Name: "feature-x", -// 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: "flexibleRollout", -// Constraints: []api.Constraint{}, -// Parameters: map[string]interface{}{ -// "rollout": 0, -// "stickiness": "default", -// }, -// Variants: []api.VariantInternal{ -// { -// Variant: api.Variant{ -// Name: "strategyVariantName", -// Payload: api.Payload{ -// Type: "string", -// Value: "strategyVariantValue", -// }, -// Enabled: true, -// }, -// Weight: 1000, -// }, -// }, -// }, -// { -// Id: 2, -// Name: "flexibleRollout", -// Constraints: []api.Constraint{}, -// Parameters: map[string]interface{}{ -// "rollout": 100, -// "stickiness": "default", -// }, -// }, -// }, -// Variants: []api.VariantInternal{ -// { -// Variant: api.Variant{ -// Name: "willBeSelected", -// Payload: api.Payload{ -// Type: "string", -// Value: "willBeSelected", -// }, -// Enabled: true, -// }, -// Weight: 100, -// }, -// }, -// }, -// } + features := []api.Feature{ + { + Name: "feature-x", + 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: "flexibleRollout", + Constraints: []api.Constraint{}, + Parameters: map[string]interface{}{ + "rollout": 0, + "stickiness": "default", + }, + Variants: []api.VariantInternal{ + { + Variant: api.Variant{ + Name: "strategyVariantName", + Payload: api.Payload{ + Type: "string", + Value: "strategyVariantValue", + }, + Enabled: true, + }, + Weight: 1000, + }, + }, + }, + { + Id: 2, + Name: "flexibleRollout", + Constraints: []api.Constraint{}, + Parameters: map[string]interface{}{ + "rollout": 100, + "stickiness": "default", + }, + }, + }, + Variants: []api.VariantInternal{ + { + Variant: api.Variant{ + Name: "willBeSelected", + Payload: api.Payload{ + Type: "string", + Value: "willBeSelected", + }, + Enabled: true, + }, + Weight: 100, + }, + }, + }, + } -// gock.New(mockerServer). -// Get("/client/features"). -// Reply(200). -// JSON(api.FeatureResponse{ -// Features: features, -// Segments: []api.Segment{}, -// }) + gock.New(mockerServer). + Get("/client/features"). + Reply(200). + JSON(api.FeatureResponse{ + Features: features, + Segments: []api.Segment{}, + }) -// mockListener := &MockedListener{} -// mockListener.On("OnReady").Return() -// mockListener.On("OnCount", mock.AnythingOfType("string"), mock.AnythingOfType("bool")).Return() -// mockListener.On("OnRegistered", mock.AnythingOfType("ClientData")) -// mockListener.On("OnError", mock.AnythingOfType("*errors.errorString")) + mockListener := &MockedListener{} + mockListener.On("OnReady").Return() + mockListener.On("OnCount", mock.AnythingOfType("string"), mock.AnythingOfType("bool")).Return() + mockListener.On("OnRegistered", mock.AnythingOfType("ClientData")) + mockListener.On("OnError", mock.AnythingOfType("*errors.errorString")) -// client, err := NewClient( -// WithUrl(mockerServer), -// WithAppName(mockAppName), -// WithInstanceId(mockInstanceId), -// WithListener(mockListener), -// ) + client, err := NewClient( + WithUrl(mockerServer), + WithAppName(mockAppName), + WithInstanceId(mockInstanceId), + WithListener(mockListener), + ) -// assert.NoError(err) + assert.NoError(err) -// client.WaitForReady() + client.WaitForReady() -// strategyVariant := client.GetVariant("feature-x") + strategyVariant := client.GetVariant("feature-x") -// assert.True(strategyVariant.Enabled) + assert.True(strategyVariant.Enabled) -// assert.Equal("willBeSelected", strategyVariant.Name) + assert.Equal("willBeSelected", strategyVariant.Name) -// assert.True(gock.IsDone(), "there should be no more mocks") -// } + assert.True(gock.IsDone(), "there should be no more mocks") +}