wikidata_adaptor 1.0.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.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.env.test +7 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +45 -0
  5. data/.yardopts +10 -0
  6. data/CHANGELOG.md +106 -0
  7. data/CLAUDE.md +200 -0
  8. data/CODE_OF_CONDUCT.md +84 -0
  9. data/COVERAGE.md +77 -0
  10. data/Gemfile +20 -0
  11. data/Gemfile.lock +124 -0
  12. data/LICENSE.txt +21 -0
  13. data/README.md +269 -0
  14. data/Rakefile +18 -0
  15. data/integration/.env.example +20 -0
  16. data/integration/README.md +58 -0
  17. data/integration/config/99_IntegrationTesting.php +3 -0
  18. data/integration/config/wikibase-php.ini +15 -0
  19. data/integration/docker-compose.yml +98 -0
  20. data/lib/wikidata_adaptor/rest_api/aliases.rb +88 -0
  21. data/lib/wikidata_adaptor/rest_api/descriptions.rb +138 -0
  22. data/lib/wikidata_adaptor/rest_api/items.rb +36 -0
  23. data/lib/wikidata_adaptor/rest_api/labels.rb +138 -0
  24. data/lib/wikidata_adaptor/rest_api/open_api_document.rb +15 -0
  25. data/lib/wikidata_adaptor/rest_api/properties.rb +36 -0
  26. data/lib/wikidata_adaptor/rest_api/property_data_types.rb +15 -0
  27. data/lib/wikidata_adaptor/rest_api/search_item.rb +44 -0
  28. data/lib/wikidata_adaptor/rest_api/search_property.rb +44 -0
  29. data/lib/wikidata_adaptor/rest_api/sitelinks.rb +59 -0
  30. data/lib/wikidata_adaptor/rest_api/statements.rb +153 -0
  31. data/lib/wikidata_adaptor/rest_api.rb +32 -0
  32. data/lib/wikidata_adaptor/test_helpers/rest_api/aliases.rb +229 -0
  33. data/lib/wikidata_adaptor/test_helpers/rest_api/descriptions.rb +308 -0
  34. data/lib/wikidata_adaptor/test_helpers/rest_api/items.rb +213 -0
  35. data/lib/wikidata_adaptor/test_helpers/rest_api/labels.rb +302 -0
  36. data/lib/wikidata_adaptor/test_helpers/rest_api/open_api_document.rb +29 -0
  37. data/lib/wikidata_adaptor/test_helpers/rest_api/properties.rb +233 -0
  38. data/lib/wikidata_adaptor/test_helpers/rest_api/property_data_types.rb +23 -0
  39. data/lib/wikidata_adaptor/test_helpers/rest_api/search_item.rb +118 -0
  40. data/lib/wikidata_adaptor/test_helpers/rest_api/search_property.rb +118 -0
  41. data/lib/wikidata_adaptor/test_helpers/rest_api/sitelinks.rb +143 -0
  42. data/lib/wikidata_adaptor/test_helpers/rest_api/statements.rb +475 -0
  43. data/lib/wikidata_adaptor/test_helpers/rest_api/support/support.rb +310 -0
  44. data/lib/wikidata_adaptor/test_helpers/rest_api.rb +89 -0
  45. data/lib/wikidata_adaptor/version.rb +6 -0
  46. data/lib/wikidata_adaptor.rb +28 -0
  47. data/sig/wikidata_adaptor.rbs +4 -0
  48. metadata +106 -0
