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
1b9ef0c2
Commit
1b9ef0c2
authored
Mar 10, 2020
by
David O'Regan
Committed by
Paul Slaughter
Mar 10, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix infinite spinner on error detail page
https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26188
parent
da570c09
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
95 additions
and
20 deletions
+95
-20
app/assets/javascripts/error_tracking/components/error_details.vue
...s/javascripts/error_tracking/components/error_details.vue
+25
-1
changelogs/unreleased/118503.yml
changelogs/unreleased/118503.yml
+5
-0
locale/gitlab.pot
locale/gitlab.pot
+3
-0
spec/frontend/error_tracking/components/error_details_spec.js
.../frontend/error_tracking/components/error_details_spec.js
+62
-19
No files found.
app/assets/javascripts/error_tracking/components/error_details.vue
View file @
1b9ef0c2
...
@@ -25,6 +25,8 @@ import { severityLevel, severityLevelVariant, errorStatus } from './constants';
...
@@ -25,6 +25,8 @@ import { severityLevel, severityLevelVariant, errorStatus } from './constants';
import
query
from
'
../queries/details.query.graphql
'
;
import
query
from
'
../queries/details.query.graphql
'
;
const
SENTRY_TIMEOUT
=
10000
;
export
default
{
export
default
{
components
:
{
components
:
{
GlButton
,
GlButton
,
...
@@ -87,6 +89,8 @@ export default {
...
@@ -87,6 +89,8 @@ export default {
if
(
res
.
data
.
project
?.
sentryErrors
?.
detailedError
)
{
if
(
res
.
data
.
project
?.
sentryErrors
?.
detailedError
)
{
this
.
$apollo
.
queries
.
error
.
stopPolling
();
this
.
$apollo
.
queries
.
error
.
stopPolling
();
this
.
setStatus
(
this
.
error
.
status
);
this
.
setStatus
(
this
.
error
.
status
);
}
else
{
this
.
onNoApolloResult
();
}
}
},
},
},
},
...
@@ -94,6 +98,8 @@ export default {
...
@@ -94,6 +98,8 @@ export default {
data
()
{
data
()
{
return
{
return
{
error
:
null
,
error
:
null
,
errorLoading
:
true
,
errorPollTimeout
:
0
,
issueCreationInProgress
:
false
,
issueCreationInProgress
:
false
,
isAlertVisible
:
false
,
isAlertVisible
:
false
,
closedIssueId
:
null
,
closedIssueId
:
null
,
...
@@ -158,8 +164,19 @@ export default {
...
@@ -158,8 +164,19 @@ export default {
return
this
.
errorStatus
!==
errorStatus
.
RESOLVED
?
__
(
'
Resolve
'
)
:
__
(
'
Unresolve
'
);
return
this
.
errorStatus
!==
errorStatus
.
RESOLVED
?
__
(
'
Resolve
'
)
:
__
(
'
Unresolve
'
);
},
},
},
},
watch
:
{
error
(
val
)
{
if
(
val
)
{
this
.
errorLoading
=
false
;
}
},
},
mounted
()
{
mounted
()
{
this
.
startPollingStacktrace
(
this
.
issueStackTracePath
);
this
.
startPollingStacktrace
(
this
.
issueStackTracePath
);
this
.
errorPollTimeout
=
Date
.
now
()
+
SENTRY_TIMEOUT
;
this
.
$apollo
.
queries
.
error
.
setOptions
({
fetchPolicy
:
'
cache-and-network
'
,
});
},
},
methods
:
{
methods
:
{
...
mapActions
(
'
details
'
,
[
...
mapActions
(
'
details
'
,
[
...
@@ -191,6 +208,13 @@ export default {
...
@@ -191,6 +208,13 @@ export default {
}
}
});
});
},
},
onNoApolloResult
()
{
if
(
Date
.
now
()
>
this
.
errorPollTimeout
)
{
this
.
$apollo
.
queries
.
error
.
stopPolling
();
this
.
errorLoading
=
false
;
createFlash
(
__
(
'
Could not connect to Sentry. Refresh the page to try again.
'
),
'
warning
'
);
}
},
formatDate
(
date
)
{
formatDate
(
date
)
{
return
`
${
this
.
timeFormatted
(
date
)}
(
${
dateFormat
(
date
,
'
UTC:yyyy-mm-dd h:MM:ssTT Z
'
)}
)`
;
return
`
${
this
.
timeFormatted
(
date
)}
(
${
dateFormat
(
date
,
'
UTC:yyyy-mm-dd h:MM:ssTT Z
'
)}
)`
;
},
},
...
@@ -200,7 +224,7 @@ export default {
...
@@ -200,7 +224,7 @@ export default {
<
template
>
<
template
>
<div>
<div>
<div
v-if=
"
$apollo.queries.error.l
oading"
class=
"py-3"
>
<div
v-if=
"
errorL
oading"
class=
"py-3"
>
<gl-loading-icon
:size=
"3"
/>
<gl-loading-icon
:size=
"3"
/>
</div>
</div>
<div
v-else-if=
"error"
class=
"error-details"
>
<div
v-else-if=
"error"
class=
"error-details"
>
...
...
changelogs/unreleased/118503.yml
0 → 100644
View file @
1b9ef0c2
---
title
:
Fix infinite spinner on error detail page
merge_request
:
26188
author
:
type
:
fixed
locale/gitlab.pot
View file @
1b9ef0c2
...
@@ -5609,6 +5609,9 @@ msgstr ""
...
@@ -5609,6 +5609,9 @@ msgstr ""
msgid "Could not connect to FogBugz, check your URL"
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
msgstr ""
msgid "Could not connect to Sentry. Refresh the page to try again."
msgstr ""
msgid "Could not connect to Web IDE file mirror service."
msgid "Could not connect to Web IDE file mirror service."
msgstr ""
msgstr ""
...
...
spec/frontend/error_tracking/components/error_details_spec.js
View file @
1b9ef0c2
import
{
createLocalVue
,
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
createLocalVue
,
shallowMount
}
from
'
@vue/test-utils
'
;
import
Vuex
from
'
vuex
'
;
import
Vuex
from
'
vuex
'
;
import
{
__
}
from
'
~/locale
'
;
import
{
__
}
from
'
~/locale
'
;
import
createFlash
from
'
~/flash
'
;
import
{
import
{
GlButton
,
GlButton
,
GlLoadingIcon
,
GlLoadingIcon
,
...
@@ -18,6 +19,8 @@ import {
...
@@ -18,6 +19,8 @@ import {
errorStatus
,
errorStatus
,
}
from
'
~/error_tracking/components/constants
'
;
}
from
'
~/error_tracking/components/constants
'
;
jest
.
mock
(
'
~/flash
'
);
const
localVue
=
createLocalVue
();
const
localVue
=
createLocalVue
();
localVue
.
use
(
Vuex
);
localVue
.
use
(
Vuex
);
...
@@ -49,18 +52,6 @@ describe('ErrorDetails', () => {
...
@@ -49,18 +52,6 @@ describe('ErrorDetails', () => {
csrfToken
:
'
fakeToken
'
,
csrfToken
:
'
fakeToken
'
,
},
},
});
});
wrapper
.
setData
({
error
:
{
id
:
'
gid://gitlab/Gitlab::ErrorTracking::DetailedError/129381
'
,
sentryId
:
129381
,
title
:
'
Issue title
'
,
externalUrl
:
'
http://sentry.gitlab.net/gitlab
'
,
firstSeen
:
'
2017-05-26T13:32:48Z
'
,
lastSeen
:
'
2018-05-26T13:32:48Z
'
,
count
:
12
,
userCount
:
2
,
},
});
}
}
beforeEach
(()
=>
{
beforeEach
(()
=>
{
...
@@ -78,6 +69,7 @@ describe('ErrorDetails', () => {
...
@@ -78,6 +69,7 @@ describe('ErrorDetails', () => {
const
state
=
{
const
state
=
{
stacktraceData
:
{},
stacktraceData
:
{},
loadingStacktrace
:
true
,
loadingStacktrace
:
true
,
errorStatus
:
''
,
};
};
store
=
new
Vuex
.
Store
({
store
=
new
Vuex
.
Store
({
...
@@ -99,6 +91,7 @@ describe('ErrorDetails', () => {
...
@@ -99,6 +91,7 @@ describe('ErrorDetails', () => {
error
:
{
error
:
{
loading
:
true
,
loading
:
true
,
stopPolling
:
jest
.
fn
(),
stopPolling
:
jest
.
fn
(),
setOptions
:
jest
.
fn
(),
},
},
},
},
},
},
...
@@ -123,10 +116,61 @@ describe('ErrorDetails', () => {
...
@@ -123,10 +116,61 @@ describe('ErrorDetails', () => {
});
});
});
});
describe
(
'
sentry response timeout
'
,
()
=>
{
const
initTime
=
300000
;
const
endTime
=
initTime
+
10000
;
beforeEach
(()
=>
{
mocks
.
$apollo
.
queries
.
error
.
loading
=
false
;
jest
.
spyOn
(
Date
,
'
now
'
).
mockReturnValue
(
initTime
);
mountComponent
();
});
it
(
'
when before timeout, still shows loading
'
,
()
=>
{
Date
.
now
.
mockReturnValue
(
endTime
-
1
);
wrapper
.
vm
.
onNoApolloResult
();
return
wrapper
.
vm
.
$nextTick
().
then
(()
=>
{
expect
(
wrapper
.
find
(
GlLoadingIcon
).
exists
()).
toBe
(
true
);
expect
(
createFlash
).
not
.
toHaveBeenCalled
();
expect
(
mocks
.
$apollo
.
queries
.
error
.
stopPolling
).
not
.
toHaveBeenCalled
();
});
});
it
(
'
when timeout is hit and no apollo result, stops loading and shows flash
'
,
()
=>
{
Date
.
now
.
mockReturnValue
(
endTime
+
1
);
wrapper
.
vm
.
onNoApolloResult
();
return
wrapper
.
vm
.
$nextTick
().
then
(()
=>
{
expect
(
wrapper
.
find
(
GlLoadingIcon
).
exists
()).
toBe
(
false
);
expect
(
wrapper
.
find
(
GlLink
).
exists
()).
toBe
(
false
);
expect
(
createFlash
).
toHaveBeenCalledWith
(
'
Could not connect to Sentry. Refresh the page to try again.
'
,
'
warning
'
,
);
expect
(
mocks
.
$apollo
.
queries
.
error
.
stopPolling
).
toHaveBeenCalled
();
});
});
});
describe
(
'
Error details
'
,
()
=>
{
describe
(
'
Error details
'
,
()
=>
{
beforeEach
(()
=>
{
beforeEach
(()
=>
{
mocks
.
$apollo
.
queries
.
error
.
loading
=
false
;
mocks
.
$apollo
.
queries
.
error
.
loading
=
false
;
mountComponent
();
mountComponent
();
wrapper
.
setData
({
error
:
{
id
:
'
gid://gitlab/Gitlab::ErrorTracking::DetailedError/129381
'
,
sentryId
:
129381
,
title
:
'
Issue title
'
,
externalUrl
:
'
http://sentry.gitlab.net/gitlab
'
,
firstSeen
:
'
2017-05-26T13:32:48Z
'
,
lastSeen
:
'
2018-05-26T13:32:48Z
'
,
count
:
12
,
userCount
:
2
,
},
});
});
});
it
(
'
should show Sentry error details without stacktrace
'
,
()
=>
{
it
(
'
should show Sentry error details without stacktrace
'
,
()
=>
{
...
@@ -232,10 +276,6 @@ describe('ErrorDetails', () => {
...
@@ -232,10 +276,6 @@ describe('ErrorDetails', () => {
});
});
describe
(
'
When a user clicks the create issue button
'
,
()
=>
{
describe
(
'
When a user clicks the create issue button
'
,
()
=>
{
beforeEach
(()
=>
{
mountComponent
();
});
it
(
'
should send sentry_issue_identifier
'
,
()
=>
{
it
(
'
should send sentry_issue_identifier
'
,
()
=>
{
const
sentryErrorIdInput
=
findInput
(
const
sentryErrorIdInput
=
findInput
(
'
issue[sentry_issue_attributes][sentry_issue_identifier]
'
,
'
issue[sentry_issue_attributes][sentry_issue_identifier]
'
,
...
@@ -275,7 +315,8 @@ describe('ErrorDetails', () => {
...
@@ -275,7 +315,8 @@ describe('ErrorDetails', () => {
describe
(
'
when error is unresolved
'
,
()
=>
{
describe
(
'
when error is unresolved
'
,
()
=>
{
beforeEach
(()
=>
{
beforeEach
(()
=>
{
store
.
state
.
details
.
errorStatus
=
errorStatus
.
UNRESOLVED
;
store
.
state
.
details
.
errorStatus
=
errorStatus
.
UNRESOLVED
;
mountComponent
();
return
wrapper
.
vm
.
$nextTick
();
});
});
it
(
'
displays Ignore and Resolve buttons
'
,
()
=>
{
it
(
'
displays Ignore and Resolve buttons
'
,
()
=>
{
...
@@ -301,7 +342,8 @@ describe('ErrorDetails', () => {
...
@@ -301,7 +342,8 @@ describe('ErrorDetails', () => {
describe
(
'
when error is ignored
'
,
()
=>
{
describe
(
'
when error is ignored
'
,
()
=>
{
beforeEach
(()
=>
{
beforeEach
(()
=>
{
store
.
state
.
details
.
errorStatus
=
errorStatus
.
IGNORED
;
store
.
state
.
details
.
errorStatus
=
errorStatus
.
IGNORED
;
mountComponent
();
return
wrapper
.
vm
.
$nextTick
();
});
});
it
(
'
displays Undo Ignore and Resolve buttons
'
,
()
=>
{
it
(
'
displays Undo Ignore and Resolve buttons
'
,
()
=>
{
...
@@ -327,7 +369,8 @@ describe('ErrorDetails', () => {
...
@@ -327,7 +369,8 @@ describe('ErrorDetails', () => {
describe
(
'
when error is resolved
'
,
()
=>
{
describe
(
'
when error is resolved
'
,
()
=>
{
beforeEach
(()
=>
{
beforeEach
(()
=>
{
store
.
state
.
details
.
errorStatus
=
errorStatus
.
RESOLVED
;
store
.
state
.
details
.
errorStatus
=
errorStatus
.
RESOLVED
;
mountComponent
();
return
wrapper
.
vm
.
$nextTick
();
});
});
it
(
'
displays Ignore and Unresolve buttons
'
,
()
=>
{
it
(
'
displays Ignore and Unresolve buttons
'
,
()
=>
{
...
...
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