summaryrefslogtreecommitdiff
path: root/spec/support/shared_examples/graphql/notes_creation_shared_examples.rb
blob: 3ff93371c190a83eeaccc2a49a4ac91a919d36bd (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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# frozen_string_literal: true

RSpec.shared_examples 'a Note mutation that does not create a Note' do
  it do
    expect do
      post_graphql_mutation(mutation, current_user: current_user)
    end.not_to change { Note.count }
  end
end

RSpec.shared_examples 'a Note mutation that creates a Note' do
  it do
    expect do
      post_graphql_mutation(mutation, current_user: current_user)
    end.to change { Note.count }.by(1)
  end
end

RSpec.shared_examples 'a Note mutation when the user does not have permission' do
  it_behaves_like 'a Note mutation that does not create a Note'

  it_behaves_like 'a mutation that returns top-level errors',
    errors: ['The resource that you are attempting to access does not exist or you don\'t have permission to perform this action']
end

RSpec.shared_examples 'a Note mutation when there are active record validation errors' do |model: Note|
  before do
    expect_next_instance_of(model) do |note|
      allow(note).to receive_message_chain(:errors, :empty?).and_return(true)
      expect(note).to receive(:valid?).at_least(:once).and_return(false)
      expect(note).to receive_message_chain(
        :errors,
        :full_messages
      ).and_return(['Error 1', 'Error 2'])
    end
  end

  it_behaves_like 'a Note mutation that does not create a Note'

  it_behaves_like 'a mutation that returns errors in the response', errors: ['Error 1', 'Error 2']

  it 'returns an empty Note' do
    post_graphql_mutation(mutation, current_user: current_user)

    expect(mutation_response).to have_key('note')
    expect(mutation_response['note']).to be_nil
  end
end

RSpec.shared_examples 'a Note mutation when the given resource id is not for a Noteable' do
  let(:noteable) { create(:label, project: project) }

  it_behaves_like 'a Note mutation that does not create a Note'

  it_behaves_like 'a mutation that returns top-level errors' do
    let(:match_errors) { include(/ does not represent an instance of Noteable/) }
  end
end

RSpec.shared_examples 'a Note mutation when the given resource id is not for a Note' do
  let(:note) { create(:issue) }

  it_behaves_like 'a mutation that returns top-level errors' do
    let(:match_errors) { include(/does not represent an instance of Note/) }
  end
end

RSpec.shared_examples 'a Note mutation when there are rate limit validation errors' do
  context 'with rate limiter', :freeze_time, :clean_gitlab_redis_rate_limiting do
    before do
      stub_application_setting(notes_create_limit: 3)
      3.times { post_graphql_mutation(mutation, current_user: current_user) }
    end

    it_behaves_like 'a Note mutation that does not create a Note'
    it_behaves_like 'a mutation that returns top-level errors',
      errors: ['This endpoint has been requested too many times. Try again later.']

    context 'when the user is in the allowlist' do
      before do
        stub_application_setting(notes_create_limit_allowlist: [current_user.username.to_s])
      end

      it_behaves_like 'a Note mutation that creates a Note'
    end
  end
end

RSpec.shared_examples 'a Note mutation with confidential notes' do
  it_behaves_like 'a Note mutation that creates a Note'

  it 'returns a Note with confidentiality enabled' do
    post_graphql_mutation(mutation, current_user: current_user)

    expect(mutation_response).to have_key('note')
    expect(mutation_response['note']['confidential']).to eq(true)
    expect(mutation_response['note']['internal']).to eq(true)
  end
end

RSpec.shared_examples 'a Note mutation updates a note successfully' do
  it 'updates the Note' do
    post_graphql_mutation(mutation, current_user: current_user)

    expect(note.reload.note).to eq(updated_body)
  end

  it 'returns the updated Note' do
    post_graphql_mutation(mutation, current_user: current_user)

    expect(mutation_response['note']['body']).to eq(updated_body)
  end
end

RSpec.shared_examples 'a Note mutation update with errors' do
  context 'when there are ActiveRecord validation errors' do
    let(:params) { { body: '', confidential: true } }

    it_behaves_like 'a mutation that returns errors in the response',
      errors: ["Note can't be blank", 'Confidential can not be changed for existing notes']

    it 'does not update the Note' do
      post_graphql_mutation(mutation, current_user: current_user)

      expect(note.reload.note).to eq(original_body)
      expect(note.confidential).to be_falsey
    end

    it 'returns the original Note' do
      post_graphql_mutation(mutation, current_user: current_user)

      expect(mutation_response['note']['body']).to eq(original_body)
      expect(mutation_response['note']['confidential']).to be_falsey
    end
  end
end

RSpec.shared_examples 'a Note mutation update only with quick actions' do
  context 'when body only contains quick actions' do
    let(:updated_body) { '/close' }

    it 'returns a nil note and empty errors' do
      post_graphql_mutation(mutation, current_user: current_user)

      expect(mutation_response).to include(
        'errors' => [],
        'note' => nil
      )
    end
  end
end