@@ -0,0 +1,302 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WikidataAdaptor
4
+ module TestHelpers
5
+ module RestApi
6
+ # WebMock stubs for Wikibase REST API labels endpoints
7
+ module Labels
8
+ #####################################
9
+ # GET /v1/entities/items/:item_id/labels
10
+ #####################################
11
+ def stub_get_item_labels(item_id)
12
+ stub_rest_api_request(
13
+ :get,
14
+ "/v1/entities/items/#{item_id}/labels",
15
+ response_body: {
16
+ en: "Douglas Adams",
17
+ fr: "Douglas Adams"
18
+ }
19
+ )
20
+ end
21
+
22
+ ####################################################
23
+ # GET /v1/entities/items/:item_id/labels/:language_code
24
+ ####################################################
25
+ def stub_get_item_label(item_id, language_code)
26
+ stub_rest_api_request(
27
+ :get,
28
+ "/v1/entities/items/#{item_id}/labels/#{language_code}",
29
+ response_body: "Douglas Adams"
30
+ )
31
+ end
32
+
33
+ #########################################################################
34
+ # GET /v1/entities/items/:item_id/labels_with_language_fallback/:language_code
35
+ #########################################################################
36
+ def stub_get_item_label_with_language_fallback(item_id, language_code)
37
+ stub_rest_api_request(
38
+ :get,
39
+ "/v1/entities/items/#{item_id}/labels_with_language_fallback/#{language_code}",
40
+ response_body: "Douglas Adams"
41
+ )
42
+ end
43
+
44
+ #########################################################################
45
+ # GET /v1/entities/items/:item_id/labels_with_language_fallback/:language_code
46
+ # -> 307 Location: /v1/entities/items/:item_id/labels/:redirect_language_code
47
+ #########################################################################
48
+ def stub_get_item_label_with_language_fallback_redirect(item_id, language_code,
49
+ redirect_language_code: language_code,
50
+ response_body: "Douglas Adams")
51
+ stub_rest_api_request(
52
+ :get,
53
+ "/v1/entities/items/#{item_id}/labels_with_language_fallback/#{language_code}",
54
+ response_status: 307,
55
+ response_headers: {
56
+ "Location" => "#{WIKIBASE_REST_ENDPOINT}/v1/entities/items/#{item_id}/labels/#{redirect_language_code}"
57
+ },
58
+ response_body: ""
59
+ )
60
+
61
+ stub_rest_api_request(
62
+ :get,
63
+ "/v1/entities/items/#{item_id}/labels/#{redirect_language_code}",
64
+ response_body: response_body
65
+ )
66
+ end
67
+
68
+ ###########################################
69
+ # GET /v1/entities/properties/:property_id/labels
70
+ ###########################################
71
+ def stub_get_property_labels(property_id)
72
+ stub_rest_api_request(
73
+ :get,
74
+ "/v1/entities/properties/#{property_id}/labels",
75
+ response_body: {
76
+ en: "instance of",
77
+ fr: "est un(e)"
78
+ }
79
+ )
80
+ end
81
+
82
+ ########################################################
83
+ # GET /v1/entities/properties/:property_id/labels/:language_code
84
+ ########################################################
85
+ def stub_get_property_label(property_id, language_code)
86
+ stub_rest_api_request(
87
+ :get,
88
+ "/v1/entities/properties/#{property_id}/labels/#{language_code}",
89
+ response_body: "instance of"
90
+ )
91
+ end
92
+
93
+ #################################################################################
94
+ # GET /v1/entities/properties/:property_id/labels_with_language_fallback/:language_code
95
+ #################################################################################
96
+ def stub_get_property_label_with_language_fallback(property_id, language_code)
97
+ stub_rest_api_request(
98
+ :get,
99
+ "/v1/entities/properties/#{property_id}/labels_with_language_fallback/#{language_code}",
100
+ response_body: "instance of"
101
+ )
102
+ end
103
+
104
+ #################################################################################
105
+ # GET /v1/entities/properties/:property_id/labels_with_language_fallback/:language_code
106
+ # -> 307 Location: /v1/entities/properties/:property_id/labels/:redirect_language_code
107
+ #################################################################################
108
+ def stub_get_property_label_with_language_fallback_redirect(property_id, language_code,
109
+ redirect_language_code: language_code,
110
+ response_body: "instance of")
111
+ stub_rest_api_request(
112
+ :get,
113
+ "/v1/entities/properties/#{property_id}/labels_with_language_fallback/#{language_code}",
114
+ response_status: 307,
115
+ response_headers: {
116
+ "Location" => "#{WIKIBASE_REST_ENDPOINT}/v1/entities/properties/#{property_id}/labels/#{redirect_language_code}"
117
+ },
118
+ response_body: ""
119
+ )
120
+
121
+ stub_rest_api_request(
122
+ :get,
123
+ "/v1/entities/properties/#{property_id}/labels/#{redirect_language_code}",
124
+ response_body: response_body
125
+ )
126
+ end
127
+
128
+ ##########################################################
129
+ # PUT /v1/entities/items/:item_id/labels/:language_code
130
+ ##########################################################
131
+ def stub_put_item_label(item_id, language_code, payload, response_body: nil)
132
+ stub_rest_api_request(
133
+ :put,
134
+ "/v1/entities/items/#{item_id}/labels/#{language_code}",
135
+ with: { body: payload.to_json },
136
+ response_body: response_body || payload["label"]
137
+ )
138
+ end
139
+
140
+ # Stub PUT item label request returning 500 error
141
+ #
142
+ # @param item_id [String] The item ID
143
+ # @param language_code [String] The language code
144
+ # @param payload [Hash] The request payload
145
+ #
146
+ # @return [WebMock::RequestStub]
147
+ def stub_put_item_label_unexpected_error(item_id, language_code, payload)
148
+ stub_rest_api_request(
149
+ :put,
150
+ "/v1/entities/items/#{item_id}/labels/#{language_code}",
151
+ response_status: 500,
152
+ with: { body: payload.to_json },
153
+ response_body: { code: "unexpected-error", message: "Unexpected Error" }
154
+ )
155
+ end
156
+
157
+ ################################################################
158
+ # PUT /v1/entities/properties/:property_id/labels/:language_code
159
+ ################################################################
160
+ def stub_put_property_label(property_id, language_code, payload, response_body: nil)
161
+ stub_rest_api_request(
162
+ :put,
163
+ "/v1/entities/properties/#{property_id}/labels/#{language_code}",
164
+ with: { body: payload.to_json },
165
+ response_body: response_body || payload["label"]
166
+ )
167
+ end
168
+
169
+ # Stub PUT property label request returning 500 error
170
+ #
171
+ # @param property_id [String] The property ID
172
+ # @param language_code [String] The language code
173
+ # @param payload [Hash] The request payload
174
+ #
175
+ # @return [WebMock::RequestStub]
176
+ def stub_put_property_label_unexpected_error(property_id, language_code, payload)
177
+ stub_rest_api_request(
178
+ :put,
179
+ "/v1/entities/properties/#{property_id}/labels/#{language_code}",
180
+ response_status: 500,
181
+ with: { body: payload.to_json },
182
+ response_body: { code: "unexpected-error", message: "Unexpected Error" }
183
+ )
184
+ end
185
+
186
+ ##########################################
187
+ # PATCH /v1/entities/items/:item_id/labels
188
+ ##########################################
189
+ def stub_patch_item_labels(item_id, payload, response_body: nil)
190
+ stub_rest_api_request(
191
+ :patch,
192
+ "/v1/entities/items/#{item_id}/labels",
193
+ with: { body: payload.to_json },
194
+ response_body: response_body || { en: "Douglas Noel Adams", fr: "Douglas Adams" }
195
+ )
196
+ end
197
+
198
+ # Stub PATCH item labels request returning 500 error
199
+ #
200
+ # @param item_id [String] The item ID
201
+ # @param payload [Hash] The request payload
202
+ #
203
+ # @return [WebMock::RequestStub]
204
+ def stub_patch_item_labels_unexpected_error(item_id, payload)
205
+ stub_rest_api_request(
206
+ :patch,
207
+ "/v1/entities/items/#{item_id}/labels",
208
+ response_status: 500,
209
+ with: { body: payload.to_json },
210
+ response_body: { code: "unexpected-error", message: "Unexpected Error" }
211
+ )
212
+ end
213
+
214
+ ################################################
215
+ # PATCH /v1/entities/properties/:property_id/labels
216
+ ################################################
217
+ def stub_patch_property_labels(property_id, payload, response_body: nil)
218
+ stub_rest_api_request(
219
+ :patch,
220
+ "/v1/entities/properties/#{property_id}/labels",
221
+ with: { body: payload.to_json },
222
+ response_body: response_body || { en: "is instance of", fr: "est un(e)" }
223
+ )
224
+ end
225
+
226
+ # Stub PATCH property labels request returning 500 error
227
+ #
228
+ # @param property_id [String] The property ID
229
+ # @param payload [Hash] The request payload
230
+ #
231
+ # @return [WebMock::RequestStub]
232
+ def stub_patch_property_labels_unexpected_error(property_id, payload)
233
+ stub_rest_api_request(
234
+ :patch,
235
+ "/v1/entities/properties/#{property_id}/labels",
236
+ response_status: 500,
237
+ with: { body: payload.to_json },
238
+ response_body: { code: "unexpected-error", message: "Unexpected Error" }
239
+ )
240
+ end
241
+
242
+ #############################################################
243
+ # DELETE /v1/entities/items/:item_id/labels/:language_code
244
+ #############################################################
245
+ def stub_delete_item_label(item_id, language_code, payload, response_body: "Label deleted")
246
+ stub_rest_api_request(
247
+ :delete,
248
+ "/v1/entities/items/#{item_id}/labels/#{language_code}",
249
+ with: { body: payload.to_json },
250
+ response_body: response_body
251
+ )
252
+ end
253
+
254
+ # Stub DELETE item label request returning 500 error
255
+ #
256
+ # @param item_id [String] The item ID
257
+ # @param language_code [String] The language code
258
+ # @param payload [Hash] The request payload
259
+ #
260
+ # @return [WebMock::RequestStub]
261
+ def stub_delete_item_label_unexpected_error(item_id, language_code, payload)
262
+ stub_rest_api_request(
263
+ :delete,
264
+ "/v1/entities/items/#{item_id}/labels/#{language_code}",
265
+ response_status: 500,
266
+ with: { body: payload.to_json },
267
+ response_body: { code: "unexpected-error", message: "Unexpected Error" }
268
+ )
269
+ end
270
+
271
+ ###################################################################
272
+ # DELETE /v1/entities/properties/:property_id/labels/:language_code
273
+ ###################################################################
274
+ def stub_delete_property_label(property_id, language_code, payload, response_body: "Label deleted")
275
+ stub_rest_api_request(
276
+ :delete,
277
+ "/v1/entities/properties/#{property_id}/labels/#{language_code}",
278
+ with: { body: payload.to_json },
279
+ response_body: response_body
280
+ )
281
+ end
282
+
283
+ # Stub DELETE property label request returning 500 error
284
+ #
285
+ # @param property_id [String] The property ID
286
+ # @param language_code [String] The language code
287
+ # @param payload [Hash] The request payload
288
+ #
289
+ # @return [WebMock::RequestStub]
290
+ def stub_delete_property_label_unexpected_error(property_id, language_code, payload)
291
+ stub_rest_api_request(
292
+ :delete,
293
+ "/v1/entities/properties/#{property_id}/labels/#{language_code}",
294
+ response_status: 500,
295
+ with: { body: payload.to_json },
296
+ response_body: { code: "unexpected-error", message: "Unexpected Error" }
297
+ )
298
+ end
299
+ end
300
+ end
301
+ end
302
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WikidataAdaptor
4
+ module TestHelpers
5
+ module RestApi
6
+ # https://doc.wikimedia.org/Wikibase/master/js/rest-api/#/OpenAPI%20document/getOpenApiDoc
7
+ module OpenApiDocument
8
+ ##################################
9
+ # GET /v1/openapi.json
10
+ ##################################
11
+ def stub_get_openapi_document(response_body = nil)
12
+ stub_rest_api_request(
13
+ :get,
14
+ "/v1/openapi.json",
15
+ response_body: response_body || {
16
+ openapi: "3.0.0",
17
+ info: {
18
+ title: "Wikibase REST API",
19
+ version: "...",
20
+ description: "OpenAPI definition of Wikibase REST API"
21
+ },
22
+ paths: {}
23
+ }
24
+ )
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,233 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "support/support"
4
+ module WikidataAdaptor
5
+ module TestHelpers
6
+ module RestApi
7
+ # WebMock stubs for Wikibase REST API properties endpoints
8
+ module Properties
9
+ include WikidataAdaptor::TestHelpers::RestApi::Support
10
+
11
+ ###############################
12
+ # GET /v1/entities/properties/:property_id
13
+ ###############################
14
+ def stub_get_property(property_id, response_body = nil)
15
+ stub_rest_api_request(
16
+ :get,
17
+ "/v1/entities/properties/#{property_id}",
18
+ response_body: response_body || {
19
+ id: property_id.to_s,
20
+ type: "property",
21
+ labels: {
22
+ en: "instance of",
23
+ fr: "est un(e)"
24
+ },
25
+ descriptions: {
26
+ en: "that class of which this subject is a particular example and member",
27
+ fr: "classe dont ce sujet est un exemple particulier"
28
+ },
29
+ aliases: {
30
+ en: ["is a"],
31
+ fr: ["est un"]
32
+ },
33
+ statements: {}
34
+ }
35
+ )
36
+ end
37
+
38
+ # Stub GET property request returning 400 invalid property error
39
+ #
40
+ # @param property_id [String] The property ID
41
+ #
42
+ # @return [WebMock::RequestStub]
43
+ def stub_get_property_invalid_property(property_id)
44
+ stub_rest_api_request(
45
+ :get,
46
+ "/v1/entities/properties/#{property_id}",
47
+ response_status: 400,
48
+ response_body: {
49
+ code: "invalid-property-id",
50
+ message: "Not a valid property ID: {#{property_id}}"
51
+ }
52
+ )
53
+ end
54
+
55
+ # Stub GET property request returning 404 not found error
56
+ #
57
+ # @param property_id [String] The property ID
58
+ #
59
+ # @return [WebMock::RequestStub]
60
+ def stub_get_property_not_found(property_id)
61
+ stub_rest_api_request(
62
+ :get,
63
+ "/v1/entities/properties/#{property_id}",
64
+ response_status: 404,
65
+ response_body: {
66
+ code: "property-not-found",
67
+ message: "Could not find a property with the ID: {#{property_id}}"
68
+ }
69
+ )
70
+ end
71
+
72
+ # Stub GET property request returning 500 error
73
+ #
74
+ # @param property_id [String] The property ID
75
+ #
76
+ # @return [WebMock::RequestStub]
77
+ def stub_get_property_unexpected_error(property_id)
78
+ stub_rest_api_request(
79
+ :get,
80
+ "/v1/entities/properties/#{property_id}",
81
+ response_status: 500,
82
+ response_body: {
83
+ code: "unexpected-error",
84
+ message: "Unexpected Error"
85
+ }
86
+ )
87
+ end
88
+
89
+ ###############################
90
+ # POST /v1/entities/properties
91
+ ###############################
92
+ def stub_post_property(payload, response_body = nil)
93
+ stub_rest_api_request(
94
+ :post,
95
+ "/v1/entities/properties",
96
+ response_status: 201,
97
+ with: { body: payload.to_json },
98
+ response_body: response_body || posted_property_response_fixture.to_json
99
+ )
100
+ end
101
+
102
+ # Stub POST property request returning 400 invalid property error
103
+ #
104
+ # @param response_body [Hash, nil] Optional response body
105
+ #
106
+ # @return [WebMock::RequestStub]
107
+ def stub_post_property_invalid_property(response_body = nil)
108
+ stub_rest_api_request(
109
+ :post,
110
+ "/v1/entities/properties",
111
+ response_status: 400,
112
+ response_body: response_body || {
113
+ code: "invalid-property-data",
114
+ message: "The provided property data is invalid."
115
+ }
116
+ )
117
+ end
118
+
119
+ # Stub POST property request returning 403 access denied error
120
+ #
121
+ # @return [WebMock::RequestStub]
122
+ def stub_post_property_access_denied
123
+ stub_rest_api_request(
124
+ :post,
125
+ "/v1/entities/properties",
126
+ response_status: 403,
127
+ response_body: {
128
+ code: "permission-denied",
129
+ message: "Access to resource is denied",
130
+ context: {
131
+ denial_reason: "{reason_code}",
132
+ denial_context: "{additional_context}"
133
+ }
134
+ }
135
+ )
136
+ end
137
+
138
+ # Stub POST property request returning 422 data policy violation error
139
+ #
140
+ # @return [WebMock::RequestStub]
141
+ def stub_post_property_data_policy_violation
142
+ stub_rest_api_request(
143
+ :post,
144
+ "/v1/entities/properties",
145
+ response_status: 422,
146
+ response_body: {
147
+ code: "data-policy-violation",
148
+ message: "Edit violates data policy",
149
+ context: {
150
+ violation: "{violation_code}",
151
+ violation_context: {
152
+ some: "context"
153
+ }
154
+ }
155
+ }
156
+ )
157
+ end
158
+
159
+ # Stub POST property request returning 429 request limit reached error
160
+ #
161
+ # @return [WebMock::RequestStub]
162
+ def stub_post_property_request_limit_reached
163
+ stub_rest_api_request(
164
+ :post,
165
+ "/v1/entities/properties",
166
+ response_status: 429,
167
+ response_body: {
168
+ code: "request-limit-reached",
169
+ message: "Exceeded the limit of actions that can be performed in a given span of time",
170
+ context: {
171
+ reason: "{reason_code}"
172
+ }
173
+ }
174
+ )
175
+ end
176
+
177
+ # Stub POST property request returning 500 error
178
+ #
179
+ # @param payload [Hash] The request payload
180
+ #
181
+ # @return [WebMock::RequestStub]
182
+ def stub_post_property_unexpected_error(payload)
183
+ stub_rest_api_request(
184
+ :post,
185
+ "/v1/entities/properties",
186
+ response_status: 500,
187
+ with: { body: payload.to_json },
188
+ response_body: {
189
+ code: "unexpected-error",
190
+ message: "Unexpected Error"
191
+ }
192
+ )
193
+ end
194
+
195
+ ##########################################
196
+ # PATCH /v1/entities/properties/:property_id
197
+ ##########################################
198
+ def stub_patch_property(property_id, payload, response_body: nil)
199
+ stub_rest_api_request(
200
+ :patch,
201
+ "/v1/entities/properties/#{property_id}",
202
+ with: { body: payload.to_json },
203
+ response_body: response_body || {
204
+ id: property_id.to_s,
205
+ type: "property",
206
+ data_type: "string",
207
+ labels: { en: "is instance of" },
208
+ descriptions: { en: "that class of which this subject is a particular example and member" },
209
+ aliases: { en: ["is a"] },
210
+ statements: {}
211
+ }
212
+ )
213
+ end
214
+
215
+ # Stub PATCH property request returning 500 error
216
+ #
217
+ # @param property_id [String] The property ID
218
+ # @param payload [Hash] The request payload
219
+ #
220
+ # @return [WebMock::RequestStub]
221
+ def stub_patch_property_unexpected_error(property_id, payload)
222
+ stub_rest_api_request(
223
+ :patch,
224
+ "/v1/entities/properties/#{property_id}",
225
+ response_status: 500,
226
+ with: { body: payload.to_json },
227
+ response_body: { code: "unexpected-error", message: "Unexpected Error" }
228
+ )
229
+ end
230
+ end
231
+ end
232
+ end
233
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WikidataAdaptor
4
+ module TestHelpers
5
+ module RestApi
6
+ # https://doc.wikimedia.org/Wikibase/master/js/rest-api/#/Property%20data%20types/getPropertyDataTypes
7
+ module PropertyDataTypes
8
+ ##########################################
9
+ # GET /v1/property-data-types
10
+ ##########################################
11
+ def stub_get_property_data_types
12
+ stub_rest_api_request(
13
+ :get,
14
+ "/v1/property-data-types",
15
+ response_body: {
16
+ "data-type" => "value-type"
17
+ }
18
+ )
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end