Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/work_items/components/work_item_relationships/work_item_relationships_spec.js')
-rw-r--r--spec/frontend/work_items/components/work_item_relationships/work_item_relationships_spec.js157
1 files changed, 149 insertions, 8 deletions
diff --git a/spec/frontend/work_items/components/work_item_relationships/work_item_relationships_spec.js b/spec/frontend/work_items/components/work_item_relationships/work_item_relationships_spec.js
index c9a2499b127..7178fa1aae7 100644
--- a/spec/frontend/work_items/components/work_item_relationships/work_item_relationships_spec.js
+++ b/spec/frontend/work_items/components/work_item_relationships/work_item_relationships_spec.js
@@ -9,12 +9,17 @@ import waitForPromises from 'helpers/wait_for_promises';
import WidgetWrapper from '~/work_items/components/widget_wrapper.vue';
import WorkItemRelationships from '~/work_items/components/work_item_relationships/work_item_relationships.vue';
import WorkItemRelationshipList from '~/work_items/components/work_item_relationships/work_item_relationship_list.vue';
+import WorkItemAddRelationshipForm from '~/work_items/components/work_item_relationships/work_item_add_relationship_form.vue';
+import groupWorkItemByIidQuery from '~/work_items/graphql/group_work_item_by_iid.query.graphql';
import workItemByIidQuery from '~/work_items/graphql/work_item_by_iid.query.graphql';
+import removeLinkedItemsMutation from '~/work_items/graphql/remove_linked_items.mutation.graphql';
import {
+ groupWorkItemByIidResponseFactory,
workItemByIidResponseFactory,
mockLinkedItems,
mockBlockingLinkedItem,
+ removeLinkedWorkItemResponse,
} from '../../mock_data';
describe('WorkItemRelationships', () => {
@@ -24,23 +29,44 @@ describe('WorkItemRelationships', () => {
const emptyLinkedWorkItemsQueryHandler = jest
.fn()
.mockResolvedValue(workItemByIidResponseFactory());
- const linkedWorkItemsQueryHandler = jest
+ const groupWorkItemsQueryHandler = jest
.fn()
- .mockResolvedValue(workItemByIidResponseFactory({ linkedItems: mockLinkedItems }));
- const blockingLinkedWorkItemQueryHandler = jest
+ .mockResolvedValue(groupWorkItemByIidResponseFactory());
+ const removeLinkedWorkItemSuccessMutationHandler = jest
.fn()
- .mockResolvedValue(workItemByIidResponseFactory({ linkedItems: mockBlockingLinkedItem }));
+ .mockResolvedValue(removeLinkedWorkItemResponse('Successfully unlinked IDs: 2.'));
+ const removeLinkedWorkItemErrorMutationHandler = jest
+ .fn()
+ .mockResolvedValue(removeLinkedWorkItemResponse(null, ['Linked item removal failed']));
+ const $toast = {
+ show: jest.fn(),
+ };
const createComponent = async ({
workItemQueryHandler = emptyLinkedWorkItemsQueryHandler,
+ workItemType = 'Task',
+ isGroup = false,
+ removeLinkedWorkItemMutationHandler = removeLinkedWorkItemSuccessMutationHandler,
} = {}) => {
- const mockApollo = createMockApollo([[workItemByIidQuery, workItemQueryHandler]]);
+ const mockApollo = createMockApollo([
+ [workItemByIidQuery, workItemQueryHandler],
+ [removeLinkedItemsMutation, removeLinkedWorkItemMutationHandler],
+ [groupWorkItemByIidQuery, groupWorkItemsQueryHandler],
+ ]);
wrapper = shallowMountExtended(WorkItemRelationships, {
apolloProvider: mockApollo,
propsData: {
+ workItemId: 'gid://gitlab/WorkItem/1',
workItemIid: '1',
workItemFullPath: 'test-project-path',
+ workItemType,
+ },
+ provide: {
+ isGroup,
+ },
+ mocks: {
+ $toast,
},
});
@@ -51,8 +77,11 @@ describe('WorkItemRelationships', () => {
const findWidgetWrapper = () => wrapper.findComponent(WidgetWrapper);
const findEmptyRelatedMessageContainer = () => wrapper.findByTestId('links-empty');
const findLinkedItemsCountContainer = () => wrapper.findByTestId('linked-items-count');
+ const findLinkedItemsHelpLink = () => wrapper.findByTestId('help-link');
const findAllWorkItemRelationshipListComponents = () =>
wrapper.findAllComponents(WorkItemRelationshipList);
+ const findAddButton = () => wrapper.findByTestId('link-item-add-button');
+ const findWorkItemRelationshipForm = () => wrapper.findComponent(WorkItemAddRelationshipForm);
it('shows loading icon when query is not processed', () => {
createComponent();
@@ -60,22 +89,35 @@ describe('WorkItemRelationships', () => {
expect(findLoadingIcon().exists()).toBe(true);
});
- it('renders the component with empty message when there are no items', async () => {
+ it('renders the component with with defaults', async () => {
await createComponent();
expect(wrapper.find('.work-item-relationships').exists()).toBe(true);
expect(findEmptyRelatedMessageContainer().exists()).toBe(true);
+ expect(findAddButton().exists()).toBe(true);
+ expect(findWorkItemRelationshipForm().exists()).toBe(false);
+ expect(findLinkedItemsHelpLink().attributes('href')).toBe(
+ '/help/user/okrs.md#linked-items-in-okrs',
+ );
});
it('renders blocking linked item lists', async () => {
- await createComponent({ workItemQueryHandler: blockingLinkedWorkItemQueryHandler });
+ await createComponent({
+ workItemQueryHandler: jest
+ .fn()
+ .mockResolvedValue(workItemByIidResponseFactory({ linkedItems: mockBlockingLinkedItem })),
+ });
expect(findAllWorkItemRelationshipListComponents().length).toBe(1);
expect(findLinkedItemsCountContainer().text()).toBe('1');
});
it('renders blocking, blocked by and related to linked item lists with proper count', async () => {
- await createComponent({ workItemQueryHandler: linkedWorkItemsQueryHandler });
+ await createComponent({
+ workItemQueryHandler: jest
+ .fn()
+ .mockResolvedValue(workItemByIidResponseFactory({ linkedItems: mockLinkedItems })),
+ });
// renders all 3 lists: blocking, blocked by and related to
expect(findAllWorkItemRelationshipListComponents().length).toBe(3);
@@ -90,4 +132,103 @@ describe('WorkItemRelationships', () => {
expect(findWidgetWrapper().props('error')).toBe(errorMessage);
});
+
+ it('does not render add button when there is no permission', async () => {
+ await createComponent({
+ workItemQueryHandler: jest
+ .fn()
+ .mockResolvedValue(workItemByIidResponseFactory({ canAdminWorkItemLink: false })),
+ });
+
+ expect(findAddButton().exists()).toBe(false);
+ });
+
+ it('shows form on add button and hides when cancel button is clicked', async () => {
+ await createComponent();
+
+ await findAddButton().vm.$emit('click');
+ expect(findWorkItemRelationshipForm().exists()).toBe(true);
+
+ await findWorkItemRelationshipForm().vm.$emit('cancel');
+ expect(findWorkItemRelationshipForm().exists()).toBe(false);
+ });
+
+ describe('when project context', () => {
+ it('calls the project work item query', () => {
+ createComponent();
+
+ expect(emptyLinkedWorkItemsQueryHandler).toHaveBeenCalled();
+ });
+
+ it('skips calling the group work item query', () => {
+ createComponent();
+
+ expect(groupWorkItemsQueryHandler).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('when group context', () => {
+ it('skips calling the project work item query', () => {
+ createComponent({ isGroup: true });
+
+ expect(emptyLinkedWorkItemsQueryHandler).not.toHaveBeenCalled();
+ });
+
+ it('calls the group work item query', () => {
+ createComponent({ isGroup: true });
+
+ expect(groupWorkItemsQueryHandler).toHaveBeenCalled();
+ });
+ });
+
+ it('removes linked item and shows toast message when removeLinkedItem event is emitted', async () => {
+ await createComponent({
+ workItemQueryHandler: jest
+ .fn()
+ .mockResolvedValue(workItemByIidResponseFactory({ linkedItems: mockLinkedItems })),
+ });
+
+ expect(findLinkedItemsCountContainer().text()).toBe('3');
+
+ await findAllWorkItemRelationshipListComponents()
+ .at(0)
+ .vm.$emit('removeLinkedItem', { id: 'gid://gitlab/WorkItem/2' });
+
+ await waitForPromises();
+
+ expect(removeLinkedWorkItemSuccessMutationHandler).toHaveBeenCalledWith({
+ input: {
+ id: 'gid://gitlab/WorkItem/1',
+ workItemsIds: ['gid://gitlab/WorkItem/2'],
+ },
+ });
+
+ expect($toast.show).toHaveBeenCalledWith('Linked item removed');
+
+ expect(findLinkedItemsCountContainer().text()).toBe('2');
+ });
+
+ it.each`
+ errorType | mutationMock | errorMessage
+ ${'an error in the mutation response'} | ${removeLinkedWorkItemErrorMutationHandler} | ${'Linked item removal failed'}
+ ${'a network error'} | ${jest.fn().mockRejectedValue(new Error('Network Error'))} | ${'Something went wrong when removing item. Please refresh this page.'}
+ `(
+ 'shows an error message when there is $errorType while removing items',
+ async ({ mutationMock, errorMessage }) => {
+ await createComponent({
+ workItemQueryHandler: jest
+ .fn()
+ .mockResolvedValue(workItemByIidResponseFactory({ linkedItems: mockLinkedItems })),
+ removeLinkedWorkItemMutationHandler: mutationMock,
+ });
+
+ await findAllWorkItemRelationshipListComponents()
+ .at(0)
+ .vm.$emit('removeLinkedItem', { id: 'gid://gitlab/WorkItem/2' });
+
+ await waitForPromises();
+
+ expect(findWidgetWrapper().props('error')).toBe(errorMessage);
+ },
+ );
});