haveapi 0.29.1 → 0.29.3

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.
data/spec/i18n_spec.rb CHANGED
@@ -10,6 +10,16 @@ module I18nSpec
10
10
  User.new(:cs) if username == 'user' && password == 'pass'
11
11
  end
12
12
  end
13
+
14
+ module ActionStateBackend
15
+ def self.list_pending(*)
16
+ []
17
+ end
18
+
19
+ def self.new(*)
20
+ nil
21
+ end
22
+ end
13
23
  end
14
24
 
15
25
  describe HaveAPI::I18n do
@@ -48,6 +58,14 @@ describe HaveAPI::I18n do
48
58
  string :global_attr_label,
49
59
  label: 'Global attribute fallback',
50
60
  desc: 'Global attribute description fallback'
61
+ string :status, choices: %i[enabled disabled]
62
+ string :priority,
63
+ choices: {
64
+ values: {
65
+ low: 'Low priority',
66
+ high: 'High priority'
67
+ }
68
+ }
51
69
  string :code, length: {
52
70
  min: 3,
53
71
  message: HaveAPI.message('haveapi.validators.length.min', min: 3)
@@ -105,8 +123,8 @@ describe HaveAPI::I18n do
105
123
  header 'Accept', 'application/json'
106
124
  call_api(:post, '/v1/things', thing: {})
107
125
 
108
- expect(api_response.message).to eq('input parameters not valid')
109
- expect(api_response.errors[:name]).to include('required parameter missing')
126
+ expect(api_response.message).to eq('input parameters are not valid')
127
+ expect(api_response.errors[:name]).to include('required parameter is missing')
110
128
  expect(last_response.headers['Vary']).to include('Accept-Language')
111
129
  end
112
130
 
@@ -115,9 +133,9 @@ describe HaveAPI::I18n do
115
133
  header 'Accept-Language', 'cs'
116
134
  call_api(:post, '/v1/things', thing: { count: 'nope' })
117
135
 
118
- expect(api_response.message).to eq('vstupní parametry nejsou platné')
119
- expect(api_response.errors[:name]).to include('povinný parametr chybí')
120
- expect(api_response.errors[:count].first).to include('neplatné celé číslo')
136
+ expect(api_response.message).to eq('vstupní parametry jsou neplatné')
137
+ expect(api_response.errors[:name]).to include('chybí povinný parametr')
138
+ expect(api_response.errors[:count].first).to include('není platné celé číslo')
121
139
  expect(last_response.headers['Vary']).to include('Accept-Language')
122
140
  end
123
141
 
@@ -143,7 +161,15 @@ describe HaveAPI::I18n do
143
161
  options '/v1/things', method: 'POST'
144
162
 
145
163
  length = api_response[:input][:parameters][:name][:validators][:length]
146
- expect(length[:message]).to eq('délka musí být v rozsahu <3, 5>')
164
+ expect(length[:message]).to eq('délka musí být v rozsahu 35')
165
+ end
166
+
167
+ it 'keeps untranslated array choices unchanged in OPTIONS responses' do
168
+ header 'Accept', 'application/json'
169
+ options '/v1/things', method: 'POST'
170
+
171
+ choices = api_response[:input][:parameters][:status][:validators][:include]
172
+ expect(choices[:values]).to eq(%w[enabled disabled])
147
173
  end
148
174
 
149
175
  it 'localizes API metadata in OPTIONS responses' do
@@ -218,6 +244,18 @@ describe HaveAPI::I18n do
218
244
  global_attr_label: {
219
245
  label: 'Přesný globální popisek',
220
246
  description: 'Přesný globální popis'
247
+ },
248
+ status: {
249
+ choices: {
250
+ enabled: { label: 'Zapnuto' },
251
+ disabled: { label: 'Vypnuto' }
252
+ }
253
+ },
254
+ priority: {
255
+ choices: {
256
+ low: { label: 'Nízká priorita' },
257
+ high: { label: 'Vysoká priorita' }
258
+ }
221
259
  }
222
260
  },
223
261
  output: {
@@ -325,6 +363,14 @@ describe HaveAPI::I18n do
325
363
  label: 'Přesný globální popisek',
326
364
  description: 'Přesný globální popis'
327
365
  )
