2017-05-05 14:23:31 -04:00
|
|
|
import Vue from 'vue';
|
2018-02-06 11:30:35 -05:00
|
|
|
import Assignee from '~/sidebar/components/assignees/assignees.vue';
|
2017-05-05 14:23:31 -04:00
|
|
|
import UsersMock from './mock_data';
|
2017-05-05 15:45:14 -04:00
|
|
|
import UsersMockHelper from '../helpers/user_mock_data_helper';
|
2017-05-05 14:23:31 -04:00
|
|
|
|
|
|
|
describe('Assignee component', () => {
|
|
|
|
let component;
|
|
|
|
let AssigneeComponent;
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
AssigneeComponent = Vue.extend(Assignee);
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('No assignees/users', () => {
|
|
|
|
it('displays no assignee icon when collapsed', () => {
|
|
|
|
component = new AssigneeComponent({
|
|
|
|
propsData: {
|
|
|
|
rootPath: 'http://localhost:3000',
|
|
|
|
users: [],
|
|
|
|
editable: false,
|
|
|
|
},
|
|
|
|
}).$mount();
|
|
|
|
|
|
|
|
const collapsed = component.$el.querySelector('.sidebar-collapsed-icon');
|
2018-10-09 14:03:09 -04:00
|
|
|
|
2017-05-05 14:23:31 -04:00
|
|
|
expect(collapsed.childElementCount).toEqual(1);
|
2019-04-16 16:21:56 -04:00
|
|
|
expect(collapsed.children[0].getAttribute('aria-label')).toEqual('None');
|
2017-05-05 14:23:31 -04:00
|
|
|
expect(collapsed.children[0].classList.contains('fa')).toEqual(true);
|
|
|
|
expect(collapsed.children[0].classList.contains('fa-user')).toEqual(true);
|
|
|
|
});
|
|
|
|
|
2019-04-16 16:21:56 -04:00
|
|
|
it('displays only "None" when no users are assigned and the issue is read-only', () => {
|
2017-05-05 14:23:31 -04:00
|
|
|
component = new AssigneeComponent({
|
|
|
|
propsData: {
|
|
|
|
rootPath: 'http://localhost:3000',
|
|
|
|
users: [],
|
|
|
|
editable: false,
|
|
|
|
},
|
|
|
|
}).$mount();
|
|
|
|
const componentTextNoUsers = component.$el.querySelector('.assign-yourself').innerText.trim();
|
|
|
|
|
2019-04-16 16:21:56 -04:00
|
|
|
expect(componentTextNoUsers).toBe('None');
|
2017-05-05 14:23:31 -04:00
|
|
|
expect(componentTextNoUsers.indexOf('assign yourself')).toEqual(-1);
|
|
|
|
});
|
|
|
|
|
2019-04-16 16:21:56 -04:00
|
|
|
it('displays only "None" when no users are assigned and the issue can be edited', () => {
|
2017-05-05 14:23:31 -04:00
|
|
|
component = new AssigneeComponent({
|
|
|
|
propsData: {
|
|
|
|
rootPath: 'http://localhost:3000',
|
|
|
|
users: [],
|
|
|
|
editable: true,
|
|
|
|
},
|
|
|
|
}).$mount();
|
|
|
|
const componentTextNoUsers = component.$el.querySelector('.assign-yourself').innerText.trim();
|
|
|
|
|
2019-04-16 16:21:56 -04:00
|
|
|
expect(componentTextNoUsers.indexOf('None')).toEqual(0);
|
2017-05-05 14:23:31 -04:00
|
|
|
expect(componentTextNoUsers.indexOf('assign yourself')).toBeGreaterThan(0);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('emits the assign-self event when "assign yourself" is clicked', () => {
|
|
|
|
component = new AssigneeComponent({
|
|
|
|
propsData: {
|
|
|
|
rootPath: 'http://localhost:3000',
|
|
|
|
users: [],
|
|
|
|
editable: true,
|
|
|
|
},
|
|
|
|
}).$mount();
|
|
|
|
|
|
|
|
spyOn(component, '$emit');
|
|
|
|
component.$el.querySelector('.assign-yourself .btn-link').click();
|
2018-10-09 14:03:09 -04:00
|
|
|
|
2017-05-05 14:23:31 -04:00
|
|
|
expect(component.$emit).toHaveBeenCalledWith('assign-self');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('One assignee/user', () => {
|
|
|
|
it('displays one assignee icon when collapsed', () => {
|
|
|
|
component = new AssigneeComponent({
|
|
|
|
propsData: {
|
|
|
|
rootPath: 'http://localhost:3000',
|
2018-10-30 16:28:31 -04:00
|
|
|
users: [UsersMock.user],
|
2017-05-05 14:23:31 -04:00
|
|
|
editable: false,
|
|
|
|
},
|
|
|
|
}).$mount();
|
|
|
|
|
|
|
|
const collapsed = component.$el.querySelector('.sidebar-collapsed-icon');
|
|
|
|
const assignee = collapsed.children[0];
|
2018-10-09 14:03:09 -04:00
|
|
|
|
2017-05-05 14:23:31 -04:00
|
|
|
expect(collapsed.childElementCount).toEqual(1);
|
2017-05-05 15:45:14 -04:00
|
|
|
expect(assignee.querySelector('.avatar').getAttribute('src')).toEqual(UsersMock.user.avatar);
|
2018-10-30 16:28:31 -04:00
|
|
|
expect(assignee.querySelector('.avatar').getAttribute('alt')).toEqual(
|
|
|
|
`${UsersMock.user.name}'s avatar`,
|
|
|
|
);
|
2018-10-30 17:36:07 -04:00
|
|
|
|
2017-05-05 14:23:31 -04:00
|
|
|
expect(assignee.querySelector('.author').innerText.trim()).toEqual(UsersMock.user.name);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Shows one user with avatar, username and author name', () => {
|
|
|
|
component = new AssigneeComponent({
|
|
|
|
propsData: {
|
|
|
|
rootPath: 'http://localhost:3000/',
|
2018-10-30 16:28:31 -04:00
|
|
|
users: [UsersMock.user],
|
2017-05-05 14:23:31 -04:00
|
|
|
editable: true,
|
|
|
|
},
|
|
|
|
}).$mount();
|
|
|
|
|
2018-07-23 11:03:40 -04:00
|
|
|
expect(component.$el.querySelector('.author-link')).not.toBeNull();
|
2017-05-05 14:23:31 -04:00
|
|
|
// The image
|
2018-10-30 16:28:31 -04:00
|
|
|
expect(component.$el.querySelector('.author-link img').getAttribute('src')).toEqual(
|
|
|
|
UsersMock.user.avatar,
|
|
|
|
);
|
2017-05-05 14:23:31 -04:00
|
|
|
// Author name
|
2018-10-30 16:28:31 -04:00
|
|
|
expect(component.$el.querySelector('.author-link .author').innerText.trim()).toEqual(
|
|
|
|
UsersMock.user.name,
|
|
|
|
);
|
2017-05-05 14:23:31 -04:00
|
|
|
// Username
|
2018-10-30 16:28:31 -04:00
|
|
|
expect(component.$el.querySelector('.author-link .username').innerText.trim()).toEqual(
|
|
|
|
`@${UsersMock.user.username}`,
|
|
|
|
);
|
2017-05-05 14:23:31 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
it('has the root url present in the assigneeUrl method', () => {
|
|
|
|
component = new AssigneeComponent({
|
|
|
|
propsData: {
|
|
|
|
rootPath: 'http://localhost:3000/',
|
2018-10-30 16:28:31 -04:00
|
|
|
users: [UsersMock.user],
|
2017-05-05 14:23:31 -04:00
|
|
|
editable: true,
|
|
|
|
},
|
|
|
|
}).$mount();
|
|
|
|
|
2018-10-30 16:28:31 -04:00
|
|
|
expect(component.assigneeUrl(UsersMock.user).indexOf('http://localhost:3000/')).not.toEqual(
|
|
|
|
-1,
|
|
|
|
);
|
2017-05-05 14:23:31 -04:00
|
|
|
});
|
2019-04-07 14:35:16 -04:00
|
|
|
|
|
|
|
it('has correct "cannot merge" tooltip when user cannot merge', () => {
|
|
|
|
const user = Object.assign({}, UsersMock.user, { can_merge: false });
|
|
|
|
|
|
|
|
component = new AssigneeComponent({
|
|
|
|
propsData: {
|
|
|
|
rootPath: 'http://localhost:3000/',
|
|
|
|
users: [user],
|
|
|
|
editable: true,
|
|
|
|
issuableType: 'merge_request',
|
|
|
|
},
|
|
|
|
}).$mount();
|
|
|
|
|
|
|
|
expect(component.mergeNotAllowedTooltipMessage).toEqual('Cannot merge');
|
|
|
|
});
|
2017-05-05 14:23:31 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
describe('Two or more assignees/users', () => {
|
2019-04-07 14:35:16 -04:00
|
|
|
it('has correct "cannot merge" tooltip when one user can merge', () => {
|
|
|
|
const users = UsersMockHelper.createNumberRandomUsers(3);
|
|
|
|
users[0].can_merge = true;
|
|
|
|
users[1].can_merge = false;
|
|
|
|
users[2].can_merge = false;
|
|
|
|
|
|
|
|
component = new AssigneeComponent({
|
|
|
|
propsData: {
|
|
|
|
rootPath: 'http://localhost:3000/',
|
|
|
|
users,
|
|
|
|
editable: true,
|
|
|
|
issuableType: 'merge_request',
|
|
|
|
},
|
|
|
|
}).$mount();
|
|
|
|
|
|
|
|
expect(component.mergeNotAllowedTooltipMessage).toEqual('1/3 can merge');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('has correct "cannot merge" tooltip when no user can merge', () => {
|
|
|
|
const users = UsersMockHelper.createNumberRandomUsers(2);
|
|
|
|
users[0].can_merge = false;
|
|
|
|
users[1].can_merge = false;
|
|
|
|
|
|
|
|
component = new AssigneeComponent({
|
|
|
|
propsData: {
|
|
|
|
rootPath: 'http://localhost:3000/',
|
|
|
|
users,
|
|
|
|
editable: true,
|
|
|
|
issuableType: 'merge_request',
|
|
|
|
},
|
|
|
|
}).$mount();
|
|
|
|
|
|
|
|
expect(component.mergeNotAllowedTooltipMessage).toEqual('No one can merge');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('has correct "cannot merge" tooltip when more than one user can merge', () => {
|
|
|
|
const users = UsersMockHelper.createNumberRandomUsers(3);
|
|
|
|
users[0].can_merge = false;
|
|
|
|
users[1].can_merge = true;
|
|
|
|
users[2].can_merge = true;
|
|
|
|
|
|
|
|
component = new AssigneeComponent({
|
|
|
|
propsData: {
|
|
|
|
rootPath: 'http://localhost:3000/',
|
|
|
|
users,
|
|
|
|
editable: true,
|
|
|
|
issuableType: 'merge_request',
|
|
|
|
},
|
|
|
|
}).$mount();
|
|
|
|
|
|
|
|
expect(component.mergeNotAllowedTooltipMessage).toEqual('2/3 can merge');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('has no "cannot merge" tooltip when every user can merge', () => {
|
|
|
|
const users = UsersMockHelper.createNumberRandomUsers(2);
|
|
|
|
users[0].can_merge = true;
|
|
|
|
users[1].can_merge = true;
|
|
|
|
|
|
|
|
component = new AssigneeComponent({
|
|
|
|
propsData: {
|
|
|
|
rootPath: 'http://localhost:3000/',
|
|
|
|
users,
|
|
|
|
editable: true,
|
|
|
|
issuableType: 'merge_request',
|
|
|
|
},
|
|
|
|
}).$mount();
|
|
|
|
|
|
|
|
expect(component.mergeNotAllowedTooltipMessage).toEqual(null);
|
|
|
|
});
|
|
|
|
|
2017-05-05 14:23:31 -04:00
|
|
|
it('displays two assignee icons when collapsed', () => {
|
|
|
|
const users = UsersMockHelper.createNumberRandomUsers(2);
|
|
|
|
component = new AssigneeComponent({
|
|
|
|
propsData: {
|
|
|
|
rootPath: 'http://localhost:3000',
|
|
|
|
users,
|
|
|
|
editable: false,
|
|
|
|
},
|
|
|
|
}).$mount();
|
|
|
|
|
|
|
|
const collapsed = component.$el.querySelector('.sidebar-collapsed-icon');
|
2018-10-09 14:03:09 -04:00
|
|
|
|
2017-05-05 14:23:31 -04:00
|
|
|
expect(collapsed.childElementCount).toEqual(2);
|
|
|
|
|
|
|
|
const first = collapsed.children[0];
|
2018-10-09 14:03:09 -04:00
|
|
|
|
2017-05-05 15:45:14 -04:00
|
|
|
expect(first.querySelector('.avatar').getAttribute('src')).toEqual(users[0].avatar);
|
2018-10-30 16:28:31 -04:00
|
|
|
expect(first.querySelector('.avatar').getAttribute('alt')).toEqual(
|
|
|
|
`${users[0].name}'s avatar`,
|
|
|
|
);
|
2018-10-30 17:36:07 -04:00
|
|
|
|
2017-05-05 14:23:31 -04:00
|
|
|
expect(first.querySelector('.author').innerText.trim()).toEqual(users[0].name);
|
|
|
|
|
|
|
|
const second = collapsed.children[1];
|
2018-10-09 14:03:09 -04:00
|
|
|
|
2017-05-05 15:45:14 -04:00
|
|
|
expect(second.querySelector('.avatar').getAttribute('src')).toEqual(users[1].avatar);
|
2018-10-30 16:28:31 -04:00
|
|
|
expect(second.querySelector('.avatar').getAttribute('alt')).toEqual(
|
|
|
|
`${users[1].name}'s avatar`,
|
|
|
|
);
|
2018-10-30 17:36:07 -04:00
|
|
|
|
2017-05-05 14:23:31 -04:00
|
|
|
expect(second.querySelector('.author').innerText.trim()).toEqual(users[1].name);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('displays one assignee icon and counter when collapsed', () => {
|
|
|
|
const users = UsersMockHelper.createNumberRandomUsers(3);
|
|
|
|
component = new AssigneeComponent({
|
|
|
|
propsData: {
|
|
|
|
rootPath: 'http://localhost:3000',
|
|
|
|
users,
|
|
|
|
editable: false,
|
|
|
|
},
|
|
|
|
}).$mount();
|
|
|
|
|
|
|
|
const collapsed = component.$el.querySelector('.sidebar-collapsed-icon');
|
2018-10-09 14:03:09 -04:00
|
|
|
|
2017-05-05 14:23:31 -04:00
|
|
|
expect(collapsed.childElementCount).toEqual(2);
|
|
|
|
|
|
|
|
const first = collapsed.children[0];
|
2018-10-09 14:03:09 -04:00
|
|
|
|
2017-05-05 15:45:14 -04:00
|
|
|
expect(first.querySelector('.avatar').getAttribute('src')).toEqual(users[0].avatar);
|
2018-10-30 16:28:31 -04:00
|
|
|
expect(first.querySelector('.avatar').getAttribute('alt')).toEqual(
|
|
|
|
`${users[0].name}'s avatar`,
|
|
|
|
);
|
2018-10-30 17:36:07 -04:00
|
|
|
|
2017-05-05 14:23:31 -04:00
|
|
|
expect(first.querySelector('.author').innerText.trim()).toEqual(users[0].name);
|
|
|
|
|
|
|
|
const second = collapsed.children[1];
|
2018-10-09 14:03:09 -04:00
|
|
|
|
2017-05-05 14:23:31 -04:00
|
|
|
expect(second.querySelector('.avatar-counter').innerText.trim()).toEqual('+2');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Shows two assignees', () => {
|
|
|
|
const users = UsersMockHelper.createNumberRandomUsers(2);
|
|
|
|
component = new AssigneeComponent({
|
|
|
|
propsData: {
|
|
|
|
rootPath: 'http://localhost:3000',
|
|
|
|
users,
|
|
|
|
editable: true,
|
|
|
|
},
|
|
|
|
}).$mount();
|
|
|
|
|
|
|
|
expect(component.$el.querySelectorAll('.user-item').length).toEqual(users.length);
|
|
|
|
expect(component.$el.querySelector('.user-list-more')).toBe(null);
|
|
|
|
});
|
|
|
|
|
2019-03-26 15:23:19 -04:00
|
|
|
it('sets tooltip container to body', () => {
|
|
|
|
const users = UsersMockHelper.createNumberRandomUsers(2);
|
|
|
|
component = new AssigneeComponent({
|
|
|
|
propsData: {
|
|
|
|
rootPath: 'http://localhost:3000',
|
|
|
|
users,
|
|
|
|
editable: true,
|
|
|
|
},
|
|
|
|
}).$mount();
|
|
|
|
|
|
|
|
expect(component.$el.querySelector('.user-link').getAttribute('data-container')).toBe('body');
|
|
|
|
});
|
|
|
|
|
2018-10-30 16:28:31 -04:00
|
|
|
it('Shows the "show-less" assignees label', done => {
|
2017-05-05 14:23:31 -04:00
|
|
|
const users = UsersMockHelper.createNumberRandomUsers(6);
|
|
|
|
component = new AssigneeComponent({
|
|
|
|
propsData: {
|
|
|
|
rootPath: 'http://localhost:3000',
|
|
|
|
users,
|
|
|
|
editable: true,
|
|
|
|
},
|
|
|
|
}).$mount();
|
|
|
|
|
2018-10-30 16:28:31 -04:00
|
|
|
expect(component.$el.querySelectorAll('.user-item').length).toEqual(
|
|
|
|
component.defaultRenderCount,
|
|
|
|
);
|
2018-10-30 17:36:07 -04:00
|
|
|
|
2017-05-05 14:23:31 -04:00
|
|
|
expect(component.$el.querySelector('.user-list-more')).not.toBe(null);
|
|
|
|
const usersLabelExpectation = users.length - component.defaultRenderCount;
|
2018-10-09 14:03:09 -04:00
|
|
|
|
2018-10-30 16:28:31 -04:00
|
|
|
expect(component.$el.querySelector('.user-list-more .btn-link').innerText.trim()).not.toBe(
|
|
|
|
`+${usersLabelExpectation} more`,
|
|
|
|
);
|
2017-05-05 14:23:31 -04:00
|
|
|
component.toggleShowLess();
|
|
|
|
Vue.nextTick(() => {
|
2018-10-30 16:28:31 -04:00
|
|
|
expect(component.$el.querySelector('.user-list-more .btn-link').innerText.trim()).toBe(
|
|
|
|
'- show less',
|
|
|
|
);
|
2017-05-05 14:23:31 -04:00
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2018-10-30 16:28:31 -04:00
|
|
|
it('Shows the "show-less" when "n+ more " label is clicked', done => {
|
2017-05-05 14:23:31 -04:00
|
|
|
const users = UsersMockHelper.createNumberRandomUsers(6);
|
|
|
|
component = new AssigneeComponent({
|
|
|
|
propsData: {
|
|
|
|
rootPath: 'http://localhost:3000',
|
|
|
|
users,
|
|
|
|
editable: true,
|
|
|
|
},
|
|
|
|
}).$mount();
|
|
|
|
|
|
|
|
component.$el.querySelector('.user-list-more .btn-link').click();
|
|
|
|
Vue.nextTick(() => {
|
2018-10-30 16:28:31 -04:00
|
|
|
expect(component.$el.querySelector('.user-list-more .btn-link').innerText.trim()).toBe(
|
|
|
|
'- show less',
|
|
|
|
);
|
2017-05-05 14:23:31 -04:00
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('gets the count of avatar via a computed property ', () => {
|
|
|
|
const users = UsersMockHelper.createNumberRandomUsers(6);
|
|
|
|
component = new AssigneeComponent({
|
|
|
|
propsData: {
|
|
|
|
rootPath: 'http://localhost:3000',
|
|
|
|
users,
|
|
|
|
editable: true,
|
|
|
|
},
|
|
|
|
}).$mount();
|
|
|
|
|
|
|
|
expect(component.sidebarAvatarCounter).toEqual(`+${users.length - 1}`);
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('n+ more label', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
const users = UsersMockHelper.createNumberRandomUsers(6);
|
|
|
|
component = new AssigneeComponent({
|
|
|
|
propsData: {
|
|
|
|
rootPath: 'http://localhost:3000',
|
|
|
|
users,
|
|
|
|
editable: true,
|
|
|
|
},
|
|
|
|
}).$mount();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('shows "+1 more" label', () => {
|
2018-10-30 16:28:31 -04:00
|
|
|
expect(component.$el.querySelector('.user-list-more .btn-link').innerText.trim()).toBe(
|
|
|
|
'+ 1 more',
|
|
|
|
);
|
2017-05-05 14:23:31 -04:00
|
|
|
});
|
|
|
|
|
2018-10-30 16:28:31 -04:00
|
|
|
it('shows "show less" label', done => {
|
2017-05-05 14:23:31 -04:00
|
|
|
component.toggleShowLess();
|
|
|
|
|
|
|
|
Vue.nextTick(() => {
|
2018-10-30 16:28:31 -04:00
|
|
|
expect(component.$el.querySelector('.user-list-more .btn-link').innerText.trim()).toBe(
|
|
|
|
'- show less',
|
|
|
|
);
|
2017-05-05 14:23:31 -04:00
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|