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_links')
-rw-r--r--spec/frontend/work_items/components/work_item_links/work_item_children_wrapper_spec.js86
-rw-r--r--spec/frontend/work_items/components/work_item_links/work_item_links_spec.js116
-rw-r--r--spec/frontend/work_items/components/work_item_links/work_item_tree_spec.js12
3 files changed, 95 insertions, 119 deletions
diff --git a/spec/frontend/work_items/components/work_item_links/work_item_children_wrapper_spec.js b/spec/frontend/work_items/components/work_item_links/work_item_children_wrapper_spec.js
index b06be6c8083..cd077fbf705 100644
--- a/spec/frontend/work_items/components/work_item_links/work_item_children_wrapper_spec.js
+++ b/spec/frontend/work_items/components/work_item_links/work_item_children_wrapper_spec.js
@@ -6,16 +6,28 @@ import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import WorkItemChildrenWrapper from '~/work_items/components/work_item_links/work_item_children_wrapper.vue';
import WorkItemLinkChild from '~/work_items/components/work_item_links/work_item_link_child.vue';
+import updateWorkItemMutation from '~/work_items/graphql/update_work_item.mutation.graphql';
import workItemByIidQuery from '~/work_items/graphql/work_item_by_iid.query.graphql';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
-import { childrenWorkItems, workItemByIidResponseFactory } from '../../mock_data';
+import {
+ changeWorkItemParentMutationResponse,
+ childrenWorkItems,
+ updateWorkItemMutationErrorResponse,
+ workItemByIidResponseFactory,
+} from '../../mock_data';
describe('WorkItemChildrenWrapper', () => {
let wrapper;
+ const $toast = {
+ show: jest.fn(),
+ };
const getWorkItemQueryHandler = jest.fn().mockResolvedValue(workItemByIidResponseFactory());
+ const updateWorkItemMutationHandler = jest
+ .fn()
+ .mockResolvedValue(changeWorkItemParentMutationResponse);
const findWorkItemLinkChildItems = () => wrapper.findAllComponents(WorkItemLinkChild);
@@ -25,18 +37,33 @@ describe('WorkItemChildrenWrapper', () => {
workItemType = 'Objective',
confidential = false,
children = childrenWorkItems,
+ mutationHandler = updateWorkItemMutationHandler,
} = {}) => {
+ const mockApollo = createMockApollo([
+ [workItemByIidQuery, getWorkItemQueryHandler],
+ [updateWorkItemMutation, mutationHandler],
+ ]);
+
+ mockApollo.clients.defaultClient.cache.writeQuery({
+ query: workItemByIidQuery,
+ variables: { fullPath: 'test/project', iid: '1' },
+ data: workItemByIidResponseFactory().data,
+ });
+
wrapper = shallowMountExtended(WorkItemChildrenWrapper, {
- apolloProvider: createMockApollo([[workItemByIidQuery, getWorkItemQueryHandler]]),
+ apolloProvider: mockApollo,
provide: {
fullPath: 'test/project',
},
propsData: {
workItemType,
workItemId: 'gid://gitlab/WorkItem/515',
+ workItemIid: '1',
confidential,
children,
- fetchByIid: true,
+ },
+ mocks: {
+ $toast,
},
});
};
@@ -51,16 +78,6 @@ describe('WorkItemChildrenWrapper', () => {
);
});
- it('remove event on child triggers `removeChild` event', () => {
- createComponent();
- const workItem = { id: 'gid://gitlab/WorkItem/2' };
- const firstChild = findWorkItemLinkChildItems().at(0);
-
- firstChild.vm.$emit('removeChild', workItem);
-
- expect(wrapper.emitted('removeChild')).toEqual([[workItem]]);
- });
-
it('emits `show-modal` on `click` event', () => {
createComponent();
const firstChild = findWorkItemLinkChildItems().at(0);
@@ -95,4 +112,47 @@ describe('WorkItemChildrenWrapper', () => {
}
},
);
+
+ describe('when removing child work item', () => {
+ const workItem = { id: 'gid://gitlab/WorkItem/2' };
+
+ describe('when successful', () => {
+ beforeEach(async () => {
+ createComponent();
+ findWorkItemLinkChildItems().at(0).vm.$emit('removeChild', workItem);
+ await waitForPromises();
+ });
+
+ it('calls a mutation to update the work item', () => {
+ expect(updateWorkItemMutationHandler).toHaveBeenCalledWith({
+ input: {
+ id: workItem.id,
+ hierarchyWidget: {
+ parentId: null,
+ },
+ },
+ });
+ });
+
+ it('shows a toast', () => {
+ expect($toast.show).toHaveBeenCalledWith('Child removed', {
+ action: { onClick: expect.anything(), text: 'Undo' },
+ });
+ });
+ });
+
+ describe('when not successful', () => {
+ beforeEach(async () => {
+ createComponent({
+ mutationHandler: jest.fn().mockResolvedValue(updateWorkItemMutationErrorResponse),
+ });
+ findWorkItemLinkChildItems().at(0).vm.$emit('removeChild', workItem);
+ await waitForPromises();
+ });
+
+ it('emits an error message', () => {
+ expect(wrapper.emitted('error')).toEqual([['Something went wrong while removing child.']]);
+ });
+ });
+ });
});
diff --git a/spec/frontend/work_items/components/work_item_links/work_item_links_spec.js b/spec/frontend/work_items/components/work_item_links/work_item_links_spec.js
index 786f8604039..dd46505bd65 100644
--- a/spec/frontend/work_items/components/work_item_links/work_item_links_spec.js
+++ b/spec/frontend/work_items/components/work_item_links/work_item_links_spec.js
@@ -4,7 +4,7 @@ import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import setWindowLocation from 'helpers/set_window_location_helper';
-import { stubComponent } from 'helpers/stub_component';
+import { RENDER_ALL_SLOTS_TEMPLATE, stubComponent } from 'helpers/stub_component';
import issueDetailsQuery from 'ee_else_ce/work_items/graphql/get_issue_details.query.graphql';
import { resolvers } from '~/graphql_shared/issuable_client';
import WidgetWrapper from '~/work_items/components/widget_wrapper.vue';
@@ -13,19 +13,14 @@ import WorkItemChildrenWrapper from '~/work_items/components/work_item_links/wor
import WorkItemDetailModal from '~/work_items/components/work_item_detail_modal.vue';
import AbuseCategorySelector from '~/abuse_reports/components/abuse_category_selector.vue';
import { FORM_TYPES } from '~/work_items/constants';
-import changeWorkItemParentMutation from '~/work_items/graphql/update_work_item.mutation.graphql';
-import workItemQuery from '~/work_items/graphql/work_item.query.graphql';
import workItemByIidQuery from '~/work_items/graphql/work_item_by_iid.query.graphql';
import {
getIssueDetailsResponse,
workItemHierarchyResponse,
workItemHierarchyEmptyResponse,
workItemHierarchyNoUpdatePermissionResponse,
- changeWorkItemParentMutationResponse,
workItemByIidResponseFactory,
- workItemQueryResponse,
mockWorkItemCommentNote,
- childrenWorkItems,
} from '../../mock_data';
Vue.use(VueApollo);
@@ -36,66 +31,48 @@ describe('WorkItemLinks', () => {
let wrapper;
let mockApollo;
- const WORK_ITEM_ID = 'gid://gitlab/WorkItem/2';
-
- const $toast = {
- show: jest.fn(),
- };
-
- const mutationChangeParentHandler = jest
- .fn()
- .mockResolvedValue(changeWorkItemParentMutationResponse);
- const childWorkItemByIidHandler = jest.fn().mockResolvedValue(workItemByIidResponseFactory());
const responseWithAddChildPermission = jest.fn().mockResolvedValue(workItemHierarchyResponse);
const responseWithoutAddChildPermission = jest
.fn()
.mockResolvedValue(workItemByIidResponseFactory({ adminParentLink: false }));
const createComponent = async ({
- data = {},
fetchHandler = responseWithAddChildPermission,
- mutationHandler = mutationChangeParentHandler,
issueDetailsQueryHandler = jest.fn().mockResolvedValue(getIssueDetailsResponse()),
hasIterationsFeature = false,
} = {}) => {
mockApollo = createMockApollo(
[
- [workItemQuery, fetchHandler],
- [changeWorkItemParentMutation, mutationHandler],
+ [workItemByIidQuery, fetchHandler],
[issueDetailsQuery, issueDetailsQueryHandler],
- [workItemByIidQuery, childWorkItemByIidHandler],
],
resolvers,
{ addTypename: true },
);
wrapper = shallowMountExtended(WorkItemLinks, {
- data() {
- return {
- ...data,
- };
- },
provide: {
fullPath: 'project/path',
hasIterationsFeature,
reportAbusePath: '/report/abuse/path',
},
- propsData: { issuableId: 1 },
- apolloProvider: mockApollo,
- mocks: {
- $toast,
+ propsData: {
+ issuableId: 1,
+ issuableIid: 1,
},
+ apolloProvider: mockApollo,
stubs: {
WorkItemDetailModal: stubComponent(WorkItemDetailModal, {
methods: {
show: showModal,
},
}),
+ WidgetWrapper: stubComponent(WidgetWrapper, {
+ template: RENDER_ALL_SLOTS_TEMPLATE,
+ }),
},
});
- wrapper.vm.$refs.wrapper.show = jest.fn();
-
await waitForPromises();
};
@@ -122,8 +99,7 @@ describe('WorkItemLinks', () => {
`(
'$expectedAssertion "Add" button in hierarchy widget header when "userPermissions.adminParentLink" is $value',
async ({ workItemFetchHandler, value }) => {
- createComponent({ fetchHandler: workItemFetchHandler });
- await waitForPromises();
+ await createComponent({ fetchHandler: workItemFetchHandler });
expect(findToggleFormDropdown().exists()).toBe(value);
},
@@ -159,24 +135,6 @@ describe('WorkItemLinks', () => {
expect(findAddLinksForm().exists()).toBe(false);
});
-
- it('adds work item child from the form', async () => {
- const workItem = {
- ...workItemQueryResponse.data.workItem,
- id: 'gid://gitlab/WorkItem/11',
- };
- await createComponent();
- findToggleFormDropdown().vm.$emit('click');
- findToggleCreateFormButton().vm.$emit('click');
- await nextTick();
-
- expect(findWorkItemLinkChildrenWrapper().props().children).toHaveLength(4);
-
- findAddLinksForm().vm.$emit('addWorkItemChild', workItem);
- await waitForPromises();
-
- expect(findWorkItemLinkChildrenWrapper().props().children).toHaveLength(5);
- });
});
describe('when no child links', () => {
@@ -230,50 +188,6 @@ describe('WorkItemLinks', () => {
});
});
- describe('remove child', () => {
- let firstChild;
-
- beforeEach(async () => {
- await createComponent({ mutationHandler: mutationChangeParentHandler });
-
- [firstChild] = childrenWorkItems;
- });
-
- it('calls correct mutation with correct variables', async () => {
- findWorkItemLinkChildrenWrapper().vm.$emit('removeChild', firstChild);
-
- await waitForPromises();
-
- expect(mutationChangeParentHandler).toHaveBeenCalledWith({
- input: {
- id: WORK_ITEM_ID,
- hierarchyWidget: {
- parentId: null,
- },
- },
- });
- });
-
- it('shows toast when mutation succeeds', async () => {
- findWorkItemLinkChildrenWrapper().vm.$emit('removeChild', firstChild);
-
- await waitForPromises();
-
- expect($toast.show).toHaveBeenCalledWith('Child removed', {
- action: { onClick: expect.anything(), text: 'Undo' },
- });
- });
-
- it('renders correct number of children after removal', async () => {
- expect(findWorkItemLinkChildrenWrapper().props().children).toHaveLength(4);
-
- findWorkItemLinkChildrenWrapper().vm.$emit('removeChild', firstChild);
- await waitForPromises();
-
- expect(findWorkItemLinkChildrenWrapper().props().children).toHaveLength(3);
- });
- });
-
describe('when parent item is confidential', () => {
it('passes correct confidentiality status to form', async () => {
await createComponent({
@@ -289,16 +203,6 @@ describe('WorkItemLinks', () => {
});
});
- it('starts prefetching work item by iid if URL contains work_item_iid query parameter', async () => {
- setWindowLocation('?work_item_iid=5');
- await createComponent();
-
- expect(childWorkItemByIidHandler).toHaveBeenCalledWith({
- iid: '5',
- fullPath: 'project/path',
- });
- });
-
it('does not open the modal if work item iid URL parameter is not found in child items', async () => {
setWindowLocation('?work_item_iid=555');
await createComponent();
diff --git a/spec/frontend/work_items/components/work_item_links/work_item_tree_spec.js b/spec/frontend/work_items/components/work_item_links/work_item_tree_spec.js
index 06716584879..f3aa347f389 100644
--- a/spec/frontend/work_items/components/work_item_links/work_item_tree_spec.js
+++ b/spec/frontend/work_items/components/work_item_links/work_item_tree_spec.js
@@ -1,6 +1,7 @@
import { nextTick } from 'vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import WidgetWrapper from '~/work_items/components/widget_wrapper.vue';
import WorkItemTree from '~/work_items/components/work_item_links/work_item_tree.vue';
import WorkItemChildrenWrapper from '~/work_items/components/work_item_links/work_item_children_wrapper.vue';
import WorkItemLinksForm from '~/work_items/components/work_item_links/work_item_links_form.vue';
@@ -19,6 +20,7 @@ describe('WorkItemTree', () => {
const findEmptyState = () => wrapper.findByTestId('tree-empty');
const findToggleFormSplitButton = () => wrapper.findComponent(OkrActionsSplitButton);
const findForm = () => wrapper.findComponent(WorkItemLinksForm);
+ const findWidgetWrapper = () => wrapper.findComponent(WidgetWrapper);
const findWorkItemLinkChildrenWrapper = () => wrapper.findComponent(WorkItemChildrenWrapper);
const createComponent = ({
@@ -70,6 +72,16 @@ describe('WorkItemTree', () => {
expect(findForm().exists()).toBe(false);
});
+ it('shows an error message on error', async () => {
+ const errorMessage = 'Some error';
+ createComponent();
+
+ findWorkItemLinkChildrenWrapper().vm.$emit('error', errorMessage);
+ await nextTick();
+
+ expect(findWidgetWrapper().props('error')).toBe(errorMessage);
+ });
+
it.each`
option | event | formType | childType
${'New objective'} | ${'showCreateObjectiveForm'} | ${FORM_TYPES.create} | ${WORK_ITEM_TYPE_ENUM_OBJECTIVE}