-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathOctopusFeatureContextTests.cs
More file actions
191 lines (151 loc) · 8.09 KB
/
OctopusFeatureContextTests.cs
File metadata and controls
191 lines (151 loc) · 8.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
using System.Text;
using FluentAssertions;
using FluentAssertions.Execution;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.VisualBasic;
using Murmur;
using OpenFeature.Constant;
using OpenFeature.Model;
namespace Octopus.OpenFeature.Provider.Tests;
public class OctopusFeatureContextTests
{
[Fact]
public void EvaluatesToTrue_IfFeatureIsContainedWithinTheSet_AndFeatureIsEnabled()
{
var featureToggles = new FeatureToggles([
new FeatureToggleEvaluation("test-feature", true, "evaluation-key", [], 100)
], []);
var context = new OctopusFeatureContext(featureToggles, NullLoggerFactory.Instance);
var result = context.Evaluate("test-feature", false, context: null);
result.Value.Should().BeTrue();
}
[Fact]
public void WhenEvaluatedWithCasingDifferences_EvaluationIsInsensitiveToCase()
{
var featureToggles = new FeatureToggles([
new FeatureToggleEvaluation("test-feature", true, "evaluation-key", [], 100)
], []);
var context = new OctopusFeatureContext(featureToggles, NullLoggerFactory.Instance);
var result = context.Evaluate("Test-Feature", false, context: null);
result.Value.Should().BeTrue();
}
[Fact]
public void EvaluatesToFalse_IfFeatureIsContainedWithinTheSet_AndFeatureIsNotEnabled()
{
var featureToggles = new FeatureToggles([
new FeatureToggleEvaluation("test-feature", false, "evaluation-key", [], 100)
], []);
var context = new OctopusFeatureContext(featureToggles, NullLoggerFactory.Instance);
var result = context.Evaluate("test-feature", false, context: null);
result.Value.Should().BeFalse();
}
[Fact]
public void GivenAFlagKeyThatIsNotASlug_ReturnsFlagNotFound_AndEvaluatesToDefaultValue()
{
var featureToggles = new FeatureToggles([
new FeatureToggleEvaluation("this-is-clearly-not-a-slug", true, "evaluation-key", [], 100)
], []);
var context = new OctopusFeatureContext(featureToggles, NullLoggerFactory.Instance);
var result = context.Evaluate("This is clearly not a slug!", defaultValue: true, context: null);
result.ErrorType.Should().Be(ErrorType.FlagNotFound);
result.Value.Should().BeTrue();
}
[Fact]
public void EvaluatesToDefaultValue_IfFeatureIsNotContainedWithinSet()
{
var featureToggles = new FeatureToggles([
new FeatureToggleEvaluation("testfeature", true, "evaluation-key", [], 100)
], []);
var context = new OctopusFeatureContext(featureToggles, NullLoggerFactory.Instance);
var result = context.Evaluate("anotherfeature", defaultValue: true, context: null);
result.ErrorType.Should().Be(ErrorType.FlagNotFound);
result.Value.Should().BeTrue();
}
EvaluationContext BuildContext(IEnumerable<(string key, string value)> values, string? targetingKey = null)
{
var builder = EvaluationContext.Builder();
foreach (var (key, value) in values)
{
builder.Set(key, value);
}
if (targetingKey != null)
{
builder.SetTargetingKey(targetingKey);
}
return builder.Build();
}
[Fact]
public void
WhenAFeatureIsToggledOnForASpecificSegment_EvaluatesToTrueWhenSegmentIsSpecified()
{
var featureToggles = new FeatureToggles([
new FeatureToggleEvaluation("testfeature", true, "evaluation-key", [new("license", "trial")], 100)
], []);
var context = new OctopusFeatureContext(featureToggles, NullLoggerFactory.Instance);
using var scope = new AssertionScope();
context.Evaluate("testfeature", false, context: BuildContext([("license", "trial")])).Value.Should().BeTrue();
context.Evaluate("testfeature", false, context: BuildContext([("other", "segment")])).Value.Should().BeFalse();
context.Evaluate("testfeature", false, context: null).Value.Should().BeFalse();
}
[Fact]
public void
WhenFeatureIsNotToggledOnForSpecificSegments_EvaluatesToTrueRegardlessOfSegmentSpecified()
{
var featureToggles = new FeatureToggles([
new FeatureToggleEvaluation("testfeature", true, "evaluation-key", [], 100)
], []);
var context = new OctopusFeatureContext(featureToggles, NullLoggerFactory.Instance);
using var scope = new AssertionScope();
context.Evaluate("testfeature", false, context: BuildContext([("license", "trial")])).Value.Should().BeTrue();
context.Evaluate("testfeature", false, context: null).Value.Should().BeTrue();
}
[Fact]
public void WhenAFeatureIsToggledOnForMultipleSegments_EvaluatesCorrectly()
{
var featureToggles = new FeatureToggles([
new FeatureToggleEvaluation(
"testfeature", true, "evaluation-key", [
new("license", "trial"),
new("region", "au"),
new("region", "us"),
],
100
)
], []);
var context = new OctopusFeatureContext(featureToggles, NullLoggerFactory.Instance);
using var scope = new AssertionScope();
// A matching context value is present for each toggled segment
context.Evaluate("testfeature", false, context: BuildContext([("license", "trial"), ("region", "us")])).Value
.Should().BeTrue("when there is a matching context value for each toggled segment, the toggle should be enabled");
// A context value is present for each toggled segment, but it is not toggled on for one of the supplied values
context.Evaluate("testfeature", false, context: BuildContext([("license", "trial"), ("region", "eu")])).Value
.Should().BeFalse("when there is a matching context value for each toggled segment, but the context value does not match the toggled segment, the toggle should be disabled");
// A matching context value is present for each toggled segment, and an additional segment is present in the provided context values
context.Evaluate("testfeature", false,
context: BuildContext([("license", "trial"), ("region", "us"), ("language", "english")])).Value.Should()
.BeTrue("when extra context values are present, the toggle should still be enabled");
// A context value is present for only one of the two toggled segments
context.Evaluate("testfeature", false, context: BuildContext([("license", "trial")])).Value.Should()
.BeFalse("when the context does not contain a value for all toggled segments, the toggle should be disabled");
// No context values are present for the two toggled segment
// Note that the default value is only returned if evaluation fails for an unexpected reason.
// In this case, the default value is not returned, as we have a successful, but false, flag evaluation.
context.Evaluate("testfeature", true, context: BuildContext([("other", "segment")])).Value.Should()
.BeFalse("when the context does not contain a value for all toggled segments, the toggle should be disabled");
// None specified
context.Evaluate("testfeature", true, context: null).Value.Should().BeFalse("when no context values are present, and the feature is toggled on for a segment, the toggle should be disabled");
}
[Fact]
public void
WhenAFeatureIsToggledOnForASpecificSegment_ToleratesNullValuesInContext()
{
var featureToggles = new FeatureToggles([
new FeatureToggleEvaluation("testfeature", true, "evaluation-key", [new("license", "trial")], 100)
], []);
var context = new OctopusFeatureContext(featureToggles, NullLoggerFactory.Instance);
using var scope = new AssertionScope();
context.Evaluate("testfeature", false, context: BuildContext([("license", null)!])).Value.Should().BeFalse();
context.Evaluate("testfeature", false, context: BuildContext([("other", "segment")])).Value.Should().BeFalse();
context.Evaluate("testfeature", false, context: null).Value.Should().BeFalse();
}
}