Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
48e49919
Commit
48e49919
authored
May 05, 2017
by
Clement Ho
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add sidebar specs
parent
933447e0
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
732 additions
and
13 deletions
+732
-13
app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.js
...sidebar/components/time_tracking/sidebar_time_tracking.js
+13
-7
app/assets/javascripts/sidebar/sidebar_bundle.js
app/assets/javascripts/sidebar/sidebar_bundle.js
+5
-2
app/assets/javascripts/sidebar/sidebar_mediator.js
app/assets/javascripts/sidebar/sidebar_mediator.js
+2
-2
app/assets/javascripts/sidebar/stores/sidebar_store.js
app/assets/javascripts/sidebar/stores/sidebar_store.js
+2
-2
spec/javascripts/sidebar/assignee_title_spec.js
spec/javascripts/sidebar/assignee_title_spec.js
+80
-0
spec/javascripts/sidebar/assignees_spec.js
spec/javascripts/sidebar/assignees_spec.js
+272
-0
spec/javascripts/sidebar/mock_data.js
spec/javascripts/sidebar/mock_data.js
+109
-0
spec/javascripts/sidebar/sidebar_assignees_spec.js
spec/javascripts/sidebar/sidebar_assignees_spec.js
+45
-0
spec/javascripts/sidebar/sidebar_bundle_spec.js
spec/javascripts/sidebar/sidebar_bundle_spec.js
+42
-0
spec/javascripts/sidebar/sidebar_mediator_spec.js
spec/javascripts/sidebar/sidebar_mediator_spec.js
+38
-0
spec/javascripts/sidebar/sidebar_service_spec.js
spec/javascripts/sidebar/sidebar_service_spec.js
+28
-0
spec/javascripts/sidebar/sidebar_store_spec.js
spec/javascripts/sidebar/sidebar_store_spec.js
+80
-0
spec/javascripts/sidebar/user_mock_data.js
spec/javascripts/sidebar/user_mock_data.js
+16
-0
No files found.
app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.js
View file @
48e49919
...
...
@@ -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
()
{
...
...
app/assets/javascripts/sidebar/sidebar_bundle.js
View file @
48e49919
...
...
@@ -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
;
app/assets/javascripts/sidebar/sidebar_mediator.js
View file @
48e49919
...
...
@@ -30,8 +30,8 @@ export default class SidebarMediator {
this
.
service
.
get
()
.
then
((
response
)
=>
{
const
data
=
response
.
json
();
this
.
store
.
process
AssigneeData
(
data
);
this
.
store
.
process
TimeTrackingData
(
data
);
this
.
store
.
set
AssigneeData
(
data
);
this
.
store
.
set
TimeTrackingData
(
data
);
})
.
catch
(()
=>
new
Flash
(
'
Error occured when fetching sidebar data
'
));
}
...
...
app/assets/javascripts/sidebar/stores/sidebar_store.js
View file @
48e49919
...
...
@@ -17,13 +17,13 @@ export default class SidebarStore {
return
SidebarStore
.
singleton
;
}
process
AssigneeData
(
data
)
{
set
AssigneeData
(
data
)
{
if
(
data
.
assignees
)
{
this
.
assignees
=
data
.
assignees
;
}
}
process
TimeTrackingData
(
data
)
{
set
TimeTrackingData
(
data
)
{
this
.
timeEstimate
=
data
.
time_estimate
;
this
.
totalTimeSpent
=
data
.
total_time_spent
;
this
.
humanTimeEstimate
=
data
.
human_time_estimate
;
...
...
spec/javascripts/sidebar/assignee_title_spec.js
0 → 100644
View file @
48e49919
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
();
});
});
spec/javascripts/sidebar/assignees_spec.js
0 → 100644
View file @
48e49919
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
();
});
});
});
});
});
spec/javascripts/sidebar/mock_data.js
0 → 100644
View file @
48e49919
/* 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
,
}));
},
};
spec/javascripts/sidebar/sidebar_assignees_spec.js
0 → 100644
View file @
48e49919
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
);
});
});
spec/javascripts/sidebar/sidebar_bundle_spec.js
0 → 100644
View file @
48e49919
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
);
});
});
spec/javascripts/sidebar/sidebar_mediator_spec.js
0 → 100644
View file @
48e49919
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
();
});
});
spec/javascripts/sidebar/sidebar_service_spec.js
0 → 100644
View file @
48e49919
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
();
});
});
});
spec/javascripts/sidebar/sidebar_store_spec.js
0 → 100644
View file @
48e49919
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
);
});
});
spec/javascripts/sidebar/user_mock_data.js
0 → 100644
View file @
48e49919
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
;
},
};
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment