Commit d5fdf995 authored by Shinya Maeda's avatar Shinya Maeda

Merge branch 'move-ff-api-controllers-to-core' into 'master'

Move Feature Flag Api and Controllers to Core RUN AS-IF-FOSS

See merge request gitlab-org/gitlab!44093
parents c4372c85 37d36eb7
...@@ -154,8 +154,6 @@ Performance/Count: ...@@ -154,8 +154,6 @@ Performance/Count:
- 'app/helpers/groups_helper.rb' - 'app/helpers/groups_helper.rb'
- 'app/services/merge_requests/add_context_service.rb' - 'app/services/merge_requests/add_context_service.rb'
- 'ee/lib/gitlab/graphql/aggregations/epics/epic_node.rb' - 'ee/lib/gitlab/graphql/aggregations/epics/epic_node.rb'
- 'ee/spec/controllers/projects/feature_flags_controller_spec.rb'
- 'ee/spec/requests/api/feature_flags_spec.rb'
- 'lib/gitlab/sidekiq_status.rb' - 'lib/gitlab/sidekiq_status.rb'
- 'spec/lib/gitlab/conflict/file_spec.rb' - 'spec/lib/gitlab/conflict/file_spec.rb'
- 'spec/lib/gitlab/git/tree_spec.rb' - 'spec/lib/gitlab/git/tree_spec.rb'
...@@ -167,7 +165,6 @@ Performance/Count: ...@@ -167,7 +165,6 @@ Performance/Count:
Performance/Detect: Performance/Detect:
Exclude: Exclude:
- 'ee/spec/controllers/projects/dependencies_controller_spec.rb' - 'ee/spec/controllers/projects/dependencies_controller_spec.rb'
- 'ee/spec/controllers/projects/feature_flags_controller_spec.rb'
- 'spec/lib/gitlab/git/tree_spec.rb' - 'spec/lib/gitlab/git/tree_spec.rb'
- 'spec/lib/gitlab/import_export/project/tree_restorer_spec.rb' - 'spec/lib/gitlab/import_export/project/tree_restorer_spec.rb'
- 'spec/models/event_spec.rb' - 'spec/models/event_spec.rb'
......
...@@ -9,6 +9,7 @@ module UserCalloutsHelper ...@@ -9,6 +9,7 @@ module UserCalloutsHelper
TABS_POSITION_HIGHLIGHT = 'tabs_position_highlight' TABS_POSITION_HIGHLIGHT = 'tabs_position_highlight'
WEBHOOKS_MOVED = 'webhooks_moved' WEBHOOKS_MOVED = 'webhooks_moved'
CUSTOMIZE_HOMEPAGE = 'customize_homepage' CUSTOMIZE_HOMEPAGE = 'customize_homepage'
FEATURE_FLAGS_NEW_VERSION = 'feature_flags_new_version'
def show_admin_integrations_moved? def show_admin_integrations_moved?
!user_dismissed?(ADMIN_INTEGRATIONS_MOVED) !user_dismissed?(ADMIN_INTEGRATIONS_MOVED)
...@@ -50,6 +51,10 @@ module UserCalloutsHelper ...@@ -50,6 +51,10 @@ module UserCalloutsHelper
customize_homepage && !user_dismissed?(CUSTOMIZE_HOMEPAGE) customize_homepage && !user_dismissed?(CUSTOMIZE_HOMEPAGE)
end end
def show_feature_flags_new_version?
!user_dismissed?(FEATURE_FLAGS_NEW_VERSION)
end
private private
def user_dismissed?(feature_name, ignore_dismissal_earlier_than = nil) def user_dismissed?(feature_name, ignore_dismissal_earlier_than = nil)
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
feature_flags_path: project_feature_flags_path(@project), feature_flags_path: project_feature_flags_path(@project),
environments_endpoint: search_project_environments_path(@project, format: :json), environments_endpoint: search_project_environments_path(@project, format: :json),
user_callouts_path: user_callouts_path, user_callouts_path: user_callouts_path,
user_callout_id: UserCalloutsHelper::FEATURE_FLAGS_NEW_VERISION, user_callout_id: UserCalloutsHelper::FEATURE_FLAGS_NEW_VERSION,
show_user_callout: show_feature_flags_new_version?.to_s, show_user_callout: show_feature_flags_new_version?.to_s,
strategy_type_docs_page_path: help_page_path('operations/feature_flags', anchor: 'feature-flag-strategies'), strategy_type_docs_page_path: help_page_path('operations/feature_flags', anchor: 'feature-flag-strategies'),
environments_scope_docs_path: help_page_path('ci/environments', anchor: 'scoping-environments-with-specs'), environments_scope_docs_path: help_page_path('ci/environments', anchor: 'scoping-environments-with-specs'),
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
feature_flags_path: project_feature_flags_path(@project), feature_flags_path: project_feature_flags_path(@project),
environments_endpoint: search_project_environments_path(@project, format: :json), environments_endpoint: search_project_environments_path(@project, format: :json),
user_callouts_path: user_callouts_path, user_callouts_path: user_callouts_path,
user_callout_id: UserCalloutsHelper::FEATURE_FLAGS_NEW_VERISION, user_callout_id: UserCalloutsHelper::FEATURE_FLAGS_NEW_VERSION,
show_user_callout: show_feature_flags_new_version?.to_s, show_user_callout: show_feature_flags_new_version?.to_s,
strategy_type_docs_page_path: help_page_path('operations/feature_flags', anchor: 'feature-flag-strategies'), strategy_type_docs_page_path: help_page_path('operations/feature_flags', anchor: 'feature-flag-strategies'),
environments_scope_docs_path: help_page_path('ci/environments', anchor: 'scoping-environments-with-specs'), environments_scope_docs_path: help_page_path('ci/environments', anchor: 'scoping-environments-with-specs'),
......
...@@ -13,7 +13,6 @@ module EE ...@@ -13,7 +13,6 @@ module EE
ACCOUNT_RECOVERY_REGULAR_CHECK = 'account_recovery_regular_check' ACCOUNT_RECOVERY_REGULAR_CHECK = 'account_recovery_regular_check'
ACTIVE_USER_COUNT_THRESHOLD = 'active_user_count_threshold' ACTIVE_USER_COUNT_THRESHOLD = 'active_user_count_threshold'
PERSONAL_ACCESS_TOKEN_EXPIRY = 'personal_access_token_expiry' PERSONAL_ACCESS_TOKEN_EXPIRY = 'personal_access_token_expiry'
FEATURE_FLAGS_NEW_VERISION = 'feature_flags_new_version'
def show_canary_deployment_callout?(project) def show_canary_deployment_callout?(project)
!user_dismissed?(CANARY_DEPLOYMENT) && !user_dismissed?(CANARY_DEPLOYMENT) &&
...@@ -90,10 +89,6 @@ module EE ...@@ -90,10 +89,6 @@ module EE
!user_dismissed?(PERSONAL_ACCESS_TOKEN_EXPIRY, 1.week.ago) !user_dismissed?(PERSONAL_ACCESS_TOKEN_EXPIRY, 1.week.ago)
end end
def show_feature_flags_new_version?
!user_dismissed?(FEATURE_FLAGS_NEW_VERISION)
end
private private
def hashed_storage_enabled? def hashed_storage_enabled?
......
...@@ -19,9 +19,6 @@ module EE ...@@ -19,9 +19,6 @@ module EE
mount ::API::EpicLinks mount ::API::EpicLinks
mount ::API::Epics mount ::API::Epics
mount ::API::ElasticsearchIndexedNamespaces mount ::API::ElasticsearchIndexedNamespaces
mount ::API::FeatureFlags
mount ::API::FeatureFlagsUserLists
mount ::API::FeatureFlagScopes
mount ::API::Geo mount ::API::Geo
mount ::API::GeoReplication mount ::API::GeoReplication
mount ::API::GeoNodes mount ::API::GeoNodes
......
...@@ -14,59 +14,6 @@ RSpec.describe 'User creates feature flag', :js do ...@@ -14,59 +14,6 @@ RSpec.describe 'User creates feature flag', :js do
sign_in(user) sign_in(user)
end end
it 'user creates a flag enabled for user ids' do
visit(new_project_feature_flag_path(project))
set_feature_flag_info('test_feature', 'Test feature')
within_strategy_row(1) do
select 'User IDs', from: 'Type'
fill_in 'User IDs', with: 'user1, user2'
environment_plus_button.click
environment_search_input.set('production')
environment_search_results.first.click
end
click_button 'Create feature flag'
expect_user_to_see_feature_flags_index_page
expect(page).to have_text('test_feature')
end
it 'user creates a flag with default environment scopes' do
visit(new_project_feature_flag_path(project))
set_feature_flag_info('test_flag', 'Test flag')
within_strategy_row(1) do
select 'All users', from: 'Type'
end
click_button 'Create feature flag'
expect_user_to_see_feature_flags_index_page
expect(page).to have_text('test_flag')
edit_feature_flag_button.click
within_strategy_row(1) do
expect(page).to have_text('All users')
expect(page).to have_text('All environments')
end
end
it 'removes the correct strategy when a strategy is deleted' do
visit(new_project_feature_flag_path(project))
click_button 'Add strategy'
within_strategy_row(1) do
select 'All users', from: 'Type'
end
within_strategy_row(2) do
select 'Percent of users', from: 'Type'
end
within_strategy_row(1) do
delete_strategy_button.click
end
within_strategy_row(1) do
expect(page).to have_select('Type', selected: 'Percent of users')
end
end
context 'with new version flags disabled' do context 'with new version flags disabled' do
before do before do
stub_feature_flags(feature_flags_new_version: false) stub_feature_flags(feature_flags_new_version: false)
...@@ -80,109 +27,12 @@ RSpec.describe 'User creates feature flag', :js do ...@@ -80,109 +27,12 @@ RSpec.describe 'User creates feature flag', :js do
expect(page).to have_current_path(project_feature_flags_path(project)) expect(page).to have_current_path(project_feature_flags_path(project))
end end
it 'shows the created feature flag' do
within_feature_flag_row(1) do
expect(page.find('.feature-flag-name')).to have_content('ci_live_trace')
expect_status_toggle_button_to_be_checked
within_feature_flag_scopes do
expect(page.find('[data-qa-selector="feature-flag-scope-info-badge"]:nth-child(1)')).to have_content('*')
end
end
end
it 'records audit event' do it 'records audit event' do
visit(project_audit_events_path(project)) visit(project_audit_events_path(project))
expect(page).to have_text("Created feature flag ci_live_trace with description \"For live trace\".") expect(page).to have_text("Created feature flag ci_live_trace with description \"For live trace\".")
end end
end end
context 'when creates with disabling the default scope' do
before do
visit(new_project_feature_flag_path(project))
set_feature_flag_info('ci_live_trace', 'For live trace')
within_scope_row(1) do
within_status { find('.project-feature-toggle').click }
end
click_button 'Create feature flag'
end
it 'shows the created feature flag' do
within_feature_flag_row(1) do
expect(page.find('.feature-flag-name')).to have_content('ci_live_trace')
expect_status_toggle_button_to_be_checked
within_feature_flag_scopes do
expect(page.find('[data-qa-selector="feature-flag-scope-muted-badge"]:nth-child(1)')).to have_content('*')
end
end
end
end
context 'when creates with an additional scope' do
before do
visit(new_project_feature_flag_path(project))
set_feature_flag_info('mr_train', '')
within_scope_row(2) do
within_environment_spec do
find('.js-env-search > input').set("review/*")
find('.js-create-button').click
end
end
within_scope_row(2) do
within_status { find('.project-feature-toggle').click }
end
click_button 'Create feature flag'
end
it 'shows the created feature flag' do
within_feature_flag_row(1) do
expect(page.find('.feature-flag-name')).to have_content('mr_train')
expect_status_toggle_button_to_be_checked
within_feature_flag_scopes do
expect(page.find('[data-qa-selector="feature-flag-scope-info-badge"]:nth-child(1)')).to have_content('*')
expect(page.find('[data-qa-selector="feature-flag-scope-info-badge"]:nth-child(2)')).to have_content('review/*')
end
end
end
end
context 'when searches an environment name for scope creation' do
let!(:environment) { create(:environment, name: 'production', project: project) }
before do
visit(new_project_feature_flag_path(project))
set_feature_flag_info('mr_train', '')
within_scope_row(2) do
within_environment_spec do
find('.js-env-search > input').set('prod')
click_button 'production'
end
end
click_button 'Create feature flag'
end
it 'shows the created feature flag' do
within_feature_flag_row(1) do
expect(page.find('.feature-flag-name')).to have_content('mr_train')
expect_status_toggle_button_to_be_checked
within_feature_flag_scopes do
expect(page.find('[data-qa-selector="feature-flag-scope-info-badge"]:nth-child(1)')).to have_content('*')
expect(page.find('[data-qa-selector="feature-flag-scope-muted-badge"]:nth-child(2)')).to have_content('production')
end
end
end
end
end end
private private
...@@ -191,16 +41,4 @@ RSpec.describe 'User creates feature flag', :js do ...@@ -191,16 +41,4 @@ RSpec.describe 'User creates feature flag', :js do
fill_in 'Name', with: name fill_in 'Name', with: name
fill_in 'Description', with: description fill_in 'Description', with: description
end end
def environment_plus_button
find('.js-new-environments-dropdown')
end
def environment_search_input
find('.js-new-environments-dropdown input')
end
def environment_search_results
all('.js-new-environments-dropdown button.dropdown-item')
end
end end
...@@ -25,10 +25,6 @@ RSpec.describe 'User deletes feature flag', :js do ...@@ -25,10 +25,6 @@ RSpec.describe 'User deletes feature flag', :js do
expect(page).to have_current_path(project_feature_flags_path(project)) expect(page).to have_current_path(project_feature_flags_path(project))
end end
it 'user does not see feature flag' do
expect(page).to have_no_content('ci_live_trace')
end
it 'records audit event' do it 'records audit event' do
visit(project_audit_events_path(project)) visit(project_audit_events_path(project))
......
...@@ -28,58 +28,6 @@ RSpec.describe 'User sees feature flag list', :js do ...@@ -28,58 +28,6 @@ RSpec.describe 'User sees feature flag list', :js do
stub_feature_flags(feature_flags_legacy_read_only_override: false) stub_feature_flags(feature_flags_legacy_read_only_override: false)
end end
it 'user sees the first flag' do
visit(project_feature_flags_path(project))
within_feature_flag_row(1) do
expect(page.find('.js-feature-flag-id')).to have_content('^1')
expect(page.find('.feature-flag-name')).to have_content('ci_live_trace')
expect_status_toggle_button_not_to_be_checked
within_feature_flag_scopes do
expect(page.find('[data-qa-selector="feature-flag-scope-muted-badge"]:nth-child(1)')).to have_content('*')
expect(page.find('[data-qa-selector="feature-flag-scope-info-badge"]:nth-child(2)')).to have_content('review/*')
end
end
end
it 'user sees the second flag' do
visit(project_feature_flags_path(project))
within_feature_flag_row(2) do
expect(page.find('.js-feature-flag-id')).to have_content('^2')
expect(page.find('.feature-flag-name')).to have_content('drop_legacy_artifacts')
expect_status_toggle_button_not_to_be_checked
within_feature_flag_scopes do
expect(page.find('[data-qa-selector="feature-flag-scope-muted-badge"]:nth-child(1)')).to have_content('*')
end
end
end
it 'user sees the third flag' do
visit(project_feature_flags_path(project))
within_feature_flag_row(3) do
expect(page.find('.js-feature-flag-id')).to have_content('^3')
expect(page.find('.feature-flag-name')).to have_content('mr_train')
expect_status_toggle_button_to_be_checked
within_feature_flag_scopes do
expect(page.find('[data-qa-selector="feature-flag-scope-info-badge"]:nth-child(1)')).to have_content('*')
expect(page.find('[data-qa-selector="feature-flag-scope-muted-badge"]:nth-child(2)')).to have_content('production')
end
end
end
it 'user sees the status toggle disabled' do
visit(project_feature_flags_path(project))
within_feature_flag_row(1) do
expect_status_toggle_button_to_be_disabled
end
end
context 'when legacy feature flags are not read-only' do context 'when legacy feature flags are not read-only' do
before do before do
stub_feature_flags(feature_flags_legacy_read_only: false) stub_feature_flags(feature_flags_legacy_read_only: false)
...@@ -150,16 +98,4 @@ RSpec.describe 'User sees feature flag list', :js do ...@@ -150,16 +98,4 @@ RSpec.describe 'User sees feature flag list', :js do
) )
end end
end end
context 'when there are no feature flags' do
before do
visit(project_feature_flags_path(project))
end
it 'shows empty page' do
expect(page).to have_text 'Get started with feature flags'
expect(page).to have_selector('.btn-success', text: 'New feature flag')
expect(page).to have_selector('[data-qa-selector="configure_feature_flags_button"]', text: 'Configure')
end
end
end end
...@@ -20,57 +20,6 @@ RSpec.describe 'User updates feature flag', :js do ...@@ -20,57 +20,6 @@ RSpec.describe 'User updates feature flag', :js do
sign_in(user) sign_in(user)
end end
context 'with a new version feature flag' do
let!(:feature_flag) do
create_flag(project, 'test_flag', false, version: Operations::FeatureFlag.versions['new_version_flag'],
description: 'For testing')
end
let!(:strategy) do
create(:operations_strategy, feature_flag: feature_flag,
name: 'default', parameters: {})
end
let!(:scope) do
create(:operations_scope, strategy: strategy, environment_scope: '*')
end
it 'user adds a second strategy' do
visit(edit_project_feature_flag_path(project, feature_flag))
wait_for_requests
click_button 'Add strategy'
within_strategy_row(2) do
select 'Percent of users', from: 'Type'
fill_in 'Percentage', with: '15'
end
click_button 'Save changes'
edit_feature_flag_button.click
within_strategy_row(1) do
expect(page).to have_text 'All users'
expect(page).to have_text 'All environments'
end
within_strategy_row(2) do
expect(page).to have_text 'Percent of users'
expect(page).to have_field 'Percentage', with: '15'
expect(page).to have_text 'All environments'
end
end
it 'user toggles the flag on' do
visit(edit_project_feature_flag_path(project, feature_flag))
status_toggle_button.click
click_button 'Save changes'
within_feature_flag_row(1) do
expect_status_toggle_button_to_be_checked
end
end
end
context 'with a legacy feature flag' do context 'with a legacy feature flag' do
let!(:feature_flag) do let!(:feature_flag) do
create_flag(project, 'ci_live_trace', true, create_flag(project, 'ci_live_trace', true,
...@@ -86,19 +35,6 @@ RSpec.describe 'User updates feature flag', :js do ...@@ -86,19 +35,6 @@ RSpec.describe 'User updates feature flag', :js do
visit(edit_project_feature_flag_path(project, feature_flag)) visit(edit_project_feature_flag_path(project, feature_flag))
end end
it 'user sees persisted default scope' do
within_scope_row(1) do
within_environment_spec do
expect(page).to have_content('* (All Environments)')
end
within_status do
expect(find('.project-feature-toggle')['aria-label'])
.to eq('Toggle Status: ON')
end
end
end
context 'when user updates the status of a scope' do context 'when user updates the status of a scope' do
before do before do
within_scope_row(2) do within_scope_row(2) do
...@@ -109,20 +45,6 @@ RSpec.describe 'User updates feature flag', :js do ...@@ -109,20 +45,6 @@ RSpec.describe 'User updates feature flag', :js do
expect(page).to have_current_path(project_feature_flags_path(project)) expect(page).to have_current_path(project_feature_flags_path(project))
end end
it 'shows the updated feature flag' do
within_feature_flag_row(1) do
expect(page.find('.feature-flag-name')).to have_content('ci_live_trace')
expect_status_toggle_button_to_be_checked
within_feature_flag_scopes do
expect(page.find('.badge:nth-child(1)')).to have_content('*')
expect(page.find('.badge:nth-child(1)')['class']).to include('badge-info')
expect(page.find('.badge:nth-child(2)')).to have_content('review/*')
expect(page.find('.badge:nth-child(2)')['class']).to include('badge-muted')
end
end
end
it 'records audit event' do it 'records audit event' do
visit(project_audit_events_path(project)) visit(project_audit_events_path(project))
...@@ -145,15 +67,6 @@ RSpec.describe 'User updates feature flag', :js do ...@@ -145,15 +67,6 @@ RSpec.describe 'User updates feature flag', :js do
expect(page).to have_current_path(project_feature_flags_path(project)) expect(page).to have_current_path(project_feature_flags_path(project))
end end
it 'shows the newly created scope' do
within_feature_flag_row(1) do
within_feature_flag_scopes do
expect(page.find('.badge:nth-child(3)')).to have_content('production')
expect(page.find('.badge:nth-child(3)')['class']).to include('badge-muted')
end
end
end
it 'records audit event' do it 'records audit event' do
visit(project_audit_events_path(project)) visit(project_audit_events_path(project))
...@@ -171,15 +84,6 @@ RSpec.describe 'User updates feature flag', :js do ...@@ -171,15 +84,6 @@ RSpec.describe 'User updates feature flag', :js do
expect(page).to have_current_path(project_feature_flags_path(project)) expect(page).to have_current_path(project_feature_flags_path(project))
end end
it 'shows the updated feature flag' do
within_feature_flag_row(1) do
within_feature_flag_scopes do
expect(page).to have_css('.badge:nth-child(1)')
expect(page).not_to have_css('.badge:nth-child(2)')
end
end
end
it 'records audit event' do it 'records audit event' do
visit(project_audit_events_path(project)) visit(project_audit_events_path(project))
...@@ -187,29 +91,5 @@ RSpec.describe 'User updates feature flag', :js do ...@@ -187,29 +91,5 @@ RSpec.describe 'User updates feature flag', :js do
end end
end end
end end
context 'when legacy flags are read-only' do
it 'the user cannot edit the flag' do
visit(edit_project_feature_flag_path(project, feature_flag))
expect(page).to have_text 'This feature flag is read-only, and it will be removed in 14.0.'
expect(page).to have_css('button.js-ff-submit.disabled')
end
end
context 'when legacy flags are read-only, but the override is active for one project' do
it 'the user can edit the flag' do
stub_feature_flags(feature_flags_legacy_read_only_override: project)
visit(edit_project_feature_flag_path(project, feature_flag))
status_toggle_button.click
click_button 'Save changes'
expect(page).to have_current_path(project_feature_flags_path(project))
within_feature_flag_row(1) do
expect_status_toggle_button_not_to_be_checked
end
end
end
end end
end end
...@@ -328,28 +328,6 @@ RSpec.describe EE::UserCalloutsHelper do ...@@ -328,28 +328,6 @@ RSpec.describe EE::UserCalloutsHelper do
end end
end end
describe '.show_feature_flags_new_version?' do
subject { helper.show_feature_flags_new_version? }
let(:user) { create(:user) }
before do
allow(helper).to receive(:current_user).and_return(user)
end
context 'when the feature flags new version info has not been dismissed' do
it { is_expected.to be_truthy }
end
context 'when the feature flags new version has been dismissed' do
before do
create(:user_callout, user: user, feature_name: described_class::FEATURE_FLAGS_NEW_VERISION)
end
it { is_expected.to be_falsy }
end
end
describe '.show_token_expiry_notification?' do describe '.show_token_expiry_notification?' do
subject { helper.show_token_expiry_notification? } subject { helper.show_token_expiry_notification? }
......
...@@ -153,6 +153,9 @@ module API ...@@ -153,6 +153,9 @@ module API
mount ::API::Environments mount ::API::Environments
mount ::API::ErrorTracking mount ::API::ErrorTracking
mount ::API::Events mount ::API::Events
mount ::API::FeatureFlags
mount ::API::FeatureFlagScopes
mount ::API::FeatureFlagsUserLists
mount ::API::Features mount ::API::Features
mount ::API::Files mount ::API::Files
mount ::API::FreezePeriods mount ::API::FreezePeriods
......
...@@ -90,7 +90,7 @@ RSpec.describe Projects::FeatureFlagsController do ...@@ -90,7 +90,7 @@ RSpec.describe Projects::FeatureFlagsController do
end end
it 'matches json schema' do it 'matches json schema' do
is_expected.to match_response_schema('feature_flags', dir: 'ee') is_expected.to match_response_schema('feature_flags')
end end
it 'returns false for active when the feature flag is inactive even if it has an active scope' do it 'returns false for active when the feature flag is inactive even if it has an active scope' do
...@@ -201,7 +201,7 @@ RSpec.describe Projects::FeatureFlagsController do ...@@ -201,7 +201,7 @@ RSpec.describe Projects::FeatureFlagsController do
recorded = ActiveRecord::QueryRecorder.new { subject } recorded = ActiveRecord::QueryRecorder.new { subject }
related_count = recorded.log related_count = recorded.log
.select { |query| query.include?('operations_feature_flag') }.count .count { |query| query.include?('operations_feature_flag') }
expect(related_count).to be_within(5).of(2) expect(related_count).to be_within(5).of(2)
end end
...@@ -263,7 +263,7 @@ RSpec.describe Projects::FeatureFlagsController do ...@@ -263,7 +263,7 @@ RSpec.describe Projects::FeatureFlagsController do
end end
it 'matches json schema' do it 'matches json schema' do
is_expected.to match_response_schema('feature_flag', dir: 'ee') is_expected.to match_response_schema('feature_flag')
end end
it 'routes based on iid' do it 'routes based on iid' do
...@@ -439,7 +439,7 @@ RSpec.describe Projects::FeatureFlagsController do ...@@ -439,7 +439,7 @@ RSpec.describe Projects::FeatureFlagsController do
end end
it 'matches json schema' do it 'matches json schema' do
is_expected.to match_response_schema('feature_flag', dir: 'ee') is_expected.to match_response_schema('feature_flag')
end end
context 'when the same named feature flag has already existed' do context 'when the same named feature flag has already existed' do
...@@ -473,7 +473,7 @@ RSpec.describe Projects::FeatureFlagsController do ...@@ -473,7 +473,7 @@ RSpec.describe Projects::FeatureFlagsController do
expect { subject }.to change { Operations::FeatureFlag.count }.by(1) expect { subject }.to change { Operations::FeatureFlag.count }.by(1)
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('feature_flag', dir: 'ee') expect(response).to match_response_schema('feature_flag')
expect(json_response['active']).to eq(true) expect(json_response['active']).to eq(true)
expect(Operations::FeatureFlag.last.active).to eq(true) expect(Operations::FeatureFlag.last.active).to eq(true)
end end
...@@ -867,7 +867,7 @@ RSpec.describe Projects::FeatureFlagsController do ...@@ -867,7 +867,7 @@ RSpec.describe Projects::FeatureFlagsController do
end end
it 'matches json schema' do it 'matches json schema' do
is_expected.to match_response_schema('feature_flag', dir: 'ee') is_expected.to match_response_schema('feature_flag')
end end
context 'when user is reporter' do context 'when user is reporter' do
...@@ -976,7 +976,7 @@ RSpec.describe Projects::FeatureFlagsController do ...@@ -976,7 +976,7 @@ RSpec.describe Projects::FeatureFlagsController do
end end
it 'matches json schema' do it 'matches json schema' do
is_expected.to match_response_schema('feature_flag', dir: 'ee') is_expected.to match_response_schema('feature_flag')
end end
context 'when updates active' do context 'when updates active' do
...@@ -1008,7 +1008,7 @@ RSpec.describe Projects::FeatureFlagsController do ...@@ -1008,7 +1008,7 @@ RSpec.describe Projects::FeatureFlagsController do
put_request(feature_flag, { active: true }) put_request(feature_flag, { active: true })
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('feature_flag', dir: 'ee') expect(response).to match_response_schema('feature_flag')
expect(json_response['active']).to eq(true) expect(json_response['active']).to eq(true)
expect(feature_flag.reload.active).to eq(true) expect(feature_flag.reload.active).to eq(true)
expect(feature_flag.default_scope.reload.active).to eq(false) expect(feature_flag.default_scope.reload.active).to eq(false)
...@@ -1167,9 +1167,9 @@ RSpec.describe Projects::FeatureFlagsController do ...@@ -1167,9 +1167,9 @@ RSpec.describe Projects::FeatureFlagsController do
}]) }])
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
scope_json = json_response['scopes'].select do |s| scope_json = json_response['scopes'].find do |s|
s['environment_scope'] == 'production' s['environment_scope'] == 'production'
end.first end
expect(scope_json['strategies']).to eq([{ expect(scope_json['strategies']).to eq([{
"name" => "default", "name" => "default",
"parameters" => {} "parameters" => {}
...@@ -1186,9 +1186,9 @@ RSpec.describe Projects::FeatureFlagsController do ...@@ -1186,9 +1186,9 @@ RSpec.describe Projects::FeatureFlagsController do
}]) }])
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
scope_json = json_response['scopes'].select do |s| scope_json = json_response['scopes'].find do |s|
s['environment_scope'] == 'production' s['environment_scope'] == 'production'
end.first end
expect(scope_json['strategies']).to eq([{ expect(scope_json['strategies']).to eq([{
"name" => "gradualRolloutUserId", "name" => "gradualRolloutUserId",
"parameters" => { "parameters" => {
...@@ -1207,9 +1207,9 @@ RSpec.describe Projects::FeatureFlagsController do ...@@ -1207,9 +1207,9 @@ RSpec.describe Projects::FeatureFlagsController do
}]) }])
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
scope_json = json_response['scopes'].select do |s| scope_json = json_response['scopes'].find do |s|
s['environment_scope'] == 'production' s['environment_scope'] == 'production'
end.first end
expect(scope_json['strategies']).to eq([{ expect(scope_json['strategies']).to eq([{
"name" => "userWithId", "name" => "userWithId",
"parameters" => { "userIds" => "sam,fred" } "parameters" => { "userIds" => "sam,fred" }
...@@ -1226,9 +1226,9 @@ RSpec.describe Projects::FeatureFlagsController do ...@@ -1226,9 +1226,9 @@ RSpec.describe Projects::FeatureFlagsController do
}]) }])
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
scope_json = json_response['scopes'].select do |s| scope_json = json_response['scopes'].find do |s|
s['environment_scope'] == 'production' s['environment_scope'] == 'production'
end.first end
expect(scope_json['strategies']).to eq([{ expect(scope_json['strategies']).to eq([{
"name" => "gradualRolloutUserId", "name" => "gradualRolloutUserId",
"parameters" => { "parameters" => {
...@@ -1247,9 +1247,9 @@ RSpec.describe Projects::FeatureFlagsController do ...@@ -1247,9 +1247,9 @@ RSpec.describe Projects::FeatureFlagsController do
}]) }])
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
scope_json = json_response['scopes'].select do |s| scope_json = json_response['scopes'].find do |s|
s['environment_scope'] == 'production' s['environment_scope'] == 'production'
end.first end
expect(scope_json['strategies']).to eq([]) expect(scope_json['strategies']).to eq([])
end end
...@@ -1265,9 +1265,9 @@ RSpec.describe Projects::FeatureFlagsController do ...@@ -1265,9 +1265,9 @@ RSpec.describe Projects::FeatureFlagsController do
}]) }])
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
scope_json = json_response['scopes'].select do |s| scope_json = json_response['scopes'].find do |s|
s['environment_scope'] == 'production' s['environment_scope'] == 'production'
end.first end
expect(scope_json['strategies'].length).to eq(2) expect(scope_json['strategies'].length).to eq(2)
expect(scope_json['strategies']).to include({ expect(scope_json['strategies']).to include({
"name" => "gradualRolloutUserId", "name" => "gradualRolloutUserId",
...@@ -1285,9 +1285,9 @@ RSpec.describe Projects::FeatureFlagsController do ...@@ -1285,9 +1285,9 @@ RSpec.describe Projects::FeatureFlagsController do
put_request(feature_flag, scopes_attributes: [{ id: scope.id }]) put_request(feature_flag, scopes_attributes: [{ id: scope.id }])
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
scope_json = json_response['scopes'].select do |s| scope_json = json_response['scopes'].find do |s|
s['environment_scope'] == 'production' s['environment_scope'] == 'production'
end.first end
expect(scope_json['strategies']).to eq([{ expect(scope_json['strategies']).to eq([{
"name" => "default", "name" => "default",
"parameters" => {} "parameters" => {}
...@@ -1301,9 +1301,9 @@ RSpec.describe Projects::FeatureFlagsController do ...@@ -1301,9 +1301,9 @@ RSpec.describe Projects::FeatureFlagsController do
put_request(feature_flag, scopes_attributes: [{ id: scope.id }]) put_request(feature_flag, scopes_attributes: [{ id: scope.id }])
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
scope_json = json_response['scopes'].select do |s| scope_json = json_response['scopes'].find do |s|
s['environment_scope'] == 'production' s['environment_scope'] == 'production'
end.first end
expect(scope_json['strategies']).to eq([{ expect(scope_json['strategies']).to eq([{
"name" => "gradualRolloutUserId", "name" => "gradualRolloutUserId",
"parameters" => { "groupId" => "default", "percentage" => "10" } "parameters" => { "groupId" => "default", "percentage" => "10" }
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'User creates feature flag', :js do
include FeatureFlagHelpers
let(:user) { create(:user) }
let(:project) { create(:project, namespace: user.namespace) }
before do
project.add_developer(user)
stub_feature_flags(feature_flag_permissions: false)
sign_in(user)
end
it 'user creates a flag enabled for user ids' do
visit(new_project_feature_flag_path(project))
set_feature_flag_info('test_feature', 'Test feature')
within_strategy_row(1) do
select 'User IDs', from: 'Type'
fill_in 'User IDs', with: 'user1, user2'
environment_plus_button.click
environment_search_input.set('production')
environment_search_results.first.click
end
click_button 'Create feature flag'
expect_user_to_see_feature_flags_index_page
expect(page).to have_text('test_feature')
end
it 'user creates a flag with default environment scopes' do
visit(new_project_feature_flag_path(project))
set_feature_flag_info('test_flag', 'Test flag')
within_strategy_row(1) do
select 'All users', from: 'Type'
end
click_button 'Create feature flag'
expect_user_to_see_feature_flags_index_page
expect(page).to have_text('test_flag')
edit_feature_flag_button.click
within_strategy_row(1) do
expect(page).to have_text('All users')
expect(page).to have_text('All environments')
end
end
it 'removes the correct strategy when a strategy is deleted' do
visit(new_project_feature_flag_path(project))
click_button 'Add strategy'
within_strategy_row(1) do
select 'All users', from: 'Type'
end
within_strategy_row(2) do
select 'Percent of users', from: 'Type'
end
within_strategy_row(1) do
delete_strategy_button.click
end
within_strategy_row(1) do
expect(page).to have_select('Type', selected: 'Percent of users')
end
end
context 'with new version flags disabled' do
before do
stub_feature_flags(feature_flags_new_version: false)
end
context 'when creates without changing scopes' do
before do
visit(new_project_feature_flag_path(project))
set_feature_flag_info('ci_live_trace', 'For live trace')
click_button 'Create feature flag'
expect(page).to have_current_path(project_feature_flags_path(project))
end
it 'shows the created feature flag' do
within_feature_flag_row(1) do
expect(page.find('.feature-flag-name')).to have_content('ci_live_trace')
expect_status_toggle_button_to_be_checked
within_feature_flag_scopes do
expect(page.find('[data-qa-selector="feature-flag-scope-info-badge"]:nth-child(1)')).to have_content('*')
end
end
end
end
context 'when creates with disabling the default scope' do
before do
visit(new_project_feature_flag_path(project))
set_feature_flag_info('ci_live_trace', 'For live trace')
within_scope_row(1) do
within_status { find('.project-feature-toggle').click }
end
click_button 'Create feature flag'
end
it 'shows the created feature flag' do
within_feature_flag_row(1) do
expect(page.find('.feature-flag-name')).to have_content('ci_live_trace')
expect_status_toggle_button_to_be_checked
within_feature_flag_scopes do
expect(page.find('[data-qa-selector="feature-flag-scope-muted-badge"]:nth-child(1)')).to have_content('*')
end
end
end
end
context 'when creates with an additional scope' do
before do
visit(new_project_feature_flag_path(project))
set_feature_flag_info('mr_train', '')
within_scope_row(2) do
within_environment_spec do
find('.js-env-search > input').set("review/*")
find('.js-create-button').click
end
end
within_scope_row(2) do
within_status { find('.project-feature-toggle').click }
end
click_button 'Create feature flag'
end
it 'shows the created feature flag' do
within_feature_flag_row(1) do
expect(page.find('.feature-flag-name')).to have_content('mr_train')
expect_status_toggle_button_to_be_checked
within_feature_flag_scopes do
expect(page.find('[data-qa-selector="feature-flag-scope-info-badge"]:nth-child(1)')).to have_content('*')
expect(page.find('[data-qa-selector="feature-flag-scope-info-badge"]:nth-child(2)')).to have_content('review/*')
end
end
end
end
context 'when searches an environment name for scope creation' do
let!(:environment) { create(:environment, name: 'production', project: project) }
before do
visit(new_project_feature_flag_path(project))
set_feature_flag_info('mr_train', '')
within_scope_row(2) do
within_environment_spec do
find('.js-env-search > input').set('prod')
click_button 'production'
end
end
click_button 'Create feature flag'
end
it 'shows the created feature flag' do
within_feature_flag_row(1) do
expect(page.find('.feature-flag-name')).to have_content('mr_train')
expect_status_toggle_button_to_be_checked
within_feature_flag_scopes do
expect(page.find('[data-qa-selector="feature-flag-scope-info-badge"]:nth-child(1)')).to have_content('*')
expect(page.find('[data-qa-selector="feature-flag-scope-muted-badge"]:nth-child(2)')).to have_content('production')
end
end
end
end
end
private
def set_feature_flag_info(name, description)
fill_in 'Name', with: name
fill_in 'Description', with: description
end
def environment_plus_button
find('.js-new-environments-dropdown')
end
def environment_search_input
find('.js-new-environments-dropdown input')
end
def environment_search_results
all('.js-new-environments-dropdown button.dropdown-item')
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'User deletes feature flag', :js do
include FeatureFlagHelpers
let(:user) { create(:user) }
let(:project) { create(:project, namespace: user.namespace) }
let!(:feature_flag) do
create_flag(project, 'ci_live_trace', false,
description: 'For live trace feature')
end
before do
project.add_developer(user)
stub_feature_flags(feature_flag_permissions: false)
sign_in(user)
visit(project_feature_flags_path(project))
find('.js-feature-flag-delete-button').click
click_button('Delete feature flag')
expect(page).to have_current_path(project_feature_flags_path(project))
end
it 'user does not see feature flag' do
expect(page).to have_no_content('ci_live_trace')
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'User sees feature flag list', :js do
include FeatureFlagHelpers
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, namespace: user.namespace) }
before_all do
project.add_developer(user)
end
before do
sign_in(user)
end
context 'with legacy feature flags' do
before do
create_flag(project, 'ci_live_trace', false).tap do |feature_flag|
create_scope(feature_flag, 'review/*', true)
end
create_flag(project, 'drop_legacy_artifacts', false)
create_flag(project, 'mr_train', true).tap do |feature_flag|
create_scope(feature_flag, 'production', false)
end
stub_feature_flags(feature_flags_legacy_read_only_override: false)
end
it 'user sees the first flag' do
visit(project_feature_flags_path(project))
within_feature_flag_row(1) do
expect(page.find('.js-feature-flag-id')).to have_content('^1')
expect(page.find('.feature-flag-name')).to have_content('ci_live_trace')
expect_status_toggle_button_not_to_be_checked
within_feature_flag_scopes do
expect(page.find('[data-qa-selector="feature-flag-scope-muted-badge"]:nth-child(1)')).to have_content('*')
expect(page.find('[data-qa-selector="feature-flag-scope-info-badge"]:nth-child(2)')).to have_content('review/*')
end
end
end
it 'user sees the second flag' do
visit(project_feature_flags_path(project))
within_feature_flag_row(2) do
expect(page.find('.js-feature-flag-id')).to have_content('^2')
expect(page.find('.feature-flag-name')).to have_content('drop_legacy_artifacts')
expect_status_toggle_button_not_to_be_checked
within_feature_flag_scopes do
expect(page.find('[data-qa-selector="feature-flag-scope-muted-badge"]:nth-child(1)')).to have_content('*')
end
end
end
it 'user sees the third flag' do
visit(project_feature_flags_path(project))
within_feature_flag_row(3) do
expect(page.find('.js-feature-flag-id')).to have_content('^3')
expect(page.find('.feature-flag-name')).to have_content('mr_train')
expect_status_toggle_button_to_be_checked
within_feature_flag_scopes do
expect(page.find('[data-qa-selector="feature-flag-scope-info-badge"]:nth-child(1)')).to have_content('*')
expect(page.find('[data-qa-selector="feature-flag-scope-muted-badge"]:nth-child(2)')).to have_content('production')
end
end
end
it 'user sees the status toggle disabled' do
visit(project_feature_flags_path(project))
within_feature_flag_row(1) do
expect_status_toggle_button_to_be_disabled
end
end
context 'when legacy feature flags are not read-only' do
before do
stub_feature_flags(feature_flags_legacy_read_only: false)
end
it 'user updates the status toggle' do
visit(project_feature_flags_path(project))
within_feature_flag_row(1) do
status_toggle_button.click
expect_status_toggle_button_to_be_checked
end
end
end
context 'when legacy feature flags are read-only but the override is active for a project' do
before do
stub_feature_flags(
feature_flags_legacy_read_only: true,
feature_flags_legacy_read_only_override: project
)
end
it 'user updates the status toggle' do
visit(project_feature_flags_path(project))
within_feature_flag_row(1) do
status_toggle_button.click
expect_status_toggle_button_to_be_checked
end
end
end
end
context 'with new version flags' do
before do
create(:operations_feature_flag, :new_version_flag, project: project,
name: 'my_flag', active: false)
end
it 'user updates the status toggle' do
visit(project_feature_flags_path(project))
within_feature_flag_row(1) do
status_toggle_button.click
expect_status_toggle_button_to_be_checked
end
end
end
context 'when there are no feature flags' do
before do
visit(project_feature_flags_path(project))
end
it 'shows empty page' do
expect(page).to have_text 'Get started with feature flags'
expect(page).to have_selector('.btn-success', text: 'New feature flag')
expect(page).to have_selector('[data-qa-selector="configure_feature_flags_button"]', text: 'Configure')
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'User updates feature flag', :js do
include FeatureFlagHelpers
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, namespace: user.namespace) }
before_all do
project.add_developer(user)
end
before do
stub_feature_flags(
feature_flag_permissions: false,
feature_flags_legacy_read_only_override: false
)
sign_in(user)
end
context 'with a new version feature flag' do
let!(:feature_flag) do
create_flag(project, 'test_flag', false, version: Operations::FeatureFlag.versions['new_version_flag'],
description: 'For testing')
end
let!(:strategy) do
create(:operations_strategy, feature_flag: feature_flag,
name: 'default', parameters: {})
end
let!(:scope) do
create(:operations_scope, strategy: strategy, environment_scope: '*')
end
it 'user adds a second strategy' do
visit(edit_project_feature_flag_path(project, feature_flag))
wait_for_requests
click_button 'Add strategy'
within_strategy_row(2) do
select 'Percent of users', from: 'Type'
fill_in 'Percentage', with: '15'
end
click_button 'Save changes'
edit_feature_flag_button.click
within_strategy_row(1) do
expect(page).to have_text 'All users'
expect(page).to have_text 'All environments'
end
within_strategy_row(2) do
expect(page).to have_text 'Percent of users'
expect(page).to have_field 'Percentage', with: '15'
expect(page).to have_text 'All environments'
end
end
it 'user toggles the flag on' do
visit(edit_project_feature_flag_path(project, feature_flag))
status_toggle_button.click
click_button 'Save changes'
within_feature_flag_row(1) do
expect_status_toggle_button_to_be_checked
end
end
end
context 'with a legacy feature flag' do
let!(:feature_flag) do
create_flag(project, 'ci_live_trace', true,
description: 'For live trace feature')
end
let!(:scope) { create_scope(feature_flag, 'review/*', true) }
context 'when legacy flags are editable' do
before do
stub_feature_flags(feature_flags_legacy_read_only: false)
visit(edit_project_feature_flag_path(project, feature_flag))
end
it 'user sees persisted default scope' do
within_scope_row(1) do
within_environment_spec do
expect(page).to have_content('* (All Environments)')
end
within_status do
expect(find('.project-feature-toggle')['aria-label'])
.to eq('Toggle Status: ON')
end
end
end
context 'when user updates the status of a scope' do
before do
within_scope_row(2) do
within_status { find('.project-feature-toggle').click }
end
click_button 'Save changes'
expect(page).to have_current_path(project_feature_flags_path(project))
end
it 'shows the updated feature flag' do
within_feature_flag_row(1) do
expect(page.find('.feature-flag-name')).to have_content('ci_live_trace')
expect_status_toggle_button_to_be_checked
within_feature_flag_scopes do
expect(page.find('.badge:nth-child(1)')).to have_content('*')
expect(page.find('.badge:nth-child(1)')['class']).to include('badge-info')
expect(page.find('.badge:nth-child(2)')).to have_content('review/*')
expect(page.find('.badge:nth-child(2)')['class']).to include('badge-muted')
end
end
end
end
context 'when user adds a new scope' do
before do
within_scope_row(3) do
within_environment_spec do
find('.js-env-search > input').set('production')
find('.js-create-button').click
end
end
click_button 'Save changes'
expect(page).to have_current_path(project_feature_flags_path(project))
end
it 'shows the newly created scope' do
within_feature_flag_row(1) do
within_feature_flag_scopes do
expect(page.find('.badge:nth-child(3)')).to have_content('production')
expect(page.find('.badge:nth-child(3)')['class']).to include('badge-muted')
end
end
end
end
context 'when user deletes a scope' do
before do
within_scope_row(2) do
within_delete { find('.js-delete-scope').click }
end
click_button 'Save changes'
expect(page).to have_current_path(project_feature_flags_path(project))
end
it 'shows the updated feature flag' do
within_feature_flag_row(1) do
within_feature_flag_scopes do
expect(page).to have_css('.badge:nth-child(1)')
expect(page).not_to have_css('.badge:nth-child(2)')
end
end
end
end
end
context 'when legacy flags are read-only' do
it 'the user cannot edit the flag' do
visit(edit_project_feature_flag_path(project, feature_flag))
expect(page).to have_text 'This feature flag is read-only, and it will be removed in 14.0.'
expect(page).to have_css('button.js-ff-submit.disabled')
end
end
context 'when legacy flags are read-only, but the override is active for one project' do
it 'the user can edit the flag' do
stub_feature_flags(feature_flags_legacy_read_only_override: project)
visit(edit_project_feature_flag_path(project, feature_flag))
status_toggle_button.click
click_button 'Save changes'
expect(page).to have_current_path(project_feature_flags_path(project))
within_feature_flag_row(1) do
expect_status_toggle_button_not_to_be_checked
end
end
end
end
end
...@@ -139,4 +139,26 @@ RSpec.describe UserCalloutsHelper do ...@@ -139,4 +139,26 @@ RSpec.describe UserCalloutsHelper do
helper.render_flash_user_callout(:warning, 'foo', 'bar') helper.render_flash_user_callout(:warning, 'foo', 'bar')
end end
end end
describe '.show_feature_flags_new_version?' do
subject { helper.show_feature_flags_new_version? }
let(:user) { create(:user) }
before do
allow(helper).to receive(:current_user).and_return(user)
end
context 'when the feature flags new version info has not been dismissed' do
it { is_expected.to be_truthy }
end
context 'when the feature flags new version has been dismissed' do
before do
create(:user_callout, user: user, feature_name: described_class::FEATURE_FLAGS_NEW_VERSION)
end
it { is_expected.to be_falsy }
end
end
end end
...@@ -58,7 +58,7 @@ RSpec.describe API::FeatureFlagScopes do ...@@ -58,7 +58,7 @@ RSpec.describe API::FeatureFlagScopes do
subject subject
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/feature_flag_detailed_scopes', dir: 'ee') expect(response).to match_response_schema('public_api/v4/feature_flag_detailed_scopes')
expect(json_response.second).to include({ 'name' => 'flag_1', 'active' => true }) expect(json_response.second).to include({ 'name' => 'flag_1', 'active' => true })
expect(json_response.first).to include({ 'name' => 'flag_2', 'active' => true }) expect(json_response.first).to include({ 'name' => 'flag_2', 'active' => true })
end end
...@@ -104,7 +104,7 @@ RSpec.describe API::FeatureFlagScopes do ...@@ -104,7 +104,7 @@ RSpec.describe API::FeatureFlagScopes do
subject subject
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/feature_flag_scopes', dir: 'ee') expect(response).to match_response_schema('public_api/v4/feature_flag_scopes')
expect(json_response.count).to eq(2) expect(json_response.count).to eq(2)
expect(json_response.first['environment_scope']).to eq(feature_flag.scopes[0].environment_scope) expect(json_response.first['environment_scope']).to eq(feature_flag.scopes[0].environment_scope)
expect(json_response.second['environment_scope']).to eq(feature_flag.scopes[1].environment_scope) expect(json_response.second['environment_scope']).to eq(feature_flag.scopes[1].environment_scope)
...@@ -141,7 +141,7 @@ RSpec.describe API::FeatureFlagScopes do ...@@ -141,7 +141,7 @@ RSpec.describe API::FeatureFlagScopes do
subject subject
expect(response).to have_gitlab_http_status(:created) expect(response).to have_gitlab_http_status(:created)
expect(response).to match_response_schema('public_api/v4/feature_flag_scope', dir: 'ee') expect(response).to match_response_schema('public_api/v4/feature_flag_scope')
expect(json_response['environment_scope']).to eq(params[:environment_scope]) expect(json_response['environment_scope']).to eq(params[:environment_scope])
expect(json_response['active']).to eq(params[:active]) expect(json_response['active']).to eq(params[:active])
expect(json_response['strategies']).to eq(Gitlab::Json.parse(params[:strategies])) expect(json_response['strategies']).to eq(Gitlab::Json.parse(params[:strategies]))
...@@ -181,7 +181,7 @@ RSpec.describe API::FeatureFlagScopes do ...@@ -181,7 +181,7 @@ RSpec.describe API::FeatureFlagScopes do
subject subject
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/feature_flag_scope', dir: 'ee') expect(response).to match_response_schema('public_api/v4/feature_flag_scope')
expect(json_response['id']).to eq(scope.id) expect(json_response['id']).to eq(scope.id)
expect(json_response['active']).to eq(scope.active) expect(json_response['active']).to eq(scope.active)
expect(json_response['environment_scope']).to eq(scope.environment_scope) expect(json_response['environment_scope']).to eq(scope.environment_scope)
...@@ -241,7 +241,7 @@ RSpec.describe API::FeatureFlagScopes do ...@@ -241,7 +241,7 @@ RSpec.describe API::FeatureFlagScopes do
subject subject
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/feature_flag_scope', dir: 'ee') expect(response).to match_response_schema('public_api/v4/feature_flag_scope')
expect(json_response['id']).to eq(scope.id) expect(json_response['id']).to eq(scope.id)
expect(json_response['active']).to eq(params[:active]) expect(json_response['active']).to eq(params[:active])
expect(json_response['strategies']).to eq(Gitlab::Json.parse(params[:strategies])) expect(json_response['strategies']).to eq(Gitlab::Json.parse(params[:strategies]))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment