summaryrefslogtreecommitdiff
path: root/spec/frontend/sidebar
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/sidebar')
-rw-r--r--spec/frontend/sidebar/assignee_title_spec.js17
-rw-r--r--spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js3
-rw-r--r--spec/frontend/sidebar/confidential/edit_form_buttons_spec.js15
-rw-r--r--spec/frontend/sidebar/lock/edit_form_buttons_spec.js14
-rw-r--r--spec/frontend/sidebar/lock/issuable_lock_form_spec.js13
-rw-r--r--spec/frontend/sidebar/reviewer_title_spec.js116
-rw-r--r--spec/frontend/sidebar/reviewers_spec.js169
-rw-r--r--spec/frontend/sidebar/sidebar_assignees_spec.js1
-rw-r--r--spec/frontend/sidebar/sidebar_labels_spec.js35
-rw-r--r--spec/frontend/sidebar/sidebar_store_spec.js37
10 files changed, 384 insertions, 36 deletions
diff --git a/spec/frontend/sidebar/assignee_title_spec.js b/spec/frontend/sidebar/assignee_title_spec.js
index 92fabaa664e..b5d1e5216f8 100644
--- a/spec/frontend/sidebar/assignee_title_spec.js
+++ b/spec/frontend/sidebar/assignee_title_spec.js
@@ -11,6 +11,7 @@ describe('AssigneeTitle component', () => {
propsData: {
numberOfAssignees: 0,
editable: false,
+ changing: false,
...props,
},
});
@@ -62,6 +63,22 @@ describe('AssigneeTitle component', () => {
});
});
+ describe('when changing is false', () => {
+ it('renders "Edit"', () => {
+ wrapper = createComponent({ editable: true });
+
+ expect(wrapper.find('[data-test-id="edit-link"]').text()).toEqual('Edit');
+ });
+ });
+
+ describe('when changing is true', () => {
+ it('renders "Edit"', () => {
+ wrapper = createComponent({ editable: true, changing: true });
+
+ expect(wrapper.find('[data-test-id="edit-link"]').text()).toEqual('Apply');
+ });
+ });
+
it('does not render spinner by default', () => {
wrapper = createComponent({
numberOfAssignees: 0,
diff --git a/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js b/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js
index 1f028f74423..5307be0bf58 100644
--- a/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js
+++ b/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js
@@ -155,8 +155,7 @@ describe('Issuable Time Tracker', () => {
it('should show the correct tooltip text', done => {
Vue.nextTick(() => {
expect(vm.showComparisonState).toBe(true);
- const $title = vm.$el.querySelector('.time-tracking-content .compare-meter').dataset
- .originalTitle;
+ const $title = vm.$el.querySelector('.time-tracking-content .compare-meter').title;
expect($title).toBe('Time remaining: 26h 23m');
done();
diff --git a/spec/frontend/sidebar/confidential/edit_form_buttons_spec.js b/spec/frontend/sidebar/confidential/edit_form_buttons_spec.js
index 2f11c6a07c2..8c868205295 100644
--- a/spec/frontend/sidebar/confidential/edit_form_buttons_spec.js
+++ b/spec/frontend/sidebar/confidential/edit_form_buttons_spec.js
@@ -1,5 +1,4 @@
import { shallowMount } from '@vue/test-utils';
-import { GlLoadingIcon } from '@gitlab/ui';
import waitForPromises from 'helpers/wait_for_promises';
import EditFormButtons from '~/sidebar/components/confidential/edit_form_buttons.vue';
import eventHub from '~/sidebar/event_hub';
@@ -56,11 +55,11 @@ describe('Edit Form Buttons', () => {
});
it('disables the toggle button', () => {
- expect(findConfidentialToggle().attributes('disabled')).toBe('disabled');
+ expect(findConfidentialToggle().props('disabled')).toBe(true);
});
- it('finds the GlLoadingIcon', () => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ it('sets loading on the toggle button', () => {
+ expect(findConfidentialToggle().props('loading')).toBe(true);
});
});
@@ -99,7 +98,7 @@ describe('Edit Form Buttons', () => {
describe('when succeeds', () => {
beforeEach(() => {
createComponent({ data: { isLoading: false }, props: { confidential: true } });
- findConfidentialToggle().trigger('click');
+ findConfidentialToggle().vm.$emit('click', new Event('click'));
});
it('dispatches the correct action', () => {
@@ -109,9 +108,9 @@ describe('Edit Form Buttons', () => {
});
});
- it('resets loading', () => {
+ it('resets loading on the toggle button', () => {
return waitForPromises().then(() => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(findConfidentialToggle().props('loading')).toBe(false);
});
});
@@ -135,7 +134,7 @@ describe('Edit Form Buttons', () => {
props: { confidential: true },
resolved: false,
});
- findConfidentialToggle().trigger('click');
+ findConfidentialToggle().vm.$emit('click', new Event('click'));
});
it('calls flash with the correct message', () => {
diff --git a/spec/frontend/sidebar/lock/edit_form_buttons_spec.js b/spec/frontend/sidebar/lock/edit_form_buttons_spec.js
index de1da3456f8..913646c8f8d 100644
--- a/spec/frontend/sidebar/lock/edit_form_buttons_spec.js
+++ b/spec/frontend/sidebar/lock/edit_form_buttons_spec.js
@@ -1,5 +1,4 @@
-import { shallowMount } from '@vue/test-utils';
-import { GlLoadingIcon } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import EditFormButtons from '~/sidebar/components/lock/edit_form_buttons.vue';
import eventHub from '~/sidebar/event_hub';
import { deprecatedCreateFlash as flash } from '~/flash';
@@ -22,7 +21,6 @@ describe('EditFormButtons', () => {
};
const findLockToggle = () => wrapper.find('[data-testid="lock-toggle"]');
- const findGlLoadingIcon = () => wrapper.find(GlLoadingIcon);
const createComponent = ({ props = {}, data = {}, resolved = true }) => {
store = issuableType === ISSUABLE_TYPE_ISSUE ? createStore() : createMrStore();
@@ -33,7 +31,7 @@ describe('EditFormButtons', () => {
jest.spyOn(store, 'dispatch').mockRejectedValue();
}
- wrapper = shallowMount(EditFormButtons, {
+ wrapper = mount(EditFormButtons, {
store,
provide: {
fullPath: '',
@@ -78,8 +76,8 @@ describe('EditFormButtons', () => {
expect(findLockToggle().attributes('disabled')).toBe('disabled');
});
- it('displays the GlLoadingIcon', () => {
- expect(findGlLoadingIcon().exists()).toBe(true);
+ it('sets loading on the toggle button', () => {
+ expect(findLockToggle().props('loading')).toBe(true);
});
});
@@ -121,7 +119,7 @@ describe('EditFormButtons', () => {
it('resets loading', async () => {
await wrapper.vm.$nextTick().then(() => {
- expect(findGlLoadingIcon().exists()).toBe(false);
+ expect(findLockToggle().props('loading')).toBe(false);
});
});
@@ -156,7 +154,7 @@ describe('EditFormButtons', () => {
it('resets loading', async () => {
await wrapper.vm.$nextTick().then(() => {
- expect(findGlLoadingIcon().exists()).toBe(false);
+ expect(findLockToggle().props('loading')).toBe(false);
});
});
diff --git a/spec/frontend/sidebar/lock/issuable_lock_form_spec.js b/spec/frontend/sidebar/lock/issuable_lock_form_spec.js
index ab1423a9bbb..e8091dcb51d 100644
--- a/spec/frontend/sidebar/lock/issuable_lock_form_spec.js
+++ b/spec/frontend/sidebar/lock/issuable_lock_form_spec.js
@@ -1,5 +1,6 @@
import { shallowMount } from '@vue/test-utils';
import { mockTracking, triggerEvent } from 'helpers/tracking_helper';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import IssuableLockForm from '~/sidebar/components/lock/issuable_lock_form.vue';
import EditForm from '~/sidebar/components/lock/edit_form.vue';
import createStore from '~/notes/stores';
@@ -19,6 +20,8 @@ describe('IssuableLockForm', () => {
const findLockStatus = () => wrapper.find('[data-testid="lock-status"]');
const findEditLink = () => wrapper.find('[data-testid="edit-link"]');
const findEditForm = () => wrapper.find(EditForm);
+ const findSidebarLockStatusTooltip = () =>
+ getBinding(findSidebarCollapseIcon().element, 'gl-tooltip');
const initStore = isLocked => {
if (issuableType === ISSUABLE_TYPE_ISSUE) {
@@ -37,6 +40,9 @@ describe('IssuableLockForm', () => {
isEditable: true,
...props,
},
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
});
};
@@ -125,6 +131,13 @@ describe('IssuableLockForm', () => {
expect(findEditForm().exists()).toBe(true);
});
});
+
+ it('renders a tooltip with the lock status text', () => {
+ const tooltip = findSidebarLockStatusTooltip();
+
+ expect(tooltip).toBeDefined();
+ expect(tooltip.value.title).toBe(isLocked ? 'Locked' : 'Unlocked');
+ });
});
});
});
diff --git a/spec/frontend/sidebar/reviewer_title_spec.js b/spec/frontend/sidebar/reviewer_title_spec.js
new file mode 100644
index 00000000000..eae266688d5
--- /dev/null
+++ b/spec/frontend/sidebar/reviewer_title_spec.js
@@ -0,0 +1,116 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlLoadingIcon } from '@gitlab/ui';
+import { mockTracking, triggerEvent } from 'helpers/tracking_helper';
+import Component from '~/sidebar/components/reviewers/reviewer_title.vue';
+
+describe('ReviewerTitle component', () => {
+ let wrapper;
+
+ const createComponent = props => {
+ return shallowMount(Component, {
+ propsData: {
+ numberOfReviewers: 0,
+ editable: false,
+ ...props,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('reviewer title', () => {
+ it('renders reviewer', () => {
+ wrapper = createComponent({
+ numberOfReviewers: 1,
+ editable: false,
+ });
+
+ expect(wrapper.vm.$el.innerText.trim()).toEqual('Reviewer');
+ });
+
+ it('renders 2 reviewers', () => {
+ wrapper = createComponent({
+ numberOfReviewers: 2,
+ editable: false,
+ });
+
+ expect(wrapper.vm.$el.innerText.trim()).toEqual('2 Reviewers');
+ });
+ });
+
+ describe('gutter toggle', () => {
+ it('does not show toggle by default', () => {
+ wrapper = createComponent({
+ numberOfReviewers: 2,
+ editable: false,
+ });
+
+ expect(wrapper.vm.$el.querySelector('.gutter-toggle')).toBeNull();
+ });
+
+ it('shows toggle when showToggle is true', () => {
+ wrapper = createComponent({
+ numberOfReviewers: 2,
+ editable: false,
+ showToggle: true,
+ });
+
+ expect(wrapper.vm.$el.querySelector('.gutter-toggle')).toEqual(expect.any(Object));
+ });
+ });
+
+ it('does not render spinner by default', () => {
+ wrapper = createComponent({
+ numberOfReviewers: 0,
+ editable: false,
+ });
+
+ expect(wrapper.find(GlLoadingIcon).exists()).toBeFalsy();
+ });
+
+ it('renders spinner when loading', () => {
+ wrapper = createComponent({
+ loading: true,
+ numberOfReviewers: 0,
+ editable: false,
+ });
+
+ expect(wrapper.find(GlLoadingIcon).exists()).toBeTruthy();
+ });
+
+ it('does not render edit link when not editable', () => {
+ wrapper = createComponent({
+ numberOfReviewers: 0,
+ editable: false,
+ });
+
+ expect(wrapper.vm.$el.querySelector('.edit-link')).toBeNull();
+ });
+
+ it('renders edit link when editable', () => {
+ wrapper = createComponent({
+ numberOfReviewers: 0,
+ editable: true,
+ });
+
+ expect(wrapper.vm.$el.querySelector('.edit-link')).not.toBeNull();
+ });
+
+ it('tracks the event when edit is clicked', () => {
+ wrapper = createComponent({
+ numberOfReviewers: 0,
+ editable: true,
+ });
+
+ const spy = mockTracking('_category_', wrapper.element, jest.spyOn);
+ triggerEvent('.js-sidebar-dropdown-toggle');
+
+ expect(spy).toHaveBeenCalledWith('_category_', 'click_edit_button', {
+ label: 'right_sidebar',
+ property: 'reviewer',
+ });
+ });
+});
diff --git a/spec/frontend/sidebar/reviewers_spec.js b/spec/frontend/sidebar/reviewers_spec.js
new file mode 100644
index 00000000000..effcac266f0
--- /dev/null
+++ b/spec/frontend/sidebar/reviewers_spec.js
@@ -0,0 +1,169 @@
+import { mount } from '@vue/test-utils';
+import { trimText } from 'helpers/text_helper';
+import { GlIcon } from '@gitlab/ui';
+import Reviewer from '~/sidebar/components/reviewers/reviewers.vue';
+import UsersMock from './mock_data';
+import UsersMockHelper from '../helpers/user_mock_data_helper';
+
+describe('Reviewer component', () => {
+ const getDefaultProps = () => ({
+ rootPath: 'http://localhost:3000',
+ users: [],
+ editable: false,
+ });
+ let wrapper;
+
+ const createWrapper = (propsData = getDefaultProps()) => {
+ wrapper = mount(Reviewer, {
+ propsData,
+ });
+ };
+
+ const findCollapsedChildren = () => wrapper.findAll('.sidebar-collapsed-icon > *');
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('No reviewers/users', () => {
+ it('displays no reviewer icon when collapsed', () => {
+ createWrapper();
+ const collapsedChildren = findCollapsedChildren();
+ const userIcon = collapsedChildren.at(0).find(GlIcon);
+
+ expect(collapsedChildren.length).toBe(1);
+ expect(collapsedChildren.at(0).attributes('aria-label')).toBe('None');
+ expect(userIcon.exists()).toBe(true);
+ expect(userIcon.props('name')).toBe('user');
+ });
+ });
+
+ describe('One reviewer/user', () => {
+ it('displays one reviewer icon when collapsed', () => {
+ createWrapper({
+ ...getDefaultProps(),
+ users: [UsersMock.user],
+ });
+
+ const collapsedChildren = findCollapsedChildren();
+ const reviewer = collapsedChildren.at(0);
+
+ expect(collapsedChildren.length).toBe(1);
+ expect(reviewer.find('.avatar').attributes('src')).toBe(UsersMock.user.avatar);
+ expect(reviewer.find('.avatar').attributes('alt')).toBe(`${UsersMock.user.name}'s avatar`);
+
+ expect(trimText(reviewer.find('.author').text())).toBe(UsersMock.user.name);
+ });
+ });
+
+ describe('Two or more reviewers/users', () => {
+ it('displays two reviewer icons when collapsed', () => {
+ const users = UsersMockHelper.createNumberRandomUsers(2);
+ createWrapper({
+ ...getDefaultProps(),
+ users,
+ });
+
+ const collapsedChildren = findCollapsedChildren();
+
+ expect(collapsedChildren.length).toBe(2);
+
+ const first = collapsedChildren.at(0);
+
+ expect(first.find('.avatar').attributes('src')).toBe(users[0].avatar_url);
+ expect(first.find('.avatar').attributes('alt')).toBe(`${users[0].name}'s avatar`);
+
+ expect(trimText(first.find('.author').text())).toBe(users[0].name);
+
+ const second = collapsedChildren.at(1);
+
+ expect(second.find('.avatar').attributes('src')).toBe(users[1].avatar_url);
+ expect(second.find('.avatar').attributes('alt')).toBe(`${users[1].name}'s avatar`);
+
+ expect(trimText(second.find('.author').text())).toBe(users[1].name);
+ });
+
+ it('displays one reviewer icon and counter when collapsed', () => {
+ const users = UsersMockHelper.createNumberRandomUsers(3);
+ createWrapper({
+ ...getDefaultProps(),
+ users,
+ });
+
+ const collapsedChildren = findCollapsedChildren();
+
+ expect(collapsedChildren.length).toBe(2);
+
+ const first = collapsedChildren.at(0);
+
+ expect(first.find('.avatar').attributes('src')).toBe(users[0].avatar_url);
+ expect(first.find('.avatar').attributes('alt')).toBe(`${users[0].name}'s avatar`);
+
+ expect(trimText(first.find('.author').text())).toBe(users[0].name);
+
+ const second = collapsedChildren.at(1);
+
+ expect(trimText(second.find('.avatar-counter').text())).toBe('+2');
+ });
+
+ it('Shows two reviewers', () => {
+ const users = UsersMockHelper.createNumberRandomUsers(2);
+ createWrapper({
+ ...getDefaultProps(),
+ users,
+ editable: true,
+ });
+
+ expect(wrapper.findAll('.user-item').length).toBe(users.length);
+ expect(wrapper.find('.user-list-more').exists()).toBe(false);
+ });
+
+ it('shows sorted reviewer where "can merge" users are sorted first', () => {
+ const users = UsersMockHelper.createNumberRandomUsers(3);
+ users[0].can_merge = false;
+ users[1].can_merge = false;
+ users[2].can_merge = true;
+
+ createWrapper({
+ ...getDefaultProps(),
+ users,
+ editable: true,
+ });
+
+ expect(wrapper.vm.sortedReviewers[0].can_merge).toBe(true);
+ });
+
+ it('passes the sorted reviewers to the uncollapsed-reviewer-list', () => {
+ const users = UsersMockHelper.createNumberRandomUsers(3);
+ users[0].can_merge = false;
+ users[1].can_merge = false;
+ users[2].can_merge = true;
+
+ createWrapper({
+ ...getDefaultProps(),
+ users,
+ });
+
+ const userItems = wrapper.findAll('.user-list .user-item a');
+
+ expect(userItems.length).toBe(3);
+ expect(userItems.at(0).attributes('title')).toBe(users[2].name);
+ });
+
+ it('passes the sorted reviewers to the collapsed-reviewer-list', () => {
+ const users = UsersMockHelper.createNumberRandomUsers(3);
+ users[0].can_merge = false;
+ users[1].can_merge = false;
+ users[2].can_merge = true;
+
+ createWrapper({
+ ...getDefaultProps(),
+ users,
+ });
+
+ const collapsedButton = wrapper.find('.sidebar-collapsed-user button');
+
+ expect(trimText(collapsedButton.text())).toBe(users[2].name);
+ });
+ });
+});
diff --git a/spec/frontend/sidebar/sidebar_assignees_spec.js b/spec/frontend/sidebar/sidebar_assignees_spec.js
index 88e2d2c9514..dc4560d2ae8 100644
--- a/spec/frontend/sidebar/sidebar_assignees_spec.js
+++ b/spec/frontend/sidebar/sidebar_assignees_spec.js
@@ -20,6 +20,7 @@ describe('sidebar assignees', () => {
mediator,
field: '',
projectPath: 'projectPath',
+ changing: false,
...props,
},
provide: {
diff --git a/spec/frontend/sidebar/sidebar_labels_spec.js b/spec/frontend/sidebar/sidebar_labels_spec.js
index 29333a344e1..7a687ffa761 100644
--- a/spec/frontend/sidebar/sidebar_labels_spec.js
+++ b/spec/frontend/sidebar/sidebar_labels_spec.js
@@ -1,6 +1,5 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
-import Vuex from 'vuex';
import {
mockLabels,
mockRegularLabel,
@@ -9,17 +8,11 @@ import axios from '~/lib/utils/axios_utils';
import SidebarLabels from '~/sidebar/components/labels/sidebar_labels.vue';
import { DropdownVariant } from '~/vue_shared/components/sidebar/labels_select_vue/constants';
import LabelsSelect from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
-import labelsSelectModule from '~/vue_shared/components/sidebar/labels_select_vue/store';
-
-const localVue = createLocalVue();
-localVue.use(Vuex);
describe('sidebar labels', () => {
let axiosMock;
let wrapper;
- const store = new Vuex.Store(labelsSelectModule());
-
const defaultProps = {
allowLabelCreate: true,
allowLabelEdit: true,
@@ -39,11 +32,9 @@ describe('sidebar labels', () => {
const mountComponent = () => {
wrapper = shallowMount(SidebarLabels, {
- localVue,
provide: {
...defaultProps,
},
- store,
});
};
@@ -81,7 +72,7 @@ describe('sidebar labels', () => {
});
});
- describe('when labels are changed', () => {
+ describe('when labels are updated', () => {
beforeEach(() => {
mountComponent();
});
@@ -114,7 +105,27 @@ describe('sidebar labels', () => {
const expected = {
[defaultProps.issuableType]: {
- label_ids: [27, 28, 40],
+ label_ids: [27, 28, 29, 40],
+ },
+ };
+
+ expect(axiosMock.history.put[0].data).toEqual(JSON.stringify(expected));
+ });
+ });
+
+ describe('when label `x` is clicked', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ it('makes an API call to update labels', async () => {
+ findLabelsSelect().vm.$emit('onLabelRemove', 27);
+
+ await axios.waitForAll();
+
+ const expected = {
+ [defaultProps.issuableType]: {
+ label_ids: [26, 28, 29],
},
};
diff --git a/spec/frontend/sidebar/sidebar_store_spec.js b/spec/frontend/sidebar/sidebar_store_spec.js
index 6d063a7cfcf..7c18222f300 100644
--- a/spec/frontend/sidebar/sidebar_store_spec.js
+++ b/spec/frontend/sidebar/sidebar_store_spec.js
@@ -57,16 +57,40 @@ describe('Sidebar store', () => {
expect(testContext.store.isFetching.assignees).toBe(true);
});
- it('adds a new assignee', () => {
- testContext.store.addAssignee(ASSIGNEE);
+ it('resets changing when resetChanging is called', () => {
+ testContext.store.changing = true;
+
+ testContext.store.resetChanging();
- expect(testContext.store.assignees.length).toEqual(1);
+ expect(testContext.store.changing).toBe(false);
});
- it('removes an assignee', () => {
- testContext.store.removeAssignee(ASSIGNEE);
+ describe('when it adds a new assignee', () => {
+ beforeEach(() => {
+ testContext.store.addAssignee(ASSIGNEE);
+ });
- expect(testContext.store.assignees.length).toEqual(0);
+ it('adds a new assignee', () => {
+ expect(testContext.store.assignees).toHaveLength(1);
+ });
+
+ it('sets changing to true', () => {
+ expect(testContext.store.changing).toBe(true);
+ });
+ });
+
+ describe('when it removes an assignee', () => {
+ beforeEach(() => {
+ testContext.store.removeAssignee(ASSIGNEE);
+ });
+
+ it('removes an assignee', () => {
+ expect(testContext.store.assignees).toHaveLength(0);
+ });
+
+ it('sets changing to true', () => {
+ expect(testContext.store.changing).toBe(true);
+ });
});
it('finds an existent assignee', () => {
@@ -86,6 +110,7 @@ describe('Sidebar store', () => {
testContext.store.removeAllAssignees();
expect(testContext.store.assignees.length).toEqual(0);
+ expect(testContext.store.changing).toBe(true);
});
it('sets participants data', () => {