flipper-ui 1.2.1 → 1.4.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/basic.ru +4 -0
- data/flipper-ui.gemspec +3 -2
- data/lib/flipper/ui/action.rb +30 -46
- data/lib/flipper/ui/actions/actors_gate.rb +2 -8
- data/lib/flipper/ui/actions/add_feature.rb +0 -9
- data/lib/flipper/ui/actions/boolean_gate.rb +1 -1
- data/lib/flipper/ui/actions/cloud_migrate.rb +26 -0
- data/lib/flipper/ui/actions/feature.rb +0 -7
- data/lib/flipper/ui/actions/features.rb +2 -9
- data/lib/flipper/ui/actions/groups_gate.rb +2 -7
- data/lib/flipper/ui/actions/percentage_of_actors_gate.rb +2 -2
- data/lib/flipper/ui/actions/percentage_of_time_gate.rb +2 -2
- data/lib/flipper/ui/actions/settings.rb +0 -3
- data/lib/flipper/ui/configuration.rb +18 -4
- data/lib/flipper/ui/middleware.rb +1 -0
- data/lib/flipper/ui/public/css/bootstrap.min.css +6 -0
- data/lib/flipper/ui/public/js/application.js +17 -33
- data/lib/flipper/ui/public/js/bootstrap.min.js +7 -0
- data/lib/flipper/ui/public/js/popper.min.js +6 -0
- data/lib/flipper/ui/sources.json +5 -0
- data/lib/flipper/ui/util.rb +10 -0
- data/lib/flipper/ui/views/add_actor.erb +8 -4
- data/lib/flipper/ui/views/add_feature.erb +3 -3
- data/lib/flipper/ui/views/add_group.erb +14 -9
- data/lib/flipper/ui/views/feature.erb +93 -80
- data/lib/flipper/ui/views/features.erb +29 -29
- data/lib/flipper/ui/views/layout.erb +28 -20
- data/lib/flipper/ui/views/settings.erb +31 -4
- data/lib/flipper/ui.rb +16 -2
- data/lib/flipper/version.rb +1 -1
- data/spec/flipper/ui/actions/actors_gate_spec.rb +6 -6
- data/spec/flipper/ui/actions/add_feature_spec.rb +1 -1
- data/spec/flipper/ui/actions/boolean_gate_spec.rb +1 -1
- data/spec/flipper/ui/actions/cloud_migrate_spec.rb +54 -0
- data/spec/flipper/ui/actions/feature_spec.rb +28 -0
- data/spec/flipper/ui/actions/features_spec.rb +60 -3
- data/spec/flipper/ui/actions/groups_gate_spec.rb +6 -6
- 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/actions/settings_spec.rb +8 -0
- data/spec/flipper/ui/configuration_spec.rb +9 -4
- data/spec/flipper/ui_spec.rb +19 -31
- metadata +40 -35
- data/lib/flipper/ui/public/css/bootstrap-4.6.0.min.css +0 -7
- data/lib/flipper/ui/public/js/bootstrap-4.6.0.min.js +0 -7
- data/lib/flipper/ui/public/js/popper-1.12.9.min.js +0 -5
|
@@ -20,7 +20,7 @@ RSpec.describe Flipper::UI::Actions::ActorsGate do
|
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
it 'renders add new actor form' do
|
|
23
|
-
form = '<form action="/features/search/actors" method="post" class="
|
|
23
|
+
form = '<form action="/features/search/actors" method="post" class="row">'
|
|
24
24
|
expect(last_response.body).to include(form)
|
|
25
25
|
end
|
|
26
26
|
end
|
|
@@ -35,7 +35,7 @@ RSpec.describe Flipper::UI::Actions::ActorsGate do
|
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
it 'renders add new actor form' do
|
|
38
|
-
form = '<form action="/features/a/
|
|
38
|
+
form = '<form action="/features/a%2Fb/actors" method="post" class="row">'
|
|
39
39
|
expect(last_response.body).to include(form)
|
|
40
40
|
end
|
|
41
41
|
end
|
|
@@ -73,7 +73,7 @@ RSpec.describe Flipper::UI::Actions::ActorsGate do
|
|
|
73
73
|
|
|
74
74
|
context "when feature name contains space" do
|
|
75
75
|
before do
|
|
76
|
-
post 'features/sp
|
|
76
|
+
post 'features/sp+ace/actors',
|
|
77
77
|
{ 'value' => value, 'operation' => 'enable', 'authenticity_token' => token },
|
|
78
78
|
'rack.session' => session
|
|
79
79
|
end
|
|
@@ -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['location']).to eq('/features/sp
|
|
87
|
+
expect(last_response.headers['location']).to eq('/features/sp+ace')
|
|
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['location']).to eq('/features/search/actors?error=%22%22
|
|
117
|
+
expect(last_response.headers['location']).to eq('/features/search/actors?error=%22%22+is+not+a+valid+actor+value.')
|
|
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['location']).to eq('/features/search/actors?error=%22%22
|
|
126
|
+
expect(last_response.headers['location']).to eq('/features/search/actors?error=%22%22+is+not+a+valid+actor+value.')
|
|
127
127
|
end
|
|
128
128
|
end
|
|
129
129
|
end
|
|
@@ -15,7 +15,7 @@ RSpec.describe Flipper::UI::Actions::AddFeature do
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
it 'renders template' do
|
|
18
|
-
form = '<form action="/features" method="post" class="
|
|
18
|
+
form = '<form action="/features" method="post" class="row g-3 mb-2">'
|
|
19
19
|
expect(last_response.body).to include(form)
|
|
20
20
|
end
|
|
21
21
|
end
|
|
@@ -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['location']).to eq('/features/sp
|
|
46
|
+
expect(last_response.headers['location']).to eq('/features/sp+ace')
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require 'flipper/cloud/migrate'
|
|
2
|
+
|
|
3
|
+
RSpec.describe Flipper::UI::Actions::CloudMigrate do
|
|
4
|
+
let(:token) do
|
|
5
|
+
if Rack::Protection::AuthenticityToken.respond_to?(:random_token)
|
|
6
|
+
Rack::Protection::AuthenticityToken.random_token
|
|
7
|
+
else
|
|
8
|
+
'a'
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
let(:session) do
|
|
13
|
+
{ :csrf => token, 'csrf' => token, '_csrf_token' => token }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
describe "POST /settings/cloud" do
|
|
17
|
+
context "when migration succeeds" do
|
|
18
|
+
before do
|
|
19
|
+
flipper.enable :search
|
|
20
|
+
allow(Flipper::Cloud).to receive(:migrate).and_return(
|
|
21
|
+
Flipper::Cloud::MigrateResult.new(code: 200, url: "https://www.flippercloud.io/cloud/setup/abc123")
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
post '/settings/cloud',
|
|
25
|
+
{'authenticity_token' => token},
|
|
26
|
+
'rack.session' => session
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'redirects to the cloud URL' do
|
|
30
|
+
expect(last_response.status).to be(302)
|
|
31
|
+
expect(last_response.headers['location']).to eq('https://www.flippercloud.io/cloud/setup/abc123')
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
context "when migration fails" do
|
|
36
|
+
before do
|
|
37
|
+
flipper.enable :search
|
|
38
|
+
allow(Flipper::Cloud).to receive(:migrate).and_return(
|
|
39
|
+
Flipper::Cloud::MigrateResult.new(code: 500, url: nil)
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
post '/settings/cloud',
|
|
43
|
+
{'authenticity_token' => token},
|
|
44
|
+
'rack.session' => session
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it 'redirects back to settings with error' do
|
|
48
|
+
expect(last_response.status).to be(302)
|
|
49
|
+
expect(last_response.headers['location']).to include('/settings')
|
|
50
|
+
expect(last_response.headers['location']).to include('error=')
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -197,4 +197,32 @@ RSpec.describe Flipper::UI::Actions::Feature do
|
|
|
197
197
|
expect(last_response.body).to include('a/b')
|
|
198
198
|
end
|
|
199
199
|
end
|
|
200
|
+
|
|
201
|
+
describe 'GET /features/:feature with dot dot slash repeated in feature name' do
|
|
202
|
+
before do
|
|
203
|
+
get '/features/..%2F..%2F..%2F..%2Fblah'
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
it 'responds with success' do
|
|
207
|
+
expect(last_response.status).to be(200)
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
it 'renders template' do
|
|
211
|
+
expect(last_response.body).to include('../../../../blah')
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
describe 'GET /features/:feature with question mark in feature name' do
|
|
216
|
+
before do
|
|
217
|
+
get '/features/can_do_stuff%3F'
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
it 'responds with success' do
|
|
221
|
+
expect(last_response.status).to be(200)
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
it 'renders template with question mark in feature name' do
|
|
225
|
+
expect(last_response.body).to include('can_do_stuff?')
|
|
226
|
+
end
|
|
227
|
+
end
|
|
200
228
|
end
|
|
@@ -28,6 +28,18 @@ RSpec.describe Flipper::UI::Actions::Features do
|
|
|
28
28
|
end
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
+
it "escapes keys that are junky" do
|
|
32
|
+
flipper.add("../../../../blah")
|
|
33
|
+
flipper.add("this that")
|
|
34
|
+
flipper.add("foo/bar")
|
|
35
|
+
flipper.add("can_do_stuff?")
|
|
36
|
+
get '/features'
|
|
37
|
+
expect(last_response.body).to include("..%2F..%2F..%2F..%2Fblah")
|
|
38
|
+
expect(last_response.body).to include("this+that")
|
|
39
|
+
expect(last_response.body).to include("foo%2Fbar")
|
|
40
|
+
expect(last_response.body).to include("can_do_stuff%3F")
|
|
41
|
+
end
|
|
42
|
+
|
|
31
43
|
context "when there are no features to list" do
|
|
32
44
|
before do
|
|
33
45
|
@original_fun_enabled = Flipper::UI.configuration.fun
|
|
@@ -78,6 +90,25 @@ RSpec.describe Flipper::UI::Actions::Features do
|
|
|
78
90
|
expect(last_response.body).not_to include('<a class="btn btn-primary btn-sm" href="/features/new">Add Feature</a>')
|
|
79
91
|
end
|
|
80
92
|
end
|
|
93
|
+
|
|
94
|
+
context 'when descriptions have links' do
|
|
95
|
+
before do
|
|
96
|
+
Flipper::UI.configuration.show_feature_description_in_list = true
|
|
97
|
+
Flipper::UI.configuration.descriptions_source = lambda { |_keys|
|
|
98
|
+
{ 'test_feature' => 'Check <a href="https://example.com">this link</a> for more info' }
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
flipper[:test_feature].enable
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it 'strips anchor tags from descriptions to avoid nested links' do
|
|
105
|
+
get '/features'
|
|
106
|
+
|
|
107
|
+
expect(last_response.status).to eq(200)
|
|
108
|
+
expect(last_response.body).to include('Check this link for more info')
|
|
109
|
+
expect(last_response.body).not_to include('<a href="https://example.com">this link</a>')
|
|
110
|
+
end
|
|
111
|
+
end
|
|
81
112
|
end
|
|
82
113
|
|
|
83
114
|
describe 'POST /features' do
|
|
@@ -124,7 +155,33 @@ RSpec.describe Flipper::UI::Actions::Features do
|
|
|
124
155
|
|
|
125
156
|
it 'redirects to feature' do
|
|
126
157
|
expect(last_response.status).to be(302)
|
|
127
|
-
expect(last_response.headers['location']).to eq('/features/notifications
|
|
158
|
+
expect(last_response.headers['location']).to eq('/features/notifications+next')
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
context 'feature name contains ../' do
|
|
163
|
+
let(:feature_name) { '../../../foo' }
|
|
164
|
+
|
|
165
|
+
it 'adds feature with space' do
|
|
166
|
+
expect(flipper.features.map(&:key)).to include(feature_name)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
it 'redirects to feature' do
|
|
170
|
+
expect(last_response.status).to be(302)
|
|
171
|
+
expect(last_response.headers['location']).to eq('/features/..%2F..%2F..%2Ffoo')
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
context 'feature name contains question mark' do
|
|
176
|
+
let(:feature_name) { 'can_do_stuff?' }
|
|
177
|
+
|
|
178
|
+
it 'adds feature with question mark' do
|
|
179
|
+
expect(flipper.features.map(&:key)).to include('can_do_stuff?')
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
it 'redirects to feature with encoded question mark' do
|
|
183
|
+
expect(last_response.status).to be(302)
|
|
184
|
+
expect(last_response.headers['location']).to eq('/features/can_do_stuff%3F')
|
|
128
185
|
end
|
|
129
186
|
end
|
|
130
187
|
|
|
@@ -138,7 +195,7 @@ RSpec.describe Flipper::UI::Actions::Features do
|
|
|
138
195
|
|
|
139
196
|
it 'redirects back to feature' do
|
|
140
197
|
expect(last_response.status).to be(302)
|
|
141
|
-
expect(last_response.headers['location']).to eq('/features/new?error=%22%22
|
|
198
|
+
expect(last_response.headers['location']).to eq('/features/new?error=%22%22+is+not+a+valid+feature+name.')
|
|
142
199
|
end
|
|
143
200
|
end
|
|
144
201
|
|
|
@@ -151,7 +208,7 @@ RSpec.describe Flipper::UI::Actions::Features do
|
|
|
151
208
|
|
|
152
209
|
it 'redirects back to feature' do
|
|
153
210
|
expect(last_response.status).to be(302)
|
|
154
|
-
expect(last_response.headers['location']).to eq('/features/new?error=%22%22
|
|
211
|
+
expect(last_response.headers['location']).to eq('/features/new?error=%22%22+is+not+a+valid+feature+name.')
|
|
155
212
|
end
|
|
156
213
|
end
|
|
157
214
|
end
|
|
@@ -26,7 +26,7 @@ RSpec.describe Flipper::UI::Actions::GroupsGate do
|
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
it 'renders add new group form' do
|
|
29
|
-
form = '<form action="/features/search/groups" method="post" class="
|
|
29
|
+
form = '<form action="/features/search/groups" method="post" class="row">'
|
|
30
30
|
expect(last_response.body).to include(form)
|
|
31
31
|
end
|
|
32
32
|
end
|
|
@@ -60,7 +60,7 @@ RSpec.describe Flipper::UI::Actions::GroupsGate do
|
|
|
60
60
|
|
|
61
61
|
context 'feature name contains space' do
|
|
62
62
|
before do
|
|
63
|
-
post 'features/sp
|
|
63
|
+
post 'features/sp+ace/groups',
|
|
64
64
|
{ 'value' => group_name, 'operation' => 'enable', 'authenticity_token' => token },
|
|
65
65
|
'rack.session' => session
|
|
66
66
|
end
|
|
@@ -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['location']).to eq('/features/sp
|
|
74
|
+
expect(last_response.headers['location']).to eq('/features/sp+ace')
|
|
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['location']).to eq('/features/search/groups?error=The
|
|
92
|
+
expect(last_response.headers['location']).to eq('/features/search/groups?error=The+group+named+%22not_here%22+has+not+been+registered.')
|
|
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['location']).to eq('/features/search/groups?error=The
|
|
101
|
+
expect(last_response.headers['location']).to eq('/features/search/groups?error=The+group+named+%22%22+has+not+been+registered.')
|
|
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['location']).to eq('/features/search/groups?error=The
|
|
110
|
+
expect(last_response.headers['location']).to eq('/features/search/groups?error=The+group+named+%22%22+has+not+been+registered.')
|
|
111
111
|
end
|
|
112
112
|
end
|
|
113
113
|
end
|
|
@@ -30,7 +30,7 @@ RSpec.describe Flipper::UI::Actions::PercentageOfActorsGate do
|
|
|
30
30
|
|
|
31
31
|
context 'with space in feature name' do
|
|
32
32
|
before do
|
|
33
|
-
post 'features/sp
|
|
33
|
+
post 'features/sp+ace/percentage_of_actors',
|
|
34
34
|
{ 'value' => '24', 'authenticity_token' => token },
|
|
35
35
|
'rack.session' => session
|
|
36
36
|
end
|
|
@@ -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['location']).to eq('/features/sp
|
|
44
|
+
expect(last_response.headers['location']).to eq('/features/sp+ace')
|
|
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['location']).to eq('/features/search?error=Invalid%
|
|
61
|
+
expect(last_response.headers['location']).to eq('/features/search?error=Invalid+percentage+of+actors+value%3A+value+must+be+a+positive+number+less+than+or+equal+to+100%2C+but+was+555')
|
|
62
62
|
end
|
|
63
63
|
end
|
|
64
64
|
end
|
|
@@ -30,7 +30,7 @@ RSpec.describe Flipper::UI::Actions::PercentageOfTimeGate do
|
|
|
30
30
|
|
|
31
31
|
context 'with space in feature name' do
|
|
32
32
|
before do
|
|
33
|
-
post 'features/sp
|
|
33
|
+
post 'features/sp+ace/percentage_of_time',
|
|
34
34
|
{ 'value' => '24', 'authenticity_token' => token },
|
|
35
35
|
'rack.session' => session
|
|
36
36
|
end
|
|
@@ -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['location']).to eq('/features/sp
|
|
44
|
+
expect(last_response.headers['location']).to eq('/features/sp+ace')
|
|
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['location']).to eq('/features/search?error=Invalid%
|
|
61
|
+
expect(last_response.headers['location']).to eq('/features/search?error=Invalid+percentage+of+time+value%3A+value+must+be+a+positive+number+less+than+or+equal+to+100%2C+but+was+555')
|
|
62
62
|
end
|
|
63
63
|
end
|
|
64
64
|
end
|
|
@@ -23,5 +23,13 @@ RSpec.describe Flipper::UI::Actions::Settings do
|
|
|
23
23
|
it 'renders template' do
|
|
24
24
|
expect(last_response.body).to include('Download')
|
|
25
25
|
end
|
|
26
|
+
|
|
27
|
+
it 'includes migrate to Flipper Cloud card' do
|
|
28
|
+
expect(last_response.body).to include('Migrate to Flipper Cloud')
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'shows feature count' do
|
|
32
|
+
expect(last_response.body).to include('features ready to migrate')
|
|
33
|
+
end
|
|
26
34
|
end
|
|
27
35
|
end
|
|
@@ -35,14 +35,19 @@ RSpec.describe Flipper::UI::Configuration do
|
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
-
describe "#
|
|
38
|
+
describe "#application_href" do
|
|
39
39
|
it "has default value" do
|
|
40
|
-
expect(configuration.
|
|
40
|
+
expect(configuration.application_href).to eq(nil)
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
it "can be updated" do
|
|
44
|
-
configuration.
|
|
45
|
-
expect(configuration.
|
|
44
|
+
configuration.application_href = 'http://www.myapp.com'
|
|
45
|
+
expect(configuration.application_href).to eq('http://www.myapp.com')
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'aliases application_breadcrumb_href to application_href' do
|
|
49
|
+
configuration.application_breadcrumb_href = "/myapp"
|
|
50
|
+
expect(configuration.application_href).to eq("/myapp")
|
|
46
51
|
end
|
|
47
52
|
end
|
|
48
53
|
|
data/spec/flipper/ui_spec.rb
CHANGED
|
@@ -76,56 +76,44 @@ RSpec.describe Flipper::UI do
|
|
|
76
76
|
end
|
|
77
77
|
end
|
|
78
78
|
|
|
79
|
-
describe "
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
describe "application_href" do
|
|
80
|
+
around do |example|
|
|
81
|
+
original_href = configuration.application_href
|
|
82
|
+
example.run
|
|
83
|
+
ensure
|
|
84
|
+
configuration.application_href = original_href
|
|
82
85
|
end
|
|
83
86
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
configuration.application_breadcrumb_href = nil
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
after do
|
|
91
|
-
configuration.application_breadcrumb_href = @original_application_breadcrumb_href
|
|
92
|
-
end
|
|
87
|
+
it 'does not have an application_href by default' do
|
|
88
|
+
expect(configuration.application_href).to be(nil)
|
|
89
|
+
end
|
|
93
90
|
|
|
94
|
-
|
|
91
|
+
context 'with application_href not set' do
|
|
92
|
+
it 'does not add App link' do
|
|
95
93
|
get '/features'
|
|
96
94
|
expect(last_response.body).not_to include('<a href="/myapp">App</a>')
|
|
97
95
|
end
|
|
98
96
|
end
|
|
99
97
|
|
|
100
|
-
context 'with
|
|
98
|
+
context 'with application_href set' do
|
|
101
99
|
before do
|
|
102
|
-
|
|
103
|
-
configuration.application_breadcrumb_href = '/myapp'
|
|
100
|
+
configuration.application_href = '/myapp'
|
|
104
101
|
end
|
|
105
102
|
|
|
106
|
-
|
|
107
|
-
configuration.application_breadcrumb_href = @original_application_breadcrumb_href
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
it 'does add App breadcrumb' do
|
|
103
|
+
it 'does add App link' do
|
|
111
104
|
get '/features'
|
|
112
|
-
expect(last_response.body).to
|
|
105
|
+
expect(last_response.body).to match('<a.*href="/myapp"')
|
|
113
106
|
end
|
|
114
107
|
end
|
|
115
108
|
|
|
116
|
-
context 'with
|
|
109
|
+
context 'with application_href set to full url' do
|
|
117
110
|
before do
|
|
118
|
-
|
|
119
|
-
configuration.application_breadcrumb_href = 'https://myapp.com/'
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
after do
|
|
123
|
-
configuration.application_breadcrumb_href = @original_application_breadcrumb_href
|
|
111
|
+
configuration.application_href = "https://myapp.com/"
|
|
124
112
|
end
|
|
125
113
|
|
|
126
|
-
it 'does add App
|
|
114
|
+
it 'does add App link' do
|
|
127
115
|
get '/features'
|
|
128
|
-
expect(last_response.body).to
|
|
116
|
+
expect(last_response.body).to match('<a.*href="https://myapp.com/"')
|
|
129
117
|
end
|
|
130
118
|
end
|
|
131
119
|
end
|
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.4.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: 2026-02-26 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rack
|
|
@@ -37,9 +37,9 @@ dependencies:
|
|
|
37
37
|
- - ">="
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
39
|
version: 1.5.3
|
|
40
|
-
- - "
|
|
40
|
+
- - "<"
|
|
41
41
|
- !ruby/object:Gem::Version
|
|
42
|
-
version:
|
|
42
|
+
version: 5.0.0
|
|
43
43
|
type: :runtime
|
|
44
44
|
prerelease: false
|
|
45
45
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -47,23 +47,43 @@ dependencies:
|
|
|
47
47
|
- - ">="
|
|
48
48
|
- !ruby/object:Gem::Version
|
|
49
49
|
version: 1.5.3
|
|
50
|
-
- - "
|
|
50
|
+
- - "<"
|
|
51
|
+
- !ruby/object:Gem::Version
|
|
52
|
+
version: 5.0.0
|
|
53
|
+
- !ruby/object:Gem::Dependency
|
|
54
|
+
name: rack-session
|
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
|
56
|
+
requirements:
|
|
57
|
+
- - ">="
|
|
58
|
+
- !ruby/object:Gem::Version
|
|
59
|
+
version: 1.0.2
|
|
60
|
+
- - "<"
|
|
51
61
|
- !ruby/object:Gem::Version
|
|
52
|
-
version:
|
|
62
|
+
version: 3.0.0
|
|
63
|
+
type: :runtime
|
|
64
|
+
prerelease: false
|
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
66
|
+
requirements:
|
|
67
|
+
- - ">="
|
|
68
|
+
- !ruby/object:Gem::Version
|
|
69
|
+
version: 1.0.2
|
|
70
|
+
- - "<"
|
|
71
|
+
- !ruby/object:Gem::Version
|
|
72
|
+
version: 3.0.0
|
|
53
73
|
- !ruby/object:Gem::Dependency
|
|
54
74
|
name: flipper
|
|
55
75
|
requirement: !ruby/object:Gem::Requirement
|
|
56
76
|
requirements:
|
|
57
77
|
- - "~>"
|
|
58
78
|
- !ruby/object:Gem::Version
|
|
59
|
-
version: 1.
|
|
79
|
+
version: 1.4.0
|
|
60
80
|
type: :runtime
|
|
61
81
|
prerelease: false
|
|
62
82
|
version_requirements: !ruby/object:Gem::Requirement
|
|
63
83
|
requirements:
|
|
64
84
|
- - "~>"
|
|
65
85
|
- !ruby/object:Gem::Version
|
|
66
|
-
version: 1.
|
|
86
|
+
version: 1.4.0
|
|
67
87
|
- !ruby/object:Gem::Dependency
|
|
68
88
|
name: erubi
|
|
69
89
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -90,14 +110,14 @@ dependencies:
|
|
|
90
110
|
requirements:
|
|
91
111
|
- - "<"
|
|
92
112
|
- !ruby/object:Gem::Version
|
|
93
|
-
version: '
|
|
113
|
+
version: '8'
|
|
94
114
|
type: :runtime
|
|
95
115
|
prerelease: false
|
|
96
116
|
version_requirements: !ruby/object:Gem::Requirement
|
|
97
117
|
requirements:
|
|
98
118
|
- - "<"
|
|
99
119
|
- !ruby/object:Gem::Version
|
|
100
|
-
version: '
|
|
120
|
+
version: '8'
|
|
101
121
|
description:
|
|
102
122
|
email: support@flippercloud.io
|
|
103
123
|
executables: []
|
|
@@ -116,6 +136,7 @@ files:
|
|
|
116
136
|
- lib/flipper/ui/actions/actors_gate.rb
|
|
117
137
|
- lib/flipper/ui/actions/add_feature.rb
|
|
118
138
|
- lib/flipper/ui/actions/boolean_gate.rb
|
|
139
|
+
- lib/flipper/ui/actions/cloud_migrate.rb
|
|
119
140
|
- lib/flipper/ui/actions/export.rb
|
|
120
141
|
- lib/flipper/ui/actions/feature.rb
|
|
121
142
|
- lib/flipper/ui/actions/features.rb
|
|
@@ -133,13 +154,14 @@ files:
|
|
|
133
154
|
- lib/flipper/ui/error.rb
|
|
134
155
|
- lib/flipper/ui/middleware.rb
|
|
135
156
|
- lib/flipper/ui/public/css/application.css
|
|
136
|
-
- lib/flipper/ui/public/css/bootstrap
|
|
157
|
+
- lib/flipper/ui/public/css/bootstrap.min.css
|
|
137
158
|
- lib/flipper/ui/public/images/logo.png
|
|
138
159
|
- lib/flipper/ui/public/js/application.js
|
|
139
|
-
- lib/flipper/ui/public/js/bootstrap
|
|
160
|
+
- lib/flipper/ui/public/js/bootstrap.min.js
|
|
140
161
|
- lib/flipper/ui/public/js/jquery-3.6.0.slim.js
|
|
141
|
-
- lib/flipper/ui/public/js/popper
|
|
162
|
+
- lib/flipper/ui/public/js/popper.min.js
|
|
142
163
|
- lib/flipper/ui/public/js/version.js
|
|
164
|
+
- lib/flipper/ui/sources.json
|
|
143
165
|
- lib/flipper/ui/util.rb
|
|
144
166
|
- lib/flipper/ui/views/add_actor.erb
|
|
145
167
|
- lib/flipper/ui/views/add_feature.erb
|
|
@@ -156,6 +178,7 @@ files:
|
|
|
156
178
|
- spec/flipper/ui/actions/actors_gate_spec.rb
|
|
157
179
|
- spec/flipper/ui/actions/add_feature_spec.rb
|
|
158
180
|
- spec/flipper/ui/actions/boolean_gate_spec.rb
|
|
181
|
+
- spec/flipper/ui/actions/cloud_migrate_spec.rb
|
|
159
182
|
- spec/flipper/ui/actions/export_spec.rb
|
|
160
183
|
- spec/flipper/ui/actions/feature_spec.rb
|
|
161
184
|
- spec/flipper/ui/actions/features_spec.rb
|
|
@@ -179,7 +202,8 @@ metadata:
|
|
|
179
202
|
homepage_uri: https://www.flippercloud.io
|
|
180
203
|
source_code_uri: https://github.com/flippercloud/flipper
|
|
181
204
|
bug_tracker_uri: https://github.com/flippercloud/flipper/issues
|
|
182
|
-
changelog_uri: https://github.com/flippercloud/flipper/releases/tag/v1.
|
|
205
|
+
changelog_uri: https://github.com/flippercloud/flipper/releases/tag/v1.4.0
|
|
206
|
+
funding_uri: https://github.com/sponsors/flippercloud
|
|
183
207
|
post_install_message:
|
|
184
208
|
rdoc_options: []
|
|
185
209
|
require_paths:
|
|
@@ -195,27 +219,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
195
219
|
- !ruby/object:Gem::Version
|
|
196
220
|
version: '0'
|
|
197
221
|
requirements: []
|
|
198
|
-
rubygems_version: 3.5.
|
|
222
|
+
rubygems_version: 3.5.22
|
|
199
223
|
signing_key:
|
|
200
224
|
specification_version: 4
|
|
201
225
|
summary: Feature flag UI for the Flipper gem
|
|
202
|
-
test_files:
|
|
203
|
-
- spec/flipper/ui/action_spec.rb
|
|
204
|
-
- spec/flipper/ui/actions/actors_gate_spec.rb
|
|
205
|
-
- spec/flipper/ui/actions/add_feature_spec.rb
|
|
206
|
-
- spec/flipper/ui/actions/boolean_gate_spec.rb
|
|
207
|
-
- spec/flipper/ui/actions/export_spec.rb
|
|
208
|
-
- spec/flipper/ui/actions/feature_spec.rb
|
|
209
|
-
- spec/flipper/ui/actions/features_spec.rb
|
|
210
|
-
- spec/flipper/ui/actions/file_spec.rb
|
|
211
|
-
- spec/flipper/ui/actions/groups_gate_spec.rb
|
|
212
|
-
- spec/flipper/ui/actions/home_spec.rb
|
|
213
|
-
- spec/flipper/ui/actions/import_spec.rb
|
|
214
|
-
- spec/flipper/ui/actions/percentage_of_actors_gate_spec.rb
|
|
215
|
-
- spec/flipper/ui/actions/percentage_of_time_gate_spec.rb
|
|
216
|
-
- spec/flipper/ui/actions/settings_spec.rb
|
|
217
|
-
- spec/flipper/ui/configuration_spec.rb
|
|
218
|
-
- spec/flipper/ui/decorators/feature_spec.rb
|
|
219
|
-
- spec/flipper/ui/decorators/gate_spec.rb
|
|
220
|
-
- spec/flipper/ui/util_spec.rb
|
|
221
|
-
- spec/flipper/ui_spec.rb
|
|
226
|
+
test_files: []
|