diff options
Diffstat (limited to 'spec/frontend/error_tracking/components')
4 files changed, 209 insertions, 5 deletions
diff --git a/spec/frontend/error_tracking/components/error_details_spec.js b/spec/frontend/error_tracking/components/error_details_spec.js new file mode 100644 index 00000000000..54e8b0848a2 --- /dev/null +++ b/spec/frontend/error_tracking/components/error_details_spec.js @@ -0,0 +1,105 @@ +import { createLocalVue, shallowMount } from '@vue/test-utils'; +import Vuex from 'vuex'; +import { GlLoadingIcon, GlLink } from '@gitlab/ui'; +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, { + localVue, + store, + propsData: { + issueDetailsPath: '/123/details', + issueStackTracePath: '/stacktrace', + }, + }); + } + + 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); + }); + }); + }); +}); diff --git a/spec/frontend/error_tracking/components/error_tracking_list_spec.js b/spec/frontend/error_tracking/components/error_tracking_list_spec.js index ce8b8908026..1bbf23cc602 100644 --- a/spec/frontend/error_tracking/components/error_tracking_list_spec.js +++ b/spec/frontend/error_tracking/components/error_tracking_list_spec.js @@ -34,7 +34,7 @@ describe('ErrorTrackingList', () => { beforeEach(() => { actions = { - getErrorList: () => {}, + getSentryData: () => {}, startPolling: () => {}, restartPolling: jest.fn().mockName('restartPolling'), }; @@ -45,8 +45,13 @@ describe('ErrorTrackingList', () => { }; store = new Vuex.Store({ - actions, - state, + modules: { + list: { + namespaced: true, + actions, + state, + }, + }, }); }); @@ -70,7 +75,7 @@ describe('ErrorTrackingList', () => { describe('results', () => { beforeEach(() => { - store.state.loading = false; + store.state.list.loading = false; mountComponent(); }); @@ -84,7 +89,7 @@ describe('ErrorTrackingList', () => { describe('no results', () => { beforeEach(() => { - store.state.loading = false; + store.state.list.loading = false; mountComponent(); }); diff --git a/spec/frontend/error_tracking/components/stacktrace_entry_spec.js b/spec/frontend/error_tracking/components/stacktrace_entry_spec.js new file mode 100644 index 00000000000..95958408770 --- /dev/null +++ b/spec/frontend/error_tracking/components/stacktrace_entry_spec.js @@ -0,0 +1,49 @@ +import { shallowMount } from '@vue/test-utils'; +import StackTraceEntry from '~/error_tracking/components/stacktrace_entry.vue'; +import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; +import FileIcon from '~/vue_shared/components/file_icon.vue'; +import Icon from '~/vue_shared/components/icon.vue'; + +describe('Stacktrace Entry', () => { + let wrapper; + + function mountComponent(props) { + wrapper = shallowMount(StackTraceEntry, { + propsData: { + filePath: 'sidekiq/util.rb', + lines: [ + [22, ' def safe_thread(name, \u0026block)\n'], + [23, ' Thread.new do\n'], + [24, " Thread.current['sidekiq_label'] = name\n"], + [25, ' watchdog(name, \u0026block)\n'], + ], + errorLine: 24, + ...props, + }, + }); + } + + beforeEach(() => { + mountComponent(); + }); + + afterEach(() => { + if (wrapper) { + wrapper.destroy(); + } + }); + + it('should render stacktrace entry collapsed', () => { + expect(wrapper.find(StackTraceEntry).exists()).toBe(true); + expect(wrapper.find(ClipboardButton).exists()).toBe(true); + expect(wrapper.find(Icon).exists()).toBe(true); + expect(wrapper.find(FileIcon).exists()).toBe(true); + expect(wrapper.element.querySelectorAll('table').length).toBe(0); + }); + + it('should render stacktrace entry table expanded', () => { + mountComponent({ expanded: true }); + expect(wrapper.element.querySelectorAll('tr.line_holder').length).toBe(4); + expect(wrapper.element.querySelectorAll('.line_content.old').length).toBe(1); + }); +}); diff --git a/spec/frontend/error_tracking/components/stacktrace_spec.js b/spec/frontend/error_tracking/components/stacktrace_spec.js new file mode 100644 index 00000000000..4f4a60acba4 --- /dev/null +++ b/spec/frontend/error_tracking/components/stacktrace_spec.js @@ -0,0 +1,45 @@ +import { shallowMount } from '@vue/test-utils'; +import Stacktrace from '~/error_tracking/components/stacktrace.vue'; +import StackTraceEntry from '~/error_tracking/components/stacktrace_entry.vue'; + +describe('ErrorDetails', () => { + let wrapper; + + const stackTraceEntry = { + filename: 'sidekiq/util.rb', + context: [ + [22, ' def safe_thread(name, \u0026block)\n'], + [23, ' Thread.new do\n'], + [24, " Thread.current['sidekiq_label'] = name\n"], + [25, ' watchdog(name, \u0026block)\n'], + ], + lineNo: 24, + }; + + function mountComponent(entries) { + wrapper = shallowMount(Stacktrace, { + propsData: { + entries, + }, + }); + } + + describe('Stacktrace', () => { + afterEach(() => { + if (wrapper) { + wrapper.destroy(); + } + }); + + it('should render single Stacktrace entry', () => { + mountComponent([stackTraceEntry]); + expect(wrapper.findAll(StackTraceEntry).length).toBe(1); + }); + + it('should render multiple Stacktrace entry', () => { + const entriesNum = 3; + mountComponent(new Array(entriesNum).fill(stackTraceEntry)); + expect(wrapper.findAll(StackTraceEntry).length).toBe(entriesNum); + }); + }); +}); |