flipper-ui 0.10.2 → 0.11.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/flipper-ui.gemspec +12 -12
  3. data/lib/flipper/ui.rb +6 -4
  4. data/lib/flipper/ui/action.rb +22 -21
  5. data/lib/flipper/ui/action_collection.rb +2 -2
  6. data/lib/flipper/ui/actions/actors_gate.rb +7 -7
  7. data/lib/flipper/ui/actions/add_feature.rb +6 -6
  8. data/lib/flipper/ui/actions/boolean_gate.rb +2 -2
  9. data/lib/flipper/ui/actions/feature.rb +5 -6
  10. data/lib/flipper/ui/actions/features.rb +9 -10
  11. data/lib/flipper/ui/actions/file.rb +0 -1
  12. data/lib/flipper/ui/actions/gate.rb +5 -2
  13. data/lib/flipper/ui/actions/groups_gate.rb +16 -14
  14. data/lib/flipper/ui/actions/home.rb +1 -2
  15. data/lib/flipper/ui/actions/percentage_of_actors_gate.rb +2 -2
  16. data/lib/flipper/ui/actions/percentage_of_time_gate.rb +2 -2
  17. data/lib/flipper/ui/decorators/feature.rb +9 -9
  18. data/lib/flipper/ui/decorators/gate.rb +7 -6
  19. data/lib/flipper/ui/middleware.rb +2 -27
  20. data/lib/flipper/ui/util.rb +2 -2
  21. data/lib/flipper/version.rb +1 -1
  22. data/spec/flipper/ui/action_spec.rb +22 -22
  23. data/spec/flipper/ui/actions/actors_gate_spec.rb +49 -45
  24. data/spec/flipper/ui/actions/add_feature_spec.rb +9 -9
  25. data/spec/flipper/ui/actions/boolean_gate_spec.rb +22 -22
  26. data/spec/flipper/ui/actions/feature_spec.rb +34 -34
  27. data/spec/flipper/ui/actions/features_spec.rb +44 -40
  28. data/spec/flipper/ui/actions/file_spec.rb +8 -8
  29. data/spec/flipper/ui/actions/gate_spec.rb +17 -15
  30. data/spec/flipper/ui/actions/groups_gate_spec.rb +57 -50
  31. data/spec/flipper/ui/actions/home_spec.rb +4 -4
  32. data/spec/flipper/ui/actions/percentage_of_actors_gate_spec.rb +24 -22
  33. data/spec/flipper/ui/actions/percentage_of_time_gate_spec.rb +24 -22
  34. data/spec/flipper/ui/decorators/feature_spec.rb +27 -27
  35. data/spec/flipper/ui/decorators/gate_spec.rb +10 -10
  36. data/spec/flipper/ui/util_spec.rb +4 -4
  37. data/spec/flipper/ui_spec.rb +58 -59
  38. metadata +7 -7
@@ -1,74 +1,74 @@
1
1
  require 'helper'
2
2
 
3
3
  RSpec.describe Flipper::UI::Actions::Feature do
4
- let(:token) {
4
+ let(:token) do
5
5
  if Rack::Protection::AuthenticityToken.respond_to?(:random_token)
6
6
  Rack::Protection::AuthenticityToken.random_token
7
7
  else
8
- "a"
8
+ 'a'
9
9
  end
10
- }
11
- let(:session) {
10
+ end
11
+ let(:session) do
12
12
  if Rack::Protection::AuthenticityToken.respond_to?(:random_token)
13
- {:csrf => token}
13
+ { csrf: token }
14
14
  else
15
- {"_csrf_token" => token}
15
+ { '_csrf_token' => token }
16
16
  end
17
- }
17
+ end
18
18
 
19
- describe "DELETE /features/:feature" do
19
+ describe 'DELETE /features/:feature' do
20
20
  before do
21
21
  flipper.enable :search
22
- delete "/features/search",
23
- {"authenticity_token" => token},
24
- "rack.session" => session
22
+ delete '/features/search',
23
+ { 'authenticity_token' => token },
24
+ 'rack.session' => session
25
25
  end
26
26
 
27
- it "removes feature" do
28
- expect(flipper.features.map(&:key)).not_to include("search")
27
+ it 'removes feature' do
28
+ expect(flipper.features.map(&:key)).not_to include('search')
29
29
  end
30
30
 
31
- it "redirects to features" do
31
+ it 'redirects to features' do
32
32
  expect(last_response.status).to be(302)
33
- expect(last_response.headers["Location"]).to eq("/features")
33
+ expect(last_response.headers['Location']).to eq('/features')
34
34
  end
35
35
  end
36
36
 
37
- describe "POST /features/:feature with _method=DELETE" do
37
+ describe 'POST /features/:feature with _method=DELETE' do
38
38
  before do
39
39
  flipper.enable :search
40
- post "/features/search",
41
- {"_method" => "DELETE", "authenticity_token" => token},
42
- "rack.session" => session
40
+ post '/features/search',
41
+ { '_method' => 'DELETE', 'authenticity_token' => token },
42
+ 'rack.session' => session
43
43
  end
44
44
 
45
- it "removes feature" do
46
- expect(flipper.features.map(&:key)).not_to include("search")
45
+ it 'removes feature' do
46
+ expect(flipper.features.map(&:key)).not_to include('search')
47
47
  end
48
48
 
49
- it "redirects to features" do
49
+ it 'redirects to features' do
50
50
  expect(last_response.status).to be(302)
51
- expect(last_response.headers["Location"]).to eq("/features")
51
+ expect(last_response.headers['Location']).to eq('/features')
52
52
  end
53
53
  end
54
54
 
55
- describe "GET /features/:feature" do
55
+ describe 'GET /features/:feature' do
56
56
  before do
57
- get "/features/search"
57
+ get '/features/search'
58
58
  end
59
59
 
60
- it "responds with success" do
60
+ it 'responds with success' do
61
61
  expect(last_response.status).to be(200)
62
62
  end
63
63
 
64
- it "renders template" do
65
- expect(last_response.body).to include("search")
66
- expect(last_response.body).to include("Enable")
67
- expect(last_response.body).to include("Disable")
68
- expect(last_response.body).to include("Actors")
69
- expect(last_response.body).to include("Groups")
70
- expect(last_response.body).to include("Percentage of Time")
71
- expect(last_response.body).to include("Percentage of Actors")
64
+ it 'renders template' do
65
+ expect(last_response.body).to include('search')
66
+ expect(last_response.body).to include('Enable')
67
+ expect(last_response.body).to include('Disable')
68
+ expect(last_response.body).to include('Actors')
69
+ expect(last_response.body).to include('Groups')
70
+ expect(last_response.body).to include('Percentage of Time')
71
+ expect(last_response.body).to include('Percentage of Actors')
72
72
  end
73
73
  end
74
74
  end
@@ -1,47 +1,47 @@
1
1
  require 'helper'
2
2
 
3
3
  RSpec.describe Flipper::UI::Actions::Features do
4
- let(:token) {
4
+ let(:token) do
5
5
  if Rack::Protection::AuthenticityToken.respond_to?(:random_token)
6
6
  Rack::Protection::AuthenticityToken.random_token
7
7
  else
8
- "a"
8
+ 'a'
9
9
  end
10
- }
11
- let(:session) {
10
+ end
11
+ let(:session) do
12
12
  if Rack::Protection::AuthenticityToken.respond_to?(:random_token)
13
- {:csrf => token}
13
+ { csrf: token }
14
14
  else
15
- {"_csrf_token" => token}
15
+ { '_csrf_token' => token }
16
16
  end
17
- }
17
+ end
18
18
 
19
- describe "GET /features" do
19
+ describe 'GET /features' do
20
20
  before do
21
21
  flipper[:stats].enable
22
22
  flipper[:search].enable
23
- get "/features"
23
+ get '/features'
24
24
  end
25
25
 
26
- it "responds with success" do
26
+ it 'responds with success' do
27
27
  expect(last_response.status).to be(200)
28
28
  end
29
29
 
