rack-flags 0.1.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -52,7 +52,12 @@ module RackFlags
52
52
  overrides
53
53
  end
54
54
 
55
- response.set_cookie(CookieCodec::COOKIE_KEY, value: CookieCodec.new.generate_cookie_from(overrides), path: '/')
55
+ response.set_cookie(
56
+ CookieCodec::COOKIE_KEY,
57
+ value: CookieCodec.new.generate_cookie_from(overrides),
58
+ path: '/',
59
+ expires: cookie_expiration
60
+ )
56
61
  redirect to('/'), 303
57
62
  end
58
63
 
@@ -67,5 +72,10 @@ module RackFlags
67
72
  flag_states[form_param_flag_state.to_sym]
68
73
  end
69
74
 
75
+ def cookie_expiration
76
+ # store overrides in the cookie for around for ~5 years from the last time they were modified
77
+ Time.new( Time.now.year + 5 )
78
+ end
79
+
70
80
  end
71
81
  end
@@ -1,3 +1,3 @@
1
1
  module RackFlags
2
- VERSION = "0.1.4"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -1,7 +1,7 @@
1
1
  require_relative 'spec_helper'
2
+ require_relative 'support/page_objects/admin_page'
2
3
 
3
4
  describe 'displaying flags in admin app' do
4
- include Capybara::DSL
5
5
 
6
6
  let( :feature_flag_config ) do
