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
0
Merge Requests
0
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
Jérome Perrin
gitlab-ce
Commits
925eea26
Commit
925eea26
authored
Jun 23, 2017
by
Winnie Hellmann
Committed by
Phil Hughes
Jun 23, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make JavaScript tests fail for unhandled Promise rejections
parent
9c7bf123
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
257 additions
and
160 deletions
+257
-160
app/assets/javascripts/boards/components/board_new_issue.js
app/assets/javascripts/boards/components/board_new_issue.js
+5
-5
app/assets/javascripts/boards/models/list.js
app/assets/javascripts/boards/models/list.js
+1
-2
app/assets/javascripts/filtered_search/filtered_search_manager.js
...ts/javascripts/filtered_search/filtered_search_manager.js
+4
-0
spec/javascripts/boards/board_new_issue_spec.js
spec/javascripts/boards/board_new_issue_spec.js
+100
-103
spec/javascripts/boards/list_spec.js
spec/javascripts/boards/list_spec.js
+37
-0
spec/javascripts/filtered_search/filtered_search_manager_spec.js
...vascripts/filtered_search/filtered_search_manager_spec.js
+47
-11
spec/javascripts/issue_show/components/app_spec.js
spec/javascripts/issue_show/components/app_spec.js
+46
-39
spec/javascripts/test_bundle.js
spec/javascripts/test_bundle.js
+17
-0
No files found.
app/assets/javascripts/boards/components/board_new_issue.js
View file @
925eea26
...
...
@@ -17,7 +17,7 @@ export default {
methods
:
{
submit
(
e
)
{
e
.
preventDefault
();
if
(
this
.
title
.
trim
()
===
''
)
return
;
if
(
this
.
title
.
trim
()
===
''
)
return
Promise
.
resolve
()
;
this
.
error
=
false
;
...
...
@@ -29,7 +29,10 @@ export default {
assignees
:
[],
});
this
.
list
.
newIssue
(
issue
)
eventHub
.
$emit
(
`scroll-board-list-
${
this
.
list
.
id
}
`
);
this
.
cancel
();
return
this
.
list
.
newIssue
(
issue
)
.
then
(()
=>
{
// Need this because our jQuery very kindly disables buttons on ALL form submissions
$
(
this
.
$refs
.
submitButton
).
enable
();
...
...
@@ -47,9 +50,6 @@ export default {
// Show error message
this
.
error
=
true
;
});
eventHub
.
$emit
(
`scroll-board-list-
${
this
.
list
.
id
}
`
);
this
.
cancel
();
},
cancel
()
{
this
.
title
=
''
;
...
...
app/assets/javascripts/boards/models/list.js
View file @
925eea26
...
...
@@ -112,8 +112,7 @@ class List {
.
then
((
resp
)
=>
{
const
data
=
resp
.
json
();
issue
.
id
=
data
.
iid
;
})
.
then
(()
=>
{
if
(
this
.
issuesSize
>
1
)
{
const
moveBeforeIid
=
this
.
issues
[
1
].
id
;
gl
.
boardService
.
moveIssue
(
issue
.
id
,
null
,
null
,
null
,
moveBeforeIid
);
...
...
app/assets/javascripts/filtered_search/filtered_search_manager.js
View file @
925eea26
...
...
@@ -40,6 +40,10 @@ class FilteredSearchManager {
return
[];
})
.
then
((
searches
)
=>
{
if
(
!
searches
)
{
return
;
}
// Put any searches that may have come in before
// we fetched the saved searches ahead of the already saved ones
const
resultantSearches
=
this
.
recentSearchesStore
.
setRecentSearches
(
...
...
spec/javascripts/boards/board_new_issue_spec.js
View file @
925eea26
...
...
@@ -12,6 +12,7 @@ import './mock_data';
describe
(
'
Issue boards new issue form
'
,
()
=>
{
let
vm
;
let
list
;
let
newIssueMock
;
const
promiseReturn
=
{
json
()
{
return
{
...
...
@@ -21,7 +22,11 @@ describe('Issue boards new issue form', () => {
};
const
submitIssue
=
()
=>
{
vm
.
$el
.
querySelector
(
'
.btn-success
'
).
click
();
const
dummySubmitEvent
=
{
preventDefault
()
{},
};
vm
.
$refs
.
submitButton
=
vm
.
$el
.
querySelector
(
'
.btn-success
'
);
return
vm
.
submit
(
dummySubmitEvent
);
};
beforeEach
((
done
)
=>
{
...
...
@@ -32,29 +37,35 @@ describe('Issue boards new issue form', () => {
gl
.
issueBoards
.
BoardsStore
.
create
();
gl
.
IssueBoardsApp
=
new
Vue
();
setTimeout
(()
=>
{
list
=
new
List
(
listObj
);
spyOn
(
gl
.
boardService
,
'
newIssue
'
).
and
.
callFake
(()
=>
new
Promise
((
resolve
,
reject
)
=>
{
if
(
vm
.
title
===
'
error
'
)
{
reject
();
}
else
{
resolve
(
promiseReturn
);
}
}));
vm
=
new
BoardNewIssueComp
({
propsData
:
{
list
,
},
}).
$mount
();
done
();
},
0
);
list
=
new
List
(
listObj
);
newIssueMock
=
Promise
.
resolve
(
promiseReturn
);
spyOn
(
list
,
'
newIssue
'
).
and
.
callFake
(()
=>
newIssueMock
);
vm
=
new
BoardNewIssueComp
({
propsData
:
{
list
,
},
}).
$mount
();
Vue
.
nextTick
()
.
then
(
done
)
.
catch
(
done
.
fail
);
});
afterEach
(()
=>
{
Vue
.
http
.
interceptors
=
_
.
without
(
Vue
.
http
.
interceptors
,
boardsMockInterceptor
);
it
(
'
calls submit if submit button is clicked
'
,
(
done
)
=>
{
spyOn
(
vm
,
'
submit
'
);
vm
.
title
=
'
Testing Title
'
;
Vue
.
nextTick
()
.
then
(()
=>
{
vm
.
$el
.
querySelector
(
'
.btn-success
'
).
click
();
expect
(
vm
.
submit
.
calls
.
count
()).
toBe
(
1
);
expect
(
vm
.
$refs
[
'
submit-button
'
]).
toBe
(
vm
.
$el
.
querySelector
(
'
.btn-success
'
));
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
it
(
'
disables submit button if title is empty
'
,
()
=>
{
...
...
@@ -64,136 +75,122 @@ describe('Issue boards new issue form', () => {
it
(
'
enables submit button if title is not empty
'
,
(
done
)
=>
{
vm
.
title
=
'
Testing Title
'
;
setTimeout
(()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.form-control
'
).
value
).
toBe
(
'
Testing Title
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.btn-success
'
).
disabled
).
not
.
toBe
(
true
);
done
();
},
0
);
Vue
.
nextTick
()
.
then
(()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.form-control
'
).
value
).
toBe
(
'
Testing Title
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.btn-success
'
).
disabled
).
not
.
toBe
(
true
);
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
it
(
'
clears title after clicking cancel
'
,
(
done
)
=>
{
vm
.
$el
.
querySelector
(
'
.btn-default
'
).
click
();
setTimeout
(()
=>
{
expect
(
vm
.
title
).
toBe
(
''
);
done
();
},
0
);
Vue
.
nextTick
()
.
then
(()
=>
{
expect
(
vm
.
title
).
toBe
(
''
);
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
it
(
'
does not create new issue if title is empty
'
,
(
done
)
=>
{
submitIssue
()
;
setTimeout
(()
=>
{
expect
(
gl
.
boardService
.
newIssue
).
not
.
toHaveBeenCalled
();
done
();
},
0
);
submitIssue
()
.
then
(()
=>
{
expect
(
list
.
newIssue
).
not
.
toHaveBeenCalled
();
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
describe
(
'
submit success
'
,
()
=>
{
it
(
'
creates new issue
'
,
(
done
)
=>
{
vm
.
title
=
'
submit title
'
;
setTimeout
(()
=>
{
submitIssue
();
expect
(
gl
.
boardService
.
newIssue
).
toHaveBeenCalled
();
done
();
},
0
);
Vue
.
nextTick
()
.
then
(
submitIssue
)
.
then
(()
=>
{
expect
(
list
.
newIssue
).
toHaveBeenCalled
();
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
it
(
'
enables button after submit
'
,
(
done
)
=>
{
vm
.
title
=
'
submit issue
'
;
setTimeout
(()
=>
{
submitIssue
();
expect
(
vm
.
$el
.
querySelector
(
'
.btn-success
'
).
disabled
).
toBe
(
false
);
done
();
},
0
);
Vue
.
nextTick
()
.
then
(
submitIssue
)
.
then
(()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.btn-success
'
).
disabled
).
toBe
(
false
);
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
it
(
'
clears title after submit
'
,
(
done
)
=>
{
vm
.
title
=
'
submit issue
'
;
Vue
.
nextTick
(()
=>
{
submitIssue
();
setTimeout
(()
=>
{
Vue
.
nextTick
()
.
then
(
submitIssue
)
.
then
(()
=>
{
expect
(
vm
.
title
).
toBe
(
''
);
done
();
},
0
);
});
});
it
(
'
adds new issue to top of list after submit request
'
,
(
done
)
=>
{
vm
.
title
=
'
submit issue
'
;
setTimeout
(()
=>
{
submitIssue
();
setTimeout
(()
=>
{
expect
(
list
.
issues
.
length
).
toBe
(
2
);
expect
(
list
.
issues
[
0
].
title
).
toBe
(
'
submit issue
'
);
expect
(
list
.
issues
[
0
].
subscribed
).
toBe
(
true
);
done
();
},
0
);
},
0
);
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
it
(
'
sets detail issue after submit
'
,
(
done
)
=>
{
expect
(
gl
.
issueBoards
.
BoardsStore
.
detail
.
issue
.
title
).
toBe
(
undefined
);
vm
.
title
=
'
submit issue
'
;
setTimeout
(()
=>
{
submitIssue
();
setTimeout
(()
=>
{
Vue
.
nextTick
()
.
then
(
submitIssue
)
.
then
(()
=>
{
expect
(
gl
.
issueBoards
.
BoardsStore
.
detail
.
issue
.
title
).
toBe
(
'
submit issue
'
);
done
();
},
0
);
},
0
);
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
it
(
'
sets detail list after submit
'
,
(
done
)
=>
{
vm
.
title
=
'
submit issue
'
;
setTimeout
(()
=>
{
submitIssue
();
setTimeout
(()
=>
{
Vue
.
nextTick
()
.
then
(
submitIssue
)
.
then
(()
=>
{
expect
(
gl
.
issueBoards
.
BoardsStore
.
detail
.
list
.
id
).
toBe
(
list
.
id
);
done
();
},
0
);
},
0
);
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
});
describe
(
'
submit error
'
,
()
=>
{
it
(
'
removes issue
'
,
(
done
)
=>
{
beforeEach
(()
=>
{
newIssueMock
=
Promise
.
reject
(
new
Error
(
'
My hovercraft is full of eels!
'
));
vm
.
title
=
'
error
'
;
});
setTimeout
((
)
=>
{
submitIssue
();
setTimeout
(()
=>
{
it
(
'
removes issue
'
,
(
done
)
=>
{
Vue
.
nextTick
()
.
then
(
submitIssue
)
.
then
(()
=>
{
expect
(
list
.
issues
.
length
).
toBe
(
1
);
done
();
},
0
);
},
0
);
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
it
(
'
shows error
'
,
(
done
)
=>
{
vm
.
title
=
'
error
'
;
setTimeout
(()
=>
{
submitIssue
();
setTimeout
(()
=>
{
Vue
.
nextTick
()
.
then
(
submitIssue
)
.
then
(()
=>
{
expect
(
vm
.
error
).
toBe
(
true
);
done
();
},
0
);
},
0
);
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
});
});
spec/javascripts/boards/list_spec.js
View file @
925eea26
...
...
@@ -150,4 +150,41 @@ describe('List model', () => {
expect
(
list
.
getIssues
).
toHaveBeenCalled
();
});
});
describe
(
'
newIssue
'
,
()
=>
{
beforeEach
(()
=>
{
spyOn
(
gl
.
boardService
,
'
newIssue
'
).
and
.
returnValue
(
Promise
.
resolve
({
json
()
{
return
{
iid
:
42
,
};
},
}));
});
it
(
'
adds new issue to top of list
'
,
(
done
)
=>
{
list
.
issues
.
push
(
new
ListIssue
({
title
:
'
Testing
'
,
iid
:
_
.
random
(
10000
),
confidential
:
false
,
labels
:
[
list
.
label
],
assignees
:
[],
}));
const
dummyIssue
=
new
ListIssue
({
title
:
'
new issue
'
,
iid
:
_
.
random
(
10000
),
confidential
:
false
,
labels
:
[
list
.
label
],
assignees
:
[],
});
list
.
newIssue
(
dummyIssue
)
.
then
(()
=>
{
expect
(
list
.
issues
.
length
).
toBe
(
2
);
expect
(
list
.
issues
[
0
]).
toBe
(
dummyIssue
);
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
});
});
spec/javascripts/filtered_search/filtered_search_manager_spec.js
View file @
925eea26
...
...
@@ -48,18 +48,23 @@ describe('Filtered Search Manager', () => {
</div>
`
);
spyOn
(
gl
.
FilteredSearchDropdownManager
.
prototype
,
'
setDropdown
'
).
and
.
callFake
(()
=>
{});
});
const
initializeManager
=
()
=>
{
/* eslint-disable jasmine/no-unsafe-spy */
spyOn
(
gl
.
FilteredSearchManager
.
prototype
,
'
loadSearchParamsFromURL
'
).
and
.
callFake
(()
=>
{});
spyOn
(
gl
.
FilteredSearchManager
.
prototype
,
'
tokenChange
'
).
and
.
callFake
(()
=>
{});
spyOn
(
gl
.
FilteredSearchDropdownManager
.
prototype
,
'
setDropdown
'
).
and
.
callFake
(()
=>
{});
spyOn
(
gl
.
FilteredSearchDropdownManager
.
prototype
,
'
updateDropdownOffset
'
).
and
.
callFake
(()
=>
{});
spyOn
(
gl
.
utils
,
'
getParameterByName
'
).
and
.
returnValue
(
null
);
spyOn
(
gl
.
FilteredSearchVisualTokens
,
'
unselectTokens
'
).
and
.
callThrough
();
/* eslint-enable jasmine/no-unsafe-spy */
input
=
document
.
querySelector
(
'
.filtered-search
'
);
tokensContainer
=
document
.
querySelector
(
'
.tokens-container
'
);
manager
=
new
gl
.
FilteredSearchManager
();
manager
.
setup
();
}
)
;
};
afterEach
(()
=>
{
manager
.
cleanup
();
...
...
@@ -67,33 +72,34 @@ describe('Filtered Search Manager', () => {
describe
(
'
class constructor
'
,
()
=>
{
const
isLocalStorageAvailable
=
'
isLocalStorageAvailable
'
;
let
filteredSearchManager
;
beforeEach
(()
=>
{
spyOn
(
RecentSearchesService
,
'
isAvailable
'
).
and
.
returnValue
(
isLocalStorageAvailable
);
spyOn
(
recentSearchesStoreSrc
,
'
default
'
);
spyOn
(
RecentSearchesRoot
.
prototype
,
'
render
'
);
filteredSearchManager
=
new
gl
.
FilteredSearchManager
();
filteredSearchManager
.
setup
();
return
filteredSearchManager
;
});
it
(
'
should instantiate RecentSearchesStore with isLocalStorageAvailable
'
,
()
=>
{
manager
=
new
gl
.
FilteredSearchManager
();
expect
(
RecentSearchesService
.
isAvailable
).
toHaveBeenCalled
();
expect
(
recentSearchesStoreSrc
.
default
).
toHaveBeenCalledWith
({
isLocalStorageAvailable
,
allowedKeys
:
gl
.
FilteredSearchTokenKeys
.
getKeys
(),
});
});
});
describe
(
'
setup
'
,
()
=>
{
beforeEach
(()
=>
{
manager
=
new
gl
.
FilteredSearchManager
();
});
it
(
'
should not instantiate Flash if an RecentSearchesServiceError is caught
'
,
()
=>
{
spyOn
(
RecentSearchesService
.
prototype
,
'
fetch
'
).
and
.
callFake
(()
=>
Promise
.
reject
(
new
RecentSearchesServiceError
()));
spyOn
(
window
,
'
Flash
'
);
filteredSearchManager
=
new
gl
.
FilteredSearchManager
();
filteredSearchManager
.
setup
();
manager
.
setup
();
expect
(
window
.
Flash
).
not
.
toHaveBeenCalled
();
});
...
...
@@ -102,6 +108,7 @@ describe('Filtered Search Manager', () => {
describe
(
'
searchState
'
,
()
=>
{
beforeEach
(()
=>
{
spyOn
(
gl
.
FilteredSearchManager
.
prototype
,
'
search
'
).
and
.
callFake
(()
=>
{});
initializeManager
();
});
it
(
'
should blur button
'
,
()
=>
{
...
...
@@ -148,6 +155,10 @@ describe('Filtered Search Manager', () => {
describe
(
'
search
'
,
()
=>
{
const
defaultParams
=
'
?scope=all&utf8=%E2%9C%93&state=opened
'
;
beforeEach
(()
=>
{
initializeManager
();
});
it
(
'
should search with a single word
'
,
(
done
)
=>
{
input
.
value
=
'
searchTerm
'
;
...
...
@@ -197,6 +208,10 @@ describe('Filtered Search Manager', () => {
});
describe
(
'
handleInputPlaceholder
'
,
()
=>
{
beforeEach
(()
=>
{
initializeManager
();
});
it
(
'
should render placeholder when there is no input
'
,
()
=>
{
expect
(
input
.
placeholder
).
toEqual
(
placeholder
);
});
...
...
@@ -223,6 +238,10 @@ describe('Filtered Search Manager', () => {
});
describe
(
'
checkForBackspace
'
,
()
=>
{
beforeEach
(()
=>
{
initializeManager
();
});
describe
(
'
tokens and no input
'
,
()
=>
{
beforeEach
(()
=>
{
tokensContainer
.
innerHTML
=
FilteredSearchSpecHelper
.
createTokensContainerHTML
(
...
...
@@ -260,6 +279,10 @@ describe('Filtered Search Manager', () => {
});
describe
(
'
removeToken
'
,
()
=>
{
beforeEach
(()
=>
{
initializeManager
();
});
it
(
'
removes token even when it is already selected
'
,
()
=>
{
tokensContainer
.
innerHTML
=
FilteredSearchSpecHelper
.
createTokensContainerHTML
(
FilteredSearchSpecHelper
.
createFilterVisualTokenHTML
(
'
milestone
'
,
'
none
'
,
true
),
...
...
@@ -291,6 +314,7 @@ describe('Filtered Search Manager', () => {
describe
(
'
removeSelectedTokenKeydown
'
,
()
=>
{
beforeEach
(()
=>
{
initializeManager
();
tokensContainer
.
innerHTML
=
FilteredSearchSpecHelper
.
createTokensContainerHTML
(
FilteredSearchSpecHelper
.
createFilterVisualTokenHTML
(
'
milestone
'
,
'
none
'
,
true
),
);
...
...
@@ -344,27 +368,39 @@ describe('Filtered Search Manager', () => {
spyOn
(
gl
.
FilteredSearchVisualTokens
,
'
removeSelectedToken
'
).
and
.
callThrough
();
spyOn
(
gl
.
FilteredSearchManager
.
prototype
,
'
handleInputPlaceholder
'
).
and
.
callThrough
();
spyOn
(
gl
.
FilteredSearchManager
.
prototype
,
'
toggleClearSearchButton
'
).
and
.
callThrough
();
manager
.
removeSelectedToken
();
initializeManager
();
});
it
(
'
calls FilteredSearchVisualTokens.removeSelectedToken
'
,
()
=>
{
manager
.
removeSelectedToken
();
expect
(
gl
.
FilteredSearchVisualTokens
.
removeSelectedToken
).
toHaveBeenCalled
();
});
it
(
'
calls handleInputPlaceholder
'
,
()
=>
{
manager
.
removeSelectedToken
();
expect
(
manager
.
handleInputPlaceholder
).
toHaveBeenCalled
();
});
it
(
'
calls toggleClearSearchButton
'
,
()
=>
{
manager
.
removeSelectedToken
();
expect
(
manager
.
toggleClearSearchButton
).
toHaveBeenCalled
();
});
it
(
'
calls update dropdown offset
'
,
()
=>
{
manager
.
removeSelectedToken
();
expect
(
manager
.
dropdownManager
.
updateDropdownOffset
).
toHaveBeenCalled
();
});
});
describe
(
'
toggleInputContainerFocus
'
,
()
=>
{
beforeEach
(()
=>
{
initializeManager
();
});
it
(
'
toggles on focus
'
,
()
=>
{
input
.
focus
();
expect
(
document
.
querySelector
(
'
.filtered-search-box
'
).
classList
.
contains
(
'
focus
'
)).
toEqual
(
true
);
...
...
spec/javascripts/issue_show/components/app_spec.js
View file @
925eea26
...
...
@@ -3,17 +3,9 @@ import '~/render_math';
import
'
~/render_gfm
'
;
import
issuableApp
from
'
~/issue_show/components/app.vue
'
;
import
eventHub
from
'
~/issue_show/event_hub
'
;
import
Poll
from
'
~/lib/utils/poll
'
;
import
issueShowData
from
'
../mock_data
'
;
const
issueShowInterceptor
=
data
=>
(
request
,
next
)
=>
{
next
(
request
.
respondWith
(
JSON
.
stringify
(
data
),
{
status
:
200
,
headers
:
{
'
POLL-INTERVAL
'
:
1
,
},
}));
};
function
formatText
(
text
)
{
return
text
.
trim
().
replace
(
/
\s\s
+/g
,
'
'
);
}
...
...
@@ -24,10 +16,10 @@ describe('Issuable output', () => {
let
vm
;
beforeEach
(()
=>
{
const
IssuableDescriptionComponent
=
Vue
.
extend
(
issuableApp
);
Vue
.
http
.
interceptors
.
push
(
issueShowInterceptor
(
issueShowData
.
initialRequest
));
spyOn
(
eventHub
,
'
$emit
'
);
spyOn
(
Poll
.
prototype
,
'
makeRequest
'
);
const
IssuableDescriptionComponent
=
Vue
.
extend
(
issuableApp
);
vm
=
new
IssuableDescriptionComponent
({
propsData
:
{
...
...
@@ -54,9 +46,18 @@ describe('Issuable output', () => {
});
it
(
'
should render a title/description/edited and update title/description/edited on update
'
,
(
done
)
=>
{
setTimeout
(()
=>
{
const
editedText
=
vm
.
$el
.
querySelector
(
'
.edited-text
'
);
vm
.
poll
.
options
.
successCallback
({
json
()
{
return
issueShowData
.
initialRequest
;
},
});
let
editedText
;
Vue
.
nextTick
()
.
then
(()
=>
{
editedText
=
vm
.
$el
.
querySelector
(
'
.edited-text
'
);
})
.
then
(()
=>
{
expect
(
document
.
querySelector
(
'
title
'
).
innerText
).
toContain
(
'
this is a title (#1)
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.title
'
).
innerHTML
).
toContain
(
'
<p>this is a title</p>
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.wiki
'
).
innerHTML
).
toContain
(
'
<p>this is a description!</p>
'
);
...
...
@@ -64,22 +65,27 @@ describe('Issuable output', () => {
expect
(
formatText
(
editedText
.
innerText
)).
toMatch
(
/Edited
[\s\S]
+
?
by Some User/
);
expect
(
editedText
.
querySelector
(
'
.author_link
'
).
href
).
toMatch
(
/
\/
some_user$/
);
expect
(
editedText
.
querySelector
(
'
time
'
)).
toBeTruthy
();
Vue
.
http
.
interceptors
.
push
(
issueShowInterceptor
(
issueShowData
.
secondRequest
));
setTimeout
(()
=>
{
expect
(
document
.
querySelector
(
'
title
'
).
innerText
).
toContain
(
'
2 (#1)
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.title
'
).
innerHTML
).
toContain
(
'
<p>2</p>
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.wiki
'
).
innerHTML
).
toContain
(
'
<p>42</p>
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.js-task-list-field
'
).
value
).
toContain
(
'
42
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.edited-text
'
)).
toBeTruthy
();
expect
(
formatText
(
vm
.
$el
.
querySelector
(
'
.edited-text
'
).
innerText
)).
toMatch
(
/Edited
[\s\S]
+
?
by Other User/
);
expect
(
editedText
.
querySelector
(
'
.author_link
'
).
href
).
toMatch
(
/
\/
other_user$/
);
expect
(
editedText
.
querySelector
(
'
time
'
)).
toBeTruthy
();
done
();
})
.
then
(()
=>
{
vm
.
poll
.
options
.
successCallback
({
json
()
{
return
issueShowData
.
secondRequest
;
},
});
});
})
.
then
(
Vue
.
nextTick
)
.
then
(()
=>
{
expect
(
document
.
querySelector
(
'
title
'
).
innerText
).
toContain
(
'
2 (#1)
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.title
'
).
innerHTML
).
toContain
(
'
<p>2</p>
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.wiki
'
).
innerHTML
).
toContain
(
'
<p>42</p>
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.js-task-list-field
'
).
value
).
toContain
(
'
42
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.edited-text
'
)).
toBeTruthy
();
expect
(
formatText
(
vm
.
$el
.
querySelector
(
'
.edited-text
'
).
innerText
)).
toMatch
(
/Edited
[\s\S]
+
?
by Other User/
);
expect
(
editedText
.
querySelector
(
'
.author_link
'
).
href
).
toMatch
(
/
\/
other_user$/
);
expect
(
editedText
.
querySelector
(
'
time
'
)).
toBeTruthy
();
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
it
(
'
shows actions if permissions are correct
'
,
(
done
)
=>
{
...
...
@@ -344,21 +350,23 @@ describe('Issuable output', () => {
describe
(
'
open form
'
,
()
=>
{
it
(
'
shows locked warning if form is open & data is different
'
,
(
done
)
=>
{
Vue
.
http
.
interceptors
.
push
(
issueShowInterceptor
(
issueShowData
.
initialRequest
));
vm
.
poll
.
options
.
successCallback
({
json
()
{
return
issueShowData
.
initialRequest
;
},
});
Vue
.
nextTick
()
.
then
(()
=>
new
Promise
((
resolve
)
=>
{
setTimeout
(
resolve
);
}))
.
then
(()
=>
{
vm
.
openForm
();
Vue
.
http
.
interceptors
.
push
(
issueShowInterceptor
(
issueShowData
.
secondRequest
));
return
new
Promise
((
resolve
)
=>
{
setTimeout
(
resolve
);
vm
.
poll
.
options
.
successCallback
({
json
()
{
return
issueShowData
.
secondRequest
;
},
});
})
.
then
(
Vue
.
nextTick
)
.
then
(()
=>
{
expect
(
vm
.
formState
.
lockedWarningVisible
,
...
...
@@ -367,9 +375,8 @@ describe('Issuable output', () => {
expect
(
vm
.
$el
.
querySelector
(
'
.alert
'
),
).
not
.
toBeNull
();
done
();
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
});
...
...
spec/javascripts/test_bundle.js
View file @
925eea26
...
...
@@ -22,6 +22,19 @@ window.gl = window.gl || {};
window
.
gl
.
TEST_HOST
=
'
http://test.host
'
;
window
.
gon
=
window
.
gon
||
{};
let
hasUnhandledPromiseRejections
=
false
;
window
.
addEventListener
(
'
unhandledrejection
'
,
(
event
)
=>
{
hasUnhandledPromiseRejections
=
true
;
console
.
error
(
'
Unhandled promise rejection:
'
);
console
.
error
(
event
.
reason
.
stack
||
event
.
reason
);
});
const
checkUnhandledPromiseRejections
=
(
done
)
=>
{
expect
(
hasUnhandledPromiseRejections
).
toBe
(
false
);
done
();
};
// HACK: Chrome 59 disconnects if there are too many synchronous tests in a row
// because it appears to lock up the thread that communicates to Karma's socket
// This async beforeEach gets called on every spec and releases the JS thread long
...
...
@@ -63,6 +76,10 @@ testsContext.keys().forEach(function (path) {
}
});
it
(
'
has no unhandled Promise rejections
'
,
(
done
)
=>
{
setTimeout
(
checkUnhandledPromiseRejections
(
done
),
1000
);
});
// if we're generating coverage reports, make sure to include all files so
// that we can catch files with 0% coverage
// see: https://github.com/deepsweet/istanbul-instrumenter-loader/issues/15
...
...
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