feature_flipper 1.3.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1c3632c7d610b676c1221bcfa84bedd1bc95847e
4
+ data.tar.gz: 449a0a967eba941e1fad80ded4d69d142fe2d0a9
5
+ SHA512:
6
+ metadata.gz: 6420b8810495627b15340ae99042546f4887a8ee6e0427178ea75c23b2ccdfdda816ec26f8307cf3513e40fa74eeafaa6a08392310ac91bde215b672740c5eef
7
+ data.tar.gz: 6da97940ac703df35ca10d8f5c923c67c1aa1c2088abe9368e3aa41c9d473ed774c8a74c154955808e1dc2b2903f5930c34939511822a3ed1fba92ad3692a9b8
@@ -0,0 +1 @@
1
+ Gemfile.lock
@@ -0,0 +1,7 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.0
5
+ - 2.1
6
+ - 2.2
7
+ - 2.3.1
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/README.md CHANGED
@@ -1,12 +1,15 @@
1
1
  FeatureFlipper
2
2
  ==============
3
3
 
4
+ [![Gem Version](https://badge.fury.io/rb/feature_flipper.svg)](https://rubygems.org/gems/feature_flipper)
5
+ [![Build Status](https://travis-ci.org/theflow/feature_flipper.svg?branch=master)](https://travis-ci.org/theflow/feature_flipper)
6
+
4
7
  FeatureFlipper is a simple library that allows you to restrict certain blocks
5
8
  of code to certain environments. This is mainly useful in projects where
6
9
  you deploy your application from HEAD and don't use branches.
7
10
 
8
- Read more about the motivation in the
9
- [introductory blog post](http://engineering.qype.com/2010/06/03/how-we-work-flipping-features/).
11
+ Read more about using feature flips here:
12
+ [Feature Toggles](http://martinfowler.com/articles/feature-toggles.html).
10
13
 
11
14
  Install
12
15
  -------
@@ -18,35 +21,39 @@ FeatureFlipper is packaged as a gem:
18
21
  In your project you have to configure the path to the app specific
19
22
  configuration file after requiring FeatureFlipper:
20
23
 
21
- require 'feature_flipper'
22
- FeatureFlipper::Config.path_to_file = "#{RAILS_ROOT}/config/features.rb"
24
+ ```ruby
25
+ require 'feature_flipper'
26
+ FeatureFlipper::Config.path_to_file = "#{Rails.root}/config/features.rb"
27
+ ```
23
28
 
24
29
  Example config file
25
30
  -------------------
26
31
 
27
- FeatureFlipper.features do
28
- in_state :development do
29
- feature :rating_game, :description => 'play a game to get recommendations'
30
- end
32
+ ```ruby
33
+ FeatureFlipper.features do
34
+ in_state :development do
35
+ feature :rating_game, :description => 'play a game to get recommendations'
36
+ end
31
37
 
32
- in_state :live do
33
- feature :city_feed, :description => 'stream of content for each city'
34
- end
35
- end
38
+ in_state :live do
39
+ feature :city_feed, :description => 'stream of content for each city'
40
+ end
41
+ end
36
42
 
37
- FeatureFlipper::Config.states = {
38
- :development => ['development', 'test'].include?(Rails.env),
39
- :live => true
40
- }
43
+ FeatureFlipper.states do
44
+ state :development, ['development', 'test'].include?(Rails.env)
45
+ state :live, true
46
+ end
47
+ ```
41
48
 
42
49
  This is your complete features.rb config file. In the example there are two
43
- states: `:development` is active on development boxes and `:live` is always active
50
+ states: `:development` is active on development servers and `:live` is always active
44
51
  (this is the last state a feature goes through).
45
52
 
46
53
  The feature `:rating_game` is still in development and not shown on the
47
54
  production site. The feature `:city_feed` is done and already enabled
48
55
  everywhere. You transition features between states by just moving the line to
49
- the new state block.
56
+ the new state block and deploying your code.
50
57
 
51
58
  You can take a look at the `static_states.rb` in the examples folder to
52
59
  see this in detail.
@@ -61,7 +68,7 @@ FeatureFlipper cares about:
61
68
  * features
62
69
 
63
70
  You first define multiple 'states' which normally depend on the environment
64
- (for example: the state 'development' is only active on development boxes).
71
+ (for example: the state 'development' is only active on development servers).
65
72
  After that you add 'features' which correspond to logical chunks of work in
66
73
  your project. These features then move through the different states
67
74
  as they get developed (for example: :development -> :staging -> :live).
@@ -73,18 +80,23 @@ more detailed description, a ticket number, a date when it was started, etc.
73
80
  Features are always defined in a state, you cannot define a feature which
74
81
  doesn't belong to a state.
75
82
 
76
- in_state :development do
77
- feature :rating_game, :description => 'play a game to get recommendations'
78
- end
83
+ ```ruby
84
+ in_state :development do
85
+ feature :rating_game, :description => 'play a game to get recommendations'
86
+ end
87
+ ```
79
88
 
80
89
  ### Defining states
81
90
 
82
91
  A state is just a name and a boolean check. The check needs to evaluate to
83
92
  `true` when it is active. For a Rails app you can just use environments:
84
93
 
85
- FeatureFlipper::Config.states = {
86
- :development => ['development', 'test'].include?(Rails.env)
87
- }
94
+ ```ruby
95
+ FeatureFlipper.states do
96
+ state :development, ['development', 'test'].include?(Rails.env)
97
+ state :staging, ['staging', development', 'test'].include?(Rails.env)
98
+ end
99
+ ```
88
100
 
89
101
  Usage
90
102
  -----
@@ -92,21 +104,16 @@ Usage
92
104
  In your code you then use the `show_feature?` method to branch depending on
93
105
  wether a feature is active or not:
94
106
 
95
- if show_feature?(:rating_game)
96
- # new code
97
- else
98
- # old code
99
- end
107
+ ```ruby
108
+ if show_feature?(:rating_game)
109
+ # new code
110
+ else
111
+ # old code
112
+ end
113
+ ```
100
114
 
101
115
  The `show_feature?` method is defined on Object, so you can use it everywhere.
102
116
 
103
- Cleaning up
104
- -----------
105
-
106
- The drawback of this approach is that your code can get quite ugly with all
107
- these if/else branches. So you have to be strict about removing features
108
- (we call it de-featurizing) after they have gone live.
109
-
110
117
  Dynamic feature groups
111
118
  ----------------------
112
119
 
@@ -117,41 +124,20 @@ employees only or to a private beta group, etc.
117
124
 
118
125
  ### Defining dynamic states
119
126
 
120
- A dynamic state is defined a bit different than a normal, static state.
121
-
122
- FeatureFlipper::Config.states = {
123
- :development => ['development', 'test'].include?(Rails.env),
124
- :employees => { :required_state => :development, :feature_group => :employees }
125
- }
126
-
127
- It has a required state and a feature group. The feature group defines
128
- a symbolic name for the group of users who should see this feature. You
129
- can name this whatever you want. The required state is the state that gets
130
- looked at for all other users that aren't in the feature group. The required
131
- state (:development) must be a defined, static state.
132
-
133
- ### Setting the feature group
134
-
135
- The feature group is set globally and is active for the whole thread.
136
- In Rails you would define a before_filter like this:
137
-
138
- class ApplicationController < ActionController::Base
139
- before_filter :set_active_feature_group
140
-
141
- def set_active_feature_group
142
- # we need to reset the feature group in each request,
143
- # otherwise it's also active for the following requests.
144
- FeatureFlipper.reset_active_feature_groups
145
-
146
- if logged_in? && current_user.employee?
147
- FeatureFlipper.active_feature_groups << :employees
148
- end
149
- end
150
-
151
- Don't forget to reset the feature group, without it the feature group
152
- is active forever. The condition if someone is in a feature group
153
- can be anything: You can store it in the database, in Redis,
154
- look at request parameters, based on the current time, etc.
127
+ A dynamic state is defined using a Proc:
128
+
129
+ ```ruby
130
+ FeatureFlipper.states do
131
+ state :development, ['development', 'test'].include?(Rails.env)
132
+ state :employees, Proc.new { |feature_name| respond_to?(:current_user, true) && current_user.employee? }
133
+ end
134
+ ```
135
+
136
+ The Proc get's evaluated in the context of where you call the `show_feature?`
137
+ method from, so it depends on your app what you can do there. In a typical Rails
138
+ app you could do checks on the current user, as shown above. This way the condition
139
+ if someone should see a feature or not can be anything: You can store it in the
140
+ database, in Redis, look at request parameters, based on the current time, etc.
155
141
 
156
142
  Take a look at `dynamic_states.rb` in the examples folder to see this
157
143
  in detail.
@@ -159,16 +145,7 @@ in detail.
159
145
  Meta
160
146
  ----
161
147
 
162
- * Code: `git clone git://github.com/qype/feature_flipper.git`
163
- * Home: <http://github.com/qype/feature_flipper>
164
- * Bugs: <http://github.com/qype/feature_flipper/issues>
165
-
166
- This project uses [Semantic Versioning][sv].
167
-
168
- Author
169
- ------
170
-
171
- Florian Munz, Qype GmbH - florian@qype.com
172
-
148
+ * Home: <https://github.com/theflow/feature_flipper>
149
+ * Bugs: <https://github.com/theflow/feature_flipper/issues>
173
150
 
174
- [sv]: http://semver.org/
151
+ This project uses [Semantic Versioning](http://semver.org/).
data/Rakefile CHANGED
@@ -1,13 +1,9 @@
1
- require 'rake'
2
1
  require 'rake/testtask'
3
2
 
4
- desc 'Default: run unit tests'
5
- task :default => :test
6
-
7
- desc 'run the feature_flipper tests'
8
3
  Rake::TestTask.new(:test) do |t|
9
- t.libs << 'lib'
10
4
  t.libs << 'test'
11
- t.pattern = 'test/**/*_test.rb'
12
- t.verbose = true
5
+ t.libs << 'lib'
6
+ t.test_files = FileList['test/**/*_test.rb']
13
7
  end
8
+
9
+ task :default => :test
@@ -1,16 +1,30 @@
1
1
  # Setup
2
2
  #
3
3
 
4
- # just need this to make it work from within the library
4
+ # just need this to make it works from within the library
5
5
  $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
6
6
 
7
- # fake production Rails environment
7
+ # stub production Rails environment
8
8
  module Rails
9
9
  def self.env
10
10
  'production'
11
11
  end
12
12
  end
13
13
 
14
+ # stub current_user method
15
+ class User
16
+ def initialize(employee)
17
+ @employee = employee
18
+ end
19
+
20
+ def employee?
21
+ @employee == true
22
+ end
23
+ end
24
+
25
+ def current_user
26
+ @current_user
27
+ end
14
28
 
15
29
  # Configuration
16
30
  #
@@ -18,7 +32,7 @@ end
18
32
  require 'feature_flipper'
19
33
 
20
34
  # set the path to your app specific config file
21
- FeatureFlipper::Config.path_to_file = "features.rb"
35
+ FeatureFlipper::Config.path_to_file = File.expand_path('features.rb', File.dirname(__FILE__))
22
36
 
23
37
 
24
38
  # Usage
@@ -26,7 +40,10 @@ FeatureFlipper::Config.path_to_file = "features.rb"
26
40
 
27
41
  puts "=== first example:"
28
42
 
29
- # no active feature_group set, so the required_state of badges is looked at
43
+ # mock current user to not be a employee
44
+ @current_user = User.new(false)
45
+
46
+ # current user it not an employee and we are on prod, so no new badges
30
47
  if show_feature?(:badges)
31
48
  puts "shiny new badges not live on prod yet"
32
49
  else
@@ -35,13 +52,11 @@ end
35
52
 
36
53
  puts "\n=== second example:"
37
54
 
38
- # now we set the active feature_group. Usually depending on the logged in user
39
-
40
- FeatureFlipper.reset_active_feature_groups
41
- FeatureFlipper.active_feature_groups << :employees
55
+ # mock current user to be a employee
56
+ @current_user = User.new(true)
42
57
 
43
58
  if show_feature?(:badges)
44
- puts "shiny new badges for this user"
59
+ puts "shiny new badges for this employee"
45
60
  else
46
61
  puts "no new badges"
47
62
  end
@@ -17,8 +17,8 @@ FeatureFlipper.features do
17
17
  end
18
18
  end
19
19
 
20
- FeatureFlipper::Config.states = {
21
- :development => ['development', 'test'].include?(Rails.env),
22
- :employees => { :required_state => :development, :feature_group => :employees },
23
- :live => true
24
- }
20
+ FeatureFlipper.states do
21
+ state :development, ['development', 'test'].include?(Rails.env)
22
+ state :employees, Proc.new { |feature_name| respond_to?(:current_user, true) && current_user.employee? }
23
+ state :live, true
24
+ end
@@ -1,7 +1,7 @@
1
1
  # Setup
2
2
  #
3
3
 
4
- # just need this to make it work from within the library
4
+ # just need this to make it works from within the library
5
5
  $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
6
6
 
7
7
  # fake production Rails environment
@@ -18,7 +18,7 @@ end
18
18
  require 'feature_flipper'
19
19
 
20
20
  # set the path to your app specific config file
21
- FeatureFlipper::Config.path_to_file = "features.rb"
21
+ FeatureFlipper::Config.path_to_file = File.expand_path('features.rb', File.dirname(__FILE__))
22
22
 
23
23
 
24
24
  # Usage
@@ -0,0 +1,23 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'feature_flipper'
3
+ s.version = '2.0.0'
4
+ s.authors = ['Florian Munz']
5
+ s.email = 'surf@theflow.de'
6
+
7
+ s.summary = 'FeatureFlipper helps you flipping features'
8
+ s.description = <<desc
9
+ FeatureFlipper is a simple library that allows you to restrict certain blocks
10
+ of code to certain environments. This is mainly useful in projects where
11
+ you deploy your application from HEAD and don't use branches.
12
+ desc
13
+ s.homepage = 'http://github.com/theflow/feature_flipper'
14
+ s.license = 'MIT'
15
+
16
+ s.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ s.require_paths = ['lib']
20
+
21
+ s.add_development_dependency 'rake'
22
+ s.add_development_dependency 'minitest', "~> 5.0"
23
+ end
@@ -4,7 +4,7 @@ module FeatureFlipper
4
4
  @states = {}
5
5
 
6
6
  def self.path_to_file
7
- @path_to_file || File.join(Rails.root, 'config', 'features.rb')
7
+ @path_to_file
8
8
  end
9
9
 
10
10
  def self.path_to_file=(path_to_file)
@@ -19,6 +19,9 @@ module FeatureFlipper
19
19
  end
20
20
 
21
21
  def self.reload_config
22
+ @features = {}
23
+ @states = {}
24
+
22
25
  @config_loaded = false
23
26
  end
24
27
 
@@ -38,44 +41,37 @@ module FeatureFlipper
38
41
  @states = states
39
42
  end
40
43
 
41
- def self.active_features
42
- features.keys.select { |feature| is_active?(feature) }
43
- end
44
-
45
44
  def self.get_state(feature_name)
46
45
  feature = features[feature_name]
47
46
  feature ? feature[:state] : nil
48
47
  end
49
48
 
50
- def self.active_state?(state)
51
- active = states[state]
52
- if active.is_a?(Hash)
53
- if active.has_key?(:feature_group)
54
- group, required_state = active[:feature_group], active[:required_state]
49
+ def self.active_state?(state, feature_name, context = nil)
50
+ condition = states[state]
51
+ if condition.is_a?(Proc)
52
+ if context
53
+ context.instance_exec(feature_name, &condition)
55
54
  else
56
- group, required_state = active.to_a.flatten
55
+ condition.call(feature_name) == true
57
56
  end
58
- (FeatureFlipper.active_feature_groups.include?(group)) || (states[required_state] == true)
59
57
  else
60
- active == true
58
+ condition == true
61
59
  end
62
60
  end
63
61
 
64
- def self.is_active?(feature_name)
62
+ def self.is_active?(feature_name, context = nil)
65
63
  ensure_config_is_loaded
66
64
 
67
65
  state = get_state(feature_name)
68
- if state.is_a?(Symbol)
69
- active_state?(state)
70
- elsif state.is_a?(Proc)
71
- state.call == true
72
- else
73
- state == true
74
- end
66
+ active_state?(state, feature_name, context)
67
+ end
68
+
69
+ def self.active_features(context = nil)
70
+ self.features.collect { |key, value| self.is_active?(key, context) ? key : nil }.compact
75
71
  end
76
72
  end
77
73
 
78
- class Mapper
74
+ class FeatureMapper
79
75
  def initialize(state)
80
76
  @state = state
81
77
  end
@@ -85,21 +81,23 @@ module FeatureFlipper
85
81
  end
86
82
  end
87
83
 
88
- class StateMapper
84
+ class FeaturesMapper
89
85
  def in_state(state, &block)
90
- Mapper.new(state).instance_eval(&block)
86
+ FeatureMapper.new(state).instance_eval(&block)
91
87
  end
92
88
  end
93
89
 
94
- def self.features(&block)
95
- StateMapper.new.instance_eval(&block)
90
+ class StatesMapper
91
+ def state(name, condition = false)
92
+ FeatureFlipper::Config.states[name] = condition
93
+ end
96
94
  end
97
95
 
98
- def self.active_feature_groups
99
- Thread.current[:feature_system_active_feature_groups] ||= []
96
+ def self.features(&block)
97
+ FeaturesMapper.new.instance_eval(&block)
100
98
  end
101
99
 
102
- def self.reset_active_feature_groups
103
- active_feature_groups.clear
100
+ def self.states(&block)
101
+ StatesMapper.new.instance_eval(&block)
104
102
  end
105
103
  end
@@ -7,11 +7,11 @@ module FeatureFlipper
7
7
  end
8
8
 
9
9
  def show_feature?(feature_name)
10
- FeatureFlipper::Config.is_active?(feature_name)
10
+ FeatureFlipper::Config.is_active?(feature_name, self)
11
11
  end
12
-
12
+
13
13
  def active_features
14
- FeatureFlipper::Config.active_features
14
+ FeatureFlipper::Config.active_features(self)
15
15
  end
16
16
  end
17
17
  end
metadata CHANGED
@@ -1,73 +1,87 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: feature_flipper
3
- version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 1.3.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0
6
5
  platform: ruby
7
- authors:
6
+ authors:
8
7
  - Florian Munz
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
-
13
- date: 2011-02-28 00:00:00 +01:00
14
- default_executable:
15
- dependencies: []
16
-
11
+ date: 2017-05-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '5.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '5.0'
17
41
  description: |
18
42
  FeatureFlipper is a simple library that allows you to restrict certain blocks
19
43
  of code to certain environments. This is mainly useful in projects where
20
44
  you deploy your application from HEAD and don't use branches.
21
-
22
45
  email: surf@theflow.de
23
46
  executables: []
24
-
25
47
  extensions: []
26
-
27
48
  extra_rdoc_files: []
28
-
29
- files:
49
+ files:
50
+ - .gitignore
51
+ - .travis.yml
52
+ - Gemfile
53
+ - LICENSE
30
54
  - README.md
31
55
  - Rakefile
32
- - LICENSE
33
- - lib/feature_flipper/config.rb
34
- - lib/feature_flipper/show.rb
35
- - lib/feature_flipper/version.rb
36
- - lib/feature_flipper.rb
37
- - test/feature_flipper_test.rb
38
- - test/features.rb
39
- - test/features_dsl.rb
40
- - test/test_helper.rb
41
56
  - examples/dynamic_states.rb
42
57
  - examples/features.rb
43
58
  - examples/static_states.rb
44
- has_rdoc: true
45
- homepage: http://github.com/qype/feature_flipper
46
- licenses: []
47
-
59
+ - feature_flipper.gemspec
60
+ - lib/feature_flipper.rb
61
+ - lib/feature_flipper/config.rb
62
+ - lib/feature_flipper/show.rb
63
+ homepage: http://github.com/theflow/feature_flipper
64
+ licenses:
65
+ - MIT
66
+ metadata: {}
48
67
  post_install_message:
49
68
  rdoc_options: []
50
-
51
- require_paths:
69
+ require_paths:
52
70
  - lib
53
- required_ruby_version: !ruby/object:Gem::Requirement
54
- none: false
55
- requirements:
56
- - - ">="
57
- - !ruby/object:Gem::Version
58
- version: "0"
59
- required_rubygems_version: !ruby/object:Gem::Requirement
60
- none: false
61
- requirements:
62
- - - ">="
63
- - !ruby/object:Gem::Version
64
- version: "0"
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
65
81
  requirements: []
66
-
67
82
  rubyforge_project:
68
- rubygems_version: 1.5.0
83
+ rubygems_version: 2.0.14
69
84
  signing_key:
70
- specification_version: 3
85
+ specification_version: 4
71
86
  summary: FeatureFlipper helps you flipping features
72
87
  test_files: []
73
-
@@ -1,3 +0,0 @@
1
- module FeatureFlipper
2
- Version = VERSION = '1.3.0'
3
- end
@@ -1,126 +0,0 @@
1
- require 'test_helper'
2
-
3
- context 'hash based FeatureFlipper' do
4
- setup do
5
- FeatureFlipper::Config.path_to_file = 'features.rb'
6
- FeatureFlipper::Config.reload_config
7
- end
8
-
9
- test 'should show enabled features' do
10
- assert show_feature?(:live_feature)
11
- end
12
-
13
- test 'should not show disabled features' do
14
- assert !show_feature?(:disabled_feature)
15
- end
16
-
17
- test 'should not show a feature when on a higher environment' do
18
- Rails.stubs(:env).returns('production')
19
- assert !show_feature?(:dev_feature)
20
- end
21
-
22
- test 'show feature should work with booleans' do
23
- assert show_feature?(:boolean_feature)
24
- end
25
-
26
- test 'show feature should work with procs' do
27
- assert show_feature?(:proc_feature)
28
- end
29
-
30
- test 'should be able to get features' do
31
- FeatureFlipper::Config.ensure_config_is_loaded
32
- all_features = FeatureFlipper::Config.features
33
-
34
- assert_not_nil all_features
35
- assert all_features.is_a?(Hash)
36
- assert_equal :dev, all_features[:dev_feature][:state]
37
- assert_equal 'dev feature', all_features[:dev_feature][:description]
38
- end
39
- end
40
-
41
- context 'DSL based FeatureFlipper' do
42
- setup do
43
- FeatureFlipper::Config.path_to_file = 'features_dsl.rb'
44
- FeatureFlipper::Config.reload_config
45
- end
46
-
47
- test 'should show enabled features' do
48
- assert show_feature?(:live_feature)
49
- end
50
-
51
- test 'should not show a feature when on a higher environment' do
52
- Rails.stubs(:env).returns('production')
53
- assert !show_feature?(:dev_feature)
54
- end
55
-
56
- test 'show feature should work with booleans' do
57
- assert show_feature?(:boolean_feature)
58
- end
59
-
60
- test 'show feature should work with procs' do
61
- assert show_feature?(:proc_feature)
62
- end
63
-
64
- test 'should be able to get features' do
65
- FeatureFlipper::Config.ensure_config_is_loaded
66
- all_features = FeatureFlipper::Config.features
67
-
68
- assert_not_nil all_features
69
- assert all_features.is_a?(Hash)
70
- assert_equal :dev, all_features[:dev_feature][:state]
71
- assert_equal 'dev feature', all_features[:dev_feature][:description]
72
- end
73
-
74
- test 'should be able to get active features' do
75
- Rails.stubs(:env).returns('production')
76
- FeatureFlipper::Config.ensure_config_is_loaded
77
- active_features = FeatureFlipper::Config.active_features
78
-
79
- assert_equal 3, active_features.size
80
- assert active_features.include?(:live_feature)
81
- assert active_features.include?(:boolean_feature)
82
- assert active_features.include?(:proc_feature)
83
- end
84
-
85
- end
86
-
87
- context 'dynamic feature groups' do
88
- setup do
89
- FeatureFlipper::Config.path_to_file = 'features.rb'
90
- FeatureFlipper::Config.reload_config
91
- FeatureFlipper.reset_active_feature_groups
92
- end
93
-
94
- test 'should show a beta feature to the feature group' do
95
- Rails.stubs(:env).returns('production')
96
- FeatureFlipper.active_feature_groups << :beta_users
97
-
98
- assert show_feature?(:beta_feature_old)
99
- assert show_feature?(:beta_feature_new)
100
- end
101
-
102
- test 'should not show a beta feature if not in the group' do
103
- Rails.stubs(:env).returns('production')
104
- FeatureFlipper.active_feature_groups << :different_feature_group
105
-
106
- assert !show_feature?(:beta_feature_old)
107
- assert !show_feature?(:beta_feature_new)
108
- end
109
-
110
- test 'should always show a beta feature on dev' do
111
- Rails.stubs(:env).returns('development')
112
- FeatureFlipper.active_feature_groups << nil
113
-
114
- assert show_feature?(:beta_feature_old)
115
- assert show_feature?(:beta_feature_new)
116
- end
117
-
118
- test 'can be in two feature groups at the same time' do
119
- Rails.stubs(:env).returns('production')
120
- FeatureFlipper.active_feature_groups << :beta_users
121
- FeatureFlipper.active_feature_groups << :employees
122
-
123
- assert show_feature?(:beta_feature_new)
124
- assert show_feature?(:employee_feature)
125
- end
126
- end
@@ -1,20 +0,0 @@
1
- FeatureFlipper::Config.features = {
2
- :live_feature => { :state => :live },
3
- :disabled_feature => { :state => :disabled },
4
- :dev_feature => { :state => :dev, :description => 'dev feature' },
5
- :boolean_feature => { :state => true },
6
- :proc_feature => { :state => Proc.new { Date.today > Date.today - 84000 } },
7
- :beta_feature_old => { :state => :beta_old },
8
- :beta_feature_new => { :state => :beta_new },
9
- :employee_feature => { :state => :employees }
10
- }
11
-
12
-
13
- FeatureFlipper::Config.states = {
14
- :disabled => false,
15
- :dev => ['development', 'test'].include?(Rails.env),
16
- :beta_old => { :beta_users => :dev },
17
- :beta_new => { :required_state => :dev, :feature_group => :beta_users },
18
- :employees => { :required_state => :dev, :feature_group => :employees },
19
- :live => true
20
- }
@@ -1,23 +0,0 @@
1
- FeatureFlipper.features do
2
- in_state :dev do
3
- feature :dev_feature, :description => 'dev feature'
4
- end
5
-
6
- in_state :live do
7
- feature :live_feature
8
- end
9
-
10
- in_state true do
11
- feature :boolean_feature
12
- end
13
-
14
- in_state Proc.new { Date.today > Date.today - 84000 } do
15
- feature :proc_feature
16
- end
17
- end
18
-
19
-
20
- FeatureFlipper::Config.states = {
21
- :dev => ['development', 'test'].include?(Rails.env),
22
- :live => true
23
- }
@@ -1,38 +0,0 @@
1
- require 'test/unit'
2
- require 'rubygems'
3
-
4
- require 'mocha'
5
-
6
- ##
7
- # test/spec/mini 5
8
- # http://gist.github.com/307649
9
- # chris@ozmm.org
10
- #
11
- def context(*args, &block)
12
- return super unless (name = args.first) && block
13
- require 'test/unit'
14
- klass = Class.new(defined?(ActiveSupport::TestCase) ? ActiveSupport::TestCase : Test::Unit::TestCase) do
15
- def self.test(name, &block)
16
- define_method("test_#{name.to_s.gsub(/\W/,'_')}", &block) if block
17
- end
18
- def self.xtest(*args) end
19
- def self.context(*args, &block) instance_eval(&block) end
20
- def self.setup(&block)
21
- define_method(:setup) { self.class.setups.each { |s| instance_eval(&s) } }
22
- setups << block
23
- end
24
- def self.setups; @setups ||= [] end
25
- def self.teardown(&block) define_method(:teardown, &block) end
26
- end
27
- (class << klass; self end).send(:define_method, :name) { name.gsub(/\W/,'_') }
28
- klass.class_eval &block
29
- end
30
-
31
-
32
- module Rails
33
- def self.env
34
- 'test'
35
- end
36
- end
37
-
38
- require 'feature_flipper'