gds-api-adapters 63.0.0 → 63.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/gds_api/publishing_api.rb +496 -4
- data/lib/gds_api/publishing_api/special_route_publisher.rb +2 -2
- data/lib/gds_api/publishing_api_v2.rb +5 -488
- data/lib/gds_api/test_helpers/publishing_api.rb +760 -29
- data/lib/gds_api/test_helpers/publishing_api_v2.rb +3 -689
- data/lib/gds_api/version.rb +1 -1
- metadata +2 -2
@@ -5,12 +5,630 @@ require "json"
|
|
5
5
|
|
6
6
|
module GdsApi
|
7
7
|
module TestHelpers
|
8
|
+
# @api documented
|
8
9
|
module PublishingApi
|
9
10
|
include ContentItemHelpers
|
10
11
|
include IntentHelpers
|
11
12
|
|
13
|
+
PUBLISHING_API_V2_ENDPOINT = Plek.current.find("publishing-api") + "/v2"
|
12
14
|
PUBLISHING_API_ENDPOINT = Plek.current.find("publishing-api")
|
13
15
|
|
16
|
+
# Stub a PUT /v2/content/:content_id request with the given content id and request body.
|
17
|
+
# if no response_hash is given, a default response as follows is created:
|
18
|
+
# {status: 200, body: '{}', headers: {"Content-Type" => "application/json; charset=utf-8"}}
|
19
|
+
#
|
20
|
+
# if a response is given, then it will be merged with the default response.
|
21
|
+
# if the given parameter for the response body is a Hash, it will be converted to JSON.
|
22
|
+
#
|
23
|
+
# The following two examples are equivalent:
|
24
|
+
# @example
|
25
|
+
# stub_publishing_api_put_content(my_content_id, my_request_body, { status: 201, body: {version: 33}.to_json })
|
26
|
+
#
|
27
|
+
# @example
|
28
|
+
# stub_publishing_api_put_content(my_content_id, my_request_body, { status: 201, body: {version: 33} })
|
29
|
+
#
|
30
|
+
# @param content_id [UUID]
|
31
|
+
# @param body [String]
|
32
|
+
# @param response_hash [Hash]
|
33
|
+
def stub_publishing_api_put_content(content_id, body, response_hash = {})
|
34
|
+
stub_publishing_api_put(content_id, body, "/content", response_hash)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Stub a PATCH /v2/links/:content_id request
|
38
|
+
#
|
39
|
+
# @example
|
40
|
+
# stub_publishing_api_patch_links(
|
41
|
+
# my_content_id,
|
42
|
+
# "links" => {
|
43
|
+
# "taxons" => %w(level_one_topic level_two_topic),
|
44
|
+
# },
|
45
|
+
# "previous_version" => 3,
|
46
|
+
# )
|
47
|
+
#
|
48
|
+
# @param content_id [UUID]
|
49
|
+
# @param body [String]
|
50
|
+
def stub_publishing_api_patch_links(content_id, body)
|
51
|
+
stub_publishing_api_patch(content_id, body, "/links")
|
52
|
+
end
|
53
|
+
|
54
|
+
# Stub a PATCH /v2/links/:content_id request to return a 409 response
|
55
|
+
#
|
56
|
+
# @example
|
57
|
+
# stub_publishing_api_patch_links_conflict(
|
58
|
+
# my_content_id,
|
59
|
+
# "links" => {
|
60
|
+
# "taxons" => %w(level_one_topic level_two_topic),
|
61
|
+
# },
|
62
|
+
# "previous_version" => 3,
|
63
|
+
# )
|
64
|
+
#
|
65
|
+
# @param content_id [UUID]
|
66
|
+
# @param body [String]
|
67
|
+
def stub_publishing_api_patch_links_conflict(content_id, body)
|
68
|
+
previous_version = JSON.parse(body.to_json)["previous_version"]
|
69
|
+
override_response_hash = { status: 409, body: version_conflict(previous_version) }
|
70
|
+
stub_publishing_api_patch(content_id, body, "/links", override_response_hash)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Stub a POST /v2/content/:content_id/publish request
|
74
|
+
#
|
75
|
+
# @param content_id [UUID]
|
76
|
+
# @param body [String]
|
77
|
+
# @param response_hash [Hash]
|
78
|
+
def stub_publishing_api_publish(content_id, body, response_hash = {})
|
79
|
+
url = PUBLISHING_API_V2_ENDPOINT + "/content/#{content_id}/publish"
|
80
|
+
response = {
|
81
|
+
status: 200,
|
82
|
+
body: "{}",
|
83
|
+
headers: { "Content-Type" => "application/json; charset=utf-8" },
|
84
|
+
}.merge(response_hash)
|
85
|
+
stub_request(:post, url).with(body: body).to_return(response)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Stub a POST /v2/content/:content_id/republish request
|
89
|
+
#
|
90
|
+
# @param content_id [UUID]
|
91
|
+
# @param body [String]
|
92
|
+
# @param response_hash [Hash]
|
93
|
+
def stub_publishing_api_republish(content_id, body = {}, response_hash = {})
|
94
|
+
url = PUBLISHING_API_V2_ENDPOINT + "/content/#{content_id}/republish"
|
95
|
+
response = {
|
96
|
+
status: 200,
|
97
|
+
body: "{}",
|
98
|
+
headers: { "Content-Type" => "application/json; charset=utf-8" },
|
99
|
+
}.merge(response_hash)
|
100
|
+
stub_request(:post, url).with(body: body).to_return(response)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Stub a POST /v2/content/:content_id/unpublish request
|
104
|
+
#
|
105
|
+
# @param content_id [UUID]
|
106
|
+
# @param params [Hash]
|
107
|
+
# @param body [String]
|
108
|
+
def stub_publishing_api_unpublish(content_id, params, response_hash = {})
|
109
|
+
url = PUBLISHING_API_V2_ENDPOINT + "/content/#{content_id}/unpublish"
|
110
|
+
response = {
|
111
|
+
status: 200,
|
112
|
+
body: "{}",
|
113
|
+
headers: { "Content-Type" => "application/json; charset=utf-8" },
|
114
|
+
}.merge(response_hash)
|
115
|
+
stub_request(:post, url).with(params).to_return(response)
|
116
|
+
end
|
117
|
+
|
118
|
+
# Stub a POST /v2/content/:content_id/discard-draft request
|
119
|
+
#
|
120
|
+
# @param content_id [UUID]
|
121
|
+
def stub_publishing_api_discard_draft(content_id)
|
122
|
+
url = PUBLISHING_API_V2_ENDPOINT + "/content/#{content_id}/discard-draft"
|
123
|
+
stub_request(:post, url).to_return(status: 200, headers: { "Content-Type" => "application/json; charset=utf-8" })
|
124
|
+
end
|
125
|
+
|
126
|
+
# Stub requests issued when publishing a new draft.
|
127
|
+
# - PUT /v2/content/:content_id
|
128
|
+
# - POST /v2/content/:content_id/publish
|
129
|
+
# - PATCH /v2/links/:content_id
|
130
|
+
#
|
131
|
+
# @param body [String]
|
132
|
+
# @param content_id [UUID]
|
133
|
+
# @param publish_body [Hash]
|
134
|
+
def stub_publishing_api_put_content_links_and_publish(body, content_id = nil, publish_body = nil)
|
135
|
+
content_id ||= body[:content_id]
|
136
|
+
if publish_body.nil?
|
137
|
+
publish_body = { update_type: body.fetch(:update_type) }
|
138
|
+
publish_body[:locale] = body[:locale] if body[:locale]
|
139
|
+
end
|
140
|
+
stubs = []
|
141
|
+
stubs << stub_publishing_api_put_content(content_id, body.except(:links))
|
142
|
+
stubs << stub_publishing_api_patch_links(content_id, body.slice(:links)) unless body.slice(:links).empty?
|
143
|
+
stubs << stub_publishing_api_publish(content_id, publish_body)
|
144
|
+
stubs
|
145
|
+
end
|
146
|
+
|
147
|
+
# Stub any PUT /v2/content/* request
|
148
|
+
def stub_any_publishing_api_put_content
|
149
|
+
stub_request(:put, %r{\A#{PUBLISHING_API_V2_ENDPOINT}/content/})
|
150
|
+
end
|
151
|
+
|
152
|
+
# Stub any PATCH /v2/links/* request
|
153
|
+
def stub_any_publishing_api_patch_links
|
154
|
+
stub_request(:patch, %r{\A#{PUBLISHING_API_V2_ENDPOINT}/links/})
|
155
|
+
end
|
156
|
+
|
157
|
+
# Stub any POST /v2/content/*/publish request
|
158
|
+
def stub_any_publishing_api_publish
|
159
|
+
stub_request(:post, %r{\A#{PUBLISHING_API_V2_ENDPOINT}/content/.*/publish})
|
160
|
+
end
|
161
|
+
|
162
|
+
# Stub any POST /v2/content/*/publish request
|
163
|
+
def stub_any_publishing_api_republish
|
164
|
+
stub_request(:post, %r{\A#{PUBLISHING_API_V2_ENDPOINT}/content/.*/republish})
|
165
|
+
end
|
166
|
+
|
167
|
+
# Stub any POST /v2/content/*/unpublish request
|
168
|
+
def stub_any_publishing_api_unpublish
|
169
|
+
stub_request(:post, %r{\A#{PUBLISHING_API_V2_ENDPOINT}/content/.*/unpublish})
|
170
|
+
end
|
171
|
+
|
172
|
+
# Stub any POST /v2/content/*/discard-draft request
|
173
|
+
def stub_any_publishing_api_discard_draft
|
174
|
+
stub_request(:post, %r{\A#{PUBLISHING_API_V2_ENDPOINT}/content/.*/discard-draft})
|
175
|
+
end
|
176
|
+
|
177
|
+
# Stub any version 2 request to the publishing API
|
178
|
+
def stub_any_publishing_api_call
|
179
|
+
stub_request(:any, %r{\A#{PUBLISHING_API_V2_ENDPOINT}})
|
180
|
+
end
|
181
|
+
|
182
|
+
# Stub any version 2 request to the publishing API to return a 404 response
|
183
|
+
def stub_any_publishing_api_call_to_return_not_found
|
184
|
+
stub_request(:any, %r{\A#{PUBLISHING_API_V2_ENDPOINT}})
|
185
|
+
.to_return(status: 404, headers: { "Content-Type" => "application/json; charset=utf-8" })
|
186
|
+
end
|
187
|
+
|
188
|
+
# Stub any version 2 request to the publishing API to return a 503 response
|
189
|
+
def stub_publishing_api_isnt_available
|
190
|
+
stub_request(:any, /#{PUBLISHING_API_V2_ENDPOINT}\/.*/).to_return(status: 503)
|
191
|
+
stub_request(:any, /#{PUBLISHING_API_ENDPOINT}\/.*/).to_return(status: 503)
|
192
|
+
end
|
193
|
+
|
194
|
+
# Assert that a draft was saved and published, and links were updated.
|
195
|
+
# - PUT /v2/content/:content_id
|
196
|
+
# - POST /v2/content/:content_id/publish
|
197
|
+
# - PATCH /v2/links/:content_id
|
198
|
+
#
|
199
|
+
# @param body [String]
|
200
|
+
# @param content_id [UUID]
|
201
|
+
# @param publish_body [Hash]
|
202
|
+
def assert_publishing_api_put_content_links_and_publish(body, content_id = nil, publish_body = nil)
|
203
|
+
content_id ||= body[:content_id]
|
204
|
+
if publish_body.nil?
|
205
|
+
publish_body = { update_type: body.fetch(:update_type) }
|
206
|
+
publish_body[:locale] = body[:locale] if body[:locale]
|
207
|
+
end
|
208
|
+
assert_publishing_api_put_content(content_id, body.except(:links))
|
209
|
+
assert_publishing_api_patch_links(content_id, body.slice(:links)) unless body.slice(:links).empty?
|
210
|
+
assert_publishing_api_publish(content_id, publish_body)
|
211
|
+
end
|
212
|
+
|
213
|
+
# Assert that content was saved (PUT /v2/content/:content_id)
|
214
|
+
#
|
215
|
+
# @param content_id [UUID]
|
216
|
+
# @param attributes_or_matcher [Object]
|
217
|
+
# @param times [Integer]
|
218
|
+
def assert_publishing_api_put_content(content_id, attributes_or_matcher = nil, times = 1)
|
219
|
+
url = PUBLISHING_API_V2_ENDPOINT + "/content/" + content_id
|
220
|
+
assert_publishing_api(:put, url, attributes_or_matcher, times)
|
221
|
+
end
|
222
|
+
|
223
|
+
# Assert that content was published (POST /v2/content/:content_id/publish)
|
224
|
+
#
|
225
|
+
# @param content_id [UUID]
|
226
|
+
# @param attributes_or_matcher [Object]
|
227
|
+
# @param times [Integer]
|
228
|
+
def assert_publishing_api_publish(content_id, attributes_or_matcher = nil, times = 1)
|
229
|
+
url = PUBLISHING_API_V2_ENDPOINT + "/content/#{content_id}/publish"
|
230
|
+
assert_publishing_api(:post, url, attributes_or_matcher, times)
|
231
|
+
end
|
232
|
+
|
233
|
+
# Assert that content was unpublished (POST /v2/content/:content_id/unpublish)
|
234
|
+
#
|
235
|
+
# @param content_id [UUID]
|
236
|
+
# @param attributes_or_matcher [Object]
|
237
|
+
# @param times [Integer]
|
238
|
+
def assert_publishing_api_unpublish(content_id, attributes_or_matcher = nil, times = 1)
|
239
|
+
url = PUBLISHING_API_V2_ENDPOINT + "/content/#{content_id}/unpublish"
|
240
|
+
assert_publishing_api(:post, url, attributes_or_matcher, times)
|
241
|
+
end
|
242
|
+
|
243
|
+
# Assert that links were updated (PATCH /v2/links/:content_id)
|
244
|
+
#
|
245
|
+
# @param content_id [UUID]
|
246
|
+
# @param attributes_or_matcher [Object]
|
247
|
+
# @param times [Integer]
|
248
|
+
def assert_publishing_api_patch_links(content_id, attributes_or_matcher = nil, times = 1)
|
249
|
+
url = PUBLISHING_API_V2_ENDPOINT + "/links/" + content_id
|
250
|
+
assert_publishing_api(:patch, url, attributes_or_matcher, times)
|
251
|
+
end
|
252
|
+
|
253
|
+
# Assert that a draft was discarded (POST /v2/content/:content_id/discard-draft)
|
254
|
+
#
|
255
|
+
# @param content_id [UUID]
|
256
|
+
# @param attributes_or_matcher [Object]
|
257
|
+
# @param times [Integer]
|
258
|
+
def assert_publishing_api_discard_draft(content_id, attributes_or_matcher = nil, times = 1)
|
259
|
+
url = PUBLISHING_API_V2_ENDPOINT + "/content/#{content_id}/discard-draft"
|
260
|
+
assert_publishing_api(:post, url, attributes_or_matcher, times)
|
261
|
+
end
|
262
|
+
|
263
|
+
# Assert that a request was made to the publishing API
|
264
|
+
#
|
265
|
+
# @param verb [String]
|
266
|
+
# @param url [String]
|
267
|
+
# @param attributes_or_matcher [Object]
|
268
|
+
# @param times [Integer]
|
269
|
+
def assert_publishing_api(verb, url, attributes_or_matcher = nil, times = 1)
|
270
|
+
if attributes_or_matcher.is_a?(Hash)
|
271
|
+
matcher = request_json_matches(attributes_or_matcher)
|
272
|
+
else
|
273
|
+
matcher = attributes_or_matcher
|
274
|
+
end
|
275
|
+
|
276
|
+
if matcher
|
277
|
+
assert_requested(verb, url, times: times, &matcher)
|
278
|
+
else
|
279
|
+
assert_requested(verb, url, times: times)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
# Get a request matcher that checks if a JSON request includes a set of attributes
|
284
|
+
def request_json_includes(required_attributes)
|
285
|
+
->(request) do
|
286
|
+
data = JSON.parse(request.body)
|
287
|
+
deep_stringify_keys(required_attributes).
|
288
|
+
to_a.all? { |key, value| data[key] == value }
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
# Get a request matcher that checks if a JSON request matches a hash
|
293
|
+
def request_json_matches(required_attributes)
|
294
|
+
->(request) do
|
295
|
+
data = JSON.parse(request.body)
|
296
|
+
deep_stringify_keys(required_attributes) == data
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
# Stub GET /v2/content/ to return a set of content items
|
301
|
+
#
|
302
|
+
# @example
|
303
|
+
#
|
304
|
+
# stub_publishing_api_has_content(
|
305
|
+
# vehicle_recalls_and_faults, # this is a variable containing an array of content items
|
306
|
+
# document_type: described_class.publishing_api_document_type, #example of a document_type: "vehicle_recalls_and_faults_alert"
|
307
|
+
# fields: fields, #example: let(:fields) { %i[base_path content_id public_updated_at title publication_state] }
|
308
|
+
# page: 1,
|
309
|
+
# per_page: 50
|
310
|
+
# )
|
311
|
+
# @param items [Array]
|
312
|
+
# @param params [Hash]
|
313
|
+
def stub_publishing_api_has_content(items, params = {})
|
314
|
+
url = PUBLISHING_API_V2_ENDPOINT + "/content"
|
315
|
+
|
316
|
+
if params.respond_to? :fetch
|
317
|
+
per_page = params.fetch(:per_page, 50)
|
318
|
+
page = params.fetch(:page, 1)
|
319
|
+
else
|
320
|
+
per_page = 50
|
321
|
+
page = 1
|
322
|
+
end
|
323
|
+
|
324
|
+
start_position = (page - 1) * per_page
|
325
|
+
page_items = items.slice(start_position, per_page) || []
|
326
|
+
|
327
|
+
number_of_pages =
|
328
|
+
if items.count < per_page
|
329
|
+
1
|
330
|
+
else
|
331
|
+
(items.count / per_page.to_f).ceil
|
332
|
+
end
|
333
|
+
|
334
|
+
body = {
|
335
|
+
results: page_items,
|
336
|
+
total: items.count,
|
337
|
+
pages: number_of_pages,
|
338
|
+
current_page: page,
|
339
|
+
}
|
340
|
+
|
341
|
+
stub_request(:get, url)
|
342
|
+
.with(query: params)
|
343
|
+
.to_return(status: 200, body: body.to_json, headers: {})
|
344
|
+
end
|
345
|
+
|
346
|
+
# This method has been refactored into publishing_api_has_content (above)
|
347
|
+
# publishing_api_has_content allows for flexible passing in of arguments, please use instead
|
348
|
+
def stub_publishing_api_has_fields_for_document(document_type, items, fields)
|
349
|
+
body = Array(items).map { |item|
|
350
|
+
deep_stringify_keys(item).slice(*fields)
|
351
|
+
}
|
352
|
+
|
353
|
+
query_params = fields.map { |f|
|
354
|
+
"&fields%5B%5D=#{f}"
|
355
|
+
}
|
356
|
+
|
357
|
+
url = PUBLISHING_API_V2_ENDPOINT + "/content?document_type=#{document_type}#{query_params.join('')}"
|
358
|
+
|
359
|
+
stub_request(:get, url).to_return(status: 200, body: { results: body }.to_json, headers: {})
|
360
|
+
end
|
361
|
+
|
362
|
+
# Stub GET /v2/linkables to return a set of content items with a specific document type
|
363
|
+
#
|
364
|
+
# @param linkables [Array]
|
365
|
+
def stub_publishing_api_has_linkables(linkables, document_type:)
|
366
|
+
url = PUBLISHING_API_V2_ENDPOINT + "/linkables?document_type=#{document_type}"
|
367
|
+
stub_request(:get, url).to_return(status: 200, body: linkables.to_json, headers: {})
|
368
|
+
end
|
369
|
+
|
370
|
+
# Stub GET /v2/content/:content_id to return a specific content item hash
|
371
|
+
#
|
372
|
+
# @param item [Hash]
|
373
|
+
def stub_publishing_api_has_item(item, params = {})
|
374
|
+
item = deep_transform_keys(item, &:to_sym)
|
375
|
+
url = PUBLISHING_API_V2_ENDPOINT + "/content/" + item[:content_id]
|
376
|
+
stub_request(:get, url)
|
377
|
+
.with(query: hash_including(params))
|
378
|
+
.to_return(status: 200, body: item.to_json, headers: {})
|
379
|
+
end
|
380
|
+
|
381
|
+
# Stub GET /v2/content/:content_id to progress through a series of responses.
|
382
|
+
#
|
383
|
+
# @param items [Array]
|
384
|
+
def stub_publishing_api_has_item_in_sequence(content_id, items)
|
385
|
+
items = items.each { |item| deep_transform_keys(item, &:to_sym) }
|
386
|
+
url = PUBLISHING_API_V2_ENDPOINT + "/content/" + content_id
|
387
|
+
calls = -1
|
388
|
+
|
389
|
+
stub_request(:get, url).to_return do |_request|
|
390
|
+
calls += 1
|
391
|
+
item = items[calls] || items.last
|
392
|
+
|
393
|
+
{ status: 200, body: item.to_json, headers: {} }
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
# Stub GET /v2/content/:content_id to return a 404 response
|
398
|
+
#
|
399
|
+
# @param content_id [UUID]
|
400
|
+
def stub_publishing_api_does_not_have_item(content_id)
|
401
|
+
url = PUBLISHING_API_V2_ENDPOINT + "/content/" + content_id
|
402
|
+
stub_request(:get, url).to_return(status: 404, body: resource_not_found(content_id, "content item").to_json, headers: {})
|
403
|
+
end
|
404
|
+
|
405
|
+
# Stub a request to links endpoint
|
406
|
+
#
|
407
|
+
# @param [Hash] links the structure of the links hash
|
408
|
+
#
|
409
|
+
# @example
|
410
|
+
#
|
411
|
+
# stub_publishing_api_has_links(
|
412
|
+
# {
|
413
|
+
# "content_id" => "64aadc14-9bca-40d9-abb6-4f21f9792a05",
|
414
|
+
# "links" => {
|
415
|
+
# "mainstream_browse_pages" => ["df2e7a3e-2078-45de-a75a-fd37d027427e"],
|
416
|
+
# "parent" => ["df2e7a3e-2078-45de-a75a-fd37d027427e"],
|
417
|
+
# "organisations" => ["569a9ee5-c195-4b7f-b9dc-edc17a09113f", "5c54ae52-341b-499e-a6dd-67f04633b8cf"]
|
418
|
+
# },
|
419
|
+
# "version" => 6
|
420
|
+
# }
|
421
|
+
# )
|
422
|
+
#
|
423
|
+
# @example
|
424
|
+
#
|
425
|
+
# Services.publishing_api.get_links("64aadc14-9bca-40d9-abb6-4f21f9792a05")
|
426
|
+
# => {
|
427
|
+
# "content_id" => "64aadc14-9bca-40d9-abb6-4f21f9792a05",
|
428
|
+
# "links" => {
|
429
|
+
# "mainstream_browse_pages" => ["df2e7a3e-2078-45de-a75a-fd37d027427e"],
|
430
|
+
# "parent" => ["df2e7a3e-2078-45de-a75a-fd37d027427e"],
|
431
|
+
# "organisations" => ["569a9ee5-c195-4b7f-b9dc-edc17a09113f", "5c54ae52-341b-499e-a6dd-67f04633b8cf"]
|
432
|
+
# },
|
433
|
+
# "version" => 6
|
434
|
+
# }
|
435
|
+
def stub_publishing_api_has_links(links)
|
436
|
+
links = deep_transform_keys(links, &:to_sym)
|
437
|
+
url = PUBLISHING_API_V2_ENDPOINT + "/links/" + links[:content_id]
|
438
|
+
stub_request(:get, url).to_return(status: 200, body: links.to_json, headers: {})
|
439
|
+
end
|
440
|
+
|
441
|
+
# Stub a request to the expanded links endpoint
|
442
|
+
#
|
443
|
+
# @param [Hash] links the structure of the links hash
|
444
|
+
#
|
445
|
+
# @example
|
446
|
+
# stub_publishing_api_has_expanded_links(
|
447
|
+
# {
|
448
|
+
# "content_id" => "64aadc14-9bca-40d9-abb4-4f21f9792a05",
|
449
|
+
# "expanded_links" => {
|
450
|
+
# "mainstream_browse_pages" => [
|
451
|
+
# {
|
452
|
+
# "content_id" => "df2e7a3e-2078-45de-a76a-fd37d027427a",
|
453
|
+
# "base_path" => "/a/base/path",
|
454
|
+
# "document_type" => "mainstream_browse_page",
|
455
|
+
# "locale" => "en",
|
456
|
+
# "links" => {},
|
457
|
+
# # ...
|
458
|
+
# }
|
459
|
+
# ],
|
460
|
+
# "parent" => [
|
461
|
+
# {
|
462
|
+
# "content_id" => "df2e7a3e-2028-45de-a75a-fd37d027427e",
|
463
|
+
# "document_type" => "mainstream_browse_page",
|
464
|
+
# # ...
|
465
|
+
# },
|
466
|
+
# ]
|
467
|
+
# }
|
468
|
+
# }
|
469
|
+
# )
|
470
|
+
#
|
471
|
+
# @example
|
472
|
+
# Services.publishing_api.expanded_links("64aadc14-9bca-40d9-abb4-4f21f9792a05")
|
473
|
+
# => {
|
474
|
+
# "content_id" => "64aadc14-9bca-40d9-abb4-4f21f9792a05",
|
475
|
+
# "expanded_links" => {
|
476
|
+
# "mainstream_browse_pages" => [
|
477
|
+
# {
|
478
|
+
# "content_id" => "df2e7a3e-2078-45de-a76a-fd37d027427a",
|
479
|
+
# "base_path" => "/a/base/path",
|
480
|
+
# "document_type" => "mainstream_browse_page",
|
481
|
+
# "locale" => "en",
|
482
|
+
# "links" => {},
|
483
|
+
# ...
|
484
|
+
# }
|
485
|
+
# ],
|
486
|
+
# "parent" => [
|
487
|
+
# {
|
488
|
+
# "content_id" => "df2e7a3e-2028-45de-a75a-fd37d027427e",
|
489
|
+
# "document_type" => "mainstream_browse_page",
|
490
|
+
# ...
|
491
|
+
# },
|
492
|
+
# ]
|
493
|
+
# }
|
494
|
+
# }
|
495
|
+
def stub_publishing_api_has_expanded_links(links, with_drafts: true, generate: false)
|
496
|
+
links = deep_transform_keys(links, &:to_sym)
|
497
|
+
request_params = {}
|
498
|
+
request_params["with_drafts"] = false if !with_drafts
|
499
|
+
request_params["generate"] = true if generate
|
500
|
+
|
501
|
+
url = PUBLISHING_API_V2_ENDPOINT + "/expanded-links/" + links[:content_id]
|
502
|
+
stub_request(:get, url)
|
503
|
+
.with(query: request_params)
|
504
|
+
.to_return(status: 200, body: links.to_json, headers: {})
|
505
|
+
end
|
506
|
+
|
507
|
+
# Stub a request to get links for content ids
|
508
|
+
#
|
509
|
+
# @param [Hash] links the links for each content id
|
510
|
+
#
|
511
|
+
# @example
|
512
|
+
# stub_publishing_api_has_links_for_content_ids(
|
513
|
+
# { "2878337b-bed9-4e7f-85b6-10ed2cbcd504" => {
|
514
|
+
# "links" => { "taxons" => ["eb6965c7-3056-45d0-ae50-2f0a5e2e0854"] }
|
515
|
+
# },
|
516
|
+
# "eec13cea-219d-4896-9c97-60114da23559" => {
|
517
|
+
# "links" => {}
|
518
|
+
# }
|
519
|
+
# }
|
520
|
+
# )
|
521
|
+
#
|
522
|
+
# @example
|
523
|
+
# Services.publishing_api.get_links_for_content_ids(["2878337b-bed9-4e7f-85b6-10ed2cbcd504"])
|
524
|
+
# => {
|
525
|
+
# "2878337b-bed9-4e7f-85b6-10ed2cbcd504" => {
|
526
|
+
# "links" => [
|
527
|
+
# "eb6965c7-3056-45d0-ae50-2f0a5e2e0854"
|
528
|
+
# ]
|
529
|
+
# }
|
530
|
+
# }
|
531
|
+
def stub_publishing_api_has_links_for_content_ids(links)
|
532
|
+
url = PUBLISHING_API_V2_ENDPOINT + "/links/by-content-id"
|
533
|
+
stub_request(:post, url).with(body: { content_ids: links.keys }).to_return(status: 200, body: links.to_json, headers: {})
|
534
|
+
end
|
535
|
+
|
536
|
+
# Stub GET /v2/links/:content_id to return a 404 response
|
537
|
+
#
|
538
|
+
# @param content_id [UUID]
|
539
|
+
def stub_publishing_api_does_not_have_links(content_id)
|
540
|
+
url = PUBLISHING_API_V2_ENDPOINT + "/links/" + content_id
|
541
|
+
stub_request(:get, url).to_return(status: 404, body: resource_not_found(content_id, "link set").to_json, headers: {})
|
542
|
+
end
|
543
|
+
|
544
|
+
# Stub calls to the lookups endpoint
|
545
|
+
#
|
546
|
+
# @param lookup_hash [Hash] Hash with base_path as key, content_id as value.
|
547
|
+
#
|
548
|
+
# @example
|
549
|
+
#
|
550
|
+
# stub_publishing_api_has_lookups({
|
551
|
+
# "/foo" => "51ac4247-fd92-470a-a207-6b852a97f2db",
|
552
|
+
# "/bar" => "261bd281-f16c-48d5-82d2-9544019ad9ca"
|
553
|
+
# })
|
554
|
+
#
|
555
|
+
def stub_publishing_api_has_lookups(lookup_hash)
|
556
|
+
url = PUBLISHING_API_ENDPOINT + "/lookup-by-base-path"
|
557
|
+
stub_request(:post, url).to_return(body: lookup_hash.to_json)
|
558
|
+
end
|
559
|
+
|
560
|
+
#
|
561
|
+
# Stub calls to the get linked items endpoint
|
562
|
+
#
|
563
|
+
# @param items [Array] The linked items we wish to return
|
564
|
+
# @param params [Hash] A hash of parameters
|
565
|
+
#
|
566
|
+
# @example
|
567
|
+
#
|
568
|
+
# stub_publishing_api_has_linked_items(
|
569
|
+
# [ item_1, item_2 ],
|
570
|
+
# {
|
571
|
+
# content_id: "51ac4247-fd92-470a-a207-6b852a97f2db",
|
572
|
+
# link_type: "taxons",
|
573
|
+
# fields: ["title", "description", "base_path"]
|
574
|
+
# }
|
575
|
+
# )
|
576
|
+
#
|
577
|
+
def stub_publishing_api_has_linked_items(items, params = {})
|
578
|
+
content_id = params.fetch(:content_id)
|
579
|
+
link_type = params.fetch(:link_type)
|
580
|
+
fields = params.fetch(:fields, %w(base_path content_id document_type title))
|
581
|
+
|
582
|
+
url = PUBLISHING_API_V2_ENDPOINT + "/linked/#{content_id}"
|
583
|
+
|
584
|
+
request_parmeters = {
|
585
|
+
"fields" => fields,
|
586
|
+
"link_type" => link_type,
|
587
|
+
}
|
588
|
+
|
589
|
+
stub_request(:get, url)
|
590
|
+
.with(query: request_parmeters)
|
591
|
+
.and_return(
|
592
|
+
body: items.to_json,
|
593
|
+
status: 200,
|
594
|
+
)
|
595
|
+
end
|
596
|
+
|
597
|
+
# Stub GET /v2/editions to return a set of editions
|
598
|
+
#
|
599
|
+
# @example
|
600
|
+
#
|
601
|
+
# stub_publishing_api_get_editions(
|
602
|
+
# vehicle_recalls_and_faults, # this is a variable containing an array of editions
|
603
|
+
# fields: fields, #example: let(:fields) { %i[base_path content_id public_updated_at title publication_state] }
|
604
|
+
# per_page: 50
|
605
|
+
# )
|
606
|
+
# @param items [Array]
|
607
|
+
# @param params [Hash]
|
608
|
+
def stub_publishing_api_get_editions(editions, params = {})
|
609
|
+
url = PUBLISHING_API_V2_ENDPOINT + "/editions"
|
610
|
+
|
611
|
+
results = editions.map do |edition|
|
612
|
+
next edition unless params[:fields]
|
613
|
+
|
614
|
+
edition.select { |k| params[:fields].include?(k) }
|
615
|
+
end
|
616
|
+
|
617
|
+
per_page = (params[:per_page] || 100).to_i
|
618
|
+
results = results.take(per_page)
|
619
|
+
|
620
|
+
body = {
|
621
|
+
results: results,
|
622
|
+
links: [
|
623
|
+
{ rel: "self", href: "#{PUBLISHING_API_V2_ENDPOINT}/editions" },
|
624
|
+
],
|
625
|
+
}
|
626
|
+
|
627
|
+
stub_request(:get, url)
|
628
|
+
.with(query: params)
|
629
|
+
.to_return(status: 200, body: body.to_json, headers: {})
|
630
|
+
end
|
631
|
+
|
14
632
|
def stub_publishing_api_unreserve_path(base_path, publishing_app = /.*/)
|
15
633
|
stub_publishing_api_unreserve_path_with_code(base_path, publishing_app, 200)
|
16
634
|
end
|
@@ -34,7 +652,7 @@ module GdsApi
|
|
34
652
|
stub_request(:delete, url).to_return(status: 200, body: "{}", headers: { "Content-Type" => "application/json; charset=utf-8" })
|
35
653
|
end
|
36
654
|
|
37
|
-
def
|
655
|
+
def stub_any_publishing_api_put_intent
|
38
656
|
stub_request(:put, %r{\A#{PUBLISHING_API_ENDPOINT}/publish-intent})
|
39
657
|
end
|
40
658
|
|
@@ -71,48 +689,171 @@ module GdsApi
|
|
71
689
|
end
|
72
690
|
end
|
73
691
|
|
74
|
-
|
75
|
-
|
692
|
+
# Stub a PUT /paths/:base_path request with the given content id and request body.
|
693
|
+
#
|
694
|
+
# @example
|
695
|
+
# stub_publishing_api_path_reservation(
|
696
|
+
# my_content_id,
|
697
|
+
# publishing_app: "content-publisher",
|
698
|
+
# override_existing: true,
|
699
|
+
# )
|
700
|
+
#
|
701
|
+
# @param base_path [String]
|
702
|
+
# @param params [Hash]
|
703
|
+
def stub_publishing_api_path_reservation(base_path, params = {})
|
704
|
+
url = PUBLISHING_API_ENDPOINT + "/paths#{base_path}"
|
705
|
+
response = {
|
706
|
+
status: 200,
|
707
|
+
headers: { content_type: "application/json" },
|
708
|
+
body: params.merge(base_path: base_path).to_json,
|
709
|
+
}
|
710
|
+
|
711
|
+
stub_request(:put, url).with(body: params).to_return(response)
|
76
712
|
end
|
77
713
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
}
|
714
|
+
# Stub all PUT /paths/:base_path requests
|
715
|
+
#
|
716
|
+
# @example
|
717
|
+
# stub_any_publishing_api_path_reservation
|
718
|
+
def stub_any_publishing_api_path_reservation
|
719
|
+
stub_request(:put, %r[\A#{PUBLISHING_API_ENDPOINT}/paths/]).to_return do |request|
|
720
|
+
base_path = request.uri.path.sub(%r{\A/paths}, "")
|
721
|
+
body = JSON.parse(request.body).merge(base_path: base_path)
|
722
|
+
{
|
723
|
+
status: 200,
|
724
|
+
headers: { content_type: "application/json" },
|
725
|
+
body: body.to_json,
|
726
|
+
}
|
727
|
+
end
|
84
728
|
end
|
85
729
|
|
730
|
+
# Stub a PUT /paths/:base_path request for a particular publishing
|
731
|
+
# application. Calling for a different publishing application will return
|
732
|
+
# a 422 response.
|
733
|
+
#
|
734
|
+
# @example
|
735
|
+
# stub_publishing_api_has_path_reservation_for("/foo", "content-publisher")
|
736
|
+
#
|
737
|
+
# @param base_path [String]
|
738
|
+
# @param publishing_app [String]
|
86
739
|
def stub_publishing_api_has_path_reservation_for(path, publishing_app)
|
87
|
-
|
88
|
-
|
740
|
+
message = "#{path} is already reserved by #{publishing_app}"
|
741
|
+
error = { code: 422,
|
742
|
+
message: "Base path #{message}",
|
743
|
+
fields: { base_path: [message] } }
|
89
744
|
|
90
745
|
stub_request(:put, "#{PUBLISHING_API_ENDPOINT}/paths#{path}").
|
91
|
-
to_return(status: 422,
|
92
|
-
headers: { content_type: "application/json" }
|
746
|
+
to_return(status: 422,
|
747
|
+
headers: { content_type: "application/json" },
|
748
|
+
body: { error: error }.to_json)
|
93
749
|
|
94
750
|
stub_request(:put, "#{PUBLISHING_API_ENDPOINT}/paths#{path}").
|
95
751
|
with(body: { "publishing_app" => publishing_app }).
|
96
752
|
to_return(status: 200,
|
97
753
|
headers: { content_type: "application/json" },
|
98
|
-
body:
|
754
|
+
body: { publishing_app: publishing_app, base_path: path }.to_json)
|
99
755
|
end
|
100
756
|
|
101
|
-
|
102
|
-
|
103
|
-
|
757
|
+
# Stub a PUT /paths/:base_path request for a particular publishing
|
758
|
+
# application. Calling for a different publishing application will return
|
759
|
+
# a 422 response.
|
760
|
+
#
|
761
|
+
# @example
|
762
|
+
# stub_publishing_api_returns_path_reservation_validation_error_for(
|
763
|
+
# "/foo",
|
764
|
+
# "field" => ["error 1", "error 2"]
|
765
|
+
# )
|
766
|
+
#
|
767
|
+
# @param base_path [String]
|
768
|
+
# @param error_fields [Hash]
|
769
|
+
def stub_publishing_api_returns_path_reservation_validation_error_for(base_path, error_fields = {})
|
770
|
+
error_fields = { "base_path" => ["Computer says no"] } if error_fields.empty?
|
104
771
|
|
105
|
-
|
106
|
-
|
772
|
+
message = error_fields.keys.first.to_s.capitalize.gsub(/_/, " ") + " " +
|
773
|
+
error_fields.values.flatten.first
|
774
|
+
|
775
|
+
error = { code: 422, message: message, fields: error_fields }
|
776
|
+
|
777
|
+
stub_request(:put, "#{PUBLISHING_API_ENDPOINT}/paths#{base_path}").
|
778
|
+
to_return(status: 422,
|
779
|
+
headers: { content_type: "application/json" },
|
780
|
+
body: { error: error }.to_json)
|
107
781
|
end
|
108
782
|
|
109
783
|
# Aliases for DEPRECATED methods
|
110
784
|
alias_method :publishing_api_isnt_available, :stub_publishing_api_isnt_available
|
785
|
+
alias_method :publishing_api_has_content, :stub_publishing_api_has_content
|
786
|
+
alias_method :publishing_api_has_fields_for_document, :stub_publishing_api_has_fields_for_document
|
787
|
+
alias_method :publishing_api_has_linkables, :stub_publishing_api_has_linkables
|
788
|
+
alias_method :publishing_api_has_item, :stub_publishing_api_has_item
|
789
|
+
alias_method :publishing_api_has_item_in_sequence, :stub_publishing_api_has_item_in_sequence
|
790
|
+
alias_method :publishing_api_does_not_have_item, :stub_publishing_api_does_not_have_item
|
791
|
+
alias_method :publishing_api_has_links, :stub_publishing_api_has_links
|
792
|
+
alias_method :publishing_api_has_expanded_links, :stub_publishing_api_has_expanded_links
|
793
|
+
alias_method :publishing_api_has_links_for_content_ids, :stub_publishing_api_has_links_for_content_ids
|
794
|
+
alias_method :publishing_api_does_not_have_links, :stub_publishing_api_does_not_have_links
|
795
|
+
alias_method :publishing_api_has_lookups, :stub_publishing_api_has_lookups
|
796
|
+
alias_method :publishing_api_has_linked_items, :stub_publishing_api_has_linked_items
|
797
|
+
alias_method :publishing_api_get_editions, :stub_publishing_api_get_editions
|
111
798
|
alias_method :publishing_api_has_path_reservation_for, :stub_publishing_api_has_path_reservation_for
|
112
799
|
alias_method :publishing_api_returns_path_reservation_validation_error_for, :stub_publishing_api_returns_path_reservation_validation_error_for
|
800
|
+
alias_method :stub_default_publishing_api_path_reservation, :stub_any_publishing_api_path_reservation
|
801
|
+
alias_method :stub_default_publishing_api_put_intent, :stub_any_publishing_api_put_intent
|
113
802
|
|
114
803
|
private
|
115
804
|
|
805
|
+
def stub_publishing_api_put(*args)
|
806
|
+
stub_publishing_api_postlike_call(:put, *args)
|
807
|
+
end
|
808
|
+
|
809
|
+
def stub_publishing_api_patch(*args)
|
810
|
+
stub_publishing_api_postlike_call(:patch, *args)
|
811
|
+
end
|
812
|
+
|
813
|
+
def stub_publishing_api_postlike_call(method, content_id, body, resource_path, override_response_hash = {})
|
814
|
+
response_hash = { status: 200, body: "{}", headers: { "Content-Type" => "application/json; charset=utf-8" } }
|
815
|
+
response_hash.merge!(override_response_hash)
|
816
|
+
response_hash[:body] = response_hash[:body].to_json if response_hash[:body].is_a?(Hash)
|
817
|
+
url = PUBLISHING_API_V2_ENDPOINT + resource_path + "/" + content_id
|
818
|
+
stub_request(method, url).with(body: body).to_return(response_hash)
|
819
|
+
end
|
820
|
+
|
821
|
+
def deep_stringify_keys(hash)
|
822
|
+
deep_transform_keys(hash, &:to_s)
|
823
|
+
end
|
824
|
+
|
825
|
+
def deep_transform_keys(object, &block)
|
826
|
+
case object
|
827
|
+
when Hash
|
828
|
+
object.each_with_object({}) do |(key, value), result|
|
829
|
+
result[yield(key)] = deep_transform_keys(value, &block)
|
830
|
+
end
|
831
|
+
when Array
|
832
|
+
object.map { |item| deep_transform_keys(item, &block) }
|
833
|
+
else
|
834
|
+
object
|
835
|
+
end
|
836
|
+
end
|
837
|
+
|
838
|
+
def resource_not_found(content_id, type)
|
839
|
+
{
|
840
|
+
error: {
|
841
|
+
code: 404,
|
842
|
+
message: "Could not find #{type} with content_id: #{content_id}",
|
843
|
+
},
|
844
|
+
}
|
845
|
+
end
|
846
|
+
|
847
|
+
def version_conflict(expected_version, actual_version = expected_version + 1)
|
848
|
+
{
|
849
|
+
error: {
|
850
|
+
code: 409,
|
851
|
+
message: "A lock-version conflict occurred. The `previous_version` you've sent (#{expected_version}) is not the same as the current lock version of the edition (#{actual_version}).",
|
852
|
+
fields: { previous_version: ["does not match"] },
|
853
|
+
},
|
854
|
+
}
|
855
|
+
end
|
856
|
+
|
116
857
|
def stub_publishing_api_unreserve_path_with_code(base_path, publishing_app, code)
|
117
858
|
url = PUBLISHING_API_ENDPOINT + "/paths" + base_path
|
118
859
|
body = { publishing_app: publishing_app }
|
@@ -147,16 +888,6 @@ module GdsApi
|
|
147
888
|
def intent_for_publishing_api(base_path, publishing_app = "publisher")
|
148
889
|
intent_for_base_path(base_path).merge("publishing_app" => publishing_app)
|
149
890
|
end
|
150
|
-
|
151
|
-
def publishing_api_path_data_for(path, override_attributes = {})
|
152
|
-
now = Time.zone.now.utc.iso8601
|
153
|
-
{
|
154
|
-
"path" => path,
|
155
|
-
"publishing_app" => "foo-publisher",
|
156
|
-
"created_at" => now,
|
157
|
-
"updated_at" => now,
|
158
|
-
}.merge(override_attributes)
|
159
|
-
end
|
160
891
|
end
|
161
892
|
end
|
162
893
|
end
|