Commit ca6263b9 authored by Shinya Maeda's avatar Shinya Maeda

Merge branch 'afontaine/remove-legacy-flags-frontend-edit' into 'master'

Remove Frontend to Edit Legacy Flags [RUN ALL RSPEC] [RUN AS-IF-FOSS]

See merge request gitlab-org/gitlab!64005
parents 6d55b31f 21c7e932
<script> <script>
import { GlAlert, GlLoadingIcon, GlToggle } from '@gitlab/ui'; import { GlAlert, GlLoadingIcon, GlToggle } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex'; import { mapState, mapActions } from 'vuex';
import axios from '~/lib/utils/axios_utils';
import { sprintf, s__ } from '~/locale'; import { sprintf, s__ } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { LEGACY_FLAG } from '../constants';
import FeatureFlagForm from './form.vue'; import FeatureFlagForm from './form.vue';
export default { export default {
...@@ -15,59 +13,29 @@ export default { ...@@ -15,59 +13,29 @@ export default {
FeatureFlagForm, FeatureFlagForm,
}, },
mixins: [glFeatureFlagMixin()], mixins: [glFeatureFlagMixin()],
inject: {
showUserCallout: {},
userCalloutId: {
default: '',
},
userCalloutsPath: {
default: '',
},
},
data() {
return {
userShouldSeeNewFlagAlert: this.showUserCallout,
};
},
translations: {
legacyReadOnlyFlagAlert: s__(
'FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag.',
),
},
computed: { computed: {
...mapState([ ...mapState([
'path', 'path',
'error', 'error',
'name', 'name',
'description', 'description',
'scopes',
'strategies', 'strategies',
'isLoading', 'isLoading',
'hasError', 'hasError',
'iid', 'iid',
'active', 'active',
'version',
]), ]),
title() { title() {
return this.iid return this.iid
? `^${this.iid} ${this.name}` ? `^${this.iid} ${this.name}`
: sprintf(s__('Edit %{name}'), { name: this.name }); : sprintf(s__('Edit %{name}'), { name: this.name });
}, },
deprecated() {
return this.version === LEGACY_FLAG;
},
}, },
created() { created() {
return this.fetchFeatureFlag(); return this.fetchFeatureFlag();
}, },
methods: { methods: {
...mapActions(['updateFeatureFlag', 'fetchFeatureFlag', 'toggleActive']), ...mapActions(['updateFeatureFlag', 'fetchFeatureFlag', 'toggleActive']),
dismissNewVersionFlagAlert() {
this.userShouldSeeNewFlagAlert = false;
axios.post(this.userCalloutsPath, {
feature_name: this.userCalloutId,
});
},
}, },
}; };
</script> </script>
...@@ -76,9 +44,6 @@ export default { ...@@ -76,9 +44,6 @@ export default {
<gl-loading-icon v-if="isLoading" size="xl" class="gl-mt-7" /> <gl-loading-icon v-if="isLoading" size="xl" class="gl-mt-7" />
<template v-else-if="!isLoading && !hasError"> <template v-else-if="!isLoading && !hasError">
<gl-alert v-if="deprecated" variant="warning" :dismissible="false" class="gl-my-5">{{
$options.translations.legacyReadOnlyFlagAlert
}}</gl-alert>
<div class="gl-display-flex gl-align-items-center gl-mb-4 gl-mt-4"> <div class="gl-display-flex gl-align-items-center gl-mb-4 gl-mt-4">
<gl-toggle <gl-toggle
:value="active" :value="active"
...@@ -100,12 +65,10 @@ export default { ...@@ -100,12 +65,10 @@ export default {
<feature-flag-form <feature-flag-form
:name="name" :name="name"
:description="description" :description="description"
:scopes="scopes"
:strategies="strategies" :strategies="strategies"
:cancel-path="path" :cancel-path="path"
:submit-text="__('Save changes')" :submit-text="__('Save changes')"
:active="active" :active="active"
:version="version"
@handleSubmit="(data) => updateFeatureFlag(data)" @handleSubmit="(data) => updateFeatureFlag(data)"
/> />
</template> </template>
......
import Vue from 'vue'; import Vue from 'vue';
import Vuex from 'vuex'; import Vuex from 'vuex';
import { parseBoolean } from '~/lib/utils/common_utils';
import EditFeatureFlag from './components/edit_feature_flag.vue'; import EditFeatureFlag from './components/edit_feature_flag.vue';
import createStore from './store/edit'; import createStore from './store/edit';
...@@ -16,9 +15,6 @@ export default () => { ...@@ -16,9 +15,6 @@ export default () => {
environmentsEndpoint, environmentsEndpoint,
projectId, projectId,
featureFlagIssuesEndpoint, featureFlagIssuesEndpoint,
userCalloutsPath,
userCalloutId,
showUserCallout,
} = el.dataset; } = el.dataset;
return new Vue({ return new Vue({
...@@ -30,9 +26,6 @@ export default () => { ...@@ -30,9 +26,6 @@ export default () => {
environmentsEndpoint, environmentsEndpoint,
projectId, projectId,
featureFlagIssuesEndpoint, featureFlagIssuesEndpoint,
userCalloutsPath,
userCalloutId,
showUserCallout: parseBoolean(showUserCallout),
}, },
render(createElement) { render(createElement) {
return createElement(EditFeatureFlag); return createElement(EditFeatureFlag);
......
...@@ -2,8 +2,7 @@ import createFlash from '~/flash'; ...@@ -2,8 +2,7 @@ import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import { visitUrl } from '~/lib/utils/url_utility'; import { visitUrl } from '~/lib/utils/url_utility';
import { __ } from '~/locale'; import { __ } from '~/locale';
import { NEW_VERSION_FLAG } from '../../constants'; import { mapStrategiesToRails } from '../helpers';
import { mapFromScopesViewModel, mapStrategiesToRails } from '../helpers';
import * as types from './mutation_types'; import * as types from './mutation_types';
/** /**
...@@ -19,12 +18,7 @@ export const updateFeatureFlag = ({ state, dispatch }, params) => { ...@@ -19,12 +18,7 @@ export const updateFeatureFlag = ({ state, dispatch }, params) => {
dispatch('requestUpdateFeatureFlag'); dispatch('requestUpdateFeatureFlag');
axios axios
.put( .put(state.endpoint, mapStrategiesToRails(params))
state.endpoint,
params.version === NEW_VERSION_FLAG
? mapStrategiesToRails(params)
: mapFromScopesViewModel(params),
)
.then(() => { .then(() => {
dispatch('receiveUpdateFeatureFlagSuccess'); dispatch('receiveUpdateFeatureFlagSuccess');
visitUrl(state.path); visitUrl(state.path);
......
import { LEGACY_FLAG } from '../../constants'; import { LEGACY_FLAG } from '../../constants';
import { mapToScopesViewModel, mapStrategiesToViewModel } from '../helpers'; import { mapStrategiesToViewModel } from '../helpers';
import * as types from './mutation_types'; import * as types from './mutation_types';
export default { export default {
...@@ -14,7 +14,6 @@ export default { ...@@ -14,7 +14,6 @@ export default {
state.description = response.description; state.description = response.description;
state.iid = response.iid; state.iid = response.iid;
state.active = response.active; state.active = response.active;
state.scopes = mapToScopesViewModel(response.scopes);
state.strategies = mapStrategiesToViewModel(response.strategies); state.strategies = mapStrategiesToViewModel(response.strategies);
state.version = response.version || LEGACY_FLAG; state.version = response.version || LEGACY_FLAG;
}, },
......
import { isEmpty, uniqueId, isString } from 'lodash'; import { ROLLOUT_STRATEGY_GITLAB_USER_LIST, NEW_VERSION_FLAG } from '../constants';
import {
ROLLOUT_STRATEGY_ALL_USERS,
ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
ROLLOUT_STRATEGY_USER_ID,
ROLLOUT_STRATEGY_GITLAB_USER_LIST,
INTERNAL_ID_PREFIX,
DEFAULT_PERCENT_ROLLOUT,
PERCENT_ROLLOUT_GROUP_ID,
fetchPercentageParams,
fetchUserIdParams,
LEGACY_FLAG,
} from '../constants';
/**
* Converts raw scope objects fetched from the API into an array of scope
* objects that is easier/nicer to bind to in Vue.
* @param {Array} scopesFromRails An array of scope objects fetched from the API
*/
export const mapToScopesViewModel = (scopesFromRails) =>
(scopesFromRails || []).map((s) => {
const percentStrategy = (s.strategies || []).find(
(strat) => strat.name === ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
);
const rolloutPercentage = fetchPercentageParams(percentStrategy) || DEFAULT_PERCENT_ROLLOUT;
const userStrategy = (s.strategies || []).find(
(strat) => strat.name === ROLLOUT_STRATEGY_USER_ID,
);
const rolloutStrategy =
(percentStrategy && percentStrategy.name) ||
(userStrategy && userStrategy.name) ||
ROLLOUT_STRATEGY_ALL_USERS;
const rolloutUserIds = (fetchUserIdParams(userStrategy) || '')
.split(',')
.filter((id) => id)
.join(', ');
return {
id: s.id,
environmentScope: s.environment_scope,
active: Boolean(s.active),
canUpdate: Boolean(s.can_update),
protected: Boolean(s.protected),
rolloutStrategy,
rolloutPercentage,
rolloutUserIds,
// eslint-disable-next-line no-underscore-dangle
shouldBeDestroyed: Boolean(s._destroy),
shouldIncludeUserIds: rolloutUserIds.length > 0 && percentStrategy !== null,
};
});
/**
* Converts the parameters emitted by the Vue component into
* the shape that the Rails API expects.
* @param {Array} scopesFromVue An array of scope objects from the Vue component
*/
export const mapFromScopesViewModel = (params) => {
const scopes = (params.scopes || []).map((s) => {
const parameters = {};
if (s.rolloutStrategy === ROLLOUT_STRATEGY_PERCENT_ROLLOUT) {
parameters.groupId = PERCENT_ROLLOUT_GROUP_ID;
parameters.percentage = s.rolloutPercentage;
} else if (s.rolloutStrategy === ROLLOUT_STRATEGY_USER_ID) {
parameters.userIds = (s.rolloutUserIds || '').replace(/, /g, ',');
}
const userIdParameters = {};
if (s.shouldIncludeUserIds && s.rolloutStrategy !== ROLLOUT_STRATEGY_USER_ID) {
userIdParameters.userIds = (s.rolloutUserIds || '').replace(/, /g, ',');
}
// Strip out any internal IDs
const id = isString(s.id) && s.id.startsWith(INTERNAL_ID_PREFIX) ? undefined : s.id;
const strategies = [
{
name: s.rolloutStrategy,
parameters,
},
];
if (!isEmpty(userIdParameters)) {
strategies.push({ name: ROLLOUT_STRATEGY_USER_ID, parameters: userIdParameters });
}
return {
id,
environment_scope: s.environmentScope,
active: s.active,
can_update: s.canUpdate,
protected: s.protected,
_destroy: s.shouldBeDestroyed,
strategies,
};
});
const model = {
operations_feature_flag: {
name: params.name,
description: params.description,
active: params.active,
scopes_attributes: scopes,
version: LEGACY_FLAG,
},
};
return model;
};
/**
* Creates a new feature flag environment scope object for use
* in a Vue component. An optional parameter can be passed to
* override the property values that are created by default.
*
* @param {Object} overrides An optional object whose
* property values will be used to override the default values.
*
*/
export const createNewEnvironmentScope = (overrides = {}, featureFlagPermissions = false) => {
const defaultScope = {
environmentScope: '',
active: false,
id: uniqueId(INTERNAL_ID_PREFIX),
rolloutStrategy: ROLLOUT_STRATEGY_ALL_USERS,
rolloutPercentage: DEFAULT_PERCENT_ROLLOUT,
rolloutUserIds: '',
};
const newScope = {
...defaultScope,
...overrides,
};
if (featureFlagPermissions) {
newScope.canUpdate = true;
newScope.protected = false;
}
return newScope;
};
const mapStrategyScopesToRails = (scopes) => const mapStrategyScopesToRails = (scopes) =>
scopes.length === 0 scopes.length === 0
...@@ -206,8 +61,8 @@ export const mapStrategiesToRails = (params) => ({ ...@@ -206,8 +61,8 @@ export const mapStrategiesToRails = (params) => ({
operations_feature_flag: { operations_feature_flag: {
name: params.name, name: params.name,
description: params.description, description: params.description,
version: params.version,
active: params.active, active: params.active,
strategies_attributes: (params.strategies || []).map(mapStrategyToRails), strategies_attributes: (params.strategies || []).map(mapStrategyToRails),
version: NEW_VERSION_FLAG,
}, },
}); });
...@@ -13,10 +13,6 @@ class Projects::FeatureFlagsController < Projects::ApplicationController ...@@ -13,10 +13,6 @@ class Projects::FeatureFlagsController < Projects::ApplicationController
before_action :ensure_flag_writable!, only: [:update] before_action :ensure_flag_writable!, only: [:update]
before_action :exclude_legacy_flags_check, only: [:edit] before_action :exclude_legacy_flags_check, only: [:edit]
before_action do
push_frontend_feature_flag(:feature_flag_permissions)
end
feature_category :feature_flags feature_category :feature_flags
def index def index
......
...@@ -8,9 +8,6 @@ ...@@ -8,9 +8,6 @@
project_id: @project.id, project_id: @project.id,
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_callout_id: UserCalloutsHelper::FEATURE_FLAGS_NEW_VERSION,
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/index.md', anchor: 'scoping-environments-with-specs'), environments_scope_docs_path: help_page_path('ci/environments/index.md', anchor: 'scoping-environments-with-specs'),
feature_flag_issues_endpoint: feature_flag_issues_links_endpoint(@project, @feature_flag, current_user) } } feature_flag_issues_endpoint: feature_flag_issues_links_endpoint(@project, @feature_flag, current_user) } }
---
name: feature_flag_permissions
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/10096
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/254981
milestone: '11.10'
type: development
group: group::release
default_enabled: false
...@@ -13,9 +13,6 @@ ...@@ -13,9 +13,6 @@
.form-group .form-group
= f.label :deploy_access_levels_attributes, class: 'label-bold' do = f.label :deploy_access_levels_attributes, class: 'label-bold' do
= s_('ProtectedEnvironment|Allowed to deploy') = s_('ProtectedEnvironment|Allowed to deploy')
- if Feature.enabled?(:feature_flag_permissions, @project)
.text-muted.mb-2
= s_('ProtectedEnvironment|Select users to deploy and manage Feature Flag settings')
= render partial: 'projects/protected_environments/deploy_access_levels_dropdown', locals: { f: f } = render partial: 'projects/protected_environments/deploy_access_levels_dropdown', locals: { f: f }
.card-footer .card-footer
......
...@@ -10,7 +10,6 @@ RSpec.describe 'User creates feature flag', :js do ...@@ -10,7 +10,6 @@ RSpec.describe 'User creates feature flag', :js do
before do before do
project.add_developer(user) project.add_developer(user)
stub_feature_flags(feature_flag_permissions: false)
sign_in(user) sign_in(user)
end end
......
...@@ -15,7 +15,6 @@ RSpec.describe 'User deletes feature flag', :js do ...@@ -15,7 +15,6 @@ RSpec.describe 'User deletes feature flag', :js do
before do before do
project.add_developer(user) project.add_developer(user)
stub_feature_flags(feature_flag_permissions: false)
sign_in(user) sign_in(user)
visit(project_feature_flags_path(project)) visit(project_feature_flags_path(project))
......
...@@ -13664,9 +13664,6 @@ msgstr "" ...@@ -13664,9 +13664,6 @@ msgstr ""
msgid "FeatureFlags|Get started with feature flags" msgid "FeatureFlags|Get started with feature flags"
msgstr "" msgstr ""
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
msgid "FeatureFlags|ID" msgid "FeatureFlags|ID"
msgstr "" msgstr ""
...@@ -26423,9 +26420,6 @@ msgstr "" ...@@ -26423,9 +26420,6 @@ msgstr ""
msgid "ProtectedEnvironment|Select users" msgid "ProtectedEnvironment|Select users"
msgstr "" msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form." msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr "" msgstr ""
......
...@@ -10,7 +10,6 @@ RSpec.describe 'User creates feature flag', :js do ...@@ -10,7 +10,6 @@ RSpec.describe 'User creates feature flag', :js do
before do before do
project.add_developer(user) project.add_developer(user)
stub_feature_flags(feature_flag_permissions: false)
sign_in(user) sign_in(user)
end end
......
...@@ -15,7 +15,6 @@ RSpec.describe 'User deletes feature flag', :js do ...@@ -15,7 +15,6 @@ RSpec.describe 'User deletes feature flag', :js do
before do before do
project.add_developer(user) project.add_developer(user)
stub_feature_flags(feature_flag_permissions: false)
sign_in(user) sign_in(user)
visit(project_feature_flags_path(project)) visit(project_feature_flags_path(project))
......
...@@ -13,9 +13,6 @@ RSpec.describe 'User updates feature flag', :js do ...@@ -13,9 +13,6 @@ RSpec.describe 'User updates feature flag', :js do
end end
before do before do
stub_feature_flags(
feature_flag_permissions: false
)
sign_in(user) sign_in(user)
end end
......
import { GlToggle, GlAlert } from '@gitlab/ui'; import { GlToggle, GlAlert } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import Vue from 'vue';
import Vuex from 'vuex'; import Vuex from 'vuex';
import { mockTracking } from 'helpers/tracking_helper'; import { mockTracking } from 'helpers/tracking_helper';
import { TEST_HOST } from 'spec/test_constants'; import { TEST_HOST } from 'spec/test_constants';
import EditFeatureFlag from '~/feature_flags/components/edit_feature_flag.vue'; import EditFeatureFlag from '~/feature_flags/components/edit_feature_flag.vue';
import Form from '~/feature_flags/components/form.vue'; import Form from '~/feature_flags/components/form.vue';
import { LEGACY_FLAG, NEW_VERSION_FLAG } from '~/feature_flags/constants';
import createStore from '~/feature_flags/store/edit'; import createStore from '~/feature_flags/store/edit';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
const localVue = createLocalVue(); Vue.use(Vuex);
localVue.use(Vuex);
const userCalloutId = 'feature_flags_new_version';
const userCalloutsPath = `${TEST_HOST}/user_callouts`;
describe('Edit feature flag form', () => { describe('Edit feature flag form', () => {
let wrapper; let wrapper;
let mock; let mock;
...@@ -25,20 +20,14 @@ describe('Edit feature flag form', () => { ...@@ -25,20 +20,14 @@ describe('Edit feature flag form', () => {
endpoint: `${TEST_HOST}/feature_flags.json`, endpoint: `${TEST_HOST}/feature_flags.json`,
}); });
const factory = (opts = {}) => { const factory = (provide = {}) => {
if (wrapper) { if (wrapper) {
wrapper.destroy(); wrapper.destroy();
wrapper = null; wrapper = null;
} }
wrapper = shallowMount(EditFeatureFlag, { wrapper = shallowMount(EditFeatureFlag, {
localVue,
store, store,
provide: { provide,
showUserCallout: true,
userCalloutId,
userCalloutsPath,
...opts,
},
}); });
}; };
...@@ -52,18 +41,8 @@ describe('Edit feature flag form', () => { ...@@ -52,18 +41,8 @@ describe('Edit feature flag form', () => {
updated_at: '2019-01-17T17:27:39.778Z', updated_at: '2019-01-17T17:27:39.778Z',
name: 'feature_flag', name: 'feature_flag',
description: '', description: '',
version: LEGACY_FLAG,
edit_path: '/h5bp/html5-boilerplate/-/feature_flags/21/edit', edit_path: '/h5bp/html5-boilerplate/-/feature_flags/21/edit',
destroy_path: '/h5bp/html5-boilerplate/-/feature_flags/21', destroy_path: '/h5bp/html5-boilerplate/-/feature_flags/21',
scopes: [
{
id: 21,
active: false,
environment_scope: '*',
created_at: '2019-01-17T17:27:39.778Z',
updated_at: '2019-01-17T17:27:39.778Z',
},
],
}); });
factory(); factory();
setImmediate(() => done()); setImmediate(() => done());
...@@ -74,9 +53,7 @@ describe('Edit feature flag form', () => { ...@@ -74,9 +53,7 @@ describe('Edit feature flag form', () => {
mock.restore(); mock.restore();
}); });
const findAlert = () => wrapper.find(GlAlert); const findWarningGlAlert = () => wrapper.findComponent(GlAlert);
const findWarningGlAlert = () =>
wrapper.findAll(GlAlert).filter((c) => c.props('variant') === 'warning');
it('should display the iid', () => { it('should display the iid', () => {
expect(wrapper.find('h3').text()).toContain('^5'); expect(wrapper.find('h3').text()).toContain('^5');
...@@ -86,21 +63,13 @@ describe('Edit feature flag form', () => { ...@@ -86,21 +63,13 @@ describe('Edit feature flag form', () => {
expect(wrapper.find(GlToggle).exists()).toBe(true); expect(wrapper.find(GlToggle).exists()).toBe(true);
}); });
it('should set the value of the toggle to whether or not the flag is active', () => {
expect(wrapper.find(GlToggle).props('value')).toBe(true);
});
it('should alert users the flag is read-only', () => {
expect(findAlert().text()).toContain('GitLab is moving to a new way of managing feature flags');
});
describe('with error', () => { describe('with error', () => {
it('should render the error', () => { it('should render the error', () => {
store.dispatch('receiveUpdateFeatureFlagError', { message: ['The name is required'] }); store.dispatch('receiveUpdateFeatureFlagError', { message: ['The name is required'] });
return wrapper.vm.$nextTick(() => { return wrapper.vm.$nextTick(() => {
const warningGlAlert = findWarningGlAlert(); const warningGlAlert = findWarningGlAlert();
expect(warningGlAlert.at(1).exists()).toEqual(true); expect(warningGlAlert.exists()).toEqual(true);
expect(warningGlAlert.at(1).text()).toContain('The name is required'); expect(warningGlAlert.text()).toContain('The name is required');
}); });
}); });
}); });
...@@ -114,32 +83,6 @@ describe('Edit feature flag form', () => { ...@@ -114,32 +83,6 @@ describe('Edit feature flag form', () => {
expect(wrapper.find(Form).exists()).toEqual(true); expect(wrapper.find(Form).exists()).toEqual(true);
}); });
it('should set the version of the form from the feature flag', () => {
expect(wrapper.find(Form).attributes('version')).toBe(LEGACY_FLAG);
mock.resetHandlers();
mock.onGet(`${TEST_HOST}/feature_flags.json`).replyOnce(200, {
id: 21,
iid: 5,
active: true,
created_at: '2019-01-17T17:27:39.778Z',
updated_at: '2019-01-17T17:27:39.778Z',
name: 'feature_flag',
description: '',
version: NEW_VERSION_FLAG,
edit_path: '/h5bp/html5-boilerplate/-/feature_flags/21/edit',
destroy_path: '/h5bp/html5-boilerplate/-/feature_flags/21',
strategies: [],
});
factory();
return axios.waitForAll().then(() => {
expect(wrapper.find(Form).attributes('version')).toBe(NEW_VERSION_FLAG);
});
});
it('should track when the toggle is clicked', () => { it('should track when the toggle is clicked', () => {
const toggle = wrapper.find(GlToggle); const toggle = wrapper.find(GlToggle);
const spy = mockTracking('_category_', toggle.element, jest.spyOn); const spy = mockTracking('_category_', toggle.element, jest.spyOn);
......
...@@ -16,86 +16,24 @@ export const featureFlag = { ...@@ -16,86 +16,24 @@ export const featureFlag = {
destroy_path: 'feature_flags/1', destroy_path: 'feature_flags/1',
update_path: 'feature_flags/1', update_path: 'feature_flags/1',
edit_path: 'feature_flags/1/edit', edit_path: 'feature_flags/1/edit',
scopes: [ strategies: [
{ {
id: 1, id: 9,
active: true, name: ROLLOUT_STRATEGY_ALL_USERS,
environment_scope: '*', parameters: {},
can_update: true, scopes: [{ id: 17, environment_scope: '*' }],
protected: false,
created_at: '2019-01-14T06:41:40.987Z',
updated_at: '2019-01-14T06:41:40.987Z',
strategies: [
{
name: ROLLOUT_STRATEGY_ALL_USERS,
parameters: {},
},
],
}, },
{ {
id: 2, id: 8,
active: false, name: ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
environment_scope: 'production', parameters: {},
can_update: true, scopes: [{ id: 18, environment_scope: 'review/*' }],
protected: false,
created_at: '2019-01-14T06:41:40.987Z',
updated_at: '2019-01-14T06:41:40.987Z',
strategies: [
{
name: ROLLOUT_STRATEGY_ALL_USERS,
parameters: {},
},
],
}, },
{ {
id: 3, id: 7,
active: false, name: ROLLOUT_STRATEGY_USER_ID,
environment_scope: 'review/*', parameters: { userIds: '1,2,3,4' },
can_update: true, scopes: [{ id: 19, environment_scope: 'production' }],
protected: false,
created_at: '2019-01-14T06:41:40.987Z',
updated_at: '2019-01-14T06:41:40.987Z',
strategies: [
{
name: ROLLOUT_STRATEGY_ALL_USERS,
parameters: {},
},
],
},
{
id: 4,
active: true,
environment_scope: 'development',
can_update: true,
protected: false,
created_at: '2019-01-14T06:41:40.987Z',
updated_at: '2019-01-14T06:41:40.987Z',
strategies: [
{
name: ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
parameters: {
percentage: '86',
},
},
],
},
{
id: 5,
active: true,
environment_scope: 'development',
can_update: true,
protected: false,
created_at: '2019-01-14T06:41:40.987Z',
updated_at: '2019-01-14T06:41:40.987Z',
strategies: [
{
name: ROLLOUT_STRATEGY_FLEXIBLE_ROLLOUT,
parameters: {
rollout: '42',
stickiness: 'DEFAULT',
},
},
],
}, },
], ],
}; };
......
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper'; import testAction from 'helpers/vuex_action_helper';
import { TEST_HOST } from 'spec/test_constants'; import { TEST_HOST } from 'spec/test_constants';
import { import { ROLLOUT_STRATEGY_ALL_USERS } from '~/feature_flags/constants';
NEW_VERSION_FLAG,
LEGACY_FLAG,
ROLLOUT_STRATEGY_ALL_USERS,
} from '~/feature_flags/constants';
import { import {
updateFeatureFlag, updateFeatureFlag,
requestUpdateFeatureFlag, requestUpdateFeatureFlag,
...@@ -19,7 +15,7 @@ import { ...@@ -19,7 +15,7 @@ import {
} from '~/feature_flags/store/edit/actions'; } from '~/feature_flags/store/edit/actions';
import * as types from '~/feature_flags/store/edit/mutation_types'; import * as types from '~/feature_flags/store/edit/mutation_types';
import state from '~/feature_flags/store/edit/state'; import state from '~/feature_flags/store/edit/state';
import { mapStrategiesToRails, mapFromScopesViewModel } from '~/feature_flags/store/helpers'; import { mapStrategiesToRails } from '~/feature_flags/store/helpers';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
jest.mock('~/lib/utils/url_utility'); jest.mock('~/lib/utils/url_utility');
...@@ -45,47 +41,10 @@ describe('Feature flags Edit Module actions', () => { ...@@ -45,47 +41,10 @@ describe('Feature flags Edit Module actions', () => {
describe('success', () => { describe('success', () => {
it('dispatches requestUpdateFeatureFlag and receiveUpdateFeatureFlagSuccess ', (done) => { it('dispatches requestUpdateFeatureFlag and receiveUpdateFeatureFlagSuccess ', (done) => {
const featureFlag = {
name: 'feature_flag',
description: 'feature flag',
scopes: [
{
id: '1',
environmentScope: '*',
active: true,
shouldBeDestroyed: false,
canUpdate: true,
protected: false,
rolloutStrategy: ROLLOUT_STRATEGY_ALL_USERS,
},
],
version: LEGACY_FLAG,
active: true,
};
mock.onPut(mockedState.endpoint, mapFromScopesViewModel(featureFlag)).replyOnce(200);
testAction(
updateFeatureFlag,
featureFlag,
mockedState,
[],
[
{
type: 'requestUpdateFeatureFlag',
},
{
type: 'receiveUpdateFeatureFlagSuccess',
},
],
done,
);
});
it('handles new version flags as well', (done) => {
const featureFlag = { const featureFlag = {
name: 'name', name: 'name',
description: 'description', description: 'description',
active: true, active: true,
version: NEW_VERSION_FLAG,
strategies: [ strategies: [
{ {
name: ROLLOUT_STRATEGY_ALL_USERS, name: ROLLOUT_STRATEGY_ALL_USERS,
......
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper'; import testAction from 'helpers/vuex_action_helper';
import { ROLLOUT_STRATEGY_ALL_USERS, NEW_VERSION_FLAG } from '~/feature_flags/constants'; import { ROLLOUT_STRATEGY_ALL_USERS } from '~/feature_flags/constants';
import { mapStrategiesToRails } from '~/feature_flags/store/helpers'; import { mapStrategiesToRails } from '~/feature_flags/store/helpers';
import { import {
createFeatureFlag, createFeatureFlag,
requestCreateFeatureFlag, requestCreateFeatureFlag,
...@@ -39,7 +38,6 @@ describe('Feature flags New Module Actions', () => { ...@@ -39,7 +38,6 @@ describe('Feature flags New Module Actions', () => {
name: 'name', name: 'name',
description: 'description', description: 'description',
active: true, active: true,
version: NEW_VERSION_FLAG,
strategies: [ strategies: [
{ {
name: ROLLOUT_STRATEGY_ALL_USERS, name: ROLLOUT_STRATEGY_ALL_USERS,
...@@ -76,7 +74,6 @@ describe('Feature flags New Module Actions', () => { ...@@ -76,7 +74,6 @@ describe('Feature flags New Module Actions', () => {
name: 'name', name: 'name',
description: 'description', description: 'description',
active: true, active: true,
version: NEW_VERSION_FLAG,
strategies: [ strategies: [
{ {
name: ROLLOUT_STRATEGY_ALL_USERS, name: ROLLOUT_STRATEGY_ALL_USERS,
......
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