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
0
Merge Requests
0
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
Boxiang Sun
gitlab-ce
Commits
59a85c6b
Commit
59a85c6b
authored
May 05, 2017
by
Jacob Schatz
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'add-sidebar-specs' into 'master'
Add sidebar specs See merge request !11132
parents
86e75ae0
f1d48c25
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
738 additions
and
13 deletions
+738
-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/helpers/user_mock_data_helper.js
spec/javascripts/helpers/user_mock_data_helper.js
+16
-0
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
+40
-0
spec/javascripts/sidebar/sidebar_service_spec.js
spec/javascripts/sidebar/sidebar_service_spec.js
+32
-0
spec/javascripts/sidebar/sidebar_store_spec.js
spec/javascripts/sidebar/sidebar_store_spec.js
+80
-0
No files found.
app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.js
View file @
59a85c6b
...
...
@@ -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 @
59a85c6b
...
...
@@ -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 @
59a85c6b
...
...
@@ -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 @
59a85c6b
...
...
@@ -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/helpers/user_mock_data_helper.js
0 → 100644
View file @
59a85c6b
export
default
{
createNumberRandomUsers
(
numberUsers
)
{
const
users
=
[];
for
(
let
i
=
0
;
i
<
numberUsers
;
i
=
i
+=
1
)
{
users
.
push
(
{
avatar
:
'
http://gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon
'
,
id
:
(
i
+
1
),
name
:
`GitLab User
${
i
}
`
,
username
:
`gitlab
${
i
}
`
,
},
);
}
return
users
;
},
};
spec/javascripts/sidebar/assignee_title_spec.js
0 → 100644
View file @
59a85c6b
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 @
59a85c6b
import
Vue
from
'
vue
'
;
import
Assignee
from
'
~/sidebar/components/assignees/assignees
'
;
import
UsersMock
from
'
./mock_data
'
;
import
UsersMockHelper
from
'
../helpers/user_mock_data_helper
'
;
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
.
avatar
);
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
.
avatar
);
// 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
].
avatar
);
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
].
avatar
);
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
].
avatar
);
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 @
59a85c6b
/* 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
:
{
avatar
:
'
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 @
59a85c6b
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 @
59a85c6b
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 @
59a85c6b
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
();
})
.
catch
(()
=>
{});
});
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 @
59a85c6b
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
();
})
.
catch
(()
=>
{});
});
it
(
'
updates the data
'
,
(
done
)
=>
{
this
.
service
.
update
(
'
issue[assignee_ids]
'
,
[
1
])
.
then
((
resp
)
=>
{
expect
(
resp
).
toBeDefined
();
done
();
})
.
catch
(()
=>
{});
});
});
spec/javascripts/sidebar/sidebar_store_spec.js
0 → 100644
View file @
59a85c6b
import
SidebarStore
from
'
~/sidebar/stores/sidebar_store
'
;
import
Mock
from
'
./mock_data
'
;
import
UsersMockHelper
from
'
../helpers/user_mock_data_helper
'
;
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
);
});
});
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