30
- it "renders template" do
31
- expect(last_response.body).to include("stats")
32
- expect(last_response.body).to include("search")
30
+ it 'renders template' do
31
+ expect(last_response.body).to include('stats')
32
+ expect(last_response.body).to include('search')
33
33
  end
34
34
  end
35
35
 
36
- describe "POST /features" do
37
- let(:feature_name) { "notifications_next" }
36
+ describe 'POST /features' do
37
+ let(:feature_name) { 'notifications_next' }
38
38
 
39
39
  before do
40
40
  @original_feature_creation_enabled = Flipper::UI.feature_creation_enabled
41
41
  Flipper::UI.feature_creation_enabled = feature_creation_enabled
42
- post "/features",
43
- {"value" => feature_name, "authenticity_token" => token},
44
- "rack.session" => session
42
+ post '/features',
43
+ { 'value' => feature_name, 'authenticity_token' => token },
44
+ 'rack.session' => session
45
45
  end
46
46
 
47
47
  after do
@@ -51,48 +51,52 @@ RSpec.describe Flipper::UI::Actions::Features do
51
51
  context 'feature_creation_enabled set to true' do
52
52
  let(:feature_creation_enabled) { true }
53
53
 
54
- it "adds feature" do
55
- expect(flipper.features.map(&:key)).to include("notifications_next")
54
+ it 'adds feature' do
55
+ expect(flipper.features.map(&:key)).to include('notifications_next')
56
56
  end
57
57
 
58
- it "redirects to feature" do
58
+ it 'redirects to feature' do
59
59
  expect(last_response.status).to be(302)
60
- expect(last_response.headers["Location"]).to eq("/features/notifications_next")
60
+ expect(last_response.headers['Location']).to eq('/features/notifications_next')
61
61
  end
62
62
 
63
63
  context 'feature name contains whitespace' do
64
- let(:feature_name) { " notifications_next " }
64
+ let(:feature_name) { ' notifications_next ' }
65
65
 
66
- it "adds feature without whitespace" do
67
- expect(flipper.features.map(&:key)).to include("notifications_next")
66
+ it 'adds feature without whitespace' do
67
+ expect(flipper.features.map(&:key)).to include('notifications_next')
68
68
  end
69
69
  end
70
70
 
71
- context "for an invalid feature name" do
72
- context "empty feature name" do
73
- let(:feature_name) { "" }
71
+ context 'for an invalid feature name' do
72
+ context 'empty feature name' do
73
+ let(:feature_name) { '' }
74
74
 
75
- it "does not add feature" do
75
+ it 'does not add feature' do
76
76
  expect(flipper.features.map(&:key)).to eq([])
77
77
  end
78
78
 
79
- it "redirects back to feature" do
79
+ # rubocop:disable Metrics/LineLength
80
+ it 'redirects back to feature' do
80
81
  expect(last_response.status).to be(302)
81
- expect(last_response.headers["Location"]).to eq("/features/new?error=%22%22+is+not+a+valid+feature+name.")
82
+ expect(last_response.headers['Location']).to eq('/features/new?error=%22%22+is+not+a+valid+feature+name.')
82
83
  end
84
+ # rubocop:enable Metrics/LineLength
83
85
  end
84
86
 
85
- context "nil feature name" do
87
+ context 'nil feature name' do
86
88
  let(:feature_name) { nil }
87
89
 
88
- it "does not add feature" do
90
+ it 'does not add feature' do
89
91
  expect(flipper.features.map(&:key)).to eq([])
90
92
  end
91
93
 
92
- it "redirects back to feature" do
94
+ # rubocop:disable Metrics/LineLength
95
+ it 'redirects back to feature' do
93
96
  expect(last_response.status).to be(302)
94
- expect(last_response.headers["Location"]).to eq("/features/new?error=%22%22+is+not+a+valid+feature+name.")
97
+ expect(last_response.headers['Location']).to eq('/features/new?error=%22%22+is+not+a+valid+feature+name.')
95
98
  end
99
+ # rubocop:enable Metrics/LineLength
96
100
  end
97
101
  end
98
102
  end
@@ -100,16 +104,16 @@ RSpec.describe Flipper::UI::Actions::Features do
100
104
  context 'feature_creation_enabled set to false' do
101
105
  let(:feature_creation_enabled) { false }
102
106
 
103
- it "does not add feature" do
104
- expect(flipper.features.map(&:key)).to_not include("notifications_next")
107
+ it 'does not add feature' do
108
+ expect(flipper.features.map(&:key)).not_to include('notifications_next')
105
109
  end
106
110
 
107
- it "returns 403" do
111
+ it 'returns 403' do
108
112
  expect(last_response.status).to be(403)
109
113
  end
110
114
 
111
- it "renders feature creation disabled template" do
112
- expect(last_response.body).to include("Feature creation is disabled.")
115
+ it 'renders feature creation disabled template' do
116
+ expect(last_response.body).to include('Feature creation is disabled.')
113
117
  end
114
118
  end
115
119
  end
@@ -1,42 +1,42 @@
1
1
  require 'helper'
2
2
 
3
3
  RSpec.describe Flipper::UI::Actions::File do
4
- describe "GET /images/logo.png" do
4
+ describe 'GET /images/logo.png' do
5
5
  before do
6
6
  get '/images/logo.png'
7
7
  end
8
8
 
9
- it "responds with 200" do
9
+ it 'responds with 200' do
10
10
  expect(last_response.status).to be(200)
11
11
  end
12
12
  end
13
13
 
14
- describe "GET /css/application.css" do
14
+ describe 'GET /css/application.css' do
15
15
  before do
16
16
  get '/css/application.css'
17
17
  end
18
18
 
19
- it "responds with 200" do
19
+ it 'responds with 200' do
20
20
  expect(last_response.status).to be(200)
21
21
  end
22
22
  end
23
23
 
24
- describe "GET /fonts/bootstrap/glyphicons-halflings-regular.eot" do
24
+ describe 'GET /fonts/bootstrap/glyphicons-halflings-regular.eot' do
25
25
  before do
26
26
  get '/fonts/bootstrap/glyphicons-halflings-regular.eot'
27
27
  end
28
28
 
29
- it "responds with 200" do
29
+ it 'responds with 200' do
30
30
  expect(last_response.status).to be(200)
31
31
  end
32
32
  end
33
33
 
34
- describe "GET /octicons/octicons.eot" do
34
+ describe 'GET /octicons/octicons.eot' do
35
35
  before do
36
36
  get '/octicons/octicons.eot'
37
37
  end
38
38
 
39
- it "responds with 200" do
39
+ it 'responds with 200' do
40
40
  expect(last_response.status).to be(200)
41
41
  end
42
42
  end
@@ -1,37 +1,39 @@
1
1
  require 'helper'
2
2
 
3
3
  RSpec.describe Flipper::UI::Actions::Gate do
4
- let(:token) {
4
+ let(:token) do
5
5
  if Rack::Protection::AuthenticityToken.respond_to?(:random_token)
6
6
  Rack::Protection::AuthenticityToken.random_token
7
7
  else
8
- "a"
8
+ 'a'
9
9
  end
10
- }
11
- let(:session) {
10
+ end
11
+ let(:session) do
12
12
  if Rack::Protection::AuthenticityToken.respond_to?(:random_token)
13
- {:csrf => token}
13
+ { csrf: token }
14
14
  else
15
- {"_csrf_token" => token}
15
+ { '_csrf_token' => token }
16
16
  end
17
- }
17
+ end
18
18
 
19
- describe "POST /features/:feature/non-existent-gate" do
19
+ describe 'POST /features/:feature/non-existent-gate' do
20
20
  before do
21
- post "/features/search/non-existent-gate",
22
- {"authenticity_token" => token},
23
- "rack.session" => session
21
+ post '/features/search/non-existent-gate',
22
+ { 'authenticity_token' => token },
23
+ 'rack.session' => session
24
24
  end
25
25
 
26
- it "responds with redirect" do
26
+ it 'responds with redirect' do
27
27
  expect(last_response.status).to be(302)
28
28
  end
29
29
 
