abstract_feature_branch 0.7.1 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +138 -37
- data/VERSION +1 -1
- data/abstract_feature_branch.gemspec +26 -11
- data/config/features/admin.local.yml +2 -1
- data/config/features/admin.yml +2 -1
- data/config/features/internal/wiki.local.yml +2 -1
- data/config/features/internal/wiki.yml +2 -1
- data/config/features/public.local.yml +2 -1
- data/config/features/public.yml +2 -1
- data/lib/abstract_feature_branch.rb +14 -3
- data/lib/abstract_feature_branch/file_beautifier.rb +63 -0
- data/lib/generators/abstract_feature_branch/install_generator.rb +1 -0
- data/lib/generators/templates/config/features.local.yml +1 -0
- data/lib/generators/templates/config/initializers/abstract_feature_branch.rb +3 -0
- data/lib/generators/templates/lib/tasks/abstract_feature_branch.rake +9 -0
- data/spec/abstract_feature_branch/file_beautifier_spec.rb +384 -0
- data/spec/ext/feature_branch__feature_branch_spec.rb +145 -0
- data/spec/ext/feature_branch__feature_enabled_spec.rb +84 -0
- data/spec/{application_no_config → fixtures/application_no_config}/no_config +0 -0
- data/spec/{application_rails_config → fixtures/application_rails_config}/config/features.local.yml +1 -0
- data/spec/{application_rails_config → fixtures/application_rails_config}/config/features.yml +0 -0
- data/spec/fixtures/application_ugly_config_reference/config/another_application_configuration.yml +31 -0
- data/spec/fixtures/application_ugly_config_reference/config/database.yml +17 -0
- data/spec/fixtures/application_ugly_config_reference/config/features.local.yml +44 -0
- data/spec/fixtures/application_ugly_config_reference/config/features.yml +49 -0
- data/spec/fixtures/application_ugly_config_reference/config/features/admin.local.yml +44 -0
- data/spec/fixtures/application_ugly_config_reference/config/features/admin.yml +44 -0
- data/spec/fixtures/application_ugly_config_reference/config/features/empty.local.yml +0 -0
- data/spec/fixtures/application_ugly_config_reference/config/features/feature_empty_config.local.yml +13 -0
- data/spec/fixtures/application_ugly_config_reference/config/features/including_comments.local.yml +52 -0
- data/spec/fixtures/application_ugly_config_reference/config/features/internal/wiki.local.yml +44 -0
- data/spec/fixtures/application_ugly_config_reference/config/features/internal/wiki.yml +44 -0
- data/spec/fixtures/application_ugly_config_reference/config/features/public.local.yml +44 -0
- data/spec/fixtures/application_ugly_config_reference/config/features/public.yml +44 -0
- metadata +46 -32
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'feature_branch object extensions' do
|
4
|
+
before do
|
5
|
+
@app_env_backup = AbstractFeatureBranch.application_environment
|
6
|
+
AbstractFeatureBranch.logger.warn 'Environment variable ABSTRACT_FEATURE_BRANCH_FEATURE1 already set, potentially conflicting with another test' if ENV.keys.include?('ABSTRACT_FEATURE_BRANCH_FEATURE1')
|
7
|
+
AbstractFeatureBranch.logger.warn 'Environment variable Abstract_Feature_Branch_Feature2 already set, potentially conflicting with another test' if ENV.keys.include?('Abstract_Feature_Branch_Feature2')
|
8
|
+
AbstractFeatureBranch.logger.warn 'Environment variable abstract_feature_branch_feature3 already set, potentially conflicting with another test' if ENV.keys.include?('abstract_feature_branch_feature3')
|
9
|
+
end
|
10
|
+
after do
|
11
|
+
ENV.delete('ABSTRACT_FEATURE_BRANCH_FEATURE1')
|
12
|
+
ENV.delete('Abstract_Feature_Branch_Feature2')
|
13
|
+
ENV.delete('abstract_feature_branch_feature3')
|
14
|
+
AbstractFeatureBranch.initialize_application_root
|
15
|
+
AbstractFeatureBranch.load_application_features
|
16
|
+
AbstractFeatureBranch.application_environment = @app_env_backup
|
17
|
+
end
|
18
|
+
describe '#feature_enabled?' do
|
19
|
+
it 'determines whether a feature is enabled or not in features configuration (case-insensitive string or symbol feature names)' do
|
20
|
+
feature_enabled?('Feature1').should == true
|
21
|
+
feature_enabled?(:FEATURE2).should == true
|
22
|
+
feature_enabled?(:feature3).should == false
|
23
|
+
end
|
24
|
+
it 'returns nil for an invalid feature name' do
|
25
|
+
feature_enabled?(:invalid_feature_that_does_not_exist).should be_nil
|
26
|
+
end
|
27
|
+
it 'allows environment variables (case-insensitive booleans) to override configuration file' do
|
28
|
+
ENV['ABSTRACT_FEATURE_BRANCH_FEATURE1'] = 'FALSE'
|
29
|
+
ENV['Abstract_Feature_Branch_Feature2'] = 'False'
|
30
|
+
ENV['abstract_feature_branch_feature3'] = 'true'
|
31
|
+
AbstractFeatureBranch.load_application_features
|
32
|
+
feature_enabled?(:feature1).should == false
|
33
|
+
feature_enabled?(:feature2).should == false
|
34
|
+
feature_enabled?(:feature3).should == true
|
35
|
+
feature_enabled?(:feature4a).should == true #not overridden
|
36
|
+
end
|
37
|
+
it 'allows local configuration file to override main configuration file in test environment' do
|
38
|
+
feature_enabled?(:feature4).should == false
|
39
|
+
feature_enabled?(:feature5).should == true
|
40
|
+
end
|
41
|
+
it 'no local configuration in production environment' do
|
42
|
+
AbstractFeatureBranch.application_environment = 'production'
|
43
|
+
feature_enabled?(:feature4).should == true
|
44
|
+
feature_enabled?(:feature5).should be_nil
|
45
|
+
end
|
46
|
+
it 'works with Rails environment' do
|
47
|
+
Object.class_eval do
|
48
|
+
module Rails
|
49
|
+
def self.root
|
50
|
+
File.expand_path(File.join(__FILE__, '..', '..', 'fixtures', 'application_rails_config'))
|
51
|
+
end
|
52
|
+
def self.env
|
53
|
+
'staging'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
AbstractFeatureBranch.initialize_application_root
|
58
|
+
AbstractFeatureBranch.initialize_application_environment
|
59
|
+
AbstractFeatureBranch.load_application_features
|
60
|
+
feature_enabled?(:feature1).should == true
|
61
|
+
feature_enabled?(:feature2).should == false
|
62
|
+
feature_enabled?(:feature3).should == false
|
63
|
+
feature_enabled?(:feature4).should be_nil
|
64
|
+
feature_enabled?(:feature4a).should be_nil
|
65
|
+
feature_enabled?(:feature5).should be_nil
|
66
|
+
end
|
67
|
+
end
|
68
|
+
describe 'self#feature_enabled?' do
|
69
|
+
after do
|
70
|
+
Object.send(:remove_const, :TestObject)
|
71
|
+
end
|
72
|
+
# No need to retest all instance test cases, just a spot check due to implementation reuse
|
73
|
+
it 'determines whether a feature is enabled or not in features configuration' do
|
74
|
+
class TestObject
|
75
|
+
def self.hit_me
|
76
|
+
feature_enabled?(:feature1).should == true
|
77
|
+
feature_enabled?(:feature2).should == true
|
78
|
+
feature_enabled?(:feature3).should == false
|
79
|
+
end
|
80
|
+
end
|
81
|
+
TestObject.hit_me
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
File without changes
|
data/spec/{application_rails_config → fixtures/application_rails_config}/config/features.yml
RENAMED
File without changes
|
data/spec/fixtures/application_ugly_config_reference/config/another_application_configuration.yml
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
common: &default_settings
|
2
|
+
license_key: <%= ENV["LICENSE_KEY"] %>
|
3
|
+
app_name: <%= ENV["APP_NAME"] %>
|
4
|
+
monitor_mode: true
|
5
|
+
developer_mode: false
|
6
|
+
log_level: info
|
7
|
+
|
8
|
+
browser_monitoring:
|
9
|
+
auto_instrument: true
|
10
|
+
|
11
|
+
audit_log:
|
12
|
+
enabled: false
|
13
|
+
|
14
|
+
|
15
|
+
development:
|
16
|
+
<<: *default_settings
|
17
|
+
monitor_mode: false
|
18
|
+
developer_mode: true
|
19
|
+
|
20
|
+
test:
|
21
|
+
<<: *default_settings
|
22
|
+
monitor_mode: false
|
23
|
+
|
24
|
+
production:
|
25
|
+
<<: *default_settings
|
26
|
+
monitor_mode: true
|
27
|
+
|
28
|
+
staging:
|
29
|
+
<<: *default_settings
|
30
|
+
monitor_mode: true
|
31
|
+
app_name: <%= ENV["APP_NAME"] %> (Staging)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
development:
|
2
|
+
adapter: sqlite3
|
3
|
+
database: db/development.sqlite3
|
4
|
+
pool: 5
|
5
|
+
timeout: 5000
|
6
|
+
|
7
|
+
test:
|
8
|
+
adapter: sqlite3
|
9
|
+
database: db/test.sqlite3
|
10
|
+
pool: 5
|
11
|
+
timeout: 5000
|
12
|
+
|
13
|
+
production:
|
14
|
+
adapter: sqlite3
|
15
|
+
database: db/production.sqlite3
|
16
|
+
pool: 5
|
17
|
+
timeout: 5000
|
@@ -0,0 +1,44 @@
|
|
1
|
+
defaults: &defaults
|
2
|
+
|
3
|
+
feature4a: true
|
4
|
+
FEATURE1: true
|
5
|
+
feature4: true
|
6
|
+
feature3: false
|
7
|
+
Feature2: true
|
8
|
+
|
9
|
+
development:
|
10
|
+
<<: *defaults
|
11
|
+
FEATURE1: true
|
12
|
+
|
13
|
+
feature4a: true
|
14
|
+
feature4: true
|
15
|
+
feature3: false
|
16
|
+
Feature2: true
|
17
|
+
|
18
|
+
test:
|
19
|
+
<<: *defaults
|
20
|
+
FEATURE1: true
|
21
|
+
feature4: true
|
22
|
+
|
23
|
+
feature4a: true
|
24
|
+
feature3: false
|
25
|
+
Feature2: true
|
26
|
+
|
27
|
+
staging:
|
28
|
+
<<: *defaults
|
29
|
+
FEATURE1: true
|
30
|
+
feature4: true
|
31
|
+
feature3: false
|
32
|
+
|
33
|
+
feature4a: true
|
34
|
+
Feature2: true
|
35
|
+
|
36
|
+
production:
|
37
|
+
<<: *defaults
|
38
|
+
FEATURE1: true
|
39
|
+
feature4: true
|
40
|
+
feature3: false
|
41
|
+
Feature2: true
|
42
|
+
|
43
|
+
feature4a: true
|
44
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
defaults: &defaults
|
2
|
+
|
3
|
+
|
4
|
+
FEATURE1: true
|
5
|
+
Feature2: true
|
6
|
+
feature3: false
|
7
|
+
feature4: true
|
8
|
+
feature4a: true
|
9
|
+
|
10
|
+
development:
|
11
|
+
<<: *defaults
|
12
|
+
FEATURE1: true
|
13
|
+
|
14
|
+
Feature2: true
|
15
|
+
feature3: false
|
16
|
+
feature4: true
|
17
|
+
feature4a: true
|
18
|
+
|
19
|
+
test:
|
20
|
+
<<: *defaults
|
21
|
+
FEATURE1: true
|
22
|
+
Feature2: true
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
feature3: false
|
27
|
+
feature4: true
|
28
|
+
feature4a: true
|
29
|
+
|
30
|
+
staging:
|
31
|
+
<<: *defaults
|
32
|
+
FEATURE1: true
|
33
|
+
Feature2: true
|
34
|
+
|
35
|
+
feature3: false
|
36
|
+
|
37
|
+
feature4: true
|
38
|
+
feature4a: true
|
39
|
+
|
40
|
+
production:
|
41
|
+
<<: *defaults
|
42
|
+
FEATURE1: true
|
43
|
+
|
44
|
+
Feature2: true
|
45
|
+
|
46
|
+
feature3: false
|
47
|
+
feature4: true
|
48
|
+
|
49
|
+
feature4a: true
|
@@ -0,0 +1,44 @@
|
|
1
|
+
defaults: &defaults
|
2
|
+
|
3
|
+
feature4a: true
|
4
|
+
FEATURE1: true
|
5
|
+
feature4: true
|
6
|
+
feature3: false
|
7
|
+
Feature2: true
|
8
|
+
|
9
|
+
development:
|
10
|
+
<<: *defaults
|
11
|
+
FEATURE1: true
|
12
|
+
|
13
|
+
feature4a: true
|
14
|
+
feature4: true
|
15
|
+
feature3: false
|
16
|
+
Feature2: true
|
17
|
+
|
18
|
+
test:
|
19
|
+
<<: *defaults
|
20
|
+
FEATURE1: true
|
21
|
+
feature4: true
|
22
|
+
|
23
|
+
feature4a: true
|
24
|
+
feature3: false
|
25
|
+
Feature2: true
|
26
|
+
|
27
|
+
staging:
|
28
|
+
<<: *defaults
|
29
|
+
FEATURE1: true
|
30
|
+
feature4: true
|
31
|
+
feature3: false
|
32
|
+
|
33
|
+
feature4a: true
|
34
|
+
Feature2: true
|
35
|
+
|
36
|
+
production:
|
37
|
+
<<: *defaults
|
38
|
+
FEATURE1: true
|
39
|
+
feature4: true
|
40
|
+
feature3: false
|
41
|
+
Feature2: true
|
42
|
+
|
43
|
+
feature4a: true
|
44
|
+
|
@@ -0,0 +1,44 @@
|
|
1
|
+
defaults: &defaults
|
2
|
+
|
3
|
+
feature4a: true
|
4
|
+
FEATURE1: true
|
5
|
+
feature4: true
|
6
|
+
feature3: false
|
7
|
+
Feature2: true
|
8
|
+
|
9
|
+
development:
|
10
|
+
<<: *defaults
|
11
|
+
FEATURE1: true
|
12
|
+
|
13
|
+
feature4a: true
|
14
|
+
feature4: true
|
15
|
+
feature3: false
|
16
|
+
Feature2: true
|
17
|
+
|
18
|
+
test:
|
19
|
+
<<: *defaults
|
20
|
+
FEATURE1: true
|
21
|
+
feature4: true
|
22
|
+
|
23
|
+
feature4a: true
|
24
|
+
feature3: false
|
25
|
+
Feature2: true
|
26
|
+
|
27
|
+
staging:
|
28
|
+
<<: *defaults
|
29
|
+
FEATURE1: true
|
30
|
+
feature4: true
|
31
|
+
feature3: false
|
32
|
+
|
33
|
+
feature4a: true
|
34
|
+
Feature2: true
|
35
|
+
|
36
|
+
production:
|
37
|
+
<<: *defaults
|
38
|
+
FEATURE1: true
|
39
|
+
feature4: true
|
40
|
+
feature3: false
|
41
|
+
Feature2: true
|
42
|
+
|
43
|
+
feature4a: true
|
44
|
+
|
File without changes
|
data/spec/fixtures/application_ugly_config_reference/config/features/including_comments.local.yml
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# This file allows you to override any feature configuration locally without it being committed to git
|
2
|
+
# It is recommended to use this file only for temporary overrides. Once done, make final change in main .yml
|
3
|
+
|
4
|
+
defaults: &defaults
|
5
|
+
|
6
|
+
feature4a: true
|
7
|
+
FEATURE1: true
|
8
|
+
feature4: true
|
9
|
+
# Some comment in between features (will get deleted by beautifier)
|
10
|
+
feature3: false
|
11
|
+
|
12
|
+
# another comment in between features (will get deleted by beautifier)
|
13
|
+
Feature2: true
|
14
|
+
|
15
|
+
development:
|
16
|
+
# yet another comment in between features (will get deleted by beautifier)
|
17
|
+
<<: *defaults
|
18
|
+
FEATURE1: true
|
19
|
+
|
20
|
+
feature4a: true
|
21
|
+
feature4: true
|
22
|
+
feature3: false
|
23
|
+
Feature2: true
|
24
|
+
|
25
|
+
test:
|
26
|
+
<<: *defaults
|
27
|
+
FEATURE1: true
|
28
|
+
feature4: true
|
29
|
+
|
30
|
+
feature4a: true
|
31
|
+
feature3: false
|
32
|
+
Feature2: true
|
33
|
+
|
34
|
+
staging:
|
35
|
+
<<: *defaults
|
36
|
+
FEATURE1: true
|
37
|
+
feature4: true
|
38
|
+
feature3: false
|
39
|
+
|
40
|
+
feature4a: true
|
41
|
+
Feature2: true
|
42
|
+
|
43
|
+
production:
|
44
|
+
<<: *defaults
|
45
|
+
FEATURE1: true
|
46
|
+
feature4: true
|
47
|
+
feature3: false
|
48
|
+
Feature2: true
|
49
|
+
|
50
|
+
feature4a: true
|
51
|
+
|
52
|
+
# absolutely deleted by beautifier
|
@@ -0,0 +1,44 @@
|
|
1
|
+
defaults: &defaults
|
2
|
+
|
3
|
+
feature4a: true
|
4
|
+
FEATURE1: true
|
5
|
+
feature4: true
|
6
|
+
feature3: false
|
7
|
+
Feature2: true
|
8
|
+
|
9
|
+
development:
|
10
|
+
<<: *defaults
|
11
|
+
FEATURE1: true
|
12
|
+
|
13
|
+
feature4a: true
|
14
|
+
feature4: true
|
15
|
+
feature3: false
|
16
|
+
Feature2: true
|
17
|
+
|
18
|
+
test:
|
19
|
+
<<: *defaults
|
20
|
+
FEATURE1: true
|
21
|
+
feature4: true
|
22
|
+
|
23
|
+
feature4a: true
|
24
|
+
feature3: false
|
25
|
+
Feature2: true
|
26
|
+
|
27
|
+
staging:
|
28
|
+
<<: *defaults
|
29
|
+
FEATURE1: true
|
30
|
+
feature4: true
|
31
|
+
feature3: false
|
32
|
+
|
33
|
+
feature4a: true
|
34
|
+
Feature2: true
|
35
|
+
|
36
|
+
production:
|
37
|
+
<<: *defaults
|
38
|
+
FEATURE1: true
|
39
|
+
feature4: true
|
40
|
+
feature3: false
|
41
|
+
Feature2: true
|
42
|
+
|
43
|
+
feature4a: true
|
44
|
+
|