flipper 0.26.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/FUNDING.yml +1 -0
- data/.github/workflows/ci.yml +19 -13
- data/.github/workflows/examples.yml +32 -15
- data/Changelog.md +294 -154
- data/Gemfile +15 -10
- data/README.md +13 -11
- data/benchmark/enabled_ips.rb +10 -0
- data/benchmark/enabled_multiple_actors_ips.rb +20 -0
- data/benchmark/enabled_profile.rb +20 -0
- data/benchmark/instrumentation_ips.rb +21 -0
- data/benchmark/typecast_ips.rb +27 -0
- data/docs/images/flipper_cloud.png +0 -0
- data/examples/api/basic.ru +3 -4
- data/examples/api/custom_memoized.ru +3 -4
- data/examples/api/memoized.ru +3 -4
- data/examples/cloud/app.ru +12 -0
- data/examples/cloud/backoff_policy.rb +13 -0
- data/examples/cloud/basic.rb +22 -0
- data/examples/cloud/cloud_setup.rb +20 -0
- data/examples/cloud/forked.rb +36 -0
- data/examples/cloud/import.rb +17 -0
- data/examples/cloud/threaded.rb +33 -0
- data/examples/dsl.rb +1 -15
- data/examples/enabled_for_actor.rb +4 -2
- data/examples/expressions.rb +213 -0
- data/examples/mirroring.rb +59 -0
- data/examples/strict.rb +18 -0
- data/flipper-cloud.gemspec +19 -0
- data/flipper.gemspec +3 -5
- data/lib/flipper/actor.rb +6 -3
- data/lib/flipper/adapter.rb +33 -7
- data/lib/flipper/adapter_builder.rb +44 -0
- data/lib/flipper/adapters/dual_write.rb +1 -3
- data/lib/flipper/adapters/failover.rb +0 -4
- data/lib/flipper/adapters/failsafe.rb +0 -4
- data/lib/flipper/adapters/http/client.rb +26 -7
- data/lib/flipper/adapters/http/error.rb +1 -1
- data/lib/flipper/adapters/http.rb +29 -16
- data/lib/flipper/adapters/instrumented.rb +25 -6
- data/lib/flipper/adapters/memoizable.rb +33 -21
- data/lib/flipper/adapters/memory.rb +81 -46
- data/lib/flipper/adapters/operation_logger.rb +16 -7
- data/lib/flipper/adapters/poll/poller.rb +2 -125
- data/lib/flipper/adapters/poll.rb +5 -3
- data/lib/flipper/adapters/pstore.rb +17 -11
- data/lib/flipper/adapters/read_only.rb +4 -4
- data/lib/flipper/adapters/strict.rb +47 -0
- data/lib/flipper/adapters/sync/feature_synchronizer.rb +10 -1
- data/lib/flipper/adapters/sync.rb +0 -4
- data/lib/flipper/cloud/configuration.rb +258 -0
- data/lib/flipper/cloud/dsl.rb +27 -0
- data/lib/flipper/cloud/message_verifier.rb +95 -0
- data/lib/flipper/cloud/middleware.rb +63 -0
- data/lib/flipper/cloud/routes.rb +14 -0
- data/lib/flipper/cloud/telemetry/backoff_policy.rb +93 -0
- data/lib/flipper/cloud/telemetry/instrumenter.rb +26 -0
- data/lib/flipper/cloud/telemetry/metric.rb +39 -0
- data/lib/flipper/cloud/telemetry/metric_storage.rb +30 -0
- data/lib/flipper/cloud/telemetry/submitter.rb +98 -0
- data/lib/flipper/cloud/telemetry.rb +183 -0
- data/lib/flipper/cloud.rb +53 -0
- data/lib/flipper/configuration.rb +25 -4
- data/lib/flipper/dsl.rb +46 -45
- data/lib/flipper/engine.rb +88 -0
- data/lib/flipper/errors.rb +3 -3
- data/lib/flipper/export.rb +26 -0
- data/lib/flipper/exporter.rb +17 -0
- data/lib/flipper/exporters/json/export.rb +32 -0
- data/lib/flipper/exporters/json/v1.rb +33 -0
- data/lib/flipper/expression/builder.rb +73 -0
- data/lib/flipper/expression/constant.rb +25 -0
- data/lib/flipper/expression.rb +71 -0
- data/lib/flipper/expressions/all.rb +11 -0
- data/lib/flipper/expressions/any.rb +9 -0
- data/lib/flipper/expressions/boolean.rb +9 -0
- data/lib/flipper/expressions/comparable.rb +13 -0
- data/lib/flipper/expressions/duration.rb +28 -0
- data/lib/flipper/expressions/equal.rb +9 -0
- data/lib/flipper/expressions/greater_than.rb +9 -0
- data/lib/flipper/expressions/greater_than_or_equal_to.rb +9 -0
- data/lib/flipper/expressions/less_than.rb +9 -0
- data/lib/flipper/expressions/less_than_or_equal_to.rb +9 -0
- data/lib/flipper/expressions/not_equal.rb +9 -0
- data/lib/flipper/expressions/now.rb +9 -0
- data/lib/flipper/expressions/number.rb +9 -0
- data/lib/flipper/expressions/percentage.rb +9 -0
- data/lib/flipper/expressions/percentage_of_actors.rb +12 -0
- data/lib/flipper/expressions/property.rb +9 -0
- data/lib/flipper/expressions/random.rb +9 -0
- data/lib/flipper/expressions/string.rb +9 -0
- data/lib/flipper/expressions/time.rb +9 -0
- data/lib/flipper/feature.rb +87 -26
- data/lib/flipper/feature_check_context.rb +10 -6
- data/lib/flipper/gate.rb +13 -11
- data/lib/flipper/gate_values.rb +5 -18
- data/lib/flipper/gates/actor.rb +10 -17
- data/lib/flipper/gates/boolean.rb +1 -1
- data/lib/flipper/gates/expression.rb +75 -0
- data/lib/flipper/gates/group.rb +5 -7
- data/lib/flipper/gates/percentage_of_actors.rb +10 -13
- data/lib/flipper/gates/percentage_of_time.rb +1 -2
- data/lib/flipper/identifier.rb +2 -2
- data/lib/flipper/instrumentation/log_subscriber.rb +24 -5
- data/lib/flipper/instrumentation/statsd_subscriber.rb +2 -4
- data/lib/flipper/instrumentation/subscriber.rb +8 -1
- data/lib/flipper/metadata.rb +5 -1
- data/lib/flipper/middleware/memoizer.rb +30 -14
- data/lib/flipper/poller.rb +117 -0
- data/lib/flipper/serializers/gzip.rb +24 -0
- data/lib/flipper/serializers/json.rb +19 -0
- data/lib/flipper/spec/shared_adapter_specs.rb +95 -54
- data/lib/flipper/test/shared_adapter_test.rb +91 -48
- data/lib/flipper/typecast.rb +56 -15
- data/lib/flipper/types/actor.rb +13 -13
- data/lib/flipper/types/group.rb +4 -4
- data/lib/flipper/types/percentage.rb +1 -1
- data/lib/flipper/version.rb +1 -1
- data/lib/flipper.rb +47 -10
- data/spec/fixtures/flipper_pstore_1679087600.json +46 -0
- data/spec/flipper/adapter_builder_spec.rb +73 -0
- data/spec/flipper/adapter_spec.rb +30 -2
- data/spec/flipper/adapters/dual_write_spec.rb +2 -2
- data/spec/flipper/adapters/http_spec.rb +64 -8
- data/spec/flipper/adapters/instrumented_spec.rb +29 -11
- data/spec/flipper/adapters/memoizable_spec.rb +51 -31
- data/spec/flipper/adapters/memory_spec.rb +14 -3
- data/spec/flipper/adapters/operation_logger_spec.rb +31 -12
- data/spec/flipper/adapters/read_only_spec.rb +32 -17
- data/spec/flipper/adapters/strict_spec.rb +62 -0
- data/spec/flipper/adapters/sync/feature_synchronizer_spec.rb +27 -0
- data/spec/flipper/cloud/configuration_spec.rb +252 -0
- data/spec/flipper/cloud/dsl_spec.rb +82 -0
- data/spec/flipper/cloud/message_verifier_spec.rb +104 -0
- data/spec/flipper/cloud/middleware_spec.rb +289 -0
- data/spec/flipper/cloud/telemetry/backoff_policy_spec.rb +108 -0
- data/spec/flipper/cloud/telemetry/metric_spec.rb +87 -0
- data/spec/flipper/cloud/telemetry/metric_storage_spec.rb +58 -0
- data/spec/flipper/cloud/telemetry/submitter_spec.rb +145 -0
- data/spec/flipper/cloud/telemetry_spec.rb +156 -0
- data/spec/flipper/cloud_spec.rb +180 -0
- data/spec/flipper/configuration_spec.rb +17 -0
- data/spec/flipper/dsl_spec.rb +54 -73
- data/spec/flipper/engine_spec.rb +291 -0
- data/spec/flipper/export_spec.rb +13 -0
- data/spec/flipper/exporter_spec.rb +16 -0
- data/spec/flipper/exporters/json/export_spec.rb +60 -0
- data/spec/flipper/exporters/json/v1_spec.rb +33 -0
- data/spec/flipper/expression/builder_spec.rb +248 -0
- data/spec/flipper/expression_spec.rb +188 -0
- data/spec/flipper/expressions/all_spec.rb +15 -0
- data/spec/flipper/expressions/any_spec.rb +15 -0
- data/spec/flipper/expressions/boolean_spec.rb +15 -0
- data/spec/flipper/expressions/duration_spec.rb +43 -0
- data/spec/flipper/expressions/equal_spec.rb +24 -0
- data/spec/flipper/expressions/greater_than_or_equal_to_spec.rb +28 -0
- data/spec/flipper/expressions/greater_than_spec.rb +28 -0
- data/spec/flipper/expressions/less_than_or_equal_to_spec.rb +28 -0
- data/spec/flipper/expressions/less_than_spec.rb +32 -0
- data/spec/flipper/expressions/not_equal_spec.rb +15 -0
- data/spec/flipper/expressions/now_spec.rb +11 -0
- data/spec/flipper/expressions/number_spec.rb +21 -0
- data/spec/flipper/expressions/percentage_of_actors_spec.rb +20 -0
- data/spec/flipper/expressions/percentage_spec.rb +15 -0
- data/spec/flipper/expressions/property_spec.rb +13 -0
- data/spec/flipper/expressions/random_spec.rb +9 -0
- data/spec/flipper/expressions/string_spec.rb +11 -0
- data/spec/flipper/expressions/time_spec.rb +13 -0
- data/spec/flipper/feature_check_context_spec.rb +17 -17
- data/spec/flipper/feature_spec.rb +436 -33
- data/spec/flipper/gate_values_spec.rb +2 -33
- data/spec/flipper/gates/boolean_spec.rb +1 -1
- data/spec/flipper/gates/expression_spec.rb +108 -0
- data/spec/flipper/gates/group_spec.rb +2 -3
- data/spec/flipper/gates/percentage_of_actors_spec.rb +61 -5
- data/spec/flipper/gates/percentage_of_time_spec.rb +2 -2
- data/spec/flipper/identifier_spec.rb +4 -5
- data/spec/flipper/instrumentation/log_subscriber_spec.rb +15 -5
- data/spec/flipper/instrumentation/statsd_subscriber_spec.rb +25 -1
- data/spec/flipper/middleware/memoizer_spec.rb +67 -0
- data/spec/flipper/poller_spec.rb +47 -0
- data/spec/flipper/serializers/gzip_spec.rb +13 -0
- data/spec/flipper/serializers/json_spec.rb +13 -0
- data/spec/flipper/typecast_spec.rb +121 -6
- data/spec/flipper/types/actor_spec.rb +63 -46
- data/spec/flipper/types/group_spec.rb +2 -2
- data/spec/flipper_integration_spec.rb +168 -58
- data/spec/flipper_spec.rb +92 -28
- data/spec/spec_helper.rb +6 -13
- data/spec/support/actor_names.yml +1 -0
- data/spec/support/climate_control.rb +7 -0
- data/spec/support/fake_backoff_policy.rb +15 -0
- data/spec/support/skippable.rb +18 -0
- data/spec/support/spec_helpers.rb +11 -3
- metadata +166 -13
- data/.github/workflows/release.yml +0 -44
- data/.tool-versions +0 -1
- data/lib/flipper/railtie.rb +0 -47
- data/spec/flipper/railtie_spec.rb +0 -109
@@ -2,34 +2,41 @@ require 'flipper/types/actor'
|
|
2
2
|
|
3
3
|
RSpec.describe Flipper::Types::Actor do
|
4
4
|
subject do
|
5
|
-
|
6
|
-
described_class.new(
|
5
|
+
actor = actor_class.new('2')
|
6
|
+
described_class.new(actor)
|
7
7
|
end
|
8
8
|
|
9
|
-
let(:
|
9
|
+
let(:actor_class) do
|
10
10
|
Class.new do
|
11
11
|
attr_reader :flipper_id
|
12
12
|
|
13
13
|
def initialize(flipper_id)
|
14
|
-
@flipper_id = flipper_id
|
14
|
+
@flipper_id = flipper_id.to_s
|
15
15
|
end
|
16
16
|
|
17
17
|
def admin?
|
18
18
|
true
|
19
19
|
end
|
20
|
+
|
21
|
+
def flipper_properties
|
22
|
+
{
|
23
|
+
"flipper_id" => flipper_id,
|
24
|
+
"admin" => admin?,
|
25
|
+
}
|
26
|
+
end
|
20
27
|
end
|
21
28
|
end
|
22
29
|
|
23
30
|
describe '.wrappable?' do
|
24
31
|
it 'returns true if actor' do
|
25
|
-
|
26
|
-
|
27
|
-
expect(described_class.wrappable?(
|
32
|
+
actor = actor_class.new('1')
|
33
|
+
actor_type_instance = described_class.new(actor)
|
34
|
+
expect(described_class.wrappable?(actor_type_instance)).to eq(true)
|
28
35
|
end
|
29
36
|
|
30
37
|
it 'returns true if responds to flipper_id' do
|
31
|
-
|
32
|
-
expect(described_class.wrappable?(
|
38
|
+
actor = actor_class.new(10)
|
39
|
+
expect(described_class.wrappable?(actor)).to eq(true)
|
33
40
|
end
|
34
41
|
|
35
42
|
it 'returns false if nil' do
|
@@ -38,27 +45,27 @@ RSpec.describe Flipper::Types::Actor do
|
|
38
45
|
end
|
39
46
|
|
40
47
|
describe '.wrap' do
|
41
|
-
context 'for actor' do
|
42
|
-
it 'returns actor' do
|
43
|
-
|
44
|
-
expect(
|
45
|
-
expect(
|
48
|
+
context 'for actor type instance' do
|
49
|
+
it 'returns actor type instance' do
|
50
|
+
actor_type_instance = described_class.wrap(subject)
|
51
|
+
expect(actor_type_instance).to be_instance_of(described_class)
|
52
|
+
expect(actor_type_instance).to be(subject)
|
46
53
|
end
|
47
54
|
end
|
48
55
|
|
49
|
-
context 'for other
|
50
|
-
it 'returns actor' do
|
51
|
-
|
52
|
-
|
53
|
-
expect(
|
56
|
+
context 'for other object' do
|
57
|
+
it 'returns actor type instance' do
|
58
|
+
actor = actor_class.new('1')
|
59
|
+
actor_type_instance = described_class.wrap(actor)
|
60
|
+
expect(actor_type_instance).to be_instance_of(described_class)
|
54
61
|
end
|
55
62
|
end
|
56
63
|
end
|
57
64
|
|
58
|
-
it 'initializes with
|
59
|
-
|
60
|
-
|
61
|
-
expect(
|
65
|
+
it 'initializes with object that responds to flipper_id' do
|
66
|
+
actor = actor_class.new('1')
|
67
|
+
actor_type_instance = described_class.new(actor)
|
68
|
+
expect(actor_type_instance.value).to eq('1')
|
62
69
|
end
|
63
70
|
|
64
71
|
it 'raises error when initialized with nil' do
|
@@ -68,48 +75,58 @@ RSpec.describe Flipper::Types::Actor do
|
|
68
75
|
end
|
69
76
|
|
70
77
|
it 'raises error when initalized with non-wrappable object' do
|
71
|
-
|
78
|
+
unwrappable_object = Struct.new(:id).new(1)
|
72
79
|
expect do
|
73
|
-
described_class.new(
|
80
|
+
described_class.new(unwrappable_object)
|
74
81
|
end.to raise_error(ArgumentError,
|
75
|
-
"#{
|
82
|
+
"#{unwrappable_object.inspect} must respond to flipper_id, but does not")
|
76
83
|
end
|
77
84
|
|
78
85
|
it 'converts id to string' do
|
79
|
-
|
80
|
-
actor = described_class.new(
|
86
|
+
actor = actor_class.new(2)
|
87
|
+
actor = described_class.new(actor)
|
81
88
|
expect(actor.value).to eq('2')
|
82
89
|
end
|
83
90
|
|
84
|
-
it 'proxies everything to
|
85
|
-
|
86
|
-
actor = described_class.new(
|
91
|
+
it 'proxies everything to actor' do
|
92
|
+
actor = actor_class.new(10)
|
93
|
+
actor = described_class.new(actor)
|
87
94
|
expect(actor.admin?).to eq(true)
|
88
95
|
end
|
89
96
|
|
90
|
-
it '
|
91
|
-
|
92
|
-
actor = described_class.new(
|
93
|
-
expect(actor.
|
97
|
+
it 'proxies flipper_properties to actor' do
|
98
|
+
actor = actor_class.new(10)
|
99
|
+
actor = described_class.new(actor)
|
100
|
+
expect(actor.flipper_properties).to eq({
|
101
|
+
"flipper_id" => "10",
|
102
|
+
"admin" => true,
|
103
|
+
})
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'exposes actor' do
|
107
|
+
actor = actor_class.new(10)
|
108
|
+
actor_type_instance = described_class.new(actor)
|
109
|
+
expect(actor_type_instance.actor).to be(actor)
|
94
110
|
end
|
95
111
|
|
96
112
|
describe '#respond_to?' do
|
97
113
|
it 'returns true if responds to method' do
|
98
|
-
|
99
|
-
|
100
|
-
expect(
|
114
|
+
actor = actor_class.new('1')
|
115
|
+
actor_type_instance = described_class.new(actor)
|
116
|
+
expect(actor_type_instance.respond_to?(:value)).to eq(true)
|
101
117
|
end
|
102
118
|
|
103
|
-
it 'returns true if
|
104
|
-
|
105
|
-
|
106
|
-
expect(
|
119
|
+
it 'returns true if actor responds to method' do
|
120
|
+
actor = actor_class.new(10)
|
121
|
+
actor_type_instance = described_class.new(actor)
|
122
|
+
expect(actor_type_instance.respond_to?(:admin?)).to eq(true)
|
123
|
+
expect(actor_type_instance.respond_to?(:flipper_properties)).to eq(true)
|
107
124
|
end
|
108
125
|
|
109
|
-
it 'returns false if does not respond to method and
|
110
|
-
|
111
|
-
|
112
|
-
expect(
|
126
|
+
it 'returns false if does not respond to method and actor does not respond to method' do
|
127
|
+
actor = actor_class.new(10)
|
128
|
+
actor_type_instance = described_class.new(actor)
|
129
|
+
expect(actor_type_instance.respond_to?(:frankenstein)).to eq(false)
|
113
130
|
end
|
114
131
|
end
|
115
132
|
end
|
@@ -90,7 +90,7 @@ RSpec.describe Flipper::Types::Group do
|
|
90
90
|
context = Flipper::FeatureCheckContext.new(
|
91
91
|
feature_name: :my_feature,
|
92
92
|
values: Flipper::GateValues.new({}),
|
93
|
-
|
93
|
+
actors: [Flipper::Types::Actor.new(Flipper::Actor.new('1'))]
|
94
94
|
)
|
95
95
|
group = Flipper.register(:group_with_context) { |actor| actor }
|
96
96
|
yielded_actor = group.match?(admin_actor, context)
|
@@ -101,7 +101,7 @@ RSpec.describe Flipper::Types::Group do
|
|
101
101
|
context = Flipper::FeatureCheckContext.new(
|
102
102
|
feature_name: :my_feature,
|
103
103
|
values: Flipper::GateValues.new({}),
|
104
|
-
|
104
|
+
actors: [Flipper::Types::Actor.new(Flipper::Actor.new('1'))]
|
105
105
|
)
|
106
106
|
group = Flipper.register(:group_with_context) { |actor, context| [actor, context] }
|
107
107
|
yielded_actor, yielded_context = group.match?(admin_actor, context)
|
@@ -7,25 +7,32 @@ RSpec.describe Flipper do
|
|
7
7
|
let(:admin_group) { flipper.group(:admins) }
|
8
8
|
let(:dev_group) { flipper.group(:devs) }
|
9
9
|
|
10
|
-
let(:
|
11
|
-
double 'Non Flipper Thing', flipper_id: 1, admin?: true, dev?: false
|
10
|
+
let(:admin_actor) do
|
11
|
+
double 'Non Flipper Thing', flipper_id: 1, admin?: true, dev?: false, flipper_properties: {"admin" => true, "dev" => false}
|
12
12
|
end
|
13
|
-
let(:
|
14
|
-
double 'Non Flipper Thing', flipper_id: 10, admin?: false, dev?: true
|
13
|
+
let(:dev_actor) do
|
14
|
+
double 'Non Flipper Thing', flipper_id: 10, admin?: false, dev?: true, flipper_properties: {"admin" => false, "dev" => true}
|
15
15
|
end
|
16
16
|
|
17
|
-
let(:
|
18
|
-
double 'Non Flipper Thing', flipper_id: 1, admin?: 'true-ish', dev?: false
|
17
|
+
let(:admin_truthy_actor) do
|
18
|
+
double 'Non Flipper Thing', flipper_id: 1, admin?: 'true-ish', dev?: false, flipper_properties: {"admin" => "true-ish", "dev" => false}
|
19
19
|
end
|
20
|
-
let(:
|
21
|
-
double 'Non Flipper Thing', flipper_id: 1, admin?: nil, dev?: false
|
20
|
+
let(:admin_falsey_actor) do
|
21
|
+
double 'Non Flipper Thing', flipper_id: 1, admin?: nil, dev?: false, flipper_properties: {"admin" => nil, "dev" => false}
|
22
|
+
end
|
23
|
+
|
24
|
+
let(:basic_plan_actor) do
|
25
|
+
double 'Non Flipper Thing', flipper_id: 1, flipper_properties: {"plan" => "basic"}
|
26
|
+
end
|
27
|
+
let(:premium_plan_actor) do
|
28
|
+
double 'Non Flipper Thing', flipper_id: 10, flipper_properties: {"plan" => "premium"}
|
22
29
|
end
|
23
30
|
|
24
31
|
let(:pitt) { Flipper::Actor.new(1) }
|
25
32
|
let(:clooney) { Flipper::Actor.new(10) }
|
26
33
|
|
27
|
-
let(:five_percent_of_actors) {
|
28
|
-
let(:five_percent_of_time) {
|
34
|
+
let(:five_percent_of_actors) { Flipper::Types::PercentageOfActors.new(5) }
|
35
|
+
let(:five_percent_of_time) { Flipper::Types::PercentageOfTime.new(5) }
|
29
36
|
|
30
37
|
before do
|
31
38
|
described_class.register(:admins, &:admin?)
|
@@ -60,20 +67,22 @@ RSpec.describe Flipper do
|
|
60
67
|
expect(@result).to eq(true)
|
61
68
|
end
|
62
69
|
|
63
|
-
it 'enables feature for non flipper
|
64
|
-
expect(feature.enabled?(
|
70
|
+
it 'enables feature for non flipper actor in group' do
|
71
|
+
expect(feature.enabled?(admin_actor)).to eq(true)
|
65
72
|
end
|
66
73
|
|
67
|
-
it 'does not enable feature for non flipper
|
68
|
-
expect(feature.enabled?(
|
74
|
+
it 'does not enable feature for non flipper actor in other group' do
|
75
|
+
expect(feature.enabled?(dev_actor)).to eq(false)
|
69
76
|
end
|
70
77
|
|
71
78
|
it 'enables feature for flipper actor in group' do
|
72
|
-
expect(feature.enabled?(
|
79
|
+
expect(feature.enabled?(Flipper::Types::Actor.new(admin_actor))).to eq(true)
|
80
|
+
expect(feature.enabled?(admin_actor)).to eq(true)
|
73
81
|
end
|
74
82
|
|
75
83
|
it 'does not enable for flipper actor not in group' do
|
76
|
-
expect(feature.enabled?(
|
84
|
+
expect(feature.enabled?(Flipper::Types::Actor.new(dev_actor))).to eq(false)
|
85
|
+
expect(feature.enabled?(dev_actor)).to eq(false)
|
77
86
|
end
|
78
87
|
|
79
88
|
it 'does not enable feature for all' do
|
@@ -118,8 +127,8 @@ RSpec.describe Flipper do
|
|
118
127
|
|
119
128
|
it 'enables feature for actor within percentage' do
|
120
129
|
enabled = (1..100).select do |i|
|
121
|
-
|
122
|
-
feature.enabled?(
|
130
|
+
actor = Flipper::Actor.new(i)
|
131
|
+
feature.enabled?(actor)
|
123
132
|
end.size
|
124
133
|
|
125
134
|
expect(enabled).to be_within(2).of(5)
|
@@ -141,8 +150,8 @@ RSpec.describe Flipper do
|
|
141
150
|
|
142
151
|
it 'enables feature for actor within percentage' do
|
143
152
|
enabled = (1..100).select do |i|
|
144
|
-
|
145
|
-
feature.enabled?(
|
153
|
+
actor = Flipper::Actor.new(i)
|
154
|
+
feature.enabled?(actor)
|
146
155
|
end.size
|
147
156
|
|
148
157
|
expect(enabled).to be_within(2).of(5)
|
@@ -180,10 +189,10 @@ RSpec.describe Flipper do
|
|
180
189
|
|
181
190
|
context 'with argument that has no gate' do
|
182
191
|
it 'raises error' do
|
183
|
-
|
192
|
+
actor = Object.new
|
184
193
|
expect do
|
185
|
-
feature.enable(
|
186
|
-
end.to raise_error(Flipper::GateNotFound, "Could not find gate for #{
|
194
|
+
feature.enable(actor)
|
195
|
+
end.to raise_error(Flipper::GateNotFound, "Could not find gate for #{actor.inspect}")
|
187
196
|
end
|
188
197
|
end
|
189
198
|
end
|
@@ -215,13 +224,13 @@ RSpec.describe Flipper do
|
|
215
224
|
end
|
216
225
|
|
217
226
|
it 'disables actor in group' do
|
218
|
-
expect(feature.enabled?(
|
227
|
+
expect(feature.enabled?(admin_actor)).to eq(false)
|
219
228
|
end
|
220
229
|
|
221
230
|
it 'disables actor in percentage of actors' do
|
222
231
|
enabled = (1..100).select do |i|
|
223
|
-
|
224
|
-
feature.enabled?(
|
232
|
+
actor = Flipper::Actor.new(i)
|
233
|
+
feature.enabled?(actor)
|
225
234
|
end.size
|
226
235
|
|
227
236
|
expect(enabled).to be(0)
|
@@ -247,20 +256,22 @@ RSpec.describe Flipper do
|
|
247
256
|
expect(@result).to eq(true)
|
248
257
|
end
|
249
258
|
|
250
|
-
it 'disables the feature for non flipper
|
251
|
-
expect(feature.enabled?(
|
259
|
+
it 'disables the feature for non flipper actor in the group' do
|
260
|
+
expect(feature.enabled?(admin_actor)).to eq(false)
|
252
261
|
end
|
253
262
|
|
254
|
-
it 'does not disable feature for non flipper
|
255
|
-
expect(feature.enabled?(
|
263
|
+
it 'does not disable feature for non flipper actor in other groups' do
|
264
|
+
expect(feature.enabled?(dev_actor)).to eq(true)
|
256
265
|
end
|
257
266
|
|
258
267
|
it 'disables feature for flipper actor in group' do
|
259
|
-
expect(feature.enabled?(
|
268
|
+
expect(feature.enabled?(Flipper::Types::Actor.new(admin_actor))).to eq(false)
|
269
|
+
expect(feature.enabled?(admin_actor)).to eq(false)
|
260
270
|
end
|
261
271
|
|
262
272
|
it 'does not disable feature for flipper actor in other groups' do
|
263
|
-
expect(feature.enabled?(
|
273
|
+
expect(feature.enabled?(Flipper::Types::Actor.new(dev_actor))).to eq(true)
|
274
|
+
expect(feature.enabled?(dev_actor)).to eq(true)
|
264
275
|
end
|
265
276
|
|
266
277
|
it 'adds feature to set of features' do
|
@@ -294,7 +305,7 @@ RSpec.describe Flipper do
|
|
294
305
|
|
295
306
|
context 'with a percentage of actors' do
|
296
307
|
before do
|
297
|
-
@result = feature.disable(
|
308
|
+
@result = feature.disable(Flipper::Types::PercentageOfActors.new(0))
|
298
309
|
end
|
299
310
|
|
300
311
|
it 'returns true' do
|
@@ -303,8 +314,8 @@ RSpec.describe Flipper do
|
|
303
314
|
|
304
315
|
it 'disables feature' do
|
305
316
|
enabled = (1..100).select do |i|
|
306
|
-
|
307
|
-
feature.enabled?(
|
317
|
+
actor = Flipper::Actor.new(i)
|
318
|
+
feature.enabled?(actor)
|
308
319
|
end.size
|
309
320
|
|
310
321
|
expect(enabled).to be(0)
|
@@ -318,7 +329,7 @@ RSpec.describe Flipper do
|
|
318
329
|
context 'with a percentage of time' do
|
319
330
|
before do
|
320
331
|
@gate = feature.gate(:percentage_of_time)
|
321
|
-
@result = feature.disable(
|
332
|
+
@result = feature.disable(Flipper::Types::PercentageOfTime.new(0))
|
322
333
|
end
|
323
334
|
|
324
335
|
it 'returns true' do
|
@@ -342,10 +353,10 @@ RSpec.describe Flipper do
|
|
342
353
|
|
343
354
|
context 'with argument that has no gate' do
|
344
355
|
it 'raises error' do
|
345
|
-
|
356
|
+
actor = Object.new
|
346
357
|
expect do
|
347
|
-
feature.disable(
|
348
|
-
end.to raise_error(Flipper::GateNotFound, "Could not find gate for #{
|
358
|
+
feature.disable(actor)
|
359
|
+
end.to raise_error(Flipper::GateNotFound, "Could not find gate for #{actor.inspect}")
|
349
360
|
end
|
350
361
|
end
|
351
362
|
end
|
@@ -373,23 +384,29 @@ RSpec.describe Flipper do
|
|
373
384
|
end
|
374
385
|
|
375
386
|
it 'returns true' do
|
376
|
-
expect(feature.enabled?(
|
377
|
-
expect(feature.enabled?(
|
387
|
+
expect(feature.enabled?(Flipper::Types::Actor.new(admin_actor))).to eq(true)
|
388
|
+
expect(feature.enabled?(admin_actor)).to eq(true)
|
378
389
|
end
|
379
390
|
|
380
391
|
it 'returns true for truthy block values' do
|
381
|
-
expect(feature.enabled?(
|
392
|
+
expect(feature.enabled?(Flipper::Types::Actor.new(admin_truthy_actor))).to eq(true)
|
393
|
+
expect(feature.enabled?(admin_truthy_actor)).to eq(true)
|
394
|
+
end
|
395
|
+
|
396
|
+
it 'returns true if any actor is in enabled group' do
|
397
|
+
expect(feature.enabled?(dev_actor, admin_actor)).to be(true)
|
382
398
|
end
|
383
399
|
end
|
384
400
|
|
385
401
|
context 'for actor in disabled group' do
|
386
402
|
it 'returns false' do
|
387
|
-
expect(feature.enabled?(
|
388
|
-
expect(feature.enabled?(
|
403
|
+
expect(feature.enabled?(Flipper::Types::Actor.new(dev_actor))).to eq(false)
|
404
|
+
expect(feature.enabled?(dev_actor)).to eq(false)
|
389
405
|
end
|
390
406
|
|
391
407
|
it 'returns false for falsey block values' do
|
392
|
-
expect(feature.enabled?(
|
408
|
+
expect(feature.enabled?(Flipper::Types::Actor.new(admin_falsey_actor))).to eq(false)
|
409
|
+
expect(feature.enabled?(admin_falsey_actor)).to eq(false)
|
393
410
|
end
|
394
411
|
end
|
395
412
|
|
@@ -408,6 +425,10 @@ RSpec.describe Flipper do
|
|
408
425
|
expect(feature.enabled?(clooney)).to eq(false)
|
409
426
|
end
|
410
427
|
|
428
|
+
it 'returns false if all actors are disabled' do
|
429
|
+
expect(feature.enabled?(clooney, pitt)).to be(false)
|
430
|
+
end
|
431
|
+
|
411
432
|
it 'returns true if boolean enabled' do
|
412
433
|
feature.enable
|
413
434
|
expect(feature.enabled?(clooney)).to eq(true)
|
@@ -428,7 +449,7 @@ RSpec.describe Flipper do
|
|
428
449
|
expect(feature.enabled?).to eq(true)
|
429
450
|
expect(feature.enabled?(nil)).to eq(true)
|
430
451
|
expect(feature.enabled?(pitt)).to eq(true)
|
431
|
-
expect(feature.enabled?(
|
452
|
+
expect(feature.enabled?(admin_actor)).to eq(true)
|
432
453
|
end
|
433
454
|
end
|
434
455
|
|
@@ -446,7 +467,7 @@ RSpec.describe Flipper do
|
|
446
467
|
expect(feature.enabled?).to eq(true)
|
447
468
|
expect(feature.enabled?(nil)).to eq(true)
|
448
469
|
expect(feature.enabled?(pitt)).to eq(true)
|
449
|
-
expect(feature.enabled?(
|
470
|
+
expect(feature.enabled?(admin_actor)).to eq(true)
|
450
471
|
end
|
451
472
|
end
|
452
473
|
|
@@ -463,7 +484,7 @@ RSpec.describe Flipper do
|
|
463
484
|
expect(feature.enabled?).to eq(false)
|
464
485
|
expect(feature.enabled?(nil)).to eq(false)
|
465
486
|
expect(feature.enabled?(pitt)).to eq(false)
|
466
|
-
expect(feature.enabled?(
|
487
|
+
expect(feature.enabled?(admin_actor)).to eq(false)
|
467
488
|
end
|
468
489
|
|
469
490
|
it 'returns true if boolean enabled' do
|
@@ -471,7 +492,7 @@ RSpec.describe Flipper do
|
|
471
492
|
expect(feature.enabled?).to eq(true)
|
472
493
|
expect(feature.enabled?(nil)).to eq(true)
|
473
494
|
expect(feature.enabled?(pitt)).to eq(true)
|
474
|
-
expect(feature.enabled?(
|
495
|
+
expect(feature.enabled?(admin_actor)).to eq(true)
|
475
496
|
end
|
476
497
|
end
|
477
498
|
|
@@ -488,7 +509,7 @@ RSpec.describe Flipper do
|
|
488
509
|
expect(feature.enabled?).to eq(false)
|
489
510
|
expect(feature.enabled?(nil)).to eq(false)
|
490
511
|
expect(feature.enabled?(pitt)).to eq(false)
|
491
|
-
expect(feature.enabled?(
|
512
|
+
expect(feature.enabled?(admin_actor)).to eq(false)
|
492
513
|
end
|
493
514
|
|
494
515
|
it 'returns true if boolean enabled' do
|
@@ -496,27 +517,31 @@ RSpec.describe Flipper do
|
|
496
517
|
expect(feature.enabled?).to eq(true)
|
497
518
|
expect(feature.enabled?(nil)).to eq(true)
|
498
519
|
expect(feature.enabled?(pitt)).to eq(true)
|
499
|
-
expect(feature.enabled?(
|
520
|
+
expect(feature.enabled?(admin_actor)).to eq(true)
|
500
521
|
end
|
501
522
|
end
|
502
523
|
|
503
|
-
context 'for a non flipper
|
524
|
+
context 'for a non flipper actor' do
|
504
525
|
before do
|
505
526
|
feature.enable admin_group
|
506
527
|
end
|
507
528
|
|
508
529
|
it 'returns true if in enabled group' do
|
509
|
-
expect(feature.enabled?(
|
530
|
+
expect(feature.enabled?(admin_actor)).to eq(true)
|
510
531
|
end
|
511
532
|
|
512
533
|
it 'returns false if not in enabled group' do
|
513
|
-
expect(feature.enabled?(
|
534
|
+
expect(feature.enabled?(dev_actor)).to eq(false)
|
535
|
+
end
|
536
|
+
|
537
|
+
it 'retruns true if any actor is true' do
|
538
|
+
expect(feature.enabled?(admin_actor, dev_actor)).to eq(true)
|
514
539
|
end
|
515
540
|
|
516
541
|
it 'returns true if boolean enabled' do
|
517
542
|
feature.enable
|
518
|
-
expect(feature.enabled?(
|
519
|
-
expect(feature.enabled?(
|
543
|
+
expect(feature.enabled?(admin_actor)).to eq(true)
|
544
|
+
expect(feature.enabled?(dev_actor)).to eq(true)
|
520
545
|
end
|
521
546
|
end
|
522
547
|
end
|
@@ -530,11 +555,96 @@ RSpec.describe Flipper do
|
|
530
555
|
end
|
531
556
|
|
532
557
|
it 'enables feature for object in enabled group' do
|
533
|
-
expect(feature.enabled?(
|
558
|
+
expect(feature.enabled?(admin_actor)).to eq(true)
|
534
559
|
end
|
535
560
|
|
536
561
|
it 'does not enable feature for object in not enabled group' do
|
537
|
-
expect(feature.enabled?(
|
562
|
+
expect(feature.enabled?(dev_actor)).to eq(false)
|
563
|
+
end
|
564
|
+
end
|
565
|
+
|
566
|
+
context "for expression" do
|
567
|
+
it "works" do
|
568
|
+
feature.enable Flipper.property(:plan).eq("basic")
|
569
|
+
|
570
|
+
expect(feature.enabled?).to be(false)
|
571
|
+
expect(feature.enabled?(basic_plan_actor)).to be(true)
|
572
|
+
expect(feature.enabled?(premium_plan_actor)).to be(false)
|
573
|
+
expect(feature.enabled?(admin_actor)).to be(false)
|
574
|
+
end
|
575
|
+
|
576
|
+
it "works for true expression with no actor" do
|
577
|
+
feature.enable Flipper.boolean(true)
|
578
|
+
expect(feature.enabled?).to be(true)
|
579
|
+
end
|
580
|
+
|
581
|
+
it "works for multiple actors" do
|
582
|
+
feature.enable Flipper.property(:plan).eq("basic")
|
583
|
+
|
584
|
+
expect(feature.enabled?(basic_plan_actor, premium_plan_actor)).to be(true)
|
585
|
+
expect(feature.enabled?(premium_plan_actor, basic_plan_actor)).to be(true)
|
586
|
+
expect(feature.enabled?(premium_plan_actor, admin_actor)).to be(false)
|
587
|
+
end
|
588
|
+
end
|
589
|
+
|
590
|
+
context "for Any" do
|
591
|
+
it "works" do
|
592
|
+
expression = Flipper.any(
|
593
|
+
Flipper.property(:plan).eq("basic"),
|
594
|
+
Flipper.property(:plan).eq("plus"),
|
595
|
+
)
|
596
|
+
feature.enable expression
|
597
|
+
|
598
|
+
expect(feature.enabled?(basic_plan_actor)).to be(true)
|
599
|
+
expect(feature.enabled?(premium_plan_actor)).to be(false)
|
600
|
+
end
|
601
|
+
end
|
602
|
+
|
603
|
+
context "for All" do
|
604
|
+
it "works" do
|
605
|
+
true_actor = Flipper::Actor.new("User;1", {
|
606
|
+
"plan" => "basic",
|
607
|
+
"age" => 21,
|
608
|
+
})
|
609
|
+
false_actor = Flipper::Actor.new("User;1", {
|
610
|
+
"plan" => "basic",
|
611
|
+
"age" => 20,
|
612
|
+
})
|
613
|
+
expression = Flipper.all(
|
614
|
+
Flipper.property(:plan).eq("basic"),
|
615
|
+
Flipper.property(:age).eq(21)
|
616
|
+
)
|
617
|
+
feature.enable expression
|
618
|
+
|
619
|
+
expect(feature.enabled?(true_actor)).to be(true)
|
620
|
+
expect(feature.enabled?(false_actor)).to be(false)
|
621
|
+
end
|
622
|
+
|
623
|
+
it "works when nested" do
|
624
|
+
admin_actor = Flipper::Actor.new("User;1", {
|
625
|
+
"admin" => true,
|
626
|
+
})
|
627
|
+
true_actor = Flipper::Actor.new("User;1", {
|
628
|
+
"plan" => "basic",
|
629
|
+
"age" => 21,
|
630
|
+
})
|
631
|
+
false_actor = Flipper::Actor.new("User;1", {
|
632
|
+
"plan" => "basic",
|
633
|
+
"age" => 20,
|
634
|
+
})
|
635
|
+
expression = Flipper.any(
|
636
|
+
Flipper.property(:admin).eq(true),
|
637
|
+
Flipper.all(
|
638
|
+
Flipper.property(:plan).eq("basic"),
|
639
|
+
Flipper.property(:age).eq(21)
|
640
|
+
)
|
641
|
+
)
|
642
|
+
|
643
|
+
feature.enable expression
|
644
|
+
|
645
|
+
expect(feature.enabled?(admin_actor)).to be(true)
|
646
|
+
expect(feature.enabled?(true_actor)).to be(true)
|
647
|
+
expect(feature.enabled?(false_actor)).to be(false)
|
538
648
|
end
|
539
649
|
end
|
540
650
|
end
|