summaryrefslogtreecommitdiff
path: root/spec/frontend/error_tracking/components
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/error_tracking/components')
-rw-r--r--spec/frontend/error_tracking/components/error_details_spec.js105
-rw-r--r--spec/frontend/error_tracking/components/error_tracking_list_spec.js15
-rw-r--r--spec/frontend/error_tracking/components/stacktrace_entry_spec.js49
-rw-r--r--spec/frontend/error_tracking/components/stacktrace_spec.js45
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);
+ });
+ });
+});