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
f432e9db
Commit
f432e9db
authored
Jan 14, 2021
by
Paul Slaughter
Committed by
Heinrich Lee Yu
Jan 14, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Expose issue_email_participant and create component
parent
d89d8429
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
500 additions
and
113 deletions
+500
-113
app/assets/javascripts/lib/utils/grammar.js
app/assets/javascripts/lib/utils/grammar.js
+3
-3
app/assets/javascripts/notes/components/comment_field_layout.vue
...ets/javascripts/notes/components/comment_field_layout.vue
+69
-0
app/assets/javascripts/notes/components/comment_form.vue
app/assets/javascripts/notes/components/comment_form.vue
+38
-40
app/assets/javascripts/notes/components/email_participants_warning.vue
...vascripts/notes/components/email_participants_warning.vue
+70
-0
app/assets/javascripts/notes/components/note_form.vue
app/assets/javascripts/notes/components/note_form.vue
+40
-42
app/assets/javascripts/notes/mixins/issuable_state.js
app/assets/javascripts/notes/mixins/issuable_state.js
+0
-11
app/assets/stylesheets/pages/note_form.scss
app/assets/stylesheets/pages/note_form.scss
+6
-2
app/serializers/issue_entity.rb
app/serializers/issue_entity.rb
+4
-0
locale/gitlab.pot
locale/gitlab.pot
+9
-0
spec/controllers/projects/issues_controller_spec.rb
spec/controllers/projects/issues_controller_spec.rb
+16
-0
spec/features/projects/issues/email_participants_spec.rb
spec/features/projects/issues/email_participants_spec.rb
+34
-0
spec/frontend/notes/components/comment_field_layout_spec.js
spec/frontend/notes/components/comment_field_layout_spec.js
+137
-0
spec/frontend/notes/components/comment_form_spec.js
spec/frontend/notes/components/comment_form_spec.js
+2
-13
spec/frontend/notes/components/email_participants_warning_spec.js
...ntend/notes/components/email_participants_warning_spec.js
+70
-0
spec/frontend/notes/components/note_form_spec.js
spec/frontend/notes/components/note_form_spec.js
+2
-2
No files found.
app/assets/javascripts/lib/utils/grammar.js
View file @
f432e9db
...
...
@@ -16,12 +16,12 @@ import { sprintf, s__ } from '~/locale';
*
* @param {String[]} items
*/
export
const
toNounSeriesText
=
(
items
)
=>
{
export
const
toNounSeriesText
=
(
items
,
{
onlyCommas
=
false
}
=
{}
)
=>
{
if
(
items
.
length
===
0
)
{
return
''
;
}
else
if
(
items
.
length
===
1
)
{
return
sprintf
(
s__
(
`nounSeries|%{item}`
),
{
item
:
items
[
0
]
},
false
);
}
else
if
(
items
.
length
===
2
)
{
}
else
if
(
items
.
length
===
2
&&
!
onlyCommas
)
{
return
sprintf
(
s__
(
'
nounSeries|%{firstItem} and %{lastItem}
'
),
{
...
...
@@ -33,7 +33,7 @@ export const toNounSeriesText = (items) => {
}
return
items
.
reduce
((
item
,
nextItem
,
idx
)
=>
idx
===
items
.
length
-
1
idx
===
items
.
length
-
1
&&
!
onlyCommas
?
sprintf
(
s__
(
'
nounSeries|%{item}, and %{lastItem}
'
),
{
item
,
lastItem
:
nextItem
},
false
)
:
sprintf
(
s__
(
'
nounSeries|%{item}, %{nextItem}
'
),
{
item
,
nextItem
},
false
),
);
...
...
app/assets/javascripts/notes/components/comment_field_layout.vue
0 → 100644
View file @
f432e9db
<
script
>
import
EmailParticipantsWarning
from
'
./email_participants_warning.vue
'
;
import
NoteableWarning
from
'
~/vue_shared/components/notes/noteable_warning.vue
'
;
const
DEFAULT_NOTEABLE_TYPE
=
'
Issue
'
;
export
default
{
components
:
{
EmailParticipantsWarning
,
NoteableWarning
,
},
props
:
{
noteableData
:
{
type
:
Object
,
required
:
true
,
},
noteableType
:
{
type
:
String
,
required
:
false
,
default
:
DEFAULT_NOTEABLE_TYPE
,
},
withAlertContainer
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
computed
:
{
isLocked
()
{
return
Boolean
(
this
.
noteableData
.
discussion_locked
);
},
isConfidential
()
{
return
Boolean
(
this
.
noteableData
.
confidential
);
},
hasWarning
()
{
return
this
.
isConfidential
||
this
.
isLocked
;
},
emailParticipants
()
{
return
this
.
noteableData
.
issue_email_participants
?.
map
(({
email
})
=>
email
)
||
[];
},
},
};
</
script
>
<
template
>
<div
class=
"comment-warning-wrapper gl-border-solid gl-border-1 gl-rounded-base gl-border-gray-100"
>
<div
v-if=
"withAlertContainer"
class=
"error-alert"
data-testid=
"comment-field-alert-container"
></div>
<noteable-warning
v-if=
"hasWarning"
class=
"gl-border-b-1 gl-border-b-solid gl-border-b-gray-100 gl-rounded-base gl-rounded-bottom-left-none gl-rounded-bottom-right-none"
:is-locked=
"isLocked"
:is-confidential=
"isConfidential"
:noteable-type=
"noteableType"
:locked-noteable-docs-path=
"noteableData.locked_discussion_docs_path"
:confidential-noteable-docs-path=
"noteableData.confidential_issues_docs_path"
/>
<slot></slot>
<email-participants-warning
v-if=
"emailParticipants.length"
class=
"gl-border-t-1 gl-border-t-solid gl-border-t-gray-100 gl-rounded-base gl-rounded-top-left-none! gl-rounded-top-right-none!"
:emails=
"emailParticipants"
/>
</div>
</
template
>
app/assets/javascripts/notes/components/comment_form.vue
View file @
f432e9db
...
...
@@ -17,18 +17,17 @@ import {
import
{
refreshUserMergeRequestCounts
}
from
'
~/commons/nav/user_merge_requests
'
;
import
*
as
constants
from
'
../constants
'
;
import
eventHub
from
'
../event_hub
'
;
import
NoteableWarning
from
'
~/vue_shared/components/notes/noteable_warning.vue
'
;
import
markdownField
from
'
~/vue_shared/components/markdown/field.vue
'
;
import
userAvatarLink
from
'
~/vue_shared/components/user_avatar/user_avatar_link.vue
'
;
import
glFeatureFlagsMixin
from
'
~/vue_shared/mixins/gl_feature_flags_mixin
'
;
import
noteSignedOutWidget
from
'
./note_signed_out_widget.vue
'
;
import
discussionLockedWidget
from
'
./discussion_locked_widget.vue
'
;
import
issuableStateMixin
from
'
../mixins/issuable_state
'
;
import
CommentFieldLayout
from
'
./comment_field_layout.vue
'
;
export
default
{
name
:
'
CommentForm
'
,
components
:
{
NoteableWarning
,
noteSignedOutWidget
,
discussionLockedWidget
,
markdownField
,
...
...
@@ -36,6 +35,7 @@ export default {
GlButton
,
TimelineEntryItem
,
GlIcon
,
CommentFieldLayout
,
},
mixins
:
[
glFeatureFlagsMixin
(),
issuableStateMixin
],
props
:
{
...
...
@@ -287,6 +287,9 @@ export default {
Autosize
.
update
(
this
.
$refs
.
textarea
);
});
},
hasEmailParticipants
()
{
return
this
.
getNoteableData
.
issue_email_participants
?.
length
;
},
},
};
</
script
>
...
...
@@ -309,46 +312,41 @@ export default {
</div>
<div
class=
"timeline-content timeline-content-form"
>
<form
ref=
"commentForm"
class=
"new-note common-note-form gfm-form js-main-target-form"
>
<div
class=
"error-alert"
></div>
<noteable-warning
v-if=
"hasWarning(getNoteableData)"
:is-locked=
"isLocked(getNoteableData)"
:is-confidential=
"isConfidential(getNoteableData)"
<comment-field-layout
:with-alert-container=
"true"
:noteable-data=
"getNoteableData"
:noteable-type=
"noteableType"
:locked-noteable-docs-path=
"lockedIssueDocsPath"
:confidential-noteable-docs-path=
"confidentialIssueDocsPath"
/>
<markdown-field
ref=
"markdownField"
:is-submitting=
"isSubmitting"
:markdown-preview-path=
"markdownPreviewPath"
:markdown-docs-path=
"markdownDocsPath"
:quick-actions-docs-path=
"quickActionsDocsPath"
:add-spacing-classes=
"false"
:textarea-value=
"note"
>
<textarea
id=
"note-body"
ref=
"textarea"
slot=
"textarea"
v-model=
"note"
dir=
"auto"
:disabled=
"isSubmitting"
name=
"note[note]"
class=
"note-textarea js-vue-comment-form js-note-text js-gfm-input js-autosize markdown-area"
data-qa-selector=
"comment_field"
data-testid=
"comment-field"
:data-supports-quick-actions=
"!glFeatures.tributeAutocomplete"
:aria-label=
"__('Description')"
:placeholder=
"__('Write a comment or drag your files here…')"
@
keydown.up=
"editCurrentUserLastNote()"
@
keydown.meta.enter=
"handleSave()"
@
keydown.ctrl.enter=
"handleSave()"
></textarea>
</markdown-field>
<markdown-field
ref=
"markdownField"
:is-submitting=
"isSubmitting"
:markdown-preview-path=
"markdownPreviewPath"
:markdown-docs-path=
"markdownDocsPath"
:quick-actions-docs-path=
"quickActionsDocsPath"
:add-spacing-classes=
"false"
:textarea-value=
"note"
>
<template
#textarea
>
<textarea
id=
"note-body"
ref=
"textarea"
v-model=
"note"
dir=
"auto"
:disabled=
"isSubmitting"
name=
"note[note]"
class=
"note-textarea js-vue-comment-form js-note-text js-gfm-input js-autosize markdown-area"
data-qa-selector=
"comment_field"
data-testid=
"comment-field"
:data-supports-quick-actions=
"!glFeatures.tributeAutocomplete"
:aria-label=
"__('Description')"
:placeholder=
"__('Write a comment or drag your files here…')"
@
keydown.up=
"editCurrentUserLastNote()"
@
keydown.meta.enter=
"handleSave()"
@
keydown.ctrl.enter=
"handleSave()"
></textarea>
</
template
>
</markdown-field>
</comment-field-layout>
<div
class=
"note-form-actions"
>
<div
class=
"btn-group gl-mr-3 comment-type-dropdown js-comment-type-dropdown droplab-dropdown"
...
...
app/assets/javascripts/notes/components/email_participants_warning.vue
0 → 100644
View file @
f432e9db
<
script
>
import
{
GlSprintf
}
from
'
@gitlab/ui
'
;
import
{
s__
,
sprintf
}
from
'
~/locale
'
;
import
{
toNounSeriesText
}
from
'
~/lib/utils/grammar
'
;
export
default
{
components
:
{
GlSprintf
,
},
props
:
{
emails
:
{
type
:
Array
,
required
:
true
,
},
numberOfLessParticipants
:
{
type
:
Number
,
required
:
false
,
default
:
3
,
},
},
data
()
{
return
{
isShowingMoreParticipants
:
false
,
};
},
computed
:
{
title
()
{
return
this
.
moreParticipantsAvailable
?
toNounSeriesText
(
this
.
lessParticipants
,
{
onlyCommas
:
true
})
:
toNounSeriesText
(
this
.
emails
);
},
lessParticipants
()
{
return
this
.
emails
.
slice
(
0
,
this
.
numberOfLessParticipants
);
},
moreLabel
()
{
return
sprintf
(
s__
(
'
EmailParticipantsWarning|and %{moreCount} more
'
),
{
moreCount
:
this
.
emails
.
length
-
this
.
numberOfLessParticipants
,
});
},
moreParticipantsAvailable
()
{
return
!
this
.
isShowingMoreParticipants
&&
this
.
emails
.
length
>
this
.
numberOfLessParticipants
;
},
message
()
{
return
this
.
moreParticipantsAvailable
?
s__
(
'
EmailParticipantsWarning|%{emails}, %{andMore} will be notified of your comment.
'
)
:
s__
(
'
EmailParticipantsWarning|%{emails} will be notified of your comment.
'
);
},
},
methods
:
{
showMoreParticipants
()
{
this
.
isShowingMoreParticipants
=
true
;
},
},
};
</
script
>
<
template
>
<div
class=
"issuable-note-warning"
data-testid=
"email-participants-warning"
>
<gl-sprintf
:message=
"message"
>
<template
#andMore
>
<button
type=
"button"
class=
"btn-transparent btn-link"
@
click=
"showMoreParticipants"
>
{{
moreLabel
}}
</button>
</
template
>
<
template
#emails
>
<span>
{{
title
}}
</span>
</
template
>
</gl-sprintf>
</div>
</template>
app/assets/javascripts/notes/components/note_form.vue
View file @
f432e9db
...
...
@@ -3,19 +3,19 @@
import
{
mapGetters
,
mapActions
,
mapState
}
from
'
vuex
'
;
import
{
mergeUrlParams
}
from
'
~/lib/utils/url_utility
'
;
import
eventHub
from
'
../event_hub
'
;
import
NoteableWarning
from
'
~/vue_shared/components/notes/noteable_warning.vue
'
;
import
markdownField
from
'
~/vue_shared/components/markdown/field.vue
'
;
import
glFeatureFlagsMixin
from
'
~/vue_shared/mixins/gl_feature_flags_mixin
'
;
import
issuableStateMixin
from
'
../mixins/issuable_state
'
;
import
resolvable
from
'
../mixins/resolvable
'
;
import
{
__
,
sprintf
}
from
'
~/locale
'
;
import
{
getDraft
,
updateDraft
}
from
'
~/lib/utils/autosave
'
;
import
CommentFieldLayout
from
'
./comment_field_layout.vue
'
;
export
default
{
name
:
'
NoteForm
'
,
components
:
{
NoteableWarning
,
markdownField
,
CommentFieldLayout
,
},
mixins
:
[
glFeatureFlagsMixin
(),
issuableStateMixin
,
resolvable
],
props
:
{
...
...
@@ -303,6 +303,9 @@ export default {
this
.
$emit
(
'
handleFormUpdateAddToReview
'
,
this
.
updatedNoteBody
,
shouldResolve
);
},
hasEmailParticipants
()
{
return
this
.
getNoteableData
.
issue_email_participants
?.
length
;
},
},
};
</
script
>
...
...
@@ -316,46 +319,41 @@ export default {
></div>
<div
class=
"flash-container timeline-content"
></div>
<form
:data-line-code=
"lineCode"
class=
"edit-note common-note-form js-quick-submit gfm-form"
>
<noteable-warning
v-if=
"hasWarning(getNoteableData)"
:is-locked=
"isLocked(getNoteableData)"
:is-confidential=
"isConfidential(getNoteableData)"
:locked-noteable-docs-path=
"lockedIssueDocsPath"
:confidential-noteable-docs-path=
"confidentialIssueDocsPath"
/>
<markdown-field
:markdown-preview-path=
"markdownPreviewPath"
:markdown-docs-path=
"markdownDocsPath"
:quick-actions-docs-path=
"quickActionsDocsPath"
:line=
"line"
:note=
"discussionNote"
:can-suggest=
"canSuggest"
:add-spacing-classes=
"false"
:help-page-path=
"helpPagePath"
:show-suggest-popover=
"showSuggestPopover"
:textarea-value=
"updatedNoteBody"
@
handleSuggestDismissed=
"() => $emit('handleSuggestDismissed')"
>
<textarea
id=
"note_note"
ref=
"textarea"
slot=
"textarea"
v-model=
"updatedNoteBody"
:data-supports-quick-actions=
"!isEditing && !glFeatures.tributeAutocomplete"
name=
"note[note]"
class=
"note-textarea js-gfm-input js-note-text js-autosize markdown-area js-vue-issue-note-form"
data-qa-selector=
"reply_field"
dir=
"auto"
:aria-label=
"__('Description')"
:placeholder=
"__('Write a comment or drag your files here…')"
@
keydown.meta.enter=
"handleKeySubmit()"
@
keydown.ctrl.enter=
"handleKeySubmit()"
@
keydown.exact.up=
"editMyLastNote()"
@
keydown.exact.esc=
"cancelHandler(true)"
@
input=
"onInput"
></textarea>
</markdown-field>
<comment-field-layout
:noteable-data=
"getNoteableData"
>
<markdown-field
:markdown-preview-path=
"markdownPreviewPath"
:markdown-docs-path=
"markdownDocsPath"
:quick-actions-docs-path=
"quickActionsDocsPath"
:line=
"line"
:note=
"discussionNote"
:can-suggest=
"canSuggest"
:add-spacing-classes=
"false"
:help-page-path=
"helpPagePath"
:show-suggest-popover=
"showSuggestPopover"
:textarea-value=
"updatedNoteBody"
@
handleSuggestDismissed=
"() => $emit('handleSuggestDismissed')"
>
<template
#textarea
>
<textarea
id=
"note_note"
ref=
"textarea"
v-model=
"updatedNoteBody"
:data-supports-quick-actions=
"!isEditing && !glFeatures.tributeAutocomplete"
name=
"note[note]"
class=
"note-textarea js-gfm-input js-note-text js-autosize markdown-area js-vue-issue-note-form"
data-qa-selector=
"reply_field"
dir=
"auto"
:aria-label=
"__('Description')"
:placeholder=
"__('Write a comment or drag your files here…')"
@
keydown.meta.enter=
"handleKeySubmit()"
@
keydown.ctrl.enter=
"handleKeySubmit()"
@
keydown.exact.up=
"editMyLastNote()"
@
keydown.exact.esc=
"cancelHandler(true)"
@
input=
"onInput"
></textarea>
</
template
>
</markdown-field>
</comment-field-layout>
<div
class=
"note-form-actions clearfix"
>
<
template
v-if=
"showBatchCommentsActions"
>
<p
v-if=
"showResolveDiscussionToggle"
>
...
...
app/assets/javascripts/notes/mixins/issuable_state.js
View file @
f432e9db
...
...
@@ -12,21 +12,10 @@ export default {
lockedIssueDocsPath
()
{
return
this
.
getNoteableDataByProp
(
'
locked_discussion_docs_path
'
);
},
confidentialIssueDocsPath
()
{
return
this
.
getNoteableDataByProp
(
'
confidential_issues_docs_path
'
);
},
},
methods
:
{
isConfidential
(
issue
)
{
return
Boolean
(
issue
.
confidential
);
},
isLocked
(
issue
)
{
return
Boolean
(
issue
.
discussion_locked
);
},
hasWarning
(
issue
)
{
return
this
.
isConfidential
(
issue
)
||
this
.
isLocked
(
issue
);
},
},
};
app/assets/stylesheets/pages/note_form.scss
View file @
f432e9db
...
...
@@ -100,8 +100,6 @@
color
:
$orange-600
;
background-color
:
$orange-50
;
border-radius
:
$border-radius-default
$border-radius-default
0
0
;
border
:
1px
solid
$border-gray-normal
;
border-bottom
:
0
;
padding
:
3px
12px
;
margin
:
auto
;
align-items
:
center
;
...
...
@@ -454,3 +452,9 @@ table {
.markdown-selector
{
color
:
$blue-600
;
}
.comment-warning-wrapper
{
.md-area
{
border
:
0
;
}
}
app/serializers/issue_entity.rb
View file @
f432e9db
...
...
@@ -71,6 +71,10 @@ class IssueEntity < IssuableEntity
expose
:archived_project_docs_path
,
if:
->
(
issue
)
{
issue
.
project
.
archived?
}
do
|
issue
|
help_page_path
(
'user/project/settings/index.md'
,
anchor:
'archiving-a-project'
)
end
expose
:issue_email_participants
do
|
issue
|
issue
.
issue_email_participants
.
map
{
|
x
|
{
email:
x
.
email
}
}
end
end
IssueEntity
.
prepend_if_ee
(
'::EE::IssueEntity'
)
locale/gitlab.pot
View file @
f432e9db
...
...
@@ -10617,6 +10617,15 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
msgid "EmailParticipantsWarning|%{emails} will be notified of your comment."
msgstr ""
msgid "EmailParticipantsWarning|%{emails}, %{andMore} will be notified of your comment."
msgstr ""
msgid "EmailParticipantsWarning|and %{moreCount} more"
msgstr ""
msgid "EmailToken|reset it"
msgstr ""
...
...
spec/controllers/projects/issues_controller_spec.rb
View file @
f432e9db
...
...
@@ -227,6 +227,22 @@ RSpec.describe Projects::IssuesController do
end
end
describe
"GET #show"
do
before
do
sign_in
(
user
)
project
.
add_developer
(
user
)
end
it
"returns issue_email_participants"
do
participants
=
create_list
(
:issue_email_participant
,
2
,
issue:
issue
)
get
:show
,
params:
{
namespace_id:
project
.
namespace
,
project_id:
project
,
id:
issue
.
iid
},
format: :json
expect
(
response
).
to
have_gitlab_http_status
(
:ok
)
expect
(
json_response
[
'issue_email_participants'
]).
to
contain_exactly
({
"email"
=>
participants
[
0
].
email
},
{
"email"
=>
participants
[
1
].
email
})
end
end
describe
'GET #new'
do
it
'redirects to signin if not logged in'
do
get
:new
,
params:
{
namespace_id:
project
.
namespace
,
project_id:
project
}
...
...
spec/features/projects/issues/email_participants_spec.rb
0 → 100644
View file @
f432e9db
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
'viewing an issue'
,
:js
do
let_it_be
(
:user
)
{
create
(
:user
)
}
let_it_be
(
:project
)
{
create
(
:project
,
:public
)
}
let_it_be
(
:issue
)
{
create
(
:issue
,
project:
project
)
}
let_it_be
(
:note
)
{
create
(
:note_on_issue
,
project:
project
,
noteable:
issue
)
}
let_it_be
(
:participants
)
{
create_list
(
:issue_email_participant
,
4
,
issue:
issue
)
}
before
do
sign_in
(
user
)
visit
project_issue_path
(
project
,
issue
)
end
shared_examples
'email participants warning'
do
|
selector
|
it
'shows the correct message'
do
expect
(
find
(
selector
)).
to
have_content
(
", and 1 more will be notified of your comment"
)
end
end
context
'for a new note'
do
it_behaves_like
'email participants warning'
,
'.new-note'
end
context
'for a reply form'
do
before
do
find
(
'.js-reply-button'
).
click
end
it_behaves_like
'email participants warning'
,
'.note-edit-form'
end
end
spec/frontend/notes/components/comment_field_layout_spec.js
0 → 100644
View file @
f432e9db
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
extendedWrapper
}
from
'
helpers/vue_test_utils_helper
'
;
import
CommentFieldLayout
from
'
~/notes/components/comment_field_layout.vue
'
;
import
EmailParticipantsWarning
from
'
~/notes/components/email_participants_warning.vue
'
;
import
NoteableWarning
from
'
~/vue_shared/components/notes/noteable_warning.vue
'
;
describe
(
'
Comment Field Layout Component
'
,
()
=>
{
let
wrapper
;
afterEach
(()
=>
{
wrapper
.
destroy
();
wrapper
=
null
;
});
const
LOCKED_DISCUSSION_DOCS_PATH
=
'
docs/locked/path
'
;
const
CONFIDENTIAL_ISSUES_DOCS_PATH
=
'
docs/confidential/path
'
;
const
noteableDataMock
=
{
confidential
:
false
,
discussion_locked
:
false
,
locked_discussion_docs_path
:
LOCKED_DISCUSSION_DOCS_PATH
,
confidential_issues_docs_path
:
CONFIDENTIAL_ISSUES_DOCS_PATH
,
};
const
findIssuableNoteWarning
=
()
=>
wrapper
.
find
(
NoteableWarning
);
const
findEmailParticipantsWarning
=
()
=>
wrapper
.
find
(
EmailParticipantsWarning
);
const
findErrorAlert
=
()
=>
wrapper
.
findByTestId
(
'
comment-field-alert-container
'
);
const
createWrapper
=
(
props
=
{},
slots
=
{})
=>
{
wrapper
=
extendedWrapper
(
shallowMount
(
CommentFieldLayout
,
{
propsData
:
{
noteableData
:
noteableDataMock
,
...
props
,
},
slots
,
}),
);
};
describe
(
'
.error-alert
'
,
()
=>
{
it
(
'
does not exist by default
'
,
()
=>
{
createWrapper
();
expect
(
findErrorAlert
().
exists
()).
toBe
(
false
);
});
it
(
'
exists when withAlertContainer is true
'
,
()
=>
{
createWrapper
({
withAlertContainer
:
true
});
expect
(
findErrorAlert
().
isVisible
()).
toBe
(
true
);
});
});
describe
(
'
issue is not confidential and not locked
'
,
()
=>
{
it
(
'
does not show IssuableNoteWarning
'
,
()
=>
{
createWrapper
();
expect
(
findIssuableNoteWarning
().
exists
()).
toBe
(
false
);
});
});
describe
(
'
issue is confidential
'
,
()
=>
{
beforeEach
(()
=>
{
createWrapper
({
noteableData
:
{
...
noteableDataMock
,
confidential
:
true
},
});
});
it
(
'
shows IssuableNoteWarning
'
,
()
=>
{
expect
(
findIssuableNoteWarning
().
isVisible
()).
toBe
(
true
);
});
it
(
'
sets IssuableNoteWarning props
'
,
()
=>
{
expect
(
findIssuableNoteWarning
().
props
()).
toMatchObject
({
isLocked
:
false
,
isConfidential
:
true
,
lockedNoteableDocsPath
:
LOCKED_DISCUSSION_DOCS_PATH
,
confidentialNoteableDocsPath
:
CONFIDENTIAL_ISSUES_DOCS_PATH
,
});
});
});
describe
(
'
issue is locked
'
,
()
=>
{
beforeEach
(()
=>
{
createWrapper
({
noteableData
:
{
...
noteableDataMock
,
discussion_locked
:
true
},
});
});
it
(
'
shows IssuableNoteWarning
'
,
()
=>
{
expect
(
findIssuableNoteWarning
().
isVisible
()).
toBe
(
true
);
});
it
(
'
sets IssuableNoteWarning props
'
,
()
=>
{
expect
(
findIssuableNoteWarning
().
props
()).
toMatchObject
({
isConfidential
:
false
,
isLocked
:
true
,
lockedNoteableDocsPath
:
LOCKED_DISCUSSION_DOCS_PATH
,
confidentialNoteableDocsPath
:
CONFIDENTIAL_ISSUES_DOCS_PATH
,
});
});
});
describe
(
'
issue has no email participants
'
,
()
=>
{
it
(
'
does not show EmailParticipantsWarning
'
,
()
=>
{
createWrapper
();
expect
(
findEmailParticipantsWarning
().
exists
()).
toBe
(
false
);
});
});
describe
(
'
issue has email participants
'
,
()
=>
{
beforeEach
(()
=>
{
createWrapper
({
noteableData
:
{
...
noteableDataMock
,
issue_email_participants
:
[
{
email
:
'
someone@gitlab.com
'
},
{
email
:
'
another@gitlab.com
'
},
],
},
});
});
it
(
'
shows EmailParticipantsWarning
'
,
()
=>
{
expect
(
findEmailParticipantsWarning
().
isVisible
()).
toBe
(
true
);
});
it
(
'
sets EmailParticipantsWarning props
'
,
()
=>
{
expect
(
findEmailParticipantsWarning
().
props
(
'
emails
'
)).
toEqual
([
'
someone@gitlab.com
'
,
'
another@gitlab.com
'
,
]);
});
});
});
spec/frontend/notes/components/comment_form_spec.js
View file @
f432e9db
...
...
@@ -181,7 +181,7 @@ describe('issue_comment_form component', () => {
describe
(
'
edit mode
'
,
()
=>
{
beforeEach
(()
=>
{
mountComponent
();
mountComponent
(
{
mountFunction
:
mount
}
);
});
it
(
'
should enter edit mode when arrow up is pressed
'
,
()
=>
{
...
...
@@ -200,7 +200,7 @@ describe('issue_comment_form component', () => {
describe
(
'
event enter
'
,
()
=>
{
beforeEach
(()
=>
{
mountComponent
();
mountComponent
(
{
mountFunction
:
mount
}
);
});
it
(
'
should save note when cmd+enter is pressed
'
,
()
=>
{
...
...
@@ -368,17 +368,6 @@ describe('issue_comment_form component', () => {
});
});
});
describe
(
'
issue is confidential
'
,
()
=>
{
it
(
'
shows information warning
'
,
()
=>
{
mountComponent
({
noteableData
:
{
...
noteableDataMock
,
confidential
:
true
},
mountFunction
:
mount
,
});
expect
(
wrapper
.
find
(
'
[data-testid="confidential-warning"]
'
).
exists
()).
toBe
(
true
);
});
});
});
describe
(
'
user is not logged in
'
,
()
=>
{
...
...
spec/frontend/notes/components/email_participants_warning_spec.js
0 → 100644
View file @
f432e9db
import
{
mount
}
from
'
@vue/test-utils
'
;
import
EmailParticipantsWarning
from
'
~/notes/components/email_participants_warning.vue
'
;
describe
(
'
Email Participants Warning Component
'
,
()
=>
{
let
wrapper
;
afterEach
(()
=>
{
wrapper
.
destroy
();
wrapper
=
null
;
});
const
findMoreButton
=
()
=>
wrapper
.
find
(
'
button
'
);
const
createWrapper
=
(
emails
)
=>
{
wrapper
=
mount
(
EmailParticipantsWarning
,
{
propsData
:
{
emails
},
});
};
describe
(
'
with 3 or less emails
'
,
()
=>
{
beforeEach
(()
=>
{
createWrapper
([
'
a@gitlab.com
'
,
'
b@gitlab.com
'
,
'
c@gitlab.com
'
]);
});
it
(
'
more button does not exist
'
,
()
=>
{
expect
(
findMoreButton
().
exists
()).
toBe
(
false
);
});
it
(
'
all emails are displayed
'
,
()
=>
{
expect
(
wrapper
.
text
()).
toBe
(
'
a@gitlab.com, b@gitlab.com, and c@gitlab.com will be notified of your comment.
'
,
);
});
});
describe
(
'
with more than 3 emails
'
,
()
=>
{
beforeEach
(()
=>
{
createWrapper
([
'
a@gitlab.com
'
,
'
b@gitlab.com
'
,
'
c@gitlab.com
'
,
'
d@gitlab.com
'
]);
});
it
(
'
only displays first 3 emails
'
,
()
=>
{
expect
(
wrapper
.
text
()).
toContain
(
'
a@gitlab.com, b@gitlab.com, c@gitlab.com
'
);
expect
(
wrapper
.
text
()).
not
.
toContain
(
'
d@gitlab.com
'
);
});
it
(
'
more button does exist
'
,
()
=>
{
expect
(
findMoreButton
().
exists
()).
toBe
(
true
);
});
it
(
'
more button displays the correct wordage
'
,
()
=>
{
expect
(
findMoreButton
().
text
()).
toBe
(
'
and 1 more
'
);
});
describe
(
'
when more button clicked
'
,
()
=>
{
beforeEach
(()
=>
{
findMoreButton
().
trigger
(
'
click
'
);
});
it
(
'
more button no longer exists
'
,
()
=>
{
expect
(
findMoreButton
().
exists
()).
toBe
(
false
);
});
it
(
'
all emails are displayed
'
,
()
=>
{
expect
(
wrapper
.
text
()).
toBe
(
'
a@gitlab.com, b@gitlab.com, c@gitlab.com, and d@gitlab.com will be notified of your comment.
'
,
);
});
});
});
});
spec/frontend/notes/components/note_form_spec.js
View file @
f432e9db
import
{
mount
}
from
'
@vue/test-utils
'
;
import
{
nextTick
}
from
'
vue
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
createStore
from
'
~/notes/stores
'
;
import
NoteForm
from
'
~/notes/components/note_form.vue
'
;
import
batchComments
from
'
~/batch_comments/stores/modules/batch_comments
'
;
...
...
@@ -19,7 +19,7 @@ describe('issue_note_form component', () => {
let
props
;
const
createComponentWrapper
=
()
=>
{
return
shallowM
ount
(
NoteForm
,
{
return
m
ount
(
NoteForm
,
{
store
,
propsData
:
props
,
});
...
...
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