Add sidebar specs
This commit is contained in:
parent
933447e0da
commit
48e4991907
|
@ -17,15 +17,21 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
listenForSlashCommands() {
|
||||
$(document).on('ajax:success', '.gfm-form', (e, data) => {
|
||||
const subscribedCommands = ['spend_time', 'time_estimate'];
|
||||
const changedCommands = data.commands_changes
|
||||
$(document).on('ajax:success', '.gfm-form', this.slashCommandListened);
|
||||
},
|
||||
slashCommandListened(e, data) {
|
||||
const subscribedCommands = ['spend_time', 'time_estimate'];
|
||||
let changedCommands;
|
||||
if (data !== undefined) {
|
||||
changedCommands = data.commands_changes
|
||||
? Object.keys(data.commands_changes)
|
||||
: [];
|
||||
if (changedCommands && _.intersection(subscribedCommands, changedCommands).length) {
|
||||
this.mediator.fetch();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
changedCommands = [];
|
||||
}
|
||||
if (changedCommands && _.intersection(subscribedCommands, changedCommands).length) {
|
||||
this.mediator.fetch();
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
|
|
|
@ -4,7 +4,7 @@ import sidebarAssignees from './components/assignees/sidebar_assignees';
|
|||
|
||||
import Mediator from './sidebar_mediator';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
function domContentLoaded() {
|
||||
const mediator = new Mediator(gl.sidebarOptions);
|
||||
mediator.fetch();
|
||||
|
||||
|
@ -17,5 +17,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||
}
|
||||
|
||||
new Vue(sidebarTimeTracking).$mount('#issuable-time-tracker');
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', domContentLoaded);
|
||||
|
||||
export default domContentLoaded;
|
||||
|
|
|
@ -30,8 +30,8 @@ export default class SidebarMediator {
|
|||
this.service.get()
|
||||
.then((response) => {
|
||||
const data = response.json();
|
||||
this.store.processAssigneeData(data);
|
||||
this.store.processTimeTrackingData(data);
|
||||
this.store.setAssigneeData(data);
|
||||
this.store.setTimeTrackingData(data);
|
||||
})
|
||||
.catch(() => new Flash('Error occured when fetching sidebar data'));
|
||||
}
|
||||
|
|
|
@ -17,13 +17,13 @@ export default class SidebarStore {
|
|||
return SidebarStore.singleton;
|
||||
}
|
||||
|
||||
processAssigneeData(data) {
|
||||
setAssigneeData(data) {
|
||||
if (data.assignees) {
|
||||
this.assignees = data.assignees;
|
||||
}
|
||||
}
|
||||
|
||||
processTimeTrackingData(data) {
|
||||
setTimeTrackingData(data) {
|
||||
this.timeEstimate = data.time_estimate;
|
||||
this.totalTimeSpent = data.total_time_spent;
|
||||
this.humanTimeEstimate = data.human_time_estimate;
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
import Vue from 'vue';
|
||||
import AssigneeTitle from '~/sidebar/components/assignees/assignee_title';
|
||||
|
||||
describe('AssigneeTitle component', () => {
|
||||
let component;
|
||||
let AssigneeTitleComponent;
|
||||
|
||||
beforeEach(() => {
|
||||
AssigneeTitleComponent = Vue.extend(AssigneeTitle);
|
||||
});
|
||||
|
||||
describe('assignee title', () => {
|
||||
it('renders assignee', () => {
|
||||
component = new AssigneeTitleComponent({
|
||||
propsData: {
|
||||
numberOfAssignees: 1,
|
||||
editable: false,
|
||||
},
|
||||
}).$mount();
|
||||
|
||||
expect(component.$el.innerText.trim()).toEqual('Assignee');
|
||||
});
|
||||
|
||||
it('renders 2 assignees', () => {
|
||||
component = new AssigneeTitleComponent({
|
||||
propsData: {
|
||||
numberOfAssignees: 2,
|
||||
editable: false,
|
||||
},
|
||||
}).$mount();
|
||||
|
||||
expect(component.$el.innerText.trim()).toEqual('2 Assignees');
|
||||
});
|
||||
});
|
||||
|
||||
it('does not render spinner by default', () => {
|
||||
component = new AssigneeTitleComponent({
|
||||
propsData: {
|
||||
numberOfAssignees: 0,
|
||||
editable: false,
|
||||
},
|
||||
}).$mount();
|
||||
|
||||
expect(component.$el.querySelector('.fa')).toBeNull();
|
||||
});
|
||||
|
||||
it('renders spinner when loading', () => {
|
||||
component = new AssigneeTitleComponent({
|
||||
propsData: {
|
||||
loading: true,
|
||||
numberOfAssignees: 0,
|
||||
editable: false,
|
||||
},
|
||||
}).$mount();
|
||||
|
||||
expect(component.$el.querySelector('.fa')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('does not render edit link when not editable', () => {
|
||||
component = new AssigneeTitleComponent({
|
||||
propsData: {
|
||||
numberOfAssignees: 0,
|
||||
editable: false,
|
||||
},
|
||||
}).$mount();
|
||||
|
||||
expect(component.$el.querySelector('.edit-link')).toBeNull();
|
||||
});
|
||||
|
||||
it('renders edit link when editable', () => {
|
||||
component = new AssigneeTitleComponent({
|
||||
propsData: {
|
||||
numberOfAssignees: 0,
|
||||
editable: true,
|
||||
},
|
||||
}).$mount();
|
||||
|
||||
expect(component.$el.querySelector('.edit-link')).not.toBeNull();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,272 @@
|
|||
import Vue from 'vue';
|
||||
import Assignee from '~/sidebar/components/assignees/assignees';
|
||||
import UsersMock from './mock_data';
|
||||
import UsersMockHelper from '../test_helpers/user_mock_data';
|
||||
|
||||
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');
|
||||
expect(collapsed.childElementCount).toEqual(1);
|
||||
expect(collapsed.children[0].getAttribute('aria-label')).toEqual('No Assignee');
|
||||
expect(collapsed.children[0].classList.contains('fa')).toEqual(true);
|
||||
expect(collapsed.children[0].classList.contains('fa-user')).toEqual(true);
|
||||
});
|
||||
|
||||
it('displays only "No assignee" when no users are assigned and the issue is read-only', () => {
|
||||
component = new AssigneeComponent({
|
||||
propsData: {
|
||||
rootPath: 'http://localhost:3000',
|
||||
users: [],
|
||||
editable: false,
|
||||
},
|
||||
}).$mount();
|
||||
const componentTextNoUsers = component.$el.querySelector('.assign-yourself').innerText.trim();
|
||||
|
||||
expect(componentTextNoUsers).toBe('No assignee');
|
||||
expect(componentTextNoUsers.indexOf('assign yourself')).toEqual(-1);
|
||||
});
|
||||
|
||||
it('displays only "No assignee" when no users are assigned and the issue can be edited', () => {
|
||||
component = new AssigneeComponent({
|
||||
propsData: {
|
||||
rootPath: 'http://localhost:3000',
|
||||
users: [],
|
||||
editable: true,
|
||||
},
|
||||
}).$mount();
|
||||
const componentTextNoUsers = component.$el.querySelector('.assign-yourself').innerText.trim();
|
||||
|
||||
expect(componentTextNoUsers.indexOf('No assignee')).toEqual(0);
|
||||
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();
|
||||
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',
|
||||
users: [
|
||||
UsersMock.user,
|
||||
],
|
||||
editable: false,
|
||||
},
|
||||
}).$mount();
|
||||
|
||||
const collapsed = component.$el.querySelector('.sidebar-collapsed-icon');
|
||||
const assignee = collapsed.children[0];
|
||||
expect(collapsed.childElementCount).toEqual(1);
|
||||
expect(assignee.querySelector('.avatar').getAttribute('src')).toEqual(UsersMock.user.avatarUrl);
|
||||
expect(assignee.querySelector('.avatar').getAttribute('alt')).toEqual(`${UsersMock.user.name}'s avatar`);
|
||||
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/',
|
||||
users: [
|
||||
UsersMock.user,
|
||||
],
|
||||
editable: true,
|
||||
},
|
||||
}).$mount();
|
||||
|
||||
expect(component.$el.querySelector('.author_link')).not.toBeNull();
|
||||
// The image
|
||||
expect(component.$el.querySelector('.author_link img').getAttribute('src')).toEqual(UsersMock.user.avatarUrl);
|
||||
// Author name
|
||||
expect(component.$el.querySelector('.author_link .author').innerText.trim()).toEqual(UsersMock.user.name);
|
||||
// Username
|
||||
expect(component.$el.querySelector('.author_link .username').innerText.trim()).toEqual(`@${UsersMock.user.username}`);
|
||||
});
|
||||
|
||||
it('has the root url present in the assigneeUrl method', () => {
|
||||
component = new AssigneeComponent({
|
||||
propsData: {
|
||||
rootPath: 'http://localhost:3000/',
|
||||
users: [
|
||||
UsersMock.user,
|
||||
],
|
||||
editable: true,
|
||||
},
|
||||
}).$mount();
|
||||
|
||||
expect(component.assigneeUrl(UsersMock.user).indexOf('http://localhost:3000/')).not.toEqual(-1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Two or more assignees/users', () => {
|
||||
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');
|
||||
expect(collapsed.childElementCount).toEqual(2);
|
||||
|
||||
const first = collapsed.children[0];
|
||||
expect(first.querySelector('.avatar').getAttribute('src')).toEqual(users[0].avatarUrl);
|
||||
expect(first.querySelector('.avatar').getAttribute('alt')).toEqual(`${users[0].name}'s avatar`);
|
||||
expect(first.querySelector('.author').innerText.trim()).toEqual(users[0].name);
|
||||
|
||||
const second = collapsed.children[1];
|
||||
expect(second.querySelector('.avatar').getAttribute('src')).toEqual(users[1].avatarUrl);
|
||||
expect(second.querySelector('.avatar').getAttribute('alt')).toEqual(`${users[1].name}'s avatar`);
|
||||
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');
|
||||
expect(collapsed.childElementCount).toEqual(2);
|
||||
|
||||
const first = collapsed.children[0];
|
||||
expect(first.querySelector('.avatar').getAttribute('src')).toEqual(users[0].avatarUrl);
|
||||
expect(first.querySelector('.avatar').getAttribute('alt')).toEqual(`${users[0].name}'s avatar`);
|
||||
expect(first.querySelector('.author').innerText.trim()).toEqual(users[0].name);
|
||||
|
||||
const second = collapsed.children[1];
|
||||
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);
|
||||
});
|
||||
|
||||
it('Shows the "show-less" assignees label', (done) => {
|
||||
const users = UsersMockHelper.createNumberRandomUsers(6);
|
||||
component = new AssigneeComponent({
|
||||
propsData: {
|
||||
rootPath: 'http://localhost:3000',
|
||||
users,
|
||||
editable: true,
|
||||
},
|
||||
}).$mount();
|
||||
|
||||
expect(component.$el.querySelectorAll('.user-item').length).toEqual(component.defaultRenderCount);
|
||||
expect(component.$el.querySelector('.user-list-more')).not.toBe(null);
|
||||
const usersLabelExpectation = users.length - component.defaultRenderCount;
|
||||
expect(component.$el.querySelector('.user-list-more .btn-link').innerText.trim())
|
||||
.not.toBe(`+${usersLabelExpectation} more`);
|
||||
component.toggleShowLess();
|
||||
Vue.nextTick(() => {
|
||||
expect(component.$el.querySelector('.user-list-more .btn-link').innerText.trim())
|
||||
.toBe('- show less');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Shows the "show-less" when "n+ more " label is clicked', (done) => {
|
||||
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(() => {
|
||||
expect(component.$el.querySelector('.user-list-more .btn-link').innerText.trim())
|
||||
.toBe('- show less');
|
||||
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', () => {
|
||||
expect(component.$el.querySelector('.user-list-more .btn-link').innerText.trim())
|
||||
.toBe('+ 1 more');
|
||||
});
|
||||
|
||||
it('shows "show less" label', (done) => {
|
||||
component.toggleShowLess();
|
||||
|
||||
Vue.nextTick(() => {
|
||||
expect(component.$el.querySelector('.user-list-more .btn-link').innerText.trim())
|
||||
.toBe('- show less');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,109 @@
|
|||
/* eslint-disable quote-props*/
|
||||
|
||||
const sidebarMockData = {
|
||||
'GET': {
|
||||
'/gitlab-org/gitlab-shell/issues/5.json': {
|
||||
id: 45,
|
||||
iid: 5,
|
||||
author_id: 23,
|
||||
description: 'Nulla ullam commodi delectus adipisci quis sit.',
|
||||
lock_version: null,
|
||||
milestone_id: 21,
|
||||
position: 0,
|
||||
state: 'closed',
|
||||
title: 'Vel et nulla voluptatibus corporis dolor iste saepe laborum.',
|
||||
updated_by_id: 1,
|
||||
created_at: '2017-02-02T21: 49: 49.664Z',
|
||||
updated_at: '2017-05-03T22: 26: 03.760Z',
|
||||
deleted_at: null,
|
||||
time_estimate: 0,
|
||||
total_time_spent: 0,
|
||||
human_time_estimate: null,
|
||||
human_total_time_spent: null,
|
||||
branch_name: null,
|
||||
confidential: false,
|
||||
assignees: [
|
||||
{
|
||||
name: 'User 0',
|
||||
username: 'user0',
|
||||
id: 22,
|
||||
state: 'active',
|
||||
avatar_url: 'http: //www.gravatar.com/avatar/52e4ce24a915fb7e51e1ad3b57f4b00a?s=80\u0026d=identicon',
|
||||
web_url: 'http: //localhost:3001/user0',
|
||||
},
|
||||
{
|
||||
name: 'Marguerite Bartell',
|
||||
username: 'tajuana',
|
||||
id: 18,
|
||||
state: 'active',
|
||||
avatar_url: 'http: //www.gravatar.com/avatar/4852a41fb41616bf8f140d3701673f53?s=80\u0026d=identicon',
|
||||
web_url: 'http: //localhost:3001/tajuana',
|
||||
},
|
||||
{
|
||||
name: 'Laureen Ritchie',
|
||||
username: 'michaele.will',
|
||||
id: 16,
|
||||
state: 'active',
|
||||
avatar_url: 'http: //www.gravatar.com/avatar/e301827eb03be955c9c172cb9a8e4e8a?s=80\u0026d=identicon',
|
||||
web_url: 'http: //localhost:3001/michaele.will',
|
||||
},
|
||||
],
|
||||
due_date: null,
|
||||
moved_to_id: null,
|
||||
project_id: 4,
|
||||
weight: null,
|
||||
milestone: {
|
||||
id: 21,
|
||||
iid: 1,
|
||||
project_id: 4,
|
||||
title: 'v0.0',
|
||||
description: 'Molestiae commodi laboriosam odio sunt eaque reprehenderit.',
|
||||
state: 'active',
|
||||
created_at: '2017-02-02T21: 49: 30.530Z',
|
||||
updated_at: '2017-02-02T21: 49: 30.530Z',
|
||||
due_date: null,
|
||||
start_date: null,
|
||||
},
|
||||
labels: [],
|
||||
},
|
||||
},
|
||||
'PUT': {
|
||||
'/gitlab-org/gitlab-shell/issues/5.json': {
|
||||
data: {},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
mediator: {
|
||||
endpoint: '/gitlab-org/gitlab-shell/issues/5.json',
|
||||
editable: true,
|
||||
currentUser: {
|
||||
id: 1,
|
||||
name: 'Administrator',
|
||||
username: 'root',
|
||||
avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
|
||||
},
|
||||
rootPath: '/',
|
||||
},
|
||||
time: {
|
||||
time_estimate: 3600,
|
||||
total_time_spent: 0,
|
||||
human_time_estimate: '1h',
|
||||
human_total_time_spent: null,
|
||||
},
|
||||
user: {
|
||||
avatarUrl: 'http://gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
|
||||
id: 1,
|
||||
name: 'Administrator',
|
||||
username: 'root',
|
||||
},
|
||||
|
||||
sidebarMockInterceptor(request, next) {
|
||||
const body = sidebarMockData[request.method.toUpperCase()][request.url];
|
||||
|
||||
next(request.respondWith(JSON.stringify(body), {
|
||||
status: 200,
|
||||
}));
|
||||
},
|
||||
};
|
|
@ -0,0 +1,45 @@
|
|||
import Vue from 'vue';
|
||||
import SidebarAssignees from '~/sidebar/components/assignees/sidebar_assignees';
|
||||
import SidebarMediator from '~/sidebar/sidebar_mediator';
|
||||
import SidebarService from '~/sidebar/services/sidebar_service';
|
||||
import SidebarStore from '~/sidebar/stores/sidebar_store';
|
||||
import Mock from './mock_data';
|
||||
|
||||
describe('sidebar assignees', () => {
|
||||
let component;
|
||||
let SidebarAssigneeComponent;
|
||||
preloadFixtures('issues/open-issue.html.raw');
|
||||
|
||||
beforeEach(() => {
|
||||
Vue.http.interceptors.push(Mock.sidebarMockInterceptor);
|
||||
SidebarAssigneeComponent = Vue.extend(SidebarAssignees);
|
||||
spyOn(SidebarMediator.prototype, 'saveAssignees').and.callThrough();
|
||||
spyOn(SidebarMediator.prototype, 'assignYourself').and.callThrough();
|
||||
this.mediator = new SidebarMediator(Mock.mediator);
|
||||
loadFixtures('issues/open-issue.html.raw');
|
||||
this.sidebarAssigneesEl = document.querySelector('#js-vue-sidebar-assignees');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
SidebarService.singleton = null;
|
||||
SidebarStore.singleton = null;
|
||||
SidebarMediator.singleton = null;
|
||||
});
|
||||
|
||||
it('calls the mediator when saves the assignees', () => {
|
||||
component = new SidebarAssigneeComponent()
|
||||
.$mount(this.sidebarAssigneesEl);
|
||||
component.saveAssignees();
|
||||
|
||||
expect(SidebarMediator.prototype.saveAssignees).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('calls the mediator when "assignSelf" method is called', () => {
|
||||
component = new SidebarAssigneeComponent()
|
||||
.$mount(this.sidebarAssigneesEl);
|
||||
component.assignSelf();
|
||||
|
||||
expect(SidebarMediator.prototype.assignYourself).toHaveBeenCalled();
|
||||
expect(this.mediator.store.assignees.length).toEqual(1);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,42 @@
|
|||
import Vue from 'vue';
|
||||
import SidebarBundleDomContentLoaded from '~/sidebar/sidebar_bundle';
|
||||
import SidebarTimeTracking from '~/sidebar/components/time_tracking/sidebar_time_tracking';
|
||||
import SidebarMediator from '~/sidebar/sidebar_mediator';
|
||||
import SidebarService from '~/sidebar/services/sidebar_service';
|
||||
import SidebarStore from '~/sidebar/stores/sidebar_store';
|
||||
import Mock from './mock_data';
|
||||
|
||||
describe('sidebar bundle', () => {
|
||||
gl.sidebarOptions = Mock.mediator;
|
||||
|
||||
beforeEach(() => {
|
||||
spyOn(SidebarTimeTracking.methods, 'listenForSlashCommands').and.callFake(() => { });
|
||||
preloadFixtures('issues/open-issue.html.raw');
|
||||
Vue.http.interceptors.push(Mock.sidebarMockInterceptor);
|
||||
loadFixtures('issues/open-issue.html.raw');
|
||||
spyOn(Vue.prototype, '$mount');
|
||||
SidebarBundleDomContentLoaded();
|
||||
this.mediator = new SidebarMediator();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
SidebarService.singleton = null;
|
||||
SidebarStore.singleton = null;
|
||||
SidebarMediator.singleton = null;
|
||||
});
|
||||
|
||||
it('the mediator should be already defined with some data', () => {
|
||||
SidebarBundleDomContentLoaded();
|
||||
|
||||
expect(this.mediator.store).toBeDefined();
|
||||
expect(this.mediator.service).toBeDefined();
|
||||
expect(this.mediator.store.currentUser).toEqual(Mock.mediator.currentUser);
|
||||
expect(this.mediator.store.rootPath).toEqual(Mock.mediator.rootPath);
|
||||
expect(this.mediator.store.endPoint).toEqual(Mock.mediator.endPoint);
|
||||
expect(this.mediator.store.editable).toEqual(Mock.mediator.editable);
|
||||
});
|
||||
|
||||
it('the sidebar time tracking and assignees components to have been mounted', () => {
|
||||
expect(Vue.prototype.$mount).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,38 @@
|
|||
import Vue from 'vue';
|
||||
import SidebarMediator from '~/sidebar/sidebar_mediator';
|
||||
import SidebarStore from '~/sidebar/stores/sidebar_store';
|
||||
import SidebarService from '~/sidebar/services/sidebar_service';
|
||||
import Mock from './mock_data';
|
||||
|
||||
describe('Sidebar mediator', () => {
|
||||
beforeEach(() => {
|
||||
Vue.http.interceptors.push(Mock.sidebarMockInterceptor);
|
||||
this.mediator = new SidebarMediator(Mock.mediator);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
SidebarService.singleton = null;
|
||||
SidebarStore.singleton = null;
|
||||
SidebarMediator.singleton = null;
|
||||
});
|
||||
|
||||
it('assigns yourself ', () => {
|
||||
this.mediator.assignYourself();
|
||||
|
||||
expect(this.mediator.store.currentUser).toEqual(Mock.mediator.currentUser);
|
||||
expect(this.mediator.store.assignees[0]).toEqual(Mock.mediator.currentUser);
|
||||
});
|
||||
|
||||
it('saves assignees', (done) => {
|
||||
this.mediator.saveAssignees('issue[assignee_ids]').then((resp) => {
|
||||
expect(resp.status).toEqual(200);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fetches the data', () => {
|
||||
spyOn(this.mediator.service, 'get').and.callThrough();
|
||||
this.mediator.fetch();
|
||||
expect(this.mediator.service.get).toHaveBeenCalled();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,28 @@
|
|||
import Vue from 'vue';
|
||||
import SidebarService from '~/sidebar/services/sidebar_service';
|
||||
import Mock from './mock_data';
|
||||
|
||||
describe('Sidebar service', () => {
|
||||
beforeEach(() => {
|
||||
Vue.http.interceptors.push(Mock.sidebarMockInterceptor);
|
||||
this.service = new SidebarService('/gitlab-org/gitlab-shell/issues/5.json');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
SidebarService.singleton = null;
|
||||
});
|
||||
|
||||
it('gets the data', (done) => {
|
||||
this.service.get().then((resp) => {
|
||||
expect(resp).toBeDefined();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('updates the data', (done) => {
|
||||
this.service.update('issue[assignee_ids]', [1]).then((resp) => {
|
||||
expect(resp).toBeDefined();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,80 @@
|
|||
import SidebarStore from '~/sidebar/stores/sidebar_store';
|
||||
import Mock from './mock_data';
|
||||
import UsersMockHelper from '../test_helpers/user_mock_data';
|
||||
|
||||
describe('Sidebar store', () => {
|
||||
const assignee = {
|
||||
id: 2,
|
||||
name: 'gitlab user 2',
|
||||
username: 'gitlab2',
|
||||
avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
|
||||
};
|
||||
|
||||
const anotherAssignee = {
|
||||
id: 3,
|
||||
name: 'gitlab user 3',
|
||||
username: 'gitlab3',
|
||||
avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
this.store = new SidebarStore({
|
||||
currentUser: {
|
||||
id: 1,
|
||||
name: 'Administrator',
|
||||
username: 'root',
|
||||
avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
|
||||
},
|
||||
editable: true,
|
||||
rootPath: '/',
|
||||
endpoint: '/gitlab-org/gitlab-shell/issues/5.json',
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
SidebarStore.singleton = null;
|
||||
});
|
||||
|
||||
it('adds a new assignee', () => {
|
||||
this.store.addAssignee(assignee);
|
||||
expect(this.store.assignees.length).toEqual(1);
|
||||
});
|
||||
|
||||
it('removes an assignee', () => {
|
||||
this.store.removeAssignee(assignee);
|
||||
expect(this.store.assignees.length).toEqual(0);
|
||||
});
|
||||
|
||||
it('finds an existent assignee', () => {
|
||||
let foundAssignee;
|
||||
|
||||
this.store.addAssignee(assignee);
|
||||
foundAssignee = this.store.findAssignee(assignee);
|
||||
expect(foundAssignee).toBeDefined();
|
||||
expect(foundAssignee).toEqual(assignee);
|
||||
foundAssignee = this.store.findAssignee(anotherAssignee);
|
||||
expect(foundAssignee).toBeUndefined();
|
||||
});
|
||||
|
||||
it('removes all assignees', () => {
|
||||
this.store.removeAllAssignees();
|
||||
expect(this.store.assignees.length).toEqual(0);
|
||||
});
|
||||
|
||||
it('set assigned data', () => {
|
||||
const users = {
|
||||
assignees: UsersMockHelper.createNumberRandomUsers(3),
|
||||
};
|
||||
|
||||
this.store.setAssigneeData(users);
|
||||
expect(this.store.assignees.length).toEqual(3);
|
||||
});
|
||||
|
||||
it('set time tracking data', () => {
|
||||
this.store.setTimeTrackingData(Mock.time);
|
||||
expect(this.store.timeEstimate).toEqual(Mock.time.time_estimate);
|
||||
expect(this.store.totalTimeSpent).toEqual(Mock.time.total_time_spent);
|
||||
expect(this.store.humanTimeEstimate).toEqual(Mock.time.human_time_estimate);
|
||||
expect(this.store.humanTotalTimeSpent).toEqual(Mock.time.human_total_time_spent);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,16 @@
|
|||
export default {
|
||||
createNumberRandomUsers(numberUsers) {
|
||||
const users = [];
|
||||
for (let i = 0; i < numberUsers; i = i += 1) {
|
||||
users.push(
|
||||
{
|
||||
avatarUrl: 'http://gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
|
||||
id: (i + 1),
|
||||
name: `GitLab User ${i}`,
|
||||
username: `gitlab${i}`,
|
||||
},
|
||||
);
|
||||
}
|
||||
return users;
|
||||
},
|
||||
};
|
Loading…
Reference in New Issue