2021-11-23 15:11:19 +00:00
|
|
|
import Vue, { nextTick } from 'vue';
|
|
|
|
import VueApollo from 'vue-apollo';
|
2022-03-18 12:07:43 +00:00
|
|
|
import { GlAlert, GlFormSelect } from '@gitlab/ui';
|
2021-11-23 15:11:19 +00:00
|
|
|
import { shallowMount } from '@vue/test-utils';
|
|
|
|
import createMockApollo from 'helpers/mock_apollo_helper';
|
|
|
|
import waitForPromises from 'helpers/wait_for_promises';
|
|
|
|
import CreateWorkItem from '~/work_items/pages/create_work_item.vue';
|
2021-12-08 12:13:04 +00:00
|
|
|
import ItemTitle from '~/work_items/components/item_title.vue';
|
2022-02-09 18:16:19 +00:00
|
|
|
import projectWorkItemTypesQuery from '~/work_items/graphql/project_work_item_types.query.graphql';
|
2022-03-10 06:09:00 +00:00
|
|
|
import createWorkItemMutation from '~/work_items/graphql/create_work_item.mutation.graphql';
|
2022-03-18 12:07:43 +00:00
|
|
|
import createWorkItemFromTaskMutation from '~/work_items/graphql/create_work_item_from_task.mutation.graphql';
|
|
|
|
import {
|
|
|
|
projectWorkItemTypesQueryResponse,
|
|
|
|
createWorkItemMutationResponse,
|
|
|
|
createWorkItemFromTaskMutationResponse,
|
|
|
|
} from '../mock_data';
|
2021-11-23 15:11:19 +00:00
|
|
|
|
2022-02-23 15:14:44 +00:00
|
|
|
jest.mock('~/lib/utils/uuids', () => ({ uuids: () => ['testuuid'] }));
|
|
|
|
|
2021-11-23 15:11:19 +00:00
|
|
|
Vue.use(VueApollo);
|
|
|
|
|
|
|
|
describe('Create work item component', () => {
|
|
|
|
let wrapper;
|
|
|
|
let fakeApollo;
|
|
|
|
|
2022-02-09 18:16:19 +00:00
|
|
|
const querySuccessHandler = jest.fn().mockResolvedValue(projectWorkItemTypesQueryResponse);
|
2022-03-18 12:07:43 +00:00
|
|
|
const createWorkItemSuccessHandler = jest.fn().mockResolvedValue(createWorkItemMutationResponse);
|
|
|
|
const createWorkItemFromTaskSuccessHandler = jest
|
|
|
|
.fn()
|
|
|
|
.mockResolvedValue(createWorkItemFromTaskMutationResponse);
|
|
|
|
const errorHandler = jest.fn().mockRejectedValue('Houston, we have a problem');
|
2022-02-09 18:16:19 +00:00
|
|
|
|
2021-11-23 15:11:19 +00:00
|
|
|
const findAlert = () => wrapper.findComponent(GlAlert);
|
2021-12-08 12:13:04 +00:00
|
|
|
const findTitleInput = () => wrapper.findComponent(ItemTitle);
|
2022-03-18 12:07:43 +00:00
|
|
|
const findSelect = () => wrapper.findComponent(GlFormSelect);
|
2022-02-09 18:16:19 +00:00
|
|
|
|
2021-11-23 15:11:19 +00:00
|
|
|
const findCreateButton = () => wrapper.find('[data-testid="create-button"]');
|
|
|
|
const findCancelButton = () => wrapper.find('[data-testid="cancel-button"]');
|
2022-02-09 18:16:19 +00:00
|
|
|
const findContent = () => wrapper.find('[data-testid="content"]');
|
|
|
|
const findLoadingTypesIcon = () => wrapper.find('[data-testid="loading-types"]');
|
2021-11-23 15:11:19 +00:00
|
|
|
|
2022-03-10 06:09:00 +00:00
|
|
|
const createComponent = ({
|
|
|
|
data = {},
|
|
|
|
props = {},
|
|
|
|
queryHandler = querySuccessHandler,
|
2022-03-18 12:07:43 +00:00
|
|
|
mutationHandler = createWorkItemSuccessHandler,
|
2022-03-10 06:09:00 +00:00
|
|
|
} = {}) => {
|
2022-03-24 15:09:10 +00:00
|
|
|
fakeApollo = createMockApollo([
|
|
|
|
[projectWorkItemTypesQuery, queryHandler],
|
|
|
|
[createWorkItemMutation, mutationHandler],
|
|
|
|
[createWorkItemFromTaskMutation, mutationHandler],
|
|
|
|
]);
|
2021-11-23 15:11:19 +00:00
|
|
|
wrapper = shallowMount(CreateWorkItem, {
|
|
|
|
apolloProvider: fakeApollo,
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
...data,
|
|
|
|
};
|
|
|
|
},
|
2022-01-25 15:12:32 +00:00
|
|
|
propsData: {
|
|
|
|
...props,
|
|
|
|
},
|
2021-11-23 15:11:19 +00:00
|
|
|
mocks: {
|
|
|
|
$router: {
|
|
|
|
go: jest.fn(),
|
|
|
|
push: jest.fn(),
|
|
|
|
},
|
|
|
|
},
|
2022-02-09 18:16:19 +00:00
|
|
|
provide: {
|
|
|
|
fullPath: 'full-path',
|
|
|
|
},
|
2021-11-23 15:11:19 +00:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
wrapper.destroy();
|
|
|
|
fakeApollo = null;
|
|
|
|
});
|
|
|
|
|
|
|
|
it('does not render error by default', () => {
|
|
|
|
createComponent();
|
|
|
|
|
|
|
|
expect(findAlert().exists()).toBe(false);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('renders a disabled Create button when title input is empty', () => {
|
|
|
|
createComponent();
|
|
|
|
|
|
|
|
expect(findCreateButton().props('disabled')).toBe(true);
|
|
|
|
});
|
|
|
|
|
2022-01-25 15:12:32 +00:00
|
|
|
describe('when displayed on a separate route', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
createComponent();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('redirects to the previous page on Cancel button click', () => {
|
|
|
|
findCancelButton().vm.$emit('click');
|
|
|
|
|
|
|
|
expect(wrapper.vm.$router.go).toHaveBeenCalledWith(-1);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('redirects to the work item page on successful mutation', async () => {
|
|
|
|
findTitleInput().vm.$emit('title-input', 'Test title');
|
|
|
|
|
|
|
|
wrapper.find('form').trigger('submit');
|
|
|
|
await waitForPromises();
|
|
|
|
|
|
|
|
expect(wrapper.vm.$router.push).toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('adds right margin for create button', () => {
|
|
|
|
expect(findCreateButton().classes()).toContain('gl-mr-3');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('does not add right margin for cancel button', () => {
|
|
|
|
expect(findCancelButton().classes()).not.toContain('gl-mr-3');
|
|
|
|
});
|
2022-02-09 18:16:19 +00:00
|
|
|
|
|
|
|
it('does not add padding for content', () => {
|
|
|
|
expect(findContent().classes('gl-px-5')).toBe(false);
|
|
|
|
});
|
2022-01-25 15:12:32 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
describe('when displayed in a modal', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
createComponent({
|
|
|
|
props: {
|
|
|
|
isModal: true,
|
|
|
|
},
|
2022-03-18 12:07:43 +00:00
|
|
|
mutationHandler: createWorkItemFromTaskSuccessHandler,
|
2022-01-25 15:12:32 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('emits `closeModal` event on Cancel button click', () => {
|
|
|
|
findCancelButton().vm.$emit('click');
|
2021-11-23 15:11:19 +00:00
|
|
|
|
2022-01-25 15:12:32 +00:00
|
|
|
expect(wrapper.emitted('closeModal')).toEqual([[]]);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('emits `onCreate` on successful mutation', async () => {
|
|
|
|
findTitleInput().vm.$emit('title-input', 'Test title');
|
|
|
|
|
|
|
|
wrapper.find('form').trigger('submit');
|
|
|
|
await waitForPromises();
|
|
|
|
|
2022-03-18 12:07:43 +00:00
|
|
|
expect(wrapper.emitted('onCreate')).toEqual([['<p>New description</p>']]);
|
2022-01-25 15:12:32 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it('does not right margin for create button', () => {
|
|
|
|
expect(findCreateButton().classes()).not.toContain('gl-mr-3');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('adds right margin for cancel button', () => {
|
|
|
|
expect(findCancelButton().classes()).toContain('gl-mr-3');
|
|
|
|
});
|
2022-02-09 18:16:19 +00:00
|
|
|
|
|
|
|
it('adds padding for content', () => {
|
|
|
|
expect(findContent().classes('gl-px-5')).toBe(true);
|
|
|
|
});
|
2022-05-02 12:10:01 +00:00
|
|
|
|
|
|
|
it('defaults type to `Task`', async () => {
|
|
|
|
await waitForPromises();
|
|
|
|
expect(findSelect().attributes('value')).toBe('gid://gitlab/WorkItems::Type/3');
|
|
|
|
});
|
2022-02-09 18:16:19 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it('displays a loading icon inside dropdown when work items query is loading', () => {
|
|
|
|
createComponent();
|
|
|
|
|
|
|
|
expect(findLoadingTypesIcon().exists()).toBe(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('displays an alert when work items query is rejected', async () => {
|
|
|
|
createComponent({ queryHandler: jest.fn().mockRejectedValue('Houston, we have a problem') });
|
|
|
|
await waitForPromises();
|
|
|
|
|
|
|
|
expect(findAlert().exists()).toBe(true);
|
|
|
|
expect(findAlert().text()).toContain('fetching work item types');
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('when work item types are fetched', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
createComponent();
|
|
|
|
return waitForPromises();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('displays a list of work item types', () => {
|
2022-05-02 12:10:01 +00:00
|
|
|
expect(findSelect().attributes('options').split(',')).toHaveLength(4);
|
2022-02-09 18:16:19 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it('selects a work item type on click', async () => {
|
2022-03-18 12:07:43 +00:00
|
|
|
const mockId = 'work-item-1';
|
|
|
|
findSelect().vm.$emit('input', mockId);
|
2022-02-09 18:16:19 +00:00
|
|
|
await nextTick();
|
2022-03-18 12:07:43 +00:00
|
|
|
expect(findSelect().attributes('value')).toBe(mockId);
|
2022-02-09 18:16:19 +00:00
|
|
|
});
|
2021-11-23 15:11:19 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it('hides the alert on dismissing the error', async () => {
|
|
|
|
createComponent({ data: { error: true } });
|
2022-01-25 15:12:32 +00:00
|
|
|
|
2021-11-23 15:11:19 +00:00
|
|
|
expect(findAlert().exists()).toBe(true);
|
|
|
|
|
|
|
|
findAlert().vm.$emit('dismiss');
|
|
|
|
await nextTick();
|
2022-01-25 15:12:32 +00:00
|
|
|
|
2021-11-23 15:11:19 +00:00
|
|
|
expect(findAlert().exists()).toBe(false);
|
|
|
|
});
|
|
|
|
|
2022-01-25 15:12:32 +00:00
|
|
|
it('displays an initial title if passed', () => {
|
|
|
|
const initialTitle = 'Initial Title';
|
|
|
|
createComponent({
|
|
|
|
props: { initialTitle },
|
|
|
|
});
|
2022-03-24 12:07:26 +00:00
|
|
|
expect(findTitleInput().props('title')).toBe(initialTitle);
|
2022-01-25 15:12:32 +00:00
|
|
|
});
|
|
|
|
|
2021-11-23 15:11:19 +00:00
|
|
|
describe('when title input field has a text', () => {
|
2022-03-18 12:07:43 +00:00
|
|
|
beforeEach(async () => {
|
2021-12-08 12:13:04 +00:00
|
|
|
const mockTitle = 'Test title';
|
2021-11-23 15:11:19 +00:00
|
|
|
createComponent();
|
2022-03-18 12:07:43 +00:00
|
|
|
await waitForPromises();
|
2022-01-25 15:12:32 +00:00
|
|
|
findTitleInput().vm.$emit('title-input', mockTitle);
|
2021-11-23 15:11:19 +00:00
|
|
|
});
|
|
|
|
|
2022-03-18 12:07:43 +00:00
|
|
|
it('renders a disabled Create button', () => {
|
|
|
|
expect(findCreateButton().props('disabled')).toBe(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('renders a non-disabled Create button when work item type is selected', async () => {
|
|
|
|
findSelect().vm.$emit('input', 'work-item-1');
|
|
|
|
await nextTick();
|
2021-11-23 15:11:19 +00:00
|
|
|
expect(findCreateButton().props('disabled')).toBe(false);
|
|
|
|
});
|
2022-03-18 12:07:43 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it('shows an alert on mutation error', async () => {
|
|
|
|
createComponent({ mutationHandler: errorHandler });
|
|
|
|
await waitForPromises();
|
|
|
|
findTitleInput().vm.$emit('title-input', 'some title');
|
|
|
|
findSelect().vm.$emit('input', 'work-item-1');
|
|
|
|
wrapper.find('form').trigger('submit');
|
|
|
|
await waitForPromises();
|
2021-11-23 15:11:19 +00:00
|
|
|
|
2022-03-18 12:07:43 +00:00
|
|
|
expect(findAlert().text()).toBe(CreateWorkItem.createErrorText);
|
2021-11-23 15:11:19 +00:00
|
|
|
});
|
|
|
|
});
|