flipper-ui 1.1.2 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/examples/ui/basic.ru +2 -2
- data/lib/flipper/ui/action.rb +4 -3
- data/lib/flipper/ui/configuration.rb +5 -0
- data/lib/flipper/ui/public/js/application.js +12 -1
- data/lib/flipper/ui/public/js/version.js +33 -0
- data/lib/flipper/ui/views/feature.erb +8 -3
- data/lib/flipper/ui/views/layout.erb +16 -1
- data/lib/flipper/ui.rb +1 -1
- data/lib/flipper/version.rb +11 -1
- data/spec/flipper/ui/actions/actors_gate_spec.rb +5 -5
- data/spec/flipper/ui/actions/boolean_gate_spec.rb +3 -3
- data/spec/flipper/ui/actions/export_spec.rb +2 -2
- data/spec/flipper/ui/actions/feature_spec.rb +26 -5
- data/spec/flipper/ui/actions/features_spec.rb +4 -4
- data/spec/flipper/ui/actions/groups_gate_spec.rb +6 -6
- data/spec/flipper/ui/actions/home_spec.rb +1 -1
- data/spec/flipper/ui/actions/import_spec.rb +1 -1
- data/spec/flipper/ui/actions/percentage_of_actors_gate_spec.rb +3 -3
- data/spec/flipper/ui/actions/percentage_of_time_gate_spec.rb +3 -3
- data/spec/flipper/ui_spec.rb +1 -1
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b33985781ada74b2666ef3b636288e1c5316b7f32f8178f3adafccf3f30e7c4f
|
4
|
+
data.tar.gz: 637de7cc0214932ea6fa47aa4d3a4d32e3b8e4dd9b4e97417a610a9405fc7898
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ebc76af3eda0bf9b60912dc58b99fcaf65677a485cfa9ed4ca7a52bcf12934a6870680eb702869faa47f930575cc4b1046b3ddc34c2958f5cf7b4a504dbd7f48
|
7
|
+
data.tar.gz: a94f123f0e800036d602df242825c0452e081ccb91010f7642ecb118888b85e35c8eba63377f1fa3e1b05037ced0d2e9938413d554d0b52683709dafad11e2f7
|
data/examples/ui/basic.ru
CHANGED
@@ -42,8 +42,8 @@ Flipper::UI.configure do |config|
|
|
42
42
|
|
43
43
|
config.actor_names_source = lambda do |_keys|
|
44
44
|
{
|
45
|
-
'1' => 'John',
|
46
|
-
'6' => 'Brandon',
|
45
|
+
'1' => '<a href="https://johnnunemaker.com">John</a>',
|
46
|
+
'6' => '<a href="https://opensoul.org">Brandon</a>',
|
47
47
|
}
|
48
48
|
end
|
49
49
|
end
|
data/lib/flipper/ui/action.rb
CHANGED
@@ -53,6 +53,7 @@ module Flipper
|
|
53
53
|
style-src 'self' 'unsafe-inline';
|
54
54
|
style-src-attr 'unsafe-inline' ;
|
55
55
|
style-src-elem 'self';
|
56
|
+
connect-src https://www.flippercloud.io;
|
56
57
|
CSP
|
57
58
|
|
58
59
|
# Public: Call this in subclasses so the action knows its route.
|
@@ -108,7 +109,7 @@ module Flipper
|
|
108
109
|
@flipper = flipper
|
109
110
|
@request = request
|
110
111
|
@code = 200
|
111
|
-
@headers = {
|
112
|
+
@headers = {Rack::CONTENT_TYPE => 'text/plain'}
|
112
113
|
@breadcrumbs =
|
113
114
|
if Flipper::UI.configuration.application_breadcrumb_href
|
114
115
|
[Breadcrumb.new('App', Flipper::UI.configuration.application_breadcrumb_href)]
|
@@ -158,7 +159,7 @@ module Flipper
|
|
158
159
|
#
|
159
160
|
# Returns a response.
|
160
161
|
def view_response(name)
|
161
|
-
header
|
162
|
+
header Rack::CONTENT_TYPE, 'text/html'
|
162
163
|
header 'content-security-policy', CONTENT_SECURITY_POLICY
|
163
164
|
body = view_with_layout { view_without_layout name }
|
164
165
|
halt [@code, @headers, [body]]
|
@@ -171,7 +172,7 @@ module Flipper
|
|
171
172
|
#
|
172
173
|
# Returns a response.
|
173
174
|
def json_response(object)
|
174
|
-
header
|
175
|
+
header Rack::CONTENT_TYPE, 'application/json'
|
175
176
|
body = case object
|
176
177
|
when String
|
177
178
|
object
|
@@ -63,6 +63,10 @@ module Flipper
|
|
63
63
|
# Default is false.
|
64
64
|
attr_accessor :confirm_fully_enable
|
65
65
|
|
66
|
+
# Public: if you want to get a confirm pop up box while disabling a feature
|
67
|
+
# Default is false.
|
68
|
+
attr_accessor :confirm_disable
|
69
|
+
|
66
70
|
VALID_BANNER_CLASS_VALUES = %w(
|
67
71
|
danger
|
68
72
|
dark
|
@@ -91,6 +95,7 @@ module Flipper
|
|
91
95
|
@show_feature_description_in_list = false
|
92
96
|
@actors_separator = ','
|
93
97
|
@confirm_fully_enable = false
|
98
|
+
@confirm_disable = true
|
94
99
|
@read_only = false
|
95
100
|
end
|
96
101
|
|
@@ -14,7 +14,18 @@ $(function () {
|
|
14
14
|
e.preventDefault();
|
15
15
|
}
|
16
16
|
});
|
17
|
-
|
17
|
+
|
18
|
+
$("#disable_feature__button").on("click", function (e) {
|
19
|
+
const featureName = $(e.target).data("confirmation-text");
|
20
|
+
const promptMessage = prompt(
|
21
|
+
`Are you sure you want to disable this feature for everyone? Please enter the name of the feature to confirm it: ${featureName}`
|
22
|
+
);
|
23
|
+
|
24
|
+
if (promptMessage !== featureName) {
|
25
|
+
e.preventDefault();
|
26
|
+
}
|
27
|
+
});
|
28
|
+
|
18
29
|
$("#delete_feature__button").on("click", function (e) {
|
19
30
|
const featureName = $(e.target).data("confirmation-text");
|
20
31
|
const promptMessage = prompt(
|
@@ -0,0 +1,33 @@
|
|
1
|
+
// Get the latest release from RubyGems.org and show a badge if it's not the current version
|
2
|
+
function checkLatestRelease() {
|
3
|
+
// Skip check if last check was less than 1 day ago
|
4
|
+
if(localStorage.getItem('flipper.releaseCheckedAt') > new Date().getTime() - 86400000) return
|
5
|
+
|
6
|
+
// store the last time we checked for a new version
|
7
|
+
localStorage.setItem('flipper.releaseCheckedAt', new Date().getTime())
|
8
|
+
|
9
|
+
fetch('https://www.flippercloud.io/release.json').then(response => {
|
10
|
+
// Something went wrong, so just give up
|
11
|
+
if(!response.ok) return
|
12
|
+
|
13
|
+
response.json().then(release => {
|
14
|
+
localStorage.setItem('flipper.release', JSON.stringify(release))
|
15
|
+
showReleaseBadge()
|
16
|
+
})
|
17
|
+
})
|
18
|
+
}
|
19
|
+
|
20
|
+
// Show a badge if a new release is available
|
21
|
+
function showReleaseBadge() {
|
22
|
+
const badge = document.querySelector('#new-version-badge')
|
23
|
+
const release = JSON.parse(localStorage.getItem('flipper.release') || false)
|
24
|
+
|
25
|
+
if(!badge || !release || badge.dataset.version === release.version) return
|
26
|
+
|
27
|
+
badge.innerText = `${release.version} available!`
|
28
|
+
badge.setAttribute('href', release.changelog_uri)
|
29
|
+
badge.classList.remove('d-none')
|
30
|
+
}
|
31
|
+
|
32
|
+
checkLatestRelease()
|
33
|
+
showReleaseBadge()
|
@@ -66,7 +66,7 @@
|
|
66
66
|
<div class="col col-mr-auto pl-md-5">
|
67
67
|
<h6 class="m-0">
|
68
68
|
<% if Flipper::UI::Util.present?(@feature.actor_names[item]) %>
|
69
|
-
|
69
|
+
<%== Sanitize.fragment("#{@feature.actor_names[item]} (#{item})", Sanitize::Config::BASIC) %>
|
70
70
|
<% else %>
|
71
71
|
<%= item %>
|
72
72
|
<% end %>
|
@@ -263,8 +263,13 @@
|
|
263
263
|
|
264
264
|
<% unless @feature.off? %>
|
265
265
|
<div class="col">
|
266
|
-
<button type="submit" name="action" value="Disable" class="btn btn-outline-danger btn-block">
|
267
|
-
<span class="d-block" data-toggle="tooltip"
|
266
|
+
<button type="submit" name="action" value="Disable" <% if Flipper::UI.configuration.confirm_disable %>id="disable_feature__button"<% end %> class="btn btn-outline-danger btn-block">
|
267
|
+
<span class="d-block" data-toggle="tooltip"
|
268
|
+
<% if Flipper::UI.configuration.confirm_disable %>
|
269
|
+
data-confirmation-text="<%= feature_name %>"
|
270
|
+
<% end %>
|
271
|
+
title="Disable for everyone by clearing all percentages, groups and actors."
|
272
|
+
>
|
268
273
|
Disable
|
269
274
|
</span>
|
270
275
|
</button>
|
@@ -21,6 +21,20 @@
|
|
21
21
|
<a href="https://www.flippercloud.io/docs/ui?utm_source=oss&utm_medium=ui&utm_campaign=docs">Docs</a> •
|
22
22
|
<a href="<%= script_name %>/settings">Settings</a> •
|
23
23
|
Version: <%= Flipper::VERSION %>
|
24
|
+
<a href="#" class="badge badge-warning ml-2 d-none" style="font-size:100%" id="new-version-badge" data-version="<%= Flipper::VERSION %>">
|
25
|
+
</a>
|
26
|
+
|
27
|
+
<% if Flipper.deprecated_ruby_version? %>
|
28
|
+
<a href="https://github.com/flippercloud/flipper/pull/776" class="badge badge-danger ml-2" style="font-size:100%">
|
29
|
+
Ruby <%= RUBY_VERSION %> deprecated
|
30
|
+
</a>
|
31
|
+
<% end %>
|
32
|
+
|
33
|
+
<% if defined?(Rails) && Flipper::Engine.deprecated_rails_version? %>
|
34
|
+
<a href="https://github.com/flippercloud/flipper/pull/776" class="badge badge-danger ml-2" style="font-size:100%">
|
35
|
+
Rails <%= Rails.version %> deprecated
|
36
|
+
</a>
|
37
|
+
<% end %>
|
24
38
|
</div>
|
25
39
|
|
26
40
|
<nav aria-label="breadcrumb">
|
@@ -60,6 +74,7 @@
|
|
60
74
|
<script src="<%= script_name + jquery_js[:src] %>" integrity="<%= jquery_js[:hash] %>" crossorigin="anonymous"></script>
|
61
75
|
<script src="<%= script_name + popper_js[:src] %>" integrity="<%= popper_js[:hash] %>" crossorigin="anonymous"></script>
|
62
76
|
<script src="<%= script_name + bootstrap_js[:src] %>" integrity="<%= bootstrap_js[:hash] %>" crossorigin="anonymous"></script>
|
63
|
-
<script src="<%= script_name %>/js/application.js"></script>
|
77
|
+
<script src="<%= script_name %>/js/application.js?v=<%= Flipper::VERSION %>"></script>
|
78
|
+
<script src="<%= script_name %>/js/version.js?v=<%= Flipper::VERSION %>"></script>
|
64
79
|
</body>
|
65
80
|
</html>
|
data/lib/flipper/ui.rb
CHANGED
@@ -22,7 +22,7 @@ module Flipper
|
|
22
22
|
env_key = options.fetch(:env_key, 'flipper')
|
23
23
|
rack_protection_options = options.fetch(:rack_protection, use: :authenticity_token)
|
24
24
|
|
25
|
-
app = ->(_) { [200, {
|
25
|
+
app = ->(_) { [200, { Rack::CONTENT_TYPE => 'text/html' }, ['']] }
|
26
26
|
builder = Rack::Builder.new
|
27
27
|
yield builder if block_given?
|
28
28
|
builder.use Rack::Protection, rack_protection_options
|
data/lib/flipper/version.rb
CHANGED
@@ -1,3 +1,13 @@
|
|
1
1
|
module Flipper
|
2
|
-
VERSION = '1.
|
2
|
+
VERSION = '1.2.0'.freeze
|
3
|
+
|
4
|
+
REQUIRED_RUBY_VERSION = '2.6'.freeze
|
5
|
+
NEXT_REQUIRED_RUBY_VERSION = '3.0'.freeze
|
6
|
+
|
7
|
+
REQUIRED_RAILS_VERSION = '5.2'.freeze
|
8
|
+
NEXT_REQUIRED_RAILS_VERSION = '6.1.0'.freeze
|
9
|
+
|
10
|
+
def self.deprecated_ruby_version?
|
11
|
+
Gem::Version.new(RUBY_VERSION) < Gem::Version.new(NEXT_REQUIRED_RUBY_VERSION)
|
12
|
+
end
|
3
13
|
end
|
@@ -68,7 +68,7 @@ RSpec.describe Flipper::UI::Actions::ActorsGate do
|
|
68
68
|
|
69
69
|
it 'redirects back to feature' do
|
70
70
|
expect(last_response.status).to be(302)
|
71
|
-
expect(last_response.headers['
|
71
|
+
expect(last_response.headers['location']).to eq('/features/search')
|
72
72
|
end
|
73
73
|
|
74
74
|
context "when feature name contains space" do
|
@@ -84,7 +84,7 @@ RSpec.describe Flipper::UI::Actions::ActorsGate do
|
|
84
84
|
|
85
85
|
it "redirects back to feature" do
|
86
86
|
expect(last_response.status).to be(302)
|
87
|
-
expect(last_response.headers['
|
87
|
+
expect(last_response.headers['location']).to eq('/features/sp%20ace')
|
88
88
|
end
|
89
89
|
end
|
90
90
|
|
@@ -114,7 +114,7 @@ RSpec.describe Flipper::UI::Actions::ActorsGate do
|
|
114
114
|
|
115
115
|
it 'redirects back to feature' do
|
116
116
|
expect(last_response.status).to be(302)
|
117
|
-
expect(last_response.headers['
|
117
|
+
expect(last_response.headers['location']).to eq('/features/search/actors?error=%22%22%20is%20not%20a%20valid%20actor%20value.')
|
118
118
|
end
|
119
119
|
end
|
120
120
|
|
@@ -123,7 +123,7 @@ RSpec.describe Flipper::UI::Actions::ActorsGate do
|
|
123
123
|
|
124
124
|
it 'redirects back to feature' do
|
125
125
|
expect(last_response.status).to be(302)
|
126
|
-
expect(last_response.headers['
|
126
|
+
expect(last_response.headers['location']).to eq('/features/search/actors?error=%22%22%20is%20not%20a%20valid%20actor%20value.')
|
127
127
|
end
|
128
128
|
end
|
129
129
|
end
|
@@ -175,7 +175,7 @@ RSpec.describe Flipper::UI::Actions::ActorsGate do
|
|
175
175
|
|
176
176
|
it 'redirects back to feature' do
|
177
177
|
expect(last_response.status).to be(302)
|
178
|
-
expect(last_response.headers['
|
178
|
+
expect(last_response.headers['location']).to eq('/features/search')
|
179
179
|
end
|
180
180
|
|
181
181
|
context 'value contains whitespace' do
|
@@ -25,7 +25,7 @@ RSpec.describe Flipper::UI::Actions::BooleanGate do
|
|
25
25
|
|
26
26
|
it 'redirects back to feature' do
|
27
27
|
expect(last_response.status).to be(302)
|
28
|
-
expect(last_response.headers['
|
28
|
+
expect(last_response.headers['location']).to eq('/features/search')
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
@@ -43,7 +43,7 @@ RSpec.describe Flipper::UI::Actions::BooleanGate do
|
|
43
43
|
|
44
44
|
it 'redirects back to feature' do
|
45
45
|
expect(last_response.status).to be(302)
|
46
|
-
expect(last_response.headers['
|
46
|
+
expect(last_response.headers['location']).to eq('/features/sp%20ace')
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
@@ -61,7 +61,7 @@ RSpec.describe Flipper::UI::Actions::BooleanGate do
|
|
61
61
|
|
62
62
|
it 'redirects back to feature' do
|
63
63
|
expect(last_response.status).to be(302)
|
64
|
-
expect(last_response.headers['
|
64
|
+
expect(last_response.headers['location']).to eq('/features/search')
|
65
65
|
end
|
66
66
|
end
|
67
67
|
end
|
@@ -33,12 +33,12 @@ RSpec.describe Flipper::UI::Actions::Features do
|
|
33
33
|
end
|
34
34
|
|
35
35
|
it 'sets content disposition' do
|
36
|
-
expect(last_response.headers['
|
36
|
+
expect(last_response.headers['content-disposition']).to match(/Attachment;filename=flipper_memory_[0-9]*\.json/)
|
37
37
|
end
|
38
38
|
|
39
39
|
it 'renders json' do
|
40
40
|
data = JSON.parse(last_response.body)
|
41
|
-
expect(last_response.headers['
|
41
|
+
expect(last_response.headers['content-type']).to eq('application/json')
|
42
42
|
expect(data['version']).to eq(1)
|
43
43
|
expect(data['features']).to eq({
|
44
44
|
"analytics" => {"boolean"=>nil, "expression"=>{"Equal"=>[{"Property"=>["plan"]}, "basic"]}, "groups"=>[], "actors"=>[], "percentage_of_actors"=>nil, "percentage_of_time"=>nil},
|
@@ -24,7 +24,7 @@ RSpec.describe Flipper::UI::Actions::Feature do
|
|
24
24
|
|
25
25
|
it 'redirects to features' do
|
26
26
|
expect(last_response.status).to be(302)
|
27
|
-
expect(last_response.headers['
|
27
|
+
expect(last_response.headers['location']).to eq('/features')
|
28
28
|
end
|
29
29
|
|
30
30
|
context "with space in feature name" do
|
@@ -41,7 +41,7 @@ RSpec.describe Flipper::UI::Actions::Feature do
|
|
41
41
|
|
42
42
|
it 'redirects to features' do
|
43
43
|
expect(last_response.status).to be(302)
|
44
|
-
expect(last_response.headers['
|
44
|
+
expect(last_response.headers['location']).to eq('/features')
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
@@ -80,7 +80,7 @@ RSpec.describe Flipper::UI::Actions::Feature do
|
|
80
80
|
|
81
81
|
it 'redirects to features' do
|
82
82
|
expect(last_response.status).to be(302)
|
83
|
-
expect(last_response.headers['
|
83
|
+
expect(last_response.headers['location']).to eq('/features')
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
@@ -138,14 +138,35 @@ RSpec.describe Flipper::UI::Actions::Feature do
|
|
138
138
|
}
|
139
139
|
}
|
140
140
|
end
|
141
|
-
|
142
|
-
get '/features/search'
|
143
141
|
end
|
144
142
|
|
145
143
|
it 'renders template with custom actor names' do
|
144
|
+
get '/features/search'
|
146
145
|
expect(last_response.body).to include('Some Actor Name (some_actor_name)')
|
147
146
|
expect(last_response.body).not_to include('Some Other Actor Name')
|
148
147
|
end
|
148
|
+
|
149
|
+
it 'allows basic html' do
|
150
|
+
Flipper::UI.configure do |config|
|
151
|
+
config.actor_names_source = lambda { |_keys|
|
152
|
+
{ "some_actor_name" => '<a href="/users/some_actor_name">Some Actor Name</a>', }
|
153
|
+
}
|
154
|
+
end
|
155
|
+
|
156
|
+
get '/features/search'
|
157
|
+
expect(last_response.body).to include('<a href="/users/some_actor_name" rel="nofollow">Some Actor Name</a>')
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'sanitizes dangerous markup' do
|
161
|
+
Flipper::UI.configure do |config|
|
162
|
+
config.actor_names_source = lambda { |_keys|
|
163
|
+
{ "some_actor_name" => '<a href="javascript:alert(\'hello\')">Some Actor Name</a>', }
|
164
|
+
}
|
165
|
+
end
|
166
|
+
|
167
|
+
get '/features/search'
|
168
|
+
expect(last_response.body).not_to include('javascript:alert')
|
169
|
+
end
|
149
170
|
end
|
150
171
|
end
|
151
172
|
|
@@ -104,7 +104,7 @@ RSpec.describe Flipper::UI::Actions::Features do
|
|
104
104
|
|
105
105
|
it 'redirects to feature' do
|
106
106
|
expect(last_response.status).to be(302)
|
107
|
-
expect(last_response.headers['
|
107
|
+
expect(last_response.headers['location']).to eq('/features/notifications_next')
|
108
108
|
end
|
109
109
|
|
110
110
|
context 'feature name has whitespace at beginning and end' do
|
@@ -124,7 +124,7 @@ RSpec.describe Flipper::UI::Actions::Features do
|
|
124
124
|
|
125
125
|
it 'redirects to feature' do
|
126
126
|
expect(last_response.status).to be(302)
|
127
|
-
expect(last_response.headers['
|
127
|
+
expect(last_response.headers['location']).to eq('/features/notifications%20next')
|
128
128
|
end
|
129
129
|
end
|
130
130
|
|
@@ -138,7 +138,7 @@ RSpec.describe Flipper::UI::Actions::Features do
|
|
138
138
|
|
139
139
|
it 'redirects back to feature' do
|
140
140
|
expect(last_response.status).to be(302)
|
141
|
-
expect(last_response.headers['
|
141
|
+
expect(last_response.headers['location']).to eq('/features/new?error=%22%22%20is%20not%20a%20valid%20feature%20name.')
|
142
142
|
end
|
143
143
|
end
|
144
144
|
|
@@ -151,7 +151,7 @@ RSpec.describe Flipper::UI::Actions::Features do
|
|
151
151
|
|
152
152
|
it 'redirects back to feature' do
|
153
153
|
expect(last_response.status).to be(302)
|
154
|
-
expect(last_response.headers['
|
154
|
+
expect(last_response.headers['location']).to eq('/features/new?error=%22%22%20is%20not%20a%20valid%20feature%20name.')
|
155
155
|
end
|
156
156
|
end
|
157
157
|
end
|
@@ -55,7 +55,7 @@ RSpec.describe Flipper::UI::Actions::GroupsGate do
|
|
55
55
|
|
56
56
|
it 'redirects back to feature' do
|
57
57
|
expect(last_response.status).to be(302)
|
58
|
-
expect(last_response.headers['
|
58
|
+
expect(last_response.headers['location']).to eq('/features/search')
|
59
59
|
end
|
60
60
|
|
61
61
|
context 'feature name contains space' do
|
@@ -71,7 +71,7 @@ RSpec.describe Flipper::UI::Actions::GroupsGate do
|
|
71
71
|
|
72
72
|
it 'redirects back to feature' do
|
73
73
|
expect(last_response.status).to be(302)
|
74
|
-
expect(last_response.headers['
|
74
|
+
expect(last_response.headers['location']).to eq('/features/sp%20ace')
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
@@ -89,7 +89,7 @@ RSpec.describe Flipper::UI::Actions::GroupsGate do
|
|
89
89
|
|
90
90
|
it 'redirects back to feature' do
|
91
91
|
expect(last_response.status).to be(302)
|
92
|
-
expect(last_response.headers['
|
92
|
+
expect(last_response.headers['location']).to eq('/features/search/groups?error=The%20group%20named%20%22not_here%22%20has%20not%20been%20registered.')
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
@@ -98,7 +98,7 @@ RSpec.describe Flipper::UI::Actions::GroupsGate do
|
|
98
98
|
|
99
99
|
it 'redirects back to feature' do
|
100
100
|
expect(last_response.status).to be(302)
|
101
|
-
expect(last_response.headers['
|
101
|
+
expect(last_response.headers['location']).to eq('/features/search/groups?error=The%20group%20named%20%22%22%20has%20not%20been%20registered.')
|
102
102
|
end
|
103
103
|
end
|
104
104
|
|
@@ -107,7 +107,7 @@ RSpec.describe Flipper::UI::Actions::GroupsGate do
|
|
107
107
|
|
108
108
|
it 'redirects back to feature' do
|
109
109
|
expect(last_response.status).to be(302)
|
110
|
-
expect(last_response.headers['
|
110
|
+
expect(last_response.headers['location']).to eq('/features/search/groups?error=The%20group%20named%20%22%22%20has%20not%20been%20registered.')
|
111
111
|
end
|
112
112
|
end
|
113
113
|
end
|
@@ -129,7 +129,7 @@ RSpec.describe Flipper::UI::Actions::GroupsGate do
|
|
129
129
|
|
130
130
|
it 'redirects back to feature' do
|
131
131
|
expect(last_response.status).to be(302)
|
132
|
-
expect(last_response.headers['
|
132
|
+
expect(last_response.headers['location']).to eq('/features/search')
|
133
133
|
end
|
134
134
|
|
135
135
|
context 'group name contains whitespace' do
|
@@ -8,7 +8,7 @@ RSpec.describe Flipper::UI::Actions::Home do
|
|
8
8
|
|
9
9
|
it 'responds with redirect' do
|
10
10
|
expect(last_response.status).to be(302)
|
11
|
-
expect(last_response.headers['
|
11
|
+
expect(last_response.headers['location']).to eq('/features')
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
@@ -35,7 +35,7 @@ RSpec.describe Flipper::UI::Actions::Import do
|
|
35
35
|
|
36
36
|
it 'responds with redirect to settings' do
|
37
37
|
expect(last_response.status).to be(302)
|
38
|
-
expect(last_response.headers['
|
38
|
+
expect(last_response.headers['location']).to eq('/features')
|
39
39
|
end
|
40
40
|
end
|
41
41
|
end
|
@@ -24,7 +24,7 @@ RSpec.describe Flipper::UI::Actions::PercentageOfActorsGate do
|
|
24
24
|
|
25
25
|
it 'redirects back to feature' do
|
26
26
|
expect(last_response.status).to be(302)
|
27
|
-
expect(last_response.headers['
|
27
|
+
expect(last_response.headers['location']).to eq('/features/search')
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
@@ -41,7 +41,7 @@ RSpec.describe Flipper::UI::Actions::PercentageOfActorsGate do
|
|
41
41
|
|
42
42
|
it 'redirects back to feature' do
|
43
43
|
expect(last_response.status).to be(302)
|
44
|
-
expect(last_response.headers['
|
44
|
+
expect(last_response.headers['location']).to eq('/features/sp%20ace')
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
@@ -58,7 +58,7 @@ RSpec.describe Flipper::UI::Actions::PercentageOfActorsGate do
|
|
58
58
|
|
59
59
|
it 'redirects back to feature' do
|
60
60
|
expect(last_response.status).to be(302)
|
61
|
-
expect(last_response.headers['
|
61
|
+
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')
|
62
62
|
end
|
63
63
|
end
|
64
64
|
end
|
@@ -24,7 +24,7 @@ RSpec.describe Flipper::UI::Actions::PercentageOfTimeGate do
|
|
24
24
|
|
25
25
|
it 'redirects back to feature' do
|
26
26
|
expect(last_response.status).to be(302)
|
27
|
-
expect(last_response.headers['
|
27
|
+
expect(last_response.headers['location']).to eq('/features/search')
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
@@ -41,7 +41,7 @@ RSpec.describe Flipper::UI::Actions::PercentageOfTimeGate do
|
|
41
41
|
|
42
42
|
it 'redirects back to feature' do
|
43
43
|
expect(last_response.status).to be(302)
|
44
|
-
expect(last_response.headers['
|
44
|
+
expect(last_response.headers['location']).to eq('/features/sp%20ace')
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
@@ -58,7 +58,7 @@ RSpec.describe Flipper::UI::Actions::PercentageOfTimeGate do
|
|
58
58
|
|
59
59
|
it 'redirects back to feature' do
|
60
60
|
expect(last_response.status).to be(302)
|
61
|
-
expect(last_response.headers['
|
61
|
+
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')
|
62
62
|
end
|
63
63
|
end
|
64
64
|
end
|
data/spec/flipper/ui_spec.rb
CHANGED
@@ -42,7 +42,7 @@ RSpec.describe Flipper::UI do
|
|
42
42
|
{ 'value' => 'User;6', 'operation' => 'enable', 'authenticity_token' => token },
|
43
43
|
'rack.session' => session
|
44
44
|
expect(last_response.status).to be(302)
|
45
|
-
expect(last_response.headers['
|
45
|
+
expect(last_response.headers['location']).to eq('/features/refactor-images')
|
46
46
|
end
|
47
47
|
|
48
48
|
describe 'configure' 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: 1.
|
4
|
+
version: 1.2.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:
|
11
|
+
date: 2024-01-11 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: 1.
|
59
|
+
version: 1.2.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: 1.
|
66
|
+
version: 1.2.0
|
67
67
|
- !ruby/object:Gem::Dependency
|
68
68
|
name: erubi
|
69
69
|
requirement: !ruby/object:Gem::Requirement
|
@@ -139,6 +139,7 @@ files:
|
|
139
139
|
- lib/flipper/ui/public/js/bootstrap-4.6.0.min.js
|
140
140
|
- lib/flipper/ui/public/js/jquery-3.6.0.slim.js
|
141
141
|
- lib/flipper/ui/public/js/popper-1.12.9.min.js
|
142
|
+
- lib/flipper/ui/public/js/version.js
|
142
143
|
- lib/flipper/ui/util.rb
|
143
144
|
- lib/flipper/ui/views/add_actor.erb
|
144
145
|
- lib/flipper/ui/views/add_feature.erb
|
@@ -178,7 +179,7 @@ metadata:
|
|
178
179
|
homepage_uri: https://www.flippercloud.io
|
179
180
|
source_code_uri: https://github.com/flippercloud/flipper
|
180
181
|
bug_tracker_uri: https://github.com/flippercloud/flipper/issues
|
181
|
-
changelog_uri: https://github.com/flippercloud/flipper/
|
182
|
+
changelog_uri: https://github.com/flippercloud/flipper/releases/tag/v1.2.0
|
182
183
|
post_install_message:
|
183
184
|
rdoc_options: []
|
184
185
|
require_paths:
|
@@ -194,7 +195,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
194
195
|
- !ruby/object:Gem::Version
|
195
196
|
version: '0'
|
196
197
|
requirements: []
|
197
|
-
rubygems_version: 3.
|
198
|
+
rubygems_version: 3.5.3
|
198
199
|
signing_key:
|
199
200
|
specification_version: 4
|
200
201
|
summary: Feature flag UI for the Flipper gem
|