Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
李少辉-开发者
gitlab-foss
提交
15acb6c5
G
gitlab-foss
项目概览
李少辉-开发者
/
gitlab-foss
通知
15
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
gitlab-foss
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
15acb6c5
编写于
5月 05, 2017
作者:
F
Filipa Lacerda
浏览文件
操作
浏览文件
下载
差异文件
Merge branch '27614-instant-comments' into 'master'
Add instant comments support Closes #27614 See merge request !10760
上级
a5347fe5
645593e5
变更
16
展开全部
隐藏空白更改
内联
并排
Showing
16 changed file
with
607 addition
and
65 deletion
+607
-65
app/assets/javascripts/behaviors/quick_submit.js
app/assets/javascripts/behaviors/quick_submit.js
+1
-1
app/assets/javascripts/lib/utils/common_utils.js
app/assets/javascripts/lib/utils/common_utils.js
+8
-0
app/assets/javascripts/notes.js
app/assets/javascripts/notes.js
+287
-58
app/assets/stylesheets/framework/animations.scss
app/assets/stylesheets/framework/animations.scss
+28
-0
app/assets/stylesheets/pages/notes.scss
app/assets/stylesheets/pages/notes.scss
+23
-0
app/views/discussions/_notes.html.haml
app/views/discussions/_notes.html.haml
+1
-0
app/views/projects/notes/_edit_form.html.haml
app/views/projects/notes/_edit_form.html.haml
+1
-1
changelogs/unreleased/27614-instant-comments.yml
changelogs/unreleased/27614-instant-comments.yml
+4
-0
features/steps/project/merge_requests.rb
features/steps/project/merge_requests.rb
+7
-0
features/steps/shared/note.rb
features/steps/shared/note.rb
+4
-0
spec/features/merge_requests/user_posts_notes_spec.rb
spec/features/merge_requests/user_posts_notes_spec.rb
+1
-0
spec/features/merge_requests/user_uses_slash_commands_spec.rb
.../features/merge_requests/user_uses_slash_commands_spec.rb
+1
-0
spec/javascripts/lib/utils/common_utils_spec.js
spec/javascripts/lib/utils/common_utils_spec.js
+11
-0
spec/javascripts/notes_spec.js
spec/javascripts/notes_spec.js
+224
-5
spec/support/features/issuable_slash_commands_shared_examples.rb
...pport/features/issuable_slash_commands_shared_examples.rb
+1
-0
spec/support/time_tracking_shared_examples.rb
spec/support/time_tracking_shared_examples.rb
+5
-0
未找到文件。
app/assets/javascripts/behaviors/quick_submit.js
浏览文件 @
15acb6c5
...
...
@@ -43,8 +43,8 @@ $(document).on('keydown.quick_submit', '.js-quick-submit', (e) => {
const
$submitButton
=
$form
.
find
(
'
input[type=submit], button[type=submit]
'
);
if
(
!
$submitButton
.
attr
(
'
disabled
'
))
{
$submitButton
.
trigger
(
'
click
'
,
[
e
]);
$submitButton
.
disable
();
$form
.
submit
();
}
});
...
...
app/assets/javascripts/lib/utils/common_utils.js
浏览文件 @
15acb6c5
...
...
@@ -35,6 +35,14 @@
});
};
w
.
gl
.
utils
.
ajaxPost
=
function
(
url
,
data
)
{
return
$
.
ajax
({
type
:
'
POST
'
,
url
:
url
,
data
:
data
,
});
};
w
.
gl
.
utils
.
extractLast
=
function
(
term
)
{
return
this
.
split
(
term
).
pop
();
};
...
...
app/assets/javascripts/notes.js
浏览文件 @
15acb6c5
此差异已折叠。
点击以展开。
app/assets/stylesheets/framework/animations.scss
浏览文件 @
15acb6c5
...
...
@@ -159,3 +159,31 @@ a {
.fade-in
{
animation
:
fadeIn
$fade-in-duration
1
;
}
@keyframes
fadeInHalf
{
0
%
{
opacity
:
0
;
}
100
%
{
opacity
:
0
.5
;
}
}
.fade-in-half
{
animation
:
fadeInHalf
$fade-in-duration
1
;
}
@keyframes
fadeInFull
{
0
%
{
opacity
:
0
.5
;
}
100
%
{
opacity
:
1
;
}
}
.fade-in-full
{
animation
:
fadeInFull
$fade-in-duration
1
;
}
app/assets/stylesheets/pages/notes.scss
浏览文件 @
15acb6c5
...
...
@@ -57,6 +57,25 @@ ul.notes {
position
:
relative
;
border-bottom
:
1px
solid
$white-normal
;
&
.being-posted
{
pointer-events
:
none
;
opacity
:
0
.5
;
.dummy-avatar
{
display
:
inline-block
;
height
:
40px
;
width
:
40px
;
border-radius
:
50%
;
background-color
:
$kdb-border
;
border
:
1px
solid
darken
(
$kdb-border
,
25%
);
}
.note-headline-light
,
.fa-spinner
{
margin-left
:
3px
;
}
}
&
.note-discussion
{
&
.timeline-entry
{
padding
:
14px
10px
;
...
...
@@ -687,6 +706,10 @@ ul.notes {
}
}
.discussion-notes
.flash-container
{
margin-bottom
:
0
;
}
// Merge request notes in diffs
.diff-file
{
// Diff is side by side
...
...
app/views/discussions/_notes.html.haml
浏览文件 @
15acb6c5
.discussion-notes
%ul
.notes
{
data:
{
discussion_id:
discussion
.
id
}
}
=
render
partial:
"shared/notes/note"
,
collection:
discussion
.
notes
,
as: :note
.flash-container
-
if
current_user
.discussion-reply-holder
...
...
app/views/projects/notes/_edit_form.html.haml
浏览文件 @
15acb6c5
...
...
@@ -9,6 +9,6 @@
.note-form-actions.clearfix
.settings-message.note-edit-warning.js-finish-edit-warning
Finish editing this message first!
=
submit_tag
'Save comment'
,
class:
'btn btn-nr btn-save js-comment-button'
=
submit_tag
'Save comment'
,
class:
'btn btn-nr btn-save js-comment-
save-
button'
%button
.btn.btn-nr.btn-cancel.note-edit-cancel
{
type:
'button'
}
Cancel
changelogs/unreleased/27614-instant-comments.yml
0 → 100644
浏览文件 @
15acb6c5
---
title
:
Add support for instantly updating comments
merge_request
:
10760
author
:
features/steps/project/merge_requests.rb
浏览文件 @
15acb6c5
...
...
@@ -458,6 +458,8 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
click_button
"Comment"
end
wait_for_ajax
page
.
within
".files>div:nth-child(2) .note-body > .note-text"
do
expect
(
page
).
to
have_content
"Line is correct"
end
...
...
@@ -470,6 +472,8 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
fill_in
"note_note"
,
with:
"Line is wrong on here"
click_button
"Comment"
end
wait_for_ajax
end
step
'I should still see a comment like "Line is correct" in the second file'
do
...
...
@@ -574,6 +578,9 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
fill_in
"note_note"
,
with:
message
click_button
"Comment"
end
wait_for_ajax
page
.
within
(
".notes_holder"
,
visible:
true
)
do
expect
(
page
).
to
have_content
message
end
...
...
features/steps/shared/note.rb
浏览文件 @
15acb6c5
...
...
@@ -24,6 +24,8 @@ module SharedNote
fill_in
"note[note]"
,
with:
"XML attached"
click_button
"Comment"
end
wait_for_ajax
end
step
'I preview a comment text like "Bug fixed :smile:"'
do
...
...
@@ -37,6 +39,8 @@ module SharedNote
page
.
within
(
".js-main-target-form"
)
do
click_button
"Comment"
end
wait_for_ajax
end
step
'I write a comment like ":+1: Nice"'
do
...
...
spec/features/merge_requests/user_posts_notes_spec.rb
浏览文件 @
15acb6c5
...
...
@@ -98,6 +98,7 @@ describe 'Merge requests > User posts notes', :js do
find
(
'.btn-save'
).
click
end
wait_for_ajax
find
(
'.note'
).
hover
find
(
'.js-note-edit'
).
click
...
...
spec/features/merge_requests/user_uses_slash_commands_spec.rb
浏览文件 @
15acb6c5
...
...
@@ -160,6 +160,7 @@ feature 'Merge Requests > User uses slash commands', feature: true, js: true do
it
'changes target branch from a note'
do
write_note
(
"message start
\n
/target_branch merge-test
\n
message end."
)
wait_for_ajax
expect
(
page
).
not_to
have_content
(
'/target_branch'
)
expect
(
page
).
to
have_content
(
'message start'
)
expect
(
page
).
to
have_content
(
'message end.'
)
...
...
spec/javascripts/lib/utils/common_utils_spec.js
浏览文件 @
15acb6c5
...
...
@@ -362,5 +362,16 @@ require('~/lib/utils/common_utils');
gl
.
utils
.
setCiStatusFavicon
(
BUILD_URL
);
});
});
describe
(
'
gl.utils.ajaxPost
'
,
()
=>
{
it
(
'
should perform `$.ajax` call and do `POST` request
'
,
()
=>
{
const
requestURL
=
'
/some/random/api
'
;
const
data
=
{
keyname
:
'
value
'
};
const
ajaxSpy
=
spyOn
(
$
,
'
ajax
'
).
and
.
callFake
(()
=>
{});
gl
.
utils
.
ajaxPost
(
requestURL
,
data
);
expect
(
ajaxSpy
.
calls
.
allArgs
()[
0
][
0
].
type
).
toEqual
(
'
POST
'
);
});
});
});
})();
spec/javascripts/notes_spec.js
浏览文件 @
15acb6c5
...
...
@@ -26,7 +26,7 @@ import '~/notes';
describe
(
'
task lists
'
,
function
()
{
beforeEach
(
function
()
{
$
(
'
form
'
).
on
(
'
submit
'
,
function
(
e
)
{
$
(
'
.js-comment-button
'
).
on
(
'
click
'
,
function
(
e
)
{
e
.
preventDefault
();
});
this
.
notes
=
new
Notes
();
...
...
@@ -60,9 +60,12 @@ import '~/notes';
reset
:
function
()
{}
});
$
(
'
form
'
).
on
(
'
submit
'
,
function
(
e
)
{
$
(
'
.js-comment-button
'
).
on
(
'
click
'
,
(
e
)
=>
{
const
$form
=
$
(
this
);
e
.
preventDefault
();
$
(
'
.js-main-target-form
'
).
trigger
(
'
ajax:success
'
);
this
.
notes
.
addNote
(
$form
);
this
.
notes
.
reenableTargetFormSubmitButton
(
e
);
this
.
notes
.
resetMainTargetForm
(
e
);
});
});
...
...
@@ -238,8 +241,8 @@ import '~/notes';
$resultantNote
=
Notes
.
animateAppendNote
(
noteHTML
,
$notesList
);
});
it
(
'
should have `fade-in` class
'
,
()
=>
{
expect
(
$resultantNote
.
hasClass
(
'
fade-in
'
)).
toEqual
(
true
);
it
(
'
should have `fade-in
-full
` class
'
,
()
=>
{
expect
(
$resultantNote
.
hasClass
(
'
fade-in
-full
'
)).
toEqual
(
true
);
});
it
(
'
should append note to the notes list
'
,
()
=>
{
...
...
@@ -269,5 +272,221 @@ import '~/notes';
expect
(
$note
.
replaceWith
).
toHaveBeenCalledWith
(
$updatedNote
);
});
});
describe
(
'
getFormData
'
,
()
=>
{
it
(
'
should return form metadata object from form reference
'
,
()
=>
{
this
.
notes
=
new
Notes
();
const
$form
=
$
(
'
form
'
);
const
sampleComment
=
'
foobar
'
;
$form
.
find
(
'
textarea.js-note-text
'
).
val
(
sampleComment
);
const
{
formData
,
formContent
,
formAction
}
=
this
.
notes
.
getFormData
(
$form
);
expect
(
formData
.
indexOf
(
sampleComment
)
>
-
1
).
toBe
(
true
);
expect
(
formContent
).
toEqual
(
sampleComment
);
expect
(
formAction
).
toEqual
(
$form
.
attr
(
'
action
'
));
});
});
describe
(
'
hasSlashCommands
'
,
()
=>
{
beforeEach
(()
=>
{
this
.
notes
=
new
Notes
();
});
it
(
'
should return true when comment has slash commands
'
,
()
=>
{
const
sampleComment
=
'
/wip /milestone %1.0 /merge /unassign Merging this
'
;
const
hasSlashCommands
=
this
.
notes
.
hasSlashCommands
(
sampleComment
);
expect
(
hasSlashCommands
).
toBeTruthy
();
});
it
(
'
should return false when comment does NOT have any slash commands
'
,
()
=>
{
const
sampleComment
=
'
Looking good, Awesome!
'
;
const
hasSlashCommands
=
this
.
notes
.
hasSlashCommands
(
sampleComment
);
expect
(
hasSlashCommands
).
toBeFalsy
();
});
});
describe
(
'
stripSlashCommands
'
,
()
=>
{
const
REGEX_SLASH_COMMANDS
=
/
\/\w
+/g
;
it
(
'
should strip slash commands from the comment
'
,
()
=>
{
this
.
notes
=
new
Notes
();
const
sampleComment
=
'
/wip /milestone %1.0 /merge /unassign Merging this
'
;
const
stripedComment
=
this
.
notes
.
stripSlashCommands
(
sampleComment
);
expect
(
REGEX_SLASH_COMMANDS
.
test
(
stripedComment
)).
toBeFalsy
();
});
});
describe
(
'
createPlaceholderNote
'
,
()
=>
{
const
sampleComment
=
'
foobar
'
;
const
uniqueId
=
'
b1234-a4567
'
;
const
currentUsername
=
'
root
'
;
const
currentUserFullname
=
'
Administrator
'
;
beforeEach
(()
=>
{
this
.
notes
=
new
Notes
();
});
it
(
'
should return constructed placeholder element for regular note based on form contents
'
,
()
=>
{
const
$tempNote
=
this
.
notes
.
createPlaceholderNote
({
formContent
:
sampleComment
,
uniqueId
,
isDiscussionNote
:
false
,
currentUsername
,
currentUserFullname
});
const
$tempNoteHeader
=
$tempNote
.
find
(
'
.note-header
'
);
expect
(
$tempNote
.
prop
(
'
nodeName
'
)).
toEqual
(
'
LI
'
);
expect
(
$tempNote
.
attr
(
'
id
'
)).
toEqual
(
uniqueId
);
$tempNote
.
find
(
'
.timeline-icon > a, .note-header-info > a
'
).
each
(
function
()
{
expect
(
$
(
this
).
attr
(
'
href
'
)).
toEqual
(
`/
${
currentUsername
}
`
);
});
expect
(
$tempNote
.
find
(
'
.timeline-content
'
).
hasClass
(
'
discussion
'
)).
toBeFalsy
();
expect
(
$tempNoteHeader
.
find
(
'
.hidden-xs
'
).
text
().
trim
()).
toEqual
(
currentUserFullname
);
expect
(
$tempNoteHeader
.
find
(
'
.note-headline-light
'
).
text
().
trim
()).
toEqual
(
`@
${
currentUsername
}
`
);
expect
(
$tempNote
.
find
(
'
.note-body .note-text
'
).
text
().
trim
()).
toEqual
(
sampleComment
);
});
it
(
'
should return constructed placeholder element for discussion note based on form contents
'
,
()
=>
{
const
$tempNote
=
this
.
notes
.
createPlaceholderNote
({
formContent
:
sampleComment
,
uniqueId
,
isDiscussionNote
:
true
,
currentUsername
,
currentUserFullname
});
expect
(
$tempNote
.
prop
(
'
nodeName
'
)).
toEqual
(
'
LI
'
);
expect
(
$tempNote
.
find
(
'
.timeline-content
'
).
hasClass
(
'
discussion
'
)).
toBeTruthy
();
});
});
describe
(
'
postComment & updateComment
'
,
()
=>
{
const
sampleComment
=
'
foo
'
;
const
updatedComment
=
'
bar
'
;
const
note
=
{
id
:
1234
,
html
:
`<li class="note note-row-1234 timeline-entry" id="note_1234">
<div class="note-text">
${
sampleComment
}
</div>
</li>`
,
note
:
sampleComment
,
valid
:
true
};
let
$form
;
let
$notesContainer
;
beforeEach
(()
=>
{
this
.
notes
=
new
Notes
();
window
.
gon
.
current_username
=
'
root
'
;
window
.
gon
.
current_user_fullname
=
'
Administrator
'
;
$form
=
$
(
'
form
'
);
$notesContainer
=
$
(
'
ul.main-notes-list
'
);
$form
.
find
(
'
textarea.js-note-text
'
).
val
(
sampleComment
);
$
(
'
.js-comment-button
'
).
click
();
});
it
(
'
should show placeholder note while new comment is being posted
'
,
()
=>
{
expect
(
$notesContainer
.
find
(
'
.note.being-posted
'
).
length
>
0
).
toEqual
(
true
);
});
it
(
'
should remove placeholder note when new comment is done posting
'
,
()
=>
{
spyOn
(
$
,
'
ajax
'
).
and
.
callFake
((
options
)
=>
{
options
.
success
(
note
);
expect
(
$notesContainer
.
find
(
'
.note.being-posted
'
).
length
).
toEqual
(
0
);
});
});
it
(
'
should show actual note element when new comment is done posting
'
,
()
=>
{
spyOn
(
$
,
'
ajax
'
).
and
.
callFake
((
options
)
=>
{
options
.
success
(
note
);
expect
(
$notesContainer
.
find
(
`#
${
note
.
id
}
`
).
length
>
0
).
toEqual
(
true
);
});
});
it
(
'
should reset Form when new comment is done posting
'
,
()
=>
{
spyOn
(
$
,
'
ajax
'
).
and
.
callFake
((
options
)
=>
{
options
.
success
(
note
);
expect
(
$form
.
find
(
'
textarea.js-note-text
'
)).
toEqual
(
''
);
});
});
it
(
'
should trigger ajax:success event on Form when new comment is done posting
'
,
()
=>
{
spyOn
(
$
,
'
ajax
'
).
and
.
callFake
((
options
)
=>
{
options
.
success
(
note
);
spyOn
(
$form
,
'
trigger
'
);
expect
(
$form
.
trigger
).
toHaveBeenCalledWith
(
'
ajax:success
'
,
[
note
]);
});
});
it
(
'
should show flash error message when new comment failed to be posted
'
,
()
=>
{
spyOn
(
$
,
'
ajax
'
).
and
.
callFake
((
options
)
=>
{
options
.
error
();
expect
(
$notesContainer
.
parent
().
find
(
'
.flash-container .flash-text
'
).
is
(
'
:visible
'
)).
toEqual
(
true
);
});
});
it
(
'
should refill form textarea with original comment content when new comment failed to be posted
'
,
()
=>
{
spyOn
(
$
,
'
ajax
'
).
and
.
callFake
((
options
)
=>
{
options
.
error
();
expect
(
$form
.
find
(
'
textarea.js-note-text
'
)).
toEqual
(
sampleComment
);
});
});
it
(
'
should show updated comment as _actively being posted_ while comment being updated
'
,
()
=>
{
spyOn
(
$
,
'
ajax
'
).
and
.
callFake
((
options
)
=>
{
options
.
success
(
note
);
const
$noteEl
=
$notesContainer
.
find
(
`#note_
${
note
.
id
}
`
);
$noteEl
.
find
(
'
.js-note-edit
'
).
click
();
$noteEl
.
find
(
'
textarea.js-note-text
'
).
val
(
updatedComment
);
$noteEl
.
find
(
'
.js-comment-save-button
'
).
click
();
expect
(
$noteEl
.
hasClass
(
'
.being-posted
'
)).
toEqual
(
true
);
expect
(
$noteEl
.
find
(
'
.note-text
'
).
text
()).
toEqual
(
updatedComment
);
});
});
it
(
'
should show updated comment when comment update is done posting
'
,
()
=>
{
spyOn
(
$
,
'
ajax
'
).
and
.
callFake
((
options
)
=>
{
options
.
success
(
note
);
const
$noteEl
=
$notesContainer
.
find
(
`#note_
${
note
.
id
}
`
);
$noteEl
.
find
(
'
.js-note-edit
'
).
click
();
$noteEl
.
find
(
'
textarea.js-note-text
'
).
val
(
updatedComment
);
$noteEl
.
find
(
'
.js-comment-save-button
'
).
click
();
spyOn
(
$
,
'
ajax
'
).
and
.
callFake
((
updateOptions
)
=>
{
const
updatedNote
=
Object
.
assign
({},
note
);
updatedNote
.
note
=
updatedComment
;
updatedNote
.
html
=
`<li class="note note-row-1234 timeline-entry" id="note_1234">
<div class="note-text">
${
updatedComment
}
</div>
</li>`
;
updateOptions
.
success
(
updatedNote
);
const
$updatedNoteEl
=
$notesContainer
.
find
(
`#note_
${
updatedNote
.
id
}
`
);
expect
(
$updatedNoteEl
.
hasClass
(
'
.being-posted
'
)).
toEqual
(
false
);
// Remove being-posted visuals
expect
(
$updatedNoteEl
.
find
(
'
note-text
'
).
text
().
trim
()).
toEqual
(
updatedComment
);
// Verify if comment text updated
});
});
});
it
(
'
should show flash error message when comment failed to be updated
'
,
()
=>
{
spyOn
(
$
,
'
ajax
'
).
and
.
callFake
((
options
)
=>
{
options
.
success
(
note
);
const
$noteEl
=
$notesContainer
.
find
(
`#note_
${
note
.
id
}
`
);
$noteEl
.
find
(
'
.js-note-edit
'
).
click
();
$noteEl
.
find
(
'
textarea.js-note-text
'
).
val
(
updatedComment
);
$noteEl
.
find
(
'
.js-comment-save-button
'
).
click
();
spyOn
(
$
,
'
ajax
'
).
and
.
callFake
((
updateOptions
)
=>
{
updateOptions
.
error
();
const
$updatedNoteEl
=
$notesContainer
.
find
(
`#note_
${
note
.
id
}
`
);
expect
(
$updatedNoteEl
.
hasClass
(
'
.being-posted
'
)).
toEqual
(
false
);
// Remove being-posted visuals
expect
(
$updatedNoteEl
.
find
(
'
note-text
'
).
text
().
trim
()).
toEqual
(
sampleComment
);
// See if comment reverted back to original
expect
(
$notesContainer
.
parent
().
find
(
'
.flash-container .flash-text
'
).
is
(
'
:visible
'
)).
toEqual
(
true
);
// Flash error message shown
});
});
});
});
});
}).
call
(
window
);
spec/support/features/issuable_slash_commands_shared_examples.rb
浏览文件 @
15acb6c5
...
...
@@ -58,6 +58,7 @@ shared_examples 'issuable record that supports slash commands in its description
expect
(
page
).
not_to
have_content
'/label ~bug'
expect
(
page
).
not_to
have_content
'/milestone %"ASAP"'
wait_for_ajax
issuable
.
reload
note
=
issuable
.
notes
.
user
.
first
...
...
spec/support/time_tracking_shared_examples.rb
浏览文件 @
15acb6c5
...
...
@@ -8,6 +8,7 @@ shared_examples 'issuable time tracker' do
it
'updates the sidebar component when estimate is added'
do
submit_time
(
'/estimate 3w 1d 1h'
)
wait_for_ajax
page
.
within
'.time-tracking-estimate-only-pane'
do
expect
(
page
).
to
have_content
'3w 1d 1h'
end
...
...
@@ -16,6 +17,7 @@ shared_examples 'issuable time tracker' do
it
'updates the sidebar component when spent is added'
do
submit_time
(
'/spend 3w 1d 1h'
)
wait_for_ajax
page
.
within
'.time-tracking-spend-only-pane'
do
expect
(
page
).
to
have_content
'3w 1d 1h'
end
...
...
@@ -25,6 +27,7 @@ shared_examples 'issuable time tracker' do
submit_time
(
'/estimate 3w 1d 1h'
)
submit_time
(
'/spend 3w 1d 1h'
)
wait_for_ajax
page
.
within
'.time-tracking-comparison-pane'
do
expect
(
page
).
to
have_content
'3w 1d 1h'
end
...
...
@@ -34,6 +37,7 @@ shared_examples 'issuable time tracker' do
submit_time
(
'/estimate 3w 1d 1h'
)
submit_time
(
'/remove_estimate'
)
wait_for_ajax
page
.
within
'#issuable-time-tracker'
do
expect
(
page
).
to
have_content
'No estimate or time spent'
end
...
...
@@ -43,6 +47,7 @@ shared_examples 'issuable time tracker' do
submit_time
(
'/spend 3w 1d 1h'
)
submit_time
(
'/remove_time_spent'
)
wait_for_ajax
page
.
within
'#issuable-time-tracker'
do
expect
(
page
).
to
have_content
'No estimate or time spent'
end
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录