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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
|
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Mutations::ReleaseAssetLinks::Update do
include GraphqlHelpers
let_it_be(:project) { create(:project, :private, :repository) }
let_it_be(:release) { create(:release, project: project, tag: 'v13.10') }
let_it_be(:reporter) { create(:user).tap { |u| project.add_reporter(u) } }
let_it_be(:developer) { create(:user).tap { |u| project.add_developer(u) } }
let_it_be(:name) { 'link name' }
let_it_be(:url) { 'https://example.com/url' }
let_it_be(:filepath) { '/permanent/path' }
let_it_be(:link_type) { 'package' }
let_it_be(:release_link) do
create(:release_link,
release: release,
name: name,
url: url,
filepath: filepath,
link_type: link_type)
end
let(:current_user) { developer }
let(:mutation) { described_class.new(object: nil, context: { current_user: current_user }, field: nil) }
let(:mutation_arguments) do
{
id: release_link.to_global_id
}
end
shared_examples 'no changes to the link except for the' do |except_for|
it 'does not change other link properties' do
expect(updated_link.name).to eq(name) unless except_for == :name
expect(updated_link.url).to eq(url) unless except_for == :url
expect(updated_link.filepath).to eq(filepath) unless except_for == :filepath
expect(updated_link.link_type).to eq(link_type) unless except_for == :link_type
end
end
shared_examples 'validation error with messages' do |messages|
it 'returns the updated link as nil' do
expect(updated_link).to be_nil
end
it 'returns a validation error' do
expect(subject[:errors]).to match_array(messages)
end
end
describe '#ready?' do
let(:current_user) { developer }
subject(:ready) do
mutation.ready?(**mutation_arguments)
end
context 'when link_type is included as an argument but is passed nil' do
let(:mutation_arguments) { super().merge(link_type: nil) }
it 'raises a validation error' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'if the linkType argument is provided, it cannot be null')
end
end
end
describe '#resolve' do
subject(:resolve) do
mutation.resolve(**mutation_arguments)
end
let(:updated_link) { subject[:link] }
context 'when the current user has access to update the link' do
context 'name' do
let(:mutation_arguments) { super().merge(name: updated_name) }
context 'when a new name is provided' do
let(:updated_name) { 'Updated name' }
it 'updates the name' do
expect(updated_link.name).to eq(updated_name)
end
it_behaves_like 'no changes to the link except for the', :name
context 'with protected tag' do
context 'when user has access to the protected tag' do
let!(:protected_tag) { create(:protected_tag, :developers_can_create, name: '*', project: project) }
it 'does not have errors' do
subject
expect(resolve).to include(errors: [])
end
end
context 'when user does not have access to the protected tag' do
let!(:protected_tag) { create(:protected_tag, :maintainers_can_create, name: '*', project: project) }
it 'raises a resource access error' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
end
end
context 'when nil is provided' do
let(:updated_name) { nil }
it_behaves_like 'validation error with messages', ["Name can't be blank"]
end
end
context 'url' do
let(:mutation_arguments) { super().merge(url: updated_url) }
context 'when a new URL is provided' do
let(:updated_url) { 'https://example.com/updated/link' }
it 'updates the url' do
expect(updated_link.url).to eq(updated_url)
end
it_behaves_like 'no changes to the link except for the', :url
end
context 'when nil is provided' do
let(:updated_url) { nil }
it_behaves_like 'validation error with messages', ["Url can't be blank", "Url must be a valid URL"]
end
end
context 'filepath' do
let(:mutation_arguments) { super().merge(filepath: updated_filepath) }
context 'when a new filepath is provided' do
let(:updated_filepath) { '/updated/filepath' }
it 'updates the filepath' do
expect(updated_link.filepath).to eq(updated_filepath)
end
it_behaves_like 'no changes to the link except for the', :filepath
end
context 'when nil is provided' do
let(:updated_filepath) { nil }
it 'updates the filepath to nil' do
expect(updated_link.filepath).to be_nil
end
end
end
context 'link_type' do
let(:mutation_arguments) { super().merge(link_type: updated_link_type) }
context 'when a new link type is provided' do
let(:updated_link_type) { 'image' }
it 'updates the link type' do
expect(updated_link.link_type).to eq(updated_link_type)
end
it_behaves_like 'no changes to the link except for the', :link_type
end
# Test cases not included:
# - when nil is provided, because this validated by #ready?
# - when an invalid type is provided, because this is validated by the GraphQL schema
end
end
context 'when the current user does not have access to update the link' do
let(:current_user) { reporter }
it 'raises an error' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
context "when the link doesn't exist" do
let(:mutation_arguments) do
super().merge(id: global_id_of(id: non_existing_record_id, model_name: "Releases::Link"))
end
it 'raises an error' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
end
end
|