summaryrefslogtreecommitdiff
path: root/spec/javascripts/vue_shared
diff options
context:
space:
mode:
authorFatih Acet <acetfatih@gmail.com>2019-02-27 20:12:40 +0100
committerFatih Acet <acetfatih@gmail.com>2019-03-01 12:49:16 +0100
commit529c570c0271a94f7356815f8cb63dca9ed3f716 (patch)
treeecf05da3caba78d444229141709cb6ae7c08f65f /spec/javascripts/vue_shared
parent728e80798b53e05d4d94c54151b688366be22538 (diff)
downloadgitlab-ce-529c570c0271a94f7356815f8cb63dca9ed3f716.tar.gz
Move related issues shared components from EE
We will rewrite Related MRs widget in CE with Vue. It’s pretty much the same with Related Issues in EE. I made EE only components reusable and this is the CE backward compatability commit. Links: Issue: https://gitlab.com/gitlab-org/gitlab-ce/issues/57662 MR: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/9730
Diffstat (limited to 'spec/javascripts/vue_shared')
-rw-r--r--spec/javascripts/vue_shared/components/issue/related_issuable_item_spec.js194
-rw-r--r--spec/javascripts/vue_shared/components/issue/related_issuable_mock_data.js111
2 files changed, 305 insertions, 0 deletions
diff --git a/spec/javascripts/vue_shared/components/issue/related_issuable_item_spec.js b/spec/javascripts/vue_shared/components/issue/related_issuable_item_spec.js
new file mode 100644
index 00000000000..42198e92eea
--- /dev/null
+++ b/spec/javascripts/vue_shared/components/issue/related_issuable_item_spec.js
@@ -0,0 +1,194 @@
+import Vue from 'vue';
+import { mount, createLocalVue } from '@vue/test-utils';
+import RelatedIssuableItem from '~/vue_shared/components/issue/related_issuable_item.vue';
+import { defaultMilestone, defaultAssignees } from './related_issuable_mock_data';
+
+describe('RelatedIssuableItem', () => {
+ let wrapper;
+ const props = {
+ idKey: 1,
+ displayReference: 'gitlab-org/gitlab-test#1',
+ pathIdSeparator: '#',
+ path: `${gl.TEST_HOST}/path`,
+ title: 'title',
+ confidential: true,
+ dueDate: '1990-12-31',
+ weight: 10,
+ createdAt: '2018-12-01T00:00:00.00Z',
+ milestone: defaultMilestone,
+ assignees: defaultAssignees,
+ eventNamespace: 'relatedIssue',
+ };
+ const slots = {
+ dueDate: '<div class="js-due-date-slot"></div>',
+ weight: '<div class="js-weight-slot"></div>',
+ };
+
+ beforeEach(() => {
+ const localVue = createLocalVue();
+
+ wrapper = mount(localVue.extend(RelatedIssuableItem), {
+ localVue,
+ slots,
+ sync: false,
+ propsData: props,
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('contains issuable-info-container class when canReorder is false', () => {
+ expect(wrapper.props('canReorder')).toBe(false);
+ expect(wrapper.find('.issuable-info-container').exists()).toBe(true);
+ });
+
+ it('does not render token state', () => {
+ expect(wrapper.find('.text-secondary svg').exists()).toBe(false);
+ });
+
+ it('does not render remove button', () => {
+ expect(wrapper.find({ ref: 'removeButton' }).exists()).toBe(false);
+ });
+
+ describe('token title', () => {
+ it('links to computedPath', () => {
+ expect(wrapper.find('.item-title a').attributes('href')).toEqual(wrapper.props('path'));
+ });
+
+ it('renders confidential icon', () => {
+ expect(wrapper.find('.confidential-icon').exists()).toBe(true);
+ });
+
+ it('renders title', () => {
+ expect(wrapper.find('.item-title a').text()).toEqual(props.title);
+ });
+ });
+
+ describe('token state', () => {
+ let tokenState;
+
+ beforeEach(done => {
+ wrapper.setProps({ state: 'opened' });
+
+ Vue.nextTick(() => {
+ tokenState = wrapper.find('.issue-token-state-icon-open');
+
+ done();
+ });
+ });
+
+ it('renders if hasState', () => {
+ expect(tokenState.exists()).toBe(true);
+ });
+
+ it('renders state title', () => {
+ const stateTitle = tokenState.attributes('data-original-title');
+
+ expect(stateTitle).toContain('<span class="bold">Opened</span>');
+ expect(stateTitle).toContain(
+ '<span class="text-tertiary">Dec 1, 2018 12:00am GMT+0000</span>',
+ );
+ });
+
+ it('renders aria label', () => {
+ expect(tokenState.attributes('aria-label')).toEqual('opened');
+ });
+
+ it('renders open icon when open state', () => {
+ expect(tokenState.classes('issue-token-state-icon-open')).toBe(true);
+ });
+
+ it('renders close icon when close state', done => {
+ wrapper.setProps({
+ state: 'closed',
+ closedAt: '2018-12-01T00:00:00.00Z',
+ });
+
+ Vue.nextTick(() => {
+ expect(tokenState.classes('issue-token-state-icon-closed')).toBe(true);
+
+ done();
+ });
+ });
+ });
+
+ describe('token metadata', () => {
+ let tokenMetadata;
+
+ beforeEach(done => {
+ Vue.nextTick(() => {
+ tokenMetadata = wrapper.find('.item-meta');
+
+ done();
+ });
+ });
+
+ it('renders item path and ID', () => {
+ const pathAndID = tokenMetadata.find('.item-path-id').text();
+
+ expect(pathAndID).toContain('gitlab-org/gitlab-test');
+ expect(pathAndID).toContain('#1');
+ });
+
+ it('renders milestone icon and name', () => {
+ const milestoneIcon = tokenMetadata.find('.item-milestone svg use');
+ const milestoneTitle = tokenMetadata.find('.item-milestone .milestone-title');
+
+ expect(milestoneIcon.attributes('href')).toContain('clock');
+ expect(milestoneTitle.text()).toContain('Milestone title');
+ });
+
+ it('renders due date component', () => {
+ expect(tokenMetadata.find('.js-due-date-slot').exists()).toBe(true);
+ });
+
+ it('renders weight component', () => {
+ expect(tokenMetadata.find('.js-weight-slot').exists()).toBe(true);
+ });
+ });
+
+ describe('token assignees', () => {
+ it('renders assignees avatars', () => {
+ expect(wrapper.findAll('.item-assignees .user-avatar-link').length).toBe(2);
+ expect(wrapper.find('.item-assignees .avatar-counter').text()).toContain('+2');
+ });
+ });
+
+ describe('remove button', () => {
+ let removeBtn;
+
+ beforeEach(done => {
+ wrapper.setProps({ canRemove: true });
+ Vue.nextTick(() => {
+ removeBtn = wrapper.find({ ref: 'removeButton' });
+
+ done();
+ });
+ });
+
+ it('renders if canRemove', () => {
+ expect(removeBtn.exists()).toBe(true);
+ });
+
+ it('renders disabled button when removeDisabled', done => {
+ wrapper.vm.removeDisabled = true;
+
+ Vue.nextTick(() => {
+ expect(removeBtn.attributes('disabled')).toEqual('disabled');
+
+ done();
+ });
+ });
+
+ it('triggers onRemoveRequest when clicked', () => {
+ removeBtn.trigger('click');
+
+ const { relatedIssueRemoveRequest } = wrapper.emitted();
+
+ expect(relatedIssueRemoveRequest.length).toBe(1);
+ expect(relatedIssueRemoveRequest[0]).toEqual([props.idKey]);
+ });
+ });
+});
diff --git a/spec/javascripts/vue_shared/components/issue/related_issuable_mock_data.js b/spec/javascripts/vue_shared/components/issue/related_issuable_mock_data.js
new file mode 100644
index 00000000000..26bfdd7551e
--- /dev/null
+++ b/spec/javascripts/vue_shared/components/issue/related_issuable_mock_data.js
@@ -0,0 +1,111 @@
+export const defaultProps = {
+ endpoint: '/foo/bar/issues/1/related_issues',
+ currentNamespacePath: 'foo',
+ currentProjectPath: 'bar',
+};
+
+export const issuable1 = {
+ id: 200,
+ epic_issue_id: 1,
+ confidential: false,
+ reference: 'foo/bar#123',
+ displayReference: '#123',
+ title: 'some title',
+ path: '/foo/bar/issues/123',
+ state: 'opened',
+};
+
+export const issuable2 = {
+ id: 201,
+ epic_issue_id: 2,
+ confidential: false,
+ reference: 'foo/bar#124',
+ displayReference: '#124',
+ title: 'some other thing',
+ path: '/foo/bar/issues/124',
+ state: 'opened',
+};
+
+export const issuable3 = {
+ id: 202,
+ epic_issue_id: 3,
+ confidential: false,
+ reference: 'foo/bar#125',
+ displayReference: '#125',
+ title: 'some other other thing',
+ path: '/foo/bar/issues/125',
+ state: 'opened',
+};
+
+export const issuable4 = {
+ id: 203,
+ epic_issue_id: 4,
+ confidential: false,
+ reference: 'foo/bar#126',
+ displayReference: '#126',
+ title: 'some other other other thing',
+ path: '/foo/bar/issues/126',
+ state: 'opened',
+};
+
+export const issuable5 = {
+ id: 204,
+ epic_issue_id: 5,
+ confidential: false,
+ reference: 'foo/bar#127',
+ displayReference: '#127',
+ title: 'some other other other thing',
+ path: '/foo/bar/issues/127',
+ state: 'opened',
+};
+
+export const defaultMilestone = {
+ id: 1,
+ state: 'active',
+ title: 'Milestone title',
+ start_date: '2018-01-01',
+ due_date: '2019-12-31',
+};
+
+export const defaultAssignees = [
+ {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ state: 'active',
+ avatar_url: `${gl.TEST_HOST}`,
+ web_url: `${gl.TEST_HOST}/root`,
+ status_tooltip_html: null,
+ path: '/root',
+ },
+ {
+ id: 13,
+ name: 'Brooks Beatty',
+ username: 'brynn_champlin',
+ state: 'active',
+ avatar_url: `${gl.TEST_HOST}`,
+ web_url: `${gl.TEST_HOST}/brynn_champlin`,
+ status_tooltip_html: null,
+ path: '/brynn_champlin',
+ },
+ {
+ id: 6,
+ name: 'Bryce Turcotte',
+ username: 'melynda',
+ state: 'active',
+ avatar_url: `${gl.TEST_HOST}`,
+ web_url: `${gl.TEST_HOST}/melynda`,
+ status_tooltip_html: null,
+ path: '/melynda',
+ },
+ {
+ id: 20,
+ name: 'Conchita Eichmann',
+ username: 'juliana_gulgowski',
+ state: 'active',
+ avatar_url: `${gl.TEST_HOST}`,
+ web_url: `${gl.TEST_HOST}/juliana_gulgowski`,
+ status_tooltip_html: null,
+ path: '/juliana_gulgowski',
+ },
+];