2019-12-26 22:10:19 +05:30
|
|
|
import { createLocalVue, shallowMount } from '@vue/test-utils';
|
|
|
|
import Vuex from 'vuex';
|
2020-03-07 23:17:34 +05:30
|
|
|
import { GlLoadingIcon, GlLink, GlSprintf } from '@gitlab/ui';
|
2020-01-01 13:55:28 +05:30
|
|
|
import LoadingButton from '~/vue_shared/components/loading_button.vue';
|
2019-12-26 22:10:19 +05:30
|
|
|
import Stacktrace from '~/error_tracking/components/stacktrace.vue';
|
|
|
|
import ErrorDetails from '~/error_tracking/components/error_details.vue';
|
|
|
|
|
|
|
|
const localVue = createLocalVue();
|
|
|
|
localVue.use(Vuex);
|
|
|
|
|
|
|
|
describe('ErrorDetails', () => {
|
|
|
|
let store;
|
|
|
|
let wrapper;
|
|
|
|
let actions;
|
|
|
|
let getters;
|
|
|
|
|
|
|
|
function mountComponent() {
|
|
|
|
wrapper = shallowMount(ErrorDetails, {
|
2020-03-07 23:17:34 +05:30
|
|
|
stubs: { LoadingButton, GlSprintf },
|
2019-12-26 22:10:19 +05:30
|
|
|
localVue,
|
|
|
|
store,
|
|
|
|
propsData: {
|
|
|
|
issueDetailsPath: '/123/details',
|
|
|
|
issueStackTracePath: '/stacktrace',
|
2020-01-01 13:55:28 +05:30
|
|
|
projectIssuesPath: '/test-project/issues/',
|
|
|
|
csrfToken: 'fakeToken',
|
2019-12-26 22:10:19 +05:30
|
|
|
},
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
actions = {
|
|
|
|
startPollingDetails: () => {},
|
|
|
|
startPollingStacktrace: () => {},
|
|
|
|
};
|
|
|
|
|
|
|
|
getters = {
|
|
|
|
sentryUrl: () => 'sentry.io',
|
|
|
|
stacktrace: () => [{ context: [1, 2], lineNo: 53, filename: 'index.js' }],
|
|
|
|
};
|
|
|
|
|
|
|
|
const state = {
|
|
|
|
error: {},
|
|
|
|
loading: true,
|
|
|
|
stacktraceData: {},
|
|
|
|
loadingStacktrace: true,
|
|
|
|
};
|
|
|
|
|
|
|
|
store = new Vuex.Store({
|
|
|
|
modules: {
|
|
|
|
details: {
|
|
|
|
namespaced: true,
|
|
|
|
actions,
|
|
|
|
state,
|
|
|
|
getters,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
if (wrapper) {
|
|
|
|
wrapper.destroy();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('loading', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
mountComponent();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should show spinner while loading', () => {
|
|
|
|
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
|
|
|
|
expect(wrapper.find(GlLink).exists()).toBe(false);
|
|
|
|
expect(wrapper.find(Stacktrace).exists()).toBe(false);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('Error details', () => {
|
|
|
|
it('should show Sentry error details without stacktrace', () => {
|
|
|
|
store.state.details.loading = false;
|
|
|
|
store.state.details.error.id = 1;
|
|
|
|
mountComponent();
|
|
|
|
expect(wrapper.find(GlLink).exists()).toBe(true);
|
|
|
|
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
|
|
|
|
expect(wrapper.find(Stacktrace).exists()).toBe(false);
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('Stacktrace', () => {
|
|
|
|
it('should show stacktrace', () => {
|
|
|
|
store.state.details.loading = false;
|
|
|
|
store.state.details.error.id = 1;
|
|
|
|
store.state.details.loadingStacktrace = false;
|
|
|
|
mountComponent();
|
|
|
|
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
|
|
|
|
expect(wrapper.find(Stacktrace).exists()).toBe(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should NOT show stacktrace if no entries', () => {
|
|
|
|
store.state.details.loading = false;
|
|
|
|
store.state.details.loadingStacktrace = false;
|
|
|
|
store.getters = { 'details/sentryUrl': () => 'sentry.io', 'details/stacktrace': () => [] };
|
|
|
|
mountComponent();
|
|
|
|
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
|
|
|
|
expect(wrapper.find(Stacktrace).exists()).toBe(false);
|
|
|
|
});
|
|
|
|
});
|
2020-01-01 13:55:28 +05:30
|
|
|
|
|
|
|
describe('When a user clicks the create issue button', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
store.state.details.loading = false;
|
|
|
|
store.state.details.error = {
|
|
|
|
id: 129381,
|
|
|
|
title: 'Issue title',
|
|
|
|
external_url: 'http://sentry.gitlab.net/gitlab',
|
|
|
|
first_seen: '2017-05-26T13:32:48Z',
|
|
|
|
last_seen: '2018-05-26T13:32:48Z',
|
|
|
|
count: 12,
|
|
|
|
user_count: 2,
|
|
|
|
};
|
|
|
|
mountComponent();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should send sentry_issue_identifier', () => {
|
|
|
|
const sentryErrorIdInput = wrapper.find(
|
|
|
|
'glforminput-stub[name="issue[sentry_issue_attributes][sentry_issue_identifier]"',
|
|
|
|
);
|
|
|
|
expect(sentryErrorIdInput.attributes('value')).toBe('129381');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should set the form values with title and description', () => {
|
|
|
|
const csrfTokenInput = wrapper.find('glforminput-stub[name="authenticity_token"]');
|
|
|
|
const issueTitleInput = wrapper.find('glforminput-stub[name="issue[title]"]');
|
|
|
|
const issueDescriptionInput = wrapper.find('input[name="issue[description]"]');
|
|
|
|
expect(csrfTokenInput.attributes('value')).toBe('fakeToken');
|
|
|
|
expect(issueTitleInput.attributes('value')).toContain(wrapper.vm.issueTitle);
|
|
|
|
expect(issueDescriptionInput.attributes('value')).toContain(wrapper.vm.issueDescription);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should submit the form', () => {
|
|
|
|
window.HTMLFormElement.prototype.submit = () => {};
|
|
|
|
const submitSpy = jest.spyOn(wrapper.vm.$refs.sentryIssueForm, 'submit');
|
|
|
|
wrapper.find('button').trigger('click');
|
|
|
|
expect(submitSpy).toHaveBeenCalled();
|
|
|
|
submitSpy.mockRestore();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('GitLab issue link', () => {
|
|
|
|
const gitlabIssue = 'https://gitlab.example.com/issues/1';
|
|
|
|
const findGitLabLink = () => wrapper.find(`[href="${gitlabIssue}"]`);
|
|
|
|
const findCreateIssueButton = () => wrapper.find('[data-qa-selector="create_issue_button"]');
|
|
|
|
|
|
|
|
describe('is present', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
store.state.details.loading = false;
|
|
|
|
store.state.details.error = {
|
|
|
|
id: 1,
|
|
|
|
gitlab_issue: gitlabIssue,
|
|
|
|
};
|
|
|
|
mountComponent();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should display the issue link', () => {
|
|
|
|
expect(findGitLabLink().exists()).toBe(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not display a create issue button', () => {
|
|
|
|
expect(findCreateIssueButton().exists()).toBe(false);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('is not present', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
store.state.details.loading = false;
|
|
|
|
store.state.details.error = {
|
|
|
|
id: 1,
|
|
|
|
gitlab_issue: null,
|
|
|
|
};
|
|
|
|
mountComponent();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not display an issue link', () => {
|
|
|
|
expect(findGitLabLink().exists()).toBe(false);
|
|
|
|
});
|
|
|
|
it('should display the create issue button', () => {
|
|
|
|
expect(findCreateIssueButton().exists()).toBe(true);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2020-03-07 23:17:34 +05:30
|
|
|
|
|
|
|
describe('Escape unsafe chars for culprit field', () => {
|
|
|
|
const findReportedText = () => wrapper.find('[data-qa-selector="reported_text"]');
|
|
|
|
const culprit = '<script>console.log("surprise!")</script>';
|
|
|
|
beforeEach(() => {
|
|
|
|
store.state.details.loadingStacktrace = false;
|
|
|
|
store.state.details.loading = false;
|
|
|
|
store.state.details.error = {
|
|
|
|
id: 1,
|
|
|
|
culprit,
|
|
|
|
};
|
|
|
|
mountComponent();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not convert interpolated text to html entities', () => {
|
|
|
|
expect(findReportedText().findAll('script').length).toEqual(0);
|
|
|
|
expect(findReportedText().findAll('strong').length).toEqual(1);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should render text instead of converting to html entities', () => {
|
|
|
|
expect(findReportedText().text()).toContain(culprit);
|
|
|
|
});
|
|
|
|
});
|
2019-12-26 22:10:19 +05:30
|
|
|
});
|
|
|
|
});
|