Commit b2d14975 authored by Mario de la Ossa's avatar Mario de la Ossa

Related Issues - move to FOSS

This is the final commit that moves Related Issues to FOSS
parent 787ad7eb
import initSidebarBundle from '~/sidebar/sidebar_bundle';
import initRelatedIssues from '~/related_issues';
import initShow from '../show';
document.addEventListener('DOMContentLoaded', () => {
......@@ -6,4 +7,5 @@ document.addEventListener('DOMContentLoaded', () => {
if (gon.features && !gon.features.vueIssuableSidebar) {
initSidebarBundle();
}
initRelatedIssues();
});
<script>
import { GlLoadingIcon } from '@gitlab/ui';
import Sortable from 'sortablejs';
import sortableConfig from 'ee/sortable/sortable_config';
import sortableConfig from 'ee_else_ce/sortable/sortable_config';
import RelatedIssuableItem from '~/vue_shared/components/issue/related_issuable_item.vue';
import tooltip from '~/vue_shared/directives/tooltip';
......
......@@ -17,6 +17,9 @@ export default function initRelatedIssues() {
endpoint: relatedIssuesRootElement.dataset.endpoint,
canAdmin: parseBoolean(relatedIssuesRootElement.dataset.canAddRelatedIssues),
helpPath: relatedIssuesRootElement.dataset.helpPath,
showCategorizedIssues: parseBoolean(
relatedIssuesRootElement.dataset.showCategorizedIssues,
),
},
}),
});
......
- if can?(current_user, :read_issue_link, @project)
.js-related-issues-root{ data: { endpoint: project_issue_links_path(@project, @issue),
can_add_related_issues: "#{can?(current_user, :admin_issue_link, @issue)}",
help_path: help_page_path('user/project/issues/related_issues'),
show_categorized_issues: "false" } }
- render('projects/issues/related_issues_block')
.related-issues-block
.card.card-slim
.card-header.panel-empty-heading.border-bottom-0
%h3.card-title.mt-0.mb-0.h5
= _('Linked issues')
---
title: Move related issues to core
merge_request: 39779
author:
type: changed
<script>
import { mapState, mapGetters } from 'vuex';
import { PathIdSeparator } from 'ee/related_issues/constants';
import { PathIdSeparator } from '~/related_issues/constants';
import IssuableBody from '~/issue_show/components/app.vue';
import IssuableSidebar from '~/issuable_sidebar/components/sidebar_app.vue';
......
......@@ -11,7 +11,7 @@ import {
GlSprintf,
} from '@gitlab/ui';
import Api from 'ee/api';
import RelatedIssuesRoot from 'ee/related_issues/components/related_issues_root.vue';
import RelatedIssuesRoot from '~/related_issues/components/related_issues_root.vue';
import { s__ } from '~/locale';
import { deprecatedCreateFlash as flash, FLASH_TYPES } from '~/flash';
import featureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
......
import initSidebarBundle from 'ee/sidebar/sidebar_bundle';
import initRelatedIssues from 'ee/related_issues';
import trackShowInviteMemberLink from 'ee/projects/track_invite_members';
import initRelatedIssues from '~/related_issues';
import initShow from '~/pages/projects/issues/show';
import UserCallout from '~/user_callout';
......
<script>
import RelatedIssuableInput from 'ee/related_issues/components/related_issuable_input.vue';
import { issuableTypesMap } from 'ee/related_issues/constants';
import RelatedIssuableInput from '~/related_issues/components/related_issuable_input.vue';
import { issuableTypesMap } from '~/related_issues/constants';
export default {
components: {
......
......@@ -3,7 +3,7 @@ import { mapState, mapActions, mapGetters } from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui';
import AddItemForm from 'ee/related_issues/components/add_issuable_form.vue';
import AddItemForm from '~/related_issues/components/add_issuable_form.vue';
import SlotSwitch from '~/vue_shared/components/slot_switch.vue';
import CreateEpicForm from './create_epic_form.vue';
import CreateIssueForm from './create_issue_form.vue';
......
......@@ -3,7 +3,7 @@ import { mapState, mapActions } from 'vuex';
import { GlTooltip, GlIcon } from '@gitlab/ui';
import { issuableTypesMap } from 'ee/related_issues/constants';
import { issuableTypesMap } from '~/related_issues/constants';
import EpicActionsSplitButton from './epic_issue_actions_split_button.vue';
import EpicHealthStatus from './epic_health_status.vue';
......
......@@ -4,7 +4,7 @@ import {
itemAddFailureTypesMap,
pathIndeterminateErrorMap,
relatedIssuesRemoveErrorMap,
} from 'ee/related_issues/constants';
} from '~/related_issues/constants';
import { deprecatedCreateFlash as flash } from '~/flash';
import { s__, __ } from '~/locale';
import axios from '~/lib/utils/axios_utils';
......
import { issuableTypesMap, PathIdSeparator } from 'ee/related_issues/constants';
import { issuableTypesMap, PathIdSeparator } from '~/related_issues/constants';
export const autoCompleteSources = () => gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources;
......
import Vue from 'vue';
import { issuableTypesMap } from 'ee/related_issues/constants';
import { issuableTypesMap } from '~/related_issues/constants';
import * as types from './mutation_types';
export default {
......
import { PathIdSeparator } from 'ee/related_issues/constants';
import { PathIdSeparator } from '~/related_issues/constants';
import createGqClient, { fetchPolicies } from '~/lib/graphql';
import { ChildType } from '../constants';
......
<script>
import axios from 'axios';
import { GlButton } from '@gitlab/ui';
import RelatedIssuesStore from 'ee/related_issues/stores/related_issues_store';
import RelatedIssuesBlock from 'ee/related_issues/components/related_issues_block.vue';
import { issuableTypesMap, PathIdSeparator } from 'ee/related_issues/constants';
import RelatedIssuesStore from '~/related_issues/stores/related_issues_store';
import RelatedIssuesBlock from '~/related_issues/components/related_issues_block.vue';
import { issuableTypesMap, PathIdSeparator } from '~/related_issues/constants';
import { sprintf, __, s__ } from '~/locale';
import { joinPaths, redirectTo } from '~/lib/utils/url_utility';
import { RELATED_ISSUES_ERRORS, FEEDBACK_TYPES } from '../constants';
......
- if can?(current_user, :read_issue_link, @project)
.js-related-issues-root{ data: { endpoint: project_issue_links_path(@project, @issue),
can_add_related_issues: "#{can?(current_user, :admin_issue_link, @issue)}",
help_path: help_page_path('user/project/issues/related_issues') } }
.related-issues-block
.card.card-slim
.card-header.panel-empty-heading.border-bottom-0
%h3.card-title.mt-0.mb-0.h5
= _('Linked issues')
help_path: help_page_path('user/project/issues/related_issues'),
show_categorized_issues: "#{!!@project.feature_available?(:blocked_issues)}" } }
- render('projects/issues/related_issues_block')
......@@ -13,7 +13,7 @@ import {
LEGACY_FLAG,
NEW_VERSION_FLAG,
} from 'ee/feature_flags/constants';
import RelatedIssuesRoot from 'ee/related_issues/components/related_issues_root.vue';
import RelatedIssuesRoot from '~/related_issues/components/related_issues_root.vue';
import ToggleButton from '~/vue_shared/components/toggle_button.vue';
import { featureFlag, userList, allUsersStrategy } from '../mock_data';
......
import { mount, shallowMount } from '@vue/test-utils';
import { mount } from '@vue/test-utils';
import { issuable1 } from 'jest/vue_shared/components/issue/related_issuable_mock_data';
import IssueWeight from 'ee/boards/components/issue_card_weight.vue';
import RelatedIssuesList from 'ee/related_issues/components/related_issues_list.vue';
import {
issuable1,
issuable2,
issuable3,
issuable4,
issuable5,
} from 'jest/vue_shared/components/issue/related_issuable_mock_data';
import { PathIdSeparator } from 'ee/related_issues/constants';
import IssueDueDate from '~/boards/components/issue_due_date.vue';
import RelatedIssuesList from '~/related_issues/components/related_issues_list.vue';
import { PathIdSeparator } from '~/related_issues/constants';
/*
* Here we only test the behavior of Related Issues with Weight, as weight is an EE-only feature.
*/
describe('RelatedIssuesList', () => {
let wrapper;
......@@ -18,156 +14,6 @@ describe('RelatedIssuesList', () => {
wrapper.destroy();
});
describe('with defaults', () => {
const heading = 'Related to';
beforeEach(() => {
wrapper = shallowMount(RelatedIssuesList, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
issuableType: 'issue',
heading,
},
});
});
it('shows a heading', () => {
expect(wrapper.find('h4').text()).toContain(heading);
});
it('should not show loading icon', () => {
expect(wrapper.vm.$refs.loadingIcon).toBeUndefined();
});
});
describe('with isFetching=true', () => {
beforeEach(() => {
wrapper = shallowMount(RelatedIssuesList, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
isFetching: true,
issuableType: 'issue',
},
});
});
it('should show loading icon', () => {
expect(wrapper.vm.$refs.loadingIcon).toBeDefined();
});
});
describe('methods', () => {
beforeEach(() => {
wrapper = shallowMount(RelatedIssuesList, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
relatedIssues: [issuable1, issuable2, issuable3, issuable4, issuable5],
issuableType: 'issue',
},
});
});
it('updates the order correctly when an item is moved to the top', () => {
const beforeAfterIds = wrapper.vm.getBeforeAfterId(
wrapper.vm.$el.querySelector('ul li:first-child'),
);
expect(beforeAfterIds.beforeId).toBeNull();
expect(beforeAfterIds.afterId).toBe(2);
});
it('updates the order correctly when an item is moved to the bottom', () => {
const beforeAfterIds = wrapper.vm.getBeforeAfterId(
wrapper.vm.$el.querySelector('ul li:last-child'),
);
expect(beforeAfterIds.beforeId).toBe(4);
expect(beforeAfterIds.afterId).toBeNull();
});
it('updates the order correctly when an item is swapped with adjacent item', () => {
const beforeAfterIds = wrapper.vm.getBeforeAfterId(
wrapper.vm.$el.querySelector('ul li:nth-child(3)'),
);
expect(beforeAfterIds.beforeId).toBe(2);
expect(beforeAfterIds.afterId).toBe(4);
});
it('updates the order correctly when an item is moved somewhere in the middle', () => {
const beforeAfterIds = wrapper.vm.getBeforeAfterId(
wrapper.vm.$el.querySelector('ul li:nth-child(4)'),
);
expect(beforeAfterIds.beforeId).toBe(3);
expect(beforeAfterIds.afterId).toBe(5);
});
});
describe('issuableOrderingId returns correct issuable order id when', () => {
it('issuableType is epic', () => {
wrapper = shallowMount(RelatedIssuesList, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
issuableType: 'issue',
},
});
expect(wrapper.vm.issuableOrderingId(issuable1)).toBe(issuable1.epicIssueId);
});
it('issuableType is issue', () => {
wrapper = shallowMount(RelatedIssuesList, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
issuableType: 'epic',
},
});
expect(wrapper.vm.issuableOrderingId(issuable1)).toBe(issuable1.id);
});
});
describe('renders correct ordering id when', () => {
let relatedIssues;
beforeAll(() => {
relatedIssues = [issuable1, issuable2, issuable3, issuable4, issuable5];
});
it('issuableType is epic', () => {
wrapper = shallowMount(RelatedIssuesList, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
issuableType: 'epic',
relatedIssues,
},
});
const listItems = wrapper.vm.$el.querySelectorAll('.list-item');
Array.from(listItems).forEach((item, index) => {
expect(Number(item.dataset.orderingId)).toBe(relatedIssues[index].id);
});
});
it('issuableType is issue', () => {
wrapper = shallowMount(RelatedIssuesList, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
issuableType: 'issue',
relatedIssues,
},
});
const listItems = wrapper.vm.$el.querySelectorAll('.list-item');
Array.from(listItems).forEach((item, index) => {
expect(Number(item.dataset.orderingId)).toBe(relatedIssues[index].epicIssueId);
});
});
});
describe('related item contents', () => {
beforeAll(() => {
wrapper = mount(RelatedIssuesList, {
......@@ -187,14 +33,5 @@ describe('RelatedIssuesList', () => {
.text(),
).toBe(issuable1.weight.toString());
});
it('shows due date', () => {
expect(
wrapper
.find(IssueDueDate)
.find('.board-card-info-text')
.text(),
).toBe('Nov 22, 2010');
});
});
});
import { shallowMount } from '@vue/test-utils';
import BlockingMrInputRoot from 'ee/projects/merge_requests/blocking_mr_input_root.vue';
import RelatedIssuableInput from 'ee/related_issues/components/related_issuable_input.vue';
import RelatedIssuableInput from '~/related_issues/components/related_issuable_input.vue';
describe('blocking mr input root', () => {
let wrapper;
......
import { shallowMount } from '@vue/test-utils';
import { TEST_HOST } from 'helpers/test_constants';
import { issuableTypesMap, PathIdSeparator } from 'ee/related_issues/constants';
import RelatedIssuableInput from 'ee/related_issues/components/related_issuable_input.vue';
import { issuableTypesMap, PathIdSeparator } from '~/related_issues/constants';
import RelatedIssuableInput from '~/related_issues/components/related_issuable_input.vue';
jest.mock('ee_else_ce/gfm_auto_complete', () => {
return function gfmAutoComplete() {
......
......@@ -5,10 +5,10 @@ import { GlLoadingIcon } from '@gitlab/ui';
import RelatedItemsTreeApp from 'ee/related_items_tree/components/related_items_tree_app.vue';
import RelatedItemsTreeHeader from 'ee/related_items_tree/components/related_items_tree_header.vue';
import createDefaultStore from 'ee/related_items_tree/store';
import { issuableTypesMap } from 'ee/related_issues/constants';
import CreateIssueForm from 'ee/related_items_tree/components/create_issue_form.vue';
import AxiosMockAdapter from 'axios-mock-adapter';
import { getJSONFixture } from 'helpers/fixtures';
import { issuableTypesMap } from '~/related_issues/constants';
import axios from '~/lib/utils/axios_utils';
import { mockInitialConfig, mockParentItem, mockEpics, mockIssues } from '../mock_data';
......
......@@ -5,11 +5,11 @@ import { GlTooltip, GlIcon } from '@gitlab/ui';
import RelatedItemsTreeHeader from 'ee/related_items_tree/components/related_items_tree_header.vue';
import createDefaultStore from 'ee/related_items_tree/store';
import * as epicUtils from 'ee/related_items_tree/utils/epic_utils';
import { issuableTypesMap } from 'ee/related_issues/constants';
import EpicActionsSplitButton from 'ee/related_items_tree/components/epic_issue_actions_split_button.vue';
import EpicHealthStatus from 'ee/related_items_tree/components/epic_health_status.vue';
import { issuableTypesMap } from '~/related_issues/constants';
import { mockInitialConfig, mockParentItem, mockQueryResponse } from '../mock_data';
const localVue = createLocalVue();
......
......@@ -10,7 +10,7 @@ import StateTooltip from 'ee/related_items_tree/components/state_tooltip.vue';
import createDefaultStore from 'ee/related_items_tree/store';
import * as epicUtils from 'ee/related_items_tree/utils/epic_utils';
import { ChildType, ChildState } from 'ee/related_items_tree/constants';
import { PathIdSeparator } from 'ee/related_issues/constants';
import { PathIdSeparator } from '~/related_issues/constants';
import ItemAssignees from '~/vue_shared/components/issue/issue_assignees.vue';
import ItemDueDate from '~/boards/components/issue_due_date.vue';
import ItemMilestone from '~/vue_shared/components/issue/issue_milestone.vue';
......
......@@ -7,7 +7,7 @@ import TreeItemRemoveModal from 'ee/related_items_tree/components/tree_item_remo
import createDefaultStore from 'ee/related_items_tree/store';
import * as epicUtils from 'ee/related_items_tree/utils/epic_utils';
import { ChildType } from 'ee/related_items_tree/constants';
import { PathIdSeparator } from 'ee/related_issues/constants';
import { PathIdSeparator } from '~/related_issues/constants';
import { mockParentItem, mockQueryResponse, mockIssue1 } from '../mock_data';
......
......@@ -9,7 +9,7 @@ import TreeRoot from 'ee/related_items_tree/components/tree_root.vue';
import createDefaultStore from 'ee/related_items_tree/store';
import * as epicUtils from 'ee/related_items_tree/utils/epic_utils';
import { ChildType, treeItemChevronBtnClassName } from 'ee/related_items_tree/constants';
import { PathIdSeparator } from 'ee/related_issues/constants';
import { PathIdSeparator } from '~/related_issues/constants';
import { mockParentItem, mockQueryResponse, mockEpic1 } from '../mock_data';
......
......@@ -5,14 +5,14 @@ import * as types from 'ee/related_items_tree/store/mutation_types';
import * as epicUtils from 'ee/related_items_tree/utils/epic_utils';
import { ChildType, ChildState } from 'ee/related_items_tree/constants';
import testAction from 'helpers/vuex_action_helper';
import { TEST_HOST } from 'spec/test_constants';
import {
issuableTypesMap,
itemAddFailureTypesMap,
PathIdSeparator,
} from 'ee/related_issues/constants';
import testAction from 'helpers/vuex_action_helper';
import { TEST_HOST } from 'spec/test_constants';
} from '~/related_issues/constants';
import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as createFlash } from '~/flash';
......
import * as getters from 'ee/related_items_tree/store/getters';
import createDefaultState from 'ee/related_items_tree/store/state';
import { issuableTypesMap } from 'ee/related_issues/constants';
import { issuableTypesMap } from '~/related_issues/constants';
import { mockEpic1, mockEpic2 } from '../mock_data';
......
import * as epicUtils from 'ee/related_items_tree/utils/epic_utils';
import { PathIdSeparator } from 'ee/related_issues/constants';
import { ChildType } from 'ee/related_items_tree/constants';
import { PathIdSeparator } from '~/related_issues/constants';
import { mockQueryResponse2, mockEpic1, mockIssue1 } from '../mock_data';
......
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import RelatedIssues from 'ee/vulnerabilities/components/related_issues.vue';
import RelatedIssuesBlock from 'ee/related_issues/components/related_issues_block.vue';
import { issuableTypesMap, PathIdSeparator } from 'ee/related_issues/constants';
import { FEEDBACK_TYPES } from 'ee/vulnerabilities/constants';
import waitForPromises from 'helpers/wait_for_promises';
import RelatedIssuesBlock from '~/related_issues/components/related_issues_block.vue';
import { issuableTypesMap, PathIdSeparator } from '~/related_issues/constants';
import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import httpStatusCodes from '~/lib/utils/http_status';
......
......@@ -12,11 +12,11 @@ module QA
element :close_reopen_epic_button
end
view 'ee/app/assets/javascripts/related_issues/components/add_issuable_form.vue' do
view 'app/assets/javascripts/related_issues/components/add_issuable_form.vue' do
element :add_issue_button
end
view 'ee/app/assets/javascripts/related_issues/components/related_issuable_input.vue' do
view 'app/assets/javascripts/related_issues/components/related_issuable_input.vue' do
element :add_issue_input
end
......
......@@ -12,23 +12,6 @@ module QA
super
base.class_eval do
view 'ee/app/assets/javascripts/related_issues/components/add_issuable_form.vue' do
element :add_issue_button
end
view 'ee/app/assets/javascripts/related_issues/components/related_issuable_input.vue' do
element :add_issue_input
end
view 'ee/app/assets/javascripts/related_issues/components/related_issues_block.vue' do
element :related_issues_plus_button
end
view 'ee/app/assets/javascripts/related_issues/components/related_issues_list.vue' do
element :related_issuable_item
element :related_issues_loading_icon
end
view 'ee/app/assets/javascripts/sidebar/components/weight/weight.vue' do
element :weight_label_value
element :edit_weight_link
......@@ -43,26 +26,12 @@ module QA
click_element(:remove_weight_link)
end
def relate_issue(issue)
click_element(:related_issues_plus_button)
fill_element(:add_issue_input, issue.web_url)
send_keys_to_element(:add_issue_input, :enter)
end
def related_issuable_item
find_element(:related_issuable_item)
end
def set_weight(weight)
click_element(:edit_weight_link)
fill_element(:weight_input_field, weight)
send_keys_to_element(:weight_input_field, :enter)
end
def wait_for_related_issues_to_load
has_no_element?(:related_issues_loading_icon, wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME)
end
def weight_label_value
find_element(:weight_label_value)
end
......
......@@ -38,6 +38,37 @@ module QA
element :new_note_form, 'attr: :note' # rubocop:disable QA/ElementWithPattern
end
view 'app/assets/javascripts/related_issues/components/add_issuable_form.vue' do
element :add_issue_button
end
view 'app/assets/javascripts/related_issues/components/related_issuable_input.vue' do
element :add_issue_input
end
view 'app/assets/javascripts/related_issues/components/related_issues_block.vue' do
element :related_issues_plus_button
end
view 'app/assets/javascripts/related_issues/components/related_issues_list.vue' do
element :related_issuable_item
element :related_issues_loading_icon
end
def relate_issue(issue)
click_element(:related_issues_plus_button)
fill_element(:add_issue_input, issue.web_url)
send_keys_to_element(:add_issue_input, :enter)
end
def related_issuable_item
find_element(:related_issuable_item)
end
def wait_for_related_issues_to_load
has_no_element?(:related_issues_loading_icon, wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME)
end
def click_remove_related_issue_button
click_element(:remove_related_issue_button)
end
......
This diff is collapsed.
import { mount, shallowMount } from '@vue/test-utils';
import {
issuableTypesMap,
linkedIssueTypesMap,
PathIdSeparator,
} from 'ee/related_issues/constants';
import AddIssuableForm from 'ee/related_issues/components/add_issuable_form.vue';
import { issuableTypesMap, linkedIssueTypesMap, PathIdSeparator } from '~/related_issues/constants';
import AddIssuableForm from '~/related_issues/components/add_issuable_form.vue';
const issuable1 = {
id: 200,
......
import Vue from 'vue';
import { PathIdSeparator } from 'ee/related_issues/constants';
import issueToken from 'ee/related_issues/components/issue_token.vue';
import { PathIdSeparator } from '~/related_issues/constants';
import issueToken from '~/related_issues/components/issue_token.vue';
describe('IssueToken', () => {
const idKey = 200;
......
import { shallowMount, mount } from '@vue/test-utils';
import { GlButton, GlIcon } from '@gitlab/ui';
import RelatedIssuesBlock from 'ee/related_issues/components/related_issues_block.vue';
import {
issuable1,
issuable2,
issuable3,
} from 'jest/vue_shared/components/issue/related_issuable_mock_data';
import RelatedIssuesBlock from '~/related_issues/components/related_issues_block.vue';
import {
linkedIssueTypesMap,
linkedIssueTypesTextMap,
PathIdSeparator,
} from 'ee/related_issues/constants';
} from '~/related_issues/constants';
describe('RelatedIssuesBlock', () => {
let wrapper;
......
import { mount, shallowMount } from '@vue/test-utils';
import {
issuable1,
issuable2,
issuable3,
issuable4,
issuable5,
} from 'jest/vue_shared/components/issue/related_issuable_mock_data';
import IssueDueDate from '~/boards/components/issue_due_date.vue';
import RelatedIssuesList from '~/related_issues/components/related_issues_list.vue';
import { PathIdSeparator } from '~/related_issues/constants';
describe('RelatedIssuesList', () => {
let wrapper;
afterEach(() => {
wrapper.destroy();
});
describe('with defaults', () => {
const heading = 'Related to';
beforeEach(() => {
wrapper = shallowMount(RelatedIssuesList, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
issuableType: 'issue',
heading,
},
});
});
it('shows a heading', () => {
expect(wrapper.find('h4').text()).toContain(heading);
});
it('should not show loading icon', () => {
expect(wrapper.vm.$refs.loadingIcon).toBeUndefined();
});
});
describe('with isFetching=true', () => {
beforeEach(() => {
wrapper = shallowMount(RelatedIssuesList, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
isFetching: true,
issuableType: 'issue',
},
});
});
it('should show loading icon', () => {
expect(wrapper.vm.$refs.loadingIcon).toBeDefined();
});
});
describe('methods', () => {
beforeEach(() => {
wrapper = shallowMount(RelatedIssuesList, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
relatedIssues: [issuable1, issuable2, issuable3, issuable4, issuable5],
issuableType: 'issue',
},
});
});
it('updates the order correctly when an item is moved to the top', () => {
const beforeAfterIds = wrapper.vm.getBeforeAfterId(
wrapper.vm.$el.querySelector('ul li:first-child'),
);
expect(beforeAfterIds.beforeId).toBeNull();
expect(beforeAfterIds.afterId).toBe(2);
});
it('updates the order correctly when an item is moved to the bottom', () => {
const beforeAfterIds = wrapper.vm.getBeforeAfterId(
wrapper.vm.$el.querySelector('ul li:last-child'),
);
expect(beforeAfterIds.beforeId).toBe(4);
expect(beforeAfterIds.afterId).toBeNull();
});
it('updates the order correctly when an item is swapped with adjacent item', () => {
const beforeAfterIds = wrapper.vm.getBeforeAfterId(
wrapper.vm.$el.querySelector('ul li:nth-child(3)'),
);
expect(beforeAfterIds.beforeId).toBe(2);
expect(beforeAfterIds.afterId).toBe(4);
});
it('updates the order correctly when an item is moved somewhere in the middle', () => {
const beforeAfterIds = wrapper.vm.getBeforeAfterId(
wrapper.vm.$el.querySelector('ul li:nth-child(4)'),
);
expect(beforeAfterIds.beforeId).toBe(3);
expect(beforeAfterIds.afterId).toBe(5);
});
});
describe('issuableOrderingId returns correct issuable order id when', () => {
it('issuableType is epic', () => {
wrapper = shallowMount(RelatedIssuesList, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
issuableType: 'issue',
},
});
expect(wrapper.vm.issuableOrderingId(issuable1)).toBe(issuable1.epicIssueId);
});
it('issuableType is issue', () => {
wrapper = shallowMount(RelatedIssuesList, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
issuableType: 'epic',
},
});
expect(wrapper.vm.issuableOrderingId(issuable1)).toBe(issuable1.id);
});
});
describe('renders correct ordering id when', () => {
let relatedIssues;
beforeAll(() => {
relatedIssues = [issuable1, issuable2, issuable3, issuable4, issuable5];
});
it('issuableType is epic', () => {
wrapper = shallowMount(RelatedIssuesList, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
issuableType: 'epic',
relatedIssues,
},
});
const listItems = wrapper.vm.$el.querySelectorAll('.list-item');
Array.from(listItems).forEach((item, index) => {
expect(Number(item.dataset.orderingId)).toBe(relatedIssues[index].id);
});
});
it('issuableType is issue', () => {
wrapper = shallowMount(RelatedIssuesList, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
issuableType: 'issue',
relatedIssues,
},
});
const listItems = wrapper.vm.$el.querySelectorAll('.list-item');
Array.from(listItems).forEach((item, index) => {
expect(Number(item.dataset.orderingId)).toBe(relatedIssues[index].epicIssueId);
});
});
});
describe('related item contents', () => {
beforeAll(() => {
wrapper = mount(RelatedIssuesList, {
propsData: {
issuableType: 'issue',
pathIdSeparator: PathIdSeparator.Issue,
relatedIssues: [issuable1],
},
});
});
it('shows due date', () => {
expect(
wrapper
.find(IssueDueDate)
.find('.board-card-info-text')
.text(),
).toBe('Nov 22, 2010');
});
});
});
import { mount, shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
import RelatedIssuesRoot from 'ee/related_issues/components/related_issues_root.vue';
import relatedIssuesService from 'ee/related_issues/services/related_issues_service';
import { linkedIssueTypesMap } from 'ee/related_issues/constants';
import {
defaultProps,
issuable1,
issuable2,
} from 'jest/vue_shared/components/issue/related_issuable_mock_data';
import RelatedIssuesRoot from '~/related_issues/components/related_issues_root.vue';
import relatedIssuesService from '~/related_issues/services/related_issues_service';
import { linkedIssueTypesMap } from '~/related_issues/constants';
import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as createFlash } from '~/flash';
......
import RelatedIssuesStore from 'ee/related_issues/stores/related_issues_store';
import {
issuable1,
issuable2,
......@@ -7,6 +5,7 @@ import {
issuable4,
issuable5,
} from 'jest/vue_shared/components/issue/related_issuable_mock_data';
import RelatedIssuesStore from '~/related_issues/stores/related_issues_store';
describe('RelatedIssuesStore', () => {
let store;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment