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
@@ -1,68 +1,66 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
3
|
RSpec.describe Flipper::Api::Action do
|
4
|
-
let(:action_subclass)
|
4
|
+
let(:action_subclass) do
|
5
5
|
Class.new(described_class) do
|
6
6
|
def noooope
|
7
|
-
raise
|
7
|
+
raise 'should never run this'
|
8
8
|
end
|
9
9
|
|
10
10
|
def get
|
11
|
-
[200, {},
|
11
|
+
[200, {}, 'get']
|
12
12
|
end
|
13
13
|
|
14
14
|
def post
|
15
|
-
[200, {},
|
15
|
+
[200, {}, 'post']
|
16
16
|
end
|
17
17
|
|
18
18
|
def put
|
19
|
-
[200, {},
|
19
|
+
[200, {}, 'put']
|
20
20
|
end
|
21
21
|
|
22
22
|
def delete
|
23
|
-
[200, {},
|
23
|
+
[200, {}, 'delete']
|
24
24
|
end
|
25
25
|
end
|
26
|
-
|
26
|
+
end
|
27
27
|
|
28
28
|
describe 'https verbs' do
|
29
|
-
|
30
29
|
it "won't run method that isn't whitelisted" do
|
31
|
-
fake_request = Struct.new(:request_method, :env, :session).new(
|
30
|
+
fake_request = Struct.new(:request_method, :env, :session).new('NOOOOPE', {}, {})
|
32
31
|
action = action_subclass.new(flipper, fake_request)
|
33
|
-
expect
|
32
|
+
expect do
|
34
33
|
action.run
|
35
|
-
|
34
|
+
end.to raise_error(Flipper::Api::RequestMethodNotSupported)
|
36
35
|
end
|
37
36
|
|
38
|
-
it
|
39
|
-
fake_request = Struct.new(:request_method, :env, :session).new(
|
37
|
+
it 'will run get' do
|
38
|
+
fake_request = Struct.new(:request_method, :env, :session).new('GET', {}, {})
|
40
39
|
action = action_subclass.new(flipper, fake_request)
|
41
|
-
expect(action.run).to eq([200, {},
|
40
|
+
expect(action.run).to eq([200, {}, 'get'])
|
42
41
|
end
|
43
42
|
|
44
|
-
it
|
45
|
-
fake_request = Struct.new(:request_method, :env, :session).new(
|
43
|
+
it 'will run post' do
|
44
|
+
fake_request = Struct.new(:request_method, :env, :session).new('POST', {}, {})
|
46
45
|
action = action_subclass.new(flipper, fake_request)
|
47
|
-
expect(action.run).to eq([200, {},
|
46
|
+
expect(action.run).to eq([200, {}, 'post'])
|
48
47
|
end
|
49
48
|
|
50
|
-
it
|
51
|
-
fake_request = Struct.new(:request_method, :env, :session).new(
|
49
|
+
it 'will run put' do
|
50
|
+
fake_request = Struct.new(:request_method, :env, :session).new('PUT', {}, {})
|
52
51
|
action = action_subclass.new(flipper, fake_request)
|
53
|
-
expect(action.run).to eq([200, {},
|
52
|
+
expect(action.run).to eq([200, {}, 'put'])
|
54
53
|
end
|
55
54
|
|
56
|
-
it
|
57
|
-
fake_request = Struct.new(:request_method, :env, :session).new(
|
55
|
+
it 'will run delete' do
|
56
|
+
fake_request = Struct.new(:request_method, :env, :session).new('DELETE', {}, {})
|
58
57
|
action = action_subclass.new(flipper, fake_request)
|
59
|
-
expect(action.run).to eq([200, {},
|
58
|
+
expect(action.run).to eq([200, {}, 'delete'])
|
60
59
|
end
|
61
60
|
end
|
62
61
|
|
63
62
|
describe '#json_error_response' do
|
64
|
-
describe
|
65
|
-
|
63
|
+
describe ':feature_not_found' do
|
66
64
|
it 'locates and serializes error correctly' do
|
67
65
|
action = action_subclass.new({}, {})
|
68
66
|
response = catch(:halt) do
|
@@ -71,15 +69,12 @@ RSpec.describe Flipper::Api::Action do
|
|
71
69
|
status, headers, body = response
|
72
70
|
parsed_body = JSON.parse(body[0])
|
73
71
|
|
74
|
-
expect(headers[
|
75
|
-
expect(parsed_body
|
76
|
-
expect(parsed_body["message"]).to eq("Feature not found.")
|
77
|
-
expect(parsed_body["more_info"]).to eq("https://github.com/jnunemaker/flipper/tree/master/docs/api#error-code-reference")
|
72
|
+
expect(headers['Content-Type']).to eq('application/json')
|
73
|
+
expect(parsed_body).to eql(api_not_found_response)
|
78
74
|
end
|
79
75
|
end
|
80
76
|
|
81
77
|
describe ':group_not_registered' do
|
82
|
-
|
83
78
|
it 'locates and serializes error correctly' do
|
84
79
|
action = action_subclass.new({}, {})
|
85
80
|
response = catch(:halt) do
|
@@ -88,19 +83,18 @@ RSpec.describe Flipper::Api::Action do
|
|
88
83
|
status, headers, body = response
|
89
84
|
parsed_body = JSON.parse(body[0])
|
90
85
|
|
91
|
-
expect(headers[
|
92
|
-
expect(parsed_body[
|
93
|
-
expect(parsed_body[
|
94
|
-
expect(parsed_body[
|
86
|
+
expect(headers['Content-Type']).to eq('application/json')
|
87
|
+
expect(parsed_body['code']).to eq(2)
|
88
|
+
expect(parsed_body['message']).to eq('Group not registered.')
|
89
|
+
expect(parsed_body['more_info']).to eq(api_error_code_reference_url)
|
95
90
|
end
|
96
91
|
end
|
97
92
|
|
98
93
|
describe 'invalid error key' do
|
99
|
-
|
100
94
|
it 'raises descriptive error' do
|
101
95
|
action = action_subclass.new({}, {})
|
102
96
|
catch(:halt) do
|
103
|
-
expect{ action.json_error_response(:invalid_error_key) }.to raise_error(KeyError)
|
97
|
+
expect { action.json_error_response(:invalid_error_key) }.to raise_error(KeyError)
|
104
98
|
end
|
105
99
|
end
|
106
100
|
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
RSpec.describe Flipper::Api::JsonParams do
|
4
|
+
let(:app) do
|
5
|
+
app = lambda do |env|
|
6
|
+
request = Rack::Request.new(env)
|
7
|
+
[200, { 'Content-Type' => 'application/json' }, [JSON.generate(request.params)]]
|
8
|
+
end
|
9
|
+
builder = Rack::Builder.new
|
10
|
+
builder.use described_class
|
11
|
+
builder.run app
|
12
|
+
builder
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'json post request' do
|
16
|
+
it 'adds request body to params' do
|
17
|
+
response = post '/',
|
18
|
+
JSON.generate(flipper_id: 'user:2'),
|
19
|
+
'CONTENT_TYPE' => 'application/json'
|
20
|
+
|
21
|
+
params = JSON.parse(response.body)
|
22
|
+
expect(params).to eq('flipper_id' => 'user:2')
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'handles request bodies with multiple params' do
|
26
|
+
response = post '/',
|
27
|
+
JSON.generate(flipper_id: 'user:2', language: 'ruby'),
|
28
|
+
'CONTENT_TYPE' => 'application/json'
|
29
|
+
|
30
|
+
params = JSON.parse(response.body)
|
31
|
+
expect(params).to eq('flipper_id' => 'user:2', 'language' => 'ruby')
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'handles request bodies and single query string params' do
|
35
|
+
response = post '/?language=ruby',
|
36
|
+
JSON.generate(flipper_id: 'user:2'),
|
37
|
+
'CONTENT_TYPE' => 'application/json'
|
38
|
+
|
39
|
+
params = JSON.parse(response.body)
|
40
|
+
expect(params).to eq('flipper_id' => 'user:2', 'language' => 'ruby')
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'handles request bodies and multiple query string params' do
|
44
|
+
response = post '/?language=ruby&framework=rails',
|
45
|
+
JSON.generate(flipper_id: 'user:2'),
|
46
|
+
'CONTENT_TYPE' => 'application/json'
|
47
|
+
|
48
|
+
params = JSON.parse(response.body)
|
49
|
+
expect(params).to eq('flipper_id' => 'user:2', 'language' => 'ruby', 'framework' => 'rails')
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'favors request body params' do
|
53
|
+
response = post '/?language=javascript',
|
54
|
+
JSON.generate(flipper_id: 'user:2', language: 'ruby'),
|
55
|
+
'CONTENT_TYPE' => 'application/json'
|
56
|
+
|
57
|
+
params = JSON.parse(response.body)
|
58
|
+
expect(params).to eq('flipper_id' => 'user:2', 'language' => 'ruby')
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe 'url-encoded request' do
|
63
|
+
it 'handles params the same as a json request' do
|
64
|
+
response = post '/', flipper_id: 'user:2'
|
65
|
+
params = JSON.parse(response.body)
|
66
|
+
expect(params).to eq('flipper_id' => 'user:2')
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'handles single query string params' do
|
70
|
+
response = post '/?language=ruby', flipper_id: 'user:2'
|
71
|
+
params = JSON.parse(response.body)
|
72
|
+
expect(params).to eq('flipper_id' => 'user:2', 'language' => 'ruby')
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'handles multiple query string params' do
|
76
|
+
response = post '/?language=ruby&framework=rails', flipper_id: 'user:2'
|
77
|
+
params = JSON.parse(response.body)
|
78
|
+
expect(params).to eq('flipper_id' => 'user:2', 'language' => 'ruby', 'framework' => 'rails')
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -2,13 +2,12 @@ require 'helper'
|
|
2
2
|
|
3
3
|
RSpec.describe Flipper::Api::V1::Actions::ActorsGate do
|
4
4
|
let(:app) { build_api(flipper) }
|
5
|
+
let(:actor) { Flipper::Api::Actor.new('1') }
|
5
6
|
|
6
7
|
describe 'enable' do
|
7
|
-
let(:actor) { Flipper::Api::Actor.new("1") }
|
8
|
-
|
9
8
|
before do
|
10
9
|
flipper[:my_feature].disable_actor(actor)
|
11
|
-
post '/
|
10
|
+
post '/features/my_feature/actors', flipper_id: actor.flipper_id
|
12
11
|
end
|
13
12
|
|
14
13
|
it 'enables feature for actor' do
|
@@ -19,16 +18,16 @@ RSpec.describe Flipper::Api::V1::Actions::ActorsGate do
|
|
19
18
|
|
20
19
|
it 'returns decorated feature with actor enabled' do
|
21
20
|
gate = json_response['gates'].find { |gate| gate['key'] == 'actors' }
|
22
|
-
expect(gate['value']).to eq([
|
21
|
+
expect(gate['value']).to eq(['1'])
|
23
22
|
end
|
24
23
|
end
|
25
24
|
|
26
25
|
describe 'disable' do
|
27
|
-
let(:actor) { Flipper::Api::Actor.new(
|
26
|
+
let(:actor) { Flipper::Api::Actor.new('1') }
|
28
27
|
|
29
28
|
before do
|
30
29
|
flipper[:my_feature].enable_actor(actor)
|
31
|
-
delete '/
|
30
|
+
delete '/features/my_feature/actors', flipper_id: actor.flipper_id
|
32
31
|
end
|
33
32
|
|
34
33
|
it 'disables feature' do
|
@@ -46,70 +45,82 @@ RSpec.describe Flipper::Api::V1::Actions::ActorsGate do
|
|
46
45
|
describe 'enable missing flipper_id parameter' do
|
47
46
|
before do
|
48
47
|
flipper[:my_feature].enable
|
49
|
-
post '/
|
48
|
+
post '/features/my_feature/actors'
|
50
49
|
end
|
51
50
|
|
52
51
|
it 'returns correct error response' do
|
53
52
|
expect(last_response.status).to eq(422)
|
54
|
-
expect(json_response).to eq(
|
53
|
+
expect(json_response).to eq(api_flipper_id_is_missing_response)
|
55
54
|
end
|
56
55
|
end
|
57
56
|
|
58
57
|
describe 'disable missing flipper_id parameter' do
|
59
58
|
before do
|
60
59
|
flipper[:my_feature].enable
|
61
|
-
delete '/
|
60
|
+
delete '/features/my_feature/actors'
|
62
61
|
end
|
63
62
|
|
64
63
|
it 'returns correct error response' do
|
65
64
|
expect(last_response.status).to eq(422)
|
66
|
-
expect(json_response).to eq(
|
65
|
+
expect(json_response).to eq(api_flipper_id_is_missing_response)
|
67
66
|
end
|
68
67
|
end
|
69
68
|
|
70
69
|
describe 'enable nil flipper_id parameter' do
|
71
70
|
before do
|
72
71
|
flipper[:my_feature].enable
|
73
|
-
post '/
|
72
|
+
post '/features/my_feature/actors', flipper_id: nil
|
74
73
|
end
|
75
74
|
|
76
75
|
it 'returns correct error response' do
|
77
76
|
expect(last_response.status).to eq(422)
|
78
|
-
expect(json_response).to eq(
|
77
|
+
expect(json_response).to eq(api_flipper_id_is_missing_response)
|
79
78
|
end
|
80
79
|
end
|
81
80
|
|
82
81
|
describe 'disable nil flipper_id parameter' do
|
83
82
|
before do
|
84
83
|
flipper[:my_feature].enable
|
85
|
-
delete '/
|
84
|
+
delete '/features/my_feature/actors', flipper_id: nil
|
86
85
|
end
|
87
86
|
|
88
87
|
it 'returns correct error response' do
|
89
88
|
expect(last_response.status).to eq(422)
|
90
|
-
expect(json_response).to eq(
|
89
|
+
expect(json_response).to eq(api_flipper_id_is_missing_response)
|
91
90
|
end
|
92
91
|
end
|
93
92
|
|
94
93
|
describe 'enable missing feature' do
|
95
94
|
before do
|
96
|
-
post '/
|
95
|
+
post '/features/my_feature/actors', flipper_id: actor.flipper_id
|
97
96
|
end
|
98
97
|
|
99
|
-
it '
|
100
|
-
expect(last_response.status).to eq(
|
101
|
-
expect(
|
98
|
+
it 'enables feature for actor' do
|
99
|
+
expect(last_response.status).to eq(200)
|
100
|
+
expect(flipper[:my_feature].enabled?(actor)).to be_truthy
|
101
|
+
expect(flipper[:my_feature].enabled_gate_names).to eq([:actor])
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'returns decorated feature with actor enabled' do
|
105
|
+
gate = json_response['gates'].find { |gate| gate['key'] == 'actors' }
|
106
|
+
expect(gate['value']).to eq(['1'])
|
102
107
|
end
|
103
108
|
end
|
104
109
|
|
105
110
|
describe 'disable missing feature' do
|
106
111
|
before do
|
107
|
-
delete '/
|
112
|
+
delete '/features/my_feature/actors', flipper_id: actor.flipper_id
|
108
113
|
end
|
109
114
|
|
110
|
-
it '
|
111
|
-
expect(last_response.status).to eq(
|
112
|
-
expect(
|
115
|
+
it 'disables feature' do
|
116
|
+
expect(last_response.status).to eq(200)
|
117
|
+
expect(flipper[:my_feature].enabled?(actor)).to be_falsy
|
118
|
+
expect(flipper[:my_feature].enabled_gate_names).to be_empty
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'returns decorated feature with boolean gate disabled' do
|
122
|
+
gate = json_response['gates'].find { |gate| gate['key'] == 'actors' }
|
123
|
+
expect(gate['value']).to be_empty
|
113
124
|
end
|
114
125
|
end
|
115
126
|
end
|
@@ -6,7 +6,7 @@ RSpec.describe Flipper::Api::V1::Actions::BooleanGate do
|
|
6
6
|
describe 'enable' do
|
7
7
|
before do
|
8
8
|
flipper[:my_feature].disable
|
9
|
-
post '/
|
9
|
+
post '/features/my_feature/boolean'
|
10
10
|
end
|
11
11
|
|
12
12
|
it 'enables feature' do
|
@@ -23,7 +23,7 @@ RSpec.describe Flipper::Api::V1::Actions::BooleanGate do
|
|
23
23
|
describe 'disable' do
|
24
24
|
before do
|
25
25
|
flipper[:my_feature].enable
|
26
|
-
delete '/
|
26
|
+
delete '/features/my_feature/boolean'
|
27
27
|
end
|
28
28
|
|
29
29
|
it 'disables feature' do
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
RSpec.describe Flipper::Api::V1::Actions::ClearFeature do
|
4
|
+
let(:app) { build_api(flipper) }
|
5
|
+
|
6
|
+
describe 'clear' do
|
7
|
+
before do
|
8
|
+
Flipper.register(:admins) {}
|
9
|
+
actor_class = Struct.new(:flipper_id)
|
10
|
+
actor22 = actor_class.new('22')
|
11
|
+
|
12
|
+
feature = flipper[:my_feature]
|
13
|
+
feature.enable flipper.boolean
|
14
|
+
feature.enable flipper.group(:admins)
|
15
|
+
feature.enable flipper.actor(actor22)
|
16
|
+
feature.enable flipper.actors(25)
|
17
|
+
feature.enable flipper.time(45)
|
18
|
+
|
19
|
+
delete '/features/my_feature/clear'
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'clears feature' do
|
23
|
+
expect(last_response.status).to eq(204)
|
24
|
+
expect(flipper[:my_feature].off?).to be_truthy
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -7,10 +7,9 @@ RSpec.describe Flipper::Api::V1::Actions::Feature do
|
|
7
7
|
|
8
8
|
describe 'get' do
|
9
9
|
context 'enabled feature' do
|
10
|
-
|
11
10
|
before do
|
12
11
|
flipper[:my_feature].enable
|
13
|
-
get '
|
12
|
+
get '/features/my_feature'
|
14
13
|
end
|
15
14
|
|
16
15
|
it 'responds with correct attributes' do
|
@@ -21,7 +20,7 @@ RSpec.describe Flipper::Api::V1::Actions::Feature do
|
|
21
20
|
{
|
22
21
|
'key' => 'boolean',
|
23
22
|
'name' => 'boolean',
|
24
|
-
'value' => true,
|
23
|
+
'value' => 'true',
|
25
24
|
},
|
26
25
|
{
|
27
26
|
'key' => 'groups',
|
@@ -36,14 +35,14 @@ RSpec.describe Flipper::Api::V1::Actions::Feature do
|
|
36
35
|
{
|
37
36
|
'key' => 'percentage_of_actors',
|
38
37
|
'name' => 'percentage_of_actors',
|
39
|
-
'value' =>
|
38
|
+
'value' => nil,
|
40
39
|
},
|
41
40
|
{
|
42
41
|
'key' => 'percentage_of_time',
|
43
42
|
'name' => 'percentage_of_time',
|
44
|
-
'value' =>
|
45
|
-
}
|
46
|
-
]
|
43
|
+
'value' => nil,
|
44
|
+
},
|
45
|
+
],
|
47
46
|
}
|
48
47
|
|
49
48
|
expect(last_response.status).to eq(200)
|
@@ -54,7 +53,7 @@ RSpec.describe Flipper::Api::V1::Actions::Feature do
|
|
54
53
|
context 'disabled feature' do
|
55
54
|
before do
|
56
55
|
flipper[:my_feature].disable
|
57
|
-
get '
|
56
|
+
get '/features/my_feature'
|
58
57
|
end
|
59
58
|
|
60
59
|
it 'responds with correct attributes' do
|
@@ -65,12 +64,12 @@ RSpec.describe Flipper::Api::V1::Actions::Feature do
|
|
65
64
|
{
|
66
65
|
'key' => 'boolean',
|
67
66
|
'name' => 'boolean',
|
68
|
-
'value' =>
|
67
|
+
'value' => nil,
|
69
68
|
},
|
70
69
|
{
|
71
|
-
'key'=> 'groups',
|
72
|
-
'name'=> 'group',
|
73
|
-
'value'=> [],
|
70
|
+
'key' => 'groups',
|
71
|
+
'name' => 'group',
|
72
|
+
'value' => [],
|
74
73
|
},
|
75
74
|
{
|
76
75
|
'key' => 'actors',
|
@@ -80,14 +79,14 @@ RSpec.describe Flipper::Api::V1::Actions::Feature do
|
|
80
79
|
{
|
81
80
|
'key' => 'percentage_of_actors',
|
82
81
|
'name' => 'percentage_of_actors',
|
83
|
-
'value'=>
|
82
|
+
'value' => nil,
|
84
83
|
},
|
85
84
|
{
|
86
85
|
'key' => 'percentage_of_time',
|
87
86
|
'name' => 'percentage_of_time',
|
88
|
-
'value' =>
|
89
|
-
}
|
90
|
-
]
|
87
|
+
'value' => nil,
|
88
|
+
},
|
89
|
+
],
|
91
90
|
}
|
92
91
|
|
93
92
|
expect(last_response.status).to eq(200)
|
@@ -97,15 +96,17 @@ RSpec.describe Flipper::Api::V1::Actions::Feature do
|
|
97
96
|
|
98
97
|
context 'feature does not exist' do
|
99
98
|
before do
|
100
|
-
get '
|
99
|
+
get '/features/not_a_feature'
|
101
100
|
end
|
102
101
|
|
103
|
-
it '
|
102
|
+
it '404s' do
|
104
103
|
expect(last_response.status).to eq(404)
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
104
|
+
expected = {
|
105
|
+
'code' => 1,
|
106
|
+
'message' => 'Feature not found.',
|
107
|
+
'more_info' => api_error_code_reference_url,
|
108
|
+
}
|
109
|
+
expect(json_response).to eq(expected)
|
109
110
|
end
|
110
111
|
end
|
111
112
|
end
|
@@ -115,7 +116,7 @@ RSpec.describe Flipper::Api::V1::Actions::Feature do
|
|
115
116
|
it 'deletes feature' do
|
116
117
|
flipper[:my_feature].enable
|
117
118
|
expect(flipper.features.map(&:key)).to include('my_feature')
|
118
|
-
delete '
|
119
|
+
delete '/features/my_feature'
|
119
120
|
expect(last_response.status).to eq(204)
|
120
121
|
expect(flipper.features.map(&:key)).not_to include('my_feature')
|
121
122
|
end
|
@@ -123,15 +124,12 @@ RSpec.describe Flipper::Api::V1::Actions::Feature do
|
|
123
124
|
|
124
125
|
context 'feature not found' do
|
125
126
|
before do
|
126
|
-
delete '
|
127
|
+
delete '/features/my_feature'
|
127
128
|
end
|
128
129
|
|
129
|
-
it '
|
130
|
-
expect(last_response.status).to eq(
|
131
|
-
|
132
|
-
|
133
|
-
it 'returns formatted error response body' do
|
134
|
-
expect(json_response).to eq({ "code" => 1, "message" => "Feature not found.", "more_info" => "https://github.com/jnunemaker/flipper/tree/master/docs/api#error-code-reference" })
|
130
|
+
it 'responds with 204' do
|
131
|
+
expect(last_response.status).to eq(204)
|
132
|
+
expect(flipper.features.map(&:key)).not_to include('my_feature')
|
135
133
|
end
|
136
134
|
end
|
137
135
|
end
|