flip_fab 1.0.0 → 1.0.16
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/dependabot.yml +18 -0
- data/.github/workflows/dobby-actions.yml +29 -0
- data/.github/workflows/gem-publish.yml +46 -0
- data/.github/workflows/version-forget-me-not.yml +19 -0
- data/.gitignore +2 -0
- data/.rubocop.yml +31 -0
- data/.rubocop_todo.yml +58 -0
- data/.ruby-version +1 -0
- data/.semaphore/semaphore.yml +49 -0
- data/CODEOWNERS +3 -0
- data/Gemfile +0 -12
- data/README.md +8 -2
- data/_pipeline/step_build_gem.sh +5 -0
- data/_pipeline/step_test_gem.sh +6 -0
- data/catalog-info.yaml +8 -0
- data/example/rails_app/Gemfile +4 -21
- data/example/rails_app/Rakefile +1 -1
- data/example/rails_app/app/assets/config/manifest.js +3 -0
- data/example/rails_app/app/assets/javascripts/application.js +0 -1
- data/example/rails_app/app/controllers/beavers_controller.rb +12 -13
- data/example/rails_app/bin/bundle +1 -1
- data/example/rails_app/bin/rails +1 -1
- data/example/rails_app/config/application.rb +2 -2
- data/example/rails_app/config/boot.rb +1 -1
- data/example/rails_app/config/environment.rb +1 -1
- data/example/rails_app/config/environments/development.rb +1 -1
- data/example/rails_app/config/environments/test.rb +2 -2
- data/example/rails_app/config/initializers/cookies_serializer.rb +1 -1
- data/example/rails_app/config.ru +1 -1
- data/example/rails_app/db/schema.rb +5 -8
- data/example/rails_app/spec/rails_helper.rb +2 -2
- data/example/rails_app/spec/spec_helper.rb +0 -1
- data/example/rails_app/test/controllers/beavers_controller_test.rb +12 -12
- data/example/rails_app/test/test_helper.rb +1 -1
- data/flip_fab.gemspec +11 -5
- data/lib/flip_fab/contextual_feature.rb +23 -19
- data/lib/flip_fab/cookie_persistence.rb +10 -17
- data/lib/flip_fab/feature.rb +2 -3
- data/lib/flip_fab/features_by_name.rb +5 -4
- data/lib/flip_fab/helper.rb +0 -1
- data/lib/flip_fab/persistence.rb +2 -3
- data/lib/flip_fab/version.rb +6 -1
- data/lib/flip_fab.rb +4 -4
- data/script/cibuild +10 -0
- data/spec/lib/flip_fab/contextual_feature_spec.rb +54 -57
- data/spec/lib/flip_fab/cookie_persistence.feature +3 -3
- data/spec/lib/flip_fab/cookie_persistence_spec.rb +36 -43
- data/spec/lib/flip_fab/feature_spec.rb +6 -9
- data/spec/lib/flip_fab/features_by_name_spec.rb +3 -6
- data/spec/lib/flip_fab/helper_spec.rb +35 -38
- data/spec/lib/flip_fab/persistence_spec.rb +2 -5
- data/spec/lib/flip_fab_spec.rb +11 -15
- data/spec/spec_helper.rb +47 -49
- data/spec/support/test_app.rb +2 -2
- data/spec/support/test_context.rb +1 -1
- data/spec/support/test_multiple_persistence.rb +2 -3
- data/spec/support/test_persistence.rb +2 -3
- data/spec/support/test_rack_context.rb +3 -3
- metadata +103 -11
- data/Gemfile.lock +0 -92
- data/example/rails_app/Gemfile.lock +0 -178
- data/example/rails_app/README.rdoc +0 -28
- data/example/rails_app/config/rabbit_feed.yml +0 -8
- data/example/rails_app/config/unicorn.rb +0 -4
@@ -3,66 +3,59 @@ require 'timecop'
|
|
3
3
|
|
4
4
|
module FlipFab
|
5
5
|
describe CookiePersistence do
|
6
|
-
let(:cookies) {
|
6
|
+
let(:cookies) {}
|
7
7
|
let(:context) { TestRackContext.new cookies, 'simplybusiness.co.uk' }
|
8
8
|
before { FlipFab.define_feature :example_feature }
|
9
9
|
after { FlipFab.features.clear }
|
10
|
-
subject{ described_class.new :example_feature, context }
|
10
|
+
subject { described_class.new :example_feature, context }
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
step 'the host is :host' do |host|
|
17
|
-
@host = host
|
18
|
-
end
|
12
|
+
feature do
|
13
|
+
step 'the host is :host' do |host|
|
14
|
+
@host = host
|
15
|
+
end
|
19
16
|
|
20
|
-
|
21
|
-
|
22
|
-
|
17
|
+
step 'the feature name is :feature_name' do |feature_name|
|
18
|
+
@feature_name = feature_name
|
19
|
+
end
|
23
20
|
|
24
|
-
|
25
|
-
|
26
|
-
|
21
|
+
step 'the time is :current_time' do |current_time|
|
22
|
+
Timecop.freeze(Time.parse(current_time))
|
23
|
+
end
|
27
24
|
|
28
|
-
|
29
|
-
|
30
|
-
|
25
|
+
step 'the state of the feature is :feature_state' do |feature_state|
|
26
|
+
@feature_state = feature_state
|
27
|
+
end
|
31
28
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
29
|
+
step 'I persist the feature state in a cookie' do
|
30
|
+
context = TestRackContext.new '', @host
|
31
|
+
(described_class.new @feature_name, context).write @feature_state
|
32
|
+
@cookie = context.response_cookies
|
33
|
+
end
|
37
34
|
|
38
|
-
|
39
|
-
|
40
|
-
|
35
|
+
step 'the cookie has the path :path' do |path|
|
36
|
+
expect(@cookie).to match(/path=#{path};/)
|
37
|
+
end
|
41
38
|
|
42
|
-
|
43
|
-
|
44
|
-
expect(@cookie).not_to match(/domain/)
|
45
|
-
else
|
46
|
-
expect(@cookie).to match(/domain=#{domain};/)
|
39
|
+
step 'the cookie does not have domain :domain' do |domain|
|
40
|
+
expect(@cookie).not_to match(/domain=#{domain};/)
|
47
41
|
end
|
48
|
-
end
|
49
42
|
|
50
|
-
|
51
|
-
|
52
|
-
|
43
|
+
step 'the cookie has the name :name' do |name|
|
44
|
+
expect(@cookie).to match(/\A#{name}.*/)
|
45
|
+
end
|
53
46
|
|
54
|
-
|
55
|
-
|
56
|
-
|
47
|
+
step 'the cookie expires at :expiration' do |expiration|
|
48
|
+
expect(@cookie).to match(/expires=#{expiration}\Z/)
|
49
|
+
end
|
57
50
|
|
58
|
-
|
59
|
-
|
51
|
+
step 'the cookie value is :value' do |value|
|
52
|
+
expect(@cookie).to match(/=#{value};/)
|
53
|
+
end
|
60
54
|
end
|
61
55
|
|
62
56
|
describe '#read' do
|
63
|
-
|
64
57
|
context 'when there is no existing cookie' do
|
65
|
-
let(:cookies) {
|
58
|
+
let(:cookies) {}
|
66
59
|
|
67
60
|
it 'returns nil' do
|
68
61
|
expect(subject.read).to be_nil
|
@@ -83,7 +76,7 @@ module FlipFab
|
|
83
76
|
after { Timecop.return }
|
84
77
|
|
85
78
|
it 'saves the feature state' do
|
86
|
-
expect{ subject.write :enabled }.to change{ context.response_cookies }.from(nil).to('flip_fab.example_feature=enabled;
|
79
|
+
expect { subject.write :enabled }.to change { context.response_cookies }.from(nil).to('flip_fab.example_feature=enabled; path=/; expires=Tue, 01 Jan 1991 00:00:00 GMT')
|
87
80
|
end
|
88
81
|
end
|
89
82
|
end
|
@@ -1,11 +1,10 @@
|
|
1
1
|
module FlipFab
|
2
2
|
describe Feature do
|
3
3
|
let(:name) { :example_test }
|
4
|
-
let(:options) {{ default: :enabled, persistence_adapters: [] }}
|
4
|
+
let(:options) { { default: :enabled, persistence_adapters: [] } }
|
5
5
|
subject { described_class.new name, options }
|
6
6
|
|
7
7
|
describe '.new' do
|
8
|
-
|
9
8
|
it 'assigns the name' do
|
10
9
|
expect(subject.name).to eq(:example_test)
|
11
10
|
end
|
@@ -36,9 +35,8 @@ module FlipFab
|
|
36
35
|
end
|
37
36
|
|
38
37
|
describe '#enabled?' do
|
39
|
-
|
40
38
|
context 'when the feature is enabled' do
|
41
|
-
let(:options) {{ default: :enabled, persistence_adapters: [] }}
|
39
|
+
let(:options) { { default: :enabled, persistence_adapters: [] } }
|
42
40
|
|
43
41
|
it 'returns true' do
|
44
42
|
expect(subject.enabled?).to be_truthy
|
@@ -46,7 +44,7 @@ module FlipFab
|
|
46
44
|
end
|
47
45
|
|
48
46
|
context 'when the feature is disabled' do
|
49
|
-
let(:options) {{ default: :disabled, persistence_adapters: [] }}
|
47
|
+
let(:options) { { default: :disabled, persistence_adapters: [] } }
|
50
48
|
|
51
49
|
it 'returns false' do
|
52
50
|
expect(subject.enabled?).to be_falsey
|
@@ -55,9 +53,8 @@ module FlipFab
|
|
55
53
|
end
|
56
54
|
|
57
55
|
describe '#disabled?' do
|
58
|
-
|
59
56
|
context 'when the feature is disabled' do
|
60
|
-
let(:options) {{ default: :disabled, persistence_adapters: [] }}
|
57
|
+
let(:options) { { default: :disabled, persistence_adapters: [] } }
|
61
58
|
|
62
59
|
it 'returns true' do
|
63
60
|
expect(subject.disabled?).to be_truthy
|
@@ -65,7 +62,7 @@ module FlipFab
|
|
65
62
|
end
|
66
63
|
|
67
64
|
context 'when the feature is enabled' do
|
68
|
-
let(:options) {{ default: :enabled, persistence_adapters: [] }}
|
65
|
+
let(:options) { { default: :enabled, persistence_adapters: [] } }
|
69
66
|
|
70
67
|
it 'returns false' do
|
71
68
|
expect(subject.disabled?).to be_falsey
|
@@ -77,7 +74,7 @@ module FlipFab
|
|
77
74
|
let(:context) { double(:context) }
|
78
75
|
|
79
76
|
it 'returns a contextual feature' do
|
80
|
-
expect(subject.with_context
|
77
|
+
expect(subject.with_context(context)).to be_a ContextualFeature
|
81
78
|
expect((subject.with_context context).feature).to eq(subject)
|
82
79
|
expect((subject.with_context context).context).to eq(context)
|
83
80
|
end
|
@@ -2,21 +2,18 @@ module FlipFab
|
|
2
2
|
describe FeaturesByName do
|
3
3
|
let(:feature) { Feature.new :example_feature }
|
4
4
|
let(:features) { { example_feature: feature } }
|
5
|
-
subject{ described_class.new features }
|
5
|
+
subject { described_class.new features }
|
6
6
|
|
7
7
|
describe '#[]' do
|
8
|
-
|
9
8
|
context 'when the feature exists' do
|
10
|
-
|
11
9
|
it 'returns the feature' do
|
12
10
|
expect(subject[:example_feature]).to eq(feature)
|
13
11
|
end
|
14
12
|
end
|
15
13
|
|
16
14
|
context 'when the feature does not exist' do
|
17
|
-
|
18
15
|
it 'raises' do
|
19
|
-
expect{ subject[:no_feature] }.to raise_error 'no feature has been defined with the name: no_feature'
|
16
|
+
expect { subject[:no_feature] }.to raise_error 'no feature has been defined with the name: no_feature'
|
20
17
|
end
|
21
18
|
end
|
22
19
|
end
|
@@ -25,7 +22,7 @@ module FlipFab
|
|
25
22
|
let(:context) { double(:context) }
|
26
23
|
|
27
24
|
it 'returns contextual features by name' do
|
28
|
-
expect(subject.with_context
|
25
|
+
expect(subject.with_context(context)).to be_a described_class
|
29
26
|
expect((subject.with_context context)[:example_feature]).to be_a ContextualFeature
|
30
27
|
expect((subject.with_context context)[:example_feature].feature).to eq(feature)
|
31
28
|
end
|
@@ -4,51 +4,49 @@ module FlipFab
|
|
4
4
|
describe Helper do
|
5
5
|
include Rack::Test::Methods
|
6
6
|
let(:app) { TestApp.new }
|
7
|
-
after
|
7
|
+
after { FlipFab.features.clear }
|
8
8
|
|
9
|
-
|
10
|
-
feature
|
11
|
-
|
12
|
-
|
13
|
-
step 'there is a feature with a default state of :default_state' do |default_state|
|
14
|
-
FlipFab.define_feature :example_feature, { default: default_state.to_sym, persistence_adapters: [TestPersistence] }
|
15
|
-
end
|
9
|
+
feature do
|
10
|
+
step 'there is a feature with a default state of :default_state' do |default_state|
|
11
|
+
FlipFab.define_feature :example_feature, default: default_state.to_sym, persistence_adapters: [TestPersistence]
|
12
|
+
end
|
16
13
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
14
|
+
step 'there are two contexts' do
|
15
|
+
@first_context = TestContext.new
|
16
|
+
@second_context = TestContext.new
|
17
|
+
end
|
21
18
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
19
|
+
step 'the feature is :expected_state_in_first_context in the first context, :expected_state_in_second_context in the second context' do |expected_state_in_first_context, expected_state_in_second_context|
|
20
|
+
expect(@first_context.features[:example_feature].enabled?).to eq(expected_state_in_first_context == 'enabled')
|
21
|
+
expect(@second_context.features[:example_feature].enabled?).to eq(expected_state_in_second_context == 'enabled')
|
22
|
+
end
|
26
23
|
|
27
|
-
|
28
|
-
|
29
|
-
|
24
|
+
step 'I :enable_or_disable the feature in the first context' do |enable_or_disable|
|
25
|
+
@first_context.features[:example_feature].send(enable_or_disable.to_sym)
|
26
|
+
end
|
30
27
|
|
31
|
-
|
32
|
-
|
33
|
-
|
28
|
+
step 'there is a feature with a default state of :default_state with cookie persistence' do |default_state|
|
29
|
+
FlipFab.define_feature :example_feature, default: default_state.to_sym
|
30
|
+
end
|
34
31
|
|
35
|
-
|
36
|
-
|
37
|
-
|
32
|
+
step 'I override the state in the URL parameters with :overridden_state' do |overridden_state|
|
33
|
+
get "/?example_feature=#{overridden_state}"
|
34
|
+
end
|
38
35
|
|
39
|
-
|
40
|
-
|
41
|
-
|
36
|
+
step 'the feature is :state for the user' do |state|
|
37
|
+
expect(app.contextual_features[:example_feature].enabled?).to eq(state == 'enabled')
|
38
|
+
end
|
42
39
|
|
43
|
-
|
44
|
-
|
40
|
+
step 'I :enable_or_disable the feature for the user' do |enable_or_disable|
|
41
|
+
app.contextual_features[:example_feature].send(enable_or_disable.to_sym)
|
42
|
+
end
|
45
43
|
end
|
46
44
|
|
47
45
|
describe '#features' do
|
48
|
-
let(:params) {{}}
|
49
|
-
let(:feature_states) {{ example_feature: :enabled }}
|
46
|
+
let(:params) { {} }
|
47
|
+
let(:feature_states) { { example_feature: :enabled } }
|
50
48
|
let(:context) { (TestContext.new feature_states, params) }
|
51
|
-
before { FlipFab.define_feature :example_feature,
|
49
|
+
before { FlipFab.define_feature :example_feature, persistence_adapters: [TestPersistence] }
|
52
50
|
subject { context.features }
|
53
51
|
|
54
52
|
it 'maps the features to contextual features by feature name' do
|
@@ -60,25 +58,24 @@ module FlipFab
|
|
60
58
|
end
|
61
59
|
|
62
60
|
context 'when the feature is overridden in the params' do
|
63
|
-
let(:params) {{'example_feature' => 'disabled'}}
|
61
|
+
let(:params) { { 'example_feature' => 'disabled' } }
|
64
62
|
|
65
63
|
it 'applies the override to the feature' do
|
66
64
|
expect(subject[:example_feature].disabled?).to be_truthy
|
67
65
|
end
|
68
66
|
|
69
67
|
it 'prevents the feature\'s state from being changed' do
|
70
|
-
expect{ subject[:example_feature].enable }.not_to change{ subject[:example_feature].enabled? }.from(false)
|
68
|
+
expect { subject[:example_feature].enable }.not_to change { subject[:example_feature].enabled? }.from(false)
|
71
69
|
end
|
72
70
|
end
|
73
71
|
|
74
72
|
context 'passing the context to the feature' do
|
75
|
-
|
76
73
|
it 'feature toggling is applied to the context' do
|
77
|
-
expect{ subject[:example_feature].disable }.to change{ subject[:example_feature].enabled? }.from(true).to(false)
|
74
|
+
expect { subject[:example_feature].disable }.to change { subject[:example_feature].enabled? }.from(true).to(false)
|
78
75
|
end
|
79
76
|
|
80
77
|
it 'feature toggling is persisted in the context' do
|
81
|
-
expect{ subject[:example_feature].disable }.to change{ feature_states }.from(
|
78
|
+
expect { subject[:example_feature].disable }.to change { feature_states }.from(example_feature: :enabled).to(example_feature: :disabled)
|
82
79
|
end
|
83
80
|
end
|
84
81
|
|
@@ -5,7 +5,6 @@ module FlipFab
|
|
5
5
|
subject { described_class.new feature_name, context }
|
6
6
|
|
7
7
|
describe '.new' do
|
8
|
-
|
9
8
|
it 'assigns the feature name' do
|
10
9
|
expect(subject.feature_name).to eq(:example_test)
|
11
10
|
end
|
@@ -16,16 +15,14 @@ module FlipFab
|
|
16
15
|
end
|
17
16
|
|
18
17
|
describe '#read' do
|
19
|
-
|
20
18
|
it 'is not implemented' do
|
21
|
-
expect{ subject.read }.to raise_error NotImplementedError
|
19
|
+
expect { subject.read }.to raise_error NotImplementedError
|
22
20
|
end
|
23
21
|
end
|
24
22
|
|
25
23
|
describe '#write' do
|
26
|
-
|
27
24
|
it 'is not implemented' do
|
28
|
-
expect{ subject.write feature_name }.to raise_error NotImplementedError
|
25
|
+
expect { subject.write feature_name }.to raise_error NotImplementedError
|
29
26
|
end
|
30
27
|
end
|
31
28
|
end
|
data/spec/lib/flip_fab_spec.rb
CHANGED
@@ -1,16 +1,14 @@
|
|
1
1
|
describe FlipFab do
|
2
2
|
let(:name) { :example_feature }
|
3
3
|
|
4
|
-
|
5
|
-
feature
|
6
|
-
|
7
|
-
|
8
|
-
step 'I define a feature that is :enabled_or_disabled' do |enabled_or_disabled|
|
9
|
-
described_class.define_feature name, { default: enabled_or_disabled.to_sym }
|
10
|
-
end
|
4
|
+
feature do
|
5
|
+
step 'I define a feature that is :enabled_or_disabled' do |enabled_or_disabled|
|
6
|
+
described_class.define_feature name, default: enabled_or_disabled.to_sym
|
7
|
+
end
|
11
8
|
|
12
|
-
|
13
|
-
|
9
|
+
step 'the feature is :enabled_or_disabled' do |enabled_or_disabled|
|
10
|
+
expect(described_class.features[name].enabled?).to eq(enabled_or_disabled == 'enabled')
|
11
|
+
end
|
14
12
|
end
|
15
13
|
|
16
14
|
it 'initializes features' do
|
@@ -18,8 +16,8 @@ describe FlipFab do
|
|
18
16
|
end
|
19
17
|
|
20
18
|
context '.define_feature' do
|
21
|
-
subject{ described_class.define_feature name }
|
22
|
-
after{ described_class.features.clear }
|
19
|
+
subject { described_class.define_feature name }
|
20
|
+
after { described_class.features.clear }
|
23
21
|
|
24
22
|
it 'returns the feature' do
|
25
23
|
expect(subject).to be_a FlipFab::Feature
|
@@ -27,18 +25,16 @@ describe FlipFab do
|
|
27
25
|
end
|
28
26
|
|
29
27
|
context 'when the feature exists' do
|
30
|
-
|
31
28
|
it 'overwrites the existing feature' do
|
32
29
|
existing_feature = described_class.define_feature name
|
33
|
-
expect{ subject }.not_to change{ described_class.features.count }.from(1)
|
30
|
+
expect { subject }.not_to change { described_class.features.count }.from(1)
|
34
31
|
expect(subject).not_to eq(existing_feature)
|
35
32
|
end
|
36
33
|
end
|
37
34
|
|
38
35
|
context 'when the feature does not exist' do
|
39
|
-
|
40
36
|
it 'saves the feature' do
|
41
|
-
expect{ subject }.to change{ described_class.features.count }.from(0).to(1)
|
37
|
+
expect { subject }.to change { described_class.features.count }.from(0).to(1)
|
42
38
|
expected_feature = subject
|
43
39
|
expect(described_class.features[:example_feature]).to eq(expected_feature)
|
44
40
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'flip_fab'
|
2
2
|
|
3
|
-
Dir['./spec/support/**/*.rb'].sort.each { |f| require f}
|
3
|
+
Dir['./spec/support/**/*.rb'].sort.each { |f| require f }
|
4
4
|
|
5
5
|
# This file was generated by the `rspec --init` command. Conventionally, all
|
6
6
|
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
@@ -42,52 +42,50 @@ RSpec.configure do |config|
|
|
42
42
|
mocks.verify_partial_doubles = true
|
43
43
|
end
|
44
44
|
|
45
|
-
# The settings below are suggested to provide a good initial experience
|
46
|
-
# with RSpec, but feel free to customize to your heart's content.
|
47
|
-
|
48
|
-
#
|
49
|
-
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
config.
|
53
|
-
|
54
|
-
|
55
|
-
#
|
56
|
-
#
|
57
|
-
# - http://
|
58
|
-
# - http://
|
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
|
-
Kernel.srand config.seed
|
92
|
-
=end
|
45
|
+
# The settings below are suggested to provide a good initial experience
|
46
|
+
# with RSpec, but feel free to customize to your heart's content.
|
47
|
+
# # These two settings work together to allow you to limit a spec run
|
48
|
+
# # to individual examples or groups you care about by tagging them with
|
49
|
+
# # `:focus` metadata. When nothing is tagged with `:focus`, all examples
|
50
|
+
# # get run.
|
51
|
+
# config.filter_run :focus
|
52
|
+
# config.run_all_when_everything_filtered = true
|
53
|
+
#
|
54
|
+
# # Limits the available syntax to the non-monkey patched syntax that is recommended.
|
55
|
+
# # For more details, see:
|
56
|
+
# # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
|
57
|
+
# # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
58
|
+
# # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
|
59
|
+
# config.disable_monkey_patching!
|
60
|
+
#
|
61
|
+
# # This setting enables warnings. It's recommended, but in some cases may
|
62
|
+
# # be too noisy due to issues in dependencies.
|
63
|
+
# config.warnings = true
|
64
|
+
#
|
65
|
+
# # Many RSpec users commonly either run the entire suite or an individual
|
66
|
+
# # file, and it's useful to allow more verbose output when running an
|
67
|
+
# # individual spec file.
|
68
|
+
# if config.files_to_run.one?
|
69
|
+
# # Use the documentation formatter for detailed output,
|
70
|
+
# # unless a formatter has already been configured
|
71
|
+
# # (e.g. via a command-line flag).
|
72
|
+
# config.default_formatter = 'doc'
|
73
|
+
# end
|
74
|
+
#
|
75
|
+
# # Print the 10 slowest examples and example groups at the
|
76
|
+
# # end of the spec run, to help surface which specs are running
|
77
|
+
# # particularly slow.
|
78
|
+
# config.profile_examples = 10
|
79
|
+
#
|
80
|
+
# # Run specs in random order to surface order dependencies. If you find an
|
81
|
+
# # order dependency and want to debug it, you can fix the order by providing
|
82
|
+
# # the seed, which is printed after each run.
|
83
|
+
# # --seed 1234
|
84
|
+
# config.order = :random
|
85
|
+
#
|
86
|
+
# # Seed global randomization in this process using the `--seed` CLI option.
|
87
|
+
# # Setting this allows you to use `--seed` to deterministically reproduce
|
88
|
+
# # test failures related to randomization by passing the same `--seed` value
|
89
|
+
# # as the one that triggered the failure.
|
90
|
+
# Kernel.srand config.seed
|
93
91
|
end
|
data/spec/support/test_app.rb
CHANGED
@@ -3,14 +3,14 @@ class TestApp
|
|
3
3
|
|
4
4
|
attr_reader :request, :response, :params, :contextual_features
|
5
5
|
|
6
|
-
def call
|
6
|
+
def call(env)
|
7
7
|
@request = Rack::Request.new env
|
8
8
|
@response = Rack::Response.new
|
9
9
|
@params = request.params
|
10
10
|
|
11
11
|
@contextual_features = features
|
12
12
|
|
13
|
-
request.cookies.each{|k,v| response.set_cookie k, v }
|
13
|
+
request.cookies.each { |k, v| response.set_cookie k, v }
|
14
14
|
[response.status, response.header, response.body]
|
15
15
|
end
|
16
16
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
class TestMultiplePersistence < FlipFab::Persistence
|
2
|
-
|
3
|
-
def initialize feature_name, context
|
2
|
+
def initialize(feature_name, context)
|
4
3
|
super
|
5
4
|
end
|
6
5
|
|
@@ -8,7 +7,7 @@ class TestMultiplePersistence < FlipFab::Persistence
|
|
8
7
|
context.feature_states[:different_example_feature]
|
9
8
|
end
|
10
9
|
|
11
|
-
def write
|
10
|
+
def write(value)
|
12
11
|
context.feature_states[:different_example_feature] = value
|
13
12
|
end
|
14
13
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
class TestPersistence < FlipFab::Persistence
|
2
|
-
|
3
|
-
def initialize feature_name, context
|
2
|
+
def initialize(feature_name, context)
|
4
3
|
super
|
5
4
|
end
|
6
5
|
|
@@ -8,7 +7,7 @@ class TestPersistence < FlipFab::Persistence
|
|
8
7
|
context.feature_states[feature_name]
|
9
8
|
end
|
10
9
|
|
11
|
-
def write
|
10
|
+
def write(state)
|
12
11
|
context.feature_states[feature_name] = state
|
13
12
|
end
|
14
13
|
end
|
@@ -3,10 +3,10 @@ class TestRackContext
|
|
3
3
|
|
4
4
|
attr_reader :request, :response
|
5
5
|
|
6
|
-
def initialize
|
7
|
-
@request = Rack::Request.new(
|
6
|
+
def initialize(cookies, host)
|
7
|
+
@request = Rack::Request.new('HTTP_COOKIE' => cookies, 'HTTP_HOST' => host)
|
8
8
|
@response = Rack::Response.new
|
9
|
-
request.cookies.each{|k,v| response.set_cookie k, v }
|
9
|
+
request.cookies.each { |k, v| response.set_cookie k, v }
|
10
10
|
end
|
11
11
|
|
12
12
|
def response_cookies
|