Skip to content

Commit

Permalink
Add config to enable boolean value
Browse files Browse the repository at this point in the history
  • Loading branch information
vpetrusevici committed Oct 20, 2023
1 parent 590888f commit 3098305
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 24 deletions.
36 changes: 27 additions & 9 deletions src/OpenFeature.Contrib.Providers.Flagsmith/FlagsmithProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,18 @@ public class FlagsmithProvider : FeatureProvider
internal readonly IFlagsmithClient _flagsmithClient;

/// <summary>
/// Key that will be used as identity for Flagsmith requests. Default value is "targetingKey"
/// Key that will be used as identity for Flagsmith requests. Default: "targetingKey"
/// </summary>
public string TargetingKey { get; set; } = "targetingKey";

/// <summary>
/// Determines whether to resolve a feature value as a boolean or use
/// the isFeatureEnabled as the flag itself. These values will be false
/// and true respectively.
/// Default: false
/// </summary>
public bool UsingBooleanConfigValue { get; set; }

/// <summary>
/// Creates new instance of <see cref="FlagsmithProvider"/>
/// </summary>
Expand Down Expand Up @@ -70,27 +79,36 @@ private async Task<ResolutionDetails<T>> ResolveValue<T>(string flagKey, T defau
var isFlagEnabled = await flags.IsFeatureEnabled(flagKey);
if (!isFlagEnabled)
{
return new ResolutionDetails<T>(flagKey, defaultValue, reason: Reason.Disabled);
return new(flagKey, defaultValue, reason: Reason.Disabled);
}

var stringValue = await flags.GetFeatureValue(flagKey);

if (tryParse(stringValue, out var parsedValue))
{
return new ResolutionDetails<T>(flagKey, parsedValue);
return new(flagKey, parsedValue);
}
throw new TypeMismatchException("Failed to parse value in the expected type");

}

private async Task<ResolutionDetails<bool>> IsFeatureEnabled(string flagKey, EvaluationContext context)
{
var flags = await GetFlags(context);
var isFeatureEnabled = await flags.IsFeatureEnabled(flagKey);
return new(flagKey, isFeatureEnabled);
}


/// <inheritdoc/>
public override Metadata GetMetadata() => Metadata;

/// <inheritdoc/>

public override Task<ResolutionDetails<bool>> ResolveBooleanValue(string flagKey, bool defaultValue, EvaluationContext context = null)
=> ResolveValue(flagKey, defaultValue, bool.TryParse, context);
=> UsingBooleanConfigValue
? ResolveValue(flagKey, defaultValue, bool.TryParse, context)
: IsFeatureEnabled(flagKey, context);

/// <inheritdoc/>
public override Task<ResolutionDetails<int>> ResolveIntegerValue(string flagKey, int defaultValue, EvaluationContext context = null)
Expand Down Expand Up @@ -141,25 +159,25 @@ private Value ConvertValue(JsonNode node)
var convertedValue = ConvertValue(item);
if (convertedValue != null) arr.Add(convertedValue);
}
return new Value(arr);
return new(arr);
}

if (node is JsonObject jsonObject)
{
var dict = jsonObject.ToDictionary(x => x.Key, x => ConvertValue(x.Value));

return new Value(new Structure(dict));
return new(new Structure(dict));
}

if (node.AsValue().TryGetValue<JsonElement>(out var jsonElement))
{
if (jsonElement.ValueKind == JsonValueKind.False || jsonElement.ValueKind == JsonValueKind.True)
return new Value(jsonElement.GetBoolean());
return new(jsonElement.GetBoolean());
if (jsonElement.ValueKind == JsonValueKind.Number)
return new Value(jsonElement.GetDouble());
return new(jsonElement.GetDouble());

if (jsonElement.ValueKind == JsonValueKind.String)
return new Value(jsonElement.ToString());
return new(jsonElement.ToString());
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,25 +82,52 @@ public async Task GetValue_ForEnabledFeatureWithEvaluationContext_ReturnCorrectV
Assert.Equal(ErrorType.None, result.ErrorType);
}

[Fact]
public async Task GetBooleanValue_ForEnabledFeatureWithValidFormat_ReturnCorrectValue()

[Theory]
[InlineData(true, true, "true", true, null, true)]
[InlineData(false, true, "true", true, null, true)]
[InlineData(true, false, "true", true, null, true)]
[InlineData(false, false, "true", true, null, true)]
[InlineData(true, true, "false", true, null, false)]
[InlineData(false, true, "false", true, null, false)]
[InlineData(true, false, "false", true, null, true)]
[InlineData(false, false, "false", true, null, true)]

[InlineData(true, true, "true", false, "DISABLED", true)]
[InlineData(false, true, "true", false, "DISABLED", false)]
[InlineData(true, false, "true", false, null, false)]
[InlineData(false, false, "true", false, null, false)]
[InlineData(true, true, "false", false, "DISABLED", true)]
[InlineData(false, true, "false", false, "DISABLED", false)]
[InlineData(true, false, "false", false, null, false)]
[InlineData(false, false, "false", false, null, false)]
public async Task GetBooleanValue_ForEnabledFeatureWithValidFormatAndSettedConfigValue_ReturnExpectedResult(
bool defaultValue,
bool enabledValueConfig,
string settedValue,
bool featureEnabled,
string expectedReason,
bool expectedResult)
{
// Arrange
var flagsmithClient = Substitute.For<IFlagsmithClient>();
var flags = Substitute.For<IFlags>();
flags.GetFeatureValue("example-feature").Returns("true");
flags.IsFeatureEnabled("example-feature").Returns(true);
flags.GetFeatureValue("example-feature").Returns(settedValue);
flags.IsFeatureEnabled("example-feature").Returns(featureEnabled);
flagsmithClient.GetEnvironmentFlags().Returns(flags);

var flagsmithProvider = new FlagsmithProvider(flagsmithClient);
var flagsmithProvider = new FlagsmithProvider(flagsmithClient)
{
UsingBooleanConfigValue = enabledValueConfig,
};

// Act
var result = await flagsmithProvider.ResolveBooleanValue("example-feature", false);
var result = await flagsmithProvider.ResolveBooleanValue("example-feature", defaultValue);

// Assert
Assert.True(result.Value);
Assert.Equal(expectedResult, result.Value);
Assert.Equal("example-feature", result.FlagKey);
Assert.Null(result.Reason);
Assert.Equal(expectedReason, result.Reason);
Assert.Equal(ErrorType.None, result.ErrorType);
}

Expand Down Expand Up @@ -422,11 +449,4 @@ public async Task GetStructureValue_ForEnabledFeatureWithWrongFormatValue_Throws
await Assert.ThrowsAsync<TypeMismatchException>(() => flagsmithProvider.ResolveStructureValue("example-feature", defaultObject));
}
}

public class ExampleConfig
{
public string ExampleText { get; set; }
public int ExampleInt { get; set; }
}

}

0 comments on commit 3098305

Please sign in to comment.