RSpec.describe Flipper::Api::V1::Actions::Features do let(:app) { build_api(flipper) } let(:feature) { build_feature } let(:admin) { double 'Fake Fliper Thing', flipper_id: 10 } describe 'get' do context 'with flipper features' do before do flipper[:my_feature].enable flipper[:my_feature].enable(admin) end it 'responds with correct attributes' do get '/features' expected_response = { 'features' => [ { 'key' => 'my_feature', 'state' => 'on', 'gates' => [ { 'key' => 'boolean', 'name' => 'boolean', 'value' => 'true', }, { 'key' => 'expression', 'name' => 'expression', 'value' => nil, }, { 'key' => 'actors', 'name' => 'actor', 'value' => ['10'], }, { 'key' => 'percentage_of_actors', 'name' => 'percentage_of_actors', 'value' => nil, }, { 'key' => 'percentage_of_time', 'name' => 'percentage_of_time', 'value' => nil, }, { 'key' => 'groups', 'name' => 'group', 'value' => [], }, ], }, ], } expect(last_response.status).to eq(200) expect(json_response).to eq(expected_response) end it 'responds without names when instructed by param' do expected_response = { 'features' => [ { 'key' => 'my_feature', 'state' => 'on', 'gates' => [ { 'key' => 'boolean', 'value' => 'true'}, {"key" => "expression", "value" => nil}, { 'key' => 'actors', 'value' => ['10']}, {'key' => 'percentage_of_actors', 'value' => nil}, { 'key' => 'percentage_of_time', 'value' => nil}, { 'key' => 'groups', 'value' => []}, ], }, ], } get '/features', 'exclude_gate_names' => 'true' expect(last_response.status).to eq(200) expect(json_response).to eq(expected_response) end end context 'with keys specified' do before do flipper[:audit_log].enable flipper[:issues].enable flipper[:search].enable flipper[:stats].disable get '/features', 'keys' => 'search,stats' end it 'responds with correct attributes' do expect(last_response.status).to eq(200) keys = json_response.fetch('features').map { |feature| feature.fetch('key') }.sort expect(keys).to eq(%w(search stats)) end end context 'with keys that are not existing features' do before do flipper[:search].disable flipper[:stats].disable get '/features', 'keys' => 'search,stats,not_a_feature,another_feature_that_does_not_exist' end it 'only returns features that exist' do expect(last_response.status).to eq(200) keys = json_response.fetch('features').map { |feature| feature.fetch('key') }.sort expect(keys).to eq(%w(search stats)) end end context 'with no flipper features' do before do get '/features' end it 'returns empty array for features key' do expected_response = { 'features' => [], } expect(last_response.status).to eq(200) expect(json_response).to eq(expected_response) end end context 'with accept encoding header set to gzip' do before do flipper[:my_feature].enable flipper[:my_feature].enable(admin) end it 'responds with content encoding gzip and correct attributes' do get '/features', {}, 'HTTP_ACCEPT_ENCODING' => 'gzip' expected_response = { 'features' => [ { 'key' => 'my_feature', 'state' => 'on', 'gates' => [ { 'key' => 'boolean', 'name' => 'boolean', 'value' => 'true', }, { 'key' => 'expression', 'name' => 'expression', 'value' => nil, }, { 'key' => 'actors', 'name' => 'actor', 'value' => ['10'], }, { 'key' => 'percentage_of_actors', 'name' => 'percentage_of_actors', 'value' => nil, }, { 'key' => 'percentage_of_time', 'name' => 'percentage_of_time', 'value' => nil, }, { 'key' => 'groups', 'name' => 'group', 'value' => [], }, ], }, ], } expect(last_response["content-encoding"]).to eq('gzip') expect(last_response.status).to eq(200) expect(json_response).to eq(expected_response) end end end describe 'post' do context 'succesful request' do before do post '/features', name: 'my_feature' end it 'responds 200' do expect(last_response.status).to eq(200) end it 'returns decorated feature' do expected_response = { 'key' => 'my_feature', 'state' => 'off', 'gates' => [ { 'key' => 'boolean', 'name' => 'boolean', 'value' => nil, }, { 'key' => 'expression', 'name' => 'expression', 'value' => nil, }, { 'key' => 'actors', 'name' => 'actor', 'value' => [], }, { 'key' => 'percentage_of_actors', 'name' => 'percentage_of_actors', 'value' => nil, }, { 'key' => 'percentage_of_time', 'name' => 'percentage_of_time', 'value' => nil, }, { 'key' => 'groups', 'name' => 'group', 'value' => [], }, ], } expect(json_response).to eq(expected_response) end it 'adds feature' do expect(flipper.features.map(&:key)).to include('my_feature') end it 'does not enable feature' do expect(flipper['my_feature'].enabled?).to be_falsy end end context 'bad request' do before do post '/features' end it 'returns correct status code' do expect(last_response.status).to eq(422) end it 'returns formatted error' do expected = { 'code' => 5, 'message' => 'Required parameter name is missing.', 'more_info' => api_error_code_reference_url, } expect(json_response).to eq(expected) end end end end