summaryrefslogtreecommitdiff
path: root/spec/support/shared_examples/models/concerns/issuable_shared_examples.rb
blob: f49ec90638236658f178f4b5a44c250f87bd98b1 (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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# frozen_string_literal: true

RSpec.shared_examples 'matches_cross_reference_regex? fails fast' do
  it 'fails fast for long strings' do
    # took well under 1 second in CI https://dev.gitlab.org/gitlab/gitlabhq/merge_requests/3267#note_172823
    expect do
      Timeout.timeout(6.seconds) { mentionable.matches_cross_reference_regex? }
    end.not_to raise_error
  end
end

RSpec.shared_examples 'validates description length with custom validation' do
  let(:invalid_description) { 'x' * (::Issuable::DESCRIPTION_LENGTH_MAX + 1) }
  let(:valid_description) { 'short description' }
  let(:issuable) { build(:issue, description: description) }

  let(:error_message) do
    format(
      _('is too long (%{size}). The maximum size is %{max_size}.'),
      size: ActiveSupport::NumberHelper.number_to_human_size(invalid_description.bytesize),
      max_size: ActiveSupport::NumberHelper.number_to_human_size(::Issuable::DESCRIPTION_LENGTH_MAX)
    )
  end

  subject(:validate) { issuable.validate(context) }

  context 'when Issuable is a new record' do
    let(:context) { :create }

    context 'when description exceeds the maximum size' do
      let(:description) { invalid_description }

      it 'adds a description too long error' do
        validate

        expect(issuable.errors[:description]).to contain_exactly(error_message)
      end
    end

    context 'when description is within the allowed limits' do
      let(:description) { valid_description }

      it 'does not add a validation error' do
        validate

        expect(issuable.errors).not_to have_key(:description)
      end
    end
  end

  context 'when Issuable is an existing record' do
    let(:context) { :update }

    before do
      allow(issuable).to receive(:expire_etag_cache) # to skip the expire_etag_cache callback

      issuable.description = existing_description
      issuable.save!(validate: false)
      issuable.description = description
    end

    context 'when record already had a valid description' do
      let(:existing_description) { 'small difference so it triggers description_changed?' }

      context 'when new description exceeds the maximum size' do
        let(:description) { invalid_description }

        it 'adds a description too long error' do
          validate

          expect(issuable.errors[:description]).to contain_exactly(error_message)
        end
      end

      context 'when new description is within the allowed limits' do
        let(:description) { valid_description }

        it 'does not add a validation error' do
          validate

          expect(issuable.errors).not_to have_key(:description)
        end
      end
    end

    context 'when record existed with an invalid description' do
      let(:existing_description) { "#{invalid_description} small difference so it triggers description_changed?" }

      context 'when description is not changed' do
        let(:description) { existing_description }

        it 'does not add a validation error' do
          validate

          expect(issuable.errors).not_to have_key(:description)
        end
      end

      context 'when new description exceeds the maximum size' do
        let(:description) { invalid_description }

        it 'allows updating descriptions that already existed above the limit' do
          validate

          expect(issuable.errors).not_to have_key(:description)
        end
      end

      context 'when new description is within the allowed limits' do
        let(:description) { valid_description }

        it 'does not add a validation error' do
          validate

          expect(issuable.errors).not_to have_key(:description)
        end
      end
    end
  end
end

RSpec.shared_examples 'truncates the description to its allowed maximum length on import' do
  before do
    allow(issuable).to receive(:importing?).and_return(true)
  end

  let(:issuable) { build(:issue, description: 'x' * (::Issuable::DESCRIPTION_LENGTH_MAX + 1)) }

  subject { issuable.validate(:create) }

  it 'truncates the description to its allowed maximum length' do
    subject

    expect(issuable.description).to eq('x' * ::Issuable::DESCRIPTION_LENGTH_MAX)
    expect(issuable.errors[:description]).to be_empty
  end
end