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
a1771826
Commit
a1771826
authored
May 05, 2017
by
Jacob Schatz
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'ee-issue-title-description-realtime' into 'master'
issue-title-description realtime See merge request !1834
parents
0f84d384
f158dd2a
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
350 additions
and
136 deletions
+350
-136
app/assets/javascripts/issue_show/actions/tasks.js
app/assets/javascripts/issue_show/actions/tasks.js
+27
-0
app/assets/javascripts/issue_show/index.js
app/assets/javascripts/issue_show/index.js
+3
-3
app/assets/javascripts/issue_show/issue_title.vue
app/assets/javascripts/issue_show/issue_title.vue
+0
-80
app/assets/javascripts/issue_show/issue_title_description.vue
...assets/javascripts/issue_show/issue_title_description.vue
+180
-0
app/assets/stylesheets/pages/issues.scss
app/assets/stylesheets/pages/issues.scss
+9
-0
app/controllers/projects/issues_controller.rb
app/controllers/projects/issues_controller.rb
+10
-1
app/views/projects/issues/show.html.haml
app/views/projects/issues/show.html.haml
+4
-9
features/project/issues/issues.feature
features/project/issues/issues.feature
+1
-0
spec/features/issues/award_spec.rb
spec/features/issues/award_spec.rb
+6
-0
spec/features/task_lists_spec.rb
spec/features/task_lists_spec.rb
+22
-13
spec/javascripts/issue_show/issue_title_description_spec.js
spec/javascripts/issue_show/issue_title_description_spec.js
+60
-0
spec/javascripts/issue_show/issue_title_spec.js
spec/javascripts/issue_show/issue_title_spec.js
+0
-22
spec/javascripts/issue_show/mock_data.js
spec/javascripts/issue_show/mock_data.js
+26
-0
spec/javascripts/issue_spec.js
spec/javascripts/issue_spec.js
+0
-6
spec/support/features/issuable_slash_commands_shared_examples.rb
...pport/features/issuable_slash_commands_shared_examples.rb
+2
-2
No files found.
app/assets/javascripts/issue_show/actions/tasks.js
0 → 100644
View file @
a1771826
export
default
(
newStateData
,
tasks
)
=>
{
const
$tasks
=
$
(
'
#task_status
'
);
const
$tasksShort
=
$
(
'
#task_status_short
'
);
const
$issueableHeader
=
$
(
'
.issuable-header
'
);
const
tasksStates
=
{
newState
:
null
,
currentState
:
null
};
if
(
$tasks
.
length
===
0
)
{
if
(
!
(
newStateData
.
task_status
.
indexOf
(
'
0 of 0
'
)
===
0
))
{
$issueableHeader
.
append
(
`<span id="task_status">
${
newStateData
.
task_status
}
</span>`
);
}
else
{
$issueableHeader
.
append
(
'
<span id="task_status"></span>
'
);
}
}
else
{
tasksStates
.
newState
=
newStateData
.
task_status
.
indexOf
(
'
0 of 0
'
)
===
0
;
tasksStates
.
currentState
=
tasks
.
indexOf
(
'
0 of 0
'
)
===
0
;
}
if
(
$tasks
.
length
!==
0
&&
!
tasksStates
.
newState
)
{
$tasks
.
text
(
newStateData
.
task_status
);
$tasksShort
.
text
(
newStateData
.
task_status
);
}
else
if
(
tasksStates
.
currentState
)
{
$issueableHeader
.
append
(
`<span id="task_status">
${
newStateData
.
task_status
}
</span>`
);
}
else
if
(
tasksStates
.
newState
)
{
$tasks
.
remove
();
$tasksShort
.
remove
();
}
};
app/assets/javascripts/issue_show/index.js
View file @
a1771826
import
Vue
from
'
vue
'
;
import
IssueTitle
from
'
./issue_title.vue
'
;
import
IssueTitle
from
'
./issue_title
_description
.vue
'
;
import
'
../vue_shared/vue_resource_interceptor
'
;
(()
=>
{
const
issueTitleData
=
document
.
querySelector
(
'
.issue-title-data
'
).
dataset
;
const
{
initialTitle
,
endpoint
}
=
issueTitleData
;
const
{
canUpdateTasksClass
,
endpoint
}
=
issueTitleData
;
const
vm
=
new
Vue
({
el
:
'
.issue-title-entrypoint
'
,
render
:
createElement
=>
createElement
(
IssueTitle
,
{
props
:
{
initialTitle
,
canUpdateTasksClass
,
endpoint
,
},
}),
...
...
app/assets/javascripts/issue_show/issue_title.vue
deleted
100644 → 0
View file @
0f84d384
<
script
>
import
Visibility
from
'
visibilityjs
'
;
import
Poll
from
'
./../lib/utils/poll
'
;
import
Service
from
'
./services/index
'
;
export
default
{
props
:
{
initialTitle
:
{
required
:
true
,
type
:
String
},
endpoint
:
{
required
:
true
,
type
:
String
},
},
data
()
{
const
resource
=
new
Service
(
this
.
$http
,
this
.
endpoint
);
const
poll
=
new
Poll
({
resource
,
method
:
'
getTitle
'
,
successCallback
:
(
res
)
=>
{
this
.
renderResponse
(
res
);
},
errorCallback
:
(
err
)
=>
{
if
(
process
.
env
.
NODE_ENV
!==
'
production
'
)
{
// eslint-disable-next-line no-console
console
.
error
(
'
ISSUE SHOW TITLE REALTIME ERROR
'
,
err
);
}
else
{
throw
new
Error
(
err
);
}
},
});
return
{
poll
,
timeoutId
:
null
,
title
:
this
.
initialTitle
,
};
},
methods
:
{
renderResponse
(
res
)
{
const
body
=
JSON
.
parse
(
res
.
body
);
this
.
triggerAnimation
(
body
);
},
triggerAnimation
(
body
)
{
const
{
title
}
=
body
;
/**
* since opacity is changed, even if there is no diff for Vue to update
* we must check the title even on a 304 to ensure no visual change
*/
if
(
this
.
title
===
title
)
return
;
this
.
$el
.
style
.
opacity
=
0
;
this
.
timeoutId
=
setTimeout
(()
=>
{
this
.
title
=
title
;
this
.
$el
.
style
.
transition
=
'
opacity 0.2s ease
'
;
this
.
$el
.
style
.
opacity
=
1
;
clearTimeout
(
this
.
timeoutId
);
},
100
);
},
},
created
()
{
if
(
!
Visibility
.
hidden
())
{
this
.
poll
.
makeRequest
();
}
Visibility
.
change
(()
=>
{
if
(
!
Visibility
.
hidden
())
{
this
.
poll
.
restart
();
}
else
{
this
.
poll
.
stop
();
}
});
},
};
</
script
>
<
template
>
<h2
class=
"title"
v-html=
"title"
></h2>
</
template
>
app/assets/javascripts/issue_show/issue_title_description.vue
0 → 100644
View file @
a1771826
<
script
>
import
Visibility
from
'
visibilityjs
'
;
import
Poll
from
'
./../lib/utils/poll
'
;
import
Service
from
'
./services/index
'
;
import
tasks
from
'
./actions/tasks
'
;
export
default
{
props
:
{
endpoint
:
{
required
:
true
,
type
:
String
,
},
canUpdateTasksClass
:
{
required
:
true
,
type
:
String
,
},
},
data
()
{
const
resource
=
new
Service
(
this
.
$http
,
this
.
endpoint
);
const
poll
=
new
Poll
({
resource
,
method
:
'
getTitle
'
,
successCallback
:
(
res
)
=>
{
this
.
renderResponse
(
res
);
},
errorCallback
:
(
err
)
=>
{
throw
new
Error
(
err
);
},
});
return
{
poll
,
apiData
:
{},
tasks
:
'
0 of 0
'
,
title
:
null
,
titleText
:
''
,
titleFlag
:
{
pre
:
true
,
pulse
:
false
,
},
description
:
null
,
descriptionText
:
''
,
descriptionChange
:
false
,
descriptionFlag
:
{
pre
:
true
,
pulse
:
false
,
},
timeAgoEl
:
$
(
'
.issue_edited_ago
'
),
titleEl
:
document
.
querySelector
(
'
title
'
),
};
},
methods
:
{
updateFlag
(
key
,
toggle
)
{
this
[
key
].
pre
=
toggle
;
this
[
key
].
pulse
=
!
toggle
;
},
renderResponse
(
res
)
{
this
.
apiData
=
res
.
json
();
this
.
triggerAnimation
();
},
updateTaskHTML
()
{
tasks
(
this
.
apiData
,
this
.
tasks
);
},
elementsToVisualize
(
noTitleChange
,
noDescriptionChange
)
{
if
(
!
noTitleChange
)
{
this
.
titleText
=
this
.
apiData
.
title_text
;
this
.
updateFlag
(
'
titleFlag
'
,
true
);
}
if
(
!
noDescriptionChange
)
{
// only change to true when we need to bind TaskLists the html of description
this
.
descriptionChange
=
true
;
this
.
updateTaskHTML
();
this
.
tasks
=
this
.
apiData
.
task_status
;
this
.
updateFlag
(
'
descriptionFlag
'
,
true
);
}
},
setTabTitle
()
{
const
currentTabTitleScope
=
this
.
titleEl
.
innerText
.
split
(
'
·
'
);
currentTabTitleScope
[
0
]
=
`
${
this
.
titleText
}
(#
${
this
.
apiData
.
issue_number
}
) `
;
this
.
titleEl
.
innerText
=
currentTabTitleScope
.
join
(
'
·
'
);
},
animate
(
title
,
description
)
{
this
.
title
=
title
;
this
.
description
=
description
;
this
.
setTabTitle
();
this
.
$nextTick
(()
=>
{
this
.
updateFlag
(
'
titleFlag
'
,
false
);
this
.
updateFlag
(
'
descriptionFlag
'
,
false
);
});
},
triggerAnimation
()
{
// always reset to false before checking the change
this
.
descriptionChange
=
false
;
const
{
title
,
description
}
=
this
.
apiData
;
this
.
descriptionText
=
this
.
apiData
.
description_text
;
const
noTitleChange
=
this
.
title
===
title
;
const
noDescriptionChange
=
this
.
description
===
description
;
/**
* since opacity is changed, even if there is no diff for Vue to update
* we must check the title/description even on a 304 to ensure no visual change
*/
if
(
noTitleChange
&&
noDescriptionChange
)
return
;
this
.
elementsToVisualize
(
noTitleChange
,
noDescriptionChange
);
this
.
animate
(
title
,
description
);
},
updateEditedTimeAgo
()
{
const
toolTipTime
=
gl
.
utils
.
formatDate
(
this
.
apiData
.
updated_at
);
this
.
timeAgoEl
.
attr
(
'
datetime
'
,
this
.
apiData
.
updated_at
);
this
.
timeAgoEl
.
attr
(
'
title
'
,
toolTipTime
).
tooltip
(
'
fixTitle
'
);
},
},
created
()
{
if
(
!
Visibility
.
hidden
())
{
this
.
poll
.
makeRequest
();
}
Visibility
.
change
(()
=>
{
if
(
!
Visibility
.
hidden
())
{
this
.
poll
.
restart
();
}
else
{
this
.
poll
.
stop
();
}
});
},
updated
()
{
// if new html is injected (description changed) - bind TaskList and call renderGFM
if
(
this
.
descriptionChange
)
{
this
.
updateEditedTimeAgo
();
$
(
this
.
$refs
[
'
issue-content-container-gfm-entry
'
]).
renderGFM
();
const
tl
=
new
gl
.
TaskList
({
dataType
:
'
issue
'
,
fieldName
:
'
description
'
,
selector
:
'
.detail-page-description
'
,
});
return
tl
&&
null
;
}
return
null
;
},
};
</
script
>
<
template
>
<div>
<h2
class=
"title"
:class=
"
{ 'issue-realtime-pre-pulse': titleFlag.pre, 'issue-realtime-trigger-pulse': titleFlag.pulse }"
ref="issue-title"
v-html="title"
>
</h2>
<div
class=
"description is-task-list-enabled"
:class=
"canUpdateTasksClass"
v-if=
"description"
>
<div
class=
"wiki"
:class=
"
{ 'issue-realtime-pre-pulse': descriptionFlag.pre, 'issue-realtime-trigger-pulse': descriptionFlag.pulse }"
v-html="description"
ref="issue-content-container-gfm-entry"
>
</div>
<textarea
class=
"hidden js-task-list-field"
v-if=
"descriptionText"
>
{{
descriptionText
}}
</textarea>
</div>
</div>
</
template
>
app/assets/stylesheets/pages/issues.scss
View file @
a1771826
...
...
@@ -18,6 +18,15 @@
}
}
.issue-realtime-pre-pulse
{
opacity
:
0
;
}
.issue-realtime-trigger-pulse
{
transition
:
opacity
$fade-in-duration
linear
;
opacity
:
1
;
}
.check-all-holder
{
line-height
:
36px
;
float
:
left
;
...
...
app/controllers/projects/issues_controller.rb
View file @
a1771826
...
...
@@ -209,7 +209,16 @@ class Projects::IssuesController < Projects::ApplicationController
def
rendered_title
Gitlab
::
PollingInterval
.
set_header
(
response
,
interval:
3_000
)
render
json:
{
title:
view_context
.
markdown_field
(
@issue
,
:title
)
}
render
json:
{
title:
view_context
.
markdown_field
(
@issue
,
:title
),
title_text:
@issue
.
title
,
description:
view_context
.
markdown_field
(
@issue
,
:description
),
description_text:
@issue
.
description
,
task_status:
@issue
.
task_status
,
issue_number:
@issue
.
iid
,
updated_at:
@issue
.
updated_at
,
}
end
def
create_merge_request
...
...
app/views/projects/issues/show.html.haml
View file @
a1771826
...
...
@@ -50,17 +50,12 @@
=
link_to
'Edit'
,
edit_namespace_project_issue_path
(
@project
.
namespace
,
@project
,
@issue
),
class:
'hidden-xs hidden-sm btn btn-grouped issuable-edit'
.issue-details.issuable-details
.detail-page-description.content-block
.issue-title-data.hidden
{
"data"
=>
{
"
initial-title"
=>
markdown_field
(
@issue
,
:titl
e
),
"
endpoint"
=>
rendered_title_namespace_project_issue_path
(
@project
.
namespace
,
@project
,
@issue
)
,
.detail-page-description.content-block
{
class:
(
'hide-bottom-border'
unless
@issue
.
description
.
present?
)
}
.issue-title-data.hidden
{
"data"
=>
{
"
endpoint"
=>
rendered_title_namespace_project_issue_path
(
@project
.
namespace
,
@project
,
@issu
e
),
"
can-update-tasks-class"
=>
can?
(
current_user
,
:update_issue
,
@issue
)
?
'js-task-list-container'
:
''
,
}
}
.issue-title-entrypoint
-
if
@issue
.
description
.
present?
.description
{
class:
can?
(
current_user
,
:update_issue
,
@issue
)
?
'js-task-list-container'
:
''
}
.wiki
=
markdown_field
(
@issue
,
:description
)
%textarea
.hidden.js-task-list-field
=
@issue
.
description
=
edited_time_ago_with_tooltip
(
@issue
,
placement:
'bottom'
,
html_class:
'issue_edited_ago'
)
#merge-requests
{
data:
{
url:
referenced_merge_requests_namespace_project_issue_url
(
@project
.
namespace
,
@project
,
@issue
)
}
}
...
...
features/project/issues/issues.feature
View file @
a1771826
...
...
@@ -82,6 +82,7 @@ Feature: Project Issues
# Markdown
@javascript
Scenario
:
Headers inside the description should have ids generated for them.
Given
I visit issue page
"Release 0.4"
Then
Header
"Description header"
should have correct id and link
...
...
spec/features/issues/award_spec.rb
View file @
a1771826
...
...
@@ -6,9 +6,12 @@ feature 'Issue awards', js: true, feature: true do
let
(
:issue
)
{
create
(
:issue
,
project:
project
)
}
describe
'logged in'
do
include
WaitForVueResource
before
do
login_as
(
user
)
visit
namespace_project_issue_path
(
project
.
namespace
,
project
,
issue
)
wait_for_vue_resource
end
it
'adds award to issue'
do
...
...
@@ -38,8 +41,11 @@ feature 'Issue awards', js: true, feature: true do
end
describe
'logged out'
do
include
WaitForVueResource
before
do
visit
namespace_project_issue_path
(
project
.
namespace
,
project
,
issue
)
wait_for_vue_resource
end
it
'does not see award menu button'
do
...
...
spec/features/task_lists_spec.rb
View file @
a1771826
...
...
@@ -62,12 +62,15 @@ feature 'Task Lists', feature: true do
visit
namespace_project_issue_path
(
project
.
namespace
,
project
,
issue
)
end
describe
'for Issues'
do
describe
'multiple tasks'
do
describe
'for Issues'
,
feature:
true
do
describe
'multiple tasks'
,
js:
true
do
include
WaitForVueResource
let!
(
:issue
)
{
create
(
:issue
,
description:
markdown
,
author:
user
,
project:
project
)
}
it
'renders'
do
visit_issue
(
project
,
issue
)
wait_for_vue_resource
expect
(
page
).
to
have_selector
(
'ul.task-list'
,
count:
1
)
expect
(
page
).
to
have_selector
(
'li.task-list-item'
,
count:
6
)
...
...
@@ -76,25 +79,24 @@ feature 'Task Lists', feature: true do
it
'contains the required selectors'
do
visit_issue
(
project
,
issue
)
wait_for_vue_resource
container
=
'.detail-page-description .description.js-task-list-container'
expect
(
page
).
to
have_selector
(
container
)
expect
(
page
).
to
have_selector
(
"
#{
container
}
.wiki .task-list .task-list-item .task-list-item-checkbox"
)
expect
(
page
).
to
have_selector
(
"
#{
container
}
.js-task-list-field"
)
expect
(
page
).
to
have_selector
(
'form.js-issuable-update'
)
expect
(
page
).
to
have_selector
(
".wiki .task-list .task-list-item .task-list-item-checkbox"
)
expect
(
page
).
to
have_selector
(
'a.btn-close'
)
end
it
'is only editable by author'
do
visit_issue
(
project
,
issue
)
expect
(
page
).
to
have_selector
(
'.js-task-list-container'
)
wait_for_vue_resource
logout
(
:user
)
expect
(
page
).
to
have_selector
(
".wiki .task-list .task-list-item .task-list-item-checkbox"
)
logout
(
:user
)
login_as
(
user2
)
visit
current_path
expect
(
page
).
not_to
have_selector
(
'.js-task-list-container'
)
wait_for_vue_resource
expect
(
page
).
to
have_selector
(
".wiki .task-list .task-list-item .task-list-item-checkbox"
)
end
it
'provides a summary on Issues#index'
do
...
...
@@ -103,11 +105,14 @@ feature 'Task Lists', feature: true do
end
end
describe
'single incomplete task'
do
describe
'single incomplete task'
,
js:
true
do
include
WaitForVueResource
let!
(
:issue
)
{
create
(
:issue
,
description:
singleIncompleteMarkdown
,
author:
user
,
project:
project
)
}
it
'renders'
do
visit_issue
(
project
,
issue
)
wait_for_vue_resource
expect
(
page
).
to
have_selector
(
'ul.task-list'
,
count:
1
)
expect
(
page
).
to
have_selector
(
'li.task-list-item'
,
count:
1
)
...
...
@@ -116,15 +121,18 @@ feature 'Task Lists', feature: true do
it
'provides a summary on Issues#index'
do
visit
namespace_project_issues_path
(
project
.
namespace
,
project
)
expect
(
page
).
to
have_content
(
"0 of 1 task completed"
)
end
end
describe
'single complete task'
do
describe
'single complete task'
,
js:
true
do
include
WaitForVueResource
let!
(
:issue
)
{
create
(
:issue
,
description:
singleCompleteMarkdown
,
author:
user
,
project:
project
)
}
it
'renders'
do
visit_issue
(
project
,
issue
)
wait_for_vue_resource
expect
(
page
).
to
have_selector
(
'ul.task-list'
,
count:
1
)
expect
(
page
).
to
have_selector
(
'li.task-list-item'
,
count:
1
)
...
...
@@ -133,6 +141,7 @@ feature 'Task Lists', feature: true do
it
'provides a summary on Issues#index'
do
visit
namespace_project_issues_path
(
project
.
namespace
,
project
)
expect
(
page
).
to
have_content
(
"1 of 1 task completed"
)
end
end
...
...
spec/javascripts/issue_show/issue_title_description_spec.js
0 → 100644
View file @
a1771826
import
Vue
from
'
vue
'
;
import
$
from
'
jquery
'
;
import
'
~/render_math
'
;
import
'
~/render_gfm
'
;
import
issueTitleDescription
from
'
~/issue_show/issue_title_description.vue
'
;
import
issueShowData
from
'
./mock_data
'
;
window
.
$
=
$
;
const
issueShowInterceptor
=
data
=>
(
request
,
next
)
=>
{
next
(
request
.
respondWith
(
JSON
.
stringify
(
data
),
{
status
:
200
,
headers
:
{
'
POLL-INTERVAL
'
:
1
,
},
}));
};
describe
(
'
Issue Title
'
,
()
=>
{
document
.
body
.
innerHTML
=
'
<span id="task_status"></span>
'
;
let
IssueTitleDescriptionComponent
;
beforeEach
(()
=>
{
IssueTitleDescriptionComponent
=
Vue
.
extend
(
issueTitleDescription
);
});
afterEach
(()
=>
{
Vue
.
http
.
interceptors
=
_
.
without
(
Vue
.
http
.
interceptors
,
issueShowInterceptor
);
});
it
(
'
should render a title/description and update title/description on update
'
,
(
done
)
=>
{
Vue
.
http
.
interceptors
.
push
(
issueShowInterceptor
(
issueShowData
.
initialRequest
));
const
issueShowComponent
=
new
IssueTitleDescriptionComponent
({
propsData
:
{
canUpdateIssue
:
'
.css-stuff
'
,
endpoint
:
'
/gitlab-org/gitlab-shell/issues/9/rendered_title
'
,
},
}).
$mount
();
setTimeout
(()
=>
{
expect
(
document
.
querySelector
(
'
title
'
).
innerText
).
toContain
(
'
this is a title (#1)
'
);
expect
(
issueShowComponent
.
$el
.
querySelector
(
'
.title
'
).
innerHTML
).
toContain
(
'
<p>this is a title</p>
'
);
expect
(
issueShowComponent
.
$el
.
querySelector
(
'
.wiki
'
).
innerHTML
).
toContain
(
'
<p>this is a description!</p>
'
);
expect
(
issueShowComponent
.
$el
.
querySelector
(
'
.js-task-list-field
'
).
innerText
).
toContain
(
'
this is a description
'
);
Vue
.
http
.
interceptors
.
push
(
issueShowInterceptor
(
issueShowData
.
secondRequest
));
setTimeout
(()
=>
{
expect
(
document
.
querySelector
(
'
title
'
).
innerText
).
toContain
(
'
2 (#1)
'
);
expect
(
issueShowComponent
.
$el
.
querySelector
(
'
.title
'
).
innerHTML
).
toContain
(
'
<p>2</p>
'
);
expect
(
issueShowComponent
.
$el
.
querySelector
(
'
.wiki
'
).
innerHTML
).
toContain
(
'
<p>42</p>
'
);
expect
(
issueShowComponent
.
$el
.
querySelector
(
'
.js-task-list-field
'
).
innerText
).
toContain
(
'
42
'
);
done
();
});
});
});
});
spec/javascripts/issue_show/issue_title_spec.js
deleted
100644 → 0
View file @
0f84d384
import
Vue
from
'
vue
'
;
import
issueTitle
from
'
~/issue_show/issue_title.vue
'
;
describe
(
'
Issue Title
'
,
()
=>
{
let
IssueTitleComponent
;
beforeEach
(()
=>
{
IssueTitleComponent
=
Vue
.
extend
(
issueTitle
);
});
it
(
'
should render a title
'
,
()
=>
{
const
component
=
new
IssueTitleComponent
({
propsData
:
{
initialTitle
:
'
wow
'
,
endpoint
:
'
/gitlab-org/gitlab-shell/issues/9/rendered_title
'
,
},
}).
$mount
();
expect
(
component
.
$el
.
classList
).
toContain
(
'
title
'
);
expect
(
component
.
$el
.
innerHTML
).
toContain
(
'
wow
'
);
});
});
spec/javascripts/issue_show/mock_data.js
0 → 100644
View file @
a1771826
export
default
{
initialRequest
:
{
title
:
'
<p>this is a title</p>
'
,
title_text
:
'
this is a title
'
,
description
:
'
<p>this is a description!</p>
'
,
description_text
:
'
this is a description
'
,
issue_number
:
1
,
task_status
:
'
2 of 4 completed
'
,
},
secondRequest
:
{
title
:
'
<p>2</p>
'
,
title_text
:
'
2
'
,
description
:
'
<p>42</p>
'
,
description_text
:
'
42
'
,
issue_number
:
1
,
task_status
:
'
0 of 0 completed
'
,
},
issueSpecRequest
:
{
title
:
'
<p>this is a title</p>
'
,
title_text
:
'
this is a title
'
,
description
:
'
<li class="task-list-item enabled"><input type="checkbox" class="task-list-item-checkbox">Task List Item</li>
'
,
description_text
:
'
- [ ] Task List Item
'
,
issue_number
:
1
,
task_status
:
'
0 of 1 completed
'
,
},
};
spec/javascripts/issue_spec.js
View file @
a1771826
...
...
@@ -81,12 +81,6 @@ describe('Issue', function() {
this
.
issue
=
new
Issue
();
});
it
(
'
modifies the Markdown field
'
,
function
()
{
spyOn
(
jQuery
,
'
ajax
'
).
and
.
stub
();
$
(
'
input[type=checkbox]
'
).
attr
(
'
checked
'
,
true
).
trigger
(
'
change
'
);
expect
(
$
(
'
.js-task-list-field
'
).
val
()).
toBe
(
'
- [x] Task List Item
'
);
});
it
(
'
submits an ajax request on tasklist:changed
'
,
function
()
{
spyOn
(
jQuery
,
'
ajax
'
).
and
.
callFake
(
function
(
req
)
{
expect
(
req
.
type
).
toBe
(
'
PATCH
'
);
...
...
spec/support/features/issuable_slash_commands_shared_examples.rb
View file @
a1771826
...
...
@@ -25,7 +25,7 @@ shared_examples 'issuable record that supports slash commands in its description
wait_for_ajax
end
describe
"new
#{
issuable_type
}
"
do
describe
"new
#{
issuable_type
}
"
,
js:
true
do
context
'with commands in the description'
do
it
"creates the
#{
issuable_type
}
and interpret commands accordingly"
do
visit
public_send
(
"new_namespace_project_
#{
issuable_type
}
_path"
,
project
.
namespace
,
project
,
new_url_opts
)
...
...
@@ -44,7 +44,7 @@ shared_examples 'issuable record that supports slash commands in its description
end
end
describe
"note on
#{
issuable_type
}
"
do
describe
"note on
#{
issuable_type
}
"
,
js:
true
do
before
do
visit
public_send
(
"namespace_project_
#{
issuable_type
}
_path"
,
project
.
namespace
,
project
,
issuable
)
end
...
...
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