summaryrefslogtreecommitdiff
path: root/spec/lib/error_tracking/stacktrace_builder_spec.rb
blob: 46d0bde8122a898963e3c4d050c8d65e65f3f2b9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# frozen_string_literal: true

require 'fast_spec_helper'
require 'support/helpers/fast_rails_root'
require 'oj'

RSpec.describe ErrorTracking::StacktraceBuilder do
  include FastRailsRoot

  describe '#stacktrace' do
    let(:original_payload) { Gitlab::Json.parse(File.read(rails_root_join('spec/fixtures', payload_file))) }
    let(:payload) { original_payload }
    let(:payload_file) { 'error_tracking/parsed_event.json' }

    subject(:stacktrace) { described_class.new(payload).stacktrace }

    context 'with full error context' do
      it 'generates a correct stacktrace in expected format' do
        expected_context = [
          [132, "          end\n"],
          [133, "\n"],
          [134, "          begin\n"],
          [135, "            block.call(work, *extra)\n"],
          [136, "          rescue Exception => e\n"],
          [137, "            STDERR.puts \"Error reached top of thread-pool: #\{e.message\} (#\{e.class\})\"\n"],
          [138, "          end\n"]
        ]

        expected_entry = {
          'lineNo' => 135,
          'context' => expected_context,
          'filename' => 'puma/thread_pool.rb',
          'function' => 'block in spawn_thread',
          'colNo' => 0
        }

        expect(stacktrace).to be_kind_of(Array)
        expect(stacktrace.first).to eq(expected_entry)
      end
    end

    context 'when error context is missing' do
      let(:payload_file) { 'error_tracking/browser_event.json' }

      it 'generates a stacktrace without context' do
        expected_entry = {
          'lineNo' => 6395,
          'context' => [],
          'filename' => 'webpack-internal:///./node_modules/vue/dist/vue.runtime.esm.js',
          'function' => 'hydrate',
          'colNo' => 0
        }

        expect(stacktrace).to be_kind_of(Array)
        expect(stacktrace.first).to eq(expected_entry)
      end
    end

    context 'with empty payload' do
      let(:payload) { {} }

      it { is_expected.to eq([]) }
    end

    context 'without exception field' do
      let(:payload) { original_payload.except('exception') }

      it { is_expected.to eq([]) }
    end

    context 'without exception.values field' do
      before do
        original_payload['exception'].delete('values')
      end

      it { is_expected.to eq([]) }
    end

    context 'without any exception.values[].stacktrace fields' do
      before do
        original_payload.dig('exception', 'values').each { |value| value['stacktrace'] = '' }
      end

      it { is_expected.to eq([]) }
    end

    context 'without any exception.values[].stacktrace.frame fields' do
      before do
        original_payload.dig('exception', 'values').each { |value| value['stacktrace'].delete('frames') }
      end

      it { is_expected.to eq([]) }
    end
  end
end