summaryrefslogtreecommitdiff
path: root/spec/frontend/registry
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-01-21 18:07:31 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-01-21 18:07:31 +0000
commitd91f5211693e913da5df110b8de841fad87e3653 (patch)
treed1483aeb8fe3d2b9579b0e44f2e74979c4b8d17a /spec/frontend/registry
parentc859c3bfd242288065fe5e2d887f7204f09e2335 (diff)
downloadgitlab-ce-d91f5211693e913da5df110b8de841fad87e3653.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/registry')
-rw-r--r--spec/frontend/registry/settings/components/__snapshots__/settings_form_spec.js.snap7
-rw-r--r--spec/frontend/registry/settings/components/registry_settings_app_spec.js50
-rw-r--r--spec/frontend/registry/settings/components/settings_form_spec.js185
-rw-r--r--spec/frontend/registry/settings/store/actions_spec.js48
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,
);
});