366
+ expect(input_params[:status][:validators][:include][:values]).to eq(
367
+ enabled: 'Zapnuto',
368
+ disabled: 'Vypnuto'
369
+ )
370
+ expect(input_params[:priority][:validators][:include][:values]).to eq(
371
+ low: 'Nízká priorita',
372
+ high: 'Vysoká priorita'
373
+ )
328
374
  expect(input_params[:count]).to include(
329
375
  label: 'Count',
330
376
  description: nil
@@ -357,7 +403,7 @@ describe HaveAPI::I18n do
357
403
  create = api_response[:resources][:thing][:actions][:create]
358
404
  no_meta = create[:meta][:global][:input][:parameters][:no]
359
405
 
360
- expect(no_meta[:label]).to eq('Zakázat metadata')
406
+ expect(no_meta[:label]).to eq('Vypnout metadata')
361
407
  end
362
408
 
363
409
  it 'localizes application-supplied lazy validator messages' do
@@ -423,7 +469,7 @@ describe HaveAPI::I18n do
423
469
  expect(HaveAPI.localize(data)).to eq({
424
470
  message: 'Akce nebyla nalezena',
425
471
  errors: {
426
- name: ['povinný parametr chybí']
472
+ name: ['chybí povinný parametr']
427
473
  }
428
474
  })
429
475
  ensure
@@ -456,6 +502,39 @@ describe HaveAPI::I18n do
456
502
  end
457
503
  end
458
504
 
505
+ context 'with localized framework self-description' do
506
+ empty_api
507
+ use_version 1
508
+ default_version 1
509
+ auth_chain I18nSpec::Provider
510
+ action_state I18nSpec::ActionStateBackend
511
+
512
+ before do
513
+ header 'Accept', 'application/json'
514
+ header 'Accept-Language', 'cs'
515
+ end
516
+
517
+ it 'localizes authentication provider descriptions' do
518
+ call_api(:options, '/?describe=default')
519
+
520
+ description = api_response[:authentication][:basic][:description]
521
+ expect(description).to start_with('Autentizace pomocí HTTP Basic')
522
+ end
523
+
524
+ it 'localizes ActionState resource and action descriptions' do
525
+ call_api(:options, '/?describe=default')
526
+
527
+ action_state = api_response[:resources][:action_state]
528
+ expect(action_state[:description]).to eq('Procházet stavy blokujících akcí')
529
+ expect(action_state[:actions][:index][:description]).to eq('Vypsat stavy čekajících akcí')
530
+ expect(action_state[:actions][:poll][:description]).to eq(
531
+ 'Vrátit stav po dokončení akce, změně průběhu nebo vypršení časového limitu'
532
+ )
533
+ expect(action_state[:actions][:show][:description]).to eq('Zobrazit stav čekající akce')
534
+ expect(action_state[:actions][:cancel][:description]).to eq('Zrušit čekající akci')
535
+ end
536
+ end
537
+
459
538
  context 'with an authenticated locale resolver' do
460
539
  api do
461
540
  define_resource(:Thing) do
@@ -489,7 +568,7 @@ describe HaveAPI::I18n do
489
568
 
490
569
  action = api_response[:resources][:thing][:actions][:create]
491
570
  length = action.dig(:input, :parameters, :name, :validators, :length)
492
- expect(length[:message]).to eq('délka musí být v rozsahu <3, 5>')
571
+ expect(length[:message]).to eq('délka musí být v rozsahu 35')
493
572
  end
494
573
  end
495
574
 
@@ -869,23 +869,23 @@ describe HaveAPI::ModelAdapters::ActiveRecord do
869
869
 
870
870
  expect do
871
871
  described_class::Input.clean(ARAdapterSpec::Environment, 'abc', {})
872
- end.to raise_error(HaveAPI::ValidationError, /not a valid id/)
872
+ end.to raise_error(HaveAPI::ValidationError, /not a valid ID/)
873
873
 
874
874
  expect do
875
875
  described_class::Input.clean(ARAdapterSpec::Environment, '', {})
876
- end.to raise_error(HaveAPI::ValidationError, /not a valid id/)
876
+ end.to raise_error(HaveAPI::ValidationError, /not a valid ID/)
877
877
 
878
878
  expect do
879
879
  described_class::Input.clean(ARAdapterSpec::Environment, 1.2, {})
880
- end.to raise_error(HaveAPI::ValidationError, /not a valid id/)
880
+ end.to raise_error(HaveAPI::ValidationError, /not a valid ID/)
881
881
 
882
882
  expect do
883
883
  described_class::Input.clean(ARAdapterSpec::Environment, false, {})
884
- end.to raise_error(HaveAPI::ValidationError, /not a valid id/)
884
+ end.to raise_error(HaveAPI::ValidationError, /not a valid ID/)
885
885
 
886
886
  expect do
887
887
  described_class::Input.clean(ARAdapterSpec::Environment, true, {})
888
- end.to raise_error(HaveAPI::ValidationError, /not a valid id/)
888
+ end.to raise_error(HaveAPI::ValidationError, /not a valid ID/)
889
889
 
890
890
  expect do
891
891
  described_class::Input.clean(ARAdapterSpec::Environment, 9999, {})
@@ -913,11 +913,11 @@ describe HaveAPI::ModelAdapters::ActiveRecord do
913
913
 
914
914
  expect do
915
915
  described_class::Input.clean(ARAdapterSpec::StringAccount, %w[acct-alpha acct-beta], {})
916
- end.to raise_error(HaveAPI::ValidationError, /not a valid id/)
916
+ end.to raise_error(HaveAPI::ValidationError, /not a valid ID/)
917
917
 
918
918
  expect do
919
919
  described_class::Input.clean(ARAdapterSpec::StringAccount, { id: 'acct-alpha' }, {})
920
- end.to raise_error(HaveAPI::ValidationError, /not a valid id/)
920
+ end.to raise_error(HaveAPI::ValidationError, /not a valid ID/)
921
921
  end
922
922
 
923
923
  it 'rejects non-string includes metadata entries' do
@@ -957,7 +957,7 @@ describe HaveAPI::ModelAdapters::ActiveRecord do
957
957
  expect(last_response.status).to eq(200)
958
958
  expect(api_response).not_to be_ok
959
959
  expect(api_response.errors[:limit].first).to include(
960
- "range <0, #{HaveAPI::Actions::Paginable::MAX_LIMIT}>"
960
+ "between 0 and #{HaveAPI::Actions::Paginable::MAX_LIMIT}"
961
961
  )
962
962
  end
963
963
 
data/spec/params_spec.rb CHANGED
@@ -258,6 +258,8 @@ describe HaveAPI::Params do
258
258
  p = described_class.new(:input, ParamsSpec::MyResource::Index)
259
259
  p.add_block(proc do
260
260
  string :hostname, label: 'Hostname', desc: 'VPS hostname'
261
+ string :state, choices: %i[queued running]
262
+ string :priority, choices: { values: { low: 'Low priority' } }
261
263
  string :framework,
262
264
  label: HaveAPI.message('haveapi.parameters.metadata.no.label')
263
265
  end)
@@ -274,6 +276,22 @@ describe HaveAPI::Params do
274
276
  params_spec.attributes.hostname.label
275
277
  ])
