diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-05-03 12:09:50 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-05-03 12:09:50 +0300 |
commit | 29761d24b86b7a091ca83df4e8cd1cc14f81d534 (patch) | |
tree | eb77242b6d1685f14428caad63edd10e71502d02 /spec/frontend/work_items | |
parent | 74081733481d7d3d480a5e887ac768fe30f84055 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/work_items')
4 files changed, 141 insertions, 115 deletions
diff --git a/spec/frontend/work_items/components/work_item_detail_spec.js b/spec/frontend/work_items/components/work_item_detail_spec.js index 1d164648e27..291dacfd844 100644 --- a/spec/frontend/work_items/components/work_item_detail_spec.js +++ b/spec/frontend/work_items/components/work_item_detail_spec.js @@ -676,7 +676,10 @@ describe('WorkItemDetail component', () => { preventDefault: jest.fn(), }; - findHierarchyTree().vm.$emit('show-modal', event, { id: 'childWorkItemId' }); + findHierarchyTree().vm.$emit('show-modal', { + event, + modalWorkItem: { id: 'childWorkItemId' }, + }); await waitForPromises(); expect(wrapper.findComponent(WorkItemDetailModal).props().workItemId).toBe( @@ -705,7 +708,10 @@ describe('WorkItemDetail component', () => { preventDefault: jest.fn(), }; - findHierarchyTree().vm.$emit('show-modal', event, { id: 'childWorkItemId' }); + findHierarchyTree().vm.$emit('show-modal', { + event, + modalWorkItem: { id: 'childWorkItemId' }, + }); await waitForPromises(); expect(wrapper.emitted('update-modal')).toBeDefined(); 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 new file mode 100644 index 00000000000..ad95350fc67 --- /dev/null +++ b/spec/frontend/work_items/components/work_item_links/work_item_children_wrapper_spec.js @@ -0,0 +1,95 @@ +import Vue, { nextTick } from 'vue'; +import VueApollo from 'vue-apollo'; + +import createMockApollo from 'helpers/mock_apollo_helper'; +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 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'; + +describe('WorkItemChildrenWrapper', () => { + let wrapper; + + const getWorkItemQueryHandler = jest.fn().mockResolvedValue(workItemByIidResponseFactory()); + + const findWorkItemLinkChildItems = () => wrapper.findAllComponents(WorkItemLinkChild); + + Vue.use(VueApollo); + + const createComponent = ({ + workItemType = 'Objective', + confidential = false, + children = childrenWorkItems, + } = {}) => { + wrapper = shallowMountExtended(WorkItemChildrenWrapper, { + apolloProvider: createMockApollo([[workItemByIidQuery, getWorkItemQueryHandler]]), + propsData: { + workItemType, + workItemId: 'gid://gitlab/WorkItem/515', + confidential, + children, + projectPath: 'test/project', + fetchByIid: true, + }, + }); + }; + + it('renders all hierarchy widget children', () => { + createComponent(); + + const workItemLinkChildren = findWorkItemLinkChildItems(); + expect(workItemLinkChildren).toHaveLength(4); + expect(workItemLinkChildren.at(0).props().childItem.confidential).toBe( + childrenWorkItems[0].confidential, + ); + }); + + it('remove event on child triggers `removeChild` event', () => { + createComponent(); + const firstChild = findWorkItemLinkChildItems().at(0); + + firstChild.vm.$emit('removeChild', 'gid://gitlab/WorkItem/2'); + + expect(wrapper.emitted('removeChild')).toEqual([['gid://gitlab/WorkItem/2']]); + }); + + it('emits `show-modal` on `click` event', () => { + createComponent(); + const firstChild = findWorkItemLinkChildItems().at(0); + const event = { + childItem: 'gid://gitlab/WorkItem/2', + }; + + firstChild.vm.$emit('click', event); + + expect(wrapper.emitted('show-modal')).toEqual([[{ event, child: event.childItem }]]); + }); + + it.each` + description | workItemType | prefetch + ${'prefetches'} | ${'Issue'} | ${true} + ${'does not prefetch'} | ${'Objective'} | ${false} + `( + '$description work-item-link-child on mouseover when workItemType is "$workItemType"', + async ({ workItemType, prefetch }) => { + createComponent({ workItemType }); + const firstChild = findWorkItemLinkChildItems().at(0); + firstChild.vm.$emit('mouseover', childrenWorkItems[0]); + await nextTick(); + await waitForPromises(); + + jest.advanceTimersByTime(DEFAULT_DEBOUNCE_AND_THROTTLE_MS); + + if (prefetch) { + expect(getWorkItemQueryHandler).toHaveBeenCalled(); + } else { + expect(getWorkItemQueryHandler).not.toHaveBeenCalled(); + } + }, + ); +}); 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 1d78f35615a..b889836023d 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 @@ -5,17 +5,16 @@ 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 { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants'; 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'; import WorkItemLinks from '~/work_items/components/work_item_links/work_item_links.vue'; -import WorkItemLinkChild from '~/work_items/components/work_item_links/work_item_link_child.vue'; +import WorkItemChildrenWrapper from '~/work_items/components/work_item_links/work_item_children_wrapper.vue'; 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 getWorkItemLinksQuery from '~/work_items/graphql/work_item_links.query.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, @@ -26,6 +25,7 @@ import { workItemByIidResponseFactory, workItemQueryResponse, mockWorkItemCommentNote, + childrenWorkItems, } from '../../mock_data'; Vue.use(VueApollo); @@ -56,7 +56,7 @@ describe('WorkItemLinks', () => { } = {}) => { mockApollo = createMockApollo( [ - [getWorkItemLinksQuery, fetchHandler], + [workItemQuery, fetchHandler], [changeWorkItemParentMutation, mutationHandler], [issueDetailsQuery, issueDetailsQueryHandler], [workItemByIidQuery, childWorkItemByIidHandler], @@ -100,12 +100,11 @@ describe('WorkItemLinks', () => { const findToggleFormDropdown = () => wrapper.findByTestId('toggle-form'); const findToggleAddFormButton = () => wrapper.findByTestId('toggle-add-form'); const findToggleCreateFormButton = () => wrapper.findByTestId('toggle-create-form'); - const findWorkItemLinkChildItems = () => wrapper.findAllComponents(WorkItemLinkChild); - const findFirstWorkItemLinkChild = () => findWorkItemLinkChildItems().at(0); const findAddLinksForm = () => wrapper.findByTestId('add-links-form'); const findChildrenCount = () => wrapper.findByTestId('children-count'); const findWorkItemDetailModal = () => wrapper.findComponent(WorkItemDetailModal); const findAbuseCategorySelector = () => wrapper.findComponent(AbuseCategorySelector); + const findWorkItemLinkChildrenWrapper = () => wrapper.findComponent(WorkItemChildrenWrapper); afterEach(() => { mockApollo = null; @@ -153,12 +152,12 @@ describe('WorkItemLinks', () => { findToggleCreateFormButton().vm.$emit('click'); await nextTick(); - expect(findWorkItemLinkChildItems()).toHaveLength(4); + expect(findWorkItemLinkChildrenWrapper().props().children).toHaveLength(4); findAddLinksForm().vm.$emit('addWorkItemChild', workItem); await waitForPromises(); - expect(findWorkItemLinkChildItems()).toHaveLength(5); + expect(findWorkItemLinkChildrenWrapper().props().children).toHaveLength(5); }); }); @@ -174,10 +173,11 @@ describe('WorkItemLinks', () => { }); }); - it('renders all hierarchy widget children', async () => { + it('renders hierarchy widget children container', async () => { await createComponent(); - expect(findWorkItemLinkChildItems()).toHaveLength(4); + expect(findWorkItemLinkChildrenWrapper().exists()).toBe(true); + expect(findWorkItemLinkChildrenWrapper().props().children).toHaveLength(4); }); it('shows an alert when list loading fails', async () => { @@ -208,7 +208,7 @@ describe('WorkItemLinks', () => { }); it('does not display link menu on children', () => { - expect(findWorkItemLinkChildItems().at(0).props('canUpdate')).toBe(false); + expect(findWorkItemLinkChildrenWrapper().props('canUpdate')).toBe(false); }); }); @@ -218,11 +218,11 @@ describe('WorkItemLinks', () => { beforeEach(async () => { await createComponent({ mutationHandler: mutationChangeParentHandler }); - firstChild = findFirstWorkItemLinkChild(); + [firstChild] = childrenWorkItems; }); it('calls correct mutation with correct variables', async () => { - firstChild.vm.$emit('removeChild', firstChild.vm.childItem.id); + findWorkItemLinkChildrenWrapper().vm.$emit('removeChild', firstChild.id); await waitForPromises(); @@ -237,7 +237,7 @@ describe('WorkItemLinks', () => { }); it('shows toast when mutation succeeds', async () => { - firstChild.vm.$emit('removeChild', firstChild.vm.childItem.id); + findWorkItemLinkChildrenWrapper().vm.$emit('removeChild', firstChild.id); await waitForPromises(); @@ -247,12 +247,12 @@ describe('WorkItemLinks', () => { }); it('renders correct number of children after removal', async () => { - expect(findWorkItemLinkChildItems()).toHaveLength(4); + expect(findWorkItemLinkChildrenWrapper().props().children).toHaveLength(4); - firstChild.vm.$emit('removeChild', firstChild.vm.childItem.id); + findWorkItemLinkChildrenWrapper().vm.$emit('removeChild', firstChild.id); await waitForPromises(); - expect(findWorkItemLinkChildItems()).toHaveLength(3); + expect(findWorkItemLinkChildrenWrapper().props().children).toHaveLength(3); }); }); @@ -271,41 +271,6 @@ describe('WorkItemLinks', () => { }); }); - describe('prefetching child items', () => { - let firstChild; - - beforeEach(async () => { - setWindowLocation('?iid_path=true'); - await createComponent(); - - firstChild = findFirstWorkItemLinkChild(); - }); - - it('does not fetch the child work item by iid before hovering work item links', () => { - expect(childWorkItemByIidHandler).not.toHaveBeenCalled(); - }); - - it('fetches the child work item by iid if link is hovered for 250+ ms', async () => { - firstChild.vm.$emit('mouseover', firstChild.vm.childItem.id); - jest.advanceTimersByTime(DEFAULT_DEBOUNCE_AND_THROTTLE_MS); - await waitForPromises(); - - expect(childWorkItemByIidHandler).toHaveBeenCalledWith({ - fullPath: 'project/path', - iid: '2', - }); - }); - - it('does not fetch the child work item by iid if link is hovered for less than 250 ms', async () => { - firstChild.vm.$emit('mouseover', firstChild.vm.childItem.id); - jest.advanceTimersByTime(200); - firstChild.vm.$emit('mouseout', firstChild.vm.childItem.id); - await waitForPromises(); - - expect(childWorkItemByIidHandler).not.toHaveBeenCalled(); - }); - }); - it('starts prefetching work item by iid if URL contains work_item_iid query parameter', async () => { setWindowLocation('?work_item_iid=5'); 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 f6b70d0161a..710ed85bd97 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,44 +1,34 @@ -import Vue, { nextTick } from 'vue'; -import VueApollo from 'vue-apollo'; +import { nextTick } from 'vue'; -import createMockApollo from 'helpers/mock_apollo_helper'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; -import waitForPromises from 'helpers/wait_for_promises'; 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'; -import WorkItemLinkChild from '~/work_items/components/work_item_links/work_item_link_child.vue'; import OkrActionsSplitButton from '~/work_items/components/work_item_links/okr_actions_split_button.vue'; -import workItemByIidQuery from '~/work_items/graphql/work_item_by_iid.query.graphql'; - -import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants'; import { FORM_TYPES, WORK_ITEM_TYPE_ENUM_OBJECTIVE, WORK_ITEM_TYPE_ENUM_KEY_RESULT, } from '~/work_items/constants'; -import { childrenWorkItems, workItemByIidResponseFactory } from '../../mock_data'; +import { childrenWorkItems } from '../../mock_data'; describe('WorkItemTree', () => { let wrapper; - const getWorkItemQueryHandler = jest.fn().mockResolvedValue(workItemByIidResponseFactory()); - const findEmptyState = () => wrapper.findByTestId('tree-empty'); const findToggleFormSplitButton = () => wrapper.findComponent(OkrActionsSplitButton); const findForm = () => wrapper.findComponent(WorkItemLinksForm); - const findWorkItemLinkChildItems = () => wrapper.findAllComponents(WorkItemLinkChild); - - Vue.use(VueApollo); + const findWorkItemLinkChildrenWrapper = () => wrapper.findComponent(WorkItemChildrenWrapper); const createComponent = ({ workItemType = 'Objective', parentWorkItemType = 'Objective', confidential = false, children = childrenWorkItems, + canUpdate = true, } = {}) => { wrapper = shallowMountExtended(WorkItemTree, { - apolloProvider: createMockApollo([[workItemByIidQuery, getWorkItemQueryHandler]]), propsData: { workItemType, parentWorkItemType, @@ -46,6 +36,7 @@ describe('WorkItemTree', () => { confidential, children, projectPath: 'test/project', + canUpdate, }, }); @@ -64,14 +55,11 @@ describe('WorkItemTree', () => { expect(findEmptyState().exists()).toBe(true); }); - it('renders all hierarchy widget children', () => { + it('renders hierarchy widget children container', () => { createComponent(); - const workItemLinkChildren = findWorkItemLinkChildItems(); - expect(workItemLinkChildren).toHaveLength(4); - expect(workItemLinkChildren.at(0).props().childItem.confidential).toBe( - childrenWorkItems[0].confidential, - ); + expect(findWorkItemLinkChildrenWrapper().exists()).toBe(true); + expect(findWorkItemLinkChildrenWrapper().props().children).toHaveLength(4); }); it('does not display form by default', () => { @@ -104,47 +92,19 @@ describe('WorkItemTree', () => { }, ); - it('remove event on child triggers `removeChild` event', () => { - createComponent(); - const firstChild = findWorkItemLinkChildItems().at(0); - - firstChild.vm.$emit('removeChild', 'gid://gitlab/WorkItem/2'); - - expect(wrapper.emitted('removeChild')).toEqual([['gid://gitlab/WorkItem/2']]); - }); - - it('emits `show-modal` on `click` event', () => { - createComponent(); - const firstChild = findWorkItemLinkChildItems().at(0); - const event = { - childItem: 'gid://gitlab/WorkItem/2', - }; + describe('when no permission to update', () => { + beforeEach(() => { + createComponent({ + canUpdate: false, + }); + }); - firstChild.vm.$emit('click', event); + it('does not display button to toggle Add form', () => { + expect(findToggleFormSplitButton().exists()).toBe(false); + }); - expect(wrapper.emitted('show-modal')).toEqual([[event, event.childItem]]); + it('does not display link menu on children', () => { + expect(findWorkItemLinkChildrenWrapper().props('canUpdate')).toBe(false); + }); }); - - it.each` - description | workItemType | prefetch - ${'prefetches'} | ${'Issue'} | ${true} - ${'does not prefetch'} | ${'Objective'} | ${false} - `( - '$description work-item-link-child on mouseover when workItemType is "$workItemType"', - async ({ workItemType, prefetch }) => { - createComponent({ workItemType }); - const firstChild = findWorkItemLinkChildItems().at(0); - firstChild.vm.$emit('mouseover', childrenWorkItems[0]); - await nextTick(); - await waitForPromises(); - - jest.advanceTimersByTime(DEFAULT_DEBOUNCE_AND_THROTTLE_MS); - - if (prefetch) { - expect(getWorkItemQueryHandler).toHaveBeenCalled(); - } else { - expect(getWorkItemQueryHandler).not.toHaveBeenCalled(); - } - }, - ); }); |