flip_the_switch 0.4.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +4 -1
- data/.travis.yml +3 -1
- data/CHANGELOG.md +10 -0
- data/Classes/FlipTheSwitch/Shared/FTSFeature.h +11 -0
- data/Classes/FlipTheSwitch/Shared/FTSFeature.m +67 -0
- data/Classes/FlipTheSwitch/Shared/FTSFlipTheSwitch.h +21 -0
- data/Classes/FlipTheSwitch/Shared/FTSFlipTheSwitch.m +144 -0
- data/Classes/FlipTheSwitch/iOS/FTSFeatureCell.h +17 -0
- data/Classes/FlipTheSwitch/iOS/FTSFeatureCell.m +12 -0
- data/Classes/FlipTheSwitch/iOS/FTSFeatureConfigurationViewController.h +5 -0
- data/Classes/FlipTheSwitch/iOS/FTSFeatureConfigurationViewController.m +142 -0
- data/Classes/FlipTheSwitch/iOS/FTSFeatureDescriptionLabel.h +5 -0
- data/Classes/FlipTheSwitch/iOS/FTSFeatureDescriptionLabel.m +13 -0
- data/Example/Colors-OSX/AppDelegate.h +7 -0
- data/Example/Colors-OSX/AppDelegate.m +17 -0
- data/Example/Colors-OSX/Base.lproj/Main.storyboard +744 -0
- data/Example/Colors-OSX/ColoredViews/GreenView.h +5 -0
- data/Example/Colors-OSX/ColoredViews/GreenView.m +12 -0
- data/Example/Colors-OSX/ColoredViews/PurpleView.h +5 -0
- data/Example/Colors-OSX/ColoredViews/PurpleView.m +12 -0
- data/Example/Colors-OSX/ColoredViews/RedView.h +5 -0
- data/Example/Colors-OSX/ColoredViews/RedView.m +12 -0
- data/Example/Colors-OSX/ColoredViews/YellowView.h +5 -0
- data/Example/Colors-OSX/ColoredViews/YellowView.m +12 -0
- data/Example/Colors-OSX/FTSFlipTheSwitch+Features.h +45 -0
- data/Example/Colors-OSX/FTSFlipTheSwitch+Features.m +165 -0
- data/Example/Colors-OSX/Features.plist +39 -0
- data/Example/Colors-OSX/Images.xcassets/AppIcon.appiconset/Contents.json +58 -0
- data/Example/Colors-OSX/Info.plist +32 -0
- data/Example/Colors-OSX/Settings.bundle/Features.plist +59 -0
- data/Example/Colors-OSX/Settings.bundle/Root.plist +23 -0
- data/Example/Colors-OSX/ViewController.h +14 -0
- data/Example/Colors-OSX/ViewController.m +152 -0
- data/Example/Colors-OSX/main.m +5 -0
- data/Example/Colors-iOS/Base.lproj/Main.storyboard +111 -0
- data/Example/Colors-iOS/Colors-iOS-Info.plist +2 -2
- data/Example/Colors-iOS/FTSFlipTheSwitch+Features.h +45 -0
- data/Example/Colors-iOS/FTSFlipTheSwitch+Features.m +165 -0
- data/Example/Colors-iOS/Images.xcassets/AppIcon.appiconset/Contents.json +15 -0
- data/Example/Colors-iOS/ViewControlleriOS.m +55 -20
- data/Example/Colors.xcodeproj/project.pbxproj +273 -25
- data/Example/Colors.xcodeproj/xcshareddata/xcschemes/Colors-OSX.xcscheme +115 -0
- data/Example/Colors.xcodeproj/xcshareddata/xcschemes/Colors-iOS.xcscheme +9 -15
- data/Example/FTSFlipTheSwitch+Features.h +45 -0
- data/Example/FTSFlipTheSwitch+Features.m +165 -0
- data/Example/Features.plist +39 -0
- data/Example/Gemfile +4 -0
- data/Example/Podfile +11 -2
- data/Example/README.md +13 -0
- data/Example/Rakefile +5 -1
- data/Example/features.json +23 -0
- data/FlipTheSwitch.podspec +9 -4
- data/Gemfile +2 -1
- data/README.md +101 -21
- data/Resources/FlipTheSwitch/FlipTheSwitch.storyboard +208 -0
- data/Tests/FlipTheSwitchSpec-iOS/Features.plist +6 -1
- data/Tests/{FlipTheSwitchSpec-Mac/Features.plist → FlipTheSwitchSpec-iOS/OtherFeatures.plist} +5 -2
- data/Tests/FlipTheSwitchSpec.xcodeproj/project.pbxproj +101 -38
- data/Tests/FlipTheSwitchSpec.xcodeproj/xcshareddata/xcschemes/FlipTheSwitchSpec-Mac.xcscheme +9 -7
- data/Tests/FlipTheSwitchSpec.xcodeproj/xcshareddata/xcschemes/FlipTheSwitchSpec-iOS.xcscheme +9 -7
- data/Tests/Rakefile +1 -1
- data/Tests/Spec/Classes/FlipTheSwitch/FlipTheSwitchSpec.m +134 -28
- data/flip_the_switch.gemspec +2 -1
- data/images/feature_configuration_screen.png +0 -0
- data/lib/flip_the_switch.rb +2 -0
- data/lib/flip_the_switch/cli.rb +16 -24
- data/lib/flip_the_switch/environment.rb +11 -0
- data/lib/flip_the_switch/feature.rb +11 -0
- data/lib/flip_the_switch/generator/base.rb +3 -3
- data/lib/flip_the_switch/generator/category.rb +13 -5
- data/lib/flip_the_switch/generator/header.h.erb +15 -8
- data/lib/flip_the_switch/generator/implementation.m.erb +36 -12
- data/lib/flip_the_switch/generator/plist.rb +19 -1
- data/lib/flip_the_switch/generator/settings.rb +6 -6
- data/lib/flip_the_switch/reader/features.rb +136 -22
- data/spec/flip_the_switch/cli_spec.rb +12 -12
- data/spec/flip_the_switch/environment_spec.rb +20 -0
- data/spec/flip_the_switch/feature_spec.rb +20 -0
- data/spec/flip_the_switch/generator/category_spec.rb +14 -8
- data/spec/flip_the_switch/generator/plist_spec.rb +23 -7
- data/spec/flip_the_switch/generator/settings_spec.rb +6 -3
- data/spec/flip_the_switch/reader/defaults_spec.rb +0 -18
- data/spec/flip_the_switch/reader/features_spec.rb +74 -17
- data/spec/resources/ExpectedFeatures.plist +10 -2
- data/spec/resources/expected_header.h +8 -3
- data/spec/resources/expected_implementation.m +37 -10
- data/spec/resources/invalid_layout/features.json +7 -0
- data/spec/resources/invalid_type/features.json +23 -0
- data/spec/resources/real/features.json +38 -0
- data/tmp/.keep +0 -0
- metadata +74 -16
- data/Classes/FlipTheSwitch/FlipTheSwitch.h +0 -9
- data/Classes/FlipTheSwitch/FlipTheSwitch.m +0 -88
- data/Example/Colors-iOS/Base.lproj/Main_iPhone.storyboard +0 -76
- data/Example/features.yml +0 -3
- data/Tests/Spec/Helpers/GcovTestObserver.h +0 -4
- data/Tests/Spec/Helpers/GcovTestObserver.m +0 -12
- data/spec/resources/invalid_layout/features.yml +0 -4
- data/spec/resources/invalid_type/features.yml +0 -7
- data/spec/resources/real/features.yml +0 -6
@@ -16,15 +16,15 @@ describe FlipTheSwitch::Cli do
|
|
16
16
|
end
|
17
17
|
|
18
18
|
shared_examples_for 'generator' do
|
19
|
-
let(:feature_reader) { double(FlipTheSwitch::Reader::Features,
|
19
|
+
let(:feature_reader) { double(FlipTheSwitch::Reader::Features, features: features_for_hash('something' => true)) }
|
20
20
|
let(:generator) { double(generator_class) }
|
21
21
|
|
22
22
|
context 'when no options given' do
|
23
23
|
let(:options) { [] }
|
24
24
|
|
25
25
|
before do
|
26
|
-
FlipTheSwitch::Reader::Features.stub(:new).with(Dir.pwd, 'default').and_return(feature_reader)
|
27
|
-
generator_class.stub(:new).with(Dir.pwd, 'something' => true).and_return(generator)
|
26
|
+
FlipTheSwitch::Reader::Features.stub(:new).with(File.join(Dir.pwd, 'features.json'), 'default').and_return(feature_reader)
|
27
|
+
generator_class.stub(:new).with(Dir.pwd, features_for_hash('something' => true)).and_return(generator)
|
28
28
|
end
|
29
29
|
|
30
30
|
it 'generates using default options' do
|
@@ -36,17 +36,11 @@ describe FlipTheSwitch::Cli do
|
|
36
36
|
context 'when options given' do
|
37
37
|
before do
|
38
38
|
FlipTheSwitch::Reader::Features.stub(:new).with('input', 'environment').and_return(feature_reader)
|
39
|
-
generator_class.stub(:new).with('output',
|
40
|
-
'something' => true,
|
41
|
-
'en' => true,
|
42
|
-
'abled' => true,
|
43
|
-
'dis' => false,
|
44
|
-
'appointing' => false
|
45
|
-
}).and_return(generator)
|
39
|
+
generator_class.stub(:new).with('output', features_for_hash('something' => true)).and_return(generator)
|
46
40
|
end
|
47
41
|
|
48
42
|
context 'using full name' do
|
49
|
-
let(:options) { %w(--input=input --environment=environment --output=output
|
43
|
+
let(:options) { %w(--input=input --environment=environment --output=output) }
|
50
44
|
|
51
45
|
it 'generates using the options given' do
|
52
46
|
expect(generator).to receive(:generate)
|
@@ -55,7 +49,7 @@ describe FlipTheSwitch::Cli do
|
|
55
49
|
end
|
56
50
|
|
57
51
|
context 'using aliases' do
|
58
|
-
let(:options) { %w(-i=input -n=environment -o=output
|
52
|
+
let(:options) { %w(-i=input -n=environment -o=output) }
|
59
53
|
|
60
54
|
it 'generates using the options given' do
|
61
55
|
expect(generator).to receive(:generate)
|
@@ -65,6 +59,12 @@ describe FlipTheSwitch::Cli do
|
|
65
59
|
end
|
66
60
|
end
|
67
61
|
|
62
|
+
def features_for_hash(hash)
|
63
|
+
hash.map { |feature, enabled|
|
64
|
+
FlipTheSwitch::Feature.new(feature, enabled)
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
68
|
context 'when plist command called' do
|
69
69
|
let(:command) { 'plist' }
|
70
70
|
let(:generator_class) { FlipTheSwitch::Generator::Plist }
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe FlipTheSwitch::Environment do
|
4
|
+
subject(:environment) { described_class.new('main_environment') }
|
5
|
+
let(:sub_environment) { described_class.new('sub_environment', [], 'main_environment') }
|
6
|
+
|
7
|
+
describe '#has_parent?' do
|
8
|
+
context 'when has a parent' do
|
9
|
+
specify {
|
10
|
+
expect(sub_environment.has_parent?).to be_true
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'when has NO parent' do
|
15
|
+
specify {
|
16
|
+
expect(environment.has_parent?).to be_false
|
17
|
+
}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe FlipTheSwitch::Feature do
|
4
|
+
subject(:feature) { described_class.new('main_feature', true, 'hmm', [sub_feature]) }
|
5
|
+
let(:sub_feature) { described_class.new('sub_feature', false, nil, [], 'main_feature') }
|
6
|
+
|
7
|
+
describe '#has_parent?' do
|
8
|
+
context 'when has a parent' do
|
9
|
+
specify {
|
10
|
+
expect(sub_feature.has_parent?).to be_true
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'when has NO parent' do
|
15
|
+
specify {
|
16
|
+
expect(feature.has_parent?).to be_false
|
17
|
+
}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,9 +1,11 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe FlipTheSwitch::Generator::Category do
|
4
|
-
subject(:category) { described_class.new(output,
|
5
|
-
let(:output) { '
|
6
|
-
let(:
|
4
|
+
subject(:category) { described_class.new(output, features) }
|
5
|
+
let(:output) { 'tmp' }
|
6
|
+
let(:first_feature) { FlipTheSwitch::Feature.new('first_feature', true, 'This is the first feature', [second_feature]) }
|
7
|
+
let(:second_feature) { FlipTheSwitch::Feature.new('second_feature', false, nil, [], 'first_feature') }
|
8
|
+
let(:features) { [first_feature] }
|
7
9
|
let(:expected_header_file) { File.read('spec/resources/expected_header.h') }
|
8
10
|
let(:expected_implementation_file) { File.read('spec/resources/expected_implementation.m') }
|
9
11
|
|
@@ -12,16 +14,16 @@ describe FlipTheSwitch::Generator::Category do
|
|
12
14
|
delete_implementation_if_exists
|
13
15
|
end
|
14
16
|
|
15
|
-
it 'writes a
|
17
|
+
it 'writes a FTSFlipTheSwitch+Features.h file with the category header' do
|
16
18
|
subject.generate
|
17
19
|
|
18
|
-
expect(
|
20
|
+
expect(output_with('h')).to eql(expected_header_file)
|
19
21
|
end
|
20
22
|
|
21
|
-
it 'writes a
|
23
|
+
it 'writes a FTSFlipTheSwitch+Features.m file with the category implementation' do
|
22
24
|
subject.generate
|
23
25
|
|
24
|
-
expect(
|
26
|
+
expect(output_with('m')).to eql(expected_implementation_file)
|
25
27
|
end
|
26
28
|
|
27
29
|
private
|
@@ -38,7 +40,11 @@ describe FlipTheSwitch::Generator::Category do
|
|
38
40
|
File.delete(output_name_with(suffix)) if File.exists?(output_name_with(suffix))
|
39
41
|
end
|
40
42
|
|
43
|
+
def output_with(suffix)
|
44
|
+
File.read(output_name_with(suffix))
|
45
|
+
end
|
46
|
+
|
41
47
|
def output_name_with(suffix)
|
42
|
-
"#{output}/
|
48
|
+
"#{output}/FTSFlipTheSwitch+Features.#{suffix}"
|
43
49
|
end
|
44
50
|
end
|
@@ -1,19 +1,35 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe FlipTheSwitch::Generator::Plist do
|
4
|
-
subject(:plist) { described_class.new(output,
|
5
|
-
let(:
|
6
|
-
|
7
|
-
|
4
|
+
subject(:plist) { described_class.new(output, features) }
|
5
|
+
let(:features) { [
|
6
|
+
FlipTheSwitch::Feature.new('enabled_feature', true, nil),
|
7
|
+
FlipTheSwitch::Feature.new('disabled_feature', false, 'is disabled description')
|
8
|
+
] }
|
9
|
+
let(:output_file) { 'tmp/Features.plist' }
|
10
|
+
let(:actual_output_file) { File.read(output_file) }
|
8
11
|
let(:expected_plist_file) { File.read('spec/resources/ExpectedFeatures.plist') }
|
9
12
|
|
10
13
|
after do
|
11
14
|
File.delete(output_file) if File.exists?(output_file)
|
12
15
|
end
|
13
16
|
|
14
|
-
|
15
|
-
|
17
|
+
shared_examples "a plist writer" do |output, output_file|
|
18
|
+
let(:output) { output }
|
19
|
+
let(:output_file) { output_file }
|
16
20
|
|
17
|
-
|
21
|
+
it "writes a #{File.basename(output_file)} file with the features set" do
|
22
|
+
subject.generate
|
23
|
+
|
24
|
+
expect(File.read(output_file)).to eql(expected_plist_file)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'When the output is a directory' do
|
29
|
+
it_behaves_like "a plist writer", 'spec/resources', 'spec/resources/Features.plist'
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'when the output is a file' do
|
33
|
+
it_behaves_like "a plist writer", 'spec/resources/DasPlist.plist', 'spec/resources/DasPlist.plist'
|
18
34
|
end
|
19
35
|
end
|
@@ -2,14 +2,17 @@ require 'spec_helper'
|
|
2
2
|
require 'fileutils'
|
3
3
|
|
4
4
|
describe FlipTheSwitch::Generator::Settings do
|
5
|
-
subject(:settings) { described_class.new(output,
|
5
|
+
subject(:settings) { described_class.new(output, features) }
|
6
6
|
let(:output) { 'spec/resources' }
|
7
7
|
let(:settings_bundle) { File.join(output, 'Settings.bundle') }
|
8
|
-
let(:
|
8
|
+
let(:features) { [
|
9
|
+
FlipTheSwitch::Feature.new('first_feature', true, nil),
|
10
|
+
FlipTheSwitch::Feature.new('second_feature', false, nil)
|
11
|
+
] }
|
9
12
|
let(:root_output_file) { File.read(File.join(settings_bundle, 'Root.plist')) }
|
10
13
|
let(:features_output_file) { File.read(File.join(settings_bundle, 'Features.plist')) }
|
11
14
|
let(:features_output_file) { File.read(File.join(settings_bundle, 'Features.plist')) }
|
12
|
-
let(:expected_features_file) { File.read('spec/resources/ExpectedSettingsFeatures.plist')}
|
15
|
+
let(:expected_features_file) { File.read('spec/resources/ExpectedSettingsFeatures.plist') }
|
13
16
|
|
14
17
|
after do
|
15
18
|
delete_settings_bundle_if_exists
|
@@ -14,8 +14,6 @@ describe FlipTheSwitch::Reader::Defaults do
|
|
14
14
|
File.write(defaults_file, YAML.dump({
|
15
15
|
input: 'input',
|
16
16
|
environment: 'environment',
|
17
|
-
enabled: 'enabled',
|
18
|
-
disabled: 'disabled',
|
19
17
|
category_output: 'category_output',
|
20
18
|
plist_output: 'plist_output',
|
21
19
|
settings_output: 'settings_output'
|
@@ -30,14 +28,6 @@ describe FlipTheSwitch::Reader::Defaults do
|
|
30
28
|
expect(subject.defaults[:environment]).to eql('environment')
|
31
29
|
end
|
32
30
|
|
33
|
-
it 'returns file enabled default' do
|
34
|
-
expect(subject.defaults[:enabled]).to eql('enabled')
|
35
|
-
end
|
36
|
-
|
37
|
-
it 'returns file disabled default' do
|
38
|
-
expect(subject.defaults[:disabled]).to eql('disabled')
|
39
|
-
end
|
40
|
-
|
41
31
|
it 'returns file category output default' do
|
42
32
|
expect(subject.defaults[:category_output]).to eql('category_output')
|
43
33
|
end
|
@@ -73,14 +63,6 @@ describe FlipTheSwitch::Reader::Defaults do
|
|
73
63
|
expect(subject.defaults[:environment]).to eql('default')
|
74
64
|
end
|
75
65
|
|
76
|
-
it 'returns base enabled default' do
|
77
|
-
expect(subject.defaults[:enabled]).to eql('')
|
78
|
-
end
|
79
|
-
|
80
|
-
it 'returns base disabled default' do
|
81
|
-
expect(subject.defaults[:disabled]).to eql('')
|
82
|
-
end
|
83
|
-
|
84
66
|
it 'returns base category output default' do
|
85
67
|
expect(subject.defaults[:category_output]).to eql(Dir.pwd)
|
86
68
|
end
|
@@ -2,54 +2,111 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe FlipTheSwitch::Reader::Features do
|
4
4
|
subject(:reader) { described_class.new(input, environment) }
|
5
|
-
let(:environment) { '
|
5
|
+
let(:environment) { 'defaults' }
|
6
|
+
let(:input) { 'spec/resources/real/features.json' }
|
7
|
+
|
8
|
+
context 'when given an valid environment' do
|
9
|
+
context 'when reading a standard environment' do
|
10
|
+
it 'reads the enabled/disabled states of the features for the environment' do
|
11
|
+
expect(subject.features).to eql([
|
12
|
+
FlipTheSwitch::Feature.new('enabled_feature', true, 'This feature is enabled', [
|
13
|
+
FlipTheSwitch::Feature.new('sub_feature', false, nil, [
|
14
|
+
FlipTheSwitch::Feature.new('sub_sub_feature', false, nil, [], 'sub_feature')
|
15
|
+
], 'enabled_feature')
|
16
|
+
]),
|
17
|
+
FlipTheSwitch::Feature.new('disabled_feature', false)
|
18
|
+
])
|
19
|
+
end
|
20
|
+
end
|
6
21
|
|
7
|
-
context 'when given a real file' do
|
8
|
-
let(:input) { 'spec/resources/real' }
|
9
22
|
|
10
|
-
context 'when
|
23
|
+
context 'when reading an inherited environment' do
|
24
|
+
let(:environment) { 'alpha' }
|
25
|
+
|
11
26
|
it 'reads the enabled/disabled states of the features for the environment' do
|
12
|
-
expect(subject.
|
27
|
+
expect(subject.features).to eql([
|
28
|
+
FlipTheSwitch::Feature.new('enabled_feature', false, 'This feature is enabled', [
|
29
|
+
FlipTheSwitch::Feature.new('sub_feature', false, nil, [
|
30
|
+
FlipTheSwitch::Feature.new('sub_sub_feature', false, nil, [], 'sub_feature')
|
31
|
+
], 'enabled_feature')
|
32
|
+
]),
|
33
|
+
FlipTheSwitch::Feature.new('disabled_feature', false)
|
34
|
+
])
|
13
35
|
end
|
14
36
|
end
|
15
37
|
|
16
|
-
context 'when
|
17
|
-
let(:environment) { '
|
38
|
+
context 'when reading an double inherited environment' do
|
39
|
+
let(:environment) { 'beta' }
|
18
40
|
|
19
|
-
|
20
|
-
expect
|
21
|
-
|
22
|
-
|
41
|
+
it 'reads the enabled/disabled states of the features for the environment' do
|
42
|
+
expect(subject.features).to eql([
|
43
|
+
FlipTheSwitch::Feature.new('enabled_feature', true, 'This feature is enabled', [
|
44
|
+
FlipTheSwitch::Feature.new('sub_feature', false, nil, [
|
45
|
+
FlipTheSwitch::Feature.new('sub_sub_feature', false, nil, [], 'sub_feature')
|
46
|
+
], 'enabled_feature')
|
47
|
+
]),
|
48
|
+
FlipTheSwitch::Feature.new('disabled_feature', false)
|
49
|
+
])
|
23
50
|
end
|
24
51
|
end
|
25
52
|
end
|
26
53
|
|
54
|
+
context 'when given an invalid environment' do
|
55
|
+
let(:environment) { 'invalid' }
|
56
|
+
|
57
|
+
specify do
|
58
|
+
expect {
|
59
|
+
subject.features
|
60
|
+
}.to raise_error(FlipTheSwitch::Error::InvalidEnvironment)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'when given an invalid environment' do
|
65
|
+
let(:environment) { 'invalid' }
|
66
|
+
|
67
|
+
specify do
|
68
|
+
expect {
|
69
|
+
subject.features
|
70
|
+
}.to raise_error(FlipTheSwitch::Error::InvalidEnvironment)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'when input is an invalid file' do
|
75
|
+
let(:input) { 'spec/resources/invalid_type/features.json' }
|
76
|
+
|
77
|
+
specify do
|
78
|
+
expect {
|
79
|
+
subject.features
|
80
|
+
}.to raise_error(FlipTheSwitch::Error::InvalidFile)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
27
84
|
context 'when given a non-existent file' do
|
28
|
-
let(:input) { 'spec/resources/non-existent' }
|
85
|
+
let(:input) { 'spec/resources/non-existent/features.json' }
|
29
86
|
|
30
87
|
specify do
|
31
88
|
expect {
|
32
|
-
subject.
|
89
|
+
subject.features
|
33
90
|
}.to raise_error(FlipTheSwitch::Error::UnreadableFile)
|
34
91
|
end
|
35
92
|
end
|
36
93
|
|
37
94
|
context 'when given an invalid file type' do
|
38
|
-
let(:input) { 'spec/resources/invalid_type' }
|
95
|
+
let(:input) { 'spec/resources/invalid_type/features.json' }
|
39
96
|
|
40
97
|
specify do
|
41
98
|
expect {
|
42
|
-
subject.
|
99
|
+
subject.features
|
43
100
|
}.to raise_error(FlipTheSwitch::Error::InvalidFile)
|
44
101
|
end
|
45
102
|
end
|
46
103
|
|
47
104
|
context 'when given an invalid file layout' do
|
48
|
-
let(:input) { 'spec/resources/invalid_layout' }
|
105
|
+
let(:input) { 'spec/resources/invalid_layout/features.json' }
|
49
106
|
|
50
107
|
specify do
|
51
108
|
expect {
|
52
|
-
subject.
|
109
|
+
subject.features
|
53
110
|
}.to raise_error(FlipTheSwitch::Error::InvalidFile)
|
54
111
|
end
|
55
112
|
end
|
@@ -3,8 +3,16 @@
|
|
3
3
|
<plist version="1.0">
|
4
4
|
<dict>
|
5
5
|
<key>disabled_feature</key>
|
6
|
-
<
|
6
|
+
<dict>
|
7
|
+
<key>description</key>
|
8
|
+
<string>is disabled description</string>
|
9
|
+
<key>enabled</key>
|
10
|
+
<false/>
|
11
|
+
</dict>
|
7
12
|
<key>enabled_feature</key>
|
8
|
-
<
|
13
|
+
<dict>
|
14
|
+
<key>enabled</key>
|
15
|
+
<true/>
|
16
|
+
</dict>
|
9
17
|
</dict>
|
10
18
|
</plist>
|
@@ -1,16 +1,21 @@
|
|
1
1
|
/* AUTO-GENERATED. DO NOT ALTER */
|
2
|
-
#import <FlipTheSwitch/
|
3
|
-
|
4
|
-
@interface FlipTheSwitch (Features)
|
2
|
+
#import <FlipTheSwitch/FTSFlipTheSwitch.h>
|
5
3
|
|
4
|
+
@interface FTSFlipTheSwitch (Features)
|
5
|
+
// This is the first feature
|
6
6
|
+ (BOOL)isFirstFeatureEnabled;
|
7
7
|
+ (void)enableFirstFeature;
|
8
8
|
+ (void)disableFirstFeature;
|
9
9
|
+ (void)setFirstFeatureEnabled:(BOOL)enabled;
|
10
|
+
+ (void)resetFirstFeature;
|
11
|
+
+ (NSString *)firstFeatureKey;
|
10
12
|
|
11
13
|
+ (BOOL)isSecondFeatureEnabled;
|
12
14
|
+ (void)enableSecondFeature;
|
13
15
|
+ (void)disableSecondFeature;
|
14
16
|
+ (void)setSecondFeatureEnabled:(BOOL)enabled;
|
17
|
+
+ (void)resetSecondFeature;
|
18
|
+
+ (NSString *)secondFeatureKey;
|
15
19
|
|
20
|
+
+ (void)resetAll;
|
16
21
|
@end
|
@@ -1,46 +1,73 @@
|
|
1
1
|
/* AUTO-GENERATED. DO NOT ALTER */
|
2
|
-
#import "
|
2
|
+
#import "FTSFlipTheSwitch+Features.h"
|
3
3
|
|
4
|
-
@implementation
|
4
|
+
@implementation FTSFlipTheSwitch (Features)
|
5
5
|
|
6
6
|
+ (BOOL)isFirstFeatureEnabled
|
7
7
|
{
|
8
|
-
return [[
|
8
|
+
return [[FTSFlipTheSwitch sharedInstance] isFeatureEnabled:[self firstFeatureKey]];
|
9
9
|
}
|
10
10
|
|
11
11
|
+ (void)enableFirstFeature
|
12
12
|
{
|
13
|
-
[[
|
13
|
+
[[FTSFlipTheSwitch sharedInstance] enableFeature:[self firstFeatureKey]];
|
14
14
|
}
|
15
15
|
|
16
16
|
+ (void)disableFirstFeature
|
17
17
|
{
|
18
|
-
[[
|
18
|
+
[[FTSFlipTheSwitch sharedInstance] disableFeature:[self firstFeatureKey]];
|
19
19
|
}
|
20
20
|
|
21
21
|
+ (void)setFirstFeatureEnabled:(BOOL)enabled
|
22
22
|
{
|
23
|
-
[[
|
23
|
+
[[FTSFlipTheSwitch sharedInstance] setFeature:[self firstFeatureKey] enabled:enabled];
|
24
|
+
}
|
25
|
+
|
26
|
+
+ (void)resetFirstFeature
|
27
|
+
{
|
28
|
+
[[FTSFlipTheSwitch sharedInstance] resetFeature:[self firstFeatureKey]];
|
29
|
+
}
|
30
|
+
|
31
|
+
+ (NSString *)firstFeatureKey
|
32
|
+
{
|
33
|
+
return @"first_feature";
|
24
34
|
}
|
25
35
|
|
26
36
|
+ (BOOL)isSecondFeatureEnabled
|
27
37
|
{
|
28
|
-
return [
|
38
|
+
return [self isFirstFeatureEnabled] &&
|
39
|
+
[[FTSFlipTheSwitch sharedInstance] isFeatureEnabled:[self secondFeatureKey]];
|
29
40
|
}
|
30
41
|
|
31
42
|
+ (void)enableSecondFeature
|
32
43
|
{
|
33
|
-
[[
|
44
|
+
[[FTSFlipTheSwitch sharedInstance] enableFeature:[self secondFeatureKey]];
|
34
45
|
}
|
35
46
|
|
36
47
|
+ (void)disableSecondFeature
|
37
48
|
{
|
38
|
-
[[
|
49
|
+
[[FTSFlipTheSwitch sharedInstance] disableFeature:[self secondFeatureKey]];
|
39
50
|
}
|
40
51
|
|
41
52
|
+ (void)setSecondFeatureEnabled:(BOOL)enabled
|
42
53
|
{
|
43
|
-
[[
|
54
|
+
[[FTSFlipTheSwitch sharedInstance] setFeature:[self secondFeatureKey] enabled:enabled];
|
55
|
+
}
|
56
|
+
|
57
|
+
+ (void)resetSecondFeature
|
58
|
+
{
|
59
|
+
[[FTSFlipTheSwitch sharedInstance] resetFeature:[self secondFeatureKey]];
|
60
|
+
}
|
61
|
+
|
62
|
+
+ (NSString *)secondFeatureKey
|
63
|
+
{
|
64
|
+
return @"second_feature";
|
65
|
+
}
|
66
|
+
|
67
|
+
+ (void)resetAll
|
68
|
+
{
|
69
|
+
[self resetFirstFeature];
|
70
|
+
[self resetSecondFeature];
|
44
71
|
}
|
45
72
|
|
46
73
|
@end
|