7
7
  {
@@ -29,65 +29,41 @@ describe 'displaying flags in admin app' do
29
29
  end
30
30
  end
31
31
 
32
- let(:on_flag_section){ page.find('section[data-flag-name="on_by_default"]') }
33
- let(:off_flag_section){ page.find('section[data-flag-name="off_by_default"]') }
34
- let(:update_button){ page.find('input[type="submit"]') }
35
-
36
32
  it 'successfully GETs the admin page' do
37
- visit '/'
38
- status_code.should == 200
33
+ AdminPage.visiting do |page|
34
+ page.verify_status_code_is 200
35
+ end
39
36
  end
40
37
 
41
38
  it 'renders the feature flag name, default and description' do
42
- visit '/'
43
-
44
- on_flag_section.should_not be_nil
45
- on_flag_section.find('h3').text.should == 'on_by_default'
46
- on_flag_section.find('p').text.should == 'this flag on by default'
47
- on_flag_section.find('label.default').text.should include('Default (On)')
48
-
49
- off_flag_section.should_not be_nil
50
- off_flag_section.find('h3').text.should == 'off_by_default'
51
- off_flag_section.find('p').text.should == 'this flag off by default'
52
- off_flag_section.find('label.default').text.should include('Default (Off)')
39
+ AdminPage.visiting do |page|
40
+ on_flag_section = page.section_for_flag_named('on_by_default')
41
+ on_flag_section.should_not be_nil
42
+ on_flag_section.find('h3').text.should == 'on_by_default'
43
+ on_flag_section.find('p').text.should == 'this flag on by default'
44
+ on_flag_section.find('label.default').text.should include('Default (On)')
45
+
46
+ off_flag_section = page.section_for_flag_named('off_by_default')
47
+ off_flag_section.should_not be_nil
48
+ off_flag_section.find('h3').text.should == 'off_by_default'
49
+ off_flag_section.find('p').text.should == 'this flag off by default'
50
+ off_flag_section.find('label.default').text.should include('Default (Off)')
51
+ end
53
52
  end
54
53
 
55
54
  it 'selects the default option if there are no cookies present' do
56
- visit '/'
57
-
58
- verify_flag_section( on_flag_section, :default )
59
- verify_flag_section( off_flag_section, :default )
55
+ AdminPage.visiting do |page|
56
+ page.verify_flag_section( 'on_by_default', :default )
57
+ page.verify_flag_section( 'off_by_default', :default )
58
+ end
60
59
  end
61
60
 
62
61
  it 'allows switching off a flag defaulted to on' do
63
- visit '/'
64
-
65
- on_flag_section.choose( 'Off' )
66
- update_button.click
67
-
68
- verify_flag_section( on_flag_section, :off )
69
- verify_flag_section( off_flag_section, :default )
70
- end
71
-
72
- def verify_flag_section( section, expected_state )
73
- case expected_state.to_sym
74
- when :default
75
- section.find('label.default input').should be_checked
76
-
77
- section.find('label.on input').should_not be_checked
78
- section.find('label.off input').should_not be_checked
79
- when :on
80
- section.find('label.on input').should be_checked
81
-
82
- section.find('label.default input').should_not be_checked
83
- section.find('label.off input').should_not be_checked
84
- when :off
85
- section.find('label.off input').should be_checked
62
+ AdminPage.visiting do |page|
63
+ page.turn_off_flag_name('on_by_default')
86
64
 
87
- section.find('label.default input').should_not be_checked
88
- section.find('label.on input').should_not be_checked
89
- else
90
- raise "unrecognized state '#{expected_state}'"
65
+ page.verify_flag_section( 'on_by_default', :off )
66
+ page.verify_flag_section( 'off_by_default', :default )
91
67
  end
92
68
  end
93
69
  end
@@ -0,0 +1,44 @@
1
+ require_relative 'spec_helper'
2
+ require_relative 'support/page_objects/admin_page'
3
+ require_relative 'support/page_objects/reader_page'
4
+
5
+ describe 'end-to-end flow of setting a feature flag in the admin app and seeing its effect' do
6
+
7
+ let( :app ) do
8
+ yaml_path = ff_config_file_path
9
+ Rack::Builder.new do
10
+ use RackFlags::RackMiddleware, yaml_path: yaml_path
11
+ map('/reader'){ run ReaderApp }
12
+ map('/feature_flags'){ run RackFlags::AdminApp.new }
13
+ end
14
+ end
15
+
16
+ let( :feature_flag_config ) do
17
+ {
18
+ foo: { default: true },
19
+ bar: { default: false }
20
+ }
21
+ end
22
+
23
+ before :each do
24
+ ff_config_file_contains( feature_flag_config )
25
+ Capybara.app = app
26
+ end
27
+
28
+ it 'overriding an off flag to on' do
29
+ ReaderPage.visiting('/reader') do |page|
30
+ page.verify_flag_is_on('foo')
31
+ page.verify_flag_is_off('bar')
32
+ end
33
+
34
+ AdminPage.visiting('/feature_flags') do |page|
35
+ page.turn_on_flag_name('bar')
36
+ end
37
+
38
+ ReaderPage.visiting('/reader') do |page|
39
+ page.verify_flag_is_on('foo')
40
+ page.verify_flag_is_on('bar')
41
+ end
42
+ end
43
+
44
+ end
@@ -0,0 +1,66 @@
1
+ class AdminPage
2
+ include RSpec::Matchers
3
+ include Capybara::DSL
4
+
5
+ def self.visiting( path = "/" )
6
+ page = self.new(path)
7
+ page.visit_page
8
+ yield page
9
+ end
10
+
11
+ def initialize( path )
12
+ @path = path
13
+ end
14
+
15
+ def visit_page
16
+ visit @path
17
+ end
18
+
19
+ def turn_on_flag_name(flag_name)
20
+ section_for_flag_named(flag_name).choose('On')
21
+ update_button.click
22
+ end
23
+
24
+ def turn_off_flag_name(flag_name)
25
+ section_for_flag_named(flag_name).choose('Off')
26
+ update_button.click
27
+ end
28
+
29
+
30
+ def update_button
31
+ page.find('input[type="submit"]')
32
+ end
33
+
34
+ def section_for_flag_named(flag_name)
35
+ page.find(%Q|section[data-flag-name="#{flag_name}"]|)
36
+ end
37
+
38
+ def verify_flag_section( flag_name, expected_state )
39
+ section = section_for_flag_named( flag_name )
40
+
41
+ case expected_state.to_sym
42
+ when :default
43
+ section.find('label.default input').should be_checked
44
+
45
+ section.find('label.on input').should_not be_checked
46
+ section.find('label.off input').should_not be_checked
47
+ when :on
48
+ section.find('label.on input').should be_checked
49
+
50
+ section.find('label.default input').should_not be_checked
51
+ section.find('label.off input').should_not be_checked
52
+ when :off
53
+ section.find('label.off input').should be_checked
54
+
55
+ section.find('label.default input').should_not be_checked
56
+ section.find('label.on input').should_not be_checked
57
+ else
58
+ raise "unrecognized state '#{expected_state}'"
59
+ end
60
+ end
61
+
62
+ def verify_status_code_is(expected_status_code)
63
+ status_code.should == expected_status_code
64
+ end
65
+
66
+ end
@@ -0,0 +1,27 @@
1
+ class ReaderPage
2
+ include RSpec::Matchers
3
+ include Capybara::DSL
4
+
5
+ def self.visiting( path = "/" )
6
+ page = self.new(path)
7
+ page.visit_page
8
+ yield page
9
+ end
10
+
11
+ def initialize( path )
12
+ @path = path
13
+ end
14
+
15
+ def visit_page
16
+ visit(@path)
17
+ end
18
+
19
+ def verify_flag_is_off(flag_name)
20
+ page.should have_content("#{flag_name} is off")
21
+ end
22
+
23
+ def verify_flag_is_on(flag_name)
24
+ page.should have_content("#{flag_name} is on")
25
+ end
26
+
27
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-flags
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-08-06 00:00:00.000000000 Z
13
+ date: 2013-08-18 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rake
17
- requirement: &70155779355400 !ruby/object:Gem::Requirement
17
+ requirement: !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,10 +22,15 @@ dependencies:
22
22
  version: '0'
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *70155779355400
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: '0'
26
31
  - !ruby/object:Gem::Dependency
27
32
  name: rack
28
- requirement: &70155779354880 !ruby/object:Gem::Requirement
33
+ requirement: !ruby/object:Gem::Requirement
29
34
  none: false
30
35
  requirements:
31
36
  - - ~>
@@ -33,10 +38,15 @@ dependencies:
33
38
  version: '1.4'
34
39
  type: :runtime
35
40
  prerelease: false
36
- version_requirements: *70155779354880
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: '1.4'
37
47
  - !ruby/object:Gem::Dependency
38
48
  name: sinatra
39
- requirement: &70155779354360 !ruby/object:Gem::Requirement
49
+ requirement: !ruby/object:Gem::Requirement
40
50
  none: false
41
51
  requirements:
42
52
  - - ~>
@@ -44,10 +54,15 @@ dependencies:
44
54
  version: '1.3'
45
55
  type: :runtime
46
56
  prerelease: false
47
- version_requirements: *70155779354360
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ~>
61
+ - !ruby/object:Gem::Version
62
+ version: '1.3'
48
63
  - !ruby/object:Gem::Dependency
49
64
  name: pry-debugger
50
- requirement: &70155779353980 !ruby/object:Gem::Requirement
65
+ requirement: !ruby/object:Gem::Requirement
51
66
  none: false
52
67
  requirements:
53
68
  - - ! '>='
@@ -55,10 +70,15 @@ dependencies:
55
70
  version: '0'
56
71
  type: :development
57
72
  prerelease: false
58
- version_requirements: *70155779353980
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
59
79
  - !ruby/object:Gem::Dependency
60
80
  name: rspec-core
61
- requirement: &70155779353520 !ruby/object:Gem::Requirement
81
+ requirement: !ruby/object:Gem::Requirement
62
82
  none: false
63
83
  requirements:
64
84
  - - ! '>='
@@ -66,10 +86,15 @@ dependencies:
66
86
  version: '0'
67
87
  type: :development
68
88
  prerelease: false
69
- version_requirements: *70155779353520
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
70
95
  - !ruby/object:Gem::Dependency
71
96
  name: rspec-expectations
72
- requirement: &70155779353100 !ruby/object:Gem::Requirement
97
+ requirement: !ruby/object:Gem::Requirement
73
98
  none: false
74
99
  requirements:
75
100
  - - ! '>='
@@ -77,10 +102,15 @@ dependencies:
77
102
  version: '0'
78
103
  type: :development
79
104
  prerelease: false
80
- version_requirements: *70155779353100
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
81
111
  - !ruby/object:Gem::Dependency
82
112
  name: rr
83
- requirement: &70155779352680 !ruby/object:Gem::Requirement
113
+ requirement: !ruby/object:Gem::Requirement
84
114
  none: false
85
115
  requirements:
86
116
  - - ! '>='
@@ -88,10 +118,15 @@ dependencies:
88
118
  version: '0'
89
119
  type: :development
90
120
  prerelease: false
91
- version_requirements: *70155779352680
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ! '>='
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
92
127
  - !ruby/object:Gem::Dependency
93
128
  name: capybara
94
- requirement: &70155779352260 !ruby/object:Gem::Requirement
129
+ requirement: !ruby/object:Gem::Requirement
95
130
  none: false
96
131
  requirements:
97
132
  - - ! '>='
@@ -99,7 +134,12 @@ dependencies:
99
134
  version: '0'
100
135
  type: :development
101
136
  prerelease: false
102
- version_requirements: *70155779352260
137
+ version_requirements: !ruby/object:Gem::Requirement
138
+ none: false
139
+ requirements:
140
+ - - ! '>='
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
103
143
  description: This is a simple lightweight way to expose work-in-progress functionality
104
144
  to developers, testers or other internal users.
105
145
  email:
@@ -118,8 +158,11 @@ files:
118
158
  - resources/admin_app/index.erb
119
159
  - resources/admin_app/style.css
120
160
  - spec/acceptance/administering_feature_flags_spec.rb
161
+ - spec/acceptance/end_to_end_flow_spec.rb
121
162
  - spec/acceptance/reading_feature_flags_spec.rb
122
163
  - spec/acceptance/spec_helper.rb
164
+ - spec/acceptance/support/page_objects/admin_page.rb
165
+ - spec/acceptance/support/page_objects/reader_page.rb
123
166
  - spec/acceptance/support/reader_app.rb
124
167
  - spec/spec_helper.rb
125
168
  - spec/unit/admin_app_spec.rb
@@ -141,22 +184,31 @@ required_ruby_version: !ruby/object:Gem::Requirement
141
184
  - - ! '>='
142
185
  - !ruby/object:Gem::Version
143
186
  version: '0'
187
+ segments:
188
+ - 0
189
+ hash: -1587276137499646704
144
190
  required_rubygems_version: !ruby/object:Gem::Requirement
145
191
  none: false
146
192
  requirements:
147
193
  - - ! '>='
148
194
  - !ruby/object:Gem::Version
149
195
  version: '0'
196
+ segments:
197
+ - 0
198
+ hash: -1587276137499646704
150
199
  requirements: []
151
200
  rubyforge_project:
152
- rubygems_version: 1.8.15
201
+ rubygems_version: 1.8.25
153
202
  signing_key:
154
203
  specification_version: 3
155
204
  summary: Simple cookie-based feature flags using Rack.
156
205
  test_files:
157
206
  - spec/acceptance/administering_feature_flags_spec.rb
207
+ - spec/acceptance/end_to_end_flow_spec.rb
158
208
  - spec/acceptance/reading_feature_flags_spec.rb
159
209
  - spec/acceptance/spec_helper.rb
210
+ - spec/acceptance/support/page_objects/admin_page.rb
211
+ - spec/acceptance/support/page_objects/reader_page.rb
160
212
  - spec/acceptance/support/reader_app.rb
161
213
  - spec/spec_helper.rb
162
214
  - spec/unit/admin_app_spec.rb