flipflop 2.0.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.
Files changed (59) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +5 -0
  3. data/.travis.yml +51 -0
  4. data/Gemfile +20 -0
  5. data/LICENSE +22 -0
  6. data/README.md +261 -0
  7. data/Rakefile +16 -0
  8. data/app/assets/stylesheets/flipflop.scss +109 -0
  9. data/app/controllers/concerns/flipflop/environment_filters.rb +5 -0
  10. data/app/controllers/flipflop/features_controller.rb +59 -0
  11. data/app/controllers/flipflop/strategies_controller.rb +30 -0
  12. data/app/models/flipflop/feature.rb +3 -0
  13. data/app/views/flipflop/features/index.html.erb +60 -0
  14. data/app/views/layouts/flipflop.html.erb +1 -0
  15. data/config/routes.rb +5 -0
  16. data/flipflop.gemspec +23 -0
  17. data/lib/flipflop/configurable.rb +27 -0
  18. data/lib/flipflop/engine.rb +58 -0
  19. data/lib/flipflop/facade.rb +23 -0
  20. data/lib/flipflop/feature_cache.rb +64 -0
  21. data/lib/flipflop/feature_definition.rb +15 -0
  22. data/lib/flipflop/feature_set.rb +99 -0
  23. data/lib/flipflop/strategies/abstract_strategy.rb +103 -0
  24. data/lib/flipflop/strategies/active_record_strategy.rb +43 -0
  25. data/lib/flipflop/strategies/cookie_strategy.rb +44 -0
  26. data/lib/flipflop/strategies/default_strategy.rb +15 -0
  27. data/lib/flipflop/strategies/lambda_strategy.rb +25 -0
  28. data/lib/flipflop/strategies/query_string_strategy.rb +17 -0
  29. data/lib/flipflop/strategies/session_strategy.rb +29 -0
  30. data/lib/flipflop/strategies/test_strategy.rb +40 -0
  31. data/lib/flipflop/version.rb +3 -0
  32. data/lib/flipflop.rb +26 -0
  33. data/lib/generators/flipflop/features/USAGE +8 -0
  34. data/lib/generators/flipflop/features/features_generator.rb +7 -0
  35. data/lib/generators/flipflop/features/templates/features.rb +21 -0
  36. data/lib/generators/flipflop/install/install_generator.rb +21 -0
  37. data/lib/generators/flipflop/migration/USAGE +5 -0
  38. data/lib/generators/flipflop/migration/migration_generator.rb +23 -0
  39. data/lib/generators/flipflop/migration/templates/create_features.rb +10 -0
  40. data/lib/generators/flipflop/routes/USAGE +7 -0
  41. data/lib/generators/flipflop/routes/routes_generator.rb +5 -0
  42. data/test/integration/app_test.rb +32 -0
  43. data/test/integration/dashboard_test.rb +162 -0
  44. data/test/test_helper.rb +96 -0
  45. data/test/unit/configurable_test.rb +104 -0
  46. data/test/unit/feature_cache_test.rb +142 -0
  47. data/test/unit/feature_definition_test.rb +42 -0
  48. data/test/unit/feature_set_test.rb +136 -0
  49. data/test/unit/flipflop_test.rb +99 -0
  50. data/test/unit/strategies/abstract_strategy_request_test.rb +42 -0
  51. data/test/unit/strategies/abstract_strategy_test.rb +124 -0
  52. data/test/unit/strategies/active_record_strategy_test.rb +157 -0
  53. data/test/unit/strategies/cookie_strategy_test.rb +126 -0
  54. data/test/unit/strategies/default_strategy_test.rb +44 -0
  55. data/test/unit/strategies/lambda_strategy_test.rb +137 -0
  56. data/test/unit/strategies/query_string_strategy_test.rb +70 -0
  57. data/test/unit/strategies/session_strategy_test.rb +101 -0
  58. data/test/unit/strategies/test_strategy_test.rb +76 -0
  59. metadata +134 -0
