import { GlFormGroup, GlSprintf, GlModal } from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
import { stubComponent } from 'helpers/stub_component';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import * as ProjectsApi from '~/api/projects_api';
import ImportProjectMembersModal from '~/invite_members/components/import_project_members_modal.vue';
import ProjectSelect from '~/invite_members/components/project_select.vue';
import axios from '~/lib/utils/axios_utils';
let wrapper;
let mock;
const projectId = '1';
const projectName = 'test name';
const projectToBeImported = { id: '2' };
const $toast = {
show: jest.fn(),
};
const createComponent = () => {
wrapper = shallowMountExtended(ImportProjectMembersModal, {
propsData: {
projectId,
projectName,
},
stubs: {
GlModal: stubComponent(GlModal, {
template:
'
',
}),
GlSprintf,
GlFormGroup: stubComponent(GlFormGroup, {
props: ['state', 'invalidFeedback'],
}),
},
mocks: {
$toast,
},
});
};
beforeEach(() => {
gon.api_version = 'v4';
mock = new MockAdapter(axios);
});
afterEach(() => {
wrapper.destroy();
mock.restore();
});
describe('ImportProjectMembersModal', () => {
const findGlModal = () => wrapper.findComponent(GlModal);
const findIntroText = () => wrapper.findComponent({ ref: 'modalIntro' }).text();
const clickImportButton = () => findGlModal().vm.$emit('primary', { preventDefault: jest.fn() });
const closeModal = () => findGlModal().vm.$emit('hidden', { preventDefault: jest.fn() });
const findFormGroup = () => wrapper.findByTestId('form-group');
const formGroupInvalidFeedback = () => findFormGroup().props('invalidFeedback');
const formGroupErrorState = () => findFormGroup().props('state');
const findProjectSelect = () => wrapper.findComponent(ProjectSelect);
describe('rendering the modal', () => {
beforeEach(() => {
createComponent();
});
it('renders the modal with the correct title', () => {
expect(findGlModal().props('title')).toBe('Import members from another project');
});
it('renders the Cancel button text correctly', () => {
expect(findGlModal().props('actionCancel')).toMatchObject({
text: 'Cancel',
});
});
it('renders the Import button text correctly', () => {
expect(findGlModal().props('actionPrimary')).toMatchObject({
text: 'Import project members',
attributes: {
variant: 'confirm',
disabled: true,
loading: false,
},
});
});
it('renders the modal intro text correctly', () => {
expect(findIntroText()).toBe("You're importing members to the test name project.");
});
it('sets isLoading to true when the Invite button is clicked', async () => {
clickImportButton();
await nextTick();
expect(findGlModal().props('actionPrimary').attributes.loading).toBe(true);
});
});
describe('submitting the import', () => {
describe('when the import is successful', () => {
beforeEach(() => {
createComponent();
findProjectSelect().vm.$emit('input', projectToBeImported);
jest.spyOn(ProjectsApi, 'importProjectMembers').mockResolvedValue();
clickImportButton();
});
it('calls Api importProjectMembers', () => {
expect(ProjectsApi.importProjectMembers).toHaveBeenCalledWith(
projectId,
projectToBeImported.id,
);
});
it('displays the successful toastMessage', () => {
expect($toast.show).toHaveBeenCalledWith(
'Successfully imported',
wrapper.vm.$options.toastOptions,
);
});
it('sets isLoading to false after success', () => {
expect(findGlModal().props('actionPrimary').attributes.loading).toBe(false);
});
});
describe('when the import fails', () => {
beforeEach(async () => {
createComponent();
findProjectSelect().vm.$emit('input', projectToBeImported);
jest
.spyOn(ProjectsApi, 'importProjectMembers')
.mockRejectedValue({ response: { data: { success: false } } });
clickImportButton();
await waitForPromises();
});
it('displays the generic error message', () => {
expect(formGroupInvalidFeedback()).toBe('Unable to import project members');
expect(formGroupErrorState()).toBe(false);
});
it('sets isLoading to false after error', () => {
expect(findGlModal().props('actionPrimary').attributes.loading).toBe(false);
});
it('clears the error when the modal is closed with an error', async () => {
expect(formGroupInvalidFeedback()).toBe('Unable to import project members');
expect(formGroupErrorState()).toBe(false);
closeModal();
await nextTick();
expect(formGroupInvalidFeedback()).toBe('');
expect(formGroupErrorState()).not.toBe(false);
});
});
});
});