summaryrefslogtreecommitdiff
path: root/spec/frontend/work_items/components/work_item_links/work_item_tree_spec.js
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/work_items/components/work_item_links/work_item_tree_spec.js')
-rw-r--r--spec/frontend/work_items/components/work_item_links/work_item_tree_spec.js147
1 files changed, 147 insertions, 0 deletions
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
new file mode 100644
index 00000000000..96211e12755
--- /dev/null
+++ b/spec/frontend/work_items/components/work_item_links/work_item_tree_spec.js
@@ -0,0 +1,147 @@
+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 WorkItemTree from '~/work_items/components/work_item_links/work_item_tree.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 workItemQuery from '~/work_items/graphql/work_item.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, workItemObjectiveWithChild } from '../../mock_data';
+
+describe('WorkItemTree', () => {
+ let getWorkItemQueryHandler;
+ let wrapper;
+
+ const findToggleButton = () => wrapper.findByTestId('toggle-tree');
+ const findTreeBody = () => wrapper.findByTestId('tree-body');
+ 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 createComponent = ({
+ workItemType = 'Objective',
+ children = childrenWorkItems,
+ apolloProvider = null,
+ } = {}) => {
+ const mockWorkItemResponse = {
+ data: {
+ workItem: {
+ ...workItemObjectiveWithChild,
+ workItemType: {
+ ...workItemObjectiveWithChild.workItemType,
+ name: workItemType,
+ },
+ },
+ },
+ };
+ getWorkItemQueryHandler = jest.fn().mockResolvedValue(mockWorkItemResponse);
+
+ wrapper = shallowMountExtended(WorkItemTree, {
+ apolloProvider:
+ apolloProvider || createMockApollo([[workItemQuery, getWorkItemQueryHandler]]),
+ propsData: {
+ workItemType,
+ workItemId: 'gid://gitlab/WorkItem/515',
+ children,
+ projectPath: 'test/project',
+ },
+ });
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('is expanded by default and displays Add button', () => {
+ expect(findToggleButton().props('icon')).toBe('chevron-lg-up');
+ expect(findTreeBody().exists()).toBe(true);
+ expect(findToggleFormSplitButton().exists()).toBe(true);
+ });
+
+ it('collapses on click toggle button', async () => {
+ findToggleButton().vm.$emit('click');
+ await nextTick();
+
+ expect(findToggleButton().props('icon')).toBe('chevron-lg-down');
+ expect(findTreeBody().exists()).toBe(false);
+ });
+
+ it('displays empty state if there are no children', () => {
+ createComponent({ children: [] });
+ expect(findEmptyState().exists()).toBe(true);
+ });
+
+ it('renders all hierarchy widget children', () => {
+ expect(findWorkItemLinkChildItems()).toHaveLength(4);
+ });
+
+ it('does not display form by default', () => {
+ expect(findForm().exists()).toBe(false);
+ });
+
+ it.each`
+ option | event | formType | childType
+ ${'New objective'} | ${'showCreateObjectiveForm'} | ${FORM_TYPES.create} | ${WORK_ITEM_TYPE_ENUM_OBJECTIVE}
+ ${'Existing objective'} | ${'showAddObjectiveForm'} | ${FORM_TYPES.add} | ${WORK_ITEM_TYPE_ENUM_OBJECTIVE}
+ ${'New key result'} | ${'showCreateKeyResultForm'} | ${FORM_TYPES.create} | ${WORK_ITEM_TYPE_ENUM_KEY_RESULT}
+ ${'Existing key result'} | ${'showAddKeyResultForm'} | ${FORM_TYPES.add} | ${WORK_ITEM_TYPE_ENUM_KEY_RESULT}
+ `(
+ 'when selecting $option from split button, renders the form passing $formType and $childType',
+ async ({ event, formType, childType }) => {
+ findToggleFormSplitButton().vm.$emit(event);
+ await nextTick();
+
+ expect(findForm().exists()).toBe(true);
+ expect(findForm().props('formType')).toBe(formType);
+ expect(findForm().props('childrenType')).toBe(childType);
+ },
+ );
+
+ it('remove event on child triggers `removeChild` event', () => {
+ const firstChild = findWorkItemLinkChildItems().at(0);
+ firstChild.vm.$emit('removeChild', 'gid://gitlab/WorkItem/2');
+
+ expect(wrapper.emitted('removeChild')).toEqual([['gid://gitlab/WorkItem/2']]);
+ });
+
+ 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();
+ }
+ },
+ );
+});