diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-01-21 18:07:31 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-01-21 18:07:31 +0000 |
commit | d91f5211693e913da5df110b8de841fad87e3653 (patch) | |
tree | d1483aeb8fe3d2b9579b0e44f2e74979c4b8d17a /spec/frontend/registry | |
parent | c859c3bfd242288065fe5e2d887f7204f09e2335 (diff) | |
download | gitlab-ce-d91f5211693e913da5df110b8de841fad87e3653.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/registry')
4 files changed, 159 insertions, 131 deletions
diff --git a/spec/frontend/registry/settings/components/__snapshots__/settings_form_spec.js.snap b/spec/frontend/registry/settings/components/__snapshots__/settings_form_spec.js.snap index d26df308b97..1d8627da181 100644 --- a/spec/frontend/registry/settings/components/__snapshots__/settings_form_spec.js.snap +++ b/spec/frontend/registry/settings/components/__snapshots__/settings_form_spec.js.snap @@ -161,17 +161,20 @@ exports[`Settings Form renders 1`] = ` class="mr-2 d-block" type="reset" > + Cancel + </glbutton-stub> <glbutton-stub - class="d-block" + class="d-flex justify-content-center align-items-center js-no-auto-disable" type="submit" variant="success" > Save expiration policy - + + <!----> </glbutton-stub> </div> </div> diff --git a/spec/frontend/registry/settings/components/registry_settings_app_spec.js b/spec/frontend/registry/settings/components/registry_settings_app_spec.js index 448ff2b3be9..eceb5bf643c 100644 --- a/spec/frontend/registry/settings/components/registry_settings_app_spec.js +++ b/spec/frontend/registry/settings/components/registry_settings_app_spec.js @@ -1,55 +1,55 @@ -import Vuex from 'vuex'; -import { shallowMount, createLocalVue } from '@vue/test-utils'; +import { shallowMount } from '@vue/test-utils'; import component from '~/registry/settings/components/registry_settings_app.vue'; import { createStore } from '~/registry/settings/store/'; - -const localVue = createLocalVue(); -localVue.use(Vuex); +import { FETCH_SETTINGS_ERROR_MESSAGE } from '~/registry/settings/constants'; describe('Registry Settings App', () => { let wrapper; let store; - let fetchSpy; const findSettingsComponent = () => wrapper.find({ ref: 'settings-form' }); - const findLoadingComponent = () => wrapper.find({ ref: 'loading-icon' }); - const mountComponent = (options = {}) => { - fetchSpy = jest.fn(); + const mountComponent = ({ dispatchMock } = {}) => { + store = createStore(); + const dispatchSpy = jest.spyOn(store, 'dispatch'); + if (dispatchMock) { + dispatchSpy[dispatchMock](); + } wrapper = shallowMount(component, { - store, - methods: { - fetchSettings: fetchSpy, + mocks: { + $toast: { + show: jest.fn(), + }, }, - ...options, + store, }); }; - beforeEach(() => { - store = createStore(); - mountComponent(); - }); - afterEach(() => { wrapper.destroy(); }); it('renders', () => { + mountComponent({ dispatchMock: 'mockResolvedValue' }); expect(wrapper.element).toMatchSnapshot(); }); it('call the store function to load the data on mount', () => { - expect(fetchSpy).toHaveBeenCalled(); + mountComponent({ dispatchMock: 'mockResolvedValue' }); + expect(store.dispatch).toHaveBeenCalledWith('fetchSettings'); }); - it('renders a loader if isLoading is true', () => { - store.dispatch('toggleLoading'); - return wrapper.vm.$nextTick().then(() => { - expect(findLoadingComponent().exists()).toBe(true); - expect(findSettingsComponent().exists()).toBe(false); - }); + it('show a toast if fetchSettings fails', () => { + mountComponent({ dispatchMock: 'mockRejectedValue' }); + return wrapper.vm.$nextTick().then(() => + expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(FETCH_SETTINGS_ERROR_MESSAGE, { + type: 'error', + }), + ); }); + it('renders the setting form', () => { + mountComponent({ dispatchMock: 'mockResolvedValue' }); expect(findSettingsComponent().exists()).toBe(true); }); }); diff --git a/spec/frontend/registry/settings/components/settings_form_spec.js b/spec/frontend/registry/settings/components/settings_form_spec.js index bd733e965a4..996804f6d08 100644 --- a/spec/frontend/registry/settings/components/settings_form_spec.js +++ b/spec/frontend/registry/settings/components/settings_form_spec.js @@ -1,39 +1,44 @@ -import Vuex from 'vuex'; -import { mount, createLocalVue } from '@vue/test-utils'; +import { mount } from '@vue/test-utils'; import stubChildren from 'helpers/stub_children'; import component from '~/registry/settings/components/settings_form.vue'; import { createStore } from '~/registry/settings/store/'; -import { NAME_REGEX_LENGTH } from '~/registry/settings/constants'; +import { + NAME_REGEX_LENGTH, + UPDATE_SETTINGS_ERROR_MESSAGE, + UPDATE_SETTINGS_SUCCESS_MESSAGE, +} from '~/registry/settings/constants'; import { stringifiedFormOptions } from '../mock_data'; -const localVue = createLocalVue(); -localVue.use(Vuex); - describe('Settings Form', () => { let wrapper; let store; - let saveSpy; - let resetSpy; + let dispatchSpy; + + const FORM_ELEMENTS_ID_PREFIX = '#expiration-policy'; + + const GlLoadingIcon = { name: 'gl-loading-icon-stub', template: '<svg></svg>' }; - const findFormGroup = name => wrapper.find(`#expiration-policy-${name}-group`); - const findFormElements = (name, father = wrapper) => father.find(`#expiration-policy-${name}`); + const findFormGroup = name => wrapper.find(`${FORM_ELEMENTS_ID_PREFIX}-${name}-group`); + const findFormElements = (name, parent = wrapper) => + parent.find(`${FORM_ELEMENTS_ID_PREFIX}-${name}`); const findCancelButton = () => wrapper.find({ ref: 'cancel-button' }); const findSaveButton = () => wrapper.find({ ref: 'save-button' }); const findForm = () => wrapper.find({ ref: 'form-element' }); + const findLoadingIcon = (parent = wrapper) => parent.find(GlLoadingIcon); const mountComponent = (options = {}) => { - saveSpy = jest.fn(); - resetSpy = jest.fn(); wrapper = mount(component, { stubs: { ...stubChildren(component), GlCard: false, + GlLoadingIcon, }, - store, - methods: { - saveSettings: saveSpy, - resetSettings: resetSpy, + mocks: { + $toast: { + show: jest.fn(), + }, }, + store, ...options, }); }; @@ -41,6 +46,7 @@ describe('Settings Form', () => { beforeEach(() => { store = createStore(); store.dispatch('setInitialState', stringifiedFormOptions); + dispatchSpy = jest.spyOn(store, 'dispatch'); mountComponent(); }); @@ -59,48 +65,53 @@ describe('Settings Form', () => { ${'schedule'} | ${'cadence'} | ${'foo'} | ${'disabled'} ${'latest'} | ${'keep_n'} | ${'foo'} | ${'disabled'} ${'name-matching'} | ${'name_regex'} | ${'foo'} | ${'disabled'} - `('$elementName form element', ({ elementName, modelName, value, disabledByToggle }) => { - let formGroup; - beforeEach(() => { - formGroup = findFormGroup(elementName); - }); - it(`${elementName} form group exist in the dom`, () => { - expect(formGroup.exists()).toBe(true); - }); + `( + `${FORM_ELEMENTS_ID_PREFIX}-$elementName form element`, + ({ elementName, modelName, value, disabledByToggle }) => { + let formGroup; + beforeEach(() => { + formGroup = findFormGroup(elementName); + }); + it(`${elementName} form group exist in the dom`, () => { + expect(formGroup.exists()).toBe(true); + }); - it(`${elementName} form group has a label-for property`, () => { - expect(formGroup.attributes('label-for')).toBe(`expiration-policy-${elementName}`); - }); + it(`${elementName} form group has a label-for property`, () => { + expect(formGroup.attributes('label-for')).toBe(`expiration-policy-${elementName}`); + }); - it(`${elementName} form group has a label-cols property`, () => { - expect(formGroup.attributes('label-cols')).toBe(`${wrapper.vm.$options.labelsConfig.cols}`); - }); + it(`${elementName} form group has a label-cols property`, () => { + expect(formGroup.attributes('label-cols')).toBe(`${wrapper.vm.$options.labelsConfig.cols}`); + }); - it(`${elementName} form group has a label-align property`, () => { - expect(formGroup.attributes('label-align')).toBe(`${wrapper.vm.$options.labelsConfig.align}`); - }); + it(`${elementName} form group has a label-align property`, () => { + expect(formGroup.attributes('label-align')).toBe( + `${wrapper.vm.$options.labelsConfig.align}`, + ); + }); - it(`${elementName} form group contains an input element`, () => { - expect(findFormElements(elementName, formGroup).exists()).toBe(true); - }); + it(`${elementName} form group contains an input element`, () => { + expect(findFormElements(elementName, formGroup).exists()).toBe(true); + }); - it(`${elementName} form element change updated ${modelName} with ${value}`, () => { - const element = findFormElements(elementName, formGroup); - const modelUpdateEvent = element.vm.$options.model - ? element.vm.$options.model.event - : 'input'; - element.vm.$emit(modelUpdateEvent, value); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.vm[modelName]).toBe(value); + it(`${elementName} form element change updated ${modelName} with ${value}`, () => { + const element = findFormElements(elementName, formGroup); + const modelUpdateEvent = element.vm.$options.model + ? element.vm.$options.model.event + : 'input'; + element.vm.$emit(modelUpdateEvent, value); + return wrapper.vm.$nextTick().then(() => { + expect(wrapper.vm[modelName]).toBe(value); + }); }); - }); - it(`${elementName} is ${disabledByToggle} by enabled set to false`, () => { - store.dispatch('updateSettings', { enabled: false }); - const expectation = disabledByToggle === 'disabled' ? 'true' : undefined; - expect(findFormElements(elementName, formGroup).attributes('disabled')).toBe(expectation); - }); - }); + it(`${elementName} is ${disabledByToggle} by enabled set to false`, () => { + store.dispatch('updateSettings', { enabled: false }); + const expectation = disabledByToggle === 'disabled' ? 'true' : undefined; + expect(findFormElements(elementName, formGroup).attributes('disabled')).toBe(expectation); + }); + }, + ); describe('form actions', () => { let form; @@ -112,17 +123,79 @@ describe('Settings Form', () => { }); it('form reset event call the appropriate function', () => { + dispatchSpy.mockReturnValue(); form.trigger('reset'); - expect(resetSpy).toHaveBeenCalled(); + // expect.any(Object) is necessary because the event payload is passed to the function + expect(dispatchSpy).toHaveBeenCalledWith('resetSettings', expect.any(Object)); }); it('save has type submit', () => { expect(findSaveButton().attributes('type')).toBe('submit'); }); - it('form submit event call the appropriate function', () => { - form.trigger('submit'); - expect(saveSpy).toHaveBeenCalled(); + describe('when isLoading is true', () => { + beforeEach(() => { + store.dispatch('toggleLoading'); + }); + + afterEach(() => { + store.dispatch('toggleLoading'); + }); + + it.each` + elementName + ${'toggle'} + ${'interval'} + ${'schedule'} + ${'latest'} + ${'name-matching'} + `(`${FORM_ELEMENTS_ID_PREFIX}-$elementName is disabled`, ({ elementName }) => { + expect(findFormElements(elementName).attributes('disabled')).toBe('true'); + }); + + it('submit button is disabled and shows a spinner', () => { + const button = findSaveButton(); + expect(button.attributes('disabled')).toBeTruthy(); + expect(findLoadingIcon(button)).toExist(); + }); + + it('cancel button is disabled', () => { + expect(findCancelButton().attributes('disabled')).toBeTruthy(); + }); + }); + + describe('form submit event ', () => { + it('calls the appropriate function', () => { + dispatchSpy.mockResolvedValue(); + form.trigger('submit'); + expect(dispatchSpy).toHaveBeenCalled(); + }); + + it('dispatches the saveSettings action', () => { + dispatchSpy.mockResolvedValue(); + form.trigger('submit'); + expect(dispatchSpy).toHaveBeenCalledWith('saveSettings'); + }); + + it('show a success toast when submit succeed', () => { + dispatchSpy.mockResolvedValue(); + form.trigger('submit'); + return wrapper.vm.$nextTick().then(() => { + expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(UPDATE_SETTINGS_SUCCESS_MESSAGE, { + type: 'success', + }); + }); + }); + + it('show an error toast when submit fails', () => { + dispatchSpy.mockRejectedValue(); + form.trigger('submit'); + return wrapper.vm.$nextTick().then(() => { + expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(UPDATE_SETTINGS_ERROR_MESSAGE, { + type: 'error', + }); + }); + }); }); }); @@ -160,7 +233,7 @@ describe('Settings Form', () => { it('toggleDescriptionText text reflects enabled property', () => { const toggleHelpText = findFormGroup('toggle').find('span'); expect(toggleHelpText.html()).toContain('disabled'); - wrapper.vm.enabled = true; + wrapper.setData({ enabled: true }); return wrapper.vm.$nextTick().then(() => { expect(toggleHelpText.html()).toContain('enabled'); }); diff --git a/spec/frontend/registry/settings/store/actions_spec.js b/spec/frontend/registry/settings/store/actions_spec.js index 80fb800ac3a..65b1fc42bfe 100644 --- a/spec/frontend/registry/settings/store/actions_spec.js +++ b/spec/frontend/registry/settings/store/actions_spec.js @@ -1,15 +1,7 @@ import Api from '~/api'; -import createFlash from '~/flash'; import testAction from 'helpers/vuex_action_helper'; import * as actions from '~/registry/settings/store/actions'; import * as types from '~/registry/settings/store/mutation_types'; -import { - UPDATE_SETTINGS_ERROR_MESSAGE, - FETCH_SETTINGS_ERROR_MESSAGE, - UPDATE_SETTINGS_SUCCESS_MESSAGE, -} from '~/registry/settings/constants'; - -jest.mock('~/flash'); describe('Actions Registry Store', () => { describe.each` @@ -25,19 +17,6 @@ describe('Actions Registry Store', () => { }); }); - describe.each` - actionName | message - ${'receiveSettingsError'} | ${FETCH_SETTINGS_ERROR_MESSAGE} - ${'updateSettingsError'} | ${UPDATE_SETTINGS_ERROR_MESSAGE} - `('%s action', ({ actionName, message }) => { - it(`should call createFlash with ${message}`, done => { - testAction(actions[actionName], null, null, [], [], () => { - expect(createFlash).toHaveBeenCalledWith(message); - done(); - }); - }); - }); - describe('fetchSettings', () => { const state = { projectId: 'bar', @@ -64,18 +43,6 @@ describe('Actions Registry Store', () => { done, ); }); - - it('should call receiveSettingsError on error', done => { - Api.project = jest.fn().mockRejectedValue(); - testAction( - actions.fetchSettings, - null, - state, - [], - [{ type: 'toggleLoading' }, { type: 'receiveSettingsError' }, { type: 'toggleLoading' }], - done, - ); - }); }); describe('saveSettings', () => { @@ -102,21 +69,6 @@ describe('Actions Registry Store', () => { { type: 'receiveSettingsSuccess', payload: payload.data.container_expiration_policy }, { type: 'toggleLoading' }, ], - () => { - expect(createFlash).toHaveBeenCalledWith(UPDATE_SETTINGS_SUCCESS_MESSAGE, 'success'); - done(); - }, - ); - }); - - it('should call receiveSettingsError on error', done => { - Api.updateProject = jest.fn().mockRejectedValue(); - testAction( - actions.saveSettings, - null, - state, - [], - [{ type: 'toggleLoading' }, { type: 'updateSettingsError' }, { type: 'toggleLoading' }], done, ); }); |