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
824b40be
Commit
824b40be
authored
3 years ago
by
Tom Quirk
Committed by
Nicolò Maria Mezzopera
3 years ago
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use GlAlert for external issues list errors
Changelog: fixed EE: true
parent
cd1ea9b5
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
48 additions
and
35 deletions
+48
-35
ee/app/assets/javascripts/external_issues_list/components/external_issues_list_root.vue
...rnal_issues_list/components/external_issues_list_root.vue
+18
-7
ee/spec/frontend/external_issues_list/components/external_issues_list_root_spec.js
..._issues_list/components/external_issues_list_root_spec.js
+30
-28
No files found.
ee/app/assets/javascripts/external_issues_list/components/external_issues_list_root.vue
View file @
824b40be
<
script
>
<
script
>
import
{
GlButton
,
GlIcon
,
GlLink
,
GlSprintf
,
GlSafeHtmlDirective
as
SafeHtml
}
from
'
@gitlab/ui
'
;
import
{
GlButton
,
GlIcon
,
GlLink
,
GlSprintf
,
GlSafeHtmlDirective
as
SafeHtml
,
GlAlert
,
}
from
'
@gitlab/ui
'
;
import
*
as
Sentry
from
'
@sentry/browser
'
;
import
createFlash
from
'
~/flash
'
;
import
IssuableList
from
'
~/issuable_list/components/issuable_list_root.vue
'
;
import
IssuableList
from
'
~/issuable_list/components/issuable_list_root.vue
'
;
import
{
import
{
IssuableStates
,
IssuableStates
,
...
@@ -30,6 +37,7 @@ export default {
...
@@ -30,6 +37,7 @@ export default {
GlIcon
,
GlIcon
,
GlLink
,
GlLink
,
GlSprintf
,
GlSprintf
,
GlAlert
,
IssuableList
,
IssuableList
,
ExternalIssuesListEmptyState
,
ExternalIssuesListEmptyState
,
},
},
...
@@ -70,6 +78,7 @@ export default {
...
@@ -70,6 +78,7 @@ export default {
[
IssuableStates
.
Closed
]:
0
,
[
IssuableStates
.
Closed
]:
0
,
[
IssuableStates
.
All
]:
0
,
[
IssuableStates
.
All
]:
0
,
},
},
errorMessage
:
null
,
};
};
},
},
computed
:
{
computed
:
{
...
@@ -173,11 +182,9 @@ export default {
...
@@ -173,11 +182,9 @@ export default {
return
filteredSearchValue
;
return
filteredSearchValue
;
},
},
onExternalIssuesQueryError
(
error
,
message
)
{
onExternalIssuesQueryError
(
error
,
message
)
{
createFlash
({
this
.
errorMessage
=
message
||
error
.
message
;
message
:
message
||
error
.
message
,
captureError
:
true
,
Sentry
.
captureException
(
error
);
error
,
});
},
},
onIssuableListClickTab
(
selectedIssueState
)
{
onIssuableListClickTab
(
selectedIssueState
)
{
this
.
currentPage
=
1
;
this
.
currentPage
=
1
;
...
@@ -225,7 +232,11 @@ export default {
...
@@ -225,7 +232,11 @@ export default {
</
script
>
</
script
>
<
template
>
<
template
>
<gl-alert
v-if=
"errorMessage"
class=
"gl-mt-3"
variant=
"danger"
:dismissible=
"false"
>
{{
errorMessage
}}
</gl-alert>
<issuable-list
<issuable-list
v-else
:namespace=
"projectFullPath"
:namespace=
"projectFullPath"
:tabs=
"$options.IssuableListTabs"
:tabs=
"$options.IssuableListTabs"
:current-tab=
"currentState"
:current-tab=
"currentState"
...
...
This diff is collapsed.
Click to expand it.
ee/spec/frontend/external_issues_list/components/external_issues_list_root_spec.js
View file @
824b40be
import
{
GlAlert
}
from
'
@gitlab/ui
'
;
import
*
as
Sentry
from
'
@sentry/browser
'
;
import
{
shallowMount
,
createLocalVue
,
mount
}
from
'
@vue/test-utils
'
;
import
{
shallowMount
,
createLocalVue
,
mount
}
from
'
@vue/test-utils
'
;
import
MockAdapter
from
'
axios-mock-adapter
'
;
import
MockAdapter
from
'
axios-mock-adapter
'
;
import
VueApollo
from
'
vue-apollo
'
;
import
VueApollo
from
'
vue-apollo
'
;
...
@@ -8,7 +10,6 @@ import jiraIssuesResolver from 'ee/integrations/jira/issues_list/graphql/resolve
...
@@ -8,7 +10,6 @@ import jiraIssuesResolver from 'ee/integrations/jira/issues_list/graphql/resolve
import
createMockApollo
from
'
helpers/mock_apollo_helper
'
;
import
createMockApollo
from
'
helpers/mock_apollo_helper
'
;
import
waitForPromises
from
'
helpers/wait_for_promises
'
;
import
waitForPromises
from
'
helpers/wait_for_promises
'
;
import
createFlash
from
'
~/flash
'
;
import
IssuableList
from
'
~/issuable_list/components/issuable_list_root.vue
'
;
import
IssuableList
from
'
~/issuable_list/components/issuable_list_root.vue
'
;
import
{
i18n
}
from
'
~/issues_list/constants
'
;
import
{
i18n
}
from
'
~/issues_list/constants
'
;
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
axios
from
'
~/lib/utils/axios_utils
'
;
...
@@ -61,9 +62,21 @@ describe('ExternalIssuesListRoot', () => {
...
@@ -61,9 +62,21 @@ describe('ExternalIssuesListRoot', () => {
const
mockLabel
=
'
ecosystem
'
;
const
mockLabel
=
'
ecosystem
'
;
const
findIssuableList
=
()
=>
wrapper
.
findComponent
(
IssuableList
);
const
findIssuableList
=
()
=>
wrapper
.
findComponent
(
IssuableList
);
const
findAlert
=
()
=>
wrapper
.
findComponent
(
GlAlert
);
const
createLabelFilterEvent
=
(
data
)
=>
({
type
:
'
labels
'
,
value
:
{
data
}
});
const
createLabelFilterEvent
=
(
data
)
=>
({
type
:
'
labels
'
,
value
:
{
data
}
});
const
createSearchFilterEvent
=
(
data
)
=>
({
type
:
'
filtered-search-term
'
,
value
:
{
data
}
});
const
createSearchFilterEvent
=
(
data
)
=>
({
type
:
'
filtered-search-term
'
,
value
:
{
data
}
});
const
expectErrorHandling
=
(
expectedRenderedErrorMessage
)
=>
{
const
issuesList
=
findIssuableList
();
const
alert
=
findAlert
();
expect
(
issuesList
.
exists
()).
toBe
(
false
);
expect
(
alert
.
exists
()).
toBe
(
true
);
expect
(
alert
.
text
()).
toBe
(
expectedRenderedErrorMessage
);
expect
(
Sentry
.
captureException
).
toHaveBeenCalledWith
(
expect
.
any
(
Error
));
};
const
createComponent
=
({
const
createComponent
=
({
apolloProvider
=
createMockApolloProvider
(),
apolloProvider
=
createMockApolloProvider
(),
provide
=
mockProvide
,
provide
=
mockProvide
,
...
@@ -300,13 +313,17 @@ describe('ExternalIssuesListRoot', () => {
...
@@ -300,13 +313,17 @@ describe('ExternalIssuesListRoot', () => {
});
});
describe
(
'
error handling
'
,
()
=>
{
describe
(
'
error handling
'
,
()
=>
{
beforeEach
(()
=>
{
jest
.
spyOn
(
Sentry
,
'
captureException
'
);
});
describe
(
'
when request fails
'
,
()
=>
{
describe
(
'
when request fails
'
,
()
=>
{
it
.
each
`
it
.
each
`
APIErrors | expectedRenderedErrorMessage
APIErrors | expectedRenderedErrorMessage
${[
'
API error
'
]}
|
${
'
API error
'
}
${[
'
API error
'
]}
|
${
'
API error
'
}
${
undefined
}
|
${
i18n
.
errorFetchingIssues
}
${
undefined
}
|
${
i18n
.
errorFetchingIssues
}
`
(
`
(
'
calls `createFlash`
with "$expectedRenderedErrorMessage" when API responds with "$APIErrors"
'
,
'
displays error alert
with "$expectedRenderedErrorMessage" when API responds with "$APIErrors"
'
,
async
({
APIErrors
,
expectedRenderedErrorMessage
})
=>
{
async
({
APIErrors
,
expectedRenderedErrorMessage
})
=>
{
jest
.
spyOn
(
axios
,
'
get
'
);
jest
.
spyOn
(
axios
,
'
get
'
);
mock
mock
...
@@ -316,17 +333,13 @@ describe('ExternalIssuesListRoot', () => {
...
@@ -316,17 +333,13 @@ describe('ExternalIssuesListRoot', () => {
createComponent
();
createComponent
();
await
waitForPromises
();
await
waitForPromises
();
expect
(
createFlash
).
toHaveBeenCalledWith
({
expectErrorHandling
(
expectedRenderedErrorMessage
);
message
:
expectedRenderedErrorMessage
,
captureError
:
true
,
error
:
expect
.
any
(
Object
),
});
},
},
);
);
});
});
describe
(
'
when GraphQL network error is encountered
'
,
()
=>
{
describe
(
'
when GraphQL network error is encountered
'
,
()
=>
{
it
(
'
calls `createFlash` correctly
with default error message
'
,
async
()
=>
{
it
(
'
displays error alert
with default error message
'
,
async
()
=>
{
createComponent
({
createComponent
({
apolloProvider
:
createMockApolloProvider
({
apolloProvider
:
createMockApolloProvider
({
Query
:
{
Query
:
{
...
@@ -336,35 +349,24 @@ describe('ExternalIssuesListRoot', () => {
...
@@ -336,35 +349,24 @@ describe('ExternalIssuesListRoot', () => {
});
});
await
waitForPromises
();
await
waitForPromises
();
expect
(
createFlash
).
toHaveBeenCalledWith
({
expectErrorHandling
(
i18n
.
errorFetchingIssues
);
message
:
i18n
.
errorFetchingIssues
,
captureError
:
true
,
error
:
expect
.
any
(
Object
),
});
});
});
});
});
});
});
describe
(
'
pagination
'
,
()
=>
{
describe
(
'
pagination
'
,
()
=>
{
it
.
each
`
it
.
each
`
scenario | issuesListLoadFailed | issues | shouldShowPaginationControls
scenario | issues | shouldShowPaginationControls
${
'
fails
'
}
|
${
true
}
|
${[]}
|
${
false
}
${
'
returns no issues
'
}
|
${[]}
|
${
false
}
${
'
returns no issues
'
}
|
${
false
}
|
${[]}
|
${
false
}
${
`returns some issues`
}
|
${
mockExternalIssues
}
|
${
true
}
${
`returns some issues`
}
|
${
false
}
|
${
mockExternalIssues
}
|
${
true
}
`
(
`
(
'
sets `showPaginationControls` prop to $shouldShowPaginationControls when request $scenario
'
,
'
sets `showPaginationControls` prop to $shouldShowPaginationControls when request $scenario
'
,
async
({
issues
ListLoadFailed
,
issues
,
shouldShowPaginationControls
})
=>
{
async
({
issues
,
shouldShowPaginationControls
})
=>
{
jest
.
spyOn
(
axios
,
'
get
'
);
jest
.
spyOn
(
axios
,
'
get
'
);
mock
mock
.
onGet
(
mockProvide
.
issuesFetchPath
).
replyOnce
(
httpStatus
.
OK
,
issues
,
{
.
onGet
(
mockProvide
.
issuesFetchPath
)
.
replyOnce
(
issuesListLoadFailed
?
httpStatus
.
INTERNAL_SERVER_ERROR
:
httpStatus
.
OK
,
issues
,
{
'
x-page
'
:
1
,
'
x-page
'
:
1
,
'
x-total
'
:
issues
.
length
,
'
x-total
'
:
issues
.
length
,
},
});
);
createComponent
();
createComponent
();
await
waitForPromises
();
await
waitForPromises
();
...
...
This diff is collapsed.
Click to expand it.
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