gitlab-ce/spec/frontend/groups/components/group_path_field_spec.js

178 lines
5.4 KiB
JavaScript

import { merge } from 'lodash';
import { GlInputGroupText } from '@gitlab/ui';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import GroupPathField from '~/groups/components/group_path_field.vue';
import { getGroupPathAvailability } from '~/rest_api';
import { createAlert } from '~/alert';
jest.mock('~/alert');
jest.mock('~/rest_api', () => ({
getGroupPathAvailability: jest.fn(),
}));
describe('GroupPathField', () => {
let wrapper;
const mockGroupUrlSuggested = 'my-awesome-group1';
const defaultPropsData = {
id: 'path',
value: '',
basePath: 'http://gitlab.com/',
};
const createComponent = ({ propsData = {} } = {}) => {
wrapper = mountExtended(GroupPathField, {
propsData: merge({}, defaultPropsData, propsData),
});
};
const apiMockAvailablePath = () => {
getGroupPathAvailability.mockResolvedValueOnce({
data: { exists: false, suggests: [] },
});
};
const apiMockUnavailablePath = (suggests = [mockGroupUrlSuggested]) => {
getGroupPathAvailability.mockResolvedValueOnce({
data: { exists: true, suggests },
});
};
it('renders base path', () => {
createComponent();
expect(wrapper.findComponent(GlInputGroupText).text()).toBe(defaultPropsData.basePath);
});
describe('when `value` prop is updated', () => {
describe('when value is the suggested path', () => {
beforeEach(async () => {
apiMockUnavailablePath();
createComponent();
await wrapper.setProps({ value: 'foo' });
await waitForPromises();
await wrapper.setProps({ value: mockGroupUrlSuggested });
});
it('does not call API', () => {
expect(getGroupPathAvailability).toHaveBeenCalledTimes(1);
});
});
describe('when editing a group and path is set to initial path', () => {
beforeEach(async () => {
apiMockUnavailablePath();
createComponent({ propsData: { isEditing: true, value: 'foo' } });
await wrapper.setProps({ value: 'foo bar' });
await waitForPromises();
await wrapper.setProps({ value: 'foo' });
});
it('does not call API', () => {
expect(getGroupPathAvailability).toHaveBeenCalledTimes(1);
});
});
describe('when value is not the suggested path', () => {
describe('when value is an unavailable path', () => {
beforeEach(async () => {
apiMockUnavailablePath();
createComponent();
await wrapper.setProps({ value: 'foo' });
await waitForPromises();
});
it('emits `loading-change` event', () => {
expect(wrapper.emitted('loading-change')).toEqual([[true], [false]]);
});
it('emits `input-suggested-path` event', () => {
expect(wrapper.emitted('input-suggested-path')).toEqual([[mockGroupUrlSuggested]]);
});
it('emits `state-change` event', () => {
expect(wrapper.emitted('state-change')).toEqual([[false]]);
});
});
describe('when value is an available path', () => {
beforeEach(async () => {
apiMockAvailablePath();
createComponent();
await wrapper.setProps({ value: 'foo' });
await waitForPromises();
});
it('emits `loading-change` event', () => {
expect(wrapper.emitted('loading-change')).toEqual([[true], [false]]);
});
it('does not emit `input-suggested-path` event', () => {
expect(wrapper.emitted('input-suggested-path')).toBeUndefined();
});
it('emits `state-change` event', () => {
expect(wrapper.emitted('state-change')).toEqual([[true]]);
});
});
describe('when API returns no suggestions', () => {
beforeEach(async () => {
apiMockUnavailablePath([]);
createComponent();
await wrapper.setProps({ value: 'foo' });
await waitForPromises();
});
it('calls `createAlert`', () => {
expect(createAlert).toHaveBeenCalledWith({
message: 'An error occurred while checking group path. Please refresh and try again.',
});
});
});
describe('when API call fails', () => {
beforeEach(async () => {
getGroupPathAvailability.mockRejectedValueOnce();
createComponent();
await wrapper.setProps({ value: 'foo' });
await waitForPromises();
});
it('calls `createAlert`', () => {
expect(createAlert).toHaveBeenCalledWith({
message: 'An error occurred while checking group path. Please refresh and try again.',
});
});
});
});
describe('when multiple API calls are in-flight', () => {
it('aborts the first API call and resolves second API call', async () => {
getGroupPathAvailability.mockRejectedValueOnce({ __CANCEL__: true });
apiMockUnavailablePath();
const abortSpy = jest.spyOn(AbortController.prototype, 'abort');
createComponent();
await wrapper.setProps({ value: 'foo' });
await wrapper.setProps({ value: 'foo-bar' });
await waitForPromises();
expect(createAlert).not.toHaveBeenCalled();
expect(wrapper.emitted('input-suggested-path')).toEqual([[mockGroupUrlSuggested]]);
expect(abortSpy).toHaveBeenCalled();
});
});
});
});