flipper-ui 0.21.0 → 0.22.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.
- checksums.yaml +4 -4
- data/examples/ui/authorization.ru +11 -49
- data/examples/ui/basic.ru +10 -10
- data/lib/flipper/ui.rb +2 -2
- data/lib/flipper/ui/action.rb +1 -1
- data/lib/flipper/ui/actions/actors_gate.rb +1 -1
- data/lib/flipper/ui/actions/features.rb +2 -2
- data/lib/flipper/ui/actions/groups_gate.rb +1 -1
- data/lib/flipper/ui/actions/percentage_of_actors_gate.rb +1 -1
- data/lib/flipper/ui/actions/percentage_of_time_gate.rb +1 -1
- data/lib/flipper/ui/middleware.rb +2 -1
- data/lib/flipper/version.rb +1 -1
- data/spec/flipper/ui/actions/actors_gate_spec.rb +19 -2
- data/spec/flipper/ui/actions/boolean_gate_spec.rb +18 -0
- data/spec/flipper/ui/actions/feature_spec.rb +18 -0
- data/spec/flipper/ui/actions/features_spec.rb +16 -3
- data/spec/flipper/ui/actions/groups_gate_spec.rb +20 -3
- data/spec/flipper/ui/actions/percentage_of_actors_gate_spec.rb +18 -1
- data/spec/flipper/ui/actions/percentage_of_time_gate_spec.rb +18 -1
- data/spec/flipper/ui_spec.rb +0 -13
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3be7bbda3ec1a09b1cc1c421766ea520a9a933eeb1628ea27281c35a174725a2
|
4
|
+
data.tar.gz: ca0375faf5a0cfd4f2b6c04435c803e9414c2e41337918ad9f8bb9f95f579e46
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: effdbdd4ab7c0646dcd1a50ebd0d96fd78dc2dabb2a87ae1e524a2a4b32ce43c1b01e6e96046d1e9bc4fe298a805a2c31c713b83ad1dbfb26c31dfb70f714e90
|
7
|
+
data.tar.gz: 8d1f5b3f946a0b5d9bb42db7a497484c490cc2a2e9f15562e046ddeb41be0dba1cdda19ef1016bb5f7966ab35c600b8b57418533797b3000cec927671079ff1a
|
@@ -5,50 +5,13 @@
|
|
5
5
|
# http://localhost:9999/
|
6
6
|
#
|
7
7
|
require 'bundler/setup'
|
8
|
-
require "logger"
|
9
|
-
|
10
8
|
require "flipper/ui"
|
11
9
|
require "flipper/adapters/pstore"
|
12
|
-
require "active_support/notifications"
|
13
10
|
|
14
11
|
Flipper.register(:admins) { |actor|
|
15
12
|
actor.respond_to?(:admin?) && actor.admin?
|
16
13
|
}
|
17
14
|
|
18
|
-
Flipper.register(:early_access) { |actor|
|
19
|
-
actor.respond_to?(:early?) && actor.early?
|
20
|
-
}
|
21
|
-
|
22
|
-
# Setup logging of flipper calls.
|
23
|
-
if ENV["LOG"] == "1"
|
24
|
-
$logger = Logger.new(STDOUT)
|
25
|
-
require "flipper/instrumentation/log_subscriber"
|
26
|
-
Flipper::Instrumentation::LogSubscriber.logger = $logger
|
27
|
-
end
|
28
|
-
|
29
|
-
adapter = Flipper::Adapters::PStore.new
|
30
|
-
flipper = Flipper.new(adapter, instrumenter: ActiveSupport::Notifications)
|
31
|
-
|
32
|
-
Flipper::UI.configure do |config|
|
33
|
-
# config.banner_text = 'Production Environment'
|
34
|
-
# config.banner_class = 'danger'
|
35
|
-
config.feature_creation_enabled = true
|
36
|
-
config.feature_removal_enabled = true
|
37
|
-
# config.show_feature_description_in_list = true
|
38
|
-
config.descriptions_source = lambda do |_keys|
|
39
|
-
{
|
40
|
-
"search_performance_another_long_thing" => "Just to test feature name length.",
|
41
|
-
"gauges_tracking" => "Should we track page views with gaug.es.",
|
42
|
-
"unused" => "Not used.",
|
43
|
-
"suits" => "Are suits necessary in business?",
|
44
|
-
"secrets" => "Secrets are lies.",
|
45
|
-
"logging" => "Log all the things.",
|
46
|
-
"new_cache" => "Like the old cache but newer.",
|
47
|
-
"a/b" => "Why would someone use a slash? I don't know but someone did. Let's make this really long so they regret using slashes. Please don't use slashes.",
|
48
|
-
}
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
15
|
# Example middleware to allow reading the Flipper UI but nothing else.
|
53
16
|
class FlipperReadOnlyMiddleware
|
54
17
|
def initialize(app)
|
@@ -67,18 +30,17 @@ class FlipperReadOnlyMiddleware
|
|
67
30
|
end
|
68
31
|
|
69
32
|
# You can uncomment these to get some default data:
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
78
|
-
#
|
79
|
-
|
80
|
-
|
81
|
-
run Flipper::UI.app(flipper) { |builder|
|
33
|
+
# Flipper.enable(:search_performance_another_long_thing)
|
34
|
+
# Flipper.disable(:gauges_tracking)
|
35
|
+
# Flipper.disable(:unused)
|
36
|
+
# Flipper.enable_actor(:suits, Flipper::Actor.new('1'))
|
37
|
+
# Flipper.enable_actor(:suits, Flipper::Actor.new('6'))
|
38
|
+
# Flipper.enable_group(:secrets, :admins)
|
39
|
+
# Flipper.enable_percentage_of_time(:logging, 5)
|
40
|
+
# Flipper.enable_percentage_of_actors(:new_cache, 15)
|
41
|
+
# Flipper.add("a/b")
|
42
|
+
|
43
|
+
run Flipper::UI.app { |builder|
|
82
44
|
builder.use Rack::Session::Cookie, secret: "_super_secret"
|
83
45
|
builder.use FlipperReadOnlyMiddleware
|
84
46
|
}
|
data/examples/ui/basic.ru
CHANGED
@@ -42,16 +42,16 @@ Flipper::UI.configure do |config|
|
|
42
42
|
end
|
43
43
|
|
44
44
|
# You can uncomment these to get some default data:
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
45
|
+
# Flipper.enable(:search_performance_another_long_thing)
|
46
|
+
# Flipper.disable(:gauges_tracking)
|
47
|
+
# Flipper.disable(:unused)
|
48
|
+
# Flipper.enable_actor(:suits, Flipper::Actor.new('1'))
|
49
|
+
# Flipper.enable_actor(:suits, Flipper::Actor.new('6'))
|
50
|
+
# Flipper.enable_group(:secrets, :admins)
|
51
|
+
# Flipper.enable_group(:secrets, :early_access)
|
52
|
+
# Flipper.enable_percentage_of_time(:logging, 5)
|
53
|
+
# Flipper.enable_percentage_of_actors(:new_cache, 15)
|
54
|
+
# Flipper.add("a/b")
|
55
55
|
|
56
56
|
run Flipper::UI.app { |builder|
|
57
57
|
builder.use Rack::Session::Cookie, secret: "_super_secret"
|
data/lib/flipper/ui.rb
CHANGED
@@ -39,14 +39,14 @@ module Flipper
|
|
39
39
|
def self.app(flipper = nil, options = {})
|
40
40
|
env_key = options.fetch(:env_key, 'flipper')
|
41
41
|
rack_protection_options = options.fetch(:rack_protection, use: :authenticity_token)
|
42
|
+
|
42
43
|
app = ->(_) { [200, { 'Content-Type' => 'text/html' }, ['']] }
|
43
44
|
builder = Rack::Builder.new
|
44
45
|
yield builder if block_given?
|
45
46
|
builder.use Rack::Protection, rack_protection_options
|
46
47
|
builder.use Rack::MethodOverride
|
47
48
|
builder.use Flipper::Middleware::SetupEnv, flipper, env_key: env_key
|
48
|
-
builder.use Flipper::Middleware
|
49
|
-
builder.use Flipper::UI::Middleware, env_key: env_key
|
49
|
+
builder.use Flipper::UI::Middleware, flipper: flipper, env_key: env_key
|
50
50
|
builder.run app
|
51
51
|
klass = self
|
52
52
|
builder.define_singleton_method(:inspect) { klass.inspect } # pretty rake routes output
|
data/lib/flipper/ui/action.rb
CHANGED
@@ -151,7 +151,7 @@ module Flipper
|
|
151
151
|
# location - The String location to set the Location header to.
|
152
152
|
def redirect_to(location)
|
153
153
|
status 302
|
154
|
-
header 'Location', "#{script_name}#{location}"
|
154
|
+
header 'Location', "#{script_name}#{Rack::Utils.escape_path(location)}"
|
155
155
|
halt [@code, @headers, ['']]
|
156
156
|
end
|
157
157
|
|
@@ -27,7 +27,7 @@ module Flipper
|
|
27
27
|
value = params['value'].to_s.strip
|
28
28
|
|
29
29
|
if Util.blank?(value)
|
30
|
-
error =
|
30
|
+
error = "#{value.inspect} is not a valid actor value."
|
31
31
|
redirect_to("/features/#{feature.key}/actors?error=#{error}")
|
32
32
|
end
|
33
33
|
|
@@ -49,14 +49,14 @@ module Flipper
|
|
49
49
|
value = params['value'].to_s.strip
|
50
50
|
|
51
51
|
if Util.blank?(value)
|
52
|
-
error =
|
52
|
+
error = "#{value.inspect} is not a valid feature name."
|
53
53
|
redirect_to("/features/new?error=#{error}")
|
54
54
|
end
|
55
55
|
|
56
56
|
feature = flipper[value]
|
57
57
|
feature.add
|
58
58
|
|
59
|
-
redirect_to "/features/#{
|
59
|
+
redirect_to "/features/#{value}"
|
60
60
|
end
|
61
61
|
end
|
62
62
|
end
|
@@ -35,7 +35,7 @@ module Flipper
|
|
35
35
|
|
36
36
|
redirect_to("/features/#{feature.key}")
|
37
37
|
else
|
38
|
-
error =
|
38
|
+
error = "The group named #{value.inspect} has not been registered."
|
39
39
|
redirect_to("/features/#{feature.key}/groups?error=#{error}")
|
40
40
|
end
|
41
41
|
end
|
@@ -16,7 +16,7 @@ module Flipper
|
|
16
16
|
begin
|
17
17
|
feature.enable_percentage_of_actors params['value']
|
18
18
|
rescue ArgumentError => exception
|
19
|
-
error =
|
19
|
+
error = "Invalid percentage of actors value: #{exception.message}"
|
20
20
|
redirect_to("/features/#{@feature.key}?error=#{error}")
|
21
21
|
end
|
22
22
|
|
@@ -16,7 +16,7 @@ module Flipper
|
|
16
16
|
begin
|
17
17
|
feature.enable_percentage_of_time params['value']
|
18
18
|
rescue ArgumentError => exception
|
19
|
-
error =
|
19
|
+
error = "Invalid percentage of time value: #{exception.message}"
|
20
20
|
redirect_to("/features/#{@feature.key}?error=#{error}")
|
21
21
|
end
|
22
22
|
|
@@ -12,6 +12,7 @@ module Flipper
|
|
12
12
|
def initialize(app, options = {})
|
13
13
|
@app = app
|
14
14
|
@env_key = options.fetch(:env_key, 'flipper')
|
15
|
+
@flipper = options.fetch(:flipper) { Flipper }
|
15
16
|
|
16
17
|
@action_collection = ActionCollection.new
|
17
18
|
|
@@ -43,7 +44,7 @@ module Flipper
|
|
43
44
|
if action_class.nil?
|
44
45
|
@app.call(env)
|
45
46
|
else
|
46
|
-
flipper = env.fetch(@env_key)
|
47
|
+
flipper = env.fetch(@env_key) { Flipper }
|
47
48
|
action_class.run(flipper, request)
|
48
49
|
end
|
49
50
|
end
|
data/lib/flipper/version.rb
CHANGED
@@ -61,6 +61,23 @@ RSpec.describe Flipper::UI::Actions::ActorsGate do
|
|
61
61
|
expect(last_response.headers['Location']).to eq('/features/search')
|
62
62
|
end
|
63
63
|
|
64
|
+
context "when feature name contains space" do
|
65
|
+
before do
|
66
|
+
post 'features/sp%20ace/actors',
|
67
|
+
{ 'value' => value, 'operation' => 'enable', 'authenticity_token' => token },
|
68
|
+
'rack.session' => session
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'adds item to members' do
|
72
|
+
expect(flipper["sp ace"].actors_value).to include('User;6')
|
73
|
+
end
|
74
|
+
|
75
|
+
it "redirects back to feature" do
|
76
|
+
expect(last_response.status).to be(302)
|
77
|
+
expect(last_response.headers['Location']).to eq('/features/sp%20ace')
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
64
81
|
context 'value contains whitespace' do
|
65
82
|
let(:value) { ' User;6 ' }
|
66
83
|
|
@@ -75,7 +92,7 @@ RSpec.describe Flipper::UI::Actions::ActorsGate do
|
|
75
92
|
|
76
93
|
it 'redirects back to feature' do
|
77
94
|
expect(last_response.status).to be(302)
|
78
|
-
expect(last_response.headers['Location']).to eq('/features/search/actors?error=%22%22
|
95
|
+
expect(last_response.headers['Location']).to eq('/features/search/actors?error=%22%22%20is%20not%20a%20valid%20actor%20value.')
|
79
96
|
end
|
80
97
|
end
|
81
98
|
|
@@ -84,7 +101,7 @@ RSpec.describe Flipper::UI::Actions::ActorsGate do
|
|
84
101
|
|
85
102
|
it 'redirects back to feature' do
|
86
103
|
expect(last_response.status).to be(302)
|
87
|
-
expect(last_response.headers['Location']).to eq('/features/search/actors?error=%22%22
|
104
|
+
expect(last_response.headers['Location']).to eq('/features/search/actors?error=%22%22%20is%20not%20a%20valid%20actor%20value.')
|
88
105
|
end
|
89
106
|
end
|
90
107
|
end
|
@@ -31,6 +31,24 @@ RSpec.describe Flipper::UI::Actions::BooleanGate do
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
+
context "with space in feature name" do
|
35
|
+
before do
|
36
|
+
flipper.disable :search
|
37
|
+
post 'features/sp%20ace/boolean',
|
38
|
+
{ 'action' => 'Enable', 'authenticity_token' => token },
|
39
|
+
'rack.session' => session
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'updates feature' do
|
43
|
+
expect(flipper.enabled?("sp ace")).to be(true)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'redirects back to feature' do
|
47
|
+
expect(last_response.status).to be(302)
|
48
|
+
expect(last_response.headers['Location']).to eq('/features/sp%20ace')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
34
52
|
context 'with disable' do
|
35
53
|
before do
|
36
54
|
flipper.enable :search
|
@@ -29,6 +29,24 @@ RSpec.describe Flipper::UI::Actions::Feature do
|
|
29
29
|
expect(last_response.headers['Location']).to eq('/features')
|
30
30
|
end
|
31
31
|
|
32
|
+
context "with space in feature name" do
|
33
|
+
before do
|
34
|
+
flipper.enable "sp ace"
|
35
|
+
delete '/features/sp%20ace',
|
36
|
+
{ 'authenticity_token' => token },
|
37
|
+
'rack.session' => session
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'removes feature' do
|
41
|
+
expect(flipper.features.map(&:key)).not_to include('sp ace')
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'redirects to features' do
|
45
|
+
expect(last_response.status).to be(302)
|
46
|
+
expect(last_response.headers['Location']).to eq('/features')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
32
50
|
context 'when feature_removal_enabled is set to false' do
|
33
51
|
around do |example|
|
34
52
|
begin
|
@@ -95,7 +95,7 @@ RSpec.describe Flipper::UI::Actions::Features do
|
|
95
95
|
expect(last_response.headers['Location']).to eq('/features/notifications_next')
|
96
96
|
end
|
97
97
|
|
98
|
-
context 'feature name
|
98
|
+
context 'feature name has whitespace at beginning and end' do
|
99
99
|
let(:feature_name) { ' notifications_next ' }
|
100
100
|
|
101
101
|
it 'adds feature without whitespace' do
|
@@ -103,6 +103,19 @@ RSpec.describe Flipper::UI::Actions::Features do
|
|
103
103
|
end
|
104
104
|
end
|
105
105
|
|
106
|
+
context 'feature name contains space' do
|
107
|
+
let(:feature_name) { 'notifications next' }
|
108
|
+
|
109
|
+
it 'adds feature with space' do
|
110
|
+
expect(flipper.features.map(&:key)).to include('notifications next')
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'redirects to feature' do
|
114
|
+
expect(last_response.status).to be(302)
|
115
|
+
expect(last_response.headers['Location']).to eq('/features/notifications%20next')
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
106
119
|
context 'for an invalid feature name' do
|
107
120
|
context 'empty feature name' do
|
108
121
|
let(:feature_name) { '' }
|
@@ -113,7 +126,7 @@ RSpec.describe Flipper::UI::Actions::Features do
|
|
113
126
|
|
114
127
|
it 'redirects back to feature' do
|
115
128
|
expect(last_response.status).to be(302)
|
116
|
-
expect(last_response.headers['Location']).to eq('/features/new?error=%22%22
|
129
|
+
expect(last_response.headers['Location']).to eq('/features/new?error=%22%22%20is%20not%20a%20valid%20feature%20name.')
|
117
130
|
end
|
118
131
|
end
|
119
132
|
|
@@ -126,7 +139,7 @@ RSpec.describe Flipper::UI::Actions::Features do
|
|
126
139
|
|
127
140
|
it 'redirects back to feature' do
|
128
141
|
expect(last_response.status).to be(302)
|
129
|
-
expect(last_response.headers['Location']).to eq('/features/new?error=%22%22
|
142
|
+
expect(last_response.headers['Location']).to eq('/features/new?error=%22%22%20is%20not%20a%20valid%20feature%20name.')
|
130
143
|
end
|
131
144
|
end
|
132
145
|
end
|
@@ -60,6 +60,23 @@ RSpec.describe Flipper::UI::Actions::GroupsGate do
|
|
60
60
|
expect(last_response.headers['Location']).to eq('/features/search')
|
61
61
|
end
|
62
62
|
|
63
|
+
context 'feature name contains space' do
|
64
|
+
before do
|
65
|
+
post 'features/sp%20ace/groups',
|
66
|
+
{ 'value' => group_name, 'operation' => 'enable', 'authenticity_token' => token },
|
67
|
+
'rack.session' => session
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'adds item to members' do
|
71
|
+
expect(flipper["sp ace"].groups_value).to include('admins')
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'redirects back to feature' do
|
75
|
+
expect(last_response.status).to be(302)
|
76
|
+
expect(last_response.headers['Location']).to eq('/features/sp%20ace')
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
63
80
|
context 'group name contains whitespace' do
|
64
81
|
let(:group_name) { ' admins ' }
|
65
82
|
|
@@ -74,7 +91,7 @@ RSpec.describe Flipper::UI::Actions::GroupsGate do
|
|
74
91
|
|
75
92
|
it 'redirects back to feature' do
|
76
93
|
expect(last_response.status).to be(302)
|
77
|
-
expect(last_response.headers['Location']).to eq('/features/search/groups?error=The
|
94
|
+
expect(last_response.headers['Location']).to eq('/features/search/groups?error=The%20group%20named%20%22not_here%22%20has%20not%20been%20registered.')
|
78
95
|
end
|
79
96
|
end
|
80
97
|
|
@@ -83,7 +100,7 @@ RSpec.describe Flipper::UI::Actions::GroupsGate do
|
|
83
100
|
|
84
101
|
it 'redirects back to feature' do
|
85
102
|
expect(last_response.status).to be(302)
|
86
|
-
expect(last_response.headers['Location']).to eq('/features/search/groups?error=The
|
103
|
+
expect(last_response.headers['Location']).to eq('/features/search/groups?error=The%20group%20named%20%22%22%20has%20not%20been%20registered.')
|
87
104
|
end
|
88
105
|
end
|
89
106
|
|
@@ -92,7 +109,7 @@ RSpec.describe Flipper::UI::Actions::GroupsGate do
|
|
92
109
|
|
93
110
|
it 'redirects back to feature' do
|
94
111
|
expect(last_response.status).to be(302)
|
95
|
-
expect(last_response.headers['Location']).to eq('/features/search/groups?error=The
|
112
|
+
expect(last_response.headers['Location']).to eq('/features/search/groups?error=The%20group%20named%20%22%22%20has%20not%20been%20registered.')
|
96
113
|
end
|
97
114
|
end
|
98
115
|
end
|
@@ -30,6 +30,23 @@ RSpec.describe Flipper::UI::Actions::PercentageOfActorsGate do
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
+
context 'with space in feature name' do
|
34
|
+
before do
|
35
|
+
post 'features/sp%20ace/percentage_of_actors',
|
36
|
+
{ 'value' => '24', 'authenticity_token' => token },
|
37
|
+
'rack.session' => session
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'enables the feature' do
|
41
|
+
expect(flipper["sp ace"].percentage_of_actors_value).to be(24)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'redirects back to feature' do
|
45
|
+
expect(last_response.status).to be(302)
|
46
|
+
expect(last_response.headers['Location']).to eq('/features/sp%20ace')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
33
50
|
context 'with invalid value' do
|
34
51
|
before do
|
35
52
|
post 'features/search/percentage_of_actors',
|
@@ -43,7 +60,7 @@ RSpec.describe Flipper::UI::Actions::PercentageOfActorsGate do
|
|
43
60
|
|
44
61
|
it 'redirects back to feature' do
|
45
62
|
expect(last_response.status).to be(302)
|
46
|
-
expect(last_response.headers['Location']).to eq('/features/search?error=Invalid
|
63
|
+
expect(last_response.headers['Location']).to eq('/features/search?error=Invalid%20percentage%20of%20actors%20value:%20value%20must%20be%20a%20positive%20number%20less%20than%20or%20equal%20to%20100,%20but%20was%20555')
|
47
64
|
end
|
48
65
|
end
|
49
66
|
end
|
@@ -30,6 +30,23 @@ RSpec.describe Flipper::UI::Actions::PercentageOfTimeGate do
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
+
context 'with space in feature name' do
|
34
|
+
before do
|
35
|
+
post 'features/sp%20ace/percentage_of_time',
|
36
|
+
{ 'value' => '24', 'authenticity_token' => token },
|
37
|
+
'rack.session' => session
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'enables the feature' do
|
41
|
+
expect(flipper["sp ace"].percentage_of_time_value).to be(24)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'redirects back to feature' do
|
45
|
+
expect(last_response.status).to be(302)
|
46
|
+
expect(last_response.headers['Location']).to eq('/features/sp%20ace')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
33
50
|
context 'with invalid value' do
|
34
51
|
before do
|
35
52
|
post 'features/search/percentage_of_time',
|
@@ -43,7 +60,7 @@ RSpec.describe Flipper::UI::Actions::PercentageOfTimeGate do
|
|
43
60
|
|
44
61
|
it 'redirects back to feature' do
|
45
62
|
expect(last_response.status).to be(302)
|
46
|
-
expect(last_response.headers['Location']).to eq('/features/search?error=Invalid
|
63
|
+
expect(last_response.headers['Location']).to eq('/features/search?error=Invalid%20percentage%20of%20time%20value:%20value%20must%20be%20a%20positive%20number%20less%20than%20or%20equal%20to%20100,%20but%20was%20555')
|
47
64
|
end
|
48
65
|
end
|
49
66
|
end
|
data/spec/flipper/ui_spec.rb
CHANGED
@@ -24,19 +24,6 @@ RSpec.describe Flipper::UI do
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
describe 'Initializing middleware lazily with a block' do
|
28
|
-
let(:app) do
|
29
|
-
build_app(-> { flipper })
|
30
|
-
end
|
31
|
-
|
32
|
-
it 'works' do
|
33
|
-
flipper.enable :some_great_feature
|
34
|
-
get '/features'
|
35
|
-
expect(last_response.status).to be(200)
|
36
|
-
expect(last_response.body).to include('some_great_feature')
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
27
|
describe 'Request method unsupported by action' do
|
41
28
|
it 'raises error' do
|
42
29
|
expect do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flipper-ui
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.22.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Nunemaker
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-07-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -56,14 +56,14 @@ dependencies:
|
|
56
56
|
requirements:
|
57
57
|
- - "~>"
|
58
58
|
- !ruby/object:Gem::Version
|
59
|
-
version: 0.
|
59
|
+
version: 0.22.0
|
60
60
|
type: :runtime
|
61
61
|
prerelease: false
|
62
62
|
version_requirements: !ruby/object:Gem::Requirement
|
63
63
|
requirements:
|
64
64
|
- - "~>"
|
65
65
|
- !ruby/object:Gem::Version
|
66
|
-
version: 0.
|
66
|
+
version: 0.22.0
|
67
67
|
- !ruby/object:Gem::Dependency
|
68
68
|
name: erubi
|
69
69
|
requirement: !ruby/object:Gem::Requirement
|