diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-09-30 21:06:34 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-09-30 21:06:34 +0300 |
commit | b4cdff15ca53312ccbbafe4effac85b1ee4420ae (patch) | |
tree | 85ecd924d542c6615d04e0756bbad7481d8d5228 | |
parent | 538fff823de57d1ba5317961aa43091de9dc007f (diff) |
Add latest changes from gitlab-org/gitlab@master
23 files changed, 320 insertions, 187 deletions
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue b/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue index a700069d2c8..7ed51068d42 100644 --- a/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue +++ b/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue @@ -1,11 +1,14 @@ <script> -import { mapActions, mapState } from 'vuex'; - +import { createNamespacedHelpers, mapState, mapActions } from 'vuex'; import RegionDropdown from './region_dropdown.vue'; import RoleNameDropdown from './role_name_dropdown.vue'; import SecurityGroupDropdown from './security_group_dropdown.vue'; import SubnetDropdown from './subnet_dropdown.vue'; -import VPCDropdown from './vpc_dropdown.vue'; +import VpcDropdown from './vpc_dropdown.vue'; + +const { mapState: mapRegionsState, mapActions: mapRegionsActions } = createNamespacedHelpers( + 'regions', +); export default { components: { @@ -13,31 +16,39 @@ export default { RoleNameDropdown, SecurityGroupDropdown, SubnetDropdown, - VPCDropdown, + VpcDropdown, }, computed: { - ...mapState(['isLoadingRegions', 'loadingRegionsError', 'regions', 'selectedRegion']), + ...mapState(['selectedRegion']), + ...mapRegionsState({ + regions: 'items', + isLoadingRegions: 'isLoadingItems', + loadingRegionsError: 'loadingItemsError', + }), }, mounted() { this.fetchRegions(); }, methods: { - ...mapActions(['fetchRegions', 'setRegion']), + ...mapActions(['setRegion']), + ...mapRegionsActions({ + fetchRegions: 'fetchItems', + }), }, }; </script> <template> <form name="eks-cluster-configuration-form"> <div class="form-group"> - <label class="label-bold" name="role" for="eks-role"> - {{ s__('ClusterIntegration|Role name') }} - </label> + <label class="label-bold" name="role" for="eks-role">{{ + s__('ClusterIntegration|Role name') + }}</label> <role-name-dropdown /> </div> <div class="form-group"> - <label class="label-bold" name="role" for="eks-role"> - {{ s__('ClusterIntegration|Region') }} - </label> + <label class="label-bold" name="role" for="eks-role">{{ + s__('ClusterIntegration|Region') + }}</label> <region-dropdown :value="selectedRegion" :regions="regions" diff --git a/app/assets/javascripts/create_cluster/eks_cluster/store/actions.js b/app/assets/javascripts/create_cluster/eks_cluster/store/actions.js index cad9e5eb183..68493be37e0 100644 --- a/app/assets/javascripts/create_cluster/eks_cluster/store/actions.js +++ b/app/assets/javascripts/create_cluster/eks_cluster/store/actions.js @@ -1,25 +1,5 @@ -import * as awsServices from '../services/aws_services_facade'; import * as types from './mutation_types'; -export const requestRegions = ({ commit }) => commit(types.REQUEST_REGIONS); - -export const receiveRegionsSuccess = ({ commit }, payload) => { - commit(types.RECEIVE_REGIONS_SUCCESS, payload); -}; - -export const receiveRegionsError = ({ commit }, payload) => { - commit(types.RECEIVE_REGIONS_ERROR, payload); -}; - -export const fetchRegions = ({ dispatch }) => { - dispatch('requestRegions'); - - return awsServices - .fetchRegions() - .then(regions => dispatch('receiveRegionsSuccess', { regions })) - .catch(error => dispatch('receiveRegionsError', { error })); -}; - export const setRegion = ({ commit }, payload) => { commit(types.SET_REGION, payload); }; diff --git a/app/assets/javascripts/create_cluster/eks_cluster/store/cluster_dropdown/actions.js b/app/assets/javascripts/create_cluster/eks_cluster/store/cluster_dropdown/actions.js new file mode 100644 index 00000000000..4f1ecb22719 --- /dev/null +++ b/app/assets/javascripts/create_cluster/eks_cluster/store/cluster_dropdown/actions.js @@ -0,0 +1,14 @@ +import * as types from './mutation_types'; + +export default fetchItems => ({ + requestItems: ({ commit }) => commit(types.REQUEST_ITEMS), + receiveItemsSuccess: ({ commit }, payload) => commit(types.RECEIVE_ITEMS_SUCCESS, payload), + receiveItemsError: ({ commit }, payload) => commit(types.RECEIVE_ITEMS_ERROR, payload), + fetchItems: ({ dispatch }) => { + dispatch('requestItems'); + + return fetchItems() + .then(items => dispatch('receiveItemsSuccess', { items })) + .catch(error => dispatch('receiveItemsError', { error })); + }, +}); diff --git a/app/assets/javascripts/create_cluster/eks_cluster/store/cluster_dropdown/getters.js b/app/assets/javascripts/create_cluster/eks_cluster/store/cluster_dropdown/getters.js new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/app/assets/javascripts/create_cluster/eks_cluster/store/cluster_dropdown/getters.js diff --git a/app/assets/javascripts/create_cluster/eks_cluster/store/cluster_dropdown/index.js b/app/assets/javascripts/create_cluster/eks_cluster/store/cluster_dropdown/index.js new file mode 100644 index 00000000000..07a5821c47d --- /dev/null +++ b/app/assets/javascripts/create_cluster/eks_cluster/store/cluster_dropdown/index.js @@ -0,0 +1,13 @@ +import * as getters from './getters'; +import actions from './actions'; +import mutations from './mutations'; +import state from './state'; + +const createStore = fetchFn => ({ + actions: actions(fetchFn), + getters, + mutations, + state: state(), +}); + +export default createStore; diff --git a/app/assets/javascripts/create_cluster/eks_cluster/store/cluster_dropdown/mutation_types.js b/app/assets/javascripts/create_cluster/eks_cluster/store/cluster_dropdown/mutation_types.js new file mode 100644 index 00000000000..48959a73924 --- /dev/null +++ b/app/assets/javascripts/create_cluster/eks_cluster/store/cluster_dropdown/mutation_types.js @@ -0,0 +1,3 @@ +export const REQUEST_ITEMS = 'REQUEST_ITEMS'; +export const RECEIVE_ITEMS_SUCCESS = 'REQUEST_ITEMS_SUCCESS'; +export const RECEIVE_ITEMS_ERROR = 'RECEIVE_ITEMS_ERROR'; diff --git a/app/assets/javascripts/create_cluster/eks_cluster/store/cluster_dropdown/mutations.js b/app/assets/javascripts/create_cluster/eks_cluster/store/cluster_dropdown/mutations.js new file mode 100644 index 00000000000..d09689f1f6c --- /dev/null +++ b/app/assets/javascripts/create_cluster/eks_cluster/store/cluster_dropdown/mutations.js @@ -0,0 +1,16 @@ +import * as types from './mutation_types'; + +export default { + [types.REQUEST_ITEMS](state) { + state.isLoadingItems = true; + state.loadingItemsError = null; + }, + [types.RECEIVE_ITEMS_SUCCESS](state, { items }) { + state.isLoadingItems = false; + state.items = items; + }, + [types.RECEIVE_ITEMS_ERROR](state, { error }) { + state.isLoadingItems = false; + state.loadingItemsError = error; + }, +}; diff --git a/app/assets/javascripts/create_cluster/eks_cluster/store/cluster_dropdown/state.js b/app/assets/javascripts/create_cluster/eks_cluster/store/cluster_dropdown/state.js new file mode 100644 index 00000000000..b949a24216e --- /dev/null +++ b/app/assets/javascripts/create_cluster/eks_cluster/store/cluster_dropdown/state.js @@ -0,0 +1,5 @@ +export default () => ({ + isLoadingItems: false, + items: [], + loadingItemsError: null, +}); diff --git a/app/assets/javascripts/create_cluster/eks_cluster/store/index.js b/app/assets/javascripts/create_cluster/eks_cluster/store/index.js index 8f5ad109c2f..608c4ec9e1e 100644 --- a/app/assets/javascripts/create_cluster/eks_cluster/store/index.js +++ b/app/assets/javascripts/create_cluster/eks_cluster/store/index.js @@ -4,12 +4,22 @@ import * as getters from './getters'; import mutations from './mutations'; import state from './state'; +import clusterDropdownStore from './cluster_dropdown'; + +import * as awsServices from '../services/aws_services_facade'; + const createStore = () => new Vuex.Store({ actions, getters, mutations, state: state(), + modules: { + regions: { + namespaced: true, + ...clusterDropdownStore(awsServices.fetchRegions), + }, + }, }); export default createStore; diff --git a/app/assets/javascripts/create_cluster/eks_cluster/store/mutation_types.js b/app/assets/javascripts/create_cluster/eks_cluster/store/mutation_types.js index d66d0e70dc0..80c1354482b 100644 --- a/app/assets/javascripts/create_cluster/eks_cluster/store/mutation_types.js +++ b/app/assets/javascripts/create_cluster/eks_cluster/store/mutation_types.js @@ -1,4 +1,2 @@ -export const REQUEST_REGIONS = 'REQUEST_REGIONS'; -export const RECEIVE_REGIONS_SUCCESS = 'REQUEST_REGIONS_SUCCESS'; -export const RECEIVE_REGIONS_ERROR = 'RECEIVE_REGIONS_ERROR'; +// eslint-disable-next-line import/prefer-default-export export const SET_REGION = 'SET_REGION'; diff --git a/app/assets/javascripts/create_cluster/eks_cluster/store/mutations.js b/app/assets/javascripts/create_cluster/eks_cluster/store/mutations.js index a203dd3bf42..02f34d1bdcd 100644 --- a/app/assets/javascripts/create_cluster/eks_cluster/store/mutations.js +++ b/app/assets/javascripts/create_cluster/eks_cluster/store/mutations.js @@ -1,18 +1,6 @@ import * as types from './mutation_types'; export default { - [types.REQUEST_REGIONS](state) { - state.isLoadingRegions = true; - state.loadingRegionsError = null; - }, - [types.RECEIVE_REGIONS_SUCCESS](state, { regions }) { - state.isLoadingRegions = false; - state.regions = regions; - }, - [types.RECEIVE_REGIONS_ERROR](state, { error }) { - state.isLoadingRegions = false; - state.loadingRegionsError = error; - }, [types.SET_REGION](state, { region }) { state.selectedRegion = region; }, diff --git a/app/assets/javascripts/create_cluster/eks_cluster/store/state.js b/app/assets/javascripts/create_cluster/eks_cluster/store/state.js index ffeb1963060..84880e15d9c 100644 --- a/app/assets/javascripts/create_cluster/eks_cluster/store/state.js +++ b/app/assets/javascripts/create_cluster/eks_cluster/store/state.js @@ -2,27 +2,9 @@ export default () => ({ isValidatingCredentials: false, validCredentials: false, - isLoadingRegions: false, - isLoadingRoles: false, - isLoadingVPCs: false, - isLoadingSubnets: false, - isLoadingSecurityGroups: false, - - regions: [], - roles: [], - vpcs: [], - subnets: [], - securityGroups: [], - - loadingRegionsError: null, - loadingRolesError: null, - loadingVPCsError: null, - loadingSubnetsError: null, - loadingSecurityGroupsError: null, - selectedRegion: '', selectedRole: '', - selectedVPC: '', + selectedVpc: '', selectedSubnet: '', selectedSecurityGroup: '', }); diff --git a/app/models/concerns/atomic_internal_id.rb b/app/models/concerns/atomic_internal_id.rb index dc1735a7e48..95de11a72bf 100644 --- a/app/models/concerns/atomic_internal_id.rb +++ b/app/models/concerns/atomic_internal_id.rb @@ -44,9 +44,15 @@ module AtomicInternalId scope_attrs = { scope_value.class.table_name.singularize.to_sym => scope_value } usage = self.class.table_name.to_sym - if value.present? + if value.present? && (@iid_needs_tracking || Feature.enabled?(:iid_always_track, default_enabled: true)) + # The value was set externally, e.g. by the user + # We update the InternalId record to keep track of the greatest value. InternalId.track_greatest(self, scope_attrs, usage, value, init) - else + + @iid_needs_tracking = false + elsif !value.present? + # We don't have a value yet and use a InternalId record to generate + # the next value. value = InternalId.generate_next(self, scope_attrs, usage, init) write_attribute(column, value) end @@ -54,6 +60,13 @@ module AtomicInternalId value end + define_method("#{column}=") do |value| + super(value).tap do |v| + # Indicate the iid was set from externally + @iid_needs_tracking = true + end + end + define_method("reset_#{scope}_#{column}") do if value = read_attribute(column) scope_value = association(scope).reader diff --git a/doc/policy/maintenance.md b/doc/policy/maintenance.md index f7ba7c16a9e..d1ad9f2abe2 100644 --- a/doc/policy/maintenance.md +++ b/doc/policy/maintenance.md @@ -24,7 +24,7 @@ The following table describes the version types and their release cadence: | Version type | Description | Cadence | |:-------------|:------------|:--------| -| Major | For significant changes, or when any backward-incompatible changes are introduced to the public API. | Yearly. The next major release is GitLab 12.0 on June 22, 2019. Subsequent major releases will be scheduled for May 22 each year, by default. | +| Major | For significant changes, or when any backward-incompatible changes are introduced to the public API. | Yearly. The next major release is GitLab 13.0 on May 22, 2020. Subsequent major releases will be scheduled for May 22 each year, by default. | | Minor | For when new backward-compatible functionality is introduced to the public API, a minor feature is introduced, or when a set of smaller features is rolled out. | Monthly on the 22nd. | | Patch | For backward-compatible bug fixes that fix incorrect behavior. See [Patch releases](#patch-releases). | As needed. | diff --git a/lib/banzai/filter/video_link_filter.rb b/lib/banzai/filter/video_link_filter.rb index bdd257a5e67..b3d5d2c95d7 100644 --- a/lib/banzai/filter/video_link_filter.rb +++ b/lib/banzai/filter/video_link_filter.rb @@ -32,7 +32,7 @@ module Banzai video = doc.document.create_element( 'video', src: element['src'], - width: '400', + width: '100%', controls: true, 'data-setup' => '{}', 'data-title' => element['title'] || element['alt']) diff --git a/spec/frontend/create_cluster/eks_cluster/components/eks_cluster_configuration_form_spec.js b/spec/frontend/create_cluster/eks_cluster/components/eks_cluster_configuration_form_spec.js index 5b04328bb78..1bd16d356b9 100644 --- a/spec/frontend/create_cluster/eks_cluster/components/eks_cluster_configuration_form_spec.js +++ b/spec/frontend/create_cluster/eks_cluster/components/eks_cluster_configuration_form_spec.js @@ -4,28 +4,38 @@ import Vue from 'vue'; import EksClusterConfigurationForm from '~/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue'; import RegionDropdown from '~/create_cluster/eks_cluster/components/region_dropdown.vue'; +import clusterDropdownStoreState from '~/create_cluster/eks_cluster/store/cluster_dropdown/state'; + const localVue = createLocalVue(); localVue.use(Vuex); describe('EksClusterConfigurationForm', () => { let store; let actions; - let state; + let regionsState; + let regionsActions; let vm; beforeEach(() => { actions = { - fetchRegions: jest.fn(), setRegion: jest.fn(), + setVpc: jest.fn(), + }; + regionsActions = { + fetchItems: jest.fn(), }; - state = { - regions: [{ name: 'region 1' }], - isLoadingRegions: false, - loadingRegionsError: { message: '' }, + regionsState = { + ...clusterDropdownStoreState(), }; store = new Vuex.Store({ - state, actions, + modules: { + regions: { + namespaced: true, + state: regionsState, + actions: regionsActions, + }, + }, }); }); @@ -44,31 +54,35 @@ describe('EksClusterConfigurationForm', () => { describe('when mounted', () => { it('fetches available regions', () => { - expect(actions.fetchRegions).toHaveBeenCalled(); + expect(regionsActions.fetchItems).toHaveBeenCalled(); }); }); it('sets isLoadingRegions to RegionDropdown loading property', () => { - state.isLoadingRegions = true; + regionsState.isLoadingItems = true; return Vue.nextTick().then(() => { - expect(findRegionDropdown().props('loading')).toEqual(state.isLoadingRegions); + expect(findRegionDropdown().props('loading')).toEqual(regionsState.isLoadingItems); }); }); it('sets regions to RegionDropdown regions property', () => { - expect(findRegionDropdown().props('regions')).toEqual(state.regions); + expect(findRegionDropdown().props('regions')).toEqual(regionsState.items); }); it('sets loadingRegionsError to RegionDropdown error property', () => { - expect(findRegionDropdown().props('error')).toEqual(state.loadingRegionsError); + expect(findRegionDropdown().props('error')).toEqual(regionsState.loadingItemsError); }); - it('dispatches setRegion action when region is selected', () => { - const region = { region: 'us-west-2' }; + describe('when region is selected', () => { + const region = { name: 'us-west-2' }; - findRegionDropdown().vm.$emit('input', region); + beforeEach(() => { + findRegionDropdown().vm.$emit('input', region); + }); - expect(actions.setRegion).toHaveBeenCalledWith(expect.anything(), { region }, undefined); + it('dispatches setRegion action', () => { + expect(actions.setRegion).toHaveBeenCalledWith(expect.anything(), { region }, undefined); + }); }); }); diff --git a/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js b/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js index 9a3970813ed..3744ddb3dc6 100644 --- a/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js +++ b/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js @@ -1,91 +1,10 @@ import testAction from 'helpers/vuex_action_helper'; -import * as awsServicesFacade from '~/create_cluster/eks_cluster/services/aws_services_facade'; import createState from '~/create_cluster/eks_cluster/store/state'; import * as types from '~/create_cluster/eks_cluster/store/mutation_types'; import * as actions from '~/create_cluster/eks_cluster/store/actions'; describe('EKS Cluster Store Actions', () => { - const regions = [{ name: 'region 1' }]; - - describe('fetchRegions', () => { - describe('on success', () => { - beforeEach(() => { - jest.spyOn(awsServicesFacade, 'fetchRegions').mockResolvedValueOnce(regions); - }); - - it('dispatches success with received regions', () => - testAction( - actions.fetchRegions, - null, - createState(), - [], - [ - { type: 'requestRegions' }, - { - type: 'receiveRegionsSuccess', - payload: { regions }, - }, - ], - )); - }); - - describe('on failure', () => { - const error = new Error('Could not fetch regions'); - - beforeEach(() => { - jest.spyOn(awsServicesFacade, 'fetchRegions').mockRejectedValueOnce(error); - }); - - it('dispatches success with received regions', () => - testAction( - actions.fetchRegions, - null, - createState(), - [], - [ - { type: 'requestRegions' }, - { - type: 'receiveRegionsError', - payload: { error }, - }, - ], - )); - }); - }); - - describe('requestRegions', () => { - it(`commits ${types.REQUEST_REGIONS} mutation`, () => - testAction(actions.requestRegions, null, createState(), [{ type: types.REQUEST_REGIONS }])); - }); - - describe('receiveRegionsSuccess', () => { - it(`commits ${types.RECEIVE_REGIONS_SUCCESS} mutation`, () => - testAction(actions.receiveRegionsSuccess, { regions }, createState(), [ - { - type: types.RECEIVE_REGIONS_SUCCESS, - payload: { - regions, - }, - }, - ])); - }); - - describe('receiveRegionsError', () => { - it(`commits ${types.RECEIVE_REGIONS_ERROR} mutation`, () => { - const error = new Error('Error fetching regions'); - - testAction(actions.receiveRegionsError, { error }, createState(), [ - { - type: types.RECEIVE_REGIONS_ERROR, - payload: { - error, - }, - }, - ]); - }); - }); - describe('setRegion', () => { it(`commits ${types.SET_REGION} mutation`, () => { const region = { name: 'west-1' }; diff --git a/spec/frontend/create_cluster/eks_cluster/store/cluster_dropdown/actions_spec.js b/spec/frontend/create_cluster/eks_cluster/store/cluster_dropdown/actions_spec.js new file mode 100644 index 00000000000..58f8855a64c --- /dev/null +++ b/spec/frontend/create_cluster/eks_cluster/store/cluster_dropdown/actions_spec.js @@ -0,0 +1,95 @@ +import testAction from 'helpers/vuex_action_helper'; + +import createState from '~/create_cluster/eks_cluster/store/cluster_dropdown/state'; +import * as types from '~/create_cluster/eks_cluster/store/cluster_dropdown/mutation_types'; +import actionsFactory from '~/create_cluster/eks_cluster/store/cluster_dropdown/actions'; + +describe('Cluster dropdown Store Actions', () => { + const items = [{ name: 'item 1' }]; + let fetchFn; + let actions; + + beforeEach(() => { + fetchFn = jest.fn(); + actions = actionsFactory(fetchFn); + }); + + describe('fetchItems', () => { + describe('on success', () => { + beforeEach(() => { + fetchFn.mockResolvedValueOnce(items); + actions = actionsFactory(fetchFn); + }); + + it('dispatches success with received items', () => + testAction( + actions.fetchItems, + null, + createState(), + [], + [ + { type: 'requestItems' }, + { + type: 'receiveItemsSuccess', + payload: { items }, + }, + ], + )); + }); + + describe('on failure', () => { + const error = new Error('Could not fetch items'); + + beforeEach(() => { + fetchFn.mockRejectedValueOnce(error); + }); + + it('dispatches success with received items', () => + testAction( + actions.fetchItems, + null, + createState(), + [], + [ + { type: 'requestItems' }, + { + type: 'receiveItemsError', + payload: { error }, + }, + ], + )); + }); + }); + + describe('requestItems', () => { + it(`commits ${types.REQUEST_ITEMS} mutation`, () => + testAction(actions.requestItems, null, createState(), [{ type: types.REQUEST_ITEMS }])); + }); + + describe('receiveItemsSuccess', () => { + it(`commits ${types.RECEIVE_ITEMS_SUCCESS} mutation`, () => + testAction(actions.receiveItemsSuccess, { items }, createState(), [ + { + type: types.RECEIVE_ITEMS_SUCCESS, + payload: { + items, + }, + }, + ])); + }); + + describe('receiveItemsError', () => { + it(`commits ${types.RECEIVE_ITEMS_ERROR} mutation`, () => { + const error = new Error('Error fetching items'); + + testAction(actions.receiveItemsError, { error }, createState(), [ + { + type: types.RECEIVE_ITEMS_ERROR, + payload: { + error, + }, + }, + ]); + }); + }); +}); diff --git a/spec/frontend/create_cluster/eks_cluster/store/cluster_dropdown/mutations_spec.js b/spec/frontend/create_cluster/eks_cluster/store/cluster_dropdown/mutations_spec.js new file mode 100644 index 00000000000..0665047edea --- /dev/null +++ b/spec/frontend/create_cluster/eks_cluster/store/cluster_dropdown/mutations_spec.js @@ -0,0 +1,36 @@ +import { + REQUEST_ITEMS, + RECEIVE_ITEMS_SUCCESS, + RECEIVE_ITEMS_ERROR, +} from '~/create_cluster/eks_cluster/store/cluster_dropdown/mutation_types'; +import createState from '~/create_cluster/eks_cluster/store/cluster_dropdown/state'; +import mutations from '~/create_cluster/eks_cluster/store/cluster_dropdown/mutations'; + +describe('Cluster dropdown store mutations', () => { + let state; + let emptyPayload; + let items; + let error; + + beforeEach(() => { + emptyPayload = {}; + items = [{ name: 'item 1' }]; + error = new Error('could not load error'); + state = createState(); + }); + + it.each` + mutation | mutatedProperty | payload | expectedValue | expectedValueDescription + ${REQUEST_ITEMS} | ${'isLoadingItems'} | ${emptyPayload} | ${true} | ${true} + ${REQUEST_ITEMS} | ${'loadingItemsError'} | ${emptyPayload} | ${null} | ${null} + ${RECEIVE_ITEMS_SUCCESS} | ${'isLoadingItems'} | ${{ items }} | ${false} | ${false} + ${RECEIVE_ITEMS_SUCCESS} | ${'items'} | ${{ items }} | ${items} | ${'items payload'} + ${RECEIVE_ITEMS_ERROR} | ${'isLoadingItems'} | ${{ error }} | ${false} | ${false} + ${RECEIVE_ITEMS_ERROR} | ${'error'} | ${{ error }} | ${error} | ${'received error object'} + `(`$mutation sets $mutatedProperty to $expectedValueDescription`, data => { + const { mutation, mutatedProperty, payload, expectedValue } = data; + + mutations[mutation](state, payload); + expect(state[mutatedProperty]).toBe(expectedValue); + }); +}); diff --git a/spec/frontend/create_cluster/eks_cluster/store/mutations_spec.js b/spec/frontend/create_cluster/eks_cluster/store/mutations_spec.js index f2d48635f8c..99f05b0f449 100644 --- a/spec/frontend/create_cluster/eks_cluster/store/mutations_spec.js +++ b/spec/frontend/create_cluster/eks_cluster/store/mutations_spec.js @@ -1,36 +1,19 @@ -import { - REQUEST_REGIONS, - RECEIVE_REGIONS_ERROR, - RECEIVE_REGIONS_SUCCESS, - SET_REGION, -} from '~/create_cluster/eks_cluster/store/mutation_types'; +import { SET_REGION } from '~/create_cluster/eks_cluster/store/mutation_types'; import createState from '~/create_cluster/eks_cluster/store/state'; import mutations from '~/create_cluster/eks_cluster/store/mutations'; describe('Create EKS cluster store mutations', () => { let state; - let emptyPayload; - let regions; let region; - let error; beforeEach(() => { - emptyPayload = {}; region = { name: 'regions-1' }; - regions = [region]; - error = new Error('could not load error'); state = createState(); }); it.each` - mutation | mutatedProperty | payload | expectedValue | expectedValueDescription - ${REQUEST_REGIONS} | ${'isLoadingRegions'} | ${emptyPayload} | ${true} | ${true} - ${REQUEST_REGIONS} | ${'loadingRegionsError'} | ${emptyPayload} | ${null} | ${null} - ${RECEIVE_REGIONS_SUCCESS} | ${'isLoadingRegions'} | ${{ regions }} | ${false} | ${false} - ${RECEIVE_REGIONS_SUCCESS} | ${'regions'} | ${{ regions }} | ${regions} | ${'regions payload'} - ${RECEIVE_REGIONS_ERROR} | ${'isLoadingRegions'} | ${{ error }} | ${false} | ${false} - ${RECEIVE_REGIONS_ERROR} | ${'error'} | ${{ error }} | ${error} | ${'received error object'} - ${SET_REGION} | ${'selectedRegion'} | ${{ region }} | ${region} | ${'selected region payload'} + mutation | mutatedProperty | payload | expectedValue | expectedValueDescription + ${SET_REGION} | ${'selectedRegion'} | ${{ region }} | ${region} | ${'selected region payload'} `(`$mutation sets $mutatedProperty to $expectedValueDescription`, data => { const { mutation, mutatedProperty, payload, expectedValue } = data; diff --git a/spec/models/concerns/atomic_internal_id_spec.rb b/spec/models/concerns/atomic_internal_id_spec.rb new file mode 100644 index 00000000000..60e7e90e3f1 --- /dev/null +++ b/spec/models/concerns/atomic_internal_id_spec.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe AtomicInternalId do + let(:milestone) { build(:milestone) } + let(:iid) { double('iid', to_i: 42) } + let(:external_iid) { 100 } + let(:scope_attrs) { { project: milestone.project } } + let(:usage) { :milestones } + + describe '#ensure_project_iid!' do + subject { milestone.ensure_project_iid! } + + it 'generates a new value if non is present' do + expect(InternalId).to receive(:generate_next).with(milestone, scope_attrs, usage, anything).and_return(iid) + + expect { subject }.to change { milestone.iid }.from(nil).to(iid.to_i) + end + + it 'tracks the present value if not generated by InternalId.generate_next' do + milestone.iid = external_iid + + expect(InternalId).to receive(:track_greatest).once.with(milestone, scope_attrs, usage, external_iid, anything) + expect(InternalId).not_to receive(:generate_next) + + subject + end + + it 'generates a new value if first set with iid= but later set to nil' do + expect(InternalId).to receive(:generate_next).with(milestone, scope_attrs, usage, anything).and_return(iid) + + milestone.iid = external_iid + milestone.iid = nil + + expect { subject }.to change { milestone.iid }.from(nil).to(iid.to_i) + end + + context 'with iid_always_track disabled' do + before do + stub_feature_flags(iid_always_track: false) + end + + it 'does not track the present value if generated by InternalId.generate_next' do + milestone.ensure_project_iid! + + expect(InternalId).not_to receive(:track_greatest) + + subject + end + end + end +end diff --git a/vendor/gitignore/C++.gitignore b/vendor/gitignore/C++.gitignore index 259148fa18f..259148fa18f 100644..100755 --- a/vendor/gitignore/C++.gitignore +++ b/vendor/gitignore/C++.gitignore diff --git a/vendor/gitignore/Java.gitignore b/vendor/gitignore/Java.gitignore index a1c2a238a96..a1c2a238a96 100644..100755 --- a/vendor/gitignore/Java.gitignore +++ b/vendor/gitignore/Java.gitignore |