30
- it "escapes error message" do
31
- expect(last_response.headers["Location"]).to eq("/features/search?error=%22non-existent-gate%22+gate+does+not+exist+therefore+it+cannot+be+updated.")
30
+ # rubocop:disable Metrics/LineLength
31
+ it 'escapes error message' do
32
+ expect(last_response.headers['Location']).to eq('/features/search?error=%22non-existent-gate%22+gate+does+not+exist+therefore+it+cannot+be+updated.')
32
33
  end
34
+ # rubocop:enable Metrics/LineLength
33
35
 
34
- it "renders error in template" do
36
+ it 'renders error in template' do
35
37
  follow_redirect!
36
38
  expect(last_response.body).to match(/non-existent-gate.*gate does not exist/)
37
39
  end
@@ -1,129 +1,136 @@
1
1
  require 'helper'
2
2
 
3
3
  RSpec.describe Flipper::UI::Actions::GroupsGate do
4
- let(:token) {
4
+ let(:token) do
5
5
  if Rack::Protection::AuthenticityToken.respond_to?(:random_token)
6
6
  Rack::Protection::AuthenticityToken.random_token
7
7
  else
8
- "a"
8
+ 'a'
9
9
  end
10
- }
11
- let(:session) {
10
+ end
11
+
12
+ let(:session) do
12
13
  if Rack::Protection::AuthenticityToken.respond_to?(:random_token)
13
- {:csrf => token}
14
+ { csrf: token }
14
15
  else
15
- {"_csrf_token" => token}
16
+ { '_csrf_token' => token }
16
17
  end
17
- }
18
+ end
18
19
 
19
- describe "GET /features/:feature/groups" do
20
+ describe 'GET /features/:feature/groups' do
20
21
  before do
21
- Flipper.register(:admins) { |user| user.admin? }
22
- get "features/search/groups"
22
+ Flipper.register(:admins, &:admin?)
23
+ get 'features/search/groups'
23
24
  end
24
25
 
25
26
  after do
26
27
  Flipper.unregister_groups
27
28
  end
28
29
 
29
- it "responds with success" do
30
+ it 'responds with success' do
30
31
  expect(last_response.status).to be(200)
31
32
  end
32
33
 
33
- it "renders add new group form" do
34
+ it 'renders add new group form' do
34
35
  expect(last_response.body).to include('<form action="/features/search/groups" method="post">')
35
36
  end
36
37
  end
37
38
 
38
- describe "POST /features/:feature/groups" do
39
- let(:group_name) { "admins" }
39
+ describe 'POST /features/:feature/groups' do
40
+ let(:group_name) { 'admins' }
40
41
 
41
42
  before do
42
- Flipper.register(:admins) { |user| user.admin? }
43
+ Flipper.register(:admins, &:admin?)
43
44
  end
44
45
 
45
46
  after do
46
47
  Flipper.unregister_groups
47
48
  end
48
49
 
49
- context "enabling a group" do
50
+ context 'enabling a group' do
50
51
  before do
51
- post "features/search/groups",
52
- {"value" => group_name, "operation" => "enable", "authenticity_token" => token},
53
- "rack.session" => session
52
+ post 'features/search/groups',
53
+ { 'value' => group_name, 'operation' => 'enable', 'authenticity_token' => token },
54
+ 'rack.session' => session
54
55
  end
55
56
 
56
- it "adds item to members" do
57
- expect(flipper[:search].groups_value).to include("admins")
57
+ it 'adds item to members' do
58
+ expect(flipper[:search].groups_value).to include('admins')
58
59
  end
59
60
 
60
- it "redirects back to feature" do
61
+ it 'redirects back to feature' do
61
62
  expect(last_response.status).to be(302)
62
- expect(last_response.headers["Location"]).to eq("/features/search")
63
+ expect(last_response.headers['Location']).to eq('/features/search')
63
64
  end
64
65
 
65
66
  context 'group name contains whitespace' do
66
- let(:group_name) { " admins " }
67
+ let(:group_name) { ' admins ' }
67
68
 
68
- it "adds item without whitespace" do
69
- expect(flipper[:search].groups_value).to include("admins")
69
+ it 'adds item without whitespace' do
70
+ expect(flipper[:search].groups_value).to include('admins')
70
71
  end
71
72
  end
72
73
 
73
- context "for an unregistered group" do
74
- context "unknown group name" do
75
- let(:group_name) { "not_here" }
74
+ context 'for an unregistered group' do
75
+ context 'unknown group name' do
76
+ let(:group_name) { 'not_here' }
76
77
 
77
- it "redirects back to feature" do
78
+ # rubocop:disable Metrics/LineLength
79
+ it 'redirects back to feature' do
78
80
  expect(last_response.status).to be(302)
79
- expect(last_response.headers["Location"]).to eq("/features/search/groups?error=The+group+named+%22not_here%22+has+not+been+registered.")
81
+ expect(last_response.headers['Location']).to eq('/features/search/groups?error=The+group+named+%22not_here%22+has+not+been+registered.')
80
82
  end
83
+ # rubocop:enable Metrics/LineLength
81
84
  end
82
85
 
83
- context "empty group name" do
84
- let(:group_name) { "" }
86
+ context 'empty group name' do
87
+ let(:group_name) { '' }
85
88
 
86
- it "redirects back to feature" do
89
+ # rubocop:disable Metrics/LineLength
90
+ it 'redirects back to feature' do
87
91
  expect(last_response.status).to be(302)
88
- expect(last_response.headers["Location"]).to eq("/features/search/groups?error=The+group+named+%22%22+has+not+been+registered.")
92
+ expect(last_response.headers['Location']).to eq('/features/search/groups?error=The+group+named+%22%22+has+not+been+registered.')
89
93
  end
94
+ # rubocop:enable Metrics/LineLength
90
95
  end
91
96
 
92
- context "nil group name" do
97
+ context 'nil group name' do
93
98
  let(:group_name) { nil }
94
99
 
95
- it "redirects back to feature" do
100
+ # rubocop:disable Metrics/LineLength
101
+ it 'redirects back to feature' do
96
102
  expect(last_response.status).to be(302)
97
- expect(last_response.headers["Location"]).to eq("/features/search/groups?error=The+group+named+%22%22+has+not+been+registered.")
103
+ expect(last_response.headers['Location']).to eq('/features/search/groups?error=The+group+named+%22%22+has+not+been+registered.')
98
104
  end
105
+ # rubocop:enable Metrics/LineLength
99
106
  end
100
107
  end
101
108
  end
102
109
 
103
- context "disabling a group" do
104
- let(:group_name) { "admins" }
110
+ context 'disabling a group' do
111
+ let(:group_name) { 'admins' }
105
112
 
106
113
  before do
107
114
  flipper[:search].enable_group :admins
108
- post "features/search/groups",
109
- {"value" => group_name, "operation" => "disable", "authenticity_token" => token},
110
- "rack.session" => session
115
+ post 'features/search/groups',
116
+ { 'value' => group_name, 'operation' => 'disable', 'authenticity_token' => token },
117
+ 'rack.session' => session
111
118
  end
112
119
 
113
- it "removes item from members" do
114
- expect(flipper[:search].groups_value).not_to include("admins")
120
+ it 'removes item from members' do
121
+ expect(flipper[:search].groups_value).not_to include('admins')
115
122
  end
116
123
 
117
- it "redirects back to feature" do
124
+ it 'redirects back to feature' do
118
125
  expect(last_response.status).to be(302)
119
- expect(last_response.headers["Location"]).to eq("/features/search")
126
+ expect(last_response.headers['Location']).to eq('/features/search')
120
127
  end
121
128
 
122
129
  context 'group name contains whitespace' do
123
- let(:group_name) { " admins " }
130
+ let(:group_name) { ' admins ' }
124
131
 
125
- it "removes item without whitespace" do
126
- expect(flipper[:search].groups_value).not_to include("admins")
132
+ it 'removes item without whitespace' do
133
+ expect(flipper[:search].groups_value).not_to include('admins')
127
134
  end
128
135
  end
129
136
  end