From 7e9c479f7de77702622631cff2628a9c8dcbc627 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Thu, 19 Nov 2020 08:27:35 +0000 Subject: Add latest changes from gitlab-org/gitlab@13-6-stable-ee --- .../configure_feature_flags_modal_spec.js | 8 +-- .../frontend/feature_flags/components/form_spec.js | 10 --- .../components/strategies/flexible_rollout_spec.js | 2 +- .../components/strategies/gitlab_user_list_spec.js | 78 ++++++++++++++++++---- .../components/strategies/percent_rollout_spec.js | 2 +- .../components/strategy_parameters_spec.js | 12 ++-- .../feature_flags/components/strategy_spec.js | 17 ++++- spec/frontend/feature_flags/mock_data.js | 2 +- .../store/gitlab_user_lists/actions_spec.js | 60 +++++++++++++++++ .../store/gitlab_user_lists/getters_spec.js | 69 +++++++++++++++++++ .../store/gitlab_user_lists/mutations_spec.js | 50 ++++++++++++++ 11 files changed, 271 insertions(+), 39 deletions(-) create mode 100644 spec/frontend/feature_flags/store/gitlab_user_lists/actions_spec.js create mode 100644 spec/frontend/feature_flags/store/gitlab_user_lists/getters_spec.js create mode 100644 spec/frontend/feature_flags/store/gitlab_user_lists/mutations_spec.js (limited to 'spec/frontend/feature_flags') diff --git a/spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js b/spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js index 0e364c47f8d..67f4bee766b 100644 --- a/spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js +++ b/spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js @@ -99,13 +99,13 @@ describe('Configure Feature Flags Modal', () => { }); it('should display the api URL in an input box', () => { - const input = wrapper.find('#api_url'); - expect(input.element.value).toBe('/api/url'); + const input = wrapper.find('#api-url'); + expect(input.attributes('value')).toBe('/api/url'); }); it('should display the instance ID in an input box', () => { const input = wrapper.find('#instance_id'); - expect(input.element.value).toBe('instance-id-token'); + expect(input.attributes('value')).toBe('instance-id-token'); }); }); @@ -129,7 +129,7 @@ describe('Configure Feature Flags Modal', () => { expect(findPrimaryAction()).toBe(null); }); - it('shold not display regenerating instance ID', async () => { + it('should not display regenerating instance ID', async () => { expect(findDangerCallout().exists()).toBe(false); }); diff --git a/spec/frontend/feature_flags/components/form_spec.js b/spec/frontend/feature_flags/components/form_spec.js index 33c7eeb54b7..2c2a726d26f 100644 --- a/spec/frontend/feature_flags/components/form_spec.js +++ b/spec/frontend/feature_flags/components/form_spec.js @@ -442,12 +442,6 @@ describe('feature flag form', () => { }); }); - it('should request the user lists on mount', () => { - return wrapper.vm.$nextTick(() => { - expect(Api.fetchFeatureFlagUserLists).toHaveBeenCalledWith('1'); - }); - }); - it('should show the strategy component', () => { const strategy = wrapper.find(Strategy); expect(strategy.exists()).toBe(true); @@ -485,9 +479,5 @@ describe('feature flag form', () => { expect(wrapper.find(Strategy).props('strategy')).not.toEqual(strategy); }); }); - - it('should provide the user lists to the strategy', () => { - expect(wrapper.find(Strategy).props('userLists')).toEqual([userList]); - }); }); }); diff --git a/spec/frontend/feature_flags/components/strategies/flexible_rollout_spec.js b/spec/frontend/feature_flags/components/strategies/flexible_rollout_spec.js index f3f70a325d0..725f53d4409 100644 --- a/spec/frontend/feature_flags/components/strategies/flexible_rollout_spec.js +++ b/spec/frontend/feature_flags/components/strategies/flexible_rollout_spec.js @@ -100,7 +100,7 @@ describe('feature_flags/components/strategies/flexible_rollout.vue', () => { }); }); - describe('with percentage that is not a whole number', () => { + describe('with percentage that is not an integer number', () => { beforeEach(() => { wrapper = factory({ strategy: { parameters: { rollout: '3.14' } } }); }); diff --git a/spec/frontend/feature_flags/components/strategies/gitlab_user_list_spec.js b/spec/frontend/feature_flags/components/strategies/gitlab_user_list_spec.js index 014c6dd98b9..b34fe7779e3 100644 --- a/spec/frontend/feature_flags/components/strategies/gitlab_user_list_spec.js +++ b/spec/frontend/feature_flags/components/strategies/gitlab_user_list_spec.js @@ -1,51 +1,103 @@ -import { mount } from '@vue/test-utils'; -import { GlFormSelect } from '@gitlab/ui'; +import { mount, createLocalVue } from '@vue/test-utils'; +import Vuex from 'vuex'; +import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlLoadingIcon } from '@gitlab/ui'; +import Api from '~/api'; +import createStore from '~/feature_flags/store/new'; import GitlabUserList from '~/feature_flags/components/strategies/gitlab_user_list.vue'; import { userListStrategy, userList } from '../../mock_data'; +jest.mock('~/api'); + const DEFAULT_PROPS = { strategy: userListStrategy, - userLists: [userList], }; +const localVue = createLocalVue(); +localVue.use(Vuex); + describe('~/feature_flags/components/strategies/gitlab_user_list.vue', () => { let wrapper; const factory = (props = {}) => - mount(GitlabUserList, { propsData: { ...DEFAULT_PROPS, ...props } }); + mount(GitlabUserList, { + localVue, + store: createStore({ projectId: '1' }), + propsData: { ...DEFAULT_PROPS, ...props }, + }); + + const findDropdown = () => wrapper.find(GlDropdown); describe('with user lists', () => { + const findDropdownItem = () => wrapper.find(GlDropdownItem); + beforeEach(() => { + Api.searchFeatureFlagUserLists.mockResolvedValue({ data: [userList] }); wrapper = factory(); }); it('should show the input for userListId with the correct value', () => { - const inputWrapper = wrapper.find(GlFormSelect); - expect(inputWrapper.exists()).toBe(true); - expect(inputWrapper.element.value).toBe('2'); + const dropdownWrapper = findDropdown(); + expect(dropdownWrapper.exists()).toBe(true); + expect(dropdownWrapper.props('text')).toBe(userList.name); + }); + + it('should show a check for the selected list', () => { + const itemWrapper = findDropdownItem(); + expect(itemWrapper.props('isChecked')).toBe(true); + }); + + it('should display the name of the list in the drop;down', () => { + const itemWrapper = findDropdownItem(); + expect(itemWrapper.text()).toBe(userList.name); }); it('should emit a change event when altering the userListId', () => { - const inputWrapper = wrapper.find(GitlabUserList); - inputWrapper.vm.$emit('change', { - userListId: '3', - }); + const inputWrapper = findDropdownItem(); + inputWrapper.vm.$emit('click'); expect(wrapper.emitted('change')).toEqual([ [ { - userListId: '3', + userList, }, ], ]); }); + + it('should search when the filter changes', async () => { + let r; + Api.searchFeatureFlagUserLists.mockReturnValue( + new Promise(resolve => { + r = resolve; + }), + ); + const searchWrapper = wrapper.find(GlSearchBoxByType); + searchWrapper.vm.$emit('input', 'new'); + await wrapper.vm.$nextTick(); + const loadingIcon = wrapper.find(GlLoadingIcon); + + expect(loadingIcon.exists()).toBe(true); + expect(Api.searchFeatureFlagUserLists).toHaveBeenCalledWith('1', 'new'); + + r({ data: [userList] }); + + await wrapper.vm.$nextTick(); + + expect(loadingIcon.exists()).toBe(false); + }); }); + describe('without user lists', () => { beforeEach(() => { - wrapper = factory({ userLists: [] }); + Api.searchFeatureFlagUserLists.mockResolvedValue({ data: [] }); + wrapper = factory({ strategy: { ...userListStrategy, userList: null } }); }); it('should display a message that there are no user lists', () => { expect(wrapper.text()).toContain('There are no configured user lists'); }); + + it('should dispaly a message that no list has been selected', () => { + expect(findDropdown().text()).toContain('No user list selected'); + }); }); }); diff --git a/spec/frontend/feature_flags/components/strategies/percent_rollout_spec.js b/spec/frontend/feature_flags/components/strategies/percent_rollout_spec.js index de0b439f1c5..696b3b2e4c9 100644 --- a/spec/frontend/feature_flags/components/strategies/percent_rollout_spec.js +++ b/spec/frontend/feature_flags/components/strategies/percent_rollout_spec.js @@ -63,7 +63,7 @@ describe('~/feature_flags/components/strategies/percent_rollout.vue', () => { }); }); - describe('with percentage that is not a whole number', () => { + describe('with percentage that is not an integer number', () => { beforeEach(() => { wrapper = factory({ strategy: { parameters: { percentage: '3.14' } } }); diff --git a/spec/frontend/feature_flags/components/strategy_parameters_spec.js b/spec/frontend/feature_flags/components/strategy_parameters_spec.js index 314fb0f21f4..a024384e623 100644 --- a/spec/frontend/feature_flags/components/strategy_parameters_spec.js +++ b/spec/frontend/feature_flags/components/strategy_parameters_spec.js @@ -11,11 +11,10 @@ import GitlabUserList from '~/feature_flags/components/strategies/gitlab_user_li import PercentRollout from '~/feature_flags/components/strategies/percent_rollout.vue'; import UsersWithId from '~/feature_flags/components/strategies/users_with_id.vue'; import StrategyParameters from '~/feature_flags/components/strategy_parameters.vue'; -import { allUsersStrategy, userList } from '../mock_data'; +import { allUsersStrategy } from '../mock_data'; const DEFAULT_PROPS = { strategy: allUsersStrategy, - userLists: [userList], }; describe('~/feature_flags/components/strategy_parameters.vue', () => { @@ -71,13 +70,14 @@ describe('~/feature_flags/components/strategy_parameters.vue', () => { describe('pass through props', () => { it('should pass through any extra props that might be needed', () => { + const strategy = { + name: ROLLOUT_STRATEGY_USER_ID, + }; wrapper = factory({ - strategy: { - name: ROLLOUT_STRATEGY_GITLAB_USER_LIST, - }, + strategy, }); - expect(wrapper.find(GitlabUserList).props('userLists')).toEqual([userList]); + expect(wrapper.find(UsersWithId).props('strategy')).toEqual(strategy); }); }); }); diff --git a/spec/frontend/feature_flags/components/strategy_spec.js b/spec/frontend/feature_flags/components/strategy_spec.js index 7d6700ba184..67cf70c37e2 100644 --- a/spec/frontend/feature_flags/components/strategy_spec.js +++ b/spec/frontend/feature_flags/components/strategy_spec.js @@ -1,6 +1,9 @@ -import { mount } from '@vue/test-utils'; +import { mount, createLocalVue } from '@vue/test-utils'; +import Vuex from 'vuex'; import { last } from 'lodash'; import { GlAlert, GlFormSelect, GlLink, GlToken, GlButton } from '@gitlab/ui'; +import Api from '~/api'; +import createStore from '~/feature_flags/store/new'; import { PERCENT_ROLLOUT_GROUP_ID, ROLLOUT_STRATEGY_ALL_USERS, @@ -15,12 +18,17 @@ import StrategyParameters from '~/feature_flags/components/strategy_parameters.v import { userList } from '../mock_data'; +jest.mock('~/api'); + const provide = { strategyTypeDocsPagePath: 'link-to-strategy-docs', environmentsScopeDocsPath: 'link-scope-docs', environmentsEndpoint: '', }; +const localVue = createLocalVue(); +localVue.use(Vuex); + describe('Feature flags strategy', () => { let wrapper; @@ -32,7 +40,6 @@ describe('Feature flags strategy', () => { propsData: { strategy: {}, index: 0, - userLists: [userList], }, provide, }, @@ -41,9 +48,13 @@ describe('Feature flags strategy', () => { wrapper.destroy(); wrapper = null; } - wrapper = mount(Strategy, opts); + wrapper = mount(Strategy, { localVue, store: createStore({ projectId: '1' }), ...opts }); }; + beforeEach(() => { + Api.searchFeatureFlagUserLists.mockResolvedValue({ data: [userList] }); + }); + afterEach(() => { if (wrapper) { wrapper.destroy(); diff --git a/spec/frontend/feature_flags/mock_data.js b/spec/frontend/feature_flags/mock_data.js index ed06ea059a7..11a91e5b2a8 100644 --- a/spec/frontend/feature_flags/mock_data.js +++ b/spec/frontend/feature_flags/mock_data.js @@ -127,7 +127,7 @@ export const userListStrategy = { name: ROLLOUT_STRATEGY_GITLAB_USER_LIST, parameters: {}, scopes: [], - userListId: userList.id, + userList, }; export const percentRolloutStrategy = { diff --git a/spec/frontend/feature_flags/store/gitlab_user_lists/actions_spec.js b/spec/frontend/feature_flags/store/gitlab_user_lists/actions_spec.js new file mode 100644 index 00000000000..aba578cca59 --- /dev/null +++ b/spec/frontend/feature_flags/store/gitlab_user_lists/actions_spec.js @@ -0,0 +1,60 @@ +import testAction from 'helpers/vuex_action_helper'; +import Api from '~/api'; +import createState from '~/feature_flags/store/gitlab_user_list/state'; +import { fetchUserLists, setFilter } from '~/feature_flags/store/gitlab_user_list/actions'; +import * as types from '~/feature_flags/store/gitlab_user_list/mutation_types'; +import { userList } from '../../mock_data'; + +jest.mock('~/api'); + +describe('~/feature_flags/store/gitlab_user_list/actions', () => { + let mockedState; + + beforeEach(() => { + mockedState = createState({ projectId: '1' }); + mockedState.filter = 'test'; + }); + + describe('fetchUserLists', () => { + it('should commit FETCH_USER_LISTS and RECEIEVE_USER_LISTS_SUCCESS on success', () => { + Api.searchFeatureFlagUserLists.mockResolvedValue({ data: [userList] }); + return testAction( + fetchUserLists, + undefined, + mockedState, + [ + { type: types.FETCH_USER_LISTS }, + { type: types.RECEIVE_USER_LISTS_SUCCESS, payload: [userList] }, + ], + [], + () => expect(Api.searchFeatureFlagUserLists).toHaveBeenCalledWith('1', 'test'), + ); + }); + + it('should commit FETCH_USER_LISTS and RECEIEVE_USER_LISTS_ERROR on success', () => { + Api.searchFeatureFlagUserLists.mockRejectedValue({ message: 'error' }); + return testAction( + fetchUserLists, + undefined, + mockedState, + [ + { type: types.FETCH_USER_LISTS }, + { type: types.RECEIVE_USER_LISTS_ERROR, payload: ['error'] }, + ], + [], + () => expect(Api.searchFeatureFlagUserLists).toHaveBeenCalledWith('1', 'test'), + ); + }); + }); + + describe('setFilter', () => { + it('commits SET_FILTER and fetches new user lists', () => + testAction( + setFilter, + 'filter', + mockedState, + [{ type: types.SET_FILTER, payload: 'filter' }], + [{ type: 'fetchUserLists' }], + )); + }); +}); diff --git a/spec/frontend/feature_flags/store/gitlab_user_lists/getters_spec.js b/spec/frontend/feature_flags/store/gitlab_user_lists/getters_spec.js new file mode 100644 index 00000000000..e267cd59f50 --- /dev/null +++ b/spec/frontend/feature_flags/store/gitlab_user_lists/getters_spec.js @@ -0,0 +1,69 @@ +import { + userListOptions, + hasUserLists, + isLoading, + hasError, +} from '~/feature_flags/store/gitlab_user_list/getters'; +import statuses from '~/feature_flags/store/gitlab_user_list/status'; +import createState from '~/feature_flags/store/gitlab_user_list/state'; +import { userList } from '../../mock_data'; + +describe('~/feature_flags/store/gitlab_user_list/getters', () => { + let mockedState; + + beforeEach(() => { + mockedState = createState({ projectId: '8' }); + mockedState.userLists = [userList]; + }); + + describe('userListOption', () => { + it('should return user lists in a way usable by a dropdown', () => { + expect(userListOptions(mockedState)).toEqual([{ value: userList.id, text: userList.name }]); + }); + + it('should return an empty array if there are no lists', () => { + mockedState.userLists = []; + expect(userListOptions(mockedState)).toEqual([]); + }); + }); + + describe('hasUserLists', () => { + it.each` + userLists | status | result + ${[userList]} | ${statuses.IDLE} | ${true} + ${[]} | ${statuses.IDLE} | ${false} + ${[]} | ${statuses.START} | ${true} + `( + 'should return $result if there are $userLists.length user lists and the status is $status', + ({ userLists, status, result }) => { + mockedState.userLists = userLists; + mockedState.status = status; + expect(hasUserLists(mockedState)).toBe(result); + }, + ); + }); + + describe('isLoading', () => { + it.each` + status | result + ${statuses.LOADING} | ${true} + ${statuses.ERROR} | ${false} + ${statuses.IDLE} | ${false} + `('should return $result if the status is "$status"', ({ status, result }) => { + mockedState.status = status; + expect(isLoading(mockedState)).toBe(result); + }); + }); + + describe('hasError', () => { + it.each` + status | result + ${statuses.LOADING} | ${false} + ${statuses.ERROR} | ${true} + ${statuses.IDLE} | ${false} + `('should return $result if the status is "$status"', ({ status, result }) => { + mockedState.status = status; + expect(hasError(mockedState)).toBe(result); + }); + }); +}); diff --git a/spec/frontend/feature_flags/store/gitlab_user_lists/mutations_spec.js b/spec/frontend/feature_flags/store/gitlab_user_lists/mutations_spec.js new file mode 100644 index 00000000000..88d4554a227 --- /dev/null +++ b/spec/frontend/feature_flags/store/gitlab_user_lists/mutations_spec.js @@ -0,0 +1,50 @@ +import statuses from '~/feature_flags/store/gitlab_user_list/status'; +import createState from '~/feature_flags/store/gitlab_user_list/state'; +import * as types from '~/feature_flags/store/gitlab_user_list/mutation_types'; +import mutations from '~/feature_flags/store/gitlab_user_list/mutations'; +import { userList } from '../../mock_data'; + +describe('~/feature_flags/store/gitlab_user_list/mutations', () => { + let state; + + beforeEach(() => { + state = createState({ projectId: '8' }); + }); + + describe(types.SET_FILTER, () => { + it('sets the filter in the state', () => { + mutations[types.SET_FILTER](state, 'test'); + expect(state.filter).toBe('test'); + }); + }); + + describe(types.FETCH_USER_LISTS, () => { + it('sets the status to loading', () => { + mutations[types.FETCH_USER_LISTS](state); + expect(state.status).toBe(statuses.LOADING); + }); + }); + + describe(types.RECEIVE_USER_LISTS_SUCCESS, () => { + it('sets the user lists to the ones received', () => { + mutations[types.RECEIVE_USER_LISTS_SUCCESS](state, [userList]); + expect(state.userLists).toEqual([userList]); + }); + + it('sets the status to idle', () => { + mutations[types.RECEIVE_USER_LISTS_SUCCESS](state, [userList]); + expect(state.status).toBe(statuses.IDLE); + }); + }); + describe(types.RECEIVE_USER_LISTS_ERROR, () => { + it('sets the status to error', () => { + mutations[types.RECEIVE_USER_LISTS_ERROR](state, 'failure'); + expect(state.status).toBe(statuses.ERROR); + }); + + it('sets the error message', () => { + mutations[types.RECEIVE_USER_LISTS_ERROR](state, 'failure'); + expect(state.error).toBe('failure'); + }); + }); +}); -- cgit v1.2.1