276
278
  expect(items.none? { |item| item[:param] == 'framework' }).to be true
279
+
280
+ choice = items.detect do |item|
281
+ item[:param] == 'state' && item[:kind] == 'choices.queued.label'
282
+ end
283
+ expect(choice[:value]).to eq('queued')
284
+ expect(choice[:keys]).to eq(%w[
285
+ params_spec.resources.my_resource.actions.index.input.state.choices.queued.label
286
+ params_spec.resources.my_resource.input.state.choices.queued.label
287
+ params_spec.resources.my_resource.attributes.state.choices.queued.label
288
+ params_spec.attributes.state.choices.queued.label
289
+ ])
290
+
291
+ choice = items.detect do |item|
292
+ item[:param] == 'priority' && item[:kind] == 'choices.low.label'
293
+ end
294
+ expect(choice[:value]).to eq('Low priority')
277
295
  end
278
296
 
279
297
  it 'does not parse meta resource path segments as metadata paths' do
@@ -97,7 +97,7 @@ describe HaveAPI::Server do
97
97
 
98
98
  expect(last_response.status).to eq(400)
99
99
  expect(api_response).not_to be_ok
100
- expect(api_response.message).to match(/Bad JSON syntax/)
100
+ expect(api_response.message).to match(/Invalid JSON syntax/)
101
101
  end
102
102
 
103
103
  it 'returns 400 for non-object JSON bodies' do
@@ -109,7 +109,7 @@ describe HaveAPI::Server do
109
109
 
110
110
  expect(last_response.status).to eq(400)
111
111
  expect(api_response).not_to be_ok
112
- expect(api_response.message).to eq('JSON body must be an object')
112
+ expect(api_response.message).to eq('The JSON request body must be an object')
113
113
  end
114
114
  end
115
115
 
@@ -132,7 +132,7 @@ describe HaveAPI::Server do
132
132
 
133
133
  expect(last_response.status).to eq(415)
134
134
  expect(api_response).not_to be_ok
135
- expect(api_response.message).to eq('Unsupported Content-Type')
135
+ expect(api_response.message).to eq('Unsupported Content-Type header')
136
136
  expect(ServerIntegrationSpec::State.writes).to be_empty
137
137
  end
138
138
 
@@ -145,7 +145,7 @@ describe HaveAPI::Server do
145
145
 
146
146
  expect(last_response.status).to eq(400)
147
147
  expect(api_response).not_to be_ok
148
- expect(api_response.message).to eq('Bad Accept header')
148
+ expect(api_response.message).to eq('Invalid Accept header')
149
149
  end
150
150
 
151
151
  it 'returns JSON envelope for unknown route' do
@@ -169,7 +169,7 @@ describe HaveAPI::Server do
169
169
 
170
170
  expect(last_response.status).to eq(500)
171
171
  expect(api_response).not_to be_ok
172
- expect(api_response.message).to eq('Server error occurred')
172
+ expect(api_response.message).to eq('A server error occurred')
173
173
 
174
174
  expect(calls.size).to eq(1)
175
175
  context, exception = calls.first
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: haveapi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.29.1
4
+ version: 0.29.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jakub Skokan
@@ -29,14 +29,14 @@ dependencies:
29
29
  requirements:
30
30
  - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: 0.29.1
32
+ version: 0.29.3
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: 0.29.1
39
+ version: 0.29.3
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: i18n
42
42
  requirement: !ruby/object:Gem::Requirement