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
ced04cfb
Commit
ced04cfb
authored
Jan 22, 2020
by
Natalia Tepluhina
Committed by
Phil Hughes
Jan 22, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Convert Jest tests to use VTU in 'spec/frontend/notes/components'
parent
cc2b47fe
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
192 additions
and
194 deletions
+192
-194
app/assets/javascripts/notes/components/discussion_filter_note.vue
...s/javascripts/notes/components/discussion_filter_note.vue
+3
-3
app/assets/javascripts/notes/components/note_attachment.vue
app/assets/javascripts/notes/components/note_attachment.vue
+14
-2
app/assets/javascripts/notes/components/note_header.vue
app/assets/javascripts/notes/components/note_header.vue
+4
-3
spec/frontend/notes/components/discussion_filter_note_spec.js
.../frontend/notes/components/discussion_filter_note_spec.js
+18
-71
spec/frontend/notes/components/note_attachment_spec.js
spec/frontend/notes/components/note_attachment_spec.js
+40
-18
spec/frontend/notes/components/note_header_spec.js
spec/frontend/notes/components/note_header_spec.js
+113
-97
No files found.
app/assets/javascripts/notes/components/discussion_filter_note.vue
View file @
ced04cfb
...
...
@@ -38,12 +38,12 @@ export default {
<icon
name=
"comment"
/>
</div>
<div
class=
"timeline-content"
>
<div
v-html=
"timelineContent"
></div>
<div
ref=
"timelineContent"
v-html=
"timelineContent"
></div>
<div
class=
"discussion-filter-actions mt-2"
>
<gl-button
variant=
"default"
@
click=
"selectFilter(0)"
>
<gl-button
ref=
"showAllActivity"
variant=
"default"
@
click=
"selectFilter(0)"
>
{{
__
(
'
Show all activity
'
)
}}
</gl-button>
<gl-button
variant=
"default"
@
click=
"selectFilter(1)"
>
<gl-button
ref=
"showComments"
variant=
"default"
@
click=
"selectFilter(1)"
>
{{
__
(
'
Show comments only
'
)
}}
</gl-button>
</div>
...
...
app/assets/javascripts/notes/components/note_attachment.vue
View file @
ced04cfb
...
...
@@ -12,11 +12,23 @@ export default {
<
template
>
<div
class=
"note-attachment"
>
<a
v-if=
"attachment.image"
:href=
"attachment.url"
target=
"_blank"
rel=
"noopener noreferrer"
>
<a
v-if=
"attachment.image"
ref=
"attachmentImage"
:href=
"attachment.url"
target=
"_blank"
rel=
"noopener noreferrer"
>
<img
:src=
"attachment.url"
class=
"note-image-attach"
/>
</a>
<div
class=
"attachment"
>
<a
v-if=
"attachment.url"
:href=
"attachment.url"
target=
"_blank"
rel=
"noopener noreferrer"
>
<a
v-if=
"attachment.url"
ref=
"attachmentUrl"
:href=
"attachment.url"
target=
"_blank"
rel=
"noopener noreferrer"
>
<i
class=
"fa fa-paperclip"
aria-hidden=
"true"
>
</i>
{{
attachment
.
filename
}}
</a>
</div>
...
...
app/assets/javascripts/notes/components/note_header.vue
View file @
ced04cfb
...
...
@@ -63,13 +63,13 @@ export default {
<
template
>
<div
class=
"note-header-info"
>
<div
v-if=
"includeToggle"
class=
"discussion-actions"
>
<div
v-if=
"includeToggle"
ref=
"discussionActions"
class=
"discussion-actions"
>
<button
class=
"note-action-button discussion-toggle-button js-vue-toggle-button"
type=
"button"
@
click=
"handleToggle"
>
<i
:class=
"toggleChevronClass"
class=
"fa"
aria-hidden=
"true"
></i>
<i
ref=
"chevronIcon"
:class=
"toggleChevronClass"
class=
"fa"
aria-hidden=
"true"
></i>
{{
__
(
'
Toggle thread
'
)
}}
</button>
</div>
...
...
@@ -90,10 +90,11 @@ export default {
<span
class=
"note-headline-light note-headline-meta"
>
<span
class=
"system-note-message"
>
<slot></slot>
</span>
<template
v-if=
"createdAt"
>
<span
class=
"system-note-separator"
>
<span
ref=
"actionText"
class=
"system-note-separator"
>
<template
v-if=
"actionText"
>
{{
actionText
}}
</
template
>
</span>
<a
ref=
"noteTimestamp"
:href=
"noteTimestampLink"
class=
"note-timestamp system-note-separator"
@
click=
"updateTargetNoteHash"
...
...
spec/frontend/notes/components/discussion_filter_note_spec.js
View file @
ced04cfb
import
Vue
from
'
vue
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
DiscussionFilterNote
from
'
~/notes/components/discussion_filter_note.vue
'
;
import
eventHub
from
'
~/notes/event_hub
'
;
import
mountComponent
from
'
../../helpers/vue_mount_component_helper
'
;
describe
(
'
DiscussionFilterNote component
'
,
()
=>
{
let
vm
;
let
wrapper
;
const
createComponent
=
()
=>
{
const
Component
=
Vue
.
extend
(
DiscussionFilterNote
);
return
mountComponent
(
Component
);
wrapper
=
shallowMount
(
DiscussionFilterNote
);
};
beforeEach
(()
=>
{
vm
=
createComponent
();
createComponent
();
});
afterEach
(()
=>
{
vm
.
$destroy
();
wrapper
.
destroy
();
wrapper
=
null
;
});
describe
(
'
computed
'
,
()
=>
{
describe
(
'
timelineContent
'
,
()
=>
{
it
(
'
returns string containing instruction for switching feed type
'
,
()
=>
{
expect
(
vm
.
timelineContent
).
toBe
(
"
You're only seeing <b>other activity</b> in the feed. To add a comment, switch to one of the following options.
"
,
);
});
});
it
(
'
timelineContent renders a string containing instruction for switching feed type
'
,
()
=>
{
expect
(
wrapper
.
find
({
ref
:
'
timelineContent
'
}).
html
()).
toBe
(
"
<div>You're only seeing <b>other activity</b> in the feed. To add a comment, switch to one of the following options.</div>
"
,
);
});
describe
(
'
methods
'
,
()
=>
{
describe
(
'
selectFilter
'
,
()
=>
{
it
(
'
emits `dropdownSelect` event on `eventHub` with provided param
'
,
()
=>
{
jest
.
spyOn
(
eventHub
,
'
$emit
'
).
mockImplementation
(()
=>
{});
it
(
'
emits `dropdownSelect` event with 0 parameter on clicking Show all activity button
'
,
()
=>
{
jest
.
spyOn
(
eventHub
,
'
$emit
'
).
mockImplementation
(()
=>
{});
wrapper
.
find
({
ref
:
'
showAllActivity
'
}).
vm
.
$emit
(
'
click
'
);
vm
.
selectFilter
(
1
);
expect
(
eventHub
.
$emit
).
toHaveBeenCalledWith
(
'
dropdownSelect
'
,
1
);
});
});
expect
(
eventHub
.
$emit
).
toHaveBeenCalledWith
(
'
dropdownSelect
'
,
0
);
});
describe
(
'
template
'
,
()
=>
{
it
(
'
renders component container element
'
,
()
=>
{
expect
(
vm
.
$el
.
classList
.
contains
(
'
discussion-filter-note
'
)).
toBe
(
true
);
});
it
(
'
renders comment icon element
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.timeline-icon svg use
'
).
getAttribute
(
'
xlink:href
'
)).
toContain
(
'
comment
'
,
);
});
it
(
'
renders filter information note
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.timeline-content
'
).
innerText
.
trim
()).
toContain
(
"
You're only seeing other activity in the feed. To add a comment, switch to one of the following options.
"
,
);
});
it
(
'
renders filter buttons
'
,
()
=>
{
const
buttonsContainerEl
=
vm
.
$el
.
querySelector
(
'
.discussion-filter-actions
'
);
expect
(
buttonsContainerEl
.
querySelector
(
'
button:first-child
'
).
innerText
.
trim
()).
toContain
(
'
Show all activity
'
,
);
expect
(
buttonsContainerEl
.
querySelector
(
'
button:last-child
'
).
innerText
.
trim
()).
toContain
(
'
Show comments only
'
,
);
});
it
(
'
clicking `Show all activity` button calls `selectFilter("all")` method
'
,
()
=>
{
const
showAllBtn
=
vm
.
$el
.
querySelector
(
'
.discussion-filter-actions button:first-child
'
);
jest
.
spyOn
(
vm
,
'
selectFilter
'
).
mockImplementation
(()
=>
{});
showAllBtn
.
dispatchEvent
(
new
Event
(
'
click
'
));
expect
(
vm
.
selectFilter
).
toHaveBeenCalledWith
(
0
);
});
it
(
'
clicking `Show comments only` button calls `selectFilter("comments")` method
'
,
()
=>
{
const
showAllBtn
=
vm
.
$el
.
querySelector
(
'
.discussion-filter-actions button:last-child
'
);
jest
.
spyOn
(
vm
,
'
selectFilter
'
).
mockImplementation
(()
=>
{});
showAllBtn
.
dispatchEvent
(
new
Event
(
'
click
'
));
it
(
'
emits `dropdownSelect` event with 1 parameter on clicking Show comments only button
'
,
()
=>
{
jest
.
spyOn
(
eventHub
,
'
$emit
'
).
mockImplementation
(()
=>
{});
wrapper
.
find
({
ref
:
'
showComments
'
}).
vm
.
$emit
(
'
click
'
);
expect
(
vm
.
selectFilter
).
toHaveBeenCalledWith
(
1
);
});
expect
(
eventHub
.
$emit
).
toHaveBeenCalledWith
(
'
dropdownSelect
'
,
1
);
});
});
spec/frontend/notes/components/note_attachment_spec.js
View file @
ced04cfb
import
Vue
from
'
vue
'
;
import
noteAttachment
from
'
~/notes/components/note_attachment.vue
'
;
describe
(
'
issue note attachment
'
,
()
=>
{
it
(
'
should render properly
'
,
()
=>
{
const
props
=
{
attachment
:
{
filename
:
'
dk.png
'
,
image
:
true
,
url
:
'
/dk.png
'
,
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
NoteAttachment
from
'
~/notes/components/note_attachment.vue
'
;
describe
(
'
Issue note attachment
'
,
()
=>
{
let
wrapper
;
const
findImage
=
()
=>
wrapper
.
find
({
ref
:
'
attachmentImage
'
});
const
findUrl
=
()
=>
wrapper
.
find
({
ref
:
'
attachmentUrl
'
});
const
createComponent
=
attachment
=>
{
wrapper
=
shallowMount
(
NoteAttachment
,
{
propsData
:
{
attachment
,
},
};
});
};
afterEach
(()
=>
{
wrapper
.
destroy
();
wrapper
=
null
;
});
it
(
'
renders attachment image if it is passed in attachment prop
'
,
()
=>
{
createComponent
({
image
:
'
test-image
'
,
});
expect
(
findImage
().
exists
()).
toBe
(
true
);
});
it
(
'
renders attachment url if it is passed in attachment prop
'
,
()
=>
{
createComponent
({
url
:
'
test-url
'
,
});
expect
(
findUrl
().
exists
()).
toBe
(
true
);
});
const
Component
=
Vue
.
extend
(
noteAttachment
);
const
vm
=
new
Component
({
propsData
:
props
,
}).
$mount
();
it
(
'
does not render image and url if attachment object is empty
'
,
()
=>
{
createComponent
({});
expect
(
vm
.
$el
.
classList
.
contains
(
'
note-attachment
'
)).
toBeTruthy
();
expect
(
vm
.
$el
.
querySelector
(
'
img
'
).
src
).
toContain
(
props
.
attachment
.
url
);
expect
(
vm
.
$el
.
querySelector
(
'
a
'
).
href
).
toContain
(
props
.
attachment
.
url
);
expect
(
findImage
().
exists
()).
toBe
(
false
);
expect
(
findUrl
().
exists
()).
toBe
(
false
);
});
});
spec/frontend/notes/components/note_header_spec.js
View file @
ced04cfb
import
Vue
from
'
vue
'
;
import
noteHeader
from
'
~/notes/components/note_header.vue
'
;
import
createStore
from
'
~/notes/stores
'
;
describe
(
'
note_header component
'
,
()
=>
{
let
store
;
let
vm
;
let
Component
;
beforeEach
(()
=>
{
Component
=
Vue
.
extend
(
noteHeader
);
store
=
createStore
();
});
import
{
shallowMount
,
createLocalVue
}
from
'
@vue/test-utils
'
;
import
Vuex
from
'
vuex
'
;
import
NoteHeader
from
'
~/notes/components/note_header.vue
'
;
const
localVue
=
createLocalVue
();
localVue
.
use
(
Vuex
);
const
actions
=
{
setTargetNoteHash
:
jest
.
fn
(),
};
describe
(
'
NoteHeader component
'
,
()
=>
{
let
wrapper
;
const
findActionsWrapper
=
()
=>
wrapper
.
find
({
ref
:
'
discussionActions
'
});
const
findChevronIcon
=
()
=>
wrapper
.
find
({
ref
:
'
chevronIcon
'
});
const
findActionText
=
()
=>
wrapper
.
find
({
ref
:
'
actionText
'
});
const
findTimestamp
=
()
=>
wrapper
.
find
({
ref
:
'
noteTimestamp
'
});
const
createComponent
=
props
=>
{
wrapper
=
shallowMount
(
NoteHeader
,
{
localVue
,
store
:
new
Vuex
.
Store
({
actions
,
}),
propsData
:
{
...
props
,
actionTextHtml
:
''
,
noteId
:
'
1394
'
,
},
});
};
afterEach
(()
=>
{
vm
.
$destroy
();
wrapper
.
destroy
();
wrapper
=
null
;
});
describe
(
'
individual note
'
,
()
=>
{
beforeEach
(()
=>
{
vm
=
new
Component
({
store
,
propsData
:
{
actionText
:
'
commented
'
,
actionTextHtml
:
''
,
author
:
{
avatar_url
:
null
,
id
:
1
,
name
:
'
Root
'
,
path
:
'
/root
'
,
state
:
'
active
'
,
username
:
'
root
'
,
},
createdAt
:
'
2017-08-02T10:51:58.559Z
'
,
includeToggle
:
false
,
noteId
:
'
1394
'
,
expanded
:
true
,
},
}).
$mount
();
it
(
'
does not render discussion actions when includeToggle is false
'
,
()
=>
{
createComponent
({
includeToggle
:
false
,
});
it
(
'
should render user information
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.note-header-author-name
'
).
textContent
.
trim
()).
toEqual
(
'
Root
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.note-header-info a
'
).
getAttribute
(
'
href
'
)).
toEqual
(
'
/root
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.note-header-info a
'
).
dataset
.
userId
).
toEqual
(
'
1
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.note-header-info a
'
).
dataset
.
username
).
toEqual
(
'
root
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.note-header-info a
'
).
classList
).
toContain
(
'
js-user-link
'
);
expect
(
findActionsWrapper
().
exists
()).
toBe
(
false
);
});
describe
(
'
when includes a toggle
'
,
()
=>
{
it
(
'
renders discussion actions
'
,
()
=>
{
createComponent
({
includeToggle
:
true
,
});
expect
(
findActionsWrapper
().
exists
()).
toBe
(
true
);
});
it
(
'
should render timestamp link
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
a[href="#note_1394"]
'
)).
toBeDefined
();
it
(
'
emits toggleHandler event on button click
'
,
()
=>
{
createComponent
({
includeToggle
:
true
,
});
wrapper
.
find
(
'
.note-action-button
'
).
trigger
(
'
click
'
);
expect
(
wrapper
.
emitted
(
'
toggleHandler
'
)).
toBeDefined
();
expect
(
wrapper
.
emitted
(
'
toggleHandler
'
)).
toHaveLength
(
1
);
});
it
(
'
should not render user information when prop `author` is empty object
'
,
done
=>
{
vm
.
author
=
{};
Vue
.
nextTick
()
.
then
(()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.note-header-author-name
'
)).
toBeNull
();
})
.
then
(
done
)
.
catch
(
done
.
fail
);
it
(
'
has chevron-up icon if expanded prop is true
'
,
()
=>
{
createComponent
({
includeToggle
:
true
,
expanded
:
true
,
});
expect
(
findChevronIcon
().
classes
()).
toContain
(
'
fa-chevron-up
'
);
});
});
describe
(
'
discussion
'
,
()
=>
{
beforeEach
(()
=>
{
vm
=
new
Component
({
store
,
propsData
:
{
actionText
:
'
started a discussion
'
,
actionTextHtml
:
''
,
author
:
{
avatar_url
:
null
,
id
:
1
,
name
:
'
Root
'
,
path
:
'
/root
'
,
state
:
'
active
'
,
username
:
'
root
'
,
},
createdAt
:
'
2017-08-02T10:51:58.559Z
'
,
includeToggle
:
true
,
noteId
:
'
1395
'
,
expanded
:
true
,
},
}).
$mount
();
it
(
'
has chevron-down icon if expanded prop is false
'
,
()
=>
{
createComponent
({
includeToggle
:
true
,
expanded
:
false
,
});
expect
(
findChevronIcon
().
classes
()).
toContain
(
'
fa-chevron-down
'
);
});
});
it
(
'
should render toggle button
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.js-vue-toggle-button
'
)).
toBeDefined
();
it
(
'
renders an author link if author is passed to props
'
,
()
=>
{
createComponent
({
author
:
{
avatar_url
:
null
,
id
:
1
,
name
:
'
Root
'
,
path
:
'
/root
'
,
state
:
'
active
'
,
username
:
'
root
'
,
},
});
it
(
'
emits toggle event on click
'
,
done
=>
{
jest
.
spyOn
(
vm
,
'
$emit
'
).
mockImplementation
(()
=>
{
});
expect
(
wrapper
.
find
(
'
.js-user-link
'
).
exists
()).
toBe
(
true
);
});
vm
.
$el
.
querySelector
(
'
.js-vue-toggle-button
'
).
click
();
it
(
'
renders deleted user text if author is not passed as a prop
'
,
()
=>
{
createComponent
();
Vue
.
nextTick
(()
=>
{
expect
(
vm
.
$emit
).
toHaveBeenCalledWith
(
'
toggleHandler
'
);
done
();
});
}
);
expect
(
wrapper
.
text
()).
toContain
(
'
A deleted user
'
);
}
);
it
(
'
does not render created at information if createdAt is not passed as a prop
'
,
()
=>
{
createComponent
(
);
it
(
'
renders up arrow when open
'
,
done
=>
{
vm
.
expanded
=
true
;
expect
(
findActionText
().
exists
()).
toBe
(
false
);
expect
(
findTimestamp
().
exists
()).
toBe
(
false
);
});
Vue
.
nextTick
(()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.js-vue-toggle-button i
'
).
classList
).
toContain
(
'
fa-chevron-up
'
,
);
done
();
describe
(
'
when createdAt is passed as a prop
'
,
()
=>
{
it
(
'
renders action text and a timestamp
'
,
()
=>
{
createComponent
({
createdAt
:
'
2017-08-02T10:51:58.559Z
'
,
});
expect
(
findActionText
().
exists
()).
toBe
(
true
);
expect
(
findTimestamp
().
exists
()).
toBe
(
true
);
});
it
(
'
renders down arrow when closed
'
,
done
=>
{
vm
.
expanded
=
false
;
it
(
'
renders correct actionText if passed
'
,
()
=>
{
createComponent
({
createdAt
:
'
2017-08-02T10:51:58.559Z
'
,
actionText
:
'
Test action text
'
,
});
expect
(
findActionText
().
text
()).
toBe
(
'
Test action text
'
);
});
Vue
.
nextTick
(()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.js-vue-toggle-button i
'
).
classList
).
toContain
(
'
fa-chevron-down
'
,
);
done
();
it
(
'
calls an action when timestamp is clicked
'
,
()
=>
{
createComponent
({
createdAt
:
'
2017-08-02T10:51:58.559Z
'
,
});
findTimestamp
().
trigger
(
'
click
'
);
expect
(
actions
.
setTargetNoteHash
).
toHaveBeenCalled
();
});
});
});
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