flipper-api 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.
- checksums.yaml +4 -4
- data/flipper-api.gemspec +12 -12
- data/lib/flipper/api/action.rb +12 -10
- data/lib/flipper/api/action_collection.rb +2 -2
- data/lib/flipper/api/error_response.rb +9 -8
- data/lib/flipper/api/json_params.rb +45 -0
- data/lib/flipper/api/middleware.rb +3 -28
- data/lib/flipper/api/v1/actions/actors_gate.rb +1 -9
- data/lib/flipper/api/v1/actions/boolean_gate.rb +1 -1
- data/lib/flipper/api/v1/actions/clear_feature.rb +21 -0
- data/lib/flipper/api/v1/actions/feature.rb +8 -16
- data/lib/flipper/api/v1/actions/features.rb +26 -8
- data/lib/flipper/api/v1/actions/groups_gate.rb +18 -7
- data/lib/flipper/api/v1/actions/percentage_of_actors_gate.rb +6 -24
- data/lib/flipper/api/v1/actions/percentage_of_time_gate.rb +6 -23
- data/lib/flipper/api/v1/decorators/feature.rb +3 -4
- data/lib/flipper/api.rb +11 -27
- data/lib/flipper/version.rb +1 -1
- data/spec/flipper/api/action_spec.rb +30 -36
- data/spec/flipper/api/json_params_spec.rb +81 -0
- data/spec/flipper/api/v1/actions/actors_gate_spec.rb +33 -22
- data/spec/flipper/api/v1/actions/boolean_gate_spec.rb +2 -2
- data/spec/flipper/api/v1/actions/clear_feature_spec.rb +27 -0
- data/spec/flipper/api/v1/actions/feature_spec.rb +28 -30
- data/spec/flipper/api/v1/actions/features_spec.rb +79 -44
- data/spec/flipper/api/v1/actions/groups_gate_spec.rb +92 -10
- data/spec/flipper/api/v1/actions/percentage_of_actors_gate_spec.rb +62 -24
- data/spec/flipper/api/v1/actions/percentage_of_time_gate_spec.rb +34 -15
- data/spec/flipper/api_spec.rb +55 -0
- metadata +15 -7
@@ -10,58 +10,88 @@ RSpec.describe Flipper::Api::V1::Actions::Features do
|
|
10
10
|
before do
|
11
11
|
flipper[:my_feature].enable
|
12
12
|
flipper[:my_feature].enable(admin)
|
13
|
-
get '
|
13
|
+
get '/features'
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'responds with correct attributes' do
|
17
17
|
expected_response = {
|
18
|
-
|
18
|
+
'features' => [
|
19
19
|
{
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
'key' => 'my_feature',
|
21
|
+
'state' => 'on',
|
22
|
+
'gates' => [
|
23
23
|
{
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
'key' => 'boolean',
|
25
|
+
'name' => 'boolean',
|
26
|
+
'value' => 'true',
|
27
27
|
},
|
28
28
|
{
|
29
|
-
|
30
|
-
|
31
|
-
|
29
|
+
'key' => 'groups',
|
30
|
+
'name' => 'group',
|
31
|
+
'value' => [],
|
32
32
|
},
|
33
33
|
{
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
'key' => 'actors',
|
35
|
+
'name' => 'actor',
|
36
|
+
'value' => ['10'],
|
37
37
|
},
|
38
38
|
{
|
39
|
-
|
40
|
-
|
41
|
-
|
39
|
+
'key' => 'percentage_of_actors',
|
40
|
+
'name' => 'percentage_of_actors',
|
41
|
+
'value' => nil,
|
42
42
|
},
|
43
43
|
{
|
44
|
-
|
45
|
-
|
46
|
-
|
44
|
+
'key' => 'percentage_of_time',
|
45
|
+
'name' => 'percentage_of_time',
|
46
|
+
'value' => nil,
|
47
47
|
},
|
48
48
|
],
|
49
49
|
},
|
50
|
-
]
|
50
|
+
],
|
51
51
|
}
|
52
52
|
expect(last_response.status).to eq(200)
|
53
53
|
expect(json_response).to eq(expected_response)
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
+
context 'with keys specified' do
|
58
|
+
before do
|
59
|
+
flipper[:audit_log].enable
|
60
|
+
flipper[:issues].enable
|
61
|
+
flipper[:search].enable
|
62
|
+
flipper[:stats].disable
|
63
|
+
get '/features', 'keys' => 'search,stats'
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'responds with correct attributes' do
|
67
|
+
expect(last_response.status).to eq(200)
|
68
|
+
keys = json_response.fetch('features').map { |feature| feature.fetch('key') }.sort
|
69
|
+
expect(keys).to eq(%w(search stats))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'with keys that are not existing features' do
|
74
|
+
before do
|
75
|
+
flipper[:search].disable
|
76
|
+
flipper[:stats].disable
|
77
|
+
get '/features', 'keys' => 'search,stats,not_a_feature,another_feature_that_does_not_exist'
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'only returns features that exist' do
|
81
|
+
expect(last_response.status).to eq(200)
|
82
|
+
keys = json_response.fetch('features').map { |feature| feature.fetch('key') }.sort
|
83
|
+
expect(keys).to eq(%w(search stats))
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
57
87
|
context 'with no flipper features' do
|
58
88
|
before do
|
59
|
-
get '
|
89
|
+
get '/features'
|
60
90
|
end
|
61
91
|
|
62
92
|
it 'returns empty array for features key' do
|
63
93
|
expected_response = {
|
64
|
-
|
94
|
+
'features' => [],
|
65
95
|
}
|
66
96
|
expect(last_response.status).to eq(200)
|
67
97
|
expect(json_response).to eq(expected_response)
|
@@ -72,7 +102,7 @@ RSpec.describe Flipper::Api::V1::Actions::Features do
|
|
72
102
|
describe 'post' do
|
73
103
|
context 'succesful request' do
|
74
104
|
before do
|
75
|
-
post '
|
105
|
+
post '/features', name: 'my_feature'
|
76
106
|
end
|
77
107
|
|
78
108
|
it 'responds 200 ' do
|
@@ -82,33 +112,33 @@ RSpec.describe Flipper::Api::V1::Actions::Features do
|
|
82
112
|
it 'returns decorated feature' do
|
83
113
|
expected_response = {
|
84
114
|
|
85
|
-
|
86
|
-
|
87
|
-
|
115
|
+
'key' => 'my_feature',
|
116
|
+
'state' => 'off',
|
117
|
+
'gates' => [
|
88
118
|
{
|
89
|
-
|
90
|
-
|
91
|
-
|
119
|
+
'key' => 'boolean',
|
120
|
+
'name' => 'boolean',
|
121
|
+
'value' => nil,
|
92
122
|
},
|
93
123
|
{
|
94
|
-
|
95
|
-
|
96
|
-
|
124
|
+
'key' => 'groups',
|
125
|
+
'name' => 'group',
|
126
|
+
'value' => [],
|
97
127
|
},
|
98
128
|
{
|
99
|
-
|
100
|
-
|
101
|
-
|
129
|
+
'key' => 'actors',
|
130
|
+
'name' => 'actor',
|
131
|
+
'value' => [],
|
102
132
|
},
|
103
133
|
{
|
104
|
-
|
105
|
-
|
106
|
-
|
134
|
+
'key' => 'percentage_of_actors',
|
135
|
+
'name' => 'percentage_of_actors',
|
136
|
+
'value' => nil,
|
107
137
|
},
|
108
138
|
{
|
109
|
-
|
110
|
-
|
111
|
-
|
139
|
+
'key' => 'percentage_of_time',
|
140
|
+
'name' => 'percentage_of_time',
|
141
|
+
'value' => nil,
|
112
142
|
},
|
113
143
|
],
|
114
144
|
}
|
@@ -126,7 +156,7 @@ RSpec.describe Flipper::Api::V1::Actions::Features do
|
|
126
156
|
|
127
157
|
context 'bad request' do
|
128
158
|
before do
|
129
|
-
post '
|
159
|
+
post '/features'
|
130
160
|
end
|
131
161
|
|
132
162
|
it 'returns correct status code' do
|
@@ -134,7 +164,12 @@ RSpec.describe Flipper::Api::V1::Actions::Features do
|
|
134
164
|
end
|
135
165
|
|
136
166
|
it 'returns formatted error' do
|
137
|
-
|
167
|
+
expected = {
|
168
|
+
'code' => 5,
|
169
|
+
'message' => 'Required parameter name is missing.',
|
170
|
+
'more_info' => api_error_code_reference_url,
|
171
|
+
}
|
172
|
+
expect(json_response).to eq(expected)
|
138
173
|
end
|
139
174
|
end
|
140
175
|
end
|
@@ -9,7 +9,7 @@ RSpec.describe Flipper::Api::V1::Actions::GroupsGate do
|
|
9
9
|
Flipper.register(:admins) do |actor|
|
10
10
|
actor.respond_to?(:admin?) && actor.admin?
|
11
11
|
end
|
12
|
-
post '/
|
12
|
+
post '/features/my_feature/groups', name: 'admins'
|
13
13
|
end
|
14
14
|
|
15
15
|
it 'enables feature for group' do
|
@@ -26,6 +26,29 @@ RSpec.describe Flipper::Api::V1::Actions::GroupsGate do
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
+
describe 'enable without name params' do
|
30
|
+
before do
|
31
|
+
flipper[:my_feature].disable
|
32
|
+
Flipper.register(:admins) do |actor|
|
33
|
+
actor.respond_to?(:admin?) && actor.admin?
|
34
|
+
end
|
35
|
+
post '/features/my_feature/groups'
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'returns correct status code' do
|
39
|
+
expect(last_response.status).to eq(422)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'returns formatted error' do
|
43
|
+
expected = {
|
44
|
+
'code' => 5,
|
45
|
+
'message' => 'Required parameter name is missing.',
|
46
|
+
'more_info' => api_error_code_reference_url,
|
47
|
+
}
|
48
|
+
expect(json_response).to eq(expected)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
29
52
|
describe 'disable' do
|
30
53
|
before do
|
31
54
|
flipper[:my_feature].disable
|
@@ -33,7 +56,7 @@ RSpec.describe Flipper::Api::V1::Actions::GroupsGate do
|
|
33
56
|
actor.respond_to?(:admin?) && actor.admin?
|
34
57
|
end
|
35
58
|
flipper[:my_feature].enable_group(:admins)
|
36
|
-
delete '/
|
59
|
+
delete '/features/my_feature/groups', name: 'admins'
|
37
60
|
end
|
38
61
|
|
39
62
|
it 'disables feature for group' do
|
@@ -50,26 +73,85 @@ RSpec.describe Flipper::Api::V1::Actions::GroupsGate do
|
|
50
73
|
end
|
51
74
|
end
|
52
75
|
|
53
|
-
describe 'non-existent feature' do
|
76
|
+
describe 'disable for non-existent feature' do
|
54
77
|
before do
|
55
|
-
|
78
|
+
Flipper.register(:admins) do |actor|
|
79
|
+
actor.respond_to?(:admin?) && actor.admin?
|
80
|
+
end
|
81
|
+
delete '/features/my_feature/groups', name: 'admins'
|
56
82
|
end
|
57
83
|
|
58
|
-
it
|
59
|
-
|
60
|
-
|
84
|
+
it 'disables feature for group' do
|
85
|
+
person = double
|
86
|
+
allow(person).to receive(:flipper_id).and_return(1)
|
87
|
+
allow(person).to receive(:admin?).and_return(true)
|
88
|
+
expect(last_response.status).to eq(200)
|
89
|
+
expect(flipper[:my_feature].enabled?(person)).to be_falsey
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'returns decorated feature with group disabled' do
|
93
|
+
group_gate = json_response['gates'].find { |m| m['name'] == 'group' }
|
94
|
+
expect(group_gate['value']).to eq([])
|
61
95
|
end
|
62
96
|
end
|
63
97
|
|
64
|
-
describe 'group not registered' do
|
98
|
+
describe 'disable for group not registered' do
|
65
99
|
before do
|
66
100
|
flipper[:my_feature].disable
|
67
|
-
delete '/
|
101
|
+
delete '/features/my_feature/groups', name: 'admins'
|
68
102
|
end
|
69
103
|
|
70
104
|
it '404s with correct error response when group not registered' do
|
71
105
|
expect(last_response.status).to eq(404)
|
72
|
-
|
106
|
+
expected = {
|
107
|
+
'code' => 2,
|
108
|
+
'message' => 'Group not registered.',
|
109
|
+
'more_info' => api_error_code_reference_url,
|
110
|
+
}
|
111
|
+
expect(json_response).to eq(expected)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe 'enable for group not registered when allow_unregistered_groups is true' do
|
116
|
+
before do
|
117
|
+
Flipper.unregister_groups
|
118
|
+
flipper[:my_feature].disable
|
119
|
+
post '/features/my_feature/groups', name: 'admins', allow_unregistered_groups: 'true'
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'responds successfully' do
|
123
|
+
expect(last_response.status).to eq(200)
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'returns decorated feature with group in groups set' do
|
127
|
+
group_gate = json_response['gates'].find { |m| m['name'] == 'group' }
|
128
|
+
expect(group_gate['value']).to eq(['admins'])
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'enables group' do
|
132
|
+
expect(flipper[:my_feature].groups_value).to eq(Set["admins"])
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
describe 'disable for group not registered when allow_unregistered_groups is true' do
|
137
|
+
before do
|
138
|
+
Flipper.unregister_groups
|
139
|
+
flipper[:my_feature].disable
|
140
|
+
flipper[:my_feature].enable_group(:admins)
|
141
|
+
delete '/features/my_feature/groups', name: 'admins', allow_unregistered_groups: 'true'
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'responds successfully' do
|
145
|
+
expect(last_response.status).to eq(200)
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'returns decorated feature with group not in groups set' do
|
149
|
+
group_gate = json_response['gates'].find { |m| m['name'] == 'group' }
|
150
|
+
expect(group_gate['value']).to eq([])
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'disables group' do
|
154
|
+
expect(flipper[:my_feature].groups_value).to be_empty
|
73
155
|
end
|
74
156
|
end
|
75
157
|
end
|
@@ -4,26 +4,45 @@ RSpec.describe Flipper::Api::V1::Actions::PercentageOfActorsGate do
|
|
4
4
|
let(:app) { build_api(flipper) }
|
5
5
|
|
6
6
|
describe 'enable' do
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
context 'url-encoded request' do
|
8
|
+
before do
|
9
|
+
flipper[:my_feature].disable
|
10
|
+
post '/features/my_feature/percentage_of_actors', percentage: '10'
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'enables gate for feature' do
|
14
|
+
expect(flipper[:my_feature].enabled_gate_names).to include(:percentage_of_actors)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'returns decorated feature with gate enabled for 10 percent of actors' do
|
18
|
+
gate = json_response['gates'].find { |gate| gate['name'] == 'percentage_of_actors' }
|
19
|
+
expect(gate['value']).to eq('10')
|
20
|
+
end
|
10
21
|
end
|
11
22
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
23
|
+
context 'json request' do
|
24
|
+
before do
|
25
|
+
flipper[:my_feature].disable
|
26
|
+
post '/features/my_feature/percentage_of_actors',
|
27
|
+
JSON.generate(percentage: '10'),
|
28
|
+
'CONTENT_TYPE' => 'application/json'
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'enables gate for feature' do
|
32
|
+
expect(flipper[:my_feature].enabled_gate_names).to include(:percentage_of_actors)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'returns decorated feature with gate enabled for 10 percent of actors' do
|
36
|
+
gate = json_response['gates'].find { |gate| gate['name'] == 'percentage_of_actors' }
|
37
|
+
expect(gate['value']).to eq('10')
|
38
|
+
end
|
19
39
|
end
|
20
|
-
|
21
40
|
end
|
22
41
|
|
23
|
-
describe 'disable' do
|
42
|
+
describe 'disable without percentage' do
|
24
43
|
before do
|
25
44
|
flipper[:my_feature].enable_percentage_of_actors(10)
|
26
|
-
delete '/
|
45
|
+
delete '/features/my_feature/percentage_of_actors'
|
27
46
|
end
|
28
47
|
|
29
48
|
it 'disables gate for feature' do
|
@@ -32,54 +51,73 @@ RSpec.describe Flipper::Api::V1::Actions::PercentageOfActorsGate do
|
|
32
51
|
|
33
52
|
it 'returns decorated feature with gate disabled' do
|
34
53
|
gate = json_response['gates'].find { |gate| gate['name'] == 'percentage_of_actors' }
|
35
|
-
expect(gate['value']).to eq(0)
|
54
|
+
expect(gate['value']).to eq('0')
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe 'disable with percentage' do
|
59
|
+
before do
|
60
|
+
flipper[:my_feature].enable_percentage_of_actors(10)
|
61
|
+
delete '/features/my_feature/percentage_of_actors',
|
62
|
+
JSON.generate(percentage: '5'),
|
63
|
+
'CONTENT_TYPE' => 'application/json'
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'returns decorated feature with gate value set to 0 regardless of percentage requested' do
|
67
|
+
gate = json_response['gates'].find { |gate| gate['name'] == 'percentage_of_actors' }
|
68
|
+
expect(gate['value']).to eq('0')
|
36
69
|
end
|
37
70
|
end
|
38
71
|
|
39
72
|
describe 'non-existent feature' do
|
40
73
|
before do
|
41
|
-
delete '/
|
74
|
+
delete '/features/my_feature/percentage_of_actors'
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'disables gate for feature' do
|
78
|
+
expect(flipper[:my_feature].enabled_gates).to be_empty
|
42
79
|
end
|
43
80
|
|
44
|
-
it
|
45
|
-
expect(last_response.status).to eq(
|
46
|
-
|
81
|
+
it 'returns decorated feature with gate disabled' do
|
82
|
+
expect(last_response.status).to eq(200)
|
83
|
+
gate = json_response['gates'].find { |gate| gate['name'] == 'percentage_of_actors' }
|
84
|
+
expect(gate['value']).to eq('0')
|
47
85
|
end
|
48
86
|
end
|
49
87
|
|
50
88
|
describe 'out of range parameter percentage parameter' do
|
51
89
|
before do
|
52
90
|
flipper[:my_feature].disable
|
53
|
-
post '/
|
91
|
+
post '/features/my_feature/percentage_of_actors', percentage: '300'
|
54
92
|
end
|
55
93
|
|
56
94
|
it '422s with correct error response when percentage parameter is invalid' do
|
57
95
|
expect(last_response.status).to eq(422)
|
58
|
-
expect(json_response).to eq(
|
96
|
+
expect(json_response).to eq(api_positive_percentage_error_response)
|
59
97
|
end
|
60
98
|
end
|
61
99
|
|
62
100
|
describe 'percentage parameter not an integer' do
|
63
101
|
before do
|
64
102
|
flipper[:my_feature].disable
|
65
|
-
post '/
|
103
|
+
post '/features/my_feature/percentage_of_actors', percentage: 'foo'
|
66
104
|
end
|
67
105
|
|
68
106
|
it '422s with correct error response when percentage parameter is invalid' do
|
69
107
|
expect(last_response.status).to eq(422)
|
70
|
-
expect(json_response).to eq(
|
108
|
+
expect(json_response).to eq(api_positive_percentage_error_response)
|
71
109
|
end
|
72
110
|
end
|
73
111
|
|
74
112
|
describe 'missing percentage parameter' do
|
75
113
|
before do
|
76
114
|
flipper[:my_feature].disable
|
77
|
-
post '/
|
115
|
+
post '/features/my_feature/percentage_of_actors'
|
78
116
|
end
|
79
117
|
|
80
118
|
it '422s with correct error response when percentage parameter is missing' do
|
81
119
|
expect(last_response.status).to eq(422)
|
82
|
-
expect(json_response).to eq(
|
120
|
+
expect(json_response).to eq(api_positive_percentage_error_response)
|
83
121
|
end
|
84
122
|
end
|
85
123
|
end
|
@@ -6,7 +6,7 @@ RSpec.describe Flipper::Api::V1::Actions::PercentageOfTimeGate do
|
|
6
6
|
describe 'enable' do
|
7
7
|
before do
|
8
8
|
flipper[:my_feature].disable
|
9
|
-
post '/
|
9
|
+
post '/features/my_feature/percentage_of_time', percentage: '10'
|
10
10
|
end
|
11
11
|
|
12
12
|
it 'enables gate for feature' do
|
@@ -15,14 +15,14 @@ RSpec.describe Flipper::Api::V1::Actions::PercentageOfTimeGate do
|
|
15
15
|
|
16
16
|
it 'returns decorated feature with gate enabled for 5% of time' do
|
17
17
|
gate = json_response['gates'].find { |gate| gate['name'] == 'percentage_of_time' }
|
18
|
-
expect(gate['value']).to eq(10)
|
18
|
+
expect(gate['value']).to eq('10')
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
describe 'disable' do
|
22
|
+
describe 'disable without percentage' do
|
23
23
|
before do
|
24
24
|
flipper[:my_feature].enable_percentage_of_time(10)
|
25
|
-
delete '/
|
25
|
+
delete '/features/my_feature/percentage_of_time'
|
26
26
|
end
|
27
27
|
|
28
28
|
it 'disables gate for feature' do
|
@@ -31,54 +31,73 @@ RSpec.describe Flipper::Api::V1::Actions::PercentageOfTimeGate do
|
|
31
31
|
|
32
32
|
it 'returns decorated feature with gate disabled' do
|
33
33
|
gate = json_response['gates'].find { |gate| gate['name'] == 'percentage_of_time' }
|
34
|
-
expect(gate['value']).to eq(0)
|
34
|
+
expect(gate['value']).to eq('0')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe 'disable with percentage' do
|
39
|
+
before do
|
40
|
+
flipper[:my_feature].enable_percentage_of_time(10)
|
41
|
+
delete '/features/my_feature/percentage_of_time',
|
42
|
+
JSON.generate(percentage: '5'),
|
43
|
+
'CONTENT_TYPE' => 'application/json'
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'returns decorated feature with gate value set to 0 regardless of percentage requested' do
|
47
|
+
expect(last_response.status).to eq(200)
|
48
|
+
gate = json_response['gates'].find { |gate| gate['name'] == 'percentage_of_time' }
|
49
|
+
expect(gate['value']).to eq('0')
|
35
50
|
end
|
36
51
|
end
|
37
52
|
|
38
53
|
describe 'non-existent feature' do
|
39
54
|
before do
|
40
|
-
delete '/
|
55
|
+
delete '/features/my_feature/percentage_of_time'
|
41
56
|
end
|
42
57
|
|
43
|
-
it
|
44
|
-
expect(
|
45
|
-
|
58
|
+
it 'disables gate for feature' do
|
59
|
+
expect(flipper[:my_feature].enabled_gates).to be_empty
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'returns decorated feature with gate disabled' do
|
63
|
+
gate = json_response['gates'].find { |gate| gate['name'] == 'percentage_of_time' }
|
64
|
+
expect(gate['value']).to eq('0')
|
46
65
|
end
|
47
66
|
end
|
48
67
|
|
49
68
|
describe 'out of range parameter percentage parameter' do
|
50
69
|
before do
|
51
70
|
flipper[:my_feature].disable
|
52
|
-
post '/
|
71
|
+
post '/features/my_feature/percentage_of_time', percentage: '300'
|
53
72
|
end
|
54
73
|
|
55
74
|
it '422s with correct error response when percentage parameter is invalid' do
|
56
75
|
expect(last_response.status).to eq(422)
|
57
|
-
expect(json_response).to eq(
|
76
|
+
expect(json_response).to eq(api_positive_percentage_error_response)
|
58
77
|
end
|
59
78
|
end
|
60
79
|
|
61
80
|
describe 'percentage parameter not an integer' do
|
62
81
|
before do
|
63
82
|
flipper[:my_feature].disable
|
64
|
-
post '/
|
83
|
+
post '/features/my_feature/percentage_of_time', percentage: 'foo'
|
65
84
|
end
|
66
85
|
|
67
86
|
it '422s with correct error response when percentage parameter is invalid' do
|
68
87
|
expect(last_response.status).to eq(422)
|
69
|
-
expect(json_response).to eq(
|
88
|
+
expect(json_response).to eq(api_positive_percentage_error_response)
|
70
89
|
end
|
71
90
|
end
|
72
91
|
|
73
92
|
describe 'missing percentage parameter' do
|
74
93
|
before do
|
75
94
|
flipper[:my_feature].disable
|
76
|
-
post '/
|
95
|
+
post '/features/my_feature/percentage_of_time'
|
77
96
|
end
|
78
97
|
|
79
98
|
it '422s with correct error response when percentage parameter is missing' do
|
80
99
|
expect(last_response.status).to eq(422)
|
81
|
-
expect(json_response).to eq(
|
100
|
+
expect(json_response).to eq(api_positive_percentage_error_response)
|
82
101
|
end
|
83
102
|
end
|
84
103
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
RSpec.describe Flipper::Api do
|
4
|
+
context 'when initialized with flipper instance and flipper instance in env' do
|
5
|
+
let(:app) { build_api(flipper) }
|
6
|
+
|
7
|
+
it 'uses env instance over initialized instance' do
|
8
|
+
flipper[:built_a].enable
|
9
|
+
flipper[:built_b].disable
|
10
|
+
|
11
|
+
env_flipper = build_flipper
|
12
|
+
env_flipper[:env_a].enable
|
13
|
+
env_flipper[:env_b].disable
|
14
|
+
|
15
|
+
params = {}
|
16
|
+
env = {
|
17
|
+
'flipper' => env_flipper,
|
18
|
+
}
|
19
|
+
get '/features', params, env
|
20
|
+
|
21
|
+
expect(last_response.status).to eq(200)
|
22
|
+
feature_names = json_response.fetch('features').map { |feature| feature.fetch('key') }
|
23
|
+
expect(feature_names).to eq(%w(env_a env_b))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'when initialized without flipper instance but flipper instance in env' do
|
28
|
+
let(:app) { described_class.app }
|
29
|
+
|
30
|
+
it 'uses env instance' do
|
31
|
+
flipper[:a].enable
|
32
|
+
flipper[:b].disable
|
33
|
+
|
34
|
+
params = {}
|
35
|
+
env = {
|
36
|
+
'flipper' => flipper,
|
37
|
+
}
|
38
|
+
get '/features', params, env
|
39
|
+
|
40
|
+
expect(last_response.status).to eq(200)
|
41
|
+
feature_names = json_response.fetch('features').map { |feature| feature.fetch('key') }
|
42
|
+
expect(feature_names).to eq(%w(a b))
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context "when request does not match any api routes" do
|
47
|
+
let(:app) { build_api(flipper) }
|
48
|
+
|
49
|
+
it "returns 404" do
|
50
|
+
get '/gibberish'
|
51
|
+
expect(last_response.status).to eq(404)
|
52
|
+
expect(json_response).to eq({})
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|