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
6a3b4071
Commit
6a3b4071
authored
Jan 23, 2020
by
Natalia Tepluhina
Committed by
Martin Wortschack
Jan 23, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Convert Jest tests to use VTU in 'spec/frontend/vue_shared'
parent
0768943e
Changes
17
Show whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
509 additions
and
397 deletions
+509
-397
app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue
...ed_search/components/recent_searches_dropdown_content.vue
+12
-5
app/assets/javascripts/vue_shared/components/identicon.vue
app/assets/javascripts/vue_shared/components/identicon.vue
+1
-1
app/assets/javascripts/vue_shared/components/issue/issue_warning.vue
...javascripts/vue_shared/components/issue/issue_warning.vue
+3
-3
app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue
...ascripts/vue_shared/components/notes/placeholder_note.vue
+1
-1
spec/frontend/filtered_search/components/recent_searches_dropdown_content_spec.js
...earch/components/recent_searches_dropdown_content_spec.js
+80
-156
spec/frontend/vue_shared/components/__snapshots__/code_block_spec.js.snap
...e_shared/components/__snapshots__/code_block_spec.js.snap
+16
-0
spec/frontend/vue_shared/components/__snapshots__/identicon_spec.js.snap
...ue_shared/components/__snapshots__/identicon_spec.js.snap
+11
-0
spec/frontend/vue_shared/components/code_block_spec.js
spec/frontend/vue_shared/components/code_block_spec.js
+15
-23
spec/frontend/vue_shared/components/identicon_spec.js
spec/frontend/vue_shared/components/identicon_spec.js
+24
-56
spec/frontend/vue_shared/components/issue/__snapshots__/issue_warning_spec.js.snap
...components/issue/__snapshots__/issue_warning_spec.js.snap
+62
-0
spec/frontend/vue_shared/components/issue/issue_warning_spec.js
...rontend/vue_shared/components/issue/issue_warning_spec.js
+87
-47
spec/frontend/vue_shared/components/markdown/__snapshots__/suggestion_diff_spec.js.snap
...nents/markdown/__snapshots__/suggestion_diff_spec.js.snap
+28
-0
spec/frontend/vue_shared/components/markdown/suggestion_diff_spec.js
...nd/vue_shared/components/markdown/suggestion_diff_spec.js
+34
-49
spec/frontend/vue_shared/components/notes/__snapshots__/placeholder_note_spec.js.snap
...ponents/notes/__snapshots__/placeholder_note_spec.js.snap
+62
-0
spec/frontend/vue_shared/components/notes/__snapshots__/placeholder_system_note_spec.js.snap
.../notes/__snapshots__/placeholder_system_note_spec.js.snap
+15
-0
spec/frontend/vue_shared/components/notes/placeholder_note_spec.js
...tend/vue_shared/components/notes/placeholder_note_spec.js
+42
-38
spec/frontend/vue_shared/components/notes/placeholder_system_note_spec.js
...e_shared/components/notes/placeholder_system_note_spec.js
+16
-18
No files found.
app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue
View file @
6a3b4071
...
...
@@ -59,21 +59,25 @@ export default {
</
script
>
<
template
>
<div>
<div
v-if=
"!isLocalStorageAvailable"
class=
"dropdown-info-note"
>
<div
v-if=
"!isLocalStorageAvailable"
ref=
"localStorageNote"
class=
"dropdown-info-note"
>
{{
__
(
'
This feature requires local storage to be enabled
'
)
}}
</div>
<ul
v-else-if=
"hasItems"
>
<li
v-for=
"(item, index) in processedItems"
:key=
"`processed-items-$
{index}`">
<li
v-for=
"(item, index) in processedItems"
ref=
"dropdownItem"
:key=
"`processed-items-$
{index}`"
>
<button
type=
"button"
class=
"filtered-search-history-dropdown-item"
class=
"filtered-search-history-dropdown-item
js-dropdown-button
"
@
click=
"onItemActivated(item.text)"
>
<span>
<span
v-for=
"(token, tokenIndex) in item.tokens"
:key=
"`dropdown-token-$
{tokenIndex}`"
class="filtered-search-history-dropdown-token"
class="filtered-search-history-dropdown-token
js-dropdown-token
"
>
<span
class=
"name"
>
{{
token
.
prefix
}}
</span>
<span
class=
"name"
>
{{
token
.
operator
}}
</span>
...
...
@@ -88,6 +92,7 @@ export default {
<li
class=
"divider"
></li>
<li>
<button
ref=
"clearButton"
type=
"button"
class=
"filtered-search-history-clear-button"
@
click=
"onRequestClearRecentSearches($event)"
...
...
@@ -96,6 +101,8 @@ export default {
</button>
</li>
</ul>
<div
v-else
class=
"dropdown-info-note"
>
{{
__
(
"
You don't have any recent searches
"
)
}}
</div>
<div
v-else
ref=
"dropdownNote"
class=
"dropdown-info-note"
>
{{
__
(
"
You don't have any recent searches
"
)
}}
</div>
</div>
</
template
>
app/assets/javascripts/vue_shared/components/identicon.vue
View file @
6a3b4071
...
...
@@ -29,7 +29,7 @@ export default {
</
script
>
<
template
>
<div
:class=
"[sizeClass, identiconBackgroundClass]"
class=
"avatar identicon"
>
<div
ref=
"identicon"
:class=
"[sizeClass, identiconBackgroundClass]"
class=
"avatar identicon"
>
{{
identiconTitle
}}
</div>
</
template
>
app/assets/javascripts/vue_shared/components/issue/issue_warning.vue
View file @
6a3b4071
...
...
@@ -65,14 +65,14 @@ export default {
<div
class=
"issuable-note-warning"
>
<icon
v-if=
"!isLockedAndConfidential"
:name=
"warningIcon"
:size=
"16"
class=
"icon inline"
/>
<span
v-if=
"isLockedAndConfidential"
>
<span
v-if=
"isLockedAndConfidential"
ref=
"lockedAndConfidential"
>
<span
v-html=
"confidentialAndLockedDiscussionText"
></span>
{{
__
(
"
People without permission will never get a notification and won't be able to comment.
"
)
}}
</span>
<span
v-else-if=
"isConfidential"
>
<span
v-else-if=
"isConfidential"
ref=
"confidential"
>
{{
__
(
'
This is a confidential issue.
'
)
}}
{{
__
(
'
People without permission will never get a notification.
'
)
}}
<gl-link
:href=
"confidentialIssueDocsPath"
target=
"_blank"
>
...
...
@@ -80,7 +80,7 @@ export default {
</gl-link>
</span>
<span
v-else-if=
"isLocked"
>
<span
v-else-if=
"isLocked"
ref=
"locked"
>
{{
__
(
'
This issue is locked.
'
)
}}
{{
__
(
'
Only project members can comment.
'
)
}}
<gl-link
:href=
"lockedIssueDocsPath"
target=
"_blank"
>
...
...
app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue
View file @
6a3b4071
...
...
@@ -47,7 +47,7 @@ export default {
:img-size=
"40"
/>
</div>
<div
:class=
"
{ discussion: !note.individual_note }" class="timeline-content">
<div
ref=
"note"
:class=
"
{ discussion: !note.individual_note }" class="timeline-content">
<div
class=
"note-header"
>
<div
class=
"note-header-info"
>
<a
:href=
"getUserData.path"
>
...
...
spec/frontend/filtered_search/components/recent_searches_dropdown_content_spec.js
View file @
6a3b4071
import
Vue
from
'
vue
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
eventHub
from
'
~/filtered_search/event_hub
'
;
import
RecentSearchesDropdownContent
from
'
~/filtered_search/components/recent_searches_dropdown_content.vue
'
;
import
IssuableFilteredSearchTokenKeys
from
'
~/filtered_search/issuable_filtered_search_token_keys
'
;
const
createComponent
=
propsData
=>
{
const
Component
=
Vue
.
extend
(
RecentSearchesDropdownContent
)
;
describe
(
'
Recent Searches Dropdown Content
'
,
()
=>
{
let
wrapper
;
return
new
Component
({
el
:
document
.
createElement
(
'
div
'
),
propsData
,
});
};
// Remove all the newlines and whitespace from the formatted markup
const
trimMarkupWhitespace
=
text
=>
text
.
replace
(
/
(\n
|
\s)
+/gm
,
'
'
).
trim
();
const
findLocalStorageNote
=
()
=>
wrapper
.
find
({
ref
:
'
localStorageNote
'
});
const
findDropdownItems
=
()
=>
wrapper
.
findAll
({
ref
:
'
dropdownItem
'
});
const
findDropdownNote
=
()
=>
wrapper
.
find
({
ref
:
'
dropdownNote
'
});
describe
(
'
RecentSearchesDropdownContent
'
,
()
=>
{
const
propsDataWithoutItems
=
{
items
:
[],
allowedKeys
:
IssuableFilteredSearchTokenKeys
.
getKeys
(),
};
const
propsDataWithItems
=
{
items
:
[
'
foo
'
,
'
author:@root label:~foo bar
'
],
const
createComponent
=
props
=>
{
wrapper
=
shallowMount
(
RecentSearchesDropdownContent
,
{
propsData
:
{
allowedKeys
:
IssuableFilteredSearchTokenKeys
.
getKeys
(),
items
:
[],
isLocalStorageAvailable
:
false
,
...
props
,
},
});
};
let
vm
;
afterEach
(()
=>
{
if
(
vm
)
{
vm
.
$destroy
();
}
wrapper
.
destroy
();
wrapper
=
null
;
});
describe
(
'
with no items
'
,
()
=>
{
let
el
;
describe
(
'
when local storage is not available
'
,
()
=>
{
beforeEach
(()
=>
{
vm
=
createComponent
(
propsDataWithoutItems
);
el
=
vm
.
$el
;
createComponent
();
});
it
(
'
should render empty state
'
,
()
=>
{
expect
(
el
.
querySelector
(
'
.dropdown-info-note
'
)).
toBeDefined
();
const
items
=
el
.
querySelectorAll
(
'
.filtered-search-history-dropdown-item
'
);
expect
(
items
.
length
).
toEqual
(
propsDataWithoutItems
.
items
.
length
);
});
it
(
'
renders a note about enabling local storage
'
,
()
=>
{
expect
(
findLocalStorageNote
().
exists
()).
toBe
(
true
);
});
describe
(
'
with items
'
,
()
=>
{
let
el
;
beforeEach
(()
=>
{
vm
=
createComponent
(
propsDataWithItems
);
el
=
vm
.
$el
;
it
(
'
does not render dropdown items
'
,
()
=>
{
expect
(
findDropdownItems
().
exists
()).
toBe
(
false
);
});
it
(
'
should render clear recent searches button
'
,
()
=>
{
expect
(
el
.
querySelector
(
'
.filtered-search-history-clear-button
'
)).
toBeDefined
();
});
it
(
'
should render recent search items
'
,
()
=>
{
const
items
=
el
.
querySelectorAll
(
'
.filtered-search-history-dropdown-item
'
);
expect
(
items
.
length
).
toEqual
(
propsDataWithItems
.
items
.
length
);
expect
(
trimMarkupWhitespace
(
items
[
0
].
querySelector
(
'
.filtered-search-history-dropdown-search-token
'
).
textContent
,
),
).
toEqual
(
'
foo
'
);
const
item1Tokens
=
items
[
1
].
querySelectorAll
(
'
.filtered-search-history-dropdown-token
'
);
expect
(
item1Tokens
.
length
).
toEqual
(
2
);
expect
(
item1Tokens
[
0
].
querySelector
(
'
.name
'
).
textContent
).
toEqual
(
'
author:
'
);
expect
(
item1Tokens
[
0
].
querySelector
(
'
.value
'
).
textContent
).
toEqual
(
'
@root
'
);
expect
(
item1Tokens
[
1
].
querySelector
(
'
.name
'
).
textContent
).
toEqual
(
'
label:
'
);
expect
(
item1Tokens
[
1
].
querySelector
(
'
.value
'
).
textContent
).
toEqual
(
'
~foo
'
);
expect
(
trimMarkupWhitespace
(
items
[
1
].
querySelector
(
'
.filtered-search-history-dropdown-search-token
'
).
textContent
,
),
).
toEqual
(
'
bar
'
);
it
(
'
does not render dropdownNote
'
,
()
=>
{
expect
(
findDropdownNote
().
exists
()).
toBe
(
false
);
});
});
describe
(
'
if isLocalStorageAvailable is `false`
'
,
()
=>
{
let
el
;
beforeEach
(()
=>
{
const
props
=
Object
.
assign
({
isLocalStorageAvailable
:
false
},
propsDataWithItems
);
describe
(
'
when localStorage is available and items array is not empty
'
,
()
=>
{
let
onRecentSearchesItemSelectedSpy
;
let
onRequestClearRecentSearchesSpy
;
vm
=
createComponent
(
props
);
el
=
vm
.
$el
;
beforeAll
(()
=>
{
onRecentSearchesItemSelectedSpy
=
jest
.
fn
();
onRequestClearRecentSearchesSpy
=
jest
.
fn
();
eventHub
.
$on
(
'
recentSearchesItemSelected
'
,
onRecentSearchesItemSelectedSpy
);
eventHub
.
$on
(
'
requestClearRecentSearches
'
,
onRequestClearRecentSearchesSpy
);
});
it
(
'
should render an info note
'
,
()
=>
{
const
note
=
el
.
querySelector
(
'
.dropdown-info-note
'
);
const
items
=
el
.
querySelectorAll
(
'
.filtered-search-history-dropdown-item
'
);
expect
(
note
).
toBeDefined
();
expect
(
note
.
innerText
.
trim
()).
toBe
(
'
This feature requires local storage to be enabled
'
);
expect
(
items
.
length
).
toEqual
(
propsDataWithoutItems
.
items
.
length
);
beforeEach
(()
=>
{
createComponent
({
items
:
[
'
foo
'
,
'
author:@root label:~foo bar
'
],
isLocalStorageAvailable
:
true
,
});
});
describe
(
'
computed
'
,
()
=>
{
describe
(
'
processedItems
'
,
()
=>
{
it
(
'
with items
'
,
()
=>
{
vm
=
createComponent
(
propsDataWithItems
);
const
{
processedItems
}
=
vm
;
expect
(
processedItems
.
length
).
toEqual
(
2
);
expect
(
processedItems
[
0
].
text
).
toEqual
(
propsDataWithItems
.
items
[
0
]);
expect
(
processedItems
[
0
].
tokens
).
toEqual
([]);
expect
(
processedItems
[
0
].
searchToken
).
toEqual
(
'
foo
'
);
expect
(
processedItems
[
1
].
text
).
toEqual
(
propsDataWithItems
.
items
[
1
]);
expect
(
processedItems
[
1
].
tokens
.
length
).
toEqual
(
2
);
expect
(
processedItems
[
1
].
tokens
[
0
].
prefix
).
toEqual
(
'
author:
'
);
expect
(
processedItems
[
1
].
tokens
[
0
].
suffix
).
toEqual
(
'
@root
'
);
expect
(
processedItems
[
1
].
tokens
[
1
].
prefix
).
toEqual
(
'
label:
'
);
expect
(
processedItems
[
1
].
tokens
[
1
].
suffix
).
toEqual
(
'
~foo
'
);
expect
(
processedItems
[
1
].
searchToken
).
toEqual
(
'
bar
'
);
afterAll
(()
=>
{
eventHub
.
$off
(
'
recentSearchesItemSelected
'
,
onRecentSearchesItemSelectedSpy
);
eventHub
.
$off
(
'
requestClearRecentSearchesSpy
'
,
onRequestClearRecentSearchesSpy
);
});
it
(
'
with no items
'
,
()
=>
{
vm
=
createComponent
(
propsDataWithoutItems
);
const
{
processedItems
}
=
vm
;
expect
(
processedItems
.
length
).
toEqual
(
0
);
});
it
(
'
does not render a note about enabling local storage
'
,
()
=>
{
expect
(
findLocalStorageNote
().
exists
()).
toBe
(
false
);
});
describe
(
'
hasItems
'
,
()
=>
{
it
(
'
with items
'
,
()
=>
{
vm
=
createComponent
(
propsDataWithItems
);
const
{
hasItems
}
=
vm
;
expect
(
hasItems
).
toEqual
(
true
);
it
(
'
does not render dropdownNote
'
,
()
=>
{
expect
(
findDropdownNote
().
exists
()).
toBe
(
false
);
});
it
(
'
with no items
'
,
()
=>
{
vm
=
createComponent
(
propsDataWithoutItems
);
const
{
hasItems
}
=
vm
;
expect
(
hasItems
).
toEqual
(
false
);
it
(
'
renders a correct amount of dropdown items
'
,
()
=>
{
expect
(
findDropdownItems
()).
toHaveLength
(
2
);
});
});
});
describe
(
'
methods
'
,
()
=>
{
describe
(
'
onItemActivated
'
,
()
=>
{
let
onRecentSearchesItemSelectedSpy
;
beforeEach
(()
=>
{
onRecentSearchesItemSelectedSpy
=
jest
.
fn
();
eventHub
.
$on
(
'
recentSearchesItemSelected
'
,
onRecentSearchesItemSelectedSpy
);
vm
=
createComponent
(
propsDataWithItems
);
it
(
'
expect second dropdown to have 2 tokens
'
,
()
=>
{
expect
(
findDropdownItems
()
.
at
(
1
)
.
findAll
(
'
.js-dropdown-token
'
),
).
toHaveLength
(
2
);
});
afterEach
(()
=>
{
eventHub
.
$off
(
'
recentSearchesItemSelected
'
,
onRecentSearchesItemSelectedSpy
);
it
(
'
emits recentSearchesItemSelected on dropdown item click
'
,
()
=>
{
findDropdownItems
()
.
at
(
0
)
.
find
(
'
.js-dropdown-button
'
)
.
trigger
(
'
click
'
);
expect
(
onRecentSearchesItemSelectedSpy
).
toHaveBeenCalledWith
(
'
foo
'
);
});
it
(
'
emits event
'
,
()
=>
{
expect
(
onRecentSearchesItemSelectedSpy
).
not
.
toHaveBeenCalled
();
vm
.
onItemActivated
(
'
something
'
);
it
(
'
emits requestClearRecentSearches on Clear resent searches button
'
,
()
=>
{
wrapper
.
find
({
ref
:
'
clearButton
'
}).
trigger
(
'
click
'
);
expect
(
onRecentSearchesItemSelectedSpy
).
toHaveBeenCalledWith
(
'
something
'
);
expect
(
onRequestClearRecentSearchesSpy
).
toHaveBeenCalled
(
);
});
});
describe
(
'
onRequestClearRecentSearches
'
,
()
=>
{
let
onRequestClearRecentSearchesSpy
;
describe
(
'
when locale storage is available and items array is empty
'
,
()
=>
{
beforeEach
(()
=>
{
onRequestClearRecentSearchesSpy
=
jest
.
fn
();
eventHub
.
$on
(
'
requestClearRecentSearches
'
,
onRequestClearRecentSearchesSpy
);
vm
=
createComponent
(
propsDataWithItems
);
createComponent
({
isLocalStorageAvailable
:
true
,
});
afterEach
(()
=>
{
eventHub
.
$off
(
'
requestClearRecentSearches
'
,
onRequestClearRecentSearchesSpy
);
});
it
(
'
emits event
'
,
()
=>
{
expect
(
onRequestClearRecentSearchesSpy
).
not
.
toHaveBeenCalled
(
);
vm
.
onRequestClearRecentSearches
({
stopPropagation
:
()
=>
{}
});
it
(
'
does not render a note about enabling local storage
'
,
()
=>
{
expect
(
findLocalStorageNote
().
exists
()).
toBe
(
false
);
});
expect
(
onRequestClearRecentSearchesSpy
).
toHaveBeenCalled
();
it
(
'
does not render dropdown items
'
,
()
=>
{
expect
(
findDropdownItems
().
exists
()).
toBe
(
false
);
});
it
(
'
renders dropdown note
'
,
()
=>
{
expect
(
findDropdownNote
().
exists
()).
toBe
(
true
);
});
});
});
spec/frontend/vue_shared/components/__snapshots__/code_block_spec.js.snap
0 → 100644
View file @
6a3b4071
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Code Block matches snapshot 1`] = `
<pre
class="code-block rounded"
>
<code
class="d-block"
>
test-code
</code>
</pre>
`;
spec/frontend/vue_shared/components/__snapshots__/identicon_spec.js.snap
0 → 100644
View file @
6a3b4071
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Identicon matches snapshot 1`] = `
<div
class="avatar identicon s40 bg2"
>
E
</div>
`;
spec/frontend/vue_shared/components/code_block_spec.js
View file @
6a3b4071
import
Vue
from
'
vue
'
;
import
component
from
'
~/vue_shared/components/code_block.vue
'
;
import
mountComponent
from
'
../../helpers/vue_mount_component_helper
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
CodeBlock
from
'
~/vue_shared/components/code_block.vue
'
;
describe
(
'
Code Block
'
,
()
=>
{
const
Component
=
Vue
.
extend
(
component
);
let
vm
;
let
wrapper
;
afterEach
(()
=>
{
vm
.
$destroy
();
});
it
(
'
renders a code block with the provided code
'
,
()
=>
{
const
code
=
"
Failure/Error: is_expected.to eq(3)
\n\n
expected: 3
\n
got: -1
\n\n
(compared using ==)
\n
./spec/test_spec.rb:12:in `block (4 levels) in
\
u003ctop (required)
\
u003e'
"
;
vm
=
mountComponent
(
Component
,
{
code
,
const
createComponent
=
()
=>
{
wrapper
=
shallowMount
(
CodeBlock
,
{
propsData
:
{
code
:
'
test-code
'
,
},
});
};
expect
(
vm
.
$el
.
querySelector
(
'
code
'
).
textContent
).
toEqual
(
code
);
afterEach
(()
=>
{
wrapper
.
destroy
();
wrapper
=
null
;
});
it
(
'
escapes XSS injections
'
,
()
=>
{
const
code
=
'
CCC<img src=x onerror=alert(document.domain)>
'
;
vm
=
mountComponent
(
Component
,
{
code
,
});
it
(
'
matches snapshot
'
,
()
=>
{
createComponent
();
expect
(
vm
.
$el
.
querySelector
(
'
code
'
).
textContent
).
toEqual
(
code
);
expect
(
wrapper
.
element
).
toMatchSnapshot
(
);
});
});
spec/frontend/vue_shared/components/identicon_spec.js
View file @
6a3b4071
import
Vue
from
'
vue
'
;
import
i
denticonComponent
from
'
~/vue_shared/components/identicon.vue
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
I
denticonComponent
from
'
~/vue_shared/components/identicon.vue
'
;
const
createComponent
=
sizeClass
=>
{
const
Component
=
Vue
.
extend
(
identiconComponent
)
;
describe
(
'
Identicon
'
,
()
=>
{
let
wrapper
;
return
new
Component
({
const
createComponent
=
()
=>
{
wrapper
=
shallowMount
(
IdenticonComponent
,
{
propsData
:
{
entityId
:
1
,
entityName
:
'
entity-name
'
,
sizeClass
,
sizeClass
:
'
s40
'
,
},
}).
$mount
();
};
describe
(
'
IdenticonComponent
'
,
()
=>
{
describe
(
'
computed
'
,
()
=>
{
let
vm
;
beforeEach
(()
=>
{
vm
=
createComponent
();
});
};
afterEach
(()
=>
{
vm
.
$destroy
();
});
describe
(
'
identiconBackgroundClass
'
,
()
=>
{
it
(
'
should return bg class based on entityId
'
,
()
=>
{
vm
.
entityId
=
4
;
expect
(
vm
.
identiconBackgroundClass
).
toBeDefined
();
expect
(
vm
.
identiconBackgroundClass
).
toBe
(
'
bg5
'
);
});
wrapper
.
destroy
();
wrapper
=
null
;
});
describe
(
'
identiconTitle
'
,
()
=>
{
it
(
'
should return first letter of entity title in uppercase
'
,
()
=>
{
vm
.
entityName
=
'
dummy-group
'
;
it
(
'
matches snapshot
'
,
()
=>
{
createComponent
();
expect
(
vm
.
identiconTitle
).
toBeDefined
();
expect
(
vm
.
identiconTitle
).
toBe
(
'
D
'
);
expect
(
wrapper
.
element
).
toMatchSnapshot
();
});
});
});
describe
(
'
template
'
,
()
=>
{
it
(
'
should render identicon
'
,
()
=>
{
const
vm
=
createComponent
();
expect
(
vm
.
$el
.
nodeName
).
toBe
(
'
DIV
'
);
expect
(
vm
.
$el
.
classList
.
contains
(
'
identicon
'
)).
toBeTruthy
();
expect
(
vm
.
$el
.
classList
.
contains
(
'
s40
'
)).
toBeTruthy
();
expect
(
vm
.
$el
.
classList
.
contains
(
'
bg2
'
)).
toBeTruthy
();
vm
.
$destroy
();
});
it
(
'
should render identicon with provided sizing class
'
,
()
=>
{
const
vm
=
createComponent
(
'
s32
'
);
it
(
'
adds a correct class to identicon
'
,
()
=>
{
createComponent
();
expect
(
vm
.
$el
.
classList
.
contains
(
'
s32
'
)).
toBeTruthy
();
vm
.
$destroy
();
});
expect
(
wrapper
.
find
({
ref
:
'
identicon
'
}).
classes
()).
toContain
(
'
bg2
'
);
});
});
spec/frontend/vue_shared/components/issue/__snapshots__/issue_warning_spec.js.snap
0 → 100644
View file @
6a3b4071
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Issue Warning Component when issue is confidential but not locked renders information about confidential issue 1`] = `
<span>
This is a confidential issue.
People without permission will never get a notification.
<gl-link-stub
href="confidential-path"
target="_blank"
>
Learn more
</gl-link-stub>
</span>
`;
exports[`Issue Warning Component when issue is locked and confidential renders information about locked and confidential issue 1`] = `
<span>
<span>
This issue is
<a
href=""
rel="noopener noreferrer"
target="_blank"
>
confidential
</a>
and
<a
href=""
rel="noopener noreferrer"
target="_blank"
>
locked
</a>
.
</span>
People without permission will never get a notification and won't be able to comment.
</span>
`;
exports[`Issue Warning Component when issue is locked but not confidential renders information about locked issue 1`] = `
<span>
This issue is locked.
Only project members can comment.
<gl-link-stub
href="locked-path"
target="_blank"
>
Learn more
</gl-link-stub>
</span>
`;
spec/frontend/vue_shared/components/issue/issue_warning_spec.js
View file @
6a3b4071
import
Vue
from
'
vue
'
;
import
mountComponent
from
'
helpers/vue_mount_component_helper
'
;
import
issueWarning
from
'
~/vue_shared/components/issue/issue_warning
.vue
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
IssueWarning
from
'
~/vue_shared/components/issue/issue_warning.vue
'
;
import
Icon
from
'
~/vue_shared/components/icon
.vue
'
;
const
IssueWarning
=
Vue
.
extend
(
issueWarning
);
describe
(
'
Issue Warning Component
'
,
()
=>
{
let
wrapper
;
function
formatWarning
(
string
)
{
// Replace newlines with a space then replace multiple spaces with one space
return
string
.
trim
()
.
replace
(
/
\n
/g
,
'
'
)
.
replace
(
/
\s\s
+/g
,
'
'
);
}
const
findIcon
=
()
=>
wrapper
.
find
(
Icon
);
const
findLockedBlock
=
()
=>
wrapper
.
find
({
ref
:
'
locked
'
});
const
findConfidentialBlock
=
()
=>
wrapper
.
find
({
ref
:
'
confidential
'
});
const
findLockedAndConfidentialBlock
=
()
=>
wrapper
.
find
({
ref
:
'
lockedAndConfidential
'
});
describe
(
'
Issue Warning Component
'
,
()
=>
{
describe
(
'
isLocked
'
,
()
=>
{
it
(
'
should render locked issue warning information
'
,
()
=>
{
const
props
=
{
isLocked
:
true
,
lockedIssueDocsPath
:
'
docs/issues/locked
'
,
const
createComponent
=
props
=>
{
wrapper
=
shallowMount
(
IssueWarning
,
{
propsData
:
{
...
props
,
}
,
});
};
const
vm
=
mountComponent
(
IssueWarning
,
props
);
expect
(
vm
.
$el
.
querySelector
(
'
.icon use
'
).
getAttributeNS
(
'
http://www.w3.org/1999/xlink
'
,
'
href
'
),
).
toMatch
(
/lock$/
);
expect
(
formatWarning
(
vm
.
$el
.
querySelector
(
'
span
'
).
textContent
)).
toEqual
(
'
This issue is locked. Only project members can comment. Learn more
'
,
);
expect
(
vm
.
$el
.
querySelector
(
'
a
'
).
href
).
toContain
(
props
.
lockedIssueDocsPath
);
afterEach
(()
=>
{
wrapper
.
destroy
();
wrapper
=
null
;
});
describe
(
'
when issue is locked but not confidential
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
({
isLocked
:
true
,
lockedIssueDocsPath
:
'
locked-path
'
,
isConfidential
:
false
,
});
});
it
(
'
renders information about locked issue
'
,
()
=>
{
expect
(
findLockedBlock
().
exists
()).
toBe
(
true
);
expect
(
findLockedBlock
().
element
).
toMatchSnapshot
();
});
it
(
'
renders warning icon
'
,
()
=>
{
expect
(
findIcon
().
exists
()).
toBe
(
true
);
});
it
(
'
does not render information about locked and confidential issue
'
,
()
=>
{
expect
(
findLockedAndConfidentialBlock
().
exists
()).
toBe
(
false
);
});
it
(
'
does not render information about confidential issue
'
,
()
=>
{
expect
(
findConfidentialBlock
().
exists
()).
toBe
(
false
);
});
});
describe
(
'
isConfidential
'
,
()
=>
{
it
(
'
should render confidential issue warning information
'
,
()
=>
{
const
props
=
{
describe
(
'
when issue is confidential but not locked
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
({
isLocked
:
false
,
isConfidential
:
true
,
confidentialIssueDocsPath
:
'
/docs/issues/confidential
'
,
};
const
vm
=
mountComponent
(
IssueWarning
,
props
);
confidentialIssueDocsPath
:
'
confidential-path
'
,
});
});
it
(
'
renders information about confidential issue
'
,
()
=>
{
expect
(
findConfidentialBlock
().
exists
()).
toBe
(
true
);
expect
(
findConfidentialBlock
().
element
).
toMatchSnapshot
();
});
it
(
'
renders warning icon
'
,
()
=>
{
expect
(
wrapper
.
find
(
Icon
).
exists
()).
toBe
(
true
);
});
it
(
'
does not render information about locked issue
'
,
()
=>
{
expect
(
findLockedBlock
().
exists
()).
toBe
(
false
);
});
expect
(
vm
.
$el
.
querySelector
(
'
.icon use
'
).
getAttributeNS
(
'
http://www.w3.org/1999/xlink
'
,
'
href
'
),
).
toMatch
(
/eye-slash$/
);
expect
(
formatWarning
(
vm
.
$el
.
querySelector
(
'
span
'
).
textContent
)).
toEqual
(
'
This is a confidential issue. People without permission will never get a notification. Learn more
'
,
);
expect
(
vm
.
$el
.
querySelector
(
'
a
'
).
href
).
toContain
(
props
.
confidentialIssueDocsPath
);
it
(
'
does not render information about locked and confidential issue
'
,
()
=>
{
expect
(
findLockedAndConfidentialBlock
().
exists
()).
toBe
(
false
);
});
});
describe
(
'
isLocked and isC
onfidential
'
,
()
=>
{
it
(
'
should render locked and confidential issue warning information
'
,
()
=>
{
c
onst
vm
=
mountComponent
(
IssueWarning
,
{
describe
(
'
when issue is locked and c
onfidential
'
,
()
=>
{
beforeEach
(
()
=>
{
c
reateComponent
(
{
isLocked
:
true
,
isConfidential
:
true
,
});
});
it
(
'
renders information about locked and confidential issue
'
,
()
=>
{
expect
(
findLockedAndConfidentialBlock
().
exists
()).
toBe
(
true
);
expect
(
findLockedAndConfidentialBlock
().
element
).
toMatchSnapshot
();
});
it
(
'
does not render warning icon
'
,
()
=>
{
expect
(
wrapper
.
find
(
Icon
).
exists
()).
toBe
(
false
);
});
it
(
'
does not render information about locked issue
'
,
()
=>
{
expect
(
findLockedBlock
().
exists
()).
toBe
(
false
);
});
expect
(
vm
.
$el
.
querySelector
(
'
.icon
'
)).
toBeFalsy
();
expect
(
formatWarning
(
vm
.
$el
.
querySelector
(
'
span
'
).
textContent
)).
toEqual
(
"
This issue is confidential and locked. People without permission will never get a notification and won't be able to comment.
"
,
);
it
(
'
does not render information about confidential issue
'
,
()
=>
{
expect
(
findConfidentialBlock
().
exists
()).
toBe
(
false
);
});
});
});
spec/frontend/vue_shared/components/markdown/__snapshots__/suggestion_diff_spec.js.snap
0 → 100644
View file @
6a3b4071
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Suggestion Diff component matches snapshot 1`] = `
<div
class="md-suggestion"
>
<suggestion-diff-header-stub
class="qa-suggestion-diff-header js-suggestion-diff-header"
helppagepath="path_to_docs"
/>
<table
class="mb-3 md-suggestion-diff js-syntax-highlight code"
>
<tbody>
<suggestion-diff-row-stub
line="[object Object]"
/>
<suggestion-diff-row-stub
line="[object Object]"
/>
<suggestion-diff-row-stub
line="[object Object]"
/>
</tbody>
</table>
</div>
`;
spec/frontend/vue_shared/components/markdown/suggestion_diff_spec.js
View file @
6a3b4071
import
Vue
from
'
vue
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
SuggestionDiffComponent
from
'
~/vue_shared/components/markdown/suggestion_diff.vue
'
;
import
{
selectDiffLines
}
from
'
~/vue_shared/components/lib/utils/diff_utils
'
;
import
SuggestionDiffHeader
from
'
~/vue_shared/components/markdown/suggestion_diff_header.vue
'
;
import
SuggestionDiffRow
from
'
~/vue_shared/components/markdown/suggestion_diff_row.vue
'
;
const
MOCK_DATA
=
{
canApply
:
true
,
suggestion
:
{
id
:
1
,
diff_lines
:
[
...
...
@@ -42,60 +42,45 @@ const MOCK_DATA = {
helpPagePath
:
'
path_to_docs
'
,
};
const
lines
=
selectDiffLines
(
MOCK_DATA
.
suggestion
.
diff_lines
);
const
newLines
=
lines
.
filter
(
line
=>
line
.
type
===
'
new
'
);
describe
(
'
Suggestion Diff component
'
,
()
=>
{
let
vm
;
beforeEach
(
done
=>
{
const
Component
=
Vue
.
extend
(
SuggestionDiffComponent
);
let
wrapper
;
vm
=
new
Component
(
{
propsData
:
MOCK_DATA
,
}).
$mount
();
Vue
.
nextTick
(
done
);
const
createComponent
=
()
=>
{
wrapper
=
shallowMount
(
SuggestionDiffComponent
,
{
propsData
:
{
...
MOCK_DATA
,
},
});
};
describe
(
'
init
'
,
()
=>
{
it
(
'
renders a suggestion header
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.js-suggestion-diff-header
'
)).
not
.
toBeNull
();
beforeEach
(()
=>
{
createComponent
();
});
it
(
'
renders a diff table with syntax highlighting
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.md-suggestion-diff.js-syntax-highlight.code
'
)).
not
.
toBeNull
();
afterEach
(()
=>
{
wrapper
.
destroy
();
wrapper
=
null
;
});
it
(
'
renders the oldLineNumber
'
,
()
=>
{
const
fromLine
=
vm
.
$el
.
querySelector
(
'
.old_line
'
).
innerHTML
;
expect
(
parseInt
(
fromLine
,
10
)).
toBe
(
lines
[
0
].
old_line
);
it
(
'
matches snapshot
'
,
()
=>
{
expect
(
wrapper
.
element
).
toMatchSnapshot
();
});
it
(
'
renders the oldLineContent
'
,
()
=>
{
const
fromContent
=
vm
.
$el
.
querySelector
(
'
.line_content.old
'
).
innerHTML
;
expect
(
fromContent
.
includes
(
lines
[
0
].
text
)).
toBe
(
true
);
it
(
'
renders a correct amount of suggestion diff rows
'
,
()
=>
{
expect
(
wrapper
.
findAll
(
SuggestionDiffRow
)).
toHaveLength
(
3
);
});
it
(
'
renders new lines
'
,
()
=>
{
const
newLinesElements
=
vm
.
$el
.
querySelectorAll
(
'
.line_holder.new
'
);
it
(
'
emits apply event on sugestion diff header apply
'
,
()
=>
{
wrapper
.
find
(
SuggestionDiffHeader
).
vm
.
$emit
(
'
apply
'
,
'
test-event
'
);
newLinesElements
.
forEach
((
line
,
i
)
=>
{
expect
(
newLinesElements
[
i
].
innerHTML
.
includes
(
newLines
[
i
].
new_line
)).
toBe
(
true
);
expect
(
newLinesElements
[
i
].
innerHTML
.
includes
(
newLines
[
i
].
text
)).
toBe
(
true
);
});
});
});
describe
(
'
applySuggestion
'
,
()
=>
{
it
(
'
emits apply event when applySuggestion is called
'
,
()
=>
{
const
callback
=
()
=>
{};
jest
.
spyOn
(
vm
,
'
$emit
'
).
mockImplementation
(()
=>
{});
vm
.
applySuggestion
(
callback
);
expect
(
vm
.
$emit
).
toHaveBeenCalledWith
(
'
apply
'
,
{
suggestionId
:
vm
.
suggestion
.
id
,
callback
});
});
expect
(
wrapper
.
emitted
(
'
apply
'
)).
toBeDefined
();
expect
(
wrapper
.
emitted
(
'
apply
'
)).
toEqual
([
[
{
callback
:
'
test-event
'
,
suggestionId
:
1
,
},
],
]);
});
});
spec/frontend/vue_shared/components/notes/__snapshots__/placeholder_note_spec.js.snap
0 → 100644
View file @
6a3b4071
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Issue placeholder note component matches snapshot 1`] = `
<timeline-entry-item-stub
class="note note-wrapper being-posted fade-in-half"
>
<div
class="timeline-icon"
>
<user-avatar-link-stub
imgalt=""
imgcssclasses=""
imgsize="40"
imgsrc="mock_path"
linkhref="/root"
tooltipplacement="top"
tooltiptext=""
username=""
/>
</div>
<div
class="timeline-content discussion"
>
<div
class="note-header"
>
<div
class="note-header-info"
>
<a
href="/root"
>
<span
class="d-none d-sm-inline-block bold"
>
Root
</span>
<span
class="note-headline-light"
>
@root
</span>
</a>
</div>
</div>
<div
class="note-body"
>
<div
class="note-text md"
>
<p>
Foo
</p>
</div>
</div>
</div>
</timeline-entry-item-stub>
`;
spec/frontend/vue_shared/components/notes/__snapshots__/placeholder_system_note_spec.js.snap
0 → 100644
View file @
6a3b4071
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Placeholder system note component matches snapshot 1`] = `
<timeline-entry-item-stub
class="note system-note being-posted fade-in-half"
>
<div
class="timeline-content"
>
<em>
This is a placeholder
</em>
</div>
</timeline-entry-item-stub>
`;
spec/frontend/vue_shared/components/notes/placeholder_note_spec.js
View file @
6a3b4071
import
Vue
from
'
vue
'
;
import
issuePlaceholderNote
from
'
~/vue_shared/components/notes/placeholder_note.vue
'
;
import
createStore
from
'
~/notes/stores
'
;
import
{
shallowMount
,
createLocalVue
}
from
'
@vue/test-utils
'
;
import
Vuex
from
'
vuex
'
;
import
IssuePlaceholderNote
from
'
~/vue_shared/components/notes/placeholder_note.vue
'
;
import
{
userDataMock
}
from
'
../../../notes/mock_data
'
;
describe
(
'
issue placeholder system note component
'
,
()
=>
{
let
store
;
let
vm
;
beforeEach
(()
=>
{
const
Component
=
Vue
.
extend
(
issuePlaceholderNote
);
store
=
createStore
();
store
.
dispatch
(
'
setUserData
'
,
userDataMock
);
vm
=
new
Component
({
store
,
propsData
:
{
note
:
{
body
:
'
Foo
'
}
},
}).
$mount
();
const
localVue
=
createLocalVue
();
localVue
.
use
(
Vuex
);
const
getters
=
{
getUserData
:
()
=>
userDataMock
,
};
describe
(
'
Issue placeholder note component
'
,
()
=>
{
let
wrapper
;
const
findNote
=
()
=>
wrapper
.
find
({
ref
:
'
note
'
});
const
createComponent
=
(
isIndividual
=
false
)
=>
{
wrapper
=
shallowMount
(
IssuePlaceholderNote
,
{
localVue
,
store
:
new
Vuex
.
Store
({
getters
,
}),
propsData
:
{
note
:
{
body
:
'
Foo
'
,
individual_note
:
isIndividual
,
},
},
});
};
afterEach
(()
=>
{
vm
.
$destroy
();
wrapper
.
destroy
();
wrapper
=
null
;
});
describe
(
'
user information
'
,
()
=>
{
it
(
'
should render user avatar with link
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.user-avatar-link
'
).
getAttribute
(
'
href
'
)).
toEqual
(
userDataMock
.
path
,
);
it
(
'
matches snapshot
'
,
()
=>
{
createComponent
();
expect
(
vm
.
$el
.
querySelector
(
'
.user-avatar-link img
'
).
getAttribute
(
'
src
'
)).
toEqual
(
`
${
userDataMock
.
avatar_url
}
?width=40`
,
);
});
expect
(
wrapper
.
element
).
toMatchSnapshot
();
});
describe
(
'
note content
'
,
()
=>
{
it
(
'
should render note header information
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.note-header-info a
'
).
getAttribute
(
'
href
'
)).
toEqual
(
userDataMock
.
path
,
);
it
(
'
does not add "discussion" class to individual notes
'
,
()
=>
{
createComponent
(
true
);
expect
(
vm
.
$el
.
querySelector
(
'
.note-header-info .note-headline-light
'
).
textContent
.
trim
(),
).
toEqual
(
`@
${
userDataMock
.
username
}
`
);
expect
(
findNote
().
classes
()).
not
.
toContain
(
'
discussion
'
);
});
it
(
'
should render note body
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.note-text p
'
).
textContent
.
trim
()).
toEqual
(
'
Foo
'
);
});
it
(
'
adds "discussion" class to non-individual notes
'
,
()
=>
{
createComponent
();
expect
(
findNote
().
classes
()).
toContain
(
'
discussion
'
);
});
});
spec/frontend/vue_shared/components/notes/placeholder_system_note_spec.js
View file @
6a3b4071
import
Vue
from
'
vue
'
;
import
mountComponent
from
'
helpers/vue_mount_component_helper
'
;
import
placeholderSystemNote
from
'
~/vue_shared/components/notes/placeholder_system_note.vue
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
PlaceholderSystemNote
from
'
~/vue_shared/components/notes/placeholder_system_note.vue
'
;
describe
(
'
placeholder system note component
'
,
()
=>
{
let
PlaceholderSystemNote
;
let
vm
;
describe
(
'
Placeholder system note component
'
,
()
=>
{
let
wrapper
;
beforeEach
(()
=>
{
PlaceholderSystemNote
=
Vue
.
extend
(
placeholderSystemNote
);
const
createComponent
=
()
=>
{
wrapper
=
shallowMount
(
PlaceholderSystemNote
,
{
propsData
:
{
note
:
{
body
:
'
This is a placeholder
'
},
},
});
};
afterEach
(()
=>
{
vm
.
$destroy
();
wrapper
.
destroy
();
wrapper
=
null
;
});
it
(
'
should render system note placeholder with plain text
'
,
()
=>
{
vm
=
mountComponent
(
PlaceholderSystemNote
,
{
note
:
{
body
:
'
This is a placeholder
'
},
});
it
(
'
matches snapshot
'
,
()
=>
{
createComponent
();
expect
(
vm
.
$el
.
tagName
).
toEqual
(
'
LI
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.timeline-content em
'
).
textContent
.
trim
()).
toEqual
(
'
This is a placeholder
'
,
);
expect
(
wrapper
.
element
).
toMatchSnapshot
();
});
});
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