flipper 0.26.2 → 0.28.3
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/Changelog.md +61 -0
- data/Gemfile +2 -3
- data/benchmark/enabled_multiple_actors_ips.rb +20 -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/dsl.rb +3 -3
- data/examples/enabled_for_actor.rb +4 -2
- data/examples/mirroring.rb +59 -0
- data/lib/flipper/adapter.rb +23 -7
- data/lib/flipper/adapters/http.rb +11 -3
- data/lib/flipper/adapters/instrumented.rb +25 -2
- data/lib/flipper/adapters/memoizable.rb +19 -2
- data/lib/flipper/adapters/memory.rb +40 -16
- data/lib/flipper/adapters/operation_logger.rb +16 -3
- data/lib/flipper/dsl.rb +5 -9
- 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/feature.rb +12 -10
- data/lib/flipper/feature_check_context.rb +8 -4
- data/lib/flipper/gate.rb +12 -11
- data/lib/flipper/gates/actor.rb +11 -8
- data/lib/flipper/gates/group.rb +4 -2
- data/lib/flipper/gates/percentage_of_actors.rb +4 -5
- data/lib/flipper/identifier.rb +2 -2
- data/lib/flipper/instrumentation/log_subscriber.rb +24 -5
- data/lib/flipper/instrumentation/subscriber.rb +8 -1
- data/lib/flipper/poller.rb +1 -1
- data/lib/flipper/spec/shared_adapter_specs.rb +23 -0
- data/lib/flipper/test/shared_adapter_test.rb +24 -0
- data/lib/flipper/typecast.rb +17 -0
- data/lib/flipper/types/actor.rb +13 -13
- data/lib/flipper/types/group.rb +4 -4
- data/lib/flipper/version.rb +1 -1
- data/lib/flipper.rb +5 -4
- data/spec/fixtures/flipper_pstore_1679087600.json +46 -0
- data/spec/flipper/adapter_spec.rb +29 -2
- data/spec/flipper/adapters/http_spec.rb +25 -3
- data/spec/flipper/adapters/instrumented_spec.rb +28 -10
- data/spec/flipper/adapters/memoizable_spec.rb +30 -10
- data/spec/flipper/adapters/memory_spec.rb +11 -2
- data/spec/flipper/adapters/operation_logger_spec.rb +29 -10
- data/spec/flipper/dsl_spec.rb +25 -8
- 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/feature_check_context_spec.rb +5 -5
- data/spec/flipper/feature_spec.rb +76 -32
- data/spec/flipper/gates/boolean_spec.rb +1 -1
- 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/instrumentation/log_subscriber_spec.rb +15 -5
- data/spec/flipper/instrumentation/statsd_subscriber_spec.rb +10 -0
- data/spec/flipper/typecast_spec.rb +79 -0
- data/spec/flipper/types/actor_spec.rb +45 -45
- data/spec/flipper/types/group_spec.rb +2 -2
- data/spec/flipper_integration_spec.rb +62 -50
- data/spec/flipper_spec.rb +7 -1
- data/spec/support/skippable.rb +18 -0
- metadata +20 -2
@@ -9,7 +9,7 @@ RSpec.describe Flipper::Gates::Boolean do
|
|
9
9
|
Flipper::FeatureCheckContext.new(
|
10
10
|
feature_name: feature_name,
|
11
11
|
values: Flipper::GateValues.new(boolean: bool),
|
12
|
-
|
12
|
+
actors: [Flipper::Types::Actor.new(Flipper::Actor.new('1'))]
|
13
13
|
)
|
14
14
|
end
|
15
15
|
|
@@ -9,18 +9,17 @@ RSpec.describe Flipper::Gates::Group do
|
|
9
9
|
Flipper::FeatureCheckContext.new(
|
10
10
|
feature_name: feature_name,
|
11
11
|
values: Flipper::GateValues.new(groups: set),
|
12
|
-
|
12
|
+
actors: [Flipper::Types::Actor.new(Flipper::Actor.new('5'))]
|
13
13
|
)
|
14
14
|
end
|
15
15
|
|
16
16
|
describe '#open?' do
|
17
17
|
context 'with a group in adapter, but not registered' do
|
18
18
|
before do
|
19
|
-
Flipper.register(:staff) { |
|
19
|
+
Flipper.register(:staff) { |actor| true }
|
20
20
|
end
|
21
21
|
|
22
22
|
it 'ignores group' do
|
23
|
-
thing = Flipper::Actor.new('5')
|
24
23
|
expect(subject.open?(context(Set[:newbs, :staff]))).to be(true)
|
25
24
|
end
|
26
25
|
end
|
@@ -5,11 +5,11 @@ RSpec.describe Flipper::Gates::PercentageOfActors do
|
|
5
5
|
described_class.new
|
6
6
|
end
|
7
7
|
|
8
|
-
def context(percentage_of_actors_value, feature = feature_name,
|
8
|
+
def context(percentage_of_actors_value, feature = feature_name, actors = nil)
|
9
9
|
Flipper::FeatureCheckContext.new(
|
10
10
|
feature_name: feature,
|
11
11
|
values: Flipper::GateValues.new(percentage_of_actors: percentage_of_actors_value),
|
12
|
-
|
12
|
+
actors: Array(actors) || [Flipper::Types::Actor.new(Flipper::Actor.new('1'))]
|
13
13
|
)
|
14
14
|
end
|
15
15
|
|
@@ -20,7 +20,7 @@ RSpec.describe Flipper::Gates::PercentageOfActors do
|
|
20
20
|
let(:number_of_actors) { 10_000 }
|
21
21
|
|
22
22
|
let(:actors) do
|
23
|
-
(1..number_of_actors).map { |n| Flipper::Actor.new(n) }
|
23
|
+
(1..number_of_actors).map { |n| Flipper::Types::Actor.new(Flipper::Actor.new(n.to_s)) }
|
24
24
|
end
|
25
25
|
|
26
26
|
let(:feature_one_enabled_actors) do
|
@@ -48,13 +48,69 @@ RSpec.describe Flipper::Gates::PercentageOfActors do
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
+
context "with an array of actors" do
|
52
|
+
let(:percentage) { 0.05 }
|
53
|
+
let(:percentage_as_integer) { percentage * 100 }
|
54
|
+
let(:number_of_actors) { 3_000 }
|
55
|
+
|
56
|
+
let(:user_actors) do
|
57
|
+
(1..number_of_actors).map { |n| Flipper::Types::Actor.new(Flipper::Actor.new("User;#{n}")) }
|
58
|
+
end
|
59
|
+
|
60
|
+
let(:team_actors) do
|
61
|
+
(1..number_of_actors).map { |n| Flipper::Types::Actor.new(Flipper::Actor.new("Team;#{n}")) }
|
62
|
+
end
|
63
|
+
|
64
|
+
let(:org_actors) do
|
65
|
+
(1..number_of_actors).map { |n| Flipper::Types::Actor.new(Flipper::Actor.new("Org;#{n}")) }
|
66
|
+
end
|
67
|
+
|
68
|
+
let(:actors) { user_actors + team_actors + org_actors }
|
69
|
+
|
70
|
+
let(:feature_one_enabled_actors) do
|
71
|
+
actors.each_slice(3).select do |group|
|
72
|
+
context = context(percentage_as_integer, :name_one, group)
|
73
|
+
subject.open?(context)
|
74
|
+
end.flatten
|
75
|
+
end
|
76
|
+
|
77
|
+
let(:feature_two_enabled_actors) do
|
78
|
+
actors.each_slice(3).select do |group|
|
79
|
+
context = context(percentage_as_integer, :name_two, group)
|
80
|
+
subject.open?(context)
|
81
|
+
end.flatten
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'does not enable both features for same set of actors' do
|
85
|
+
expect(feature_one_enabled_actors).not_to eq(feature_two_enabled_actors)
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'enables feature for accurate number of actors for each feature' do
|
89
|
+
margin_of_error = 0.02 * actors.size # 2 percent margin of error
|
90
|
+
expected_enabled_size = actors.size * percentage
|
91
|
+
|
92
|
+
[
|
93
|
+
feature_one_enabled_actors.size,
|
94
|
+
feature_two_enabled_actors.size,
|
95
|
+
].each do |size|
|
96
|
+
expect(size).to be_within(margin_of_error).of(expected_enabled_size)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
it "is consistent regardless of order of actors" do
|
101
|
+
actors = user_actors.first(10)
|
102
|
+
results = 100.times.map { |n| subject.open?(context(75, :some_feature, actors.shuffle)) }
|
103
|
+
expect(results.uniq).to eq([true])
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
51
107
|
context 'for fractional percentage' do
|
52
108
|
let(:decimal) { 0.001 }
|
53
109
|
let(:percentage) { decimal * 100 }
|
54
110
|
let(:number_of_actors) { 10_000 }
|
55
111
|
|
56
112
|
let(:actors) do
|
57
|
-
(1..number_of_actors).map { |n| Flipper::Actor.new(n) }
|
113
|
+
(1..number_of_actors).map { |n| Flipper::Types::Actor.new(Flipper::Actor.new(n.to_s)) }
|
58
114
|
end
|
59
115
|
|
60
116
|
subject { described_class.new }
|
@@ -64,7 +120,7 @@ RSpec.describe Flipper::Gates::PercentageOfActors do
|
|
64
120
|
expected_open_count = number_of_actors * decimal
|
65
121
|
|
66
122
|
open_count = actors.select do |actor|
|
67
|
-
context = context(percentage, :feature, actor)
|
123
|
+
context = context(percentage, :feature, [actor])
|
68
124
|
subject.open?(context)
|
69
125
|
end.size
|
70
126
|
|
@@ -5,11 +5,11 @@ RSpec.describe Flipper::Gates::PercentageOfTime do
|
|
5
5
|
described_class.new
|
6
6
|
end
|
7
7
|
|
8
|
-
def context(percentage_of_time_value, feature = feature_name,
|
8
|
+
def context(percentage_of_time_value, feature = feature_name, actors = nil)
|
9
9
|
Flipper::FeatureCheckContext.new(
|
10
10
|
feature_name: feature,
|
11
11
|
values: Flipper::GateValues.new(percentage_of_time: percentage_of_time_value),
|
12
|
-
|
12
|
+
actors: Array(actors) || [Flipper::Types::Actor.new(Flipper::Actor.new('1'))]
|
13
13
|
)
|
14
14
|
end
|
15
15
|
|
@@ -2,6 +2,12 @@ require 'logger'
|
|
2
2
|
require 'flipper/adapters/instrumented'
|
3
3
|
require 'flipper/instrumentation/log_subscriber'
|
4
4
|
|
5
|
+
begin
|
6
|
+
require 'active_support/isolated_execution_state'
|
7
|
+
rescue LoadError
|
8
|
+
# ActiveSupport::IsolatedExecutionState is only available in Rails 5.2+
|
9
|
+
end
|
10
|
+
|
5
11
|
RSpec.describe Flipper::Instrumentation::LogSubscriber do
|
6
12
|
let(:adapter) do
|
7
13
|
memory = Flipper::Adapters::Memory.new
|
@@ -12,8 +18,8 @@ RSpec.describe Flipper::Instrumentation::LogSubscriber do
|
|
12
18
|
end
|
13
19
|
|
14
20
|
before do
|
15
|
-
Flipper.register(:admins) do |
|
16
|
-
|
21
|
+
Flipper.register(:admins) do |actor|
|
22
|
+
actor.respond_to?(:admin?) && actor.admin?
|
17
23
|
end
|
18
24
|
|
19
25
|
@io = StringIO.new
|
@@ -26,6 +32,10 @@ RSpec.describe Flipper::Instrumentation::LogSubscriber do
|
|
26
32
|
described_class.logger = nil
|
27
33
|
end
|
28
34
|
|
35
|
+
after(:all) do
|
36
|
+
ActiveSupport::Notifications.unsubscribe("flipper")
|
37
|
+
end
|
38
|
+
|
29
39
|
let(:log) { @io.string }
|
30
40
|
|
31
41
|
context 'feature enabled checks' do
|
@@ -36,7 +46,7 @@ RSpec.describe Flipper::Instrumentation::LogSubscriber do
|
|
36
46
|
|
37
47
|
it 'logs feature calls with result after operation' do
|
38
48
|
feature_line = find_line('Flipper feature(search) enabled? false')
|
39
|
-
expect(feature_line).to include('[
|
49
|
+
expect(feature_line).to include('[ actors=nil ]')
|
40
50
|
end
|
41
51
|
|
42
52
|
it 'logs adapter calls' do
|
@@ -46,7 +56,7 @@ RSpec.describe Flipper::Instrumentation::LogSubscriber do
|
|
46
56
|
end
|
47
57
|
end
|
48
58
|
|
49
|
-
context 'feature enabled checks with
|
59
|
+
context 'feature enabled checks with an actor' do
|
50
60
|
let(:user) { Flipper::Types::Actor.new(Flipper::Actor.new('1')) }
|
51
61
|
|
52
62
|
before do
|
@@ -54,7 +64,7 @@ RSpec.describe Flipper::Instrumentation::LogSubscriber do
|
|
54
64
|
flipper[:search].enabled?(user)
|
55
65
|
end
|
56
66
|
|
57
|
-
it 'logs
|
67
|
+
it 'logs actors for feature' do
|
58
68
|
feature_line = find_line('Flipper feature(search) enabled?')
|
59
69
|
expect(feature_line).to include(user.inspect)
|
60
70
|
end
|
@@ -2,6 +2,12 @@ require 'flipper/adapters/instrumented'
|
|
2
2
|
require 'flipper/instrumentation/statsd'
|
3
3
|
require 'statsd'
|
4
4
|
|
5
|
+
begin
|
6
|
+
require 'active_support/isolated_execution_state'
|
7
|
+
rescue LoadError
|
8
|
+
# ActiveSupport::IsolatedExecutionState is only available in Rails 5.2+
|
9
|
+
end
|
10
|
+
|
5
11
|
RSpec.describe Flipper::Instrumentation::StatsdSubscriber do
|
6
12
|
let(:statsd_client) { Statsd.new }
|
7
13
|
let(:socket) { FakeUDPSocket.new }
|
@@ -25,6 +31,10 @@ RSpec.describe Flipper::Instrumentation::StatsdSubscriber do
|
|
25
31
|
Thread.current[:statsd_socket] = nil
|
26
32
|
end
|
27
33
|
|
34
|
+
after(:all) do
|
35
|
+
ActiveSupport::Notifications.unsubscribe("flipper")
|
36
|
+
end
|
37
|
+
|
28
38
|
def assert_timer(metric)
|
29
39
|
regex = /#{Regexp.escape metric}\:\d+\|ms/
|
30
40
|
result = socket.buffer.detect { |op| op.first =~ regex }
|
@@ -114,4 +114,83 @@ RSpec.describe Flipper::Typecast do
|
|
114
114
|
described_class.to_set('asdf')
|
115
115
|
end.to raise_error(ArgumentError, %("asdf" cannot be converted to a set))
|
116
116
|
end
|
117
|
+
|
118
|
+
describe "#features_hash" do
|
119
|
+
it "returns new hash" do
|
120
|
+
hash = {
|
121
|
+
"search" => {
|
122
|
+
boolean: nil,
|
123
|
+
}
|
124
|
+
}
|
125
|
+
result = described_class.features_hash(hash)
|
126
|
+
expect(result).not_to be(hash)
|
127
|
+
expect(result["search"]).not_to be(hash["search"])
|
128
|
+
end
|
129
|
+
|
130
|
+
it "converts gate value arrays to sets" do
|
131
|
+
hash = {
|
132
|
+
"search" => {
|
133
|
+
boolean: nil,
|
134
|
+
groups: ['a', 'b'],
|
135
|
+
actors: ['User;1'],
|
136
|
+
percentage_of_actors: nil,
|
137
|
+
percentage_of_time: nil,
|
138
|
+
},
|
139
|
+
}
|
140
|
+
result = described_class.features_hash(hash)
|
141
|
+
expect(result).to eq({
|
142
|
+
"search" => {
|
143
|
+
boolean: nil,
|
144
|
+
groups: Set['a', 'b'],
|
145
|
+
actors: Set['User;1'],
|
146
|
+
percentage_of_actors: nil,
|
147
|
+
percentage_of_time: nil,
|
148
|
+
},
|
149
|
+
})
|
150
|
+
end
|
151
|
+
|
152
|
+
it "converts gate value boolean and integers to strings" do
|
153
|
+
hash = {
|
154
|
+
"search" => {
|
155
|
+
boolean: true,
|
156
|
+
groups: Set.new,
|
157
|
+
actors: Set.new,
|
158
|
+
percentage_of_actors: 10,
|
159
|
+
percentage_of_time: 15,
|
160
|
+
},
|
161
|
+
}
|
162
|
+
result = described_class.features_hash(hash)
|
163
|
+
expect(result).to eq({
|
164
|
+
"search" => {
|
165
|
+
boolean: "true",
|
166
|
+
groups: Set.new,
|
167
|
+
actors: Set.new,
|
168
|
+
percentage_of_actors: "10",
|
169
|
+
percentage_of_time: "15",
|
170
|
+
},
|
171
|
+
})
|
172
|
+
end
|
173
|
+
|
174
|
+
it "converts string gate keys to symbols" do
|
175
|
+
hash = {
|
176
|
+
"search" => {
|
177
|
+
"boolean" => nil,
|
178
|
+
"groups" => Set.new,
|
179
|
+
"actors" => Set.new,
|
180
|
+
"percentage_of_actors" => nil,
|
181
|
+
"percentage_of_time" => nil,
|
182
|
+
},
|
183
|
+
}
|
184
|
+
result = described_class.features_hash(hash)
|
185
|
+
expect(result).to eq({
|
186
|
+
"search" => {
|
187
|
+
boolean: nil,
|
188
|
+
groups: Set.new,
|
189
|
+
actors: Set.new,
|
190
|
+
percentage_of_actors: nil,
|
191
|
+
percentage_of_time: nil,
|
192
|
+
},
|
193
|
+
})
|
194
|
+
end
|
195
|
+
end
|
117
196
|
end
|
@@ -2,11 +2,11 @@ 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
|
|
@@ -22,14 +22,14 @@ RSpec.describe Flipper::Types::Actor do
|
|
22
22
|
|
23
23
|
describe '.wrappable?' do
|
24
24
|
it 'returns true if actor' do
|
25
|
-
|
26
|
-
|
27
|
-
expect(described_class.wrappable?(
|
25
|
+
actor = actor_class.new('1')
|
26
|
+
actor_type_instance = described_class.new(actor)
|
27
|
+
expect(described_class.wrappable?(actor_type_instance)).to eq(true)
|
28
28
|
end
|
29
29
|
|
30
30
|
it 'returns true if responds to flipper_id' do
|
31
|
-
|
32
|
-
expect(described_class.wrappable?(
|
31
|
+
actor = actor_class.new(10)
|
32
|
+
expect(described_class.wrappable?(actor)).to eq(true)
|
33
33
|
end
|
34
34
|
|
35
35
|
it 'returns false if nil' do
|
@@ -38,27 +38,27 @@ RSpec.describe Flipper::Types::Actor do
|
|
38
38
|
end
|
39
39
|
|
40
40
|
describe '.wrap' do
|
41
|
-
context 'for actor' do
|
42
|
-
it 'returns actor' do
|
43
|
-
|
44
|
-
expect(
|
45
|
-
expect(
|
41
|
+
context 'for actor type instance' do
|
42
|
+
it 'returns actor type instance' do
|
43
|
+
actor_type_instance = described_class.wrap(subject)
|
44
|
+
expect(actor_type_instance).to be_instance_of(described_class)
|
45
|
+
expect(actor_type_instance).to be(subject)
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
-
context 'for other
|
50
|
-
it 'returns actor' do
|
51
|
-
|
52
|
-
|
53
|
-
expect(
|
49
|
+
context 'for other object' do
|
50
|
+
it 'returns actor type instance' do
|
51
|
+
actor = actor_class.new('1')
|
52
|
+
actor_type_instance = described_class.wrap(actor)
|
53
|
+
expect(actor_type_instance).to be_instance_of(described_class)
|
54
54
|
end
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
-
it 'initializes with
|
59
|
-
|
60
|
-
|
61
|
-
expect(
|
58
|
+
it 'initializes with object that responds to flipper_id' do
|
59
|
+
actor = actor_class.new('1')
|
60
|
+
actor_type_instance = described_class.new(actor)
|
61
|
+
expect(actor_type_instance.value).to eq('1')
|
62
62
|
end
|
63
63
|
|
64
64
|
it 'raises error when initialized with nil' do
|
@@ -68,48 +68,48 @@ RSpec.describe Flipper::Types::Actor do
|
|
68
68
|
end
|
69
69
|
|
70
70
|
it 'raises error when initalized with non-wrappable object' do
|
71
|
-
|
71
|
+
unwrappable_object = Struct.new(:id).new(1)
|
72
72
|
expect do
|
73
|
-
described_class.new(
|
73
|
+
described_class.new(unwrappable_object)
|
74
74
|
end.to raise_error(ArgumentError,
|
75
|
-
"#{
|
75
|
+
"#{unwrappable_object.inspect} must respond to flipper_id, but does not")
|
76
76
|
end
|
77
77
|
|
78
78
|
it 'converts id to string' do
|
79
|
-
|
80
|
-
actor = described_class.new(
|
79
|
+
actor = actor_class.new(2)
|
80
|
+
actor = described_class.new(actor)
|
81
81
|
expect(actor.value).to eq('2')
|
82
82
|
end
|
83
83
|
|
84
|
-
it 'proxies everything to
|
85
|
-
|
86
|
-
actor = described_class.new(
|
84
|
+
it 'proxies everything to actor' do
|
85
|
+
actor = actor_class.new(10)
|
86
|
+
actor = described_class.new(actor)
|
87
87
|
expect(actor.admin?).to eq(true)
|
88
88
|
end
|
89
89
|
|
90
|
-
it 'exposes
|
91
|
-
|
92
|
-
|
93
|
-
expect(actor
|
90
|
+
it 'exposes actor' do
|
91
|
+
actor = actor_class.new(10)
|
92
|
+
actor_type_instance = described_class.new(actor)
|
93
|
+
expect(actor_type_instance.actor).to be(actor)
|
94
94
|
end
|
95
95
|
|
96
96
|
describe '#respond_to?' do
|
97
97
|
it 'returns true if responds to method' do
|
98
|
-
|
99
|
-
|
100
|
-
expect(
|
98
|
+
actor = actor_class.new('1')
|
99
|
+
actor_type_instance = described_class.new(actor)
|
100
|
+
expect(actor_type_instance.respond_to?(:value)).to eq(true)
|
101
101
|
end
|
102
102
|
|
103
|
-
it 'returns true if
|
104
|
-
|
105
|
-
|
106
|
-
expect(
|
103
|
+
it 'returns true if actor responds to method' do
|
104
|
+
actor = actor_class.new(10)
|
105
|
+
actor_type_instance = described_class.new(actor)
|
106
|
+
expect(actor_type_instance.respond_to?(:admin?)).to eq(true)
|
107
107
|
end
|
108
108
|
|
109
|
-
it 'returns false if does not respond to method and
|
110
|
-
|
111
|
-
|
112
|
-
expect(
|
109
|
+
it 'returns false if does not respond to method and actor does not respond to method' do
|
110
|
+
actor = actor_class.new(10)
|
111
|
+
actor_type_instance = described_class.new(actor)
|
112
|
+
expect(actor_type_instance.respond_to?(:frankenstein)).to eq(false)
|
113
113
|
end
|
114
114
|
end
|
115
115
|
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)
|