@@ -0,0 +1,44 @@
1
+ require File.expand_path("../../../test_helper", __FILE__)
2
+
3
+ describe Flipflop::Strategies::DefaultStrategy do
4
+ before do
5
+ Flipflop.configure do
6
+ feature :one, default: true
7
+ feature :two
8
+ end
9
+ end
10
+
11
+ describe "with defaults" do
12
+ subject do
13
+ Flipflop::Strategies::DefaultStrategy.new.freeze
14
+ end
15
+
16
+ it "should have default name" do
17
+ assert_equal "default", subject.name
18
+ end
19
+
20
+ it "should have no default description" do
21
+ assert_equal "Uses feature default status.", subject.description
22
+ end
23
+
24
+ it "should not be switchable" do
25
+ assert_equal false, subject.switchable?
26
+ end
27
+
28
+ it "should have unique key" do
29
+ assert_match /^\d+$/, subject.key
30
+ end
31
+
32
+ describe "with explicitly defaulted feature" do
33
+ it "should have feature enabled" do
34
+ assert_equal true, subject.enabled?(:one)
35
+ end
36
+ end
37
+
38
+ describe "with implicitly defaulted feature" do
39
+ it "should not have feature enabled" do
40
+ assert_equal false, subject.enabled?(:two)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,137 @@
1
+ require File.expand_path("../../../test_helper", __FILE__)
2
+
3
+ describe Flipflop::Strategies::LambdaStrategy do
4
+ subject do
5
+ Flipflop::Strategies::LambdaStrategy.new.freeze
6
+ end
7
+
8
+ describe "with defaults" do
9
+ it "should have default name" do
10
+ assert_equal "lambda", subject.name
11
+ end
12
+
13
+ it "should not have default description" do
14
+ assert_equal "Resolves feature settings with custom code.",
15
+ subject.description
16
+ end
17
+
18
+ it "should not be switchable" do
19
+ assert_equal false, subject.switchable?
20
+ end
21
+
22
+ it "should have unique key" do
23
+ assert_match /^\d+$/, subject.key
24
+ end
25
+ end
26
+
27
+ describe "with lambda" do
28
+ attr_accessor :features
29
+
30
+ before do
31
+ self.features = {}
32
+ end
33
+
34
+ subject do
35
+ features = self.features
36
+ Flipflop::Strategies::LambdaStrategy.new(lambda: ->(feature) { features[feature] }).freeze
37
+ end
38
+
39
+ describe "with enabled feature" do
40
+ before do
41
+ features[:one] = true
42
+ end
43
+
44
+ it "should have feature enabled" do
45
+ assert_equal true, subject.enabled?(:one)
46
+ end
47
+ end
48
+
49
+ describe "with disabled feature" do
50
+ before do
51
+ features[:two] = false
52
+ end
53
+
54
+ it "should not have feature enabled" do
55
+ assert_equal false, subject.enabled?(:two)
56
+ end
57
+ end
58
+
59
+ describe "with unknown feature" do
60
+ it "should not know feature" do
61
+ assert_nil subject.enabled?(:three)
62
+ end
63
+ end
64
+ end
65
+
66
+ describe "with request lambda" do
67
+ subject do
68
+ Flipflop::Strategies::LambdaStrategy.new(lambda: ->(feature) {
69
+ request.params[feature]
70
+ }).freeze
71
+ end
72
+
73
+ before do
74
+ Flipflop::Strategies::AbstractStrategy::RequestInterceptor.request = create_request
75
+ end
76
+
77
+ after do
78
+ Flipflop::Strategies::AbstractStrategy::RequestInterceptor.request = nil
79
+ end
80
+
81
+ describe "with enabled feature" do
82
+ before do
83
+ subject.send(:request).params[:one] = true
84
+ end
85
+
86
+ it "should have feature enabled" do
87
+ assert_equal true, subject.enabled?(:one)
88
+ end
89
+ end
90
+ end
91
+
92
+ describe "with non conforming parameters" do
93
+ subject do
94
+ Flipflop::Strategies::LambdaStrategy.new(lambda: ->() { }).freeze
95
+ end
96
+
97
+ it "should raise error" do
98
+ assert_raises Flipflop::StrategyError do
99
+ subject
100
+ end
101
+ end
102
+
103
+ it "should raise with message" do
104
+ message = nil
105
+ begin
106
+ subject
107
+ rescue => err
108
+ message = err.message
109
+ end
110
+ assert_equal "Strategy 'lambda' has lambda with arity 0, expected 1 or -1.", message
111
+ end
112
+ end
113
+
114
+ describe "with non conforming return value" do
115
+ subject do
116
+ Flipflop::Strategies::LambdaStrategy.new(lambda: ->(feature) {
117
+ return feature
118
+ }).freeze
119
+ end
120
+
121
+ it "should raise error" do
122
+ assert_raises Flipflop::StrategyError do
123
+ subject.enabled?(:one)
124
+ end
125
+ end
126
+
127
+ it "should raise with message" do
128
+ message = nil
129
+ begin
130
+ subject.enabled?(:one)
131
+ rescue => err
132
+ message = err.message
133
+ end
134
+ assert_equal "Strategy 'lambda' returned invalid result :one for feature 'one'.", message
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,70 @@
1
+ require File.expand_path("../../../test_helper", __FILE__)
2
+
3
+ describe Flipflop::Strategies::QueryStringStrategy do
4
+ subject do
5
+ Flipflop::Strategies::QueryStringStrategy.new.freeze
6
+ end
7
+
8
+ describe "in request context" do
9
+ before do
10
+ Flipflop::Strategies::AbstractStrategy::RequestInterceptor.request = create_request
11
+ end
12
+
13
+ after do
14
+ Flipflop::Strategies::AbstractStrategy::RequestInterceptor.request = nil
15
+ end
16
+
17
+ it "should have default name" do
18
+ assert_equal "query_string", subject.name
19
+ end
20
+
21
+ it "should not have default description" do
22
+ assert_equal "Interprets query string parameters as features.",
23
+ subject.description
24
+ end
25
+
26
+ it "should not be switchable" do
27
+ assert_equal false, subject.switchable?
28
+ end
29
+
30
+ it "should have unique key" do
31
+ assert_match /^\d+$/, subject.key
32
+ end
33
+
34
+ describe "with enabled feature" do
35
+ before do
36
+ subject.send(:request).params[:one] = "1"
37
+ end
38
+
39
+ it "should have feature enabled" do
40
+ assert_equal true, subject.enabled?(:one)
41
+ end
42
+ end
43
+
44
+ describe "with disabled feature" do
45
+ before do
46
+ subject.send(:request).params[:two] = "0"
47
+ end
48
+
49
+ it "should not have feature enabled" do
50
+ assert_equal false, subject.enabled?(:two)
51
+ end
52
+ end
53
+
54
+ describe "with unknown feature" do
55
+ it "should not know feature" do
56
+ assert_nil subject.enabled?(:three)
57
+ end
58
+ end
59
+ end
60
+
61
+ describe "outside request context" do
62
+ it "should not know feature" do
63
+ assert_nil subject.enabled?(:one)
64
+ end
65
+
66
+ it "should not be switchable" do
67
+ assert_equal false, subject.switchable?
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,101 @@
1
+ require File.expand_path("../../../test_helper", __FILE__)
2
+
3
+ describe Flipflop::Strategies::SessionStrategy do
4
+ subject do
5
+ Flipflop::Strategies::SessionStrategy.new.freeze
6
+ end
7
+
8
+ describe "in request context" do
9
+ before do
10
+ Flipflop::Strategies::AbstractStrategy::RequestInterceptor.request = create_request
11
+ end
12
+
13
+ after do
14
+ Flipflop::Strategies::AbstractStrategy::RequestInterceptor.request = nil
15
+ end
16
+
17
+ it "should have default name" do
18
+ assert_equal "session", subject.name
19
+ end
20
+
21
+ it "should have default description" do
22
+ assert_equal "Stores features in the user session. Applies to current user.",
23
+ subject.description
24
+ end
25
+
26
+ it "should be switchable" do
27
+ assert_equal true, subject.switchable?
28
+ end
29
+
30
+ it "should have unique key" do
31
+ assert_match /^\d+$/, subject.key
32
+ end
33
+
34
+ describe "with enabled feature" do
35
+ before do
36
+ subject.send(:request).session[:one] = true
37
+ end
38
+
39
+ it "should have feature enabled" do
40
+ assert_equal true, subject.enabled?(:one)
41
+ end
42
+
43
+ it "should be able to switch feature off" do
44
+ subject.switch!(:one, false)
45
+ assert_equal false, subject.enabled?(:one)
46
+ end
47
+
48
+ it "should be able to clear feature" do
49
+ subject.clear!(:one)
50
+ assert_nil subject.enabled?(:one)
51
+ end
52
+ end
53
+
54
+ describe "with disabled feature" do
55
+ before do
56
+ subject.send(:request).session[:two] = false
57
+ end
58
+
59
+ it "should not have feature enabled" do
60
+ assert_equal false, subject.enabled?(:two)
61
+ end
62
+
63
+ it "should be able to switch feature on" do
64
+ subject.switch!(:two, true)
65
+ assert_equal true, subject.enabled?(:two)
66
+ end
67
+
68
+ it "should be able to clear feature" do
69
+ subject.clear!(:two)
70
+ assert_nil subject.enabled?(:two)
71
+ end
72
+ end
73
+
74
+ describe "with unsessioned feature" do
75
+ it "should not know feature" do
76
+ assert_nil subject.enabled?(:three)
77
+ end
78
+
79
+ it "should be able to switch feature on" do
80
+ subject.switch!(:three, true)
81
+ assert_equal true, subject.enabled?(:three)
82
+ end
83
+ end
84
+ end
85
+
86
+ describe "outside request context" do
87
+ it "should not know feature" do
88
+ assert_nil subject.enabled?(:one)
89
+ end
90
+
91
+ it "should not be switchable" do
92
+ assert_equal false, subject.switchable?
93
+ end
94
+
95
+ it "should not be able to switch feature on" do
96
+ assert_raises Flipflop::StrategyError do
97
+ subject.switch!(:one, true)
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,76 @@
1
+ require File.expand_path("../../../test_helper", __FILE__)
2
+
3
+ describe Flipflop::Strategies::TestStrategy do
4
+ describe "with defaults" do
5
+ subject do
6
+ Flipflop::Strategies::TestStrategy.new.freeze
7
+ end
8
+
9
+ it "should have default name" do
10
+ assert_equal "test", subject.name
11
+ end
12
+
13
+ it "should not have default description" do
14
+ assert_nil subject.description
15
+ end
16
+
17
+ it "should be switchable" do
18
+ assert_equal true, subject.switchable?
19
+ end
20
+
21
+ it "should have unique key" do
22
+ assert_match /^\d+$/, subject.key
23
+ end
24
+
25
+ describe "with enabled feature" do
26
+ before do
27
+ subject.switch!(:one, true)
28
+ end
29
+
30
+ it "should have feature enabled" do
31
+ assert_equal true, subject.enabled?(:one)
32
+ end
33
+
34
+ it "should be able to switch feature off" do
35
+ subject.switch!(:one, false)
36
+ assert_equal false, subject.enabled?(:one)
37
+ end
38
+
39
+ it "should be able to clear feature" do
40
+ subject.clear!(:one)
41
+ assert_nil subject.enabled?(:one)
42
+ end
43
+ end
44
+
45
+ describe "with disabled feature" do
46
+ before do
47
+ subject.switch!(:two, false)
48
+ end
49
+
50
+ it "should not have feature enabled" do
51
+ assert_equal false, subject.enabled?(:two)
52
+ end
53
+
54
+ it "should be able to switch feature on" do
55
+ subject.switch!(:two, true)
56
+ assert_equal true, subject.enabled?(:two)
57
+ end
58
+
59
+ it "should be able to clear feature" do
60
+ subject.clear!(:two)
61
+ assert_nil subject.enabled?(:two)
62
+ end
63
+ end
64
+
65
+ describe "with unsaved feature" do
66
+ it "should not know feature" do
67
+ assert_nil subject.enabled?(:three)
68
+ end
69
+
70
+ it "should be able to switch feature on" do
71
+ subject.switch!(:three, true)
72
+ assert_equal true, subject.enabled?(:three)
73
+ end
74
+ end
75
+ end
76
+ end
metadata ADDED
@@ -0,0 +1,134 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: flipflop
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Paul Annesley
8
+ - Rolf Timmermans
9
+ - Jippe Holwerda
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2016-03-17 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activesupport
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '4.0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ! '>='
27
+ - !ruby/object:Gem::Version
28
+ version: '4.0'
29
+ - !ruby/object:Gem::Dependency
30
+ name: bootstrap
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ~>
34
+ - !ruby/object:Gem::Version
35
+ version: 4.0.0.alpha3
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ~>
41
+ - !ruby/object:Gem::Version
42
+ version: 4.0.0.alpha3
43
+ description: Declarative API for specifying features, switchable in declaration, database
44
+ and cookies.
45
+ email:
46
+ - paul@annesley.cc
47
+ - rolftimmermans@voormedia.com
48
+ - jippeholwerda@voormedia.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - .gitignore
54
+ - .travis.yml
55
+ - Gemfile
56
+ - LICENSE
57
+ - README.md
58
+ - Rakefile
59
+ - app/assets/stylesheets/flipflop.scss
60
+ - app/controllers/concerns/flipflop/environment_filters.rb
61
+ - app/controllers/flipflop/features_controller.rb
62
+ - app/controllers/flipflop/strategies_controller.rb
63
+ - app/models/flipflop/feature.rb
64
+ - app/views/flipflop/features/index.html.erb
65
+ - app/views/layouts/flipflop.html.erb
66
+ - config/routes.rb
67
+ - flipflop.gemspec
68
+ - lib/flipflop.rb
69
+ - lib/flipflop/configurable.rb
70
+ - lib/flipflop/engine.rb
71
+ - lib/flipflop/facade.rb
72
+ - lib/flipflop/feature_cache.rb
73
+ - lib/flipflop/feature_definition.rb
74
+ - lib/flipflop/feature_set.rb
75
+ - lib/flipflop/strategies/abstract_strategy.rb
76
+ - lib/flipflop/strategies/active_record_strategy.rb
77
+ - lib/flipflop/strategies/cookie_strategy.rb
78
+ - lib/flipflop/strategies/default_strategy.rb
79
+ - lib/flipflop/strategies/lambda_strategy.rb
80
+ - lib/flipflop/strategies/query_string_strategy.rb
81
+ - lib/flipflop/strategies/session_strategy.rb
82
+ - lib/flipflop/strategies/test_strategy.rb
83
+ - lib/flipflop/version.rb
84
+ - lib/generators/flipflop/features/USAGE
85
+ - lib/generators/flipflop/features/features_generator.rb
86
+ - lib/generators/flipflop/features/templates/features.rb
87
+ - lib/generators/flipflop/install/install_generator.rb
88
+ - lib/generators/flipflop/migration/USAGE
89
+ - lib/generators/flipflop/migration/migration_generator.rb
90
+ - lib/generators/flipflop/migration/templates/create_features.rb
91
+ - lib/generators/flipflop/routes/USAGE
92
+ - lib/generators/flipflop/routes/routes_generator.rb
93
+ - test/integration/app_test.rb
94
+ - test/integration/dashboard_test.rb
95
+ - test/test_helper.rb
96
+ - test/unit/configurable_test.rb
97
+ - test/unit/feature_cache_test.rb
98
+ - test/unit/feature_definition_test.rb
99
+ - test/unit/feature_set_test.rb
100
+ - test/unit/flipflop_test.rb
101
+ - test/unit/strategies/abstract_strategy_request_test.rb
102
+ - test/unit/strategies/abstract_strategy_test.rb
103
+ - test/unit/strategies/active_record_strategy_test.rb
104
+ - test/unit/strategies/cookie_strategy_test.rb
105
+ - test/unit/strategies/default_strategy_test.rb
106
+ - test/unit/strategies/lambda_strategy_test.rb
107
+ - test/unit/strategies/query_string_strategy_test.rb
108
+ - test/unit/strategies/session_strategy_test.rb
109
+ - test/unit/strategies/test_strategy_test.rb
110
+ homepage: https://github.com/voormedia/flipflop
111
+ licenses:
112
+ - MIT
113
+ metadata: {}
114
+ post_install_message:
115
+ rdoc_options: []
116
+ require_paths:
117
+ - lib
118
+ required_ruby_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ! '>='
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ required_rubygems_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ! '>='
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ requirements: []
129
+ rubyforge_project:
130
+ rubygems_version: 2.4.5
131
+ signing_key:
132
+ specification_version: 4
133
+ summary: A feature flipflopper for Rails web applications.
134
+ test_files: []