flipper 1.3.0 → 1.3.6
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/workflows/ci.yml +19 -5
- data/.github/workflows/examples.yml +19 -5
- data/CLAUDE.md +74 -0
- data/Gemfile +7 -3
- data/README.md +1 -1
- data/examples/cloud/backoff_policy.rb +1 -1
- data/lib/flipper/adapter_builder.rb +1 -1
- data/lib/flipper/adapters/http/error.rb +1 -1
- data/lib/flipper/adapters/http.rb +2 -2
- data/lib/flipper/adapters/poll.rb +15 -0
- data/lib/flipper/cloud/configuration.rb +5 -2
- data/lib/flipper/cloud/telemetry/backoff_policy.rb +6 -3
- data/lib/flipper/cloud/telemetry/submitter.rb +3 -1
- data/lib/flipper/cloud/telemetry.rb +2 -2
- data/lib/flipper/export.rb +0 -2
- data/lib/flipper/expressions/all.rb +0 -2
- data/lib/flipper/feature.rb +8 -1
- data/lib/flipper/gate.rb +1 -1
- data/lib/flipper/instrumentation/log_subscriber.rb +1 -2
- data/lib/flipper/instrumentation/statsd.rb +4 -2
- data/lib/flipper/instrumentation/subscriber.rb +0 -4
- data/lib/flipper/metadata.rb +1 -0
- data/lib/flipper/poller.rb +2 -2
- data/lib/flipper/version.rb +1 -1
- data/lib/generators/flipper/setup_generator.rb +5 -0
- data/lib/generators/flipper/templates/initializer.rb +45 -0
- data/spec/flipper/adapters/http_spec.rb +1 -0
- data/spec/flipper/adapters/poll_spec.rb +41 -0
- data/spec/flipper/adapters/strict_spec.rb +2 -2
- data/spec/flipper/cli_spec.rb +4 -2
- data/spec/flipper/cloud/dsl_spec.rb +1 -1
- data/spec/flipper/cloud/telemetry/backoff_policy_spec.rb +3 -3
- data/spec/flipper/cloud/telemetry/submitter_spec.rb +4 -4
- data/spec/flipper/cloud/telemetry_spec.rb +6 -6
- data/spec/flipper/cloud_spec.rb +9 -4
- data/spec/flipper/dsl_spec.rb +0 -3
- data/spec/flipper/engine_spec.rb +8 -7
- data/spec/flipper/feature_spec.rb +22 -11
- data/spec/flipper/instrumentation/log_subscriber_spec.rb +1 -0
- data/spec/flipper/instrumentation/statsd_subscriber_spec.rb +1 -1
- data/spec/flipper/middleware/memoizer_spec.rb +5 -6
- data/spec/flipper/model/active_record_spec.rb +11 -0
- data/spec/flipper_spec.rb +1 -1
- data/spec/spec_helper.rb +11 -5
- data/spec/support/fail_on_output.rb +1 -1
- data/spec/support/spec_helpers.rb +13 -2
- data/test_rails/generators/flipper/setup_generator_test.rb +5 -0
- data/test_rails/generators/flipper/update_generator_test.rb +1 -1
- data/test_rails/helper.rb +3 -0
- data/test_rails/system/test_help_test.rb +1 -0
- metadata +9 -8
@@ -29,13 +29,13 @@ RSpec.describe Flipper::Adapters::Strict do
|
|
29
29
|
|
30
30
|
context "#get" do
|
31
31
|
it "raises an error for unknown feature" do
|
32
|
-
expect(
|
32
|
+
expect(capture_output { subject.get(feature) }).to match(/Could not find feature "unknown"/)
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
36
|
context "#get_multi" do
|
37
37
|
it "raises an error for unknown feature" do
|
38
|
-
expect(
|
38
|
+
expect(capture_output { subject.get_multi([feature]) }).to match(/Could not find feature "unknown"/)
|
39
39
|
end
|
40
40
|
end
|
41
41
|
end
|
data/spec/flipper/cli_spec.rb
CHANGED
@@ -5,6 +5,8 @@ RSpec.describe Flipper::CLI do
|
|
5
5
|
let(:stderr) { StringIO.new }
|
6
6
|
let(:cli) { Flipper::CLI.new(stdout: stdout, stderr: stderr) }
|
7
7
|
|
8
|
+
Result = Struct.new(:status, :stdout, :stderr, keyword_init: true)
|
9
|
+
|
8
10
|
before do
|
9
11
|
# Prentend stdout/stderr a TTY to test colorization
|
10
12
|
allow(stdout).to receive(:tty?).and_return(true)
|
@@ -12,7 +14,7 @@ RSpec.describe Flipper::CLI do
|
|
12
14
|
end
|
13
15
|
|
14
16
|
# Infer the command from the description
|
15
|
-
|
17
|
+
let(:argv) do
|
16
18
|
descriptions = self.class.parent_groups.map {|g| g.metadata[:description_args] }.reverse.flatten.drop(1)
|
17
19
|
descriptions.map { |arg| Shellwords.split(arg) }.flatten
|
18
20
|
end
|
@@ -26,7 +28,7 @@ RSpec.describe Flipper::CLI do
|
|
26
28
|
status = e.status
|
27
29
|
end
|
28
30
|
|
29
|
-
|
31
|
+
Result.new(status: status, stdout: stdout.string, stderr: stderr.string)
|
30
32
|
end
|
31
33
|
|
32
34
|
before do
|
@@ -4,8 +4,8 @@ RSpec.describe Flipper::Cloud::Telemetry::BackoffPolicy do
|
|
4
4
|
context "#initialize" do
|
5
5
|
it "with no options" do
|
6
6
|
policy = described_class.new
|
7
|
-
expect(policy.min_timeout_ms).to eq(
|
8
|
-
expect(policy.max_timeout_ms).to eq(
|
7
|
+
expect(policy.min_timeout_ms).to eq(30_000)
|
8
|
+
expect(policy.max_timeout_ms).to eq(120_000)
|
9
9
|
expect(policy.multiplier).to eq(1.5)
|
10
10
|
expect(policy.randomization_factor).to eq(0.5)
|
11
11
|
end
|
@@ -87,7 +87,7 @@ RSpec.describe Flipper::Cloud::Telemetry::BackoffPolicy do
|
|
87
87
|
randomization_factor: 0.5,
|
88
88
|
})
|
89
89
|
10.times { policy.next_interval }
|
90
|
-
expect(policy.next_interval).to
|
90
|
+
expect(policy.next_interval).to be_within(10_000*0.1).of(10_000)
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
@@ -71,15 +71,15 @@ RSpec.describe Flipper::Cloud::Telemetry::Submitter do
|
|
71
71
|
to_return(status: 429, body: "{}").
|
72
72
|
to_return(status: 200, body: "{}")
|
73
73
|
instance = described_class.new(cloud_configuration)
|
74
|
-
expect(instance.backoff_policy.min_timeout_ms).to eq(
|
75
|
-
expect(instance.backoff_policy.max_timeout_ms).to eq(
|
74
|
+
expect(instance.backoff_policy.min_timeout_ms).to eq(30_000)
|
75
|
+
expect(instance.backoff_policy.max_timeout_ms).to eq(120_000)
|
76
76
|
end
|
77
77
|
|
78
78
|
it "tries 10 times by default" do
|
79
79
|
stub_request(:post, "https://www.flippercloud.io/adapter/telemetry").
|
80
80
|
to_return(status: 500, body: "{}")
|
81
81
|
subject.call(enabled_metrics)
|
82
|
-
expect(subject.backoff_policy.retries).to eq(
|
82
|
+
expect(subject.backoff_policy.retries).to eq(4) # 4 retries + 1 initial attempt
|
83
83
|
end
|
84
84
|
|
85
85
|
[
|
@@ -105,7 +105,7 @@ RSpec.describe Flipper::Cloud::Telemetry::Submitter do
|
|
105
105
|
stub_request(:post, "https://www.flippercloud.io/adapter/telemetry").
|
106
106
|
to_raise(error_class)
|
107
107
|
subject.call(enabled_metrics)
|
108
|
-
expect(subject.backoff_policy.retries).to eq(
|
108
|
+
expect(subject.backoff_policy.retries).to eq(4)
|
109
109
|
end
|
110
110
|
end
|
111
111
|
|
@@ -25,7 +25,7 @@ RSpec.describe Flipper::Cloud::Telemetry do
|
|
25
25
|
|
26
26
|
expect(telemetry.interval).to eq(60)
|
27
27
|
expect(telemetry.timer.execution_interval).to eq(60)
|
28
|
-
expect(stub).to have_been_requested
|
28
|
+
expect(stub).to have_been_requested.at_least_once
|
29
29
|
end
|
30
30
|
|
31
31
|
it "phones home and updates telemetry interval if present" do
|
@@ -45,7 +45,7 @@ RSpec.describe Flipper::Cloud::Telemetry do
|
|
45
45
|
|
46
46
|
expect(telemetry.interval).to eq(120)
|
47
47
|
expect(telemetry.timer.execution_interval).to eq(120)
|
48
|
-
expect(stub).to have_been_requested
|
48
|
+
expect(stub).to have_been_requested.at_least_once
|
49
49
|
end
|
50
50
|
|
51
51
|
it "phones home and requests shutdown if telemetry-shutdown header is true" do
|
@@ -67,7 +67,7 @@ RSpec.describe Flipper::Cloud::Telemetry do
|
|
67
67
|
result: true,
|
68
68
|
})
|
69
69
|
telemetry.stop
|
70
|
-
expect(stub).to have_been_requested
|
70
|
+
expect(stub).to have_been_requested.at_least_once
|
71
71
|
expect(output.string).to match(/action=telemetry_shutdown message=The server has requested that telemetry be shut down./)
|
72
72
|
end
|
73
73
|
|
@@ -90,7 +90,7 @@ RSpec.describe Flipper::Cloud::Telemetry do
|
|
90
90
|
result: true,
|
91
91
|
})
|
92
92
|
telemetry.stop
|
93
|
-
expect(stub).to have_been_requested
|
93
|
+
expect(stub).to have_been_requested.at_least_once
|
94
94
|
expect(output.string).not_to match(/action=telemetry_shutdown message=The server has requested that telemetry be shut down./)
|
95
95
|
end
|
96
96
|
|
@@ -122,7 +122,7 @@ RSpec.describe Flipper::Cloud::Telemetry do
|
|
122
122
|
# Check the conig interval and the timer interval.
|
123
123
|
expect(telemetry.interval).to eq(120)
|
124
124
|
expect(telemetry.timer.execution_interval).to eq(120)
|
125
|
-
expect(stub).to have_been_requested.times(
|
125
|
+
expect(stub).to have_been_requested.times(5)
|
126
126
|
end
|
127
127
|
|
128
128
|
it "doesn't try to update telemetry interval from error if not response error" do
|
@@ -152,7 +152,7 @@ RSpec.describe Flipper::Cloud::Telemetry do
|
|
152
152
|
|
153
153
|
expect(telemetry.interval).to eq(60)
|
154
154
|
expect(telemetry.timer.execution_interval).to eq(60)
|
155
|
-
expect(stub).to have_been_requested.times(
|
155
|
+
expect(stub).to have_been_requested.times(5)
|
156
156
|
end
|
157
157
|
|
158
158
|
describe '#record' do
|
data/spec/flipper/cloud_spec.rb
CHANGED
@@ -43,6 +43,7 @@ RSpec.describe Flipper::Cloud do
|
|
43
43
|
|
44
44
|
context 'initialize with token and options' do
|
45
45
|
it 'sets correct url' do
|
46
|
+
stub_request(:any, %r{fakeflipper.com}).to_return(status: 200)
|
46
47
|
instance = described_class.new(token: 'asdf', url: 'https://www.fakeflipper.com/sadpanda')
|
47
48
|
# pardon the nesting...
|
48
49
|
memoized = instance.adapter
|
@@ -78,27 +79,31 @@ RSpec.describe Flipper::Cloud do
|
|
78
79
|
end
|
79
80
|
|
80
81
|
it 'can set debug_output' do
|
82
|
+
instance = Flipper::Adapters::Http::Client.new(token: 'asdf', url: 'https://www.flippercloud.io/adapter')
|
81
83
|
expect(Flipper::Adapters::Http::Client).to receive(:new)
|
82
|
-
.with(hash_including(debug_output: STDOUT)).at_least(:once)
|
84
|
+
.with(hash_including(debug_output: STDOUT)).at_least(:once).and_return(instance)
|
83
85
|
described_class.new(token: 'asdf', debug_output: STDOUT)
|
84
86
|
end
|
85
87
|
|
86
88
|
it 'can set read_timeout' do
|
89
|
+
instance = Flipper::Adapters::Http::Client.new(token: 'asdf', url: 'https://www.flippercloud.io/adapter')
|
87
90
|
expect(Flipper::Adapters::Http::Client).to receive(:new)
|
88
|
-
.with(hash_including(read_timeout: 1)).at_least(:once)
|
91
|
+
.with(hash_including(read_timeout: 1)).at_least(:once).and_return(instance)
|
89
92
|
described_class.new(token: 'asdf', read_timeout: 1)
|
90
93
|
end
|
91
94
|
|
92
95
|
it 'can set open_timeout' do
|
96
|
+
instance = Flipper::Adapters::Http::Client.new(token: 'asdf', url: 'https://www.flippercloud.io/adapter')
|
93
97
|
expect(Flipper::Adapters::Http::Client).to receive(:new)
|
94
|
-
.with(hash_including(open_timeout: 1)).at_least(:once)
|
98
|
+
.with(hash_including(open_timeout: 1)).at_least(:once).and_return(instance)
|
95
99
|
described_class.new(token: 'asdf', open_timeout: 1)
|
96
100
|
end
|
97
101
|
|
98
102
|
if RUBY_VERSION >= '2.6.0'
|
99
103
|
it 'can set write_timeout' do
|
104
|
+
instance = Flipper::Adapters::Http::Client.new(token: 'asdf', url: 'https://www.flippercloud.io/adapter')
|
100
105
|
expect(Flipper::Adapters::Http::Client).to receive(:new)
|
101
|
-
.with(hash_including(open_timeout: 1)).at_least(:once)
|
106
|
+
.with(hash_including(open_timeout: 1)).at_least(:once).and_return(instance)
|
102
107
|
described_class.new(token: 'asdf', open_timeout: 1)
|
103
108
|
end
|
104
109
|
end
|
data/spec/flipper/dsl_spec.rb
CHANGED
@@ -225,9 +225,6 @@ RSpec.describe Flipper::DSL do
|
|
225
225
|
|
226
226
|
describe '#enable_group/disable_group' do
|
227
227
|
it 'enables and disables the feature for group' do
|
228
|
-
actor = Flipper::Actor.new(5)
|
229
|
-
group = Flipper.register(:fives) { |actor| actor.flipper_id == 5 }
|
230
|
-
|
231
228
|
expect(subject[:stats].groups_value).to be_empty
|
232
229
|
subject.enable_group(:stats, :fives)
|
233
230
|
expect(subject[:stats].groups_value).to eq(Set['fives'])
|
data/spec/flipper/engine_spec.rb
CHANGED
@@ -12,6 +12,7 @@ RSpec.describe Flipper::Engine do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
before do
|
15
|
+
stub_request(:get, /flippercloud\.io/).to_return(status: 200, body: "{}")
|
15
16
|
Rails.application = nil
|
16
17
|
ActiveSupport::Dependencies.autoload_paths = ActiveSupport::Dependencies.autoload_paths.dup
|
17
18
|
ActiveSupport::Dependencies.autoload_once_paths = ActiveSupport::Dependencies.autoload_once_paths.dup
|
@@ -29,7 +30,7 @@ RSpec.describe Flipper::Engine do
|
|
29
30
|
|
30
31
|
let(:config) { application.config.flipper }
|
31
32
|
|
32
|
-
subject { application.initialize! }
|
33
|
+
subject { SpecHelpers.silence { application.initialize! } }
|
33
34
|
|
34
35
|
shared_examples 'config.strict' do
|
35
36
|
let(:adapter) { Flipper.adapter.adapter }
|
@@ -233,7 +234,7 @@ RSpec.describe Flipper::Engine do
|
|
233
234
|
it "initializes cloud configuration" do
|
234
235
|
stub_request(:get, /flippercloud\.io/).to_return(status: 200, body: "{}")
|
235
236
|
|
236
|
-
application.initialize!
|
237
|
+
silence { application.initialize! }
|
237
238
|
|
238
239
|
expect(Flipper.instance).to be_a(Flipper::Cloud::DSL)
|
239
240
|
expect(Flipper.instance.instrumenter).to be_a(Flipper::Cloud::Telemetry::Instrumenter)
|
@@ -263,7 +264,7 @@ RSpec.describe Flipper::Engine do
|
|
263
264
|
}
|
264
265
|
|
265
266
|
it "configures webhook app" do
|
266
|
-
application.initialize!
|
267
|
+
silence { application.initialize! }
|
267
268
|
|
268
269
|
stub = stub_request(:get, "https://www.flippercloud.io/adapter/features?exclude_gate_names=true").with({
|
269
270
|
headers: { "flipper-cloud-token" => ENV["FLIPPER_CLOUD_TOKEN"] },
|
@@ -278,7 +279,7 @@ RSpec.describe Flipper::Engine do
|
|
278
279
|
|
279
280
|
context "without CLOUD_SYNC_SECRET" do
|
280
281
|
it "does not configure webhook app" do
|
281
|
-
application.initialize!
|
282
|
+
silence { application.initialize! }
|
282
283
|
|
283
284
|
post "/_flipper"
|
284
285
|
expect(last_response.status).to eq(404)
|
@@ -288,7 +289,7 @@ RSpec.describe Flipper::Engine do
|
|
288
289
|
context "without FLIPPER_CLOUD_TOKEN" do
|
289
290
|
it "gracefully skips configuring webhook app" do
|
290
291
|
ENV["FLIPPER_CLOUD_TOKEN"] = nil
|
291
|
-
application.initialize!
|
292
|
+
silence { application.initialize! }
|
292
293
|
expect(Flipper.instance).to be_a(Flipper::DSL)
|
293
294
|
|
294
295
|
post "/_flipper"
|
@@ -324,7 +325,7 @@ RSpec.describe Flipper::Engine do
|
|
324
325
|
end
|
325
326
|
|
326
327
|
it "enables cloud" do
|
327
|
-
application.initialize!
|
328
|
+
silence { application.initialize! }
|
328
329
|
expect(ENV["FLIPPER_CLOUD_TOKEN"]).to eq("credentials-token")
|
329
330
|
expect(ENV["FLIPPER_CLOUD_SYNC_SECRET"]).to eq("credentials-secret")
|
330
331
|
expect(Flipper.instance).to be_a(Flipper::Cloud::DSL)
|
@@ -339,7 +340,7 @@ RSpec.describe Flipper::Engine do
|
|
339
340
|
|
340
341
|
describe "config.actor_limit" do
|
341
342
|
let(:adapter) do
|
342
|
-
application.initialize!
|
343
|
+
silence { application.initialize! }
|
343
344
|
Flipper.adapter.adapter.adapter
|
344
345
|
end
|
345
346
|
|
@@ -76,6 +76,26 @@ RSpec.describe Flipper::Feature do
|
|
76
76
|
expect(subject.enabled?(actors)).to be(false)
|
77
77
|
end
|
78
78
|
end
|
79
|
+
|
80
|
+
context "for an object that implements .nil? == true" do
|
81
|
+
let(:actor) { Flipper::Actor.new("User;1") }
|
82
|
+
|
83
|
+
before do
|
84
|
+
def actor.nil?
|
85
|
+
true
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'returns true if feature is enabled' do
|
90
|
+
subject.enable
|
91
|
+
expect(subject.enabled?(actor)).to be(true)
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'returns false if feature is disabled' do
|
95
|
+
subject.disable
|
96
|
+
expect(subject.enabled?(actor)).to be(false)
|
97
|
+
end
|
98
|
+
end
|
79
99
|
end
|
80
100
|
|
81
101
|
describe '#to_s' do
|
@@ -195,7 +215,7 @@ RSpec.describe Flipper::Feature do
|
|
195
215
|
|
196
216
|
it 'is recorded for enable' do
|
197
217
|
actor = Flipper::Types::Actor.new(Flipper::Actor.new('1'))
|
198
|
-
|
218
|
+
subject.gate_for(actor)
|
199
219
|
|
200
220
|
subject.enable(actor)
|
201
221
|
|
@@ -210,7 +230,7 @@ RSpec.describe Flipper::Feature do
|
|
210
230
|
|
211
231
|
it 'always instruments flipper type instance for enable' do
|
212
232
|
actor = Flipper::Actor.new('1')
|
213
|
-
|
233
|
+
subject.gate_for(actor)
|
214
234
|
|
215
235
|
subject.enable(actor)
|
216
236
|
|
@@ -221,7 +241,6 @@ RSpec.describe Flipper::Feature do
|
|
221
241
|
|
222
242
|
it 'is recorded for disable' do
|
223
243
|
thing = Flipper::Types::Boolean.new
|
224
|
-
gate = subject.gate_for(thing)
|
225
244
|
|
226
245
|
subject.disable(thing)
|
227
246
|
|
@@ -266,7 +285,6 @@ RSpec.describe Flipper::Feature do
|
|
266
285
|
|
267
286
|
it 'always instruments flipper type instance for disable' do
|
268
287
|
actor = Flipper::Actor.new('1')
|
269
|
-
gate = subject.gate_for(actor)
|
270
288
|
|
271
289
|
subject.disable(actor)
|
272
290
|
|
@@ -709,7 +727,6 @@ RSpec.describe Flipper::Feature do
|
|
709
727
|
context "with expression instance" do
|
710
728
|
it "updates gate values to equal expression or clears expression" do
|
711
729
|
expression = Flipper.property(:plan).eq("basic")
|
712
|
-
other_expression = Flipper.property(:age).gte(21)
|
713
730
|
expect(subject.gate_values.expression).to be(nil)
|
714
731
|
subject.enable_expression(expression)
|
715
732
|
expect(subject.gate_values.expression).to eq(expression.value)
|
@@ -721,7 +738,6 @@ RSpec.describe Flipper::Feature do
|
|
721
738
|
context "with Hash" do
|
722
739
|
it "updates gate values to equal expression or clears expression" do
|
723
740
|
expression = Flipper.property(:plan).eq("basic")
|
724
|
-
other_expression = Flipper.property(:age).gte(21)
|
725
741
|
expect(subject.gate_values.expression).to be(nil)
|
726
742
|
subject.enable_expression(expression.value)
|
727
743
|
expect(subject.gate_values.expression).to eq(expression.value)
|
@@ -1078,8 +1094,6 @@ RSpec.describe Flipper::Feature do
|
|
1078
1094
|
describe '#enable_group/disable_group' do
|
1079
1095
|
context 'with symbol group name' do
|
1080
1096
|
it 'updates the gate values to include the group' do
|
1081
|
-
actor = Flipper::Actor.new(5)
|
1082
|
-
group = Flipper.register(:five_only) { |actor| actor.flipper_id == 5 }
|
1083
1097
|
expect(subject.gate_values.groups).to be_empty
|
1084
1098
|
subject.enable_group(:five_only)
|
1085
1099
|
expect(subject.gate_values.groups).to eq(Set['five_only'])
|
@@ -1090,8 +1104,6 @@ RSpec.describe Flipper::Feature do
|
|
1090
1104
|
|
1091
1105
|
context 'with string group name' do
|
1092
1106
|
it 'updates the gate values to include the group' do
|
1093
|
-
actor = Flipper::Actor.new(5)
|
1094
|
-
group = Flipper.register(:five_only) { |actor| actor.flipper_id == 5 }
|
1095
1107
|
expect(subject.gate_values.groups).to be_empty
|
1096
1108
|
subject.enable_group('five_only')
|
1097
1109
|
expect(subject.gate_values.groups).to eq(Set['five_only'])
|
@@ -1102,7 +1114,6 @@ RSpec.describe Flipper::Feature do
|
|
1102
1114
|
|
1103
1115
|
context 'with group instance' do
|
1104
1116
|
it 'updates the gate values for the group' do
|
1105
|
-
actor = Flipper::Actor.new(5)
|
1106
1117
|
group = Flipper.register(:five_only) { |actor| actor.flipper_id == 5 }
|
1107
1118
|
expect(subject.gate_values.groups).to be_empty
|
1108
1119
|
subject.enable_group(group)
|
@@ -18,7 +18,7 @@ RSpec.describe Flipper::Instrumentation::StatsdSubscriber do
|
|
18
18
|
Flipper.new(adapter, instrumenter: ActiveSupport::Notifications)
|
19
19
|
end
|
20
20
|
|
21
|
-
let(:user) {
|
21
|
+
let(:user) { Flipper::Actor.new('1') }
|
22
22
|
|
23
23
|
before do
|
24
24
|
described_class.client = statsd_client
|
@@ -80,7 +80,7 @@ RSpec.describe Flipper::Middleware::Memoizer do
|
|
80
80
|
context 'with preload: true' do
|
81
81
|
let(:app) do
|
82
82
|
# ensure scoped for builder block, annoying...
|
83
|
-
|
83
|
+
flipper
|
84
84
|
middleware = described_class
|
85
85
|
|
86
86
|
Rack::Builder.new do
|
@@ -141,7 +141,7 @@ RSpec.describe Flipper::Middleware::Memoizer do
|
|
141
141
|
context 'with preload specific' do
|
142
142
|
let(:app) do
|
143
143
|
# ensure scoped for builder block, annoying...
|
144
|
-
|
144
|
+
flipper
|
145
145
|
middleware = described_class
|
146
146
|
|
147
147
|
Rack::Builder.new do
|
@@ -266,7 +266,7 @@ RSpec.describe Flipper::Middleware::Memoizer do
|
|
266
266
|
context 'with multiple instances' do
|
267
267
|
let(:app) do
|
268
268
|
# ensure scoped for builder block, annoying...
|
269
|
-
|
269
|
+
flipper
|
270
270
|
middleware = described_class
|
271
271
|
|
272
272
|
Rack::Builder.new do
|
@@ -285,7 +285,7 @@ RSpec.describe Flipper::Middleware::Memoizer do
|
|
285
285
|
end
|
286
286
|
|
287
287
|
def get(uri, params = {}, env = {}, &block)
|
288
|
-
|
288
|
+
capture_output { super(uri, params, env, &block) }
|
289
289
|
end
|
290
290
|
|
291
291
|
include_examples 'flipper middleware'
|
@@ -316,7 +316,7 @@ RSpec.describe Flipper::Middleware::Memoizer do
|
|
316
316
|
context 'with flipper setup in env' do
|
317
317
|
let(:app) do
|
318
318
|
# ensure scoped for builder block, annoying...
|
319
|
-
|
319
|
+
flipper
|
320
320
|
middleware = described_class
|
321
321
|
|
322
322
|
Rack::Builder.new do
|
@@ -460,7 +460,6 @@ RSpec.describe Flipper::Middleware::Memoizer do
|
|
460
460
|
cache.clear
|
461
461
|
cached = Flipper::Adapters::ActiveSupportCacheStore.new(logged_memory, cache)
|
462
462
|
logged_cached = Flipper::Adapters::OperationLogger.new(cached)
|
463
|
-
memo = {}
|
464
463
|
flipper = Flipper.new(logged_cached)
|
465
464
|
flipper[:stats].enable
|
466
465
|
flipper[:shiny].enable
|
@@ -30,9 +30,20 @@ RSpec.describe Flipper::Model::ActiveRecord do
|
|
30
30
|
include Flipper::Model::ActiveRecord
|
31
31
|
end
|
32
32
|
|
33
|
+
class DelegatedUser < DelegateClass(User)
|
34
|
+
end
|
35
|
+
|
33
36
|
class Admin < User
|
34
37
|
end
|
35
38
|
|
39
|
+
it "doesn't warn for to_ary" do
|
40
|
+
# looks like we should remove this but you are wrong, we have specs that
|
41
|
+
# fail if there are warnings and if this regresses it will print a warning
|
42
|
+
# so it is in fact testing something
|
43
|
+
user = User.create!(name: "Test")
|
44
|
+
Flipper.enabled?(:something, DelegatedUser.new(user))
|
45
|
+
end
|
46
|
+
|
36
47
|
describe "flipper_id" do
|
37
48
|
it "returns class name and id" do
|
38
49
|
expect(User.new(id: 1).flipper_id).to eq("User;1")
|
data/spec/flipper_spec.rb
CHANGED
@@ -313,7 +313,7 @@ RSpec.describe Flipper do
|
|
313
313
|
|
314
314
|
describe '.group_exists' do
|
315
315
|
it 'returns true if the group is already created' do
|
316
|
-
|
316
|
+
described_class.register('admins', &:admin?)
|
317
317
|
expect(described_class.group_exists?(:admins)).to eq(true)
|
318
318
|
end
|
319
319
|
|
data/spec/spec_helper.rb
CHANGED
@@ -2,12 +2,14 @@ $LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
|
|
2
2
|
|
3
3
|
require 'pp'
|
4
4
|
require 'pathname'
|
5
|
-
|
6
|
-
|
7
|
-
require 'rubygems'
|
8
|
-
require 'bundler'
|
5
|
+
require 'bundler/setup'
|
9
6
|
|
10
|
-
|
7
|
+
require 'warning'
|
8
|
+
Warning.ignore(/lib\/statsd/)
|
9
|
+
Warning.ignore(/lib\/debug\//)
|
10
|
+
Warning.ignore(/lib\/ice_age\//)
|
11
|
+
Warning.ignore(/lib\/moneta\//)
|
12
|
+
Warning.ignore(/lib\/mongo\//)
|
11
13
|
|
12
14
|
require 'debug'
|
13
15
|
require 'statsd'
|
@@ -20,6 +22,7 @@ require 'flipper/spec/shared_adapter_specs'
|
|
20
22
|
require 'flipper/ui'
|
21
23
|
require 'flipper/test_help'
|
22
24
|
|
25
|
+
FlipperRoot = Pathname(__FILE__).dirname.join('..').expand_path
|
23
26
|
Dir[FlipperRoot.join('spec/support/**/*.rb')].sort.each { |f| require f }
|
24
27
|
|
25
28
|
# Disable telemetry logging in specs.
|
@@ -27,6 +30,9 @@ ENV["FLIPPER_CLOUD_LOGGING_ENABLED"] = "false"
|
|
27
30
|
|
28
31
|
RSpec.configure do |config|
|
29
32
|
config.before(:example) do
|
33
|
+
# default stub for telemetry
|
34
|
+
stub_request(:post, "https://www.flippercloud.io/adapter/telemetry").
|
35
|
+
to_return(status: 200, body: "", headers: {})
|
30
36
|
Flipper::Cloud::Telemetry.reset if defined?(Flipper::Cloud::Telemetry) && Flipper::Cloud::Telemetry.respond_to?(:reset)
|
31
37
|
Flipper::Poller.reset if defined?(Flipper::Poller)
|
32
38
|
Flipper.unregister_groups
|
@@ -1,7 +1,7 @@
|
|
1
1
|
if ENV["CI"] || ENV["FAIL_ON_OUTPUT"]
|
2
2
|
RSpec.configure do |config|
|
3
3
|
config.around do |example|
|
4
|
-
output =
|
4
|
+
output = capture_output { example.run }
|
5
5
|
fail "Use `silence { }` to avoid printing to STDOUT/STDERR\n#{output}" unless output.empty?
|
6
6
|
end
|
7
7
|
end
|
@@ -79,11 +79,22 @@ module SpecHelpers
|
|
79
79
|
original_stdout = $stdout
|
80
80
|
|
81
81
|
# Redirect stderr and stdout
|
82
|
-
|
82
|
+
$stderr = $stdout = StringIO.new
|
83
|
+
|
84
|
+
yield
|
85
|
+
ensure
|
86
|
+
$stderr = original_stderr
|
87
|
+
$stdout = original_stdout
|
88
|
+
end
|
89
|
+
|
90
|
+
def capture_output
|
91
|
+
original_stderr = $stderr
|
92
|
+
original_stdout = $stdout
|
93
|
+
|
94
|
+
output = $stdout = $stderr = StringIO.new
|
83
95
|
|
84
96
|
yield
|
85
97
|
|
86
|
-
# Return output
|
87
98
|
output.string
|
88
99
|
ensure
|
89
100
|
$stderr = original_stderr
|
@@ -17,6 +17,11 @@ class SetupGeneratorTest < Rails::Generators::TestCase
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
+
test "generates an initializer" do
|
21
|
+
run_generator
|
22
|
+
assert_file 'config/initializers/flipper.rb', /Flipper\.configure/
|
23
|
+
end
|
24
|
+
|
20
25
|
test "does not invoke flipper:active_record generator if ActiveRecord adapter not defined" do
|
21
26
|
# Ensure adapter not defined
|
22
27
|
Flipper::Adapters.send(:remove_const, :ActiveRecord) rescue nil
|
data/test_rails/helper.rb
CHANGED
@@ -6,6 +6,7 @@ return unless Rails::VERSION::MAJOR >= 7
|
|
6
6
|
require "capybara/cuprite"
|
7
7
|
require "flipper"
|
8
8
|
require "flipper/test_help"
|
9
|
+
require "action_controller/railtie"
|
9
10
|
|
10
11
|
require 'action_dispatch/system_testing/server'
|
11
12
|
ActionDispatch::SystemTesting::Server.silence_puma = true
|