Commit 1b9ef0c2 authored by David O'Regan's avatar David O'Regan Committed by Paul Slaughter

Fix infinite spinner on error detail page

https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26188
parent da570c09
......@@ -25,6 +25,8 @@ import { severityLevel, severityLevelVariant, errorStatus } from './constants';
import query from '../queries/details.query.graphql';
const SENTRY_TIMEOUT = 10000;
export default {
components: {
GlButton,
......@@ -87,6 +89,8 @@ export default {
if (res.data.project?.sentryErrors?.detailedError) {
this.$apollo.queries.error.stopPolling();
this.setStatus(this.error.status);
} else {
this.onNoApolloResult();
}
},
},
......@@ -94,6 +98,8 @@ export default {
data() {
return {
error: null,
errorLoading: true,
errorPollTimeout: 0,
issueCreationInProgress: false,
isAlertVisible: false,
closedIssueId: null,
......@@ -158,8 +164,19 @@ export default {
return this.errorStatus !== errorStatus.RESOLVED ? __('Resolve') : __('Unresolve');
},
},
watch: {
error(val) {
if (val) {
this.errorLoading = false;
}
},
},
mounted() {
this.startPollingStacktrace(this.issueStackTracePath);
this.errorPollTimeout = Date.now() + SENTRY_TIMEOUT;
this.$apollo.queries.error.setOptions({
fetchPolicy: 'cache-and-network',
});
},
methods: {
...mapActions('details', [
......@@ -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) {
return `${this.timeFormatted(date)} (${dateFormat(date, 'UTC:yyyy-mm-dd h:MM:ssTT Z')})`;
},
......@@ -200,7 +224,7 @@ export default {
<template>
<div>
<div v-if="$apollo.queries.error.loading" class="py-3">
<div v-if="errorLoading" class="py-3">
<gl-loading-icon :size="3" />
</div>
<div v-else-if="error" class="error-details">
......
---
title: Fix infinite spinner on error detail page
merge_request: 26188
author:
type: fixed
......@@ -5609,6 +5609,9 @@ msgstr ""
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
msgid "Could not connect to Sentry. Refresh the page to try again."
msgstr ""
msgid "Could not connect to Web IDE file mirror service."
msgstr ""
......
import { createLocalVue, shallowMount } from '@vue/test-utils';
import Vuex from 'vuex';
import { __ } from '~/locale';
import createFlash from '~/flash';
import {
GlButton,
GlLoadingIcon,
......@@ -18,6 +19,8 @@ import {
errorStatus,
} from '~/error_tracking/components/constants';
jest.mock('~/flash');
const localVue = createLocalVue();
localVue.use(Vuex);
......@@ -49,18 +52,6 @@ describe('ErrorDetails', () => {
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(() => {
......@@ -78,6 +69,7 @@ describe('ErrorDetails', () => {
const state = {
stacktraceData: {},
loadingStacktrace: true,
errorStatus: '',
};
store = new Vuex.Store({
......@@ -99,6 +91,7 @@ describe('ErrorDetails', () => {
error: {
loading: true,
stopPolling: jest.fn(),
setOptions: jest.fn(),
},
},
},
......@@ -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', () => {
beforeEach(() => {
mocks.$apollo.queries.error.loading = false;
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', () => {
......@@ -232,10 +276,6 @@ describe('ErrorDetails', () => {
});
describe('When a user clicks the create issue button', () => {
beforeEach(() => {
mountComponent();
});
it('should send sentry_issue_identifier', () => {
const sentryErrorIdInput = findInput(
'issue[sentry_issue_attributes][sentry_issue_identifier]',
......@@ -275,7 +315,8 @@ describe('ErrorDetails', () => {
describe('when error is unresolved', () => {
beforeEach(() => {
store.state.details.errorStatus = errorStatus.UNRESOLVED;
mountComponent();
return wrapper.vm.$nextTick();
});
it('displays Ignore and Resolve buttons', () => {
......@@ -301,7 +342,8 @@ describe('ErrorDetails', () => {
describe('when error is ignored', () => {
beforeEach(() => {
store.state.details.errorStatus = errorStatus.IGNORED;
mountComponent();
return wrapper.vm.$nextTick();
});
it('displays Undo Ignore and Resolve buttons', () => {
......@@ -327,7 +369,8 @@ describe('ErrorDetails', () => {
describe('when error is resolved', () => {
beforeEach(() => {
store.state.details.errorStatus = errorStatus.RESOLVED;
mountComponent();
return wrapper.vm.$nextTick();
});
it('displays Ignore and Unresolve buttons', () => {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment