flipper-ui 0.10.2 → 0.11.0.beta1

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.
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