Commit f2698879 authored by Jason Goodman's avatar Jason Goodman Committed by Nathan Friend

Map feature flag userWithId strategy parameters between BE and FE

Add feature specs for new version feature flags
parent d4066b09
...@@ -69,7 +69,7 @@ export default { ...@@ -69,7 +69,7 @@ export default {
}; };
</script> </script>
<template> <template>
<gl-new-dropdown> <gl-new-dropdown class="js-new-environments-dropdown">
<template #button-content> <template #button-content>
<span class="d-md-none mr-1"> <span class="d-md-none mr-1">
{{ $options.translations.addEnvironmentsLabel }} {{ $options.translations.addEnvironmentsLabel }}
......
...@@ -161,16 +161,30 @@ const mapStrategyScopesToView = scopes => ...@@ -161,16 +161,30 @@ const mapStrategyScopesToView = scopes =>
environmentScope: s.environment_scope, environmentScope: s.environment_scope,
})); }));
const mapStrategiesParametersToViewModel = params => {
if (params.userIds) {
return { ...params, userIds: params.userIds.split(',').join(', ') };
}
return params;
};
export const mapStrategiesToViewModel = strategiesFromRails => export const mapStrategiesToViewModel = strategiesFromRails =>
(strategiesFromRails || []).map(s => ({ (strategiesFromRails || []).map(s => ({
id: s.id, id: s.id,
name: s.name, name: s.name,
parameters: s.parameters, parameters: mapStrategiesParametersToViewModel(s.parameters),
// eslint-disable-next-line no-underscore-dangle // eslint-disable-next-line no-underscore-dangle
shouldBeDestroyed: Boolean(s._destroy), shouldBeDestroyed: Boolean(s._destroy),
scopes: mapStrategyScopesToView(s.scopes), scopes: mapStrategyScopesToView(s.scopes),
})); }));
const mapStrategiesParametersToRails = params => {
if (params.userIds) {
return { ...params, userIds: params.userIds.split(', ').join(',') };
}
return params;
};
export const mapStrategiesToRails = params => ({ export const mapStrategiesToRails = params => ({
operations_feature_flag: { operations_feature_flag: {
name: params.name, name: params.name,
...@@ -179,7 +193,7 @@ export const mapStrategiesToRails = params => ({ ...@@ -179,7 +193,7 @@ export const mapStrategiesToRails = params => ({
strategies_attributes: (params.strategies || []).map(s => ({ strategies_attributes: (params.strategies || []).map(s => ({
id: s.id, id: s.id,
name: s.name, name: s.name,
parameters: s.parameters, parameters: mapStrategiesParametersToRails(s.parameters),
_destroy: s.shouldBeDestroyed, _destroy: s.shouldBeDestroyed,
scopes_attributes: mapStrategyScopesToRails(s.scopes || []), scopes_attributes: mapStrategyScopesToRails(s.scopes || []),
})), })),
......
...@@ -12,123 +12,144 @@ describe 'User creates feature flag', :js do ...@@ -12,123 +12,144 @@ describe 'User creates feature flag', :js do
project.add_developer(user) project.add_developer(user)
stub_licensed_features(feature_flags: true) stub_licensed_features(feature_flags: true)
stub_feature_flags(feature_flag_permissions: false) stub_feature_flags(feature_flag_permissions: false)
stub_feature_flags(feature_flags_new_version: false)
sign_in(user) sign_in(user)
end end
context 'when creates without changing scopes' do 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
context 'with new version flags disabled' do
before do before do
visit(new_project_feature_flag_path(project)) stub_feature_flags(feature_flags_new_version: false)
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 end
it 'shows the created feature flag' do context 'when creates without changing scopes' do
within_feature_flag_row(1) do before do
expect(page.find('.feature-flag-name')).to have_content('ci_live_trace') visit(new_project_feature_flag_path(project))
expect(page).to have_css('.js-feature-flag-status button.is-checked') 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
within_feature_flag_scopes do it 'shows the created feature flag' do
expect(page.find('.badge:nth-child(1)')).to have_content('*') within_feature_flag_row(1) do
expect(page.find('.badge:nth-child(1)')['class']).to include('badge-active') expect(page.find('.feature-flag-name')).to have_content('ci_live_trace')
expect(page).to have_css('.js-feature-flag-status button.is-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-active')
end
end end
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 context 'when creates with disabling the default scope' do
before do before do
visit(new_project_feature_flag_path(project)) visit(new_project_feature_flag_path(project))
set_feature_flag_info('ci_live_trace', 'For live trace') set_feature_flag_info('ci_live_trace', 'For live trace')
within_scope_row(1) do within_scope_row(1) do
within_status { find('.project-feature-toggle').click } within_status { find('.project-feature-toggle').click }
end end
click_button 'Create feature flag' click_button 'Create feature flag'
end end
it 'shows the created feature flag' do it 'shows the created feature flag' do
within_feature_flag_row(1) do within_feature_flag_row(1) do
expect(page.find('.feature-flag-name')).to have_content('ci_live_trace') expect(page.find('.feature-flag-name')).to have_content('ci_live_trace')
expect(page).to have_css('.js-feature-flag-status button.is-checked') expect(page).to have_css('.js-feature-flag-status button.is-checked')
within_feature_flag_scopes do within_feature_flag_scopes do
expect(page.find('.badge:nth-child(1)')).to have_content('*') expect(page.find('.badge:nth-child(1)')).to have_content('*')
expect(page.find('.badge:nth-child(1)')['class']).to include('badge-inactive') expect(page.find('.badge:nth-child(1)')['class']).to include('badge-inactive')
end
end end
end end
end end
end
context 'when creates with an additional scope' do context 'when creates with an additional scope' do
before do before do
visit(new_project_feature_flag_path(project)) visit(new_project_feature_flag_path(project))
set_feature_flag_info('mr_train', '') set_feature_flag_info('mr_train', '')
within_scope_row(2) do within_scope_row(2) do
within_environment_spec do within_environment_spec do
find('.js-env-input').set("review/*") find('.js-env-input').set("review/*")
find('.js-create-button').click find('.js-create-button').click
end
end end
end
within_scope_row(2) do within_scope_row(2) do
within_status { find('.project-feature-toggle').click } within_status { find('.project-feature-toggle').click }
end end
click_button 'Create feature flag'
end
it 'shows the created feature flag' do click_button 'Create feature flag'
within_feature_flag_row(1) do end
expect(page.find('.feature-flag-name')).to have_content('mr_train')
expect(page).to have_css('.js-feature-flag-status button.is-checked')
within_feature_flag_scopes do it 'shows the created feature flag' do
expect(page.find('.badge:nth-child(1)')).to have_content('*') within_feature_flag_row(1) do
expect(page.find('.badge:nth-child(1)')['class']).to include('badge-active') expect(page.find('.feature-flag-name')).to have_content('mr_train')
expect(page.find('.badge:nth-child(2)')).to have_content('review/*') expect(page).to have_css('.js-feature-flag-status button.is-checked')
expect(page.find('.badge:nth-child(2)')['class']).to include('badge-active')
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-active')
expect(page.find('.badge:nth-child(2)')).to have_content('review/*')
expect(page.find('.badge:nth-child(2)')['class']).to include('badge-active')
end
end end
end end
end end
end
context 'when searches an environment name for scope creation' do context 'when searches an environment name for scope creation' do
let!(:environment) { create(:environment, name: 'production', project: project) } let!(:environment) { create(:environment, name: 'production', project: project) }
before do before do
visit(new_project_feature_flag_path(project)) visit(new_project_feature_flag_path(project))
set_feature_flag_info('mr_train', '') set_feature_flag_info('mr_train', '')
within_scope_row(2) do within_scope_row(2) do
within_environment_spec do within_environment_spec do
find('.js-env-input').set('prod') find('.js-env-input').set('prod')
click_button 'production' click_button 'production'
end
end end
end
click_button 'Create feature flag' click_button 'Create feature flag'
end 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(page).to have_css('.js-feature-flag-status button.is-checked')
within_feature_flag_scopes do it 'shows the created feature flag' do
expect(page.find('.badge:nth-child(1)')).to have_content('*') within_feature_flag_row(1) do
expect(page.find('.badge:nth-child(1)')['class']).to include('badge-active') expect(page.find('.feature-flag-name')).to have_content('mr_train')
expect(page.find('.badge:nth-child(2)')).to have_content('production') expect(page).to have_css('.js-feature-flag-status button.is-checked')
expect(page.find('.badge:nth-child(2)')['class']).to include('badge-inactive')
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-active')
expect(page.find('.badge:nth-child(2)')).to have_content('production')
expect(page.find('.badge:nth-child(2)')['class']).to include('badge-inactive')
end
end end
end end
end end
...@@ -140,4 +161,16 @@ describe 'User creates feature flag', :js do ...@@ -140,4 +161,16 @@ 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
...@@ -378,7 +378,23 @@ describe('feature flags helpers spec', () => { ...@@ -378,7 +378,23 @@ describe('feature flags helpers spec', () => {
}, },
]); ]);
}); });
it('inserts spaces between user ids', () => {
const strategy = _.first(
mapStrategiesToViewModel([
{
id: '1',
name: 'userWithId',
parameters: { userIds: 'user1,user2,user3' },
scopes: [],
},
]),
);
expect(strategy.parameters).toEqual({ userIds: 'user1, user2, user3' });
});
}); });
describe('mapStrategiesToRails', () => { describe('mapStrategiesToRails', () => {
it('should map rails casing to view model casing', () => { it('should map rails casing to view model casing', () => {
expect( expect(
...@@ -425,6 +441,7 @@ describe('feature flags helpers spec', () => { ...@@ -425,6 +441,7 @@ describe('feature flags helpers spec', () => {
}, },
}); });
}); });
it('should insert a default * scope if there are none', () => { it('should insert a default * scope if there are none', () => {
expect( expect(
mapStrategiesToRails({ mapStrategiesToRails({
...@@ -460,5 +477,24 @@ describe('feature flags helpers spec', () => { ...@@ -460,5 +477,24 @@ describe('feature flags helpers spec', () => {
}, },
}); });
}); });
it('removes white space between user ids', () => {
const result = mapStrategiesToRails({
name: 'test',
version: NEW_VERSION_FLAG,
strategies: [
{
id: '1',
name: 'userWithId',
parameters: { userIds: 'user1, user2, user3' },
scopes: [],
},
],
});
const strategyAttrs = _.first(result.operations_feature_flag.strategies_attributes);
expect(strategyAttrs.parameters).toEqual({ userIds: 'user1,user2,user3' });
});
}); });
}); });
...@@ -32,6 +32,12 @@ module FeatureFlagHelpers ...@@ -32,6 +32,12 @@ module FeatureFlagHelpers
end end
end end
def within_strategy_row(index)
within ".feature-flags-form > fieldset > div:nth-child(#{index + 3})" do
yield
end
end
def within_environment_spec def within_environment_spec
within '.table-section:nth-child(1)' do within '.table-section:nth-child(1)' do
yield yield
...@@ -49,4 +55,11 @@ module FeatureFlagHelpers ...@@ -49,4 +55,11 @@ module FeatureFlagHelpers
yield yield
end end
end end
def expect_user_to_see_feature_flags_index_page
expect(page).to have_css('h3.page-title', text: 'Feature Flags')
expect(page).to have_text('All')
expect(page).to have_text('Enabled')
expect(page).to have_text('Disabled')